package org.kohsuke.args4j;
import org.kohsuke.args4j.spi.OptionHandler;
import org.kohsuke.args4j.spi.Setter;
import java.io.File;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import java.lang.reflect.AccessibleObject;
import java.util.ResourceBundle;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
/**
* Marks a field/setter that receives a command line switch value.
*
* <p>
* This annotation can be placed on a field of type T or the method
* of the form <code>void <i><code>methodName</code></i>(T value)</code>. Its access
* modified can be anything, but if it's not public, your application
* needs to run in a security context that allows args4j to access
* the field/method (see {@link AccessibleObject#setAccessible(boolean)}.
*
* <p>
* The behavior of the annotation differs depending on T --- the type
* of the field or the parameter of the method.
*
* <h2>Boolean Switch</h2>
* <p>
* When <var>T</var> is {@code boolean} , it represents
* a {@code boolean} option that takes the form of <code>-OPT</code>. When this option is set,
* the property will be set to {@code true}.
*
* <h2>String Switch</h2>
* <p>
* When <var>T</var> is {@link String}, it represents
* an option that takes one operand. The value of the operand is set
* to the property.
*
* <h2>Enum Switch</h2>
* <p>
* When <var>T</var> is derived from {@link Enum}, it represents an option that takes
* an operand, which must be one of the enum constant. The comparion between
* the operand and the enum constant name is done in a case insensitive fashion.
* <p>
* For example, the following definition will represent command line options
* like <code>-coin penny</code> or <code>-coin DIME</code>,
* but things like <code>-coin</code> or <code>-coin abc</code> are errors.
*
* <pre>
* enum Coin { PENNY,NICKEL,DIME,QUARTER }
*
* class Option {
* @Option(name="-coin")
* public Coin coin;
* }
* </pre>
*
* <h2>File Switch</h2>
* <p>
* When <var>T</var> is a {@link File}, it represents an option that takes a file/directory
* name as an operand.
*
* @author Kohsuke Kawaguchi
*/
@Retention(RUNTIME)
@Target({FIELD,METHOD,PARAMETER})
public @interface Option {
/**
* Name of the option, such as <code>-foo</code> or <code>-bar</code>.
*/
String name();
/**
* Aliases for the options, such as <code>--long-option-name</code>.
*/
String[] aliases() default { };
/**
* Help string used to display the usage screen.
*
* <p>
* This parameter works in two ways. For a simple use,
* you can just encode the human-readable help string directly,
* and that will be used as the message. This is easier,
* but it doesn't support localization.
*
* <p>
* For more advanced use, this property is set to a key of a
* {@link ResourceBundle}. The actual message is obtained
* by querying a {@link ResourceBundle} instance supplied to
* {@link CmdLineParser} by this key. This allows the usage
* screen to be properly localized.
*
* <p>
* If this value is empty, the option will not be displayed
* in the usage screen.
*/
String usage() default "";
/**
* When the option takes an operand, the usage screen will show something like this
*
* <pre>
* -x FOO : blah blah blah
* </pre>
*
* You can replace the <code>FOO</code> token by using this parameter.
*
* <p>
* If left unspecified, this value is infered from the type of the option.
*
* <p>
* Just like {@link #usage()}, normally, this value is printed as is.
* But if a {@link ResourceBundle} is given to the {@link CmdLineParser},
* it will be used to obtain the locale-specific value.
*/
String metaVar() default "";
/**
* Specify that the option is mandatory.
*
* <p>
* At the end of {@link CmdLineParser#parseArgument(String...)},
* a {@link CmdLineException} will be thrown if a required option
* is not present.
*
* <p>
* Note that in most of the command line interface design principles,
* options should be really optional. So use caution when using this
* flag.
*/
boolean required() default false;
/**
* Specify that the option is a help option.
*
* <p>
* When flagging an option being the help option, required
* arguments or options that are missing in an actual command
* line don't cause an exception to be thrown.
* @see #required()
*/
boolean help() default false;
/**
* Specify that the option is hidden from the usage, by default.
*
* <p>
* You can still have {@link CmdLineParser} show hidden options
* by using {@link OptionHandlerFilter#ALL}, which allows you to
* create an option that shows hidden options.
*
* <p>
* If you need more complicated filtering logic, define your own
* annotations and check them in {@link Setter#asAnnotatedElement()}.
*
* @see OptionHandlerFilter#PUBLIC
*/
boolean hidden() default false;
/**
* Specify the {@link OptionHandler} that processes the command line arguments.
*
* <p>
* The default value {@link OptionHandler} indicates that
* the {@link OptionHandler} will be infered from
* the type of the field/method where a {@link Option} annotation
* is placed.
*
* <p>
* If this annotation element is used, it overrides the inference
* and determines the handler to be used. This is convenient for
* defining a non-standard option parsing semantics.
*
* <h3>Example</h3>
*
* <pre>
* // this is a normal "-r" option
* @Option(name="-r")
* boolean value;
*
* // this causes arg4j to use MyHandler, not the default
* // handler provided for boolean
* @Option(name="-b",handler=MyHandler.class)
* boolean value;
* </pre>
*/
Class<? extends OptionHandler> handler() default OptionHandler.class;
/**
* List of other options that this option depends on.
*
* <h3>Example</h3>
*
* <pre>
* @Option(name="-a")
* int a;
* //-b is not required but if it's provided, then a becomes required
* @Option(name="-b", depends={"-a"}
* int b;
* </pre>
*
* <p>
* At the end of {@link CmdLineParser#parseArgument(String...)},
* a {@link CmdLineException} will be thrown if options required by another one
* are not present.
* </p>
*/
String[] depends() default { };
/**
* List of other options that this option is incompatible with..
*
* <h3>Example</h3>
*
* <pre>
* @Option(name="-a")
* int a;
* // -h and -a cannot be specified together
* @Option(name="-h", forbids={"-a"}
* boolean h;
* </pre>
*
* <p>
* At the end of {@link CmdLineParser#parseArgument(String...)},
* a {@link CmdLineException} will be thrown if forbidden option
* combinations are present.
* </p>
*/
String[] forbids() default { };
boolean multiValued() default false;
}