Annotation based option specification
-------------------------------------
Key: CLI-196
URL: https://issues.apache.org/jira/browse/CLI-196
Project: Commons CLI
Issue Type: New Feature
Components: CLI-1.x
Reporter: Kevin Holloway
Priority: Minor
This is a proposal for an alternative way of specifying command line options,
using annotations. It's implementation wraps Commons CLI code and uses
reflection.
>From a user perspective, the following is a example of a mythical program that
>takes three arguments:
-utc, reports the date in terms of UTC.
-offset <integer>, adds an offset to the reference date.
-reference <amount>, the reference amount (whatever that is).
The Java code for the options is as follows:
{code}
public class XyzOptions {
private boolean utc;
private int offset;
private BigDecimal reference;
@Option (name="utc", description="Reports the date in terms of UTC")
void setUTC (boolean utc) {
this.utc = utc;
}
@Option (name="offset", description="Adds an offset to the reference date")
void setOffset (int offset) {
this.offset = offset;
}
@Option (name="reference", required=true, description="The reference amount")
void setReferenceAmount (BigDecimal amount) {
this.reference = amount;
}
// get methods omitted
}
{code}
@Option is an annotation that provides CLI option details. The @Option
annotates set methods of the options class.
The Java code that uses these options is as follows:
{code}
public static void main (String[] args) {
XyzOptions options = CommandLine.parse(args, XyzOptions.class, "dateCommand");
// the program options can then be accessed using get methods or field access
on the options object.
}
{code}
The "CommandLine" class is the class that builds the CLI Options instance using
the @Option annotations and reflection.
The @Option annotation allows the following to be specified:
* name. The short name of the option.
* longForm. The long form of the option.
* description. The description of the option. This is the description that
appears in the help text.
* required. true if this option is required. This defaults to false, meaning
the option is optional.
* argOptional. true if the option argument is optional. This defaults to
false, meaning the option argument is mandatory.
The remaining information is obtained by reflection on the set method parameter.
* If the set method parameter is boolean or Boolean, the option is assumed to
take no argument. It is a simple switch.
* If the set method parameter takes any other type, the option is assumed to
take an argument of that type.
** If the parameter type is String, the option argument is used as-is.
** If the parameter type is a primitive type (or the class equivalent), the
option argument is converted to that type and passed to the set method.
** If the parameter type is something else (such as BigDecimal), the command
line parser looks for a class constructor that takes a String argument. If
this is found, and instance of the object is created an passed to the set
method. Any class that has a constructor that takes a single String argument
can be used.
Option arguments can be validated in the set methods. For example, if a File
needs to be a directory, the set method could be as follows:
{code}
@Option (name="dir", description="The output directory")
void setOutputDir (File file) {
if (!file.isDirectory()) {
throw new IllegalArgumentException ("'dir' option must specify a
directory");
}
this.file = file;
}
{code}
The code for what is described here is available if anyone wants it.
This is the idea. There are some issues to resolve, but the first question is:
does anyone think it worth pursuing this?
--
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.