private void consumeOneMapArgument(ArgSpec argSpec, LookBehind lookBehind, Range arity, int consumed, String arg, Class<?>[] classes, ITypeConverter<?> keyConverter, ITypeConverter<?> valueConverter, Map<Object, Object> result, int index, String argDescription) { if (!lookBehind.isAttached()) { parseResult.nowProcessing(argSpec, arg); } String raw = trim(arg); String[] values = argSpec.splitValue(raw, commandSpec.parser(), arity, consumed); for (String value : values) { String[] keyValue = splitKeyValue(argSpec, value); Object mapKey = tryConvert(argSpec, index, keyConverter, keyValue[0], classes[0]); Object mapValue = tryConvert(argSpec, index, valueConverter, keyValue[1], classes[1]); result.put(mapKey, mapValue); if (tracer.isInfo()) { tracer.info("Putting [%s : %s] in %s<%s, %s> %s for %s%n", String.valueOf(mapKey), String.valueOf(mapValue), result.getClass().getSimpleName(), classes[0].getSimpleName(), classes[1].getSimpleName(), argSpec.toString(), argDescription); } parseResult.addStringValue(argSpec, keyValue[0]); parseResult.addStringValue(argSpec, keyValue[1]); } parseResult.addOriginalStringValue(argSpec, raw); }
private int applyValuesToMapField(ArgSpec argSpec, LookBehind lookBehind, Range arity, Stack<String> args, Set<ArgSpec> initialized, String argDescription) throws Exception { Class<?>[] classes = argSpec.auxiliaryTypes(); if (classes.length < 2) { throw new ParameterException(CommandLine.this, argSpec.toString() + " needs two types (one for the map key, one for the value) but only has " + classes.length + " types configured.",argSpec, null); } ITypeConverter<?> keyConverter = getTypeConverter(classes[0], argSpec, 0); ITypeConverter<?> valueConverter = getTypeConverter(classes[1], argSpec, 1); @SuppressWarnings("unchecked") Map<Object, Object> map = (Map<Object, Object>) argSpec.getValue(); if (map == null || (!map.isEmpty() && !initialized.contains(argSpec))) { tracer.debug("Initializing binding for %s with empty %s%n", optionDescription("", argSpec, 0), argSpec.type().getSimpleName()); map = createMap(argSpec.type()); // map class argSpec.setValue(map); } initialized.add(argSpec); int originalSize = map.size(); consumeMapArguments(argSpec, lookBehind, arity, args, classes, keyConverter, valueConverter, map, argDescription); parseResult.add(argSpec, position); argSpec.setValue(map); return map.size() - originalSize; }
private int consumeOneArgument(ArgSpec argSpec, LookBehind lookBehind, Range arity, int consumed, String arg, Class<?> type, List<Object> result, int index, String argDescription) { if (!lookBehind.isAttached()) { parseResult.nowProcessing(argSpec, arg); } String raw = trim(arg); String[] values = argSpec.splitValue(raw, commandSpec.parser(), arity, consumed); ITypeConverter<?> converter = getTypeConverter(type, argSpec, 0); for (int j = 0; j < values.length; j++) { result.add(tryConvert(argSpec, index, converter, values[j], type)); if (tracer.isInfo()) { tracer.info("Adding [%s] to %s for %s%n", String.valueOf(result.get(result.size() - 1)), argSpec.toString(), argDescription); } parseResult.addStringValue(argSpec, values[j]); } parseResult.addOriginalStringValue(argSpec, raw); return ++index; } private boolean canConsumeOneArgument(ArgSpec argSpec, Range arity, int consumed, String arg, Class<?> type, String argDescription) {
@Test public void testArrayOptionWithoutArityConsumesOneArgument() { // #192 class OptionsNoArityAndParameters { @Parameters char[] charParams; @Option(names = "-chars") char[] charOptions; } OptionsNoArityAndParameters params = CommandLine.populateCommand(new OptionsNoArityAndParameters(), "-chars a b c d".split(" ")); assertArrayEquals(Arrays.toString(params.charOptions), new char[] {'a', }, params.charOptions); assertArrayEquals(Arrays.toString(params.charParams), new char[] {'b', 'c', 'd'}, params.charParams); // repeated occurrence params = CommandLine.populateCommand(new OptionsNoArityAndParameters(), "-chars a -chars b c d".split(" ")); assertArrayEquals(Arrays.toString(params.charOptions), new char[] {'a', 'b', }, params.charOptions); assertArrayEquals(Arrays.toString(params.charParams), new char[] {'c', 'd'}, params.charParams); try { CommandLine.populateCommand(new OptionsNoArityAndParameters(), "-chars".split(" ")); fail("expected MissingParameterException"); } catch (MissingParameterException ok) { assertEquals("Missing required parameter for option '-chars' (<charOptions>)", ok.getMessage()); assertEquals(1, ok.getMissing().size()); assertTrue(ok.getMissing().get(0).toString(), ok.getMissing().get(0) instanceof Model.OptionSpec); } }
private void consumeOneMapArgument(ArgSpec argSpec, LookBehind lookBehind, Range arity, int consumed, String arg, Class<?>[] classes, ITypeConverter<?> keyConverter, ITypeConverter<?> valueConverter, Map<Object, Object> result, int index, String argDescription) { if (!lookBehind.isAttached()) { parseResult.nowProcessing(argSpec, arg); } String raw = trim(arg); String[] values = argSpec.splitValue(raw, commandSpec.parser(), arity, consumed); for (String value : values) { String[] keyValue = splitKeyValue(argSpec, value); Object mapKey = tryConvert(argSpec, index, keyConverter, keyValue[0], classes[0]); Object mapValue = tryConvert(argSpec, index, valueConverter, keyValue[1], classes[1]); result.put(mapKey, mapValue); if (tracer.isInfo()) { tracer.info("Putting [%s : %s] in %s<%s, %s> %s for %s%n", String.valueOf(mapKey), String.valueOf(mapValue), result.getClass().getSimpleName(), classes[0].getSimpleName(), classes[1].getSimpleName(), argSpec.toString(), argDescription); } parseResult.addStringValue(argSpec, keyValue[0]); parseResult.addStringValue(argSpec, keyValue[1]); } parseResult.addOriginalStringValue(argSpec, raw); }
@Test public void test130MixPositionalParamsWithOptionsArity() { class Arg { @Parameters(arity = "2") List<String> parameters; @Option(names = "-o") List<String> options; } Arg result = CommandLine.populateCommand(new Arg(), "-o", "v1", "p1", "p2", "-o", "v2", "p3", "p4"); assertEquals(Arrays.asList("v1", "v2"), result.options); assertEquals(Arrays.asList("p1", "p2", "p3", "p4"), result.parameters); try { CommandLine.populateCommand(new Arg(), "-o", "v1", "p1", "-o", "v2", "p3"); fail("Expected MissingParameterException"); } catch (MissingParameterException ex) { assertEquals("Expected parameter 2 (of 2 mandatory parameters) for positional parameter at index 0..* (<parameters>) but found '-o'", ex.getMessage()); assertEquals(1, ex.getMissing().size()); assertTrue(ex.getMissing().get(0).toString(), ex.getMissing().get(0) instanceof PositionalParamSpec); } try { CommandLine.populateCommand(new Arg(), "-o", "v1", "p1", "p2", "-o", "v2", "p3"); fail("Expected MissingParameterException"); } catch (MissingParameterException ex) { assertEquals("positional parameter at index 0..* (<parameters>) requires at least 2 values, but only 1 were specified: [p3]", ex.getMessage()); assertEquals(1, ex.getMissing().size()); assertTrue(ex.getMissing().get(0).toString(), ex.getMissing().get(0) instanceof PositionalParamSpec); } }
private int applyValuesToMapField(ArgSpec argSpec, LookBehind lookBehind, Range arity, Stack<String> args, Set<ArgSpec> initialized, String argDescription) throws Exception { Class<?>[] classes = argSpec.auxiliaryTypes(); if (classes.length < 2) { throw new ParameterException(CommandLine.this, argSpec.toString() + " needs two types (one for the map key, one for the value) but only has " + classes.length + " types configured.",argSpec, null); } ITypeConverter<?> keyConverter = getTypeConverter(classes[0], argSpec, 0); ITypeConverter<?> valueConverter = getTypeConverter(classes[1], argSpec, 1); @SuppressWarnings("unchecked") Map<Object, Object> map = (Map<Object, Object>) argSpec.getValue(); if (map == null || (!map.isEmpty() && !initialized.contains(argSpec))) { tracer.debug("Initializing binding for %s with empty %s%n", optionDescription("", argSpec, 0), argSpec.type().getSimpleName()); map = createMap(argSpec.type()); // map class argSpec.setValue(map); } initialized.add(argSpec); int originalSize = map.size(); consumeMapArguments(argSpec, lookBehind, arity, args, classes, keyConverter, valueConverter, map, argDescription); parseResult.add(argSpec, position); argSpec.setValue(map); return map.size() - originalSize; }
private int consumeOneArgument(ArgSpec argSpec, LookBehind lookBehind, Range arity, int consumed, String arg, Class<?> type, List<Object> result, int index, String argDescription) { if (!lookBehind.isAttached()) { parseResult.nowProcessing(argSpec, arg); } String raw = trim(arg); String[] values = argSpec.splitValue(raw, commandSpec.parser(), arity, consumed); ITypeConverter<?> converter = getTypeConverter(type, argSpec, 0); for (int j = 0; j < values.length; j++) { result.add(tryConvert(argSpec, index, converter, values[j], type)); if (tracer.isInfo()) { tracer.info("Adding [%s] to %s for %s%n", String.valueOf(result.get(result.size() - 1)), argSpec.toString(), argDescription); } parseResult.addStringValue(argSpec, values[j]); } parseResult.addOriginalStringValue(argSpec, raw); return ++index; } private boolean canConsumeOneArgument(ArgSpec argSpec, Range arity, int consumed, String arg, Class<?> type, String argDescription) {
@Test public void testVersionHelp_helpCommand() { CommandSpec helpCommand = CommandSpec.create().helpCommand(true); assertTrue(helpCommand.helpCommand()); CommandSpec parent = CommandSpec.create().addOption(OptionSpec.builder("-x").required(true).build()); parent.addSubcommand("help", helpCommand); CommandLine commandLine = new CommandLine(parent); commandLine.parse("help"); // no missing param exception try { commandLine.parse(); } catch (MissingParameterException ex) { assertEquals("Missing required option '-x=PARAM'", ex.getMessage()); assertEquals(1, ex.getMissing().size()); assertSame(ex.getMissing().get(0).toString(), parent.posixOptionsMap().get('x'), ex.getMissing().get(0)); } }
private void assertArgsHaveBundle(ResourceBundle orig, List<? extends ArgSpec> args) { assertFalse("args should not be empty", args.isEmpty()); for (ArgSpec arg : args) { assertNotNull("Messages for " + arg.toString(), arg.messages()); assertSame(arg.toString(), orig, arg.messages().resourceBundle()); } }
private boolean is(ArgSpec p, String attribute, boolean value) { if (value) { if (tracer.isInfo()) {tracer.info("%s has '%s' annotation: not validating required fields%n", p.toString(), attribute); }} return value; } @SuppressWarnings("unchecked")
if (tracer.isInfo()) { tracer.info(traceMessage, argSpec.toString(), String.valueOf(oldValue), String.valueOf(newValue), argDescription); } argSpec.setValue(newValue);
assertEquals("positional parameter at index 0..* (<values>) requires at least 2 values, but only 1 were specified: [a,b,c,d,e]", ex.getMessage()); assertEquals(1, ex.getMissing().size()); assertTrue(ex.getMissing().get(0).toString(), ex.getMissing().get(0) instanceof CommandLine.Model.PositionalParamSpec);
@Test public void test130MixPositionalParamsWithOptionsArity() { class Arg { @Parameters(arity = "2") List<String> parameters; @Option(names = "-o") List<String> options; } Arg result = CommandLine.populateCommand(new Arg(), "-o", "v1", "p1", "p2", "-o", "v2", "p3", "p4"); assertEquals(Arrays.asList("v1", "v2"), result.options); assertEquals(Arrays.asList("p1", "p2", "p3", "p4"), result.parameters); try { CommandLine.populateCommand(new Arg(), "-o", "v1", "p1", "-o", "v2", "p3"); fail("Expected MissingParameterException"); } catch (MissingParameterException ex) { assertEquals("Expected parameter 2 (of 2 mandatory parameters) for positional parameter at index 0..* (<parameters>) but found '-o'", ex.getMessage()); assertEquals(1, ex.getMissing().size()); assertTrue(ex.getMissing().get(0).toString(), ex.getMissing().get(0) instanceof PositionalParamSpec); } try { CommandLine.populateCommand(new Arg(), "-o", "v1", "p1", "p2", "-o", "v2", "p3"); fail("Expected MissingParameterException"); } catch (MissingParameterException ex) { assertEquals("positional parameter at index 0..* (<parameters>) requires at least 2 values, but only 1 were specified: [p3]", ex.getMessage()); assertEquals(1, ex.getMissing().size()); assertTrue(ex.getMissing().get(0).toString(), ex.getMissing().get(0) instanceof PositionalParamSpec); } }
@Test public void testArrayOptionWithoutArityConsumesOneArgument() { // #192 class OptionsNoArityAndParameters { @Parameters char[] charParams; @Option(names = "-chars") char[] charOptions; } OptionsNoArityAndParameters params = CommandLine.populateCommand(new OptionsNoArityAndParameters(), "-chars a b c d".split(" ")); assertArrayEquals(Arrays.toString(params.charOptions), new char[] {'a', }, params.charOptions); assertArrayEquals(Arrays.toString(params.charParams), new char[] {'b', 'c', 'd'}, params.charParams); // repeated occurrence params = CommandLine.populateCommand(new OptionsNoArityAndParameters(), "-chars a -chars b c d".split(" ")); assertArrayEquals(Arrays.toString(params.charOptions), new char[] {'a', 'b', }, params.charOptions); assertArrayEquals(Arrays.toString(params.charParams), new char[] {'c', 'd'}, params.charParams); try { CommandLine.populateCommand(new OptionsNoArityAndParameters(), "-chars".split(" ")); fail("expected MissingParameterException"); } catch (MissingParameterException ok) { assertEquals("Missing required parameter for option '-chars' (<charOptions>)", ok.getMessage()); assertEquals(1, ok.getMissing().size()); assertTrue(ok.getMissing().get(0).toString(), ok.getMissing().get(0) instanceof Model.OptionSpec); } }
@Test public void testVersionHelp_helpCommand() { CommandSpec helpCommand = CommandSpec.create().helpCommand(true); assertTrue(helpCommand.helpCommand()); CommandSpec parent = CommandSpec.create().addOption(OptionSpec.builder("-x").required(true).build()); parent.addSubcommand("help", helpCommand); CommandLine commandLine = new CommandLine(parent); commandLine.parse("help"); // no missing param exception try { commandLine.parse(); } catch (MissingParameterException ex) { assertEquals("Missing required option '-x=PARAM'", ex.getMessage()); assertEquals(1, ex.getMissing().size()); assertSame(ex.getMissing().get(0).toString(), parent.posixOptionsMap().get('x'), ex.getMissing().get(0)); } }
private void assertArgsHaveBundle(ResourceBundle orig, List<? extends ArgSpec> args) { assertFalse("args should not be empty", args.isEmpty()); for (ArgSpec arg : args) { assertNotNull("Messages for " + arg.toString(), arg.messages()); assertSame(arg.toString(), orig, arg.messages().resourceBundle()); } }
private boolean is(ArgSpec p, String attribute, boolean value) { if (value) { if (tracer.isInfo()) {tracer.info("%s has '%s' annotation: not validating required fields%n", p.toString(), attribute); }} return value; } @SuppressWarnings("unchecked")