summaryrefslogtreecommitdiffstats
path: root/src/main/java/com/beust
diff options
context:
space:
mode:
authorCedric Beust <cedric@beust.com>2012-06-24 15:12:31 -0700
committerCedric Beust <cedric@beust.com>2012-06-24 15:12:31 -0700
commit369d387138b6da9e77e01d82273ef6271580eb47 (patch)
tree1b6467c94e100e86c111b7f1e185d40f7a96a2cd /src/main/java/com/beust
parent0975e46cbf9e8aa7febc03dc38be47c19b408371 (diff)
downloadplatform_external_jcommander-369d387138b6da9e77e01d82273ef6271580eb47.tar.gz
platform_external_jcommander-369d387138b6da9e77e01d82273ef6271580eb47.tar.bz2
platform_external_jcommander-369d387138b6da9e77e01d82273ef6271580eb47.zip
Support for setters on top of fields.
Diffstat (limited to 'src/main/java/com/beust')
-rw-r--r--src/main/java/com/beust/jcommander/JCommander.java279
-rw-r--r--src/main/java/com/beust/jcommander/Parameter.java3
-rw-r--r--src/main/java/com/beust/jcommander/ParameterDescription.java81
-rw-r--r--src/main/java/com/beust/jcommander/Parameterized.java224
-rw-r--r--src/main/java/com/beust/jcommander/WrappedParameter.java22
5 files changed, 438 insertions, 171 deletions
diff --git a/src/main/java/com/beust/jcommander/JCommander.java b/src/main/java/com/beust/jcommander/JCommander.java
index dd758ef..66ce5f5 100644
--- a/src/main/java/com/beust/jcommander/JCommander.java
+++ b/src/main/java/com/beust/jcommander/JCommander.java
@@ -31,16 +31,13 @@ import com.beust.jcommander.internal.Maps;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
-import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
-import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.EnumSet;
@@ -79,10 +76,10 @@ public class JCommander {
private List<Object> m_objects = Lists.newArrayList();
/**
- * This field will contain whatever command line parameter is not an option.
+ * This field/method will contain whatever command line parameter is not an option.
* It is expected to be a List<String>.
*/
- private Field m_mainParameterField = null;
+ private Parameterized m_mainParameter = null;
/**
* The object on which we found the main parameter field.
@@ -97,19 +94,19 @@ public class JCommander {
private ParameterDescription m_mainParameterDescription;
/**
- * A set of all the fields that are required. During the reflection phase,
+ * A set of all the parameterizeds that are required. During the reflection phase,
* this field receives all the fields that are annotated with required=true
* and during the parsing phase, all the fields that are assigned a value
* are removed from it. At the end of the parsing phase, if it's not empty,
* then some required fields did not receive a value and an exception is
* thrown.
*/
- private Map<Field, ParameterDescription> m_requiredFields = Maps.newHashMap();
+ private Map<Parameterized, ParameterDescription> m_requiredFields = Maps.newHashMap();
/**
- * A map of all the annotated fields.
+ * A map of all the parameterized fields/methods/
*/
- private Map<Field, ParameterDescription> m_fields = Maps.newHashMap();
+ private Map<Parameterized, ParameterDescription> m_fields = Maps.newHashMap();
private ResourceBundle m_bundle;
@@ -142,6 +139,7 @@ public class JCommander {
private Comparator<? super ParameterDescription> m_parameterDescriptionComparator
= new Comparator<ParameterDescription>() {
+ @Override
public int compare(ParameterDescription p0, ParameterDescription p1) {
return p0.getLongestName().compareTo(p1.getLongestName());
}
@@ -512,74 +510,138 @@ public class JCommander {
private void addDescription(Object object) {
Class<?> cls = object.getClass();
- while (!Object.class.equals(cls)) {
- for (Field f : cls.getDeclaredFields()) {
- p("Field:" + cls.getSimpleName() + "." + f.getName());
- f.setAccessible(true);
- Annotation annotation = f.getAnnotation(Parameter.class);
- Annotation delegateAnnotation = f.getAnnotation(ParametersDelegate.class);
- Annotation dynamicParameter = f.getAnnotation(DynamicParameter.class);
- if (annotation != null) {
- //
- // @Parameter
- //
- Parameter p = (Parameter) annotation;
- if (p.names().length == 0) {
- p("Found main parameter:" + f);
- if (m_mainParameterField != null) {
- throw new ParameterException("Only one @Parameter with no names attribute is"
- + " allowed, found:" + m_mainParameterField + " and " + f);
- }
- m_mainParameterField = f;
- m_mainParameterObject = object;
- m_mainParameterAnnotation = p;
- m_mainParameterDescription = new ParameterDescription(object, p, f, m_bundle, this);
- } else {
- for (String name : p.names()) {
- if (m_descriptions.containsKey(name)) {
- throw new ParameterException("Found the option " + name + " multiple times");
- }
- p("Adding description for " + name);
- ParameterDescription pd = new ParameterDescription(object, p, f, m_bundle, this);
- m_fields.put(f, pd);
- m_descriptions.put(name, pd);
-
- if (p.required()) m_requiredFields.put(f, pd);
- }
- }
- } else if (delegateAnnotation != null) {
- //
- // @ParametersDelegate
- //
- try {
- Object delegateObject = f.get(object);
- if (delegateObject == null){
- throw new ParameterException("Delegate field '" + f.getName() + "' cannot be null.");
- }
- addDescription(delegateObject);
- } catch (IllegalAccessException e) {
+ List<Parameterized> parameterizeds = Parameterized.parseArg(object);
+ for (Parameterized parameterized : parameterizeds) {
+ WrappedParameter wp = parameterized.getWrappedParameter();
+ if (wp != null && wp.getParameter() != null) {
+ Parameter annotation = wp.getParameter();
+ //
+ // @Parameter
+ //
+ Parameter p = annotation;
+ if (p.names().length == 0) {
+ p("Found main parameter:" + parameterized);
+ if (m_mainParameter != null) {
+ throw new ParameterException("Only one @Parameter with no names attribute is"
+ + " allowed, found:" + m_mainParameter + " and " + parameterized);
}
- } else if (dynamicParameter != null) {
- //
- // @DynamicParameter
- //
- DynamicParameter dp = (DynamicParameter) dynamicParameter;
- for (String name : dp.names()) {
+ m_mainParameter = parameterized;
+ m_mainParameterObject = object;
+ m_mainParameterAnnotation = p;
+ m_mainParameterDescription =
+ new ParameterDescription(object, p, parameterized, m_bundle, this);
+ } else {
+ for (String name : p.names()) {
if (m_descriptions.containsKey(name)) {
throw new ParameterException("Found the option " + name + " multiple times");
}
p("Adding description for " + name);
- ParameterDescription pd = new ParameterDescription(object, dp, f, m_bundle, this);
- m_fields.put(f, pd);
+ ParameterDescription pd =
+ new ParameterDescription(object, p, parameterized, m_bundle, this);
+ m_fields.put(parameterized, pd);
m_descriptions.put(name, pd);
- if (dp.required()) m_requiredFields.put(f, pd);
+ if (p.required()) m_requiredFields.put(parameterized, pd);
}
}
+ } else if (parameterized.getDelegateAnnotation() != null) {
+ //
+ // @ParametersDelegate
+ //
+ Object delegateObject = parameterized.get(object);
+ if (delegateObject == null){
+ throw new ParameterException("Delegate field '" + parameterized.getName()
+ + "' cannot be null.");
+ }
+ addDescription(delegateObject);
+ } else if (wp != null && wp.getDynamicParameter() != null) {
+ //
+ // @DynamicParameter
+ //
+ DynamicParameter dp = wp.getDynamicParameter();
+ for (String name : dp.names()) {
+ if (m_descriptions.containsKey(name)) {
+ throw new ParameterException("Found the option " + name + " multiple times");
+ }
+ p("Adding description for " + name);
+ ParameterDescription pd =
+ new ParameterDescription(object, dp, parameterized, m_bundle, this);
+ m_fields.put(parameterized, pd);
+ m_descriptions.put(name, pd);
+
+ if (dp.required()) m_requiredFields.put(parameterized, pd);
+ }
}
- // Traverse the super class until we find Object.class
- cls = cls.getSuperclass();
}
+
+// while (!Object.class.equals(cls)) {
+// for (Field f : cls.getDeclaredFields()) {
+// p("Field:" + cls.getSimpleName() + "." + f.getName());
+// f.setAccessible(true);
+// Annotation annotation = f.getAnnotation(Parameter.class);
+// Annotation delegateAnnotation = f.getAnnotation(ParametersDelegate.class);
+// Annotation dynamicParameter = f.getAnnotation(DynamicParameter.class);
+// if (annotation != null) {
+// //
+// // @Parameter
+// //
+// Parameter p = (Parameter) annotation;
+// if (p.names().length == 0) {
+// p("Found main parameter:" + f);
+// if (m_mainParameterField != null) {
+// throw new ParameterException("Only one @Parameter with no names attribute is"
+// + " allowed, found:" + m_mainParameterField + " and " + f);
+// }
+// m_mainParameterField = parameterized;
+// m_mainParameterObject = object;
+// m_mainParameterAnnotation = p;
+// m_mainParameterDescription = new ParameterDescription(object, p, f, m_bundle, this);
+// } else {
+// for (String name : p.names()) {
+// if (m_descriptions.containsKey(name)) {
+// throw new ParameterException("Found the option " + name + " multiple times");
+// }
+// p("Adding description for " + name);
+// ParameterDescription pd = new ParameterDescription(object, p, f, m_bundle, this);
+// m_fields.put(f, pd);
+// m_descriptions.put(name, pd);
+//
+// if (p.required()) m_requiredFields.put(f, pd);
+// }
+// }
+// } else if (delegateAnnotation != null) {
+// //
+// // @ParametersDelegate
+// //
+// try {
+// Object delegateObject = f.get(object);
+// if (delegateObject == null){
+// throw new ParameterException("Delegate field '" + f.getName() + "' cannot be null.");
+// }
+// addDescription(delegateObject);
+// } catch (IllegalAccessException e) {
+// }
+// } else if (dynamicParameter != null) {
+// //
+// // @DynamicParameter
+// //
+// DynamicParameter dp = (DynamicParameter) dynamicParameter;
+// for (String name : dp.names()) {
+// if (m_descriptions.containsKey(name)) {
+// throw new ParameterException("Found the option " + name + " multiple times");
+// }
+// p("Adding description for " + name);
+// ParameterDescription pd = new ParameterDescription(object, dp, f, m_bundle, this);
+// m_fields.put(f, pd);
+// m_descriptions.put(name, pd);
+//
+// if (dp.required()) m_requiredFields.put(f, pd);
+// }
+// }
+// }
+// // Traverse the super class until we find Object.class
+// cls = cls.getSuperclass();
+// }
}
private void initializeDefaultValue(ParameterDescription pd) {
@@ -622,7 +684,7 @@ public class JCommander {
//
char[] password = readPassword(pd.getDescription(), pd.getParameter().echoInput());
pd.addValue(new String(password));
- m_requiredFields.remove(pd.getField());
+ m_requiredFields.remove(pd.getParameterized());
} else {
if (pd.getParameter().variableArity()) {
//
@@ -633,14 +695,14 @@ public class JCommander {
//
// Regular option
//
- Class<?> fieldType = pd.getField().getType();
+ Class<?> fieldType = pd.getParameterized().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());
+ m_requiredFields.remove(pd.getParameterized());
} else {
increment = processFixedArity(args, i, pd, fieldType);
}
@@ -663,11 +725,11 @@ public class JCommander {
String value = arg;
Object convertedValue = value;
- if (m_mainParameterField.getGenericType() instanceof ParameterizedType) {
- ParameterizedType p = (ParameterizedType) m_mainParameterField.getGenericType();
+ if (m_mainParameter.getGenericType() instanceof ParameterizedType) {
+ ParameterizedType p = (ParameterizedType) m_mainParameter.getGenericType();
Type cls = p.getActualTypeArguments()[0];
if (cls instanceof Class) {
- convertedValue = convertValue(m_mainParameterField, (Class) cls, value);
+ convertedValue = convertValue(m_mainParameter, (Class) cls, value);
}
}
@@ -699,29 +761,15 @@ public class JCommander {
// Mark the parameter descriptions held in m_fields as assigned
for (ParameterDescription parameterDescription : m_descriptions.values()) {
if (parameterDescription.isAssigned()) {
- m_fields.get(parameterDescription.getField()).setAssigned(true);
+ m_fields.get(parameterDescription.getParameterized()).setAssigned(true);
}
}
}
- /**
- * @return the generic type of the collection for this field, or null if not applicable.
- */
- private Type findFieldGenericType(Field field) {
- if (field.getGenericType() instanceof ParameterizedType) {
- ParameterizedType p = (ParameterizedType) field.getGenericType();
- Type cls = p.getActualTypeArguments()[0];
- if (cls instanceof Class) {
- return cls;
- }
- }
-
- return null;
- }
-
private class DefaultVariableArity implements IVariableArity {
+ @Override
public int processVariableArity(String optionName, String[] options) {
int i = 0;
while (i < options.length && !isOption(options, options[i])) {
@@ -774,14 +822,14 @@ public class JCommander {
(Boolean.class.isAssignableFrom(fieldType)
|| boolean.class.isAssignableFrom(fieldType))) {
pd.addValue("true");
- m_requiredFields.remove(pd.getField());
+ m_requiredFields.remove(pd.getParameterized());
} else if (index < args.length - 1) {
int offset = "--".equals(args[index + 1]) ? 1 : 0;
if (index + arity < args.length) {
for (int j = 1; j <= arity; j++) {
pd.addValue(trim(args[index + j + offset]));
- m_requiredFields.remove(pd.getField());
+ m_requiredFields.remove(pd.getParameterized());
}
index += arity + offset;
} else {
@@ -818,26 +866,21 @@ public class JCommander {
* error message).
*/
private List<?> getMainParameter(String arg) {
- if (m_mainParameterField == null) {
+ if (m_mainParameter == null) {
throw new ParameterException(
"Was passed main parameter '" + arg + "' but no main parameter was defined");
}
- try {
- List result = (List) m_mainParameterField.get(m_mainParameterObject);
- if (result == null) {
- result = Lists.newArrayList();
- if (! List.class.isAssignableFrom(m_mainParameterField.getType())) {
- throw new ParameterException("Main parameter field " + m_mainParameterField
- + " needs to be of type List, not " + m_mainParameterField.getType());
- }
- m_mainParameterField.set(m_mainParameterObject, result);
+ List<?> result = (List<?>) m_mainParameter.get(m_mainParameterObject);
+ if (result == null) {
+ result = Lists.newArrayList();
+ if (! List.class.isAssignableFrom(m_mainParameter.getType())) {
+ throw new ParameterException("Main parameter field " + m_mainParameter
+ + " needs to be of type List, not " + m_mainParameter.getType());
}
- return result;
- }
- catch(IllegalAccessException ex) {
- throw new ParameterException("Couldn't access main parameter: " + ex.getMessage());
+ m_mainParameter.set(m_mainParameterObject, result);
}
+ return result;
}
public String getMainParameterDescription() {
@@ -846,15 +889,15 @@ public class JCommander {
: null;
}
- private int longestName(Collection<?> objects) {
- int result = 0;
- for (Object o : objects) {
- int l = o.toString().length();
- if (l > result) result = l;
- }
-
- return result;
- }
+// private int longestName(Collection<?> objects) {
+// int result = 0;
+// for (Object o : objects) {
+// int l = o.toString().length();
+// if (l > result) result = l;
+// }
+//
+// return result;
+// }
/**
* Set the program name (used only in the usage).
@@ -1128,7 +1171,7 @@ public class JCommander {
}
public Object convertValue(ParameterDescription pd, String value) {
- return convertValue(pd.getField(), pd.getField().getType(), value);
+ return convertValue(pd.getParameterized(), pd.getParameterized().getType(), value);
}
/**
@@ -1136,8 +1179,8 @@ public class JCommander {
* @param type The type of the actual parameter
* @param value The value to convert
*/
- public Object convertValue(Field field, Class type, String value) {
- Parameter annotation = field.getAnnotation(Parameter.class);
+ public Object convertValue(Parameterized parameterized, Class type, String value) {
+ Parameter annotation = parameterized.getParameter();
// Do nothing if it's a @DynamicParameter
if (annotation == null) return value;
@@ -1158,7 +1201,7 @@ public class JCommander {
}
if (converterClass == null) {
- Type elementType = findFieldGenericType(field);
+ Type elementType = parameterized.findFieldGenericType();
converterClass = elementType != null
? findConverter((Class<? extends IStringConverter<?>>) elementType)
: StringConverter.class;
@@ -1194,7 +1237,7 @@ public class JCommander {
} else {
converter = instantiateConverter(optionName, converterClass);
if (type.isAssignableFrom(List.class)
- && field.getGenericType() instanceof ParameterizedType) {
+ && parameterized.getGenericType() instanceof ParameterizedType) {
// The field is a List
if (listConverterWasSpecified) {
diff --git a/src/main/java/com/beust/jcommander/Parameter.java b/src/main/java/com/beust/jcommander/Parameter.java
index c73d69b..51b941f 100644
--- a/src/main/java/com/beust/jcommander/Parameter.java
+++ b/src/main/java/com/beust/jcommander/Parameter.java
@@ -19,6 +19,7 @@
package com.beust.jcommander;
import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
import com.beust.jcommander.converters.CommaParameterSplitter;
import com.beust.jcommander.converters.IParameterSplitter;
@@ -30,7 +31,7 @@ import java.lang.annotation.Retention;
import java.lang.annotation.Target;
@Retention(java.lang.annotation.RetentionPolicy.RUNTIME)
-@Target({ FIELD })
+@Target({ FIELD, METHOD })
public @interface Parameter {
/**
diff --git a/src/main/java/com/beust/jcommander/ParameterDescription.java b/src/main/java/com/beust/jcommander/ParameterDescription.java
index 9299e59..5f4a0a7 100644
--- a/src/main/java/com/beust/jcommander/ParameterDescription.java
+++ b/src/main/java/com/beust/jcommander/ParameterDescription.java
@@ -21,7 +21,6 @@ package com.beust.jcommander;
import com.beust.jcommander.validators.NoValidator;
import com.beust.jcommander.validators.NoValueValidator;
-import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collection;
import java.util.EnumSet;
@@ -42,7 +41,8 @@ public class ParameterDescription {
private Parameter m_parameterAnnotation;
private DynamicParameter m_dynamicParameterAnnotation;
- private Field m_field;
+ /** The field/method */
+ private Parameterized m_parameterized;
/** Keep track of whether a value was added to flag an error */
private boolean m_assigned = false;
private ResourceBundle m_bundle;
@@ -52,23 +52,25 @@ public class ParameterDescription {
/** Longest of the names(), used to present usage() alphabetically */
private String m_longestName = "";
- public ParameterDescription(Object object, DynamicParameter annotation, Field field,
+ public ParameterDescription(Object object, DynamicParameter annotation,
+ Parameterized parameterized,
ResourceBundle bundle, JCommander jc) {
- if (! Map.class.isAssignableFrom(field.getType())) {
- throw new ParameterException("@DynamicParameter " + field.getName() + " should be of type "
- + "Map but is " + field.getType().getName());
+ if (! Map.class.isAssignableFrom(parameterized.getType())) {
+ throw new ParameterException("@DynamicParameter " + parameterized.getName()
+ + " should be of type "
+ + "Map but is " + parameterized.getType().getName());
}
m_dynamicParameterAnnotation = annotation;
m_wrappedParameter = new WrappedParameter(m_dynamicParameterAnnotation);
- init(object, field, bundle, jc);
+ init(object, parameterized, bundle, jc);
}
- public ParameterDescription(Object object, Parameter annotation, Field field,
+ public ParameterDescription(Object object, Parameter annotation, Parameterized parameterized,
ResourceBundle bundle, JCommander jc) {
m_parameterAnnotation = annotation;
m_wrappedParameter = new WrappedParameter(m_parameterAnnotation);
- init(object, field, bundle, jc);
+ init(object, parameterized, bundle, jc);
}
/**
@@ -115,10 +117,10 @@ public class ParameterDescription {
}
@SuppressWarnings("unchecked")
- private void init(Object object, Field field, ResourceBundle bundle,
+ private void init(Object object, Parameterized parameterized, ResourceBundle bundle,
JCommander jCommander) {
m_object = object;
- m_field = field;
+ m_parameterized = parameterized;
m_bundle = bundle;
if (m_bundle == null) {
m_bundle = findResourceBundle(object);
@@ -127,9 +129,9 @@ public class ParameterDescription {
if (m_parameterAnnotation != null) {
String description;
- if (Enum.class.isAssignableFrom(field.getType())
+ if (Enum.class.isAssignableFrom(parameterized.getType())
&& m_parameterAnnotation.description().isEmpty()) {
- description = "Options: " + EnumSet.allOf((Class<? extends Enum>) field.getType());
+ description = "Options: " + EnumSet.allOf((Class<? extends Enum>) parameterized.getType());
}else {
description = m_parameterAnnotation.description();
}
@@ -144,7 +146,7 @@ public class ParameterDescription {
}
try {
- m_default = m_field.get(m_object);
+ m_default = parameterized.get(object);
} catch (Exception e) {
}
@@ -194,18 +196,14 @@ public class ParameterDescription {
return m_wrappedParameter;
}
- public Field getField() {
- return m_field;
+ public Parameterized getParameterized() {
+ return m_parameterized;
}
private boolean isMultiOption() {
- Class<?> fieldType = m_field.getType();
+ Class<?> fieldType = m_parameterized.getType();
return fieldType.equals(List.class) || fieldType.equals(Set.class)
- || isDynamicParameter(m_field);
- }
-
- private boolean isDynamicParameter(Field field) {
- return field.getAnnotation(DynamicParameter.class) != null;
+ || m_parameterized.isDynamicParameter();
}
public void addValue(String value) {
@@ -231,7 +229,7 @@ public class ParameterDescription {
*/
public void addValue(String value, boolean isDefault) {
p("Adding " + (isDefault ? "default " : "") + "value:" + value
- + " to parameter:" + m_field.getName());
+ + " to parameter:" + m_parameterized.getName());
String name = m_wrappedParameter.names()[0];
if (m_assigned && ! isMultiOption()) {
throw new ParameterException("Can only specify option " + name + " once.");
@@ -239,35 +237,30 @@ public class ParameterDescription {
validateParameter(name, value);
- Class<?> type = m_field.getType();
+ Class<?> type = m_parameterized.getType();
Object convertedValue = m_jCommander.convertValue(this, value);
validateValueParameter(name, convertedValue);
boolean isCollection = Collection.class.isAssignableFrom(type);
- try {
- if (isCollection) {
- @SuppressWarnings("unchecked")
- Collection<Object> l = (Collection<Object>) m_field.get(m_object);
- if (l == null || fieldIsSetForTheFirstTime(isDefault)) {
- l = newCollection(type);
- m_field.set(m_object, l);
- }
- if (convertedValue instanceof Collection) {
- l.addAll((Collection) convertedValue);
- } else { // if (isMainParameter || m_parameterAnnotation.arity() > 1) {
- l.add(convertedValue);
+ if (isCollection) {
+ @SuppressWarnings("unchecked")
+ Collection<Object> l = (Collection<Object>) m_parameterized.get(m_object);
+ if (l == null || fieldIsSetForTheFirstTime(isDefault)) {
+ l = newCollection(type);
+ m_parameterized.set(m_object, l);
+ }
+ if (convertedValue instanceof Collection) {
+ l.addAll((Collection) convertedValue);
+ } else { // if (isMainParameter || m_parameterAnnotation.arity() > 1) {
+ l.add(convertedValue);
// } else {
// l.
- }
- } else {
- m_wrappedParameter.addValue(m_field, m_object, convertedValue);
}
- if (! isDefault) m_assigned = true;
- }
- catch(IllegalAccessException ex) {
- ex.printStackTrace();
+ } else {
+ m_wrappedParameter.addValue(m_parameterized, m_object, convertedValue);
}
+ if (! isDefault) m_assigned = true;
}
private void validateParameter(String name, String value) {
@@ -346,7 +339,7 @@ public class ParameterDescription {
@Override
public String toString() {
- return "[ParameterDescription " + m_field.getName() + "]";
+ return "[ParameterDescription " + m_parameterized.getName() + "]";
}
public boolean isDynamicParameter() {
diff --git a/src/main/java/com/beust/jcommander/Parameterized.java b/src/main/java/com/beust/jcommander/Parameterized.java
new file mode 100644
index 0000000..ec698fa
--- /dev/null
+++ b/src/main/java/com/beust/jcommander/Parameterized.java
@@ -0,0 +1,224 @@
+package com.beust.jcommander;
+
+import com.beust.jcommander.internal.Lists;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.util.List;
+
+/**
+ * Encapsulate a field or a method annotated with @Parameter or @DynamicParameter
+ */
+public class Parameterized {
+
+ // Either a method or a field
+ private Field m_field;
+ private Method m_method;
+ private Method m_getter;
+
+ // Either of these two
+ private WrappedParameter m_wrappedParameter;
+ private ParametersDelegate m_parametersDelegate;
+
+ public Parameterized(WrappedParameter wp, ParametersDelegate pd,
+ Field field, Method method) {
+ m_wrappedParameter = wp;
+ m_method = method;
+ m_field = field;
+ if (m_field != null) {
+ m_field.setAccessible(true);
+ }
+ m_parametersDelegate = pd;
+ }
+
+ public static List<Parameterized> parseArg(Object arg) {
+ List<Parameterized> result = Lists.newArrayList();
+
+ Class<? extends Object> cls = arg.getClass();
+ while (!Object.class.equals(cls)) {
+ for (Field f : cls.getDeclaredFields()) {
+ Annotation annotation = f.getAnnotation(Parameter.class);
+ Annotation delegateAnnotation = f.getAnnotation(ParametersDelegate.class);
+ Annotation dynamicParameter = f.getAnnotation(DynamicParameter.class);
+ if (annotation != null) {
+ result.add(new Parameterized(new WrappedParameter((Parameter) annotation), null,
+ f, null));
+ } else if (dynamicParameter != null) {
+ result.add(new Parameterized(new WrappedParameter((DynamicParameter) dynamicParameter), null,
+ f, null));
+ } else if (delegateAnnotation != null) {
+ result.add(new Parameterized(null, (ParametersDelegate) delegateAnnotation,
+ f, null));
+ }
+ }
+ cls = cls.getSuperclass();
+ }
+
+ // Reassigning
+ cls = arg.getClass();
+ while (!Object.class.equals(cls)) {
+ for (Method m : cls.getDeclaredMethods()) {
+ Annotation annotation = m.getAnnotation(Parameter.class);
+ Annotation delegateAnnotation = m.getAnnotation(ParametersDelegate.class);
+ Annotation dynamicParameter = m.getAnnotation(DynamicParameter.class);
+ if (annotation != null) {
+ result.add(new Parameterized(new WrappedParameter((Parameter) annotation), null,
+ null, m));
+ } else if (dynamicParameter != null) {
+ result.add(new Parameterized(new WrappedParameter((DynamicParameter) annotation), null,
+ null, m));
+ } else if (delegateAnnotation != null) {
+ result.add(new Parameterized(null, (ParametersDelegate) delegateAnnotation,
+ null, m));
+ }
+ }
+ cls = cls.getSuperclass();
+ }
+
+ return result;
+ }
+
+ public WrappedParameter getWrappedParameter() {
+ return m_wrappedParameter;
+ }
+
+ public Class<?> getType() {
+ if (m_method != null) {
+ return m_method.getParameterTypes()[0];
+ } else {
+ return m_field.getType();
+ }
+ }
+
+ public String getName() {
+ if (m_method != null) {
+ return m_method.getName();
+ } else {
+ return m_field.getName();
+ }
+ }
+
+ public Object get(Object object) {
+ try {
+ if (m_method != null) {
+ if (m_getter == null) {
+ m_getter = m_method.getDeclaringClass()
+ .getMethod("g" + m_method.getName().substring(1),
+ new Class[0]);
+ }
+ return m_getter.invoke(object);
+ } else {
+ return m_field.get(object);
+ }
+ } catch (SecurityException e) {
+ throw new ParameterException(e);
+ } catch (NoSuchMethodException e) {
+ throw new ParameterException(e);
+ } catch (IllegalArgumentException e) {
+ throw new ParameterException(e);
+ } catch (IllegalAccessException e) {
+ throw new ParameterException(e);
+ } catch (InvocationTargetException e) {
+ throw new ParameterException(e);
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((m_field == null) ? 0 : m_field.hashCode());
+ result = prime * result + ((m_method == null) ? 0 : m_method.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ Parameterized other = (Parameterized) obj;
+ if (m_field == null) {
+ if (other.m_field != null)
+ return false;
+ } else if (!m_field.equals(other.m_field))
+ return false;
+ if (m_method == null) {
+ if (other.m_method != null)
+ return false;
+ } else if (!m_method.equals(other.m_method))
+ return false;
+ return true;
+ }
+
+ public boolean isDynamicParameter(Field field) {
+ if (m_method != null) {
+ return m_method.getAnnotation(DynamicParameter.class) != null;
+ } else {
+ return m_field.getAnnotation(DynamicParameter.class) != null;
+ }
+ }
+
+ public void set(Object object, Object value) {
+ try {
+ if (m_method != null) {
+ m_method.invoke(object, value);
+ } else {
+ m_field.set(object, value);
+ }
+ } catch (IllegalArgumentException ex) {
+ throw new ParameterException(ex);
+ } catch (IllegalAccessException ex) {
+ throw new ParameterException(ex);
+ } catch (InvocationTargetException ex) {
+ throw new ParameterException(ex);
+ }
+ }
+
+ public ParametersDelegate getDelegateAnnotation() {
+ return m_parametersDelegate;
+ }
+
+ public Type getGenericType() {
+ if (m_method != null) {
+ return m_method.getGenericParameterTypes()[0];
+ } else {
+ return m_field.getGenericType();
+ }
+ }
+
+ public Parameter getParameter() {
+ return m_wrappedParameter.getParameter();
+ }
+
+ /**
+ * @return the generic type of the collection for this field, or null if not applicable.
+ */
+ public Type findFieldGenericType() {
+ if (m_method != null) {
+ return null;
+ } else {
+ if (m_field.getGenericType() instanceof ParameterizedType) {
+ ParameterizedType p = (ParameterizedType) m_field.getGenericType();
+ Type cls = p.getActualTypeArguments()[0];
+ if (cls instanceof Class) {
+ return cls;
+ }
+ }
+ }
+
+ return null;
+ }
+
+ public boolean isDynamicParameter() {
+ return m_wrappedParameter.getDynamicParameter() != null;
+ }
+
+}
diff --git a/src/main/java/com/beust/jcommander/WrappedParameter.java b/src/main/java/com/beust/jcommander/WrappedParameter.java
index d49205d..1f690a0 100644
--- a/src/main/java/com/beust/jcommander/WrappedParameter.java
+++ b/src/main/java/com/beust/jcommander/WrappedParameter.java
@@ -1,6 +1,5 @@
package com.beust.jcommander;
-import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
@@ -19,6 +18,14 @@ public class WrappedParameter {
m_dynamicParameter = p;
}
+ public Parameter getParameter() {
+ return m_parameter;
+ }
+
+ public DynamicParameter getDynamicParameter() {
+ return m_dynamicParameter;
+ }
+
public int arity() {
return m_parameter != null ? m_parameter.arity() : 1;
}
@@ -57,10 +64,9 @@ public class WrappedParameter {
return m_parameter != null ? m_parameter.echoInput() : false;
}
- public void addValue(Field field, Object object, Object value)
- throws IllegalArgumentException, IllegalAccessException {
+ public void addValue(Parameterized parameterized, Object object, Object value) {
if (m_parameter != null) {
- field.set(object, value);
+ parameterized.set(object, value);
} else {
String a = m_dynamicParameter.assignment();
String sv = value.toString();
@@ -71,15 +77,15 @@ public class WrappedParameter {
"Dynamic parameter expected a value of the form a" + a + "b"
+ " but got:" + sv);
}
- callPut(object, field, sv.substring(0, aInd), sv.substring(aInd + 1));
+ callPut(object, parameterized, sv.substring(0, aInd), sv.substring(aInd + 1));
}
}
- private void callPut(Object object, Field field, String key, String value) {
+ private void callPut(Object object, Parameterized parameterized, String key, String value) {
try {
Method m;
- m = findPut(field.getType());
- m.invoke(field.get(object), key, value);
+ m = findPut(parameterized.getType());
+ m.invoke(parameterized.get(object), key, value);
} catch (SecurityException e) {
e.printStackTrace();
} catch(IllegalAccessException e) {