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/main/java/com/beust/jcommander/converters/CommaParameterSplitter.java b/src/main/java/com/beust/jcommander/converters/CommaParameterSplitter.java index 0e3bb1869..cc81382fb 100644 --- a/src/main/java/com/beust/jcommander/converters/CommaParameterSplitter.java +++ b/src/main/java/com/beust/jcommander/converters/CommaParameterSplitter.java @@ -9,4 +9,4 @@ public List split(String value) { return Arrays.asList(value.split(",")); } -} +} \ No newline at end of file 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