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}