Wednesday, June 28, 2017

Java Command-Line Interfaces (Part 4): Commandline

This fourth part of my series on command-line parsing in Java features Commandline, which is described as "a Java library to parse command line arguments" that "is based on a mapping from the command line arguments onto objects, by using annotations."

Like previously covered args4j and jbock, Commandline employs annotations to provide the "definition" of potential command-line options. However, while args4j does this via annotations on class fields and jbock does this via annotations on the constructor and its parameters, Commandline uses annotations on "set" (mutator) methods. In this post, I use a Main class example as in the previous posts on Java-based command-line processing, but in normal situations, I'd typically prefer to have a special class representing command-line arguments.

The following code listing demonstrates use of Commandline annotations on "get" methods to implement the "definition" stage of Commandline's command-line processing.

Commandline "Definition" Stage of Command-line Processing

public class Main
   /** Is verbosity enabled? */
   private boolean verbose;

   /** Name/path of applicable file. */
   private String fileName;

   public void setVerbose(final boolean newVerbose)
      verbose = newVerbose;

   public void setFileName(final String newFileName)
      fileName = newFileName;

The code listing above shows the use of Commandline annotation @Option along with other annotations that customize the defined option (@ShortSwitch and @LongSwitch for short and long arguments, @Required for mandatory arguments, @SingleArgument to specify one argument associated with switch, and @Toggle to indicate that the presence or absence of the switch is what's significant [no argument associated with that switch]).

The next code listing demonstrates the "parsing" and "interrogation" stages of command-line parsing with Commandline.

"Parsing" and "Interrogating" with Commandline

   // "Parsing" stage.
   final Main main = CommandLineParser.parse(
      Main.class, arguments, OptionStyle.LONG_OR_COMPACT);

   // "Interrogation" stage.
   out.println("You provided file name of '" + main.fileName
      + "' and verbose is set to '" + main.verbose + "'.");
catch (IllegalAccessException | InstantiationException | InvocationTargetException exception)
   out.println("ERROR: Unable to parse command-line arguments: " + exception);

The last code example demonstrates that parsing is accomplished with the single CommandLineParser.parse(Class<T>, String[], OptionStyle) call and interrogation is as simple as accessing the members of the instance returned by that method. The third argument provided to the parse method is significant because it instructs the parser how to expect the switches to be presented.

The code example just shown uses OptionStyle.LONG_OR_COMPACT, which the documentation describes: "Long switches are prepended by two dashes. Short switches are prepended with a single dash, and may be concatenated into one switch." In contrast, OptionStyle.SIMPLE instructs the parser to expect "All switches have to be standalone" and "all (both long and short) needs to be prepended with a single dash on the command line."

The next screen snapshot demonstrates this simple application in action.

When a required argument is not provided, a message (including stack trace) like that shown in the next screen snapshot is presented.

I don't include an example of using help or usage based on Commandline here because, as the project's GitHub page states, "Generating a help text" is "functionality that is currently not supported." The complete code listing for the class used in this post to demonstrate use of Commandline is available on GitHub.

Here are some additional characteristics of Commandline to consider when selecting a library to help with command-line parsing in Java.

Commandline is another of the plethora of open source command-line processing libraries available to Java developers and, like several of the others, uses annotations to do most of the heavy lifting.

Additional References

No comments: