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.api;
018
019import java.io.Serializable; // for javadoc only
020
021import java.util.Collection;
022import java.util.Collections;
023import java.util.Map;
024
025/**
026 * A {@link ConfigurationException} indicating that conflicting {@link
027 * ConfigurationValue}s were found for a given configuration property
028 * request.
029 *
030 * @author <a href="http://about.me/lairdnelson"
031 * target="_parent">Laird Nelson</a>
032 *
033 * @see ConfigurationValue
034 */
035public class AmbiguousConfigurationValuesException extends ConfigurationException {
036
037
038  /*
039   * Static fields.
040   */
041
042
043  /**
044   * The version of this class for {@linkplain Serializable
045   * serialization} purposes.
046   */
047  private static final long serialVersionUID = 1L;
048
049
050  /*
051   * Instance fields.
052   */
053
054  
055  /**
056   * A {@link Collection} of conflicting {@link ConfigurationValue}s.
057   *
058   * <p>This field is never {@code null} but may be {@linkplain
059   * Collection#isEmpty() empty}.</p>
060   */
061  private final Collection<? extends ConfigurationValue> values;
062
063  /**
064   * The configuration coordinates in effect at the time conflicting
065   * values were found.
066   *
067   * <p>This field is never {@code null}.</p>
068   */
069  private final Map<? extends String, ? extends String> configurationCoordinates;
070
071  /**
072   * The name of the configuration property for which a value was requested.
073   *
074   * <p>This field is never {@code null}.</p>
075   */
076  private final String name;
077
078
079  /*
080   * Constructors.
081   */
082  
083
084  /**
085   * Creates a new {@link AmbiguousConfigurationValuesException}.
086   *
087   * @param message the error message; may be {@code null}
088   *
089   * @param cause the {@link Throwable} that caused this {@link
090   * AmbiguousConfigurationValuesException} to be created; may be
091   * {@code null}
092   *
093   * @param configurationCoordinates the configuration coordinates in
094   * effect at the time conflicting values were found; may be {@code
095   * null}
096   *
097   * @param name the name of the configuration property for which a
098   * value was requested; must not be {@code null}
099   *
100   * @param values the conflicting values; may be {@code null}
101   *
102   * @exception NullPointerException if {@code name} is {@code null}
103   */
104  public AmbiguousConfigurationValuesException(final String message,
105                                               final Throwable cause,
106                                               final Map<? extends String, ? extends String> configurationCoordinates,
107                                               final String name,
108                                               final Collection<? extends ConfigurationValue> values) {
109    super(message, cause);
110    if (name == null) {
111      final NullPointerException throwMe = new NullPointerException();
112      throwMe.addSuppressed(this);
113      throw throwMe;
114    }
115    this.configurationCoordinates = configurationCoordinates == null ? Collections.emptyMap() : Collections.unmodifiableMap(configurationCoordinates);
116    this.name = name;
117    this.values = values == null ? Collections.emptySet() : values;
118  }
119
120  /**
121   * Returns the {@link Collection} of conflicting values that caused
122   * this {@link AmbiguousConfigurationValuesException} to be created.
123   *
124   * <p>This method will never return {@code null}.</p>
125   *
126   * @return a non-{@code null} {@link Collection} of {@link
127   * ConfigurationValue}s
128   */
129  public final Collection<? extends ConfigurationValue> getValues() {
130    return this.values;
131  }
132
133  /**
134   * Returns a {@link Map} representing the configuration coordinates
135   * in effect when this {@link AmbiguousConfigurationValuesException}
136   * was created.
137   *
138   * <p>This method never returns {@code null}.</p>
139   *
140   * @return a non-{@code null} {@link Map} of configuration
141   * coordinates
142   */
143  public final Map<? extends String, ? extends String> getCoordinates() {
144    return this.configurationCoordinates;
145  }
146
147  /**
148   * Returns the name of the configuration property for which a value was requested.
149   *
150   * <p>This method never returns {@code null}.</p>
151   *
152   * @return the name of the configuration property for which a value
153   * was requested; never {@code null}
154   */
155  public final String getName() {
156    return this.name;
157  }
158
159  /**
160   * Returns a non-{@code null} {@link String} representation of this
161   * {@link AmbiguousConfigurationValuesException}.
162   *
163   * <p>This method never returns {@code null}.</p>
164   *
165   * <p>Overrides of this method must not return {@code null}.</p>
166   *
167   * @return a non-{@code null} {@link String} representation of this
168   * {@link AmbiguousConfigurationValuesException}
169   */
170  @Override
171  public String toString() {
172    final StringBuilder sb = new StringBuilder(super.toString());
173    sb.append(" ");
174    sb.append(this.getCoordinates());
175    sb.append(" ");
176    sb.append(this.getName());
177    sb.append(" \u27a1 ");
178    sb.append(this.getValues());
179    return sb.toString();
180  }
181  
182}