Factor out {SharedSingleton,ImmutableOffset}MapTemplate
[yangtools.git] / common / util / src / main / java / org / opendaylight / yangtools / util / SharedSingletonMapTemplate.java
1 /*
2  * Copyright (c) 2018 Pantheon Technologies, s.r.o. and others.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.yangtools.util;
9
10 import static com.google.common.base.Preconditions.checkArgument;
11
12 import com.google.common.base.MoreObjects;
13 import java.util.Iterator;
14 import java.util.Map;
15 import java.util.Map.Entry;
16 import java.util.function.BiFunction;
17 import org.eclipse.jdt.annotation.NonNull;
18
19 /**
20  * Template for instantiating {@link SharedSingletonMap} instances with a fixed key. The template can then be
21  * used as a factory for instances via using {@link #instantiateTransformed(Map, BiFunction)} or, more efficiently,
22  * using {@link #instantiateWithValue(Object)}.
23  *
24  * @param <K> the type of keys maintained by this template
25  */
26 public abstract class SharedSingletonMapTemplate<K> extends ImmutableMapTemplate<K> {
27     private static final class Ordered<K> extends SharedSingletonMapTemplate<K> {
28         Ordered(final K key) {
29             super(key);
30         }
31
32         @Override
33         public <V> @NonNull SharedSingletonMap<K, V> instantiateWithValue(final V value) {
34             return new SharedSingletonMap.Ordered<>(keySet(), value);
35         }
36     }
37
38     private static final class Unordered<K> extends SharedSingletonMapTemplate<K> {
39         Unordered(final K key) {
40             super(key);
41         }
42
43         @Override
44         public <V> @NonNull SharedSingletonMap<K, V> instantiateWithValue(final V value) {
45             return new SharedSingletonMap.Unordered<>(keySet(), value);
46         }
47     }
48
49     private final @NonNull SingletonSet<K> keySet;
50
51     SharedSingletonMapTemplate(final K key) {
52         this.keySet = SharedSingletonMap.cachedSet(key);
53     }
54
55     /**
56      * Create a template which produces Maps with specified key. The resulting map will retain insertion order through
57      * {@link UnmodifiableMapPhase#toModifiableMap()} transformations.
58      *
59      * @param key Single key in resulting map
60      * @param <K> the type of keys maintained by resulting template
61      * @return A template object.
62      * @throws NullPointerException if {@code key} is null
63      */
64     public static <K> @NonNull SharedSingletonMapTemplate<K> ordered(final K key) {
65         return new Ordered<>(key);
66     }
67
68     /**
69      * Create a template which produces Maps with specified key. The resulting map will NOT retain ordering through
70      * {@link UnmodifiableMapPhase#toModifiableMap()} transformations.
71      *
72      * @param key Single key in resulting map
73      * @param <K> the type of keys maintained by resulting template
74      * @return A template object.
75      * @throws NullPointerException if {@code key} is null
76      */
77     public static <K> @NonNull SharedSingletonMapTemplate<K> unordered(final K key) {
78         return new Unordered<>(key);
79     }
80
81     @Override
82     public final SingletonSet<K> keySet() {
83         return keySet;
84     }
85
86     @Override
87     public final <T, V> @NonNull SharedSingletonMap<K, V> instantiateTransformed(final Map<K, T> fromMap,
88             final BiFunction<K, T, V> valueTransformer) {
89         final Iterator<Entry<K, T>> it = fromMap.entrySet().iterator();
90         checkArgument(it.hasNext(), "Input is empty while expecting 1 item");
91
92         final Entry<K, T> entry = it.next();
93         final K expected = keySet.getElement();
94         final K actual = entry.getKey();
95         checkArgument(expected.equals(actual), "Unexpected key %s, expecting %s", actual, expected);
96
97         final V value = transformValue(actual, entry.getValue(), valueTransformer);
98         checkArgument(!it.hasNext(), "Input has more than one item");
99         return instantiateWithValue(value);
100     }
101
102     @Override
103     @SafeVarargs
104     public final <V> @NonNull SharedSingletonMap<K, V> instantiateWithValues(final V... values) {
105         checkArgument(values.length == 1);
106         return instantiateWithValue(values[0]);
107     }
108
109     /**
110      * Instantiate an immutable map with the value supplied.
111      *
112      * @param value Value to use
113      * @param <V> the type of mapped values
114      * @return An immutable map
115      * @throws NullPointerException if {@code value} is null
116      */
117     public abstract <V> @NonNull SharedSingletonMap<K, V> instantiateWithValue(V value);
118
119     @Override
120     public final String toString() {
121         return MoreObjects.toStringHelper(this).add("keySet", keySet).toString();
122     }
123 }