Many Java applications started from the command line take arguments to control their behavior. These arguments are available
in the string array argument passed into the application's static main() method. Typically, there are two types of arguments: options (or switches) and actual data arguments. A Java application
must process these arguments and perform two basic tasks:
Often, the code that performs these tasks is custom-made for each application and thus requires substantial effort both to
create and to maintain, especially if the requirements go beyond simple cases with only one or two options. The Options class described in this article implements a generic approach to easily handle the most complex situations. The class allows
for a simple definition of the required options and data arguments, and provides thorough syntax checks and easy access to
the results of these checks. New Java 5 features like generics and typesafe enums were also used for this project.
Over the years, I have written several Java tools that take command line arguments to control their behavior. Early on, I found it annoying to manually create and maintain the code for processing the various options. This led to the development of a prototype class to facilitate this task, but that class admittedly had its limitations since, on close inspection, the number of possible different varieties for command line arguments turned out to be significant. Eventually, I decided to develop a general solution to this problem.
In developing this solution, I had to solve two main problems:
Analysis of Problem 1 led to the following observations:
-) on Unix platforms for options like -a or a slash (/) on Windows platforms.
-a can be present or not) or take a value. An example is:java MyTool -a -b logfile.inp
:), or an equals sign (=):java MyTool -a -b logfile.inp java MyTool -a -b:logfile.inp java MyTool -a -b=logfile.inp
java -Djava.library.path=/usr/lib ...
D), the separator (=), and the option's actual value (/usr/lib), an additional parameter (java.library.path) can take on any number of values (in the above example, numerous environment properties can be specified using this syntax).
In this article, this parameter is called "detail."
java MyTool -a -b=logfile.inp data1 data2 data3 // All data at the end
or
java MyTool -a data1 data2 -b=logfile.inp data3 // Might be acceptable to an application
java MyTool -a -b datafile.inp java MyTool -k [-verbose] foo bar duh java MyTool -check -verify logfile.out
So, in devising a way to allow users to express all these varieties, I came up with the following general options form, which is used as the basis for this article:
<prefix><key>[[<detail>]<separator><value>]
This form must be combined with the multiplicity property as described above.
Within the constraints of the general form of an option described above, the Options class described in this article is designed to be the general solution for any command line processing needs that a Java
application might have.
The Options class, which is the core class for the solution described in this article, comes with two helper classes:
OptionData: This class holds all the information for one specific option
OptionSet: This class holds a set of options. Options itself can hold any number of such sets
Before describing the details of these classes, other important concepts of the Options class must be introduced.
The prefix, the separator, and the multiplicity property have been captured by enums, a feature provided for the first time by Java 5:
public enum Prefix {
DASH('-'),
SLASH('/');
private char c;
private Prefix(char c) {
this.c = c;
}
char getName() {
return c;
}
}
public enum Separator {
COLON(':'),
EQUALS('='),
BLANK(' '),
NONE('D');
private char c;
private Separator(char c) {
this.c = c;
}
char getName() {
return c;
}
}
public enum Multiplicity {
ONCE,
ONCE_OR_MORE,
ZERO_OR_ONE,
ZERO_OR_MORE;
}
Using enums has some advantages: increased type safety and tight, effortless control over the set of permissible values. Enums can also conveniently be used with genericized collections.
Note that the Prefix and Separator enums have their own constructors, allowing for the definition of an actual character representing this enum instance (versus the name used to refer to the particular enum instance). These characters can be retrieved using these enums' getName() methods, and the characters are used for the java.util.regex package's pattern syntax. This package is used to perform some of the syntax checks in the Options class, details of which will follow.
The Multiplicity enum currently supports four different values:
ONCE: The option has to occur exactly once
ONCE_OR_MORE: The option has to occur at least once
ZERO_OR_ONCE: The option can either be absent or present exactly once
ZERO_OR_MORE: The option can either be absent or present any number of times
More definitions can easily be added should the need arise.
The OptionData class is basically a data container: firstly, for the data describing the option itself, and secondly, for the actual data
found on the command line for that option. This design is already reflected in the constructor:
| Subject |
|
|
|
|
|
|
|
( 1 2 all )
|
feedbackBy Anonymous on September 12, 2009, 4:24 amthe email account under feedback are dead...
Reply | Read entire comment
Commons CLIBy Anonymous on July 10, 2009, 10:28 amCommons CLI is a much more intuitive library.
Reply | Read entire comment
Thank you very much. This is a very useful, well structured, excBy Anonymous on July 7, 2009, 11:31 amThank you very much. This is a very useful, well structured, excellently coded, good documented peace of code.
Reply | Read entire comment
Great!By mcyoung on April 1, 2009, 2:23 pmOutstanding effort. This is exactly what I was looking for, and very similar to the Ruby class I have been using. Thank you.
Reply | Read entire comment
AmazingBy Anonymous on November 1, 2008, 3:48 pmThank you so much for producing this. I'm sure that I, as well as other coders, will benefit a great deal from your work!
Reply | Read entire comment
View all comments