diff options
Diffstat (limited to 'src/main')
-rw-r--r-- | src/main/java/com/beust/jcommander/IVariableArity.java | 16 | ||||
-rw-r--r-- | src/main/java/com/beust/jcommander/JCommander.java | 103 | ||||
-rw-r--r-- | src/main/java/com/beust/jcommander/Parameter.java | 5 |
3 files changed, 89 insertions, 35 deletions
diff --git a/src/main/java/com/beust/jcommander/IVariableArity.java b/src/main/java/com/beust/jcommander/IVariableArity.java new file mode 100644 index 0000000..e7499c9 --- /dev/null +++ b/src/main/java/com/beust/jcommander/IVariableArity.java @@ -0,0 +1,16 @@ +package com.beust.jcommander; + +/** + * Must be implemented by argument classes that contain at least one + * @Parameter with "variableArity = true". + */ +public interface IVariableArity { + + /** + * @param optionName the name of the option to process. + * @param options the entire list of options. + * + * @return how many options were processed. + */ + int processVariableArity(String optionName, String[] options); +} diff --git a/src/main/java/com/beust/jcommander/JCommander.java b/src/main/java/com/beust/jcommander/JCommander.java index 0ae4e85..5735814 100644 --- a/src/main/java/com/beust/jcommander/JCommander.java +++ b/src/main/java/com/beust/jcommander/JCommander.java @@ -526,48 +526,28 @@ public class JCommander { char[] password = readPassword(pd.getDescription()); pd.addValue(new String(password)); } else { - // - // Regular option - // - Class<?> fieldType = pd.getField().getType(); - - // Boolean, set to true as soon as we see it, unless it specified - // an arity of 1, in which case we need to read the next value - if ((fieldType == boolean.class || fieldType == Boolean.class) - && pd.getParameter().arity() == -1) { - pd.addValue("true"); - m_requiredFields.remove(pd.getField()); + if (pd.getParameter().variableArity()) { + // + // Variable arity? + // + i = processVariableArity(args, i, pd); } else { - // Regular parameter, use the arity to tell use how many values - // we need to consume - int arity = pd.getParameter().arity(); - int n = (arity != -1 ? arity : 1); - - // Special case for boolean parameters of arity 0 - if (n == 0 && - (Boolean.class.isAssignableFrom(fieldType) - || boolean.class.isAssignableFrom(fieldType))) { + // + // Regular option + // + Class<?> fieldType = pd.getField().getType(); + + // Boolean, set to true as soon as we see it, unless it specified + // an arity of 1, in which case we need to read the next value + if ((fieldType == boolean.class || fieldType == Boolean.class) + && pd.getParameter().arity() == -1) { pd.addValue("true"); m_requiredFields.remove(pd.getField()); - } else if (i < args.length - 1) { - int offset = "--".equals(args[i + 1]) ? 1 : 0; - - if (i + n < args.length) { - for (int j = 1; j <= n; j++) { - pd.addValue(trim(args[i + j + offset])); - m_requiredFields.remove(pd.getField()); - } - i += n + offset; - } else { - throw new ParameterException("Expected " + n + " values after " + arg); - } } else { - throw new ParameterException("Expected a value after parameter " + arg); + i = processFixedArity(args, i, pd, fieldType); } } } - } else { - throw new ParameterException("Unknown option: " + a); } } else { @@ -624,6 +604,59 @@ public class JCommander { } /** + * @return the number of options that were processed. + */ + private int processVariableArity(String[] args, int index, ParameterDescription pd) { + Object arg = pd.getObject(); + if (! (arg instanceof IVariableArity)) { + throw new ParameterException("Arg class " + arg.getClass() + + " should implement IVariableArity"); + } + + IVariableArity va = (IVariableArity) arg; + List<String> currentArgs = Lists.newArrayList(); + for (int j = index + 1; j < args.length; j++) { + currentArgs.add(args[j]); + } + int result = va.processVariableArity(pd.getParameter().names()[0], + currentArgs.toArray(new String[0])); + return result; + } + + private int processFixedArity(String[] args, int index, ParameterDescription pd, + Class<?> fieldType) { + // Regular parameter, use the arity to tell use how many values + // we need to consume + String arg = args[index]; + int arity = pd.getParameter().arity(); + int n = (arity != -1 ? arity : 1); + + // Special case for boolean parameters of arity 0 + if (n == 0 && + (Boolean.class.isAssignableFrom(fieldType) + || boolean.class.isAssignableFrom(fieldType))) { + pd.addValue("true"); + m_requiredFields.remove(pd.getField()); + } else if (index < args.length - 1) { + int offset = "--".equals(args[index + 1]) ? 1 : 0; + + if (index + n < args.length) { + for (int j = 1; j <= n; j++) { + pd.addValue(trim(args[index + j + offset])); + m_requiredFields.remove(pd.getField()); + } + index += n + offset; + } else { + throw new ParameterException("Expected " + n + " values after " + arg); + } + } else { + throw new ParameterException("Expected a value after parameter " + arg); + } + + return index; + } + + /** * Invoke Console.readPassword through reflection to avoid depending * on Java 6. */ diff --git a/src/main/java/com/beust/jcommander/Parameter.java b/src/main/java/com/beust/jcommander/Parameter.java index 7003f5d..c697d2e 100644 --- a/src/main/java/com/beust/jcommander/Parameter.java +++ b/src/main/java/com/beust/jcommander/Parameter.java @@ -78,4 +78,9 @@ public @interface Parameter { * The validation class to use. */ Class<? extends IParameterValidator> validateWith() default NoValidator.class; + + /** + * @return true if this parameter has a variable arity. See @{IVariableArity} + */ + boolean variableArity() default false; } |