3

I have an option like so

    @CommandLine.Option(names = "-D", description = "Define a symbol.")
    /* A list of defines provided by the user. */
    Map<String, String> defines = new LinkedHashMap<String, String>();

This does work when I do the following:

-Dkey=value

however when I do this

-Dkey

it does not work. Is there a way to add in a default value for keys which do not have a value associated with them?

Har
  • 3,727
  • 10
  • 41
  • 75

1 Answers1

3

Update: from picocli 4.6, this can be accomplished by specifying a mapFallbackValue in the option or positional parameter.

@Option(names = {"-P", "--properties"}, mapFallbackValue = Option.NULL_VALUE)
Map<String, Optional<Integer>> properties;

@Parameters(mapFallbackValue= "INFO", description= "... ${MAP-FALLBACK-VALUE} ...")
Map<Class<?>, LogLevel> logLevels;

The value type may be wrapped in a java.util.Optional. (If it isn't, and the fallback value is Option.NULL_VALUE, picocli will put the value null in the map for the specified key.)


(Original answer follows below):

This can be accomplished with a custom parameterConsumer. For example:

/* A list of defines provided by the user. */
@Option(names = "-D", parameterConsumer = MyMapParameterConsumer.class,
  description = "Define a symbol.")
Map<String, String> defines = new LinkedHashMap<String, String>();

... where MyMapParameterConsumer can look something like this:


class MyMapParameterConsumer implements IParameterConsumer {
    @Override
    public void consumeParameters(
            Stack<String> args, 
            ArgSpec argSpec, 
            CommandSpec commandSpec) {

        if (args.isEmpty()) {
            throw new ParameterException(commandSpec.commandLine(), 
                    "Missing required parameter");
        }
        String parameter = args.pop();
        String[] keyValue = parameter.split("=", 1);
        String key = keyValue[0];
        String value = keyValue.length > 1 
                ? keyValue[1]
                : "MY_DEFAULT";
        Map<String, String> map = argSpec.getValue();
        map.put(key, value);
    }
}
Remko Popma
  • 35,130
  • 11
  • 92
  • 114
  • I don't understand the args does that mean the total arguments rather than an argument for the -Dkey=value pair? – Har Nov 01 '19 at 14:21
  • When the `consumeParameters` method is called, the `-D` option has already been consumed, but its parameter(s) are still on the stack. When the parameter was attached to the option (as in `-Dkey=value`, the parser will have detached the parameter and pushed it back on the stack. So the `key=value` parameter should be at the top of the stack, followed by the remaining command line arguments. – Remko Popma Nov 01 '19 at 15:02