/* * Copyright (c) 2018 Pantheon Technologies, 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.util; import static com.google.common.base.Preconditions.checkArgument; import com.google.common.annotations.Beta; import java.util.Collection; import java.util.Map; import java.util.Set; import java.util.function.BiFunction; import org.eclipse.jdt.annotation.NonNull; import org.opendaylight.yangtools.concepts.Immutable; /** * Template for instantiating {@link UnmodifiableMapPhase} instances with a fixed set of keys. The template can then be * used as a factory for instances via using {@link #instantiateTransformed(Map, BiFunction)} or, more efficiently, * using {@link #instantiateWithValues(Object[])} where the argument array has values ordered corresponding to the key * order defined by {@link #keySet()}. * *

* 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 the type of keys maintained by this template */ @Beta public abstract class ImmutableMapTemplate implements Immutable { ImmutableMapTemplate() { // Hidden on purpose } /** * Create a template which produces Maps with specified keys, with iteration order matching the iteration order * of {@code keys}. {@link #keySet()} will return these keys in exactly the same order. The resulting map will * retain insertion order through {@link UnmodifiableMapPhase#toModifiableMap()} transformations. * * @param keys Keys in requested iteration order. * @param the type of keys maintained by resulting template * @return A template object. * @throws NullPointerException if {@code keys} or any of its elements is null * @throws IllegalArgumentException if {@code keys} is empty */ public static @NonNull ImmutableMapTemplate ordered(final Collection keys) { switch (keys.size()) { case 0: throw new IllegalArgumentException("Proposed keyset must not be empty"); case 1: return SharedSingletonMapTemplate.ordered(keys.iterator().next()); default: return ImmutableOffsetMapTemplate.ordered(keys); } } /** * Create a template which produces Maps with specified keys, with unconstrained iteration order. Produced maps * will have the iteration order matching the order returned by {@link #keySet()}. The resulting map will * NOT retain ordering through {@link UnmodifiableMapPhase#toModifiableMap()} transformations. * * @param keys Keys in any iteration order. * @param the type of keys maintained by resulting template * @return A template object. * @throws NullPointerException if {@code keys} or any of its elements is null * @throws IllegalArgumentException if {@code keys} is empty */ public static @NonNull ImmutableMapTemplate unordered(final Collection keys) { switch (keys.size()) { case 0: throw new IllegalArgumentException("Proposed keyset must not be empty"); case 1: return SharedSingletonMapTemplate.unordered(keys.iterator().next()); default: return ImmutableOffsetMapTemplate.unordered(keys); } } /** * Instantiate an immutable map by applying specified {@code transformer} to values of {@code fromMap}. * * @param fromMap Input map * @param keyValueTransformer Transformation to apply to values * @param the type of input values * @param the type of mapped values * @return An immutable map * @throws NullPointerException if any of the arguments is null or if the transformer produces a {@code null} value * @throws IllegalArgumentException if {@code fromMap#keySet()} does not match this template's keys */ public abstract @NonNull UnmodifiableMapPhase instantiateTransformed(Map fromMap, BiFunction keyValueTransformer); /** * Instantiate an immutable map by filling values from provided array. The array MUST be ordered to match key order * as returned by {@link #keySet()}. * * @param values Values to use * @param 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.length} does not match the number of keys in this template */ @SuppressWarnings("unchecked") public abstract @NonNull UnmodifiableMapPhase instantiateWithValues(V... values); /** * Returns the set of keys expected by this template, in the iteration order Maps resulting from instantiation * will have. * * @return This template's key set * @see Map#keySet() */ public abstract Set keySet(); final @NonNull V transformValue(final K key, final T input, final BiFunction transformer) { final V value = transformer.apply(key, input); checkArgument(value != null, "Transformer returned null for input %s at key %s", input, key); return value; } }