From ec51ebe83ea6e42236adf8ca3d12ef00d1c5d2bb Mon Sep 17 00:00:00 2001 From: Asriter Date: Sun, 25 Apr 2021 19:21:08 +0800 Subject: [PATCH 1/3] fixed Parameter does not display {},[],: correctly In fact, the bug is not caused by the input of these symbols in the argument, but by the "splitter" call that splits the String according to ", ". so the input JSON will be split. I added a method "JSONCheck" in CommParameterSplitter to determine if the parameter is JSON, and if it is, it will not be split according to ",". --- .../converters/CommaParameterSplitter.java | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/beust/jcommander/converters/CommaParameterSplitter.java b/src/main/java/com/beust/jcommander/converters/CommaParameterSplitter.java index 0e3bb1869..99bb8b728 100644 --- a/src/main/java/com/beust/jcommander/converters/CommaParameterSplitter.java +++ b/src/main/java/com/beust/jcommander/converters/CommaParameterSplitter.java @@ -5,8 +5,21 @@ public class CommaParameterSplitter implements IParameterSplitter { - public List split(String value) { - return Arrays.asList(value.split(",")); + @Override + public List split(final String value) { + return getJsonType(value.trim()) ? Arrays.asList(value) : Arrays.asList(value.split(",")); } + + /** + * Check if the parameter is in Json format. + * + * @param arg the split parameter + * @return {@code true} if {@code String} is in Json format + */ + public static boolean getJsonType(final String arg) { + final char[] chars = arg.toCharArray(); + return chars[0] == '{' && chars[chars.length-1] == '}' || chars[0] == '[' && chars[chars.length-1] == ']' + ? true : false; + } } From 06b8596e99e7465c72a08f5448832217534ff4c7 Mon Sep 17 00:00:00 2001 From: Asriter Date: Sat, 22 May 2021 01:53:52 +0800 Subject: [PATCH 2/3] fixed issues Subcommands #445 I add a method 'addSubcommand' that add a command for the command added by user but the main command. Use this method, 'myprogram command subcommand --flag1 --flag2' can run successfully. --- .../java/com/beust/jcommander/JCommander.java | 98 ++++++++++++++++++- .../jcommander/command/subcommandTest.java | 85 ++++++++++++++++ 2 files changed, 182 insertions(+), 1 deletion(-) create mode 100644 src/test/java/com/beust/jcommander/command/subcommandTest.java diff --git a/src/main/java/com/beust/jcommander/JCommander.java b/src/main/java/com/beust/jcommander/JCommander.java index f988bde99..cd4f3afe8 100644 --- a/src/main/java/com/beust/jcommander/JCommander.java +++ b/src/main/java/com/beust/jcommander/JCommander.java @@ -1287,7 +1287,7 @@ private IStringConverter findConverterInstance(Parameter parameter, Class } /** - * @param type The type of the actual parameter + * @param type The type of the actual parameter. * @param optionName * @param value The value to convert */ @@ -1420,6 +1420,102 @@ public void addCommand(String name, Object object, String... aliases) { } } + /** + * This method can create a subcommand for one command. + * The used command like this: programName command subcommand --flag + * Actually this method is wrap "addCommand", add a command for one command but the main command + * @param name the name for subcommand + * @param object the class you want to create for subcommand + * @param parentCommand the instance of command that you want to add subcommand + * @param aliases the aliases for the subcommand + **/ + public void addSubcommand(String name, Object object, JCommander parentCommand, String... aliases){ + if (parentCommand == null) { + throw new MissingCommandException("Expected a command, command not exist"); + } + parentCommand.addCommand(name, object, aliases); + } + + /** + * his method can create a subcommand for one command. + * The used command like this: programName command subcommand --flag + * Actually this method is wrap "addCommand", add a command for one command but the main command + * @param name the name for subcommand + * @param object the class you want to create for subcommand + * @param parentCommand the instance of command that you want to add subcommand + */ + public void addSubcommand(String name, Object object, JCommander parentCommand) { + addSubcommand(name, object, parentCommand, new String[0]); + } + + /** + * his method can create a subcommand for one command. + * The used command like this: programName command subcommand --flag + * Actually this method is wrap "addCommand", add a command for one command but the main command + * @param object the class you want to create for subcommand + * @param parentCommand the instance of command that you want to add subcommand + */ + public void addSubcommand(Object object, JCommander parentCommand) { + Parameters p = object.getClass().getAnnotation(Parameters.class); + if (p != null && p.commandNames().length > 0) { + for (String commandName : p.commandNames()) { + addSubcommand(commandName, object, parentCommand); + } + } else { + throw new ParameterException("Trying to add command " + object.getClass().getName() + + " without specifying its names in @Parameters"); + } + } + + /** + * This method can create a subcommand for one command. + * The used command like this: programName command subcommand --flag + * Actually this method is wrap "addCommand", add a command for one command but the main command + * @param name the name for subcommand + * @param object the class you want to create for subcommand + * @param parentCommandName the String name of command that you want to add subcommand + * @param aliases the aliases for the subcommand + **/ + public void addSubcommand(String name, Object object,String parentCommandName, String... aliases){ + JCommander parentJC = findCommandByAlias(parentCommandName); + if (parentJC != null) + parentJC.addCommand(name, object, aliases); + else { + throw new MissingCommandException("Expected a command, " + parentCommandName + " not found"); + } + } + + /** + * This method can create a subcommand for one command. + * The used command like this: programName command subcommand --flag + * Actually this method is wrap "addCommand", add a command for one command but the main command + * @param name the name for subcommand + * @param object the class you want to create for subcommand + * @param parentCommandName the String name of command that you want to add subcommand + **/ + public void addSubcommand(String name, Object object, String parentCommandName) { + addSubcommand(name, object, parentCommandName, new String[0]); + } + + /** + * This method can create a subcommand for one command. + * The used command like this: programName command subcommand --flag + * Actually this method is wrap "addCommand", add a command for one command but the main command + * @param object the class you want to create for subcommand + * @param parentCommandName the String name of command that you want to add subcommand + **/ + public void addSubcommand(Object object, String parentCommandName) { + Parameters p = object.getClass().getAnnotation(Parameters.class); + if (p != null && p.commandNames().length > 0) { + for (String commandName : p.commandNames()) { + addSubcommand(commandName, object, parentCommandName); + } + } else { + throw new ParameterException("Trying to add command " + object.getClass().getName() + + " without specifying its names in @Parameters"); + } + } + public Map getCommands() { Map res = Maps.newLinkedHashMap(); diff --git a/src/test/java/com/beust/jcommander/command/subcommandTest.java b/src/test/java/com/beust/jcommander/command/subcommandTest.java new file mode 100644 index 000000000..e3c969617 --- /dev/null +++ b/src/test/java/com/beust/jcommander/command/subcommandTest.java @@ -0,0 +1,85 @@ +package test; + +import com.beust.jcommander.*; +import java.util.*; +import org.testng.annotations.Test; +import org.testng.Assert; + +class testClass1 { + @Parameter(names = "testCommand",description = "same name test") + public String result = "null"; + + @Parameter(names = "mainTestCommand",description = "main command test") + public int mainResult = -1; +} + +class testClass2 { + @Parameter(names = "testCommand",description = "test 2 over~!") + public String result = "null"; + + @Parameter(names = "subTestCommand",description = "sub command test") + public int subResult = -1; +} + + +////CS304 (manually written) Issue link:https://github.com/cbeust/jcommander/issues/431 +public class subcommandTest { + + @Test + private void subCommandOnlyTest() { + //String[] args = new String[]{"command1", "mainTestCommand", "1", "command1", "sub", "subTestCommand", "2"}; + //String[] args = new String[]{"command1", "mainTestCommand", "1"}; + String[] args = new String[]{"command1", "sub", "subTestCommand", "2"}; + JCommander jc = new JCommander(this); + testClass1 mainCommand = new testClass1(); + testClass2 subCommand = new testClass2(); + jc.addCommand("command1", mainCommand); + jc.addSubcommand("sub", subCommand, "command1"); + jc.parse(args); + + Assert.assertTrue(mainCommand.mainResult == -1, "the result of main command is:" + mainCommand.mainResult + " but not -1"); + Assert.assertTrue(subCommand.subResult == 2, "the result of sub command is:" + subCommand.subResult + " but not 2"); + } + + @Test + private void mainCommandOnlyTest() { + String[] args = new String[]{"command1", "mainTestCommand", "1"}; + JCommander jc = new JCommander(this); + testClass1 mainCommand = new testClass1(); + testClass2 subCommand = new testClass2(); + jc.addCommand("command1", mainCommand); + jc.addSubcommand("sub", subCommand, "command1"); + jc.parse(args); + + Assert.assertTrue(mainCommand.mainResult == 1, "the result of main command is:" + mainCommand.mainResult + " but not 1"); + Assert.assertTrue(subCommand.subResult == -1, "the result of sub command is:" + subCommand.subResult + " but not -1"); + } + + @Test + private void sameNameParamentTestSub() { + String[] args = new String[]{"command1", "sub", "testCommand", "test over"}; + JCommander jc = new JCommander(this); + testClass1 mainCommand = new testClass1(); + testClass2 subCommand = new testClass2(); + jc.addCommand("command1", mainCommand); + jc.addSubcommand("sub", subCommand, "command1"); + jc.parse(args); + + Assert.assertTrue(mainCommand.result == "null", "the result of main command is:" + mainCommand.result + " but not null"); + Assert.assertTrue(subCommand.result == "test over", "the result of sub command is:" + subCommand.result + " but not test over"); + } + + @Test + private void sameNameParamentTestMain() { + String[] args = new String[]{"command1", "testCommand", "test over"}; + JCommander jc = new JCommander(this); + testClass1 mainCommand = new testClass1(); + testClass2 subCommand = new testClass2(); + jc.addCommand("command1", mainCommand); + jc.addSubcommand("sub", subCommand, "command1"); + jc.parse(args); + + Assert.assertTrue(mainCommand.result == "test over", "the result of main command is:" + mainCommand.result + " but not test over"); + Assert.assertTrue(subCommand.result == "null", "the result of sub command is:" + subCommand.result + " but not null"); + } +} \ No newline at end of file From 112959dfdbc0f43ea5e2b26c6ee60e1d27ad4a76 Mon Sep 17 00:00:00 2001 From: Asriter Date: Sat, 22 May 2021 01:57:28 +0800 Subject: [PATCH 3/3] Update CommaParameterSplitter.java --- .../converters/CommaParameterSplitter.java | 19 +++---------------- 1 file changed, 3 insertions(+), 16 deletions(-) diff --git a/src/main/java/com/beust/jcommander/converters/CommaParameterSplitter.java b/src/main/java/com/beust/jcommander/converters/CommaParameterSplitter.java index 99bb8b728..cc81382fb 100644 --- a/src/main/java/com/beust/jcommander/converters/CommaParameterSplitter.java +++ b/src/main/java/com/beust/jcommander/converters/CommaParameterSplitter.java @@ -5,21 +5,8 @@ public class CommaParameterSplitter implements IParameterSplitter { - @Override - public List split(final String value) { - return getJsonType(value.trim()) ? Arrays.asList(value) : Arrays.asList(value.split(",")); + public List split(String value) { + return Arrays.asList(value.split(",")); } - - /** - * Check if the parameter is in Json format. - * - * @param arg the split parameter - * @return {@code true} if {@code String} is in Json format - */ - public static boolean getJsonType(final String arg) { - final char[] chars = arg.toCharArray(); - return chars[0] == '{' && chars[chars.length-1] == '}' || chars[0] == '[' && chars[chars.length-1] == ']' - ? true : false; - } -} +} \ No newline at end of file