001/* -*- mode: Java; c-basic-offset: 2; indent-tabs-mode: nil; coding: utf-8-unix -*-
002 *
003 * Copyright © 2017 MicroBean.
004 *
005 * Licensed under the Apache License, Version 2.0 (the "License");
006 * you may not use this file except in compliance with the License.
007 * You may obtain a copy of the License at
008 *
009 *     http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
014 * implied.  See the License for the specific language governing
015 * permissions and limitations under the License.
016 */
017package org.microbean.configuration.spi;
018
019import java.util.Collection;
020import java.util.Collections; // for javadoc only
021import java.util.Map;
022
023import org.microbean.configuration.api.AmbiguousConfigurationValuesException; // for javadoc only
024import org.microbean.configuration.api.ConfigurationValue;
025
026/**
027 * A resolver of ambiguous {@link ConfigurationValue}s.
028 *
029 * @author <a href="https://about.me/lairdnelson"
030 * target="_parent">Laird Nelson</a>
031 *
032 * @see #arbitrate(Map, String, Collection)
033 */
034public interface Arbiter {
035
036  /**
037   * Given a logical request for a configuration value, represented by
038   * the {@code callerCoordinates} and {@code name} parameter values,
039   * and a {@link Collection} of {@link ConfigurationValue} instances
040   * that represents the ambiguous response from several {@link
041   * Configuration} instances, attempts to resolve the ambiguity by
042   * returning a single {@link ConfigurationValue} instead.
043   *
044   * <p>Implementations of this method may return {@code null}.</p>
045   *
046   * <p>A special case is when the supplied {@code ambiguousValues}
047   * parameter is {@code null} or {@linkplain Collection#isEmpty()
048   * empty}.  This means, effectively, that all consulted {@link
049   * Configuration} instances returned {@code null} from their {@link
050   * Configuration#getValue(Map, String)} methods.  An {@link Arbiter}
051   * encountering this state of affairs and returning a single
052   * non-{@code null} {@link ConfigurationValue} is effectively
053   * synthesizing a default value.</p>
054   *
055   * @param requestedCoordinates the ({@linkplain
056   * Collections#unmodifiableMap(Map) immutable}) configuration
057   * coordinates in effect for the request; may be {@code null}
058   *
059   * @param name the name of the configuration value; must not be
060   * {@code null}
061   *
062   * @param ambiguousValues an {@linkplain
063   * Collections#unmodifiableCollection(Collection) immutable} {@link
064   * Collection} of definitionally ambiguous {@link
065   * ConfigurationValue}s that resulted from the request; may be
066   * {@code null}
067   *
068   * @return the result of arbitration, or {@code null} if the dispute
069   * cannot be arbitrated by this {@link Arbiter}
070   *
071   * @exception NullPointerException if {@code name} is {@code null}
072   *
073   * @exception AmbiguousConfigurationValuesException if overall
074   * arbitration is to be cut short by this {@link
075   * Arbiter}&mdash;normally an {@link Arbiter} should simply return
076   * {@code null}
077   */
078  public ConfigurationValue arbitrate(final Map<? extends String, ? extends String> requestedCoordinates,
079                                      final String name,
080                                      final Collection<? extends ConfigurationValue> ambiguousValues);
081  
082}