Factor out {SharedSingleton,ImmutableOffset}MapTemplate
[yangtools.git] / common / util / src / main / java / org / opendaylight / yangtools / util / ImmutableMapTemplate.java
index 50e3c9ffbf2f95b6fbabc53633d3576278d7af63..4f9d4b0c538ea38461c6114c3606bf544b992f3e 100644 (file)
@@ -8,17 +8,10 @@
 package org.opendaylight.yangtools.util;
 
 import static com.google.common.base.Preconditions.checkArgument;
-import static java.util.Objects.requireNonNull;
 
 import com.google.common.annotations.Beta;
-import com.google.common.base.MoreObjects;
-import com.google.common.collect.ImmutableMap;
-import java.util.Arrays;
 import java.util.Collection;
-import java.util.Iterator;
 import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Objects;
 import java.util.Set;
 import java.util.function.BiFunction;
 import org.eclipse.jdt.annotation.NonNull;
@@ -30,146 +23,14 @@ import org.opendaylight.yangtools.concepts.Immutable;
  * using {@link #instantiateWithValues(Object[])} where the argument array has values ordered corresponding to the key
  * order defined by {@link #keySet()}.
  *
+ * <p>
+ * If the keySet is static known to contain only a single key, consider using {@link SharedSingletonMapTemplate}. If
+ * it is statically known to contain multiple keys, consider using {@link ImmutableOffsetMapTemplate}.
+ *
  * @param <K> the type of keys maintained by this template
  */
 @Beta
 public abstract class ImmutableMapTemplate<K> implements Immutable {
-    private abstract static class AbstractMultiple<K> extends ImmutableMapTemplate<K> {
-        private final @NonNull ImmutableMap<K, Integer> offsets;
-
-        AbstractMultiple(final ImmutableMap<K, Integer> offsets) {
-            this.offsets = requireNonNull(offsets);
-        }
-
-        @Override
-        public final Set<K> keySet() {
-            return offsets.keySet();
-        }
-
-        @Override
-        public final <T, V> @NonNull ImmutableOffsetMap<K, V> instantiateTransformed(final Map<K, T> fromMap,
-                final BiFunction<K, T, V> valueTransformer) {
-            final int size = offsets.size();
-            checkArgument(fromMap.size() == size);
-
-            @SuppressWarnings("unchecked")
-            final V[] objects = (V[]) new Object[size];
-            for (Entry<K, T> entry : fromMap.entrySet()) {
-                final K key = requireNonNull(entry.getKey());
-                final Integer offset = offsets.get(key);
-                checkArgument(offset != null, "Key %s present in input, but not in offsets %s", key, offsets);
-
-                objects[offset.intValue()] = transformValue(key, entry.getValue(), valueTransformer);
-            }
-
-            return createMap(offsets, objects);
-        }
-
-        @Override
-        @SafeVarargs
-        public final <V> @NonNull UnmodifiableMapPhase<K, V> instantiateWithValues(final V... values) {
-            checkArgument(values.length == offsets.size());
-            final V[] copy = values.clone();
-            Arrays.stream(copy).forEach(Objects::requireNonNull);
-            return createMap(offsets, values);
-        }
-
-        @Override
-        public final String toString() {
-            return MoreObjects.toStringHelper(this).add("offsets", offsets).toString();
-        }
-
-        abstract <V> @NonNull ImmutableOffsetMap<K, V> createMap(ImmutableMap<K, Integer> offsets, V[] objects);
-    }
-
-    private static final class Ordered<K> extends AbstractMultiple<K> {
-        Ordered(final Collection<K> keys) {
-            super(OffsetMapCache.orderedOffsets(keys));
-        }
-
-        @Override
-        <V> @NonNull ImmutableOffsetMap<K, V> createMap(final ImmutableMap<K, Integer> offsets, final V[] objects) {
-            return new ImmutableOffsetMap.Ordered<>(offsets, objects);
-        }
-    }
-
-    private static final class Unordered<K> extends AbstractMultiple<K> {
-        Unordered(final Collection<K> keys) {
-            super(OffsetMapCache.unorderedOffsets(keys));
-        }
-
-        @Override
-        <V> @NonNull ImmutableOffsetMap<K, V> createMap(final ImmutableMap<K, Integer> offsets, final V[] objects) {
-            return new ImmutableOffsetMap.Unordered<>(offsets, objects);
-        }
-    }
-
-    private abstract static class AbstractSingle<K> extends ImmutableMapTemplate<K> {
-        private final @NonNull SingletonSet<K> keySet;
-
-        AbstractSingle(final K key) {
-            this.keySet = SharedSingletonMap.cachedSet(key);
-        }
-
-        @Override
-        public Set<K> keySet() {
-            return keySet;
-        }
-
-        @Override
-        public final <T, V> @NonNull SharedSingletonMap<K, V> instantiateTransformed(final Map<K, T> fromMap,
-                final BiFunction<K, T, V> valueTransformer) {
-            final Iterator<Entry<K, T>> it = fromMap.entrySet().iterator();
-            checkArgument(it.hasNext(), "Input is empty while expecting 1 item");
-
-            final Entry<K, T> entry = it.next();
-            final K expected = keySet.getElement();
-            final K actual = entry.getKey();
-            checkArgument(expected.equals(actual), "Unexpected key %s, expecting %s", actual, expected);
-
-            final V value = transformValue(actual, entry.getValue(), valueTransformer);
-            checkArgument(!it.hasNext(), "Input has more than one item");
-
-            return createMap(keySet, value);
-        }
-
-        @Override
-        @SafeVarargs
-        public final <V> @NonNull UnmodifiableMapPhase<K, V> instantiateWithValues(final V... values) {
-            checkArgument(values.length == 1);
-            return createMap(keySet, values[0]);
-        }
-
-        @Override
-        public final String toString() {
-            return MoreObjects.toStringHelper(this).add("keySet", keySet).toString();
-        }
-
-        abstract <V> @NonNull SharedSingletonMap<K, V> createMap(SingletonSet<K> keySet, V value);
-    }
-
-    private static final class SingleOrdered<K> extends AbstractSingle<K> {
-        SingleOrdered(final K key) {
-            super(key);
-        }
-
-        @Override
-        <V> @NonNull SharedSingletonMap<K, V> createMap(final SingletonSet<K> keySet, final V value) {
-            return new SharedSingletonMap.Ordered<>(keySet, value);
-        }
-    }
-
-    private static final class SingleUnordered<K> extends AbstractSingle<K> {
-        SingleUnordered(final K key) {
-            super(key);
-        }
-
-        @Override
-        <V> @NonNull SharedSingletonMap<K, V> createMap(final SingletonSet<K> keySet, final V value) {
-            return new SharedSingletonMap.Unordered<>(keySet, value);
-        }
-    }
-
     ImmutableMapTemplate() {
         // Hidden on purpose
     }
@@ -190,9 +51,9 @@ public abstract class ImmutableMapTemplate<K> implements Immutable {
             case 0:
                 throw new IllegalArgumentException("Proposed keyset must not be empty");
             case 1:
-                return new SingleOrdered<>(keys.iterator().next());
+                return SharedSingletonMapTemplate.ordered(keys.iterator().next());
             default:
-                return new Ordered<>(keys);
+                return ImmutableOffsetMapTemplate.ordered(keys);
         }
     }
 
@@ -212,9 +73,9 @@ public abstract class ImmutableMapTemplate<K> implements Immutable {
             case 0:
                 throw new IllegalArgumentException("Proposed keyset must not be empty");
             case 1:
-                return new SingleUnordered<>(keys.iterator().next());
+                return SharedSingletonMapTemplate.unordered(keys.iterator().next());
             default:
-                return new Unordered<>(keys);
+                return ImmutableOffsetMapTemplate.unordered(keys);
         }
     }
 
@@ -240,7 +101,7 @@ public abstract class ImmutableMapTemplate<K> implements Immutable {
      * @param <V> the type of mapped values
      * @return An immutable map
      * @throws NullPointerException if {@code values} or any of its elements is null
-     * @throws IllegalArgumentException if {@code values.lenght} does not match the number of keys in this template
+     * @throws IllegalArgumentException if {@code values.length} does not match the number of keys in this template
      */
     @SuppressWarnings("unchecked")
     public abstract <V> @NonNull UnmodifiableMapPhase<K, V> instantiateWithValues(V... values);