All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.opendaylight.yangtools.binding.util.BindingMap Maven / Gradle / Ivy

/*
 * Copyright (c) 2020 PANTHEON.tech, s.r.o. and others.  All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
 * and is available at http://www.eclipse.org/legal/epl-v10.html
 */
package org.opendaylight.yangtools.binding.util;

import com.google.common.annotations.Beta;
import com.google.common.collect.Collections2;
import com.google.common.collect.ImmutableMap;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Map;
import java.util.Map.Entry;
import java.util.stream.Collector;
import java.util.stream.Collectors;
import org.eclipse.jdt.annotation.NonNull;
import org.opendaylight.yangtools.binding.EntryObject;
import org.opendaylight.yangtools.binding.Key;

/**
 * Utility class for instantiating Maps containing {@link EntryObject} values. Unlike normal Map instantiation
 * utilities, methods in this class index values via their identifier, hence providing a more convenient API, amenable
 * to fluent builders.
 *
 * 

* A typical example of use with generated DataObjects looks like this: *

 *   
 *     Foo foo = new FooBuilder()
 *          .setBar(BindingMap.of(
 *              new BarBuilder().setName("one").build(),
 *              new BarBuilder().setName("two").build()))
 *          .build();
 *   
 * 
* *

* Another alternative is to use builders: *

 *   
 *     Foo foo = new FooBuilder()
 *          .setBar(BindingMap.<BarKey, Bar>builder()
 *              .add(new BarBuilder().setName("one").build())
 *              .add(new BarBuilder().setName("two").build())
 *              .build())
 *          .build();
 *   
 * 
* *

* This class allows for two modes of operation: *

    *
  • Unordered, available through {@link #of(EntryObject...)}/{@link #builder()} family of functions. Maps * instantiated through this, preferred, interface will have their iteration order randomized, as explain in * Java 9+ unmodifiable collections.
  • *
  • Ordered, available through {@link #ordered(EntryObject...)}/{@link #orderedBuilder()} family of functions. * Maps instantiated through this interface have a predictable iteration order, as per {@link ImmutableMap} * class design. The use of this interface is generally discouraged, as it may lead to code relying on map * iteration order. Nevertheless it may prove useful where the goal is to have predictable outcomes and hence * is provided for completeness.
  • *
*/ @Beta public final class BindingMap { private BindingMap() { // Hidden on purpose } /** * Returns an unmodifiable map containing a single mapping. * * @param the {@code Map}'s key type * @param the {@code Map}'s value type * @param v1 the mapping's value * @return a {@code Map} containing the specified value * @throws NullPointerException if the value is {@code null} */ public static , V extends EntryObject> @NonNull Map of(final V v1) { return Map.of(v1.key(), v1); } /** * Returns an unmodifiable map containing two mappings. The resulting map is NOT guaranteed retain iteration * order of mappings. * * @param the {@code Map}'s key type * @param the {@code Map}'s value type * @param v1 the first mapping's value * @param v2 the second mapping's value * @return a {@code Map} containing the specified mappings * @throws IllegalArgumentException if the values contain duplicate keys * @throws NullPointerException if any value is {@code null} */ public static , V extends EntryObject> @NonNull Map of(final V v1, final V v2) { return Map.of(v1.key(), v1, v2.key(), v2); } /** * Returns an unmodifiable map containing three mappings. The resulting map is NOT guaranteed to retain * iteration order of mappings. * * @param the {@code Map}'s key type * @param the {@code Map}'s value type * @param v1 the first mapping's value * @param v2 the second mapping's value * @param v3 the third mapping's value * @return a {@code Map} containing the specified mappings * @throws IllegalArgumentException if the values contain duplicate keys * @throws NullPointerException if any value is {@code null} */ public static , V extends EntryObject> @NonNull Map of(final V v1, final V v2, final V v3) { return Map.of(v1.key(), v1, v2.key(), v2, v3.key(), v3); } /** * Returns an unmodifiable map containing four mappings. The resulting map is NOT guaranteed to retain * iteration order of mappings. * * @param the {@code Map}'s key type * @param the {@code Map}'s value type * @param v1 the first mapping's value * @param v2 the second mapping's value * @param v3 the third mapping's value * @param v4 the fourth mapping's value * @return a {@code Map} containing the specified mappings * @throws IllegalArgumentException if the values contain duplicate keys * @throws NullPointerException if any value is {@code null} */ public static , V extends EntryObject> @NonNull Map of(final V v1, final V v2, final V v3, final V v4) { return Map.of(v1.key(), v1, v2.key(), v2, v3.key(), v3, v4.key(), v4); } /** * Returns an unmodifiable map containing five mappings. The resulting map is NOT guaranteed to retain * iteration order of mappings. * * @param the {@code Map}'s key type * @param the {@code Map}'s value type * @param v1 the first mapping's value * @param v2 the second mapping's value * @param v3 the third mapping's value * @param v4 the fourth mapping's value * @param v5 the fifth mapping's value * @return a {@code Map} containing the specified mappings * @throws IllegalArgumentException if the values contain duplicate keys * @throws NullPointerException if any value is {@code null} */ public static , V extends EntryObject> @NonNull Map of(final V v1, final V v2, final V v3, final V v4, final V v5) { return Map.of(v1.key(), v1, v2.key(), v2, v3.key(), v3, v4.key(), v4, v5.key(), v5); } /** * Returns an unmodifiable map containing six mappings. The resulting map is NOT guaranteed to retain * iteration order of mappings. * * @param the {@code Map}'s key type * @param the {@code Map}'s value type * @param v1 the first mapping's value * @param v2 the second mapping's value * @param v3 the third mapping's value * @param v4 the fourth mapping's value * @param v5 the fifth mapping's value * @param v6 the sixth mapping's value * @return a {@code Map} containing the specified mappings * @throws IllegalArgumentException if the values contain duplicate keys * @throws NullPointerException if any value is {@code null} */ public static , V extends EntryObject> @NonNull Map of(final V v1, final V v2, final V v3, final V v4, final V v5, final V v6) { return Map.of(v1.key(), v1, v2.key(), v2, v3.key(), v3, v4.key(), v4, v5.key(), v5, v6.key(), v6); } /** * Returns an unmodifiable map containing seven mappings. The resulting map is NOT guaranteed to retain * iteration order of mappings. * * @param the {@code Map}'s key type * @param the {@code Map}'s value type * @param v1 the first mapping's value * @param v2 the second mapping's value * @param v3 the third mapping's value * @param v4 the fourth mapping's value * @param v5 the fifth mapping's value * @param v6 the sixth mapping's value * @param v7 the seventh mapping's value * @return a {@code Map} containing the specified mappings * @throws IllegalArgumentException if the values contain duplicate keys * @throws NullPointerException if any value is {@code null} */ public static , V extends EntryObject> @NonNull Map of(final V v1, final V v2, final V v3, final V v4, final V v5, final V v6, final V v7) { return Map.of(v1.key(), v1, v2.key(), v2, v3.key(), v3, v4.key(), v4, v5.key(), v5, v6.key(), v6, v7.key(), v7); } /** * Returns an unmodifiable map containing eight mappings. The resulting map is NOT guaranteed to retain * iteration order of mappings. * * @param the {@code Map}'s key type * @param the {@code Map}'s value type * @param v1 the first mapping's value * @param v2 the second mapping's value * @param v3 the third mapping's value * @param v4 the fourth mapping's value * @param v5 the fifth mapping's value * @param v6 the sixth mapping's value * @param v7 the seventh mapping's value * @param v8 the eighth mapping's value * @return a {@code Map} containing the specified mappings * @throws IllegalArgumentException if the values contain duplicate keys * @throws NullPointerException if any value is {@code null} */ public static , V extends EntryObject> @NonNull Map of(final V v1, final V v2, final V v3, final V v4, final V v5, final V v6, final V v7, final V v8) { return Map.of(v1.key(), v1, v2.key(), v2, v3.key(), v3, v4.key(), v4, v5.key(), v5, v6.key(), v6, v7.key(), v7, v8.key(), v8); } /** * Returns an unmodifiable map containing nine mappings. The resulting map is NOT guaranteed to retain * iteration order of mappings. * * @param the {@code Map}'s key type * @param the {@code Map}'s value type * @param v1 the first mapping's value * @param v2 the second mapping's value * @param v3 the third mapping's value * @param v4 the fourth mapping's value * @param v5 the fifth mapping's value * @param v6 the sixth mapping's value * @param v7 the seventh mapping's value * @param v8 the eighth mapping's value * @param v9 the ninth mapping's value * @return a {@code Map} containing the specified mappings * @throws IllegalArgumentException if the values contain duplicate keys * @throws NullPointerException if any value is {@code null} */ public static , V extends EntryObject> @NonNull Map of(final V v1, final V v2, final V v3, final V v4, final V v5, final V v6, final V v7, final V v8, final V v9) { return Map.of(v1.key(), v1, v2.key(), v2, v3.key(), v3, v4.key(), v4, v5.key(), v5, v6.key(), v6, v7.key(), v7, v8.key(), v8, v9.key(), v9); } /** * Returns an unmodifiable map containing ten mappings. The resulting map is NOT guaranteed to retain * iteration order of mappings. * * @param the {@code Map}'s key type * @param the {@code Map}'s value type * @param v1 the first mapping's value * @param v2 the second mapping's value * @param v3 the third mapping's value * @param v4 the fourth mapping's value * @param v5 the fifth mapping's value * @param v6 the sixth mapping's value * @param v7 the seventh mapping's value * @param v8 the eighth mapping's value * @param v9 the ninth mapping's value * @param v10 the ninth mapping's value * @return a {@code Map} containing the specified mappings * @throws IllegalArgumentException if the values contain duplicate keys * @throws NullPointerException if any value is {@code null} */ public static , V extends EntryObject> @NonNull Map of(final V v1, final V v2, final V v3, final V v4, final V v5, final V v6, final V v7, final V v8, final V v9, final V v10) { return Map.of(v1.key(), v1, v2.key(), v2, v3.key(), v3, v4.key(), v4, v5.key(), v5, v6.key(), v6, v7.key(), v7, v8.key(), v8, v9.key(), v9, v10.key(), v10); } /** * Returns an unmodifiable map containing given values. The resulting map is NOT guaranteed to retain * iteration order of the input array. * * @param the {@code Map}'s key type * @param the {@code Map}'s value type * @param values values from which the map is populated * @return a {@code Map} containing the specified values * @throws IllegalArgumentException if there are any duplicate keys in the provided values * @throws NullPointerException if any value is {@code null}, or if the {@code values} array is {@code null} */ @SafeVarargs public static , V extends EntryObject> @NonNull Map of(final V... values) { return of(Arrays.asList(values)); } /** * Returns an unmodifiable map containing given values. The resulting map is NOT guaranteed to retain * iteration order of the input collection. * * @param the {@code Map}'s key type * @param the {@code Map}'s value type * @param values values from which the map is populated * @return a {@code Map} containing the specified values * @throws IllegalArgumentException if there are any duplicate keys in the provided values * @throws NullPointerException if any value is {@code null}, or if the {@code values} array is {@code null} */ public static , V extends EntryObject> @NonNull Map of( final Collection values) { return values.stream().collect(toMap()); } /** * Returns a collector which collects binding {@link EntryObject}s into an unmodifiable map. The resulting map is * NOT guaranteed to retain iteration order of the stream it collects. * * @param the {@code Map}'s key type * @param the {@code Map}'s value type * @return A collector that accumulates the input elements into an unmodifiable map. */ public static , V extends EntryObject> @NonNull Collector> toMap() { return Collectors.toUnmodifiableMap(EntryObject::key, v -> v); } /** * Create a builder on an unmodifiable map, which does not retain value insertion order. The builder will be * pre-sized to hold {@value Builder#DEFAULT_INITIAL_CAPACITY} elements. * * @param the {@code Map}'s key type * @param the {@code Map}'s value type * @return A {@link Builder} instance. */ public static , V extends EntryObject> @NonNull Builder builder() { return builder(Builder.DEFAULT_INITIAL_CAPACITY); } /** * Create a builder on an unmodifiable map, which does not retain value insertion order. The builder will be * pre-sized to hold specified number of elements. * * @param the {@code Map}'s key type * @param the {@code Map}'s value type * @param expectedSize Expected number of values in the resulting map * @return A {@link Builder} instance. */ public static , V extends EntryObject> @NonNull Builder builder( final int expectedSize) { return new UnorderedBuilder<>(expectedSize); } /** * Returns an unmodifiable map containing two mappings. The resulting map will retain iteration order of mappings. * * @param the {@code Map}'s key type * @param the {@code Map}'s value type * @param v1 the first mapping's value * @param v2 the second mapping's value * @return a {@code Map} containing the specified mappings * @throws IllegalArgumentException if the values contain duplicate keys * @throws NullPointerException if any value is {@code null} */ public static , V extends EntryObject> @NonNull Map ordered(final V v1, final V v2) { return ImmutableMap.of(v1.key(), v1, v2.key(), v2); } /** * Returns an unmodifiable map containing three mappings. The resulting map will retain iteration order of mappings. * * @param the {@code Map}'s key type * @param the {@code Map}'s value type * @param v1 the first mapping's value * @param v2 the second mapping's value * @param v3 the third mapping's value * @return a {@code Map} containing the specified mappings * @throws IllegalArgumentException if the values contain duplicate keys * @throws NullPointerException if any value is {@code null} */ public static , V extends EntryObject> @NonNull Map ordered(final V v1, final V v2, final V v3) { return ImmutableMap.of(v1.key(), v1, v2.key(), v2, v3.key(), v3); } /** * Returns an unmodifiable map containing four mappings. The resulting map will retain iteration order of mappings. * * @param the {@code Map}'s key type * @param the {@code Map}'s value type * @param v1 the first mapping's value * @param v2 the second mapping's value * @param v3 the third mapping's value * @param v4 the fourth mapping's value * @return a {@code Map} containing the specified mappings * @throws IllegalArgumentException if the values contain duplicate keys * @throws NullPointerException if any value is {@code null} */ public static , V extends EntryObject> @NonNull Map ordered(final V v1, final V v2, final V v3, final V v4) { return ImmutableMap.of(v1.key(), v1, v2.key(), v2, v3.key(), v3, v4.key(), v4); } /** * Returns an unmodifiable map containing five mappings. The resulting map will retain iteration order of mappings. * * @param the {@code Map}'s key type * @param the {@code Map}'s value type * @param v1 the first mapping's value * @param v2 the second mapping's value * @param v3 the third mapping's value * @param v4 the fourth mapping's value * @param v5 the fifth mapping's value * @return a {@code Map} containing the specified mappings * @throws IllegalArgumentException if the values contain duplicate keys * @throws NullPointerException if any value is {@code null} */ public static , V extends EntryObject> @NonNull Map ordered(final V v1, final V v2, final V v3, final V v4, final V v5) { return ImmutableMap.of(v1.key(), v1, v2.key(), v2, v3.key(), v3, v4.key(), v4, v5.key(), v5); } /** * Returns an unmodifiable map containing given values. Resulting {@code Map} will retain the iteration order of * values. * * @param the {@code Map}'s key type * @param the {@code Map}'s value type * @param values values from which the map is populated * @return a {@code Map} containing the specified values * @throws IllegalArgumentException if there are any duplicate keys in the provided values * @throws NullPointerException if any value is {@code null}, or if the {@code values} array is {@code null} */ @SafeVarargs public static , V extends EntryObject> @NonNull Map ordered(final V... values) { return ordered(Arrays.asList(values)); } /** * Returns an unmodifiable map containing given values. Resulting {@code Map} will retain the iteration order of * values. * * @param the {@code Map}'s key type * @param the {@code Map}'s value type * @param values values from which the map is populated * @return a {@code Map} containing the specified values * @throws IllegalArgumentException if there are any duplicate keys in the provided values * @throws NullPointerException if any value is {@code null}, or if the {@code values} array is {@code null} */ public static , V extends EntryObject> @NonNull Map ordered( final Collection values) { return values.stream().collect(toOrderedMap()); } /** * Returns a collector which collects binding {@link EntryObject}s into an unmodifiable map. The resulting map will * retain iteration order of the stream it collects. * * @param the {@code Map}'s key type * @param the {@code Map}'s value type * @return A collector that accumulates the input elements into an unmodifiable map. */ public static , V extends EntryObject> @NonNull Collector> toOrderedMap() { return ImmutableMap.toImmutableMap(EntryObject::key, v -> v); } /** * Create a builder on an unmodifiable map, which retains value insertion order. The builder will be pre-sized to * hold {@value Builder#DEFAULT_INITIAL_CAPACITY} elements. * * @param the {@code Map}'s key type * @param the {@code Map}'s value type * @return A {@link Builder} instance. */ public static , V extends EntryObject> @NonNull Builder orderedBuilder() { return orderedBuilder(Builder.DEFAULT_INITIAL_CAPACITY); } /** * Create a builder on an unmodifiable map, which retains value insertion order. The builder will be pre-sized to * hold specified number of elements. * * @param the {@code Map}'s key type * @param the {@code Map}'s value type * @param expectedSize Expected number of values in the resulting map * @return A {@link Builder} instance. */ public static , V extends EntryObject> @NonNull Builder orderedBuilder( final int expectedSize) { return new OrderedBuilder<>(expectedSize); } /** * Builder producing a Map containing binding {@link EntryObject} values. * * @param the {@code Map}'s key type * @param the {@code Map}'s value type */ public abstract static class Builder, V extends EntryObject> { static final int DEFAULT_INITIAL_CAPACITY = 4; Builder() { // Hidden on purpose } /** * Add a value to this builder. * * @param value the value to add * @return this builder * @throws NullPointerException if value is {@code null} */ public final @NonNull Builder add(final V value) { addEntry(value.key(), value); return this; } /** * Add values to this builder. * * @param values the values to add * @return this builder * @throws NullPointerException if value is, or contains, {@code null} */ @SafeVarargs public final @NonNull Builder addAll(final V... values) { return addAll(Arrays.asList(values)); } /** * Add values to this builder. * * @param values the values to add * @return this builder * @throws NullPointerException if value is, or contains, {@code null} */ public final @NonNull Builder addAll(final Collection values) { addEntries(Collections2.transform(values, value -> Map.entry(value.key(), value))); return this; } /** * Build map from existing map entries in this builder. * * @return Resulting map * @throws IllegalArgumentException if duplicate keys were added */ public abstract @NonNull Map build(); /** * Add map entry identified by its {@code key} and containing {@code value} to this builder. * * @param key Key of the map entry * @param value Value of the map entry */ abstract void addEntry(K key, V value); /** * Add collection of map entries to this builder. * * @param entries Map entries to add */ abstract void addEntries(Collection> entries); } private static final class OrderedBuilder, V extends EntryObject> extends Builder { private final ImmutableMap.Builder delegate; OrderedBuilder(final int expectedSize) { delegate = ImmutableMap.builderWithExpectedSize(expectedSize); } @Override public Map build() { return delegate.build(); } @Override void addEntry(final K key, final V value) { delegate.put(key, value); } @Override void addEntries(final Collection> entries) { delegate.putAll(entries); } } private static final class UnorderedBuilder, V extends EntryObject> extends Builder { private final ArrayList> buffer; UnorderedBuilder(final int expectedSize) { buffer = new ArrayList<>(expectedSize); } @Override @SuppressWarnings("unchecked") public Map build() { return Map.ofEntries(buffer.toArray(new Entry[0])); } @Override void addEntry(final K key, final V value) { buffer.add(Map.entry(key, value)); } @Override void addEntries(final Collection> entries) { buffer.addAll(entries); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy