Saturday, September 23, 2017

Java Command-Line Interfaces (Part 16): JArgp

The Java-based command line argument processing library covered in this post was the featured library of an IBM developerWorks article Java programming dynamics, Part 3, Applied reflection (this 2003 article was "archived" in 2016, but is still available for PDF download). The library, called JArgp (Java Command Line Argument Processing Library), is defined on its main web page as "a library for processing command line arguments in Java." This page adds, "Unlike most other libraries of this type, JArgp uses reflection to store actual values directly to fields in the target application object." JArgp 1.0 is featured in this post.

JArgp is a minimalistic library as shown by the small number of classes in the JArgp JAR.

The "definition" stage is accomplished in JArgp via specification of an array of ParameterDef instances. Custom classes can be written to extend the ParameterDef class, but I'll be able to use two provided extensions of this class (StringDef and BoolDef) to implement the file path/name and verbosity arguments implemented in earlier posts in this series. This is exemplified in the next code listing (full code will be made available on GitHub).

"Definition" Stage with JArgp

private static final ParameterDef[] PARAMETERS_DEFINITIONS =
{
   new StringDef('f', "file", "File path and name"),
   new BoolDef('v', "verbose", "Verbosity level")
};

The initial argument to the constructors of the ParameterDef-extending classes StringDef and BoolDef is the single character that will be the command-line flag. In this case, the defined command-line argument flags will be "-f" for file path/name and "-v" for verbosity. The second argument of each constructor is the name of the class's field that any values associated with the command line flags will be written to. The third argument to each constructor is a description of that command line argument flag. As far as I can tell, there's no way to specify "long" argument names (no ability to specify --file or --verbose in this case).

The "parsing" stage is accomplished in JArgp with invocation of the static ArgumentProcessor method processArgs(String[], ParameterDef[], Object). This is exemplified in the next code listing.

"Parsing" in JArgp

final Main instance = new Main();
// The integer returned by the next invocation is actually the
// zero-based index of next argument to be processed
final int numberArgumentsProcessed
   = ArgumentProcessor.processArgs(
arguments, PARAMETERS_DEFINITIONS, instance);

The "interrogation" stage with JArgp is implemented by accessing the fields in the instance that have names matching those provided in the parameter definitions. This is shown in the next code listing.

"Interrogation" Stage in JArgp

out.println(
     "File path/name is " + instance.file
   + " and verbosity is " + instance.verbose);

Use of the code shown so far is demonstrated in the next screen snapshot.

If I wanted to apply the descriptions I provided to the command line flags when defining them, I could have used the instance method approach for parsing rather than the static function approach showed earlier. This is demonstrated in the next code listing.

final Main instance = new Main();
final ArgumentProcessor argumentProcessor
   = new ArgumentProcessor(PARAMETERS_DEFINITIONS);
argumentProcessor.processArgs(arguments, instance);
argumentProcessor.listParameters(50, out);

The last line in the previous code listing demonstrates how the ArgumentProcessor.listParameters(int, PrintStream) method can be used to write the flags and their descriptions to output. This output is demonstrated in the next screen snapshot.

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

JArgp is a minimalistic library for processing command line arguments in Java. It doesn't support "long" argument names by default and doesn't support as many features as some of the other libraries covered in this series, but it is small and easy to use. I primarily included it in this series because of its background tied to the IBM DeveloperWorks article.

Additional Resources

No comments: