/** Sets whether the parser should ignore case when converting arguments to {@code enum} values. The default is {@code false}. * When set to true, for example, for an option of type <a href="https://docs.oracle.com/javase/8/docs/api/java/time/DayOfWeek.html">java.time.DayOfWeek</a>, * values {@code MonDaY}, {@code monday} and {@code MONDAY} are all recognized if {@code true}. * <p>The specified setting will be registered with this {@code CommandLine} and the full hierarchy of its * subcommands and nested sub-subcommands <em>at the moment this method is called</em>. Subcommands added * later will have the default setting. To ensure a setting is applied to all * subcommands, call the setter last, after adding subcommands.</p> * @param newValue the new setting * @return this {@code CommandLine} object, to allow method chaining * @since 3.4 */ public CommandLine setCaseInsensitiveEnumValuesAllowed(boolean newValue) { getCommandSpec().parser().caseInsensitiveEnumValuesAllowed(newValue); for (CommandLine command : getCommandSpec().subcommands().values()) { command.setCaseInsensitiveEnumValuesAllowed(newValue); } return this; }
final CommandLine commandLine = new CommandLine(cliOptions); commandLine.setUsageHelpWidth(CliOptions.HELP_WIDTH); commandLine.setCaseInsensitiveEnumValuesAllowed(true);
@Test public void testEnumTypeConversionIsCaseInsensitiveIfConfigured() { EnumParams params = new EnumParams(); new CommandLine(params).setCaseInsensitiveEnumValuesAllowed(true).parse( "-timeUnit sEcONds -timeUnitArray milliSeconds miCroSeConds -timeUnitList SEConds MiCROsEconds nanoSEConds".split(" ")); assertEquals(SECONDS, params.timeUnit); assertArrayEquals(new TimeUnit[]{MILLISECONDS, TimeUnit.MICROSECONDS}, params.timeUnitArray); List<TimeUnit> expected = new ArrayList<TimeUnit>(Arrays.asList(TimeUnit.SECONDS, TimeUnit.MICROSECONDS, TimeUnit.NANOSECONDS)); assertEquals(expected, params.timeUnitList); } enum MyTestEnum {
@Test public void testEnumCaseInsensitiveTypeConversionErrorMessageUsesConstantValuesNotToString() { class App { @Option(names = "-e") MyTestEnum myEnum; } App params = new App(); try { new CommandLine(params).setCaseInsensitiveEnumValuesAllowed(true).parse("-e big".split(" ")); } catch (ParameterException ex) { assertEquals("Invalid value for option '-e': expected one of [BIG, SMALL, TINY] (case-insensitive) but was 'big'", ex.getMessage()); } } @Test
@Test public void testParserCaseInsensitiveEnumValuesAllowed_enabled() throws Exception { PojoWithEnumOptions fields = new PojoWithEnumOptions(); new CommandLine(fields).setCaseInsensitiveEnumValuesAllowed(true).parse("-u=milliseconds"); assertSame(TimeUnit.MILLISECONDS, fields.enumValue); } @Test
@Test public void testParserCaseInsensitiveEnumValuesAllowed_invalidInput() throws Exception { PojoWithEnumOptions fields = new PojoWithEnumOptions(); CommandLine cmd = new CommandLine(fields).setCaseInsensitiveEnumValuesAllowed(true); try { cmd.parse("-u=millisecondINVALID"); fail("Expected exception"); } catch (ParameterException ex) { assertTrue(ex.getMessage(), ex.getMessage().startsWith("Invalid value for option '-u': expected one of ")); } }
@Test public void testParserCaseInsensitiveEnumValuesAllowed_BeforeSubcommandsAdded() { @Command class TopLevel {} CommandLine commandLine = new CommandLine(new TopLevel()); assertEquals(false, commandLine.isCaseInsensitiveEnumValuesAllowed()); commandLine.setCaseInsensitiveEnumValuesAllowed(true); assertEquals(true, commandLine.isCaseInsensitiveEnumValuesAllowed()); int childCount = 0; int grandChildCount = 0; commandLine.addSubcommand("main", createNestedCommand()); for (CommandLine sub : commandLine.getSubcommands().values()) { childCount++; assertEquals("subcommand added afterwards is not impacted", false, sub.isCaseInsensitiveEnumValuesAllowed()); for (CommandLine subsub : sub.getSubcommands().values()) { grandChildCount++; assertEquals("subcommand added afterwards is not impacted", false, subsub.isCaseInsensitiveEnumValuesAllowed()); } } assertTrue(childCount > 0); assertTrue(grandChildCount > 0); }
@Test public void testParserCaseInsensitiveEnumValuesAllowed_AfterSubcommandsAdded() { @Command class TopLevel {} CommandLine commandLine = new CommandLine(new TopLevel()); commandLine.addSubcommand("main", createNestedCommand()); assertEquals(false, commandLine.isCaseInsensitiveEnumValuesAllowed()); commandLine.setCaseInsensitiveEnumValuesAllowed(true); assertEquals(true, commandLine.isCaseInsensitiveEnumValuesAllowed()); int childCount = 0; int grandChildCount = 0; for (CommandLine sub : commandLine.getSubcommands().values()) { childCount++; assertEquals("subcommand added before IS impacted", true, sub.isCaseInsensitiveEnumValuesAllowed()); for (CommandLine subsub : sub.getSubcommands().values()) { grandChildCount++; assertEquals("subsubcommand added before IS impacted", true, sub.isCaseInsensitiveEnumValuesAllowed()); } } assertTrue(childCount > 0); assertTrue(grandChildCount > 0); }
/** Sets whether the parser should ignore case when converting arguments to {@code enum} values. The default is {@code false}. * When set to true, for example, for an option of type <a href="https://docs.oracle.com/javase/8/docs/api/java/time/DayOfWeek.html">java.time.DayOfWeek</a>, * values {@code MonDaY}, {@code monday} and {@code MONDAY} are all recognized if {@code true}. * <p>The specified setting will be registered with this {@code CommandLine} and the full hierarchy of its * subcommands and nested sub-subcommands <em>at the moment this method is called</em>. Subcommands added * later will have the default setting. To ensure a setting is applied to all * subcommands, call the setter last, after adding subcommands.</p> * @param newValue the new setting * @return this {@code CommandLine} object, to allow method chaining * @since 3.4 */ public CommandLine setCaseInsensitiveEnumValuesAllowed(boolean newValue) { getCommandSpec().parser().caseInsensitiveEnumValuesAllowed(newValue); for (CommandLine command : getCommandSpec().subcommands().values()) { command.setCaseInsensitiveEnumValuesAllowed(newValue); } return this; }
final CommandLine commandLine = new CommandLine(cliOptions); commandLine.setUsageHelpWidth(CliOptions.HELP_WIDTH); commandLine.setCaseInsensitiveEnumValuesAllowed(true);
@Test public void testEnumTypeConversionIsCaseInsensitiveIfConfigured() { EnumParams params = new EnumParams(); new CommandLine(params).setCaseInsensitiveEnumValuesAllowed(true).parse( "-timeUnit sEcONds -timeUnitArray milliSeconds miCroSeConds -timeUnitList SEConds MiCROsEconds nanoSEConds".split(" ")); assertEquals(SECONDS, params.timeUnit); assertArrayEquals(new TimeUnit[]{MILLISECONDS, TimeUnit.MICROSECONDS}, params.timeUnitArray); List<TimeUnit> expected = new ArrayList<TimeUnit>(Arrays.asList(TimeUnit.SECONDS, TimeUnit.MICROSECONDS, TimeUnit.NANOSECONDS)); assertEquals(expected, params.timeUnitList); } enum MyTestEnum {
@Test public void testEnumCaseInsensitiveTypeConversionErrorMessageUsesConstantValuesNotToString() { class App { @Option(names = "-e") MyTestEnum myEnum; } App params = new App(); try { new CommandLine(params).setCaseInsensitiveEnumValuesAllowed(true).parse("-e big".split(" ")); } catch (ParameterException ex) { assertEquals("Invalid value for option '-e': expected one of [BIG, SMALL, TINY] (case-insensitive) but was 'big'", ex.getMessage()); } } @Test
@Test public void testParserCaseInsensitiveEnumValuesAllowed_enabled() throws Exception { PojoWithEnumOptions fields = new PojoWithEnumOptions(); new CommandLine(fields).setCaseInsensitiveEnumValuesAllowed(true).parse("-u=milliseconds"); assertSame(TimeUnit.MILLISECONDS, fields.enumValue); } @Test
@Test public void testParserCaseInsensitiveEnumValuesAllowed_invalidInput() throws Exception { PojoWithEnumOptions fields = new PojoWithEnumOptions(); CommandLine cmd = new CommandLine(fields).setCaseInsensitiveEnumValuesAllowed(true); try { cmd.parse("-u=millisecondINVALID"); fail("Expected exception"); } catch (ParameterException ex) { assertTrue(ex.getMessage(), ex.getMessage().startsWith("Invalid value for option '-u': expected one of ")); } }
@Test public void testParserCaseInsensitiveEnumValuesAllowed_BeforeSubcommandsAdded() { @Command class TopLevel {} CommandLine commandLine = new CommandLine(new TopLevel()); assertEquals(false, commandLine.isCaseInsensitiveEnumValuesAllowed()); commandLine.setCaseInsensitiveEnumValuesAllowed(true); assertEquals(true, commandLine.isCaseInsensitiveEnumValuesAllowed()); int childCount = 0; int grandChildCount = 0; commandLine.addSubcommand("main", createNestedCommand()); for (CommandLine sub : commandLine.getSubcommands().values()) { childCount++; assertEquals("subcommand added afterwards is not impacted", false, sub.isCaseInsensitiveEnumValuesAllowed()); for (CommandLine subsub : sub.getSubcommands().values()) { grandChildCount++; assertEquals("subcommand added afterwards is not impacted", false, subsub.isCaseInsensitiveEnumValuesAllowed()); } } assertTrue(childCount > 0); assertTrue(grandChildCount > 0); }
@Test public void testParserCaseInsensitiveEnumValuesAllowed_AfterSubcommandsAdded() { @Command class TopLevel {} CommandLine commandLine = new CommandLine(new TopLevel()); commandLine.addSubcommand("main", createNestedCommand()); assertEquals(false, commandLine.isCaseInsensitiveEnumValuesAllowed()); commandLine.setCaseInsensitiveEnumValuesAllowed(true); assertEquals(true, commandLine.isCaseInsensitiveEnumValuesAllowed()); int childCount = 0; int grandChildCount = 0; for (CommandLine sub : commandLine.getSubcommands().values()) { childCount++; assertEquals("subcommand added before IS impacted", true, sub.isCaseInsensitiveEnumValuesAllowed()); for (CommandLine subsub : sub.getSubcommands().values()) { grandChildCount++; assertEquals("subsubcommand added before IS impacted", true, sub.isCaseInsensitiveEnumValuesAllowed()); } } assertTrue(childCount > 0); assertTrue(grandChildCount > 0); }
public void parse( final AbstractParseResultHandler<List<Object>> resultHandler, final DefaultExceptionHandler<List<Object>> exceptionHandler, final String... args) { commandLine = new CommandLine(this); commandLine.setCaseInsensitiveEnumValuesAllowed(true); standaloneCommands = new StandaloneCommand(); if (isFullInstantiation()) { commandLine.addMixin("standaloneCommands", standaloneCommands); } commandLine.addSubcommand( BlocksSubCommand.COMMAND_NAME, new BlocksSubCommand(blockImporter, resultHandler.out())); commandLine.addSubcommand( PublicKeySubCommand.COMMAND_NAME, new PublicKeySubCommand(resultHandler.out())); commandLine.addSubcommand( PasswordSubCommand.COMMAND_NAME, new PasswordSubCommand(resultHandler.out())); commandLine.registerConverter(Address.class, Address::fromHexString); commandLine.registerConverter(BytesValue.class, BytesValue::fromHexString); commandLine.registerConverter(Level.class, Level::valueOf); commandLine.registerConverter(SyncMode.class, SyncMode::fromString); commandLine.registerConverter(Wei.class, (arg) -> Wei.of(Long.parseUnsignedLong(arg))); // Create a handler that will search for a config file option and use it for default values // and eventually it will run regular parsing of the remaining options. final ConfigOptionSearchAndRunHandler configParsingHandler = new ConfigOptionSearchAndRunHandler( resultHandler, exceptionHandler, CONFIG_FILE_OPTION_NAME, isDocker); commandLine.parseWithHandlers(configParsingHandler, exceptionHandler, args); }