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 java.util.Arrays;
16 import java.util.Collection;
18 import java.util.Map.Entry;
19 import java.util.Objects;
21 import java.util.function.BiFunction;
22 import org.eclipse.jdt.annotation.NonNull;
25 * Template for instantiating {@link ImmutableOffsetMap} instances with a fixed set of keys. The template can then be
26 * used as a factory for instances via using {@link #instantiateTransformed(Map, BiFunction)} or, more efficiently,
27 * using {@link #instantiateWithValues(Object[])} where the argument array has values ordered corresponding to the key
28 * order defined by {@link #keySet()}.
30 * @param <K> the type of keys maintained by this template
32 public abstract class ImmutableOffsetMapTemplate<K> extends ImmutableMapTemplate<K> {
33 private static final class Ordered<K> extends ImmutableOffsetMapTemplate<K> {
34 Ordered(final Collection<K> keys) {
35 super(OffsetMapCache.orderedOffsets(keys));
39 <V> @NonNull ImmutableOffsetMap<K, V> createMap(final ImmutableMap<K, Integer> offsets, final V[] objects) {
40 return new ImmutableOffsetMap.Ordered<>(offsets, objects);
44 private static final class Unordered<K> extends ImmutableOffsetMapTemplate<K> {
45 Unordered(final Collection<K> keys) {
46 super(OffsetMapCache.unorderedOffsets(keys));
50 <V> @NonNull ImmutableOffsetMap<K, V> createMap(final ImmutableMap<K, Integer> offsets, final V[] objects) {
51 return new ImmutableOffsetMap.Unordered<>(offsets, objects);
55 private final @NonNull ImmutableMap<K, Integer> offsets;
57 ImmutableOffsetMapTemplate(final ImmutableMap<K, Integer> offsets) {
58 this.offsets = requireNonNull(offsets);
62 * Create a template which produces Maps with specified keys, with iteration order matching the iteration order
63 * of {@code keys}. {@link #keySet()} will return these keys in exactly the same order. The resulting map will
64 * retain insertion order through {@link UnmodifiableMapPhase#toModifiableMap()} transformations.
66 * @param keys Keys in requested iteration order.
67 * @param <K> the type of keys maintained by resulting template
68 * @return A template object.
69 * @throws NullPointerException if {@code keys} or any of its elements is null
70 * @throws IllegalArgumentException if {@code keys} is does not have at least two keys
72 public static <K> @NonNull ImmutableOffsetMapTemplate<K> ordered(final Collection<K> keys) {
73 checkArgument(keys.size() > 1);
74 return new Ordered<>(keys);
78 * Create a template which produces Maps with specified keys, with unconstrained iteration order. Produced maps
79 * will have the iteration order matching the order returned by {@link #keySet()}. The resulting map will
80 * NOT retain ordering through {@link UnmodifiableMapPhase#toModifiableMap()} transformations.
82 * @param keys Keys in any iteration order.
83 * @param <K> the type of keys maintained by resulting template
84 * @return A template object.
85 * @throws NullPointerException if {@code keys} or any of its elements is null
86 * @throws IllegalArgumentException if {@code keys} is does not have at least two keys
88 public static <K> @NonNull ImmutableOffsetMapTemplate<K> unordered(final Collection<K> keys) {
89 checkArgument(keys.size() > 1);
90 return new Unordered<>(keys);
94 public final Set<K> keySet() {
95 return offsets.keySet();
99 public final <T, V> @NonNull ImmutableOffsetMap<K, V> instantiateTransformed(final Map<K, T> fromMap,
100 final BiFunction<K, T, V> valueTransformer) {
101 final int size = offsets.size();
102 checkArgument(fromMap.size() == size);
104 @SuppressWarnings("unchecked")
105 final V[] objects = (V[]) new Object[size];
106 for (Entry<K, T> entry : fromMap.entrySet()) {
107 final K key = requireNonNull(entry.getKey());
108 final Integer offset = offsets.get(key);
109 checkArgument(offset != null, "Key %s present in input, but not in offsets %s", key, offsets);
111 objects[offset.intValue()] = transformValue(key, entry.getValue(), valueTransformer);
114 return createMap(offsets, objects);
119 public final <V> @NonNull ImmutableOffsetMap<K, V> instantiateWithValues(final V... values) {
120 checkArgument(values.length == offsets.size());
121 final V[] copy = values.clone();
122 Arrays.stream(copy).forEach(Objects::requireNonNull);
123 return createMap(offsets, values);
127 public final String toString() {
128 return MoreObjects.toStringHelper(this).add("offsets", offsets).toString();
131 abstract <V> @NonNull ImmutableOffsetMap<K, V> createMap(ImmutableMap<K, Integer> offsets, V[] objects);