Original Answer
The picocli user manual has a detailed section on assigning default values in argument groups.
Applications need to do both of the below:
- specify default values in both the
@Option
annotation, and in the initial value of the @Option
-annotated field. (Yes, that means some duplication.)
- manually instantiate the
@ArgGroup
-annotated field
For your example, that means:
@Command
public class CMD implements Runnable {
@Parameters
private String x;
@ArgGroup(exclusive = false)
private Group group = new Group();
static class Group {
@Option(names = "-a", required = true, defaultValue = "aa")
public static String a = "aa";
@Option(names = "-b", required = true, defaultValue = "bb")
public static String b = "bb";
@Option(names = "-c", required = false, defaultValue = "cc")
public static String c = "cc";
}
Update (Answer #2)
@kienbui pointed out that I missed these requirements:
(...) if -a
is specified, then -b
becomes mandatory (user input becomes required), and similarly if -b
is specified, then -a
becomes mandatory. Otherwise, if neither -a
nor -b
is specified, none of the options are required and default values are assigned to the options that are not specified by the end user.
This can be achieved by making a separate inner arg-group for just options -a
and -b
, and removing the default values from the option declarations, but initializing them with their default values.
For example:
@Command
static class CMD implements Runnable {
@Parameters
private String x;
@ArgGroup(exclusive = false)
private Group group = new Group();
static class Group {
@ArgGroup(exclusive = false)
private InnerGroup inner = new InnerGroup("aa", "bb"); // default values
@Option(names = "-c", required = false, defaultValue = "cc")
public String c = "cc";
}
static class InnerGroup {
// default constructor, used by picocli when
// one or more options in this group are
// matched on the command line
public InnerGroup() {}
// this constructor assigns default values,
// used only when *both* options are missing
public InnerGroup(String a, String b) {
this.a = a;
this.b = b;
}
@Option(names = "-a", required = true)
public String a;
@Option(names = "-b", required = true)
public String b;
}
@Override
public void run() {
System.out.printf("a=%s, b=%s, c=%s, x=%s%n",
group.inner.a, group.inner.b, group.c, x);
}
}