001/* -*- mode: Java; c-basic-offset: 2; indent-tabs-mode: nil; coding: utf-8-unix -*-
002 *
003 * Copyright © 2019–2020 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.settings;
018
019import java.lang.annotation.Annotation;
020import java.lang.annotation.Documented;
021import java.lang.annotation.ElementType;
022import java.lang.annotation.Retention;
023import java.lang.annotation.RetentionPolicy;
024import java.lang.annotation.Target;
025
026import java.lang.reflect.Type;
027
028import java.util.Collections;
029import java.util.HashSet;
030import java.util.Objects;
031import java.util.Set;
032
033import java.util.function.Supplier;
034
035import javax.enterprise.util.AnnotationLiteral;
036import javax.enterprise.util.Nonbinding;
037
038import javax.inject.Qualifier;
039
040/**
041 * A {@linkplain Qualifier CDI <code>Qualifier</code>} indicating that
042 * the annotated element should be provided via a {@link
043 * Settings}-originated <a
044 * href="{@docRoot}/overview-summary.html#setting_value_acquisition">value
045 * acquisition operation</a>, such as {@link Settings#get(String, Set,
046 * Converter, BiFunction)}.
047 *
048 * @author <a href="https://about.me/lairdnelson"
049 * target="_parent">Laird Nelson</a>
050 *
051 * @see Settings#get(String, Set, Converter, BiFunction)
052 */
053@Documented
054@Qualifier
055@Retention(RetentionPolicy.RUNTIME)
056@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE })
057public @interface Setting {
058
059
060  /*
061   * Static fields.
062   */
063
064
065  /**
066   * A value indicating {@code null} for use in annotation elements,
067   * since annotation elements cannot return or be set to {@code
068   * null}.
069   *
070   * @see #defaultValue()
071   */
072  static final String UNSET = "\u2400"; // see https://en.wikipedia.org/wiki/Control_Pictures
073
074
075  /*
076   * Elements.
077   */
078
079
080  /**
081   * The setting name.
082   *
083   * @return the setting name; never {@code null} but possibly {@link
084   * #UNSET}
085   */
086  String name();
087
088  /**
089   * The default value for the setting.
090   *
091   * @return the default value; never {@code null} but possibly {@link
092   * #UNSET}
093   */
094  @Nonbinding
095  String defaultValue() default UNSET;
096
097  /**
098   * Whether a value for the setting must be present; it is illegal to
099   * set this to {@code true} and set the {@link #defaultValue()
100   * defaultValue} element to a value other than {@link #UNSET}
101   *
102   * @return whether a value for the setting must be present
103   */
104  @Nonbinding
105  boolean required() default false;
106
107
108  /*
109   * Inner and nested classes.
110   */
111
112
113  /**
114   * An {@link AnnotationLiteral} that implements the {@link Setting}
115   * interface/annotation.
116   *
117   * @author <a href="https://about.me/lairdnelson"
118   * target="_parent">Laird Nelson</a>
119   *
120   * @see Setting
121   */
122  public static final class Literal extends AnnotationLiteral<Setting> implements Setting {
123
124    private static final long serialVersionUID = 1L;
125
126    private final String name;
127
128    private final String defaultValue;
129
130    private final boolean required;
131
132    /**
133     * Creates a new {@link Literal}.
134     *
135     * @param name the value for the {@link Setting#name() name}
136     * element; may be {@code null} in which case {@link
137     * Setting#UNSET} will be used instead
138     *
139     * @param defaultValue the value for the {@link
140     * Setting#defaultValue() defaultValue} element; may be {@code
141     * null} in which case {@link Setting#UNSET} will be used instead
142     *
143     * @param required the value for the {@link Setting#required()
144     * required} element
145     */
146    public Literal(final String name, final String defaultValue, final boolean required) {
147      this.name = name == null ? UNSET : name;
148      this.defaultValue = defaultValue == null ? UNSET : defaultValue;
149      this.required = required;
150    }
151
152    /**
153     * The setting name.
154     *
155     * @return the setting name; never {@code null} but possibly {@link
156     * #UNSET}
157     */
158    @Override
159    public final String name() {
160      return this.name;
161    }
162
163    /**
164     * The default value for the setting.
165     *
166     * @return the default value; never {@code null} but possibly
167     * {@link #UNSET}
168     */
169    @Override
170    public final String defaultValue() {
171      return this.defaultValue;
172    }
173
174    /**
175     * Whether a value for the setting must be present; it is illegal
176     * to set this to {@code true} and set the {@link #defaultValue()
177     * defaultValue} element to a value other than {@link #UNSET}
178     *
179     * @return whether a value for the setting must be present
180     */
181    @Override
182    public final boolean required() {
183      return this.required;
184    }
185
186  }
187
188}