Injection of values from the command-line directly into your class attributes is not only the easiest way to use Argument but it also decouples the application code from knowing anything about the command-line.
As covered in the [Retrieval of Values] article you can always directly reference the arguments and obtain their values. And then you can write code to "push" these values into class attributes so that your code can make use of them. But that is not the recommended approach.
All examples that follow will assume that the user of MyProgram entered the command-line like this.
> MyProgram -a value1
Notice the use the shortest version of unrelated keywords in the examples. That way the focus can remain on the ones associated with this topic. -tS
is the shortest way of entering --type String
. -ka is the shortest way of entering --key a
.
Starting with the retrieval way and then modifying it to be the injection technique.
// in the main method ICmdLine argument = CmdLine.create("-tS -ka").parse(commandLineArgs); String myArgValue = (String) argument.arg("-a").getValue(); System.out.println(myArgValue);
With injection of values we don't need to hang on to the Argument
instance so we don't assign it to a variable. We have defined a public class attribute called myArgValue
that will be the target of the -a
argument. This is because we have used the --variable
parameter when defining the parser. Argument will look for the variable and push the value of the argument into it during the parse
call.
// class attribute public String myArgValue; // in the main method CmdLine.create("-tS -ka --variable myArgValue").parse(this, commandLineArgs); System.out.println(myArgValue);
It is important to match up the argument --type
parameter and the type of the variable. --type String
will need a String variable, --type Integer
can make use of the primitive int
or the class Integer
as the variable type. An example of --type Integer
. Notice the very shortened version of the --variable
parameter (-v
).
// class attribute public int myArgValue; // in the main method CmdLine.create("-tI -ka -v myArgValue").parse(this, commandLineArgs); System.out.println(myArgValue);
--multiple
values in an ArrayThis example shows -a
as a multiple value argument. In Java, one way to store that in a variable is to use an array. Here, -a
is a String
type so we will store the values in a String[]
. Argument will create the String[]
before adding the values to it. You don't need to initialize the variable in any way.
// class attribute public String[] myArgValues; // in the main method CmdLine.create("-tS -ka --multiple 1 -v myArgValues").parse(this, commandLineArgs); for (String value : myArgValues) System.out.println(value);
--multiple
values in a ListThis example shows -a
as a multiple value argument. In Java, one way to store that in a variable is to use a List. Here, -a
is a String
type so we will store the values in a List<String>
. Argument will create the List<String> as an ArrayList<String>
before adding the values to it. You don't need to initialize the variable in any way.
// class attribute public List<String> myArgValues; // in the main method CmdLine.create("-tS -ka --multiple 1 -v myArgValues").parse(this, commandLineArgs); for (String value : myArgValues) System.out.println(value);
--class
to override what Argument will make--class
is needed if Argument can not determine the type from the variable (--var
) itself or you need to provide a different class due to the variable type not being a concrete class, or it uses generics. Argument will by default attempt to create instances for the --type
of argument you have defined. In some cases this may produce errors that indicate you need to use --class
.
--class
is only valid for embedded parsers (--begin
arguments). It is mutually exclusive with the --factoryM
and --factoryA
parameters.
These examples use a second class called MyGroup. It is created for the embedded parser and used when loading the embedded parsers argument.
This is to show that --class
is not usually needed. The type that Argument creates for myGroup
is inferred from its type definition.
static public class MyGroup { public String testString1; public String testString2; } static public class MyProgram { // class attribute public MyGroup myGroup; // in the main method CmdLine.create( "-tBegin -ka -v myGroup", "-tString -k t1 -p --var testString1", "-tString -k t2 -p --var testString2", "-tEnd -ka" ).parse(this, commandLineArgs); System.out.println(myGroup.testString1); System.out.println(myGroup.testString2);
Usage:
Input:
MyProgram -a ('Little' 'Gray Cloud')
Little
Gray Cloud
--class
is needed for this example. The target variable (myGroup) is defined this time as a superclass (Object). And we want to create the proper instance (MyGroup).
static public class MyGroup { public String testString1; public String testString2; } static public class MyProgram { // class attribute public Object myGroup; // in the main method CmdLine.create( "-tBegin -ka -v myGroup --class " + MyGroup.class.getName(), "-tString -k t1 -p --var testString1", "-tString -k t2 -p --var testString2", "-tEnd -ka" ).parse(this, commandLineArgs); System.out.println(((MyGroup)myGroup).testString1); System.out.println(((MyGroup)myGroup).testString2);
This is the fun part. And probably the most useful for complex command lines. It enables you to use polymorphism when populating multi-value arguments (--multiple
) based on the information from the command-line. Unlike --class
, --factoryMethod
can be used on --type begin
and --type String
arguments.
--type String
argumentsIn this example we have two subclasses of the AbstractColor class. Argument will call the factory method create to get the proper instance. The (String) value that the user enters is passed to the factory method and the proper instance is returned to Argument.
static abstract public class AbstractColor { static public AbstractColor create(String name) { if ("red".equals(name)) return new RedColor(); if ("blue".equals(name)) return new BlueColor(); return null; } } static public class RedColor extends AbstractColor { } static public class BlueColor extends AbstractColor { } static public class MyProgram { // class attribute public AbstractColor color; // in the main method CmdLine.create( "-tString -kcolor --var color --factoryMethod AbstractColor.create --list red blue" ).parse(this, commandLineArgs); System.out.println(color.getClass().getName());
Input:
MyProgram --color red
RedColor
--type String
arguments with --multiple
valuesThis also is a good technique for --multiple
valued arguments.
static abstract public class AbstractColor { static public AbstractColor create(String name) { if ("red".equals(name)) return new RedColor(); if ("blue".equals(name)) return new BlueColor(); return null; } } static public class RedColor extends AbstractColor { } static public class BlueColor extends AbstractColor { } static public class MyProgram { // class attribute public AbstractColor[] color; // in the main method CmdLine.create( "-tString -kcolor --var color --factoryMethod AbstractColor.create --list red blue -m1" ).parse(this, commandLineArgs); for (AbstractColor col : color) System.out.println(col.getClass().getName());
Input:
MyProgram --color red blue red
RedColor
BlueColor
RedColor
--type Begin
arguments (requires --factoryArgName
)Since they are so similar we will just go right to a --multiple
valued embedded argument. The new to be away of is the --factoryArgName used to help create the instances. The --factoryArgName specifies which of the arguments in the embedded parse will be used when calling the --factoryMethod.
To show the power of --begin we have added a new variable to the AbstractColor class called intensity.
static abstract public class AbstractColor { static public AbstractColor create(String name) { if ("red".equals(name)) return new RedColor(); if ("blue".equals(name)) return new BlueColor(); return null; } public int intensity; } static public class RedColor extends AbstractColor { } static public class BlueColor extends AbstractColor { } static public class MyProgram { // class attribute public AbstractColor[] color; // in the main method CmdLine.create( "tBegin -k color --var color --factoryMethod AbstractColor.create --factoryArgName '--name' -m1", " -tString -kname -p --list red blue", " -tInteger -kintensity -p --var intensity --range 0 255", "-tEnd -k color" ).parse(this, commandLineArgs); for (AbstractColor col : color) System.out.println(col.getClass().getName() + " " + col.intensity);
Input:
MyProgram --color (red 85) (blue 190) (red 13)
RedColor 85
BlueColor 190
RedColor 13