001/*
002 * ============================================================================
003 * Copyright © 2002-2023 by Thomas Thrien.
004 * All Rights Reserved.
005 * ============================================================================
006 *
007 * Licensed to the public under the agreements of the GNU Lesser General Public
008 * License, version 3.0 (the "License"). You may obtain a copy of the License at
009 *
010 *      http://www.gnu.org/licenses/lgpl.html
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
014 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
015 * License for the specific language governing permissions and limitations
016 * under the License.
017 */
018
019package org.tquadrat.foundation.config;
020
021import static java.lang.annotation.ElementType.METHOD;
022import static java.lang.annotation.RetentionPolicy.CLASS;
023import static org.apiguardian.api.API.Status.STABLE;
024
025import java.lang.annotation.Documented;
026import java.lang.annotation.Retention;
027import java.lang.annotation.Target;
028import java.util.Collection;
029import java.util.MissingResourceException;
030import java.util.ResourceBundle;
031
032import org.apiguardian.api.API;
033import org.tquadrat.foundation.annotation.ClassVersion;
034import org.tquadrat.foundation.config.cli.CmdLineValueHandler;
035import org.tquadrat.foundation.config.cli.DateValueHandler;
036
037/**
038 *  <p>{@summary This annotation is used in the context of a configuration bean
039 *  specification to mark a property that receives the value of a command line
040 *  option.} It will be placed to the getter for the property.</p>
041 *  <p>A command line option has a name that identifies it on the command line
042 *  so that it can appear nearly everywhere in the parameter list, but of
043 *  course before all
044 *  {@linkplain Argument arguments}.</p>
045 *
046 *  @extauthor Thomas Thrien - thomas.thrien@tquadrat.org
047 *  @thanks Kohsuke Kawaguchi - kk@kohsuke.org
048 *  @thanks Mark Sinke
049 *  @version $Id: Option.java 1061 2023-09-25 16:32:43Z tquadrat $
050 *  @since 0.0.1
051 *
052 *  @UMLGraph.link
053 */
054@ClassVersion( sourceVersion = "$Id: Option.java 1061 2023-09-25 16:32:43Z tquadrat $" )
055@Documented
056@Retention( CLASS )
057@Target( METHOD )
058@API( status = STABLE, since = "0.0.1" )
059public @interface Option
060{
061        /*------------*\
062    ====** Attributes **=======================================================
063        \*------------*/
064    /**
065     *  <p>{@summary Aliases for the
066     *  {@linkplain #name() option name}.}</p>
067     *  <p>The aliases has to follow the same rules as for the option name
068     *  itself.</p>
069     *
070     *  @return The list of aliases.
071     *
072     *  @see #name()
073     */
074    String [] aliases() default {};
075
076    /**
077     *  <p>{@summary Some special value handlers (like the
078     *  {@link DateValueHandler DateValueHandler})
079     *  use this field for additional validation information, like a format
080     *  String.} It is ignored by most others.</p>
081     *  <p>Refer to the documentation of those value handlers for the exact
082     *  contents specification.</p>
083     *
084     *  @return The extended format specification according to the option
085     *      handler, or the empty String.
086     */
087    String format() default "";
088
089    /**
090     *  <p>{@summary Specifies the
091     *  {@linkplain CmdLineValueHandler command line value handler}
092     *  that translates the command line argument value to the type of the
093     *  target property and places that value to the property.}</p>
094     *  <p>The default value {@code CmdLineValueHandler.class} indicates that
095     *  the effective {@code CmdLineValueHandler} implementation will be
096     *  inferred from the type of the annotated property.</p>
097     *  <p>If it is set to a class that extends
098     *  {@link CmdLineValueHandler},
099     *  an instance of that class will be created (therefore it has to provide
100     *  a constructor with the signature
101     *  {@code &lt;<i>Constructor</i>&gt;(CLIDefinition, BiConsumer)})
102     *  that is used as the handler. This is convenient for defining a
103     *  non-standard option parsing semantics.</p>
104     *  <p><b>Example</b></p>
105     *  <pre><code>
106     *  // this is a normal &quot;-r&quot; option
107     *  &#064;Option()
108     *  boolean getFlag();
109     *
110     *  // This causes that MyHandler is used instead of the default handler
111     *  // provided for boolean
112     *  &#064;Option( handler = MyHandler.class )
113     *  boolean getYesNo();</code></pre>
114     *
115     *  @return The {@code CmdLineValueHandler} implementation.
116     */
117    Class<?>  handler() default CmdLineValueHandler.class;
118
119    /**
120     *  <p>{@summary A name for the option value that is used in messages.}</p>
121     *  <p>If left unspecified, that name is inferred from the type of the
122     *  configuration property itself.</p>
123     *
124     *  @return A meta variable string.
125     */
126    String metaVar() default "";
127
128    /**
129     *  <p>{@summary A flag that indicates whether the option is multi-valued,
130     *  for mappings to a
131     *  {@link Collection Collection}.}</p>
132     *  <p>If set to {@code true}, the same option can appear multiple times on
133     *  the command line, and each value will be added to the underlying data
134     *  structure.</p>
135     *
136     *  @return {@code true} if the option is multivalued,
137     *      {@code false} otherwise.
138     */
139    boolean multiValued() default false;
140
141    /**
142     *  <p>{@summary The name of the option.} It has to be either a single dash
143     *  (&quot;-&quot;), followed by a single character (short option), or two
144     *  dashes followed by more than one character (long option).</p>
145     *  <p>The name may contain letters, numbers, and most special characters
146     *  that are allowed on a command line, but no whitespace characters.</p>
147     *  <p>Some samples:</p>
148     *  <ul>
149     *      <li>{@code -r}</li>
150     *      <li>{@code --port}</li>
151     *      <li>{@code -1} &ndash; valid but not really recommended</li>
152     *      <li>{@code --} &ndash; invalid, but allowed on the command line,
153     *          having a special meaning there</li>
154     *      <li>{@code -} &ndash; invalid</li>
155     *      <li>{@code -name} &ndash; invalid: had to be started with two
156     *          dashes</li>
157     *      <li>{@code --f} &ndash; invalid: not enough characters after the
158     *          two dashes</li>
159     *      <li>{@code --port-number} &ndash; valid, but dashes within the name
160     *          are discouraged</li>
161     *      <li>{@code --port number} &ndash; invalid because of the blank</li>
162     *      <li>{@code --port_number}</li>
163     *      <li>{@code -@} &ndash; valid but strongly discouraged</li>
164     *  </ul>
165     *
166     *  @return The option name.
167     *
168     *  @see org.tquadrat.foundation.config.CLIBeanSpec#LEAD_IN
169     */
170    String name();
171
172    /**
173     *  <p>{@summary Specifies that the option is mandatory.} This implies that
174     *  the return type of the getter that is annotated with this annotation
175     *  may not be
176     *  {@link java.util.Optional}.</p>
177     *  <p>Note that in most of the command line interface design principles,
178     *  options should be really optional. So use caution when using this flag.
179     *  Consequently the default is {@code false}.</p>
180     *
181     *  @return {@code true} if the option is mandatory,
182     *      {@code false} otherwise.
183     */
184    boolean required() default false;
185
186    /**
187     *  <p>{@summary A help text that will be displayed in the usage output if
188     *  {@link ConfigBeanSpec#getResourceBundle() ConfigBeanSpec.getResourceBundle()}
189     *  returns no
190     *  {@link ResourceBundle ResourceBundle}
191     *  instance or the call to
192     *  {@link ResourceBundle#getString(String) getString()}
193     *  with the value of
194     *  {@link #usageKey()}
195     *  on the retrieved resources throws a
196     *  {@link MissingResourceException}.}</p>
197     *  <p>The default is the empty String.</p>
198     *
199     *  @return The usage help text.
200     */
201    String usage() default "";
202
203    /**
204     *  <p>{@summary The
205     *  {@linkplain ResourceBundle#getString(String) resource bundle key}
206     *  for a help text that will be displayed in the usage output.}</p>
207     *  <p>If not specified, the value will be derived from the name of the
208     *  property like this:</p>
209     *  <pre><code>  USAGE_&lt;<i>PropertyName</i>&gt;</code></pre>
210     *  <p>The text will be retrieved from the
211     *  {@link java.util.ResourceBundle ResourceBundle}
212     *  that is returned from
213     *  {@link org.tquadrat.foundation.config.ConfigBeanSpec#getResourceBundle() ConfigBeanSpec.getResourceBundle()};
214     *  if that is {@code null} the value of
215     *  {@link #usage()}
216     *  is taken instead.</p>
217     *  <p>This allows to localise the usage output.</p>
218     *
219     *  @return The resource bundle key for the usage text.
220     *
221     *  @see org.tquadrat.foundation.config.spi.CLIDefinition#USAGE_KEY_FORMAT
222     */
223    String usageKey() default "";
224}
225//  annotation Option
226
227/*
228 *  End of File
229 */