2 * Copyright (c) 2018 Pantheon Technologies, s.r.o. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.yangtools.util;
10 import static com.google.common.base.Preconditions.checkArgument;
11 import static java.util.Objects.requireNonNull;
13 import com.google.common.base.MoreObjects;
14 import com.google.common.collect.ImmutableMap;
15 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
16 import java.util.Arrays;
17 import java.util.Collection;
19 import java.util.Map.Entry;
20 import java.util.Objects;
22 import java.util.function.BiFunction;
23 import org.eclipse.jdt.annotation.NonNull;
26 * Template for instantiating {@link ImmutableOffsetMap} instances with a fixed set of keys. The template can then be
27 * used as a factory for instances via using {@link #instantiateTransformed(Map, BiFunction)} or, more efficiently,
28 * using {@link #instantiateWithValues(Object[])} where the argument array has values ordered corresponding to the key
29 * order defined by {@link #keySet()}.
31 * @param <K> the type of keys maintained by this template
33 public abstract class ImmutableOffsetMapTemplate<K> extends ImmutableMapTemplate<K> {
34 private static final class Ordered<K> extends ImmutableOffsetMapTemplate<K> {
35 Ordered(final Collection<K> keys) {
36 super(OffsetMapCache.orderedOffsets(keys));
40 <V> @NonNull ImmutableOffsetMap<K, V> createMap(final ImmutableMap<K, Integer> offsets, final V[] objects) {
41 return new ImmutableOffsetMap.Ordered<>(offsets, objects);
45 private static final class Unordered<K> extends ImmutableOffsetMapTemplate<K> {
46 Unordered(final Collection<K> keys) {
47 super(OffsetMapCache.unorderedOffsets(keys));
51 <V> @NonNull ImmutableOffsetMap<K, V> createMap(final ImmutableMap<K, Integer> offsets, final V[] objects) {
52 return new ImmutableOffsetMap.Unordered<>(offsets, objects);
56 private final @NonNull ImmutableMap<K, Integer> offsets;
58 ImmutableOffsetMapTemplate(final ImmutableMap<K, Integer> offsets) {
59 this.offsets = requireNonNull(offsets);
63 * Create a template which produces Maps with specified keys, with iteration order matching the iteration order
64 * of {@code keys}. {@link #keySet()} will return these keys in exactly the same order. The resulting map will
65 * retain insertion order through {@link UnmodifiableMapPhase#toModifiableMap()} transformations.
67 * @param keys Keys in requested iteration order.
68 * @param <K> the type of keys maintained by resulting template
69 * @return A template object.
70 * @throws NullPointerException if {@code keys} or any of its elements is null
71 * @throws IllegalArgumentException if {@code keys} is does not have at least two keys
73 public static <K> @NonNull ImmutableOffsetMapTemplate<K> ordered(final Collection<K> keys) {
74 checkArgument(keys.size() > 1);
75 return new Ordered<>(keys);
79 * Create a template which produces Maps with specified keys, with unconstrained iteration order. Produced maps
80 * will have the iteration order matching the order returned by {@link #keySet()}. The resulting map will
81 * NOT retain ordering through {@link UnmodifiableMapPhase#toModifiableMap()} transformations.
83 * @param keys Keys in any iteration order.
84 * @param <K> the type of keys maintained by resulting template
85 * @return A template object.
86 * @throws NullPointerException if {@code keys} or any of its elements is null
87 * @throws IllegalArgumentException if {@code keys} is does not have at least two keys
89 public static <K> @NonNull ImmutableOffsetMapTemplate<K> unordered(final Collection<K> keys) {
90 checkArgument(keys.size() > 1);
91 return new Unordered<>(keys);
95 public final Set<K> keySet() {
96 return offsets.keySet();
100 public final <T, V> @NonNull ImmutableOffsetMap<K, V> instantiateTransformed(final Map<K, T> fromMap,
101 final BiFunction<K, T, V> valueTransformer) {
102 final int size = offsets.size();
103 checkArgument(fromMap.size() == size);
105 @SuppressWarnings("unchecked")
106 final V[] objects = (V[]) new Object[size];
107 for (Entry<K, T> entry : fromMap.entrySet()) {
108 final K key = requireNonNull(entry.getKey());
109 objects[offsetOf(key)] = transformValue(key, entry.getValue(), valueTransformer);
112 return createMap(offsets, objects);
115 @SuppressFBWarnings(value = "NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE",
116 justification = "SpotBugs does not grok checkArgument()")
117 private int offsetOf(final K key) {
118 final Integer offset = offsets.get(key);
119 checkArgument(offset != null, "Key %s present in input, but not in offsets %s", key, offsets);
125 public final <V> @NonNull ImmutableOffsetMap<K, V> instantiateWithValues(final V... values) {
126 checkArgument(values.length == offsets.size());
127 final V[] copy = values.clone();
128 Arrays.stream(copy).forEach(Objects::requireNonNull);
129 return createMap(offsets, values);
133 public final String toString() {
134 return MoreObjects.toStringHelper(this).add("offsets", offsets).toString();
137 abstract <V> @NonNull ImmutableOffsetMap<K, V> createMap(ImmutableMap<K, Integer> offsets, V[] objects);