diff options
author | Cedric Beust <cedric@beust.com> | 2012-06-24 15:12:31 -0700 |
---|---|---|
committer | Cedric Beust <cedric@beust.com> | 2012-06-24 15:12:31 -0700 |
commit | 369d387138b6da9e77e01d82273ef6271580eb47 (patch) | |
tree | 1b6467c94e100e86c111b7f1e185d40f7a96a2cd /src/main/java/com/beust | |
parent | 0975e46cbf9e8aa7febc03dc38be47c19b408371 (diff) | |
download | platform_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')
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) { |