'arggroup with default value in picocli

Write cmd interface with Java code used picocli v4.6.3

My case: ./cmd [-a -b [-c]]

user put a,b option or got default value example:

  • user only put: ./cmd x1

    a,b,c option got default value

  • ./cmd x1 -a=a1

    request input b option and vice versa (c option still get default value)

  • ./cmd x1 -c=c1

    a & b option get default value

@Command
public class CMD implements Runnable {

    @Parameters
    private String x;

    
    @ArgGroup(exclusive = false)
    private Group group;

    static class Group {
        @Option(names = "-a", required = true, defaultValue = "aa")
        public static String a;

        @Option(names = "-b", required = true, defaultValue = "bb")
        public static String b;

        @Option(names = "-c", required = false, defaultValue = "cc")
        public static String c;
    }

But it didn't work as I wanted I didn't have the solution



Solution 1:[1]

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);
    }
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1