Monday, October 9, 2017

Java Command-Line Interfaces (Part 21): Airline 2

The focus of this twenty-first post in this series on parsing command-line arguments in Java is on the Airline 2 library. The GitHub project page for Airline 2 describes the library, "Airline is a Java library providing an annotation-based framework for parsing command line interfaces." The page goes onto state that Airline "supports both simple single commands through to complex git style interfaces with groups." The page also defines Airline 2's relationship with the original Airline library: "This is a substantially rewritten fork of the original airline library." It is specifically Airline 2.3.0 that is featured in this post.

The examples in this post will be similar to those demonstrated in earlier posts in this series on alternative libraries for parsing command line arguments from Java. As such, the options supported in these examples will be specification of a file's path and name and specification of whether or not verbosity should be enabled. The full code listing for the examples shown here is available on GitHub.

The "definition" stage of parsing command-line arguments from Java with Airline 2 is easily accomplished using @Option annotations as shown in the next code listing.

"Definition" Stage with Airline 2

@Option(title="file", name={"-f", "--file"}, description="Path and name of file.")
private String file;

@Option(title="verbose", name={"-v", "--verbose"}, description="Enable or disable verbosity.")
private boolean verbose;

The code for these instances of @Option annotations is fairly self-explanatory. The "name" element of the @Option annotation expects one or more Strings and thus allows multiple flags to be specified for the same option. In this case, I used the same single-hyphen/single-character "short" form and double hyphen/word "long" forms for the options.

The "parsing" stage can be accomplished with Airline 2 using the SingleCommand class and its static singleCommand(Class<C>) method to acquire an instance of SingleCommand and then invoking the parse(String[]) method on that instance. These two statements are demonstrated in the next code listing.

"Parsing" Stage with Airline 2

final SingleCommand<Main> parser = SingleCommand.singleCommand(Main.class);
final Main main = parser.parse(arguments);

The "interrogation" stage in Airline 2 is accomplished by simply accessing the @Option-annotated fields of the instance provided by the SingleCommand.parse(String[]) method. This is demonstrated in the next code listing.

"Interrogation" Stage with Airline 2

if (main.file != null)
{
   out.println("File path/name is '" + main.file + "'.");
   out.println("Verbosity is " + main.verbose);
}
else
{
   out.println("ERROR: File path/name must be provided with -f or --file.");
}

The next two screen snapshots show the examples in action. The first screen snapshot shows the output when no arguments are provided and the second image shows "normal" use of the long and short versions of the two options for specifying file path/name and verbosity.

Airline comes with support for generating usage and help information. Unfortunately, I was not able to get it to work for me because I ran into a compilation error that stated, "class file for com.github.rvesse.airline.io.printers.UsagePrinter not found." I don't see that class in the airline-2.3.0.jar I downloaded.

There are characteristics of Airline 2 to consider when selecting a framework or library to help with command-line parsing in Java.

  • Airline 2 is open source and licensed under the Apache License, Version 2.0.
  • Airline 2 is one of the "weightier" libraries covered in this series with the airline-2.3.0.jar being approximately 316 KB in size and having runtime dependencies on Apache Commons Collections, Apache Commons Lang, and javax.inject/javax.inject.
  • Although Airline has been around for a while, Airline 2 is a more recently updated fork of that project.
  • The documentation for basic use of Airline 2 is straightforward and useful, but documentation for many of the features not shown in this post is still under construction with numerous "TODO" statements.

Airline 2 is easy to use for the "single command" style of arguments processing implemented in my examples in these posts. I did not see any method for expressing whether an option is required, but simply checking for null for a required option before proceeding is an easy approach for this. Given its size and dependencies, Airline 2 is probably best suited for those looking to use many of its powerful features not demonstrated in this post. For the simple examples demonstrated in this post and in the other posts in this series, there are lighter libraries with fewer dependencies that work very similarly to Airline 2 in terms of expressing "definition", "parsing", and "interrogation" stages.

Additional References

No comments: