diff options
Diffstat (limited to 'src/main/java/com/beust/jcommander/ParameterDescription.java')
-rw-r--r-- | src/main/java/com/beust/jcommander/ParameterDescription.java | 265 |
1 files changed, 165 insertions, 100 deletions
diff --git a/src/main/java/com/beust/jcommander/ParameterDescription.java b/src/main/java/com/beust/jcommander/ParameterDescription.java index 2ef2d5f..bed5ba1 100644 --- a/src/main/java/com/beust/jcommander/ParameterDescription.java +++ b/src/main/java/com/beust/jcommander/ParameterDescription.java @@ -21,36 +21,28 @@ package com.beust.jcommander; import com.beust.jcommander.validators.NoValidator; import com.beust.jcommander.validators.NoValueValidator; -import java.util.ArrayList; -import java.util.Collection; -import java.util.EnumSet; -import java.util.HashSet; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Locale; -import java.util.Map; +import java.lang.annotation.Annotation; +import java.lang.reflect.Field; +import java.util.*; import java.util.ResourceBundle; -import java.util.Set; -import java.util.SortedSet; -import java.util.TreeSet; public class ParameterDescription { - private Object m_object; + private Object object; - private WrappedParameter m_wrappedParameter; - private Parameter m_parameterAnnotation; - private DynamicParameter m_dynamicParameterAnnotation; + private WrappedParameter wrappedParameter; + private Parameter parameterAnnotation; + private DynamicParameter dynamicParameterAnnotation; /** The field/method */ - private Parameterized m_parameterized; + private Parameterized parameterized; /** Keep track of whether a value was added to flag an error */ - private boolean m_assigned = false; - private ResourceBundle m_bundle; - private String m_description; - private JCommander m_jCommander; - private Object m_default; + private boolean assigned = false; + private ResourceBundle bundle; + private String description; + private JCommander jCommander; + private Object defaultObject; /** Longest of the names(), used to present usage() alphabetically */ - private String m_longestName = ""; + private String longestName = ""; public ParameterDescription(Object object, DynamicParameter annotation, Parameterized parameterized, @@ -61,15 +53,15 @@ public class ParameterDescription { + "Map but is " + parameterized.getType().getName()); } - m_dynamicParameterAnnotation = annotation; - m_wrappedParameter = new WrappedParameter(m_dynamicParameterAnnotation); + dynamicParameterAnnotation = annotation; + wrappedParameter = new WrappedParameter(dynamicParameterAnnotation); init(object, parameterized, bundle, jc); } public ParameterDescription(Object object, Parameter annotation, Parameterized parameterized, ResourceBundle bundle, JCommander jc) { - m_parameterAnnotation = annotation; - m_wrappedParameter = new WrappedParameter(m_parameterAnnotation); + parameterAnnotation = annotation; + wrappedParameter = new WrappedParameter(parameterAnnotation); init(object, parameterized, bundle, jc); } @@ -100,90 +92,86 @@ public class ParameterDescription { } private void initDescription(String description, String descriptionKey, String[] names) { - m_description = description; + this.description = description; if (! "".equals(descriptionKey)) { - if (m_bundle != null) { - m_description = m_bundle.getString(descriptionKey); - } else { -// JCommander.getConsole().println("Warning: field " + object.getClass() + "." + field.getName() -// + " has a descriptionKey but no bundle was defined with @ResourceBundle, using " + -// "default description:'" + m_description + "'"); + if (bundle != null) { + this.description = bundle.getString(descriptionKey); } } for (String name : names) { - if (name.length() > m_longestName.length()) m_longestName = name; + if (name.length() > longestName.length()) longestName = name; } } @SuppressWarnings("unchecked") private void init(Object object, Parameterized parameterized, ResourceBundle bundle, JCommander jCommander) { - m_object = object; - m_parameterized = parameterized; - m_bundle = bundle; - if (m_bundle == null) { - m_bundle = findResourceBundle(object); + this.object = object; + this.parameterized = parameterized; + this.bundle = bundle; + if (this.bundle == null) { + this.bundle = findResourceBundle(object); } - m_jCommander = jCommander; + this.jCommander = jCommander; - if (m_parameterAnnotation != null) { + if (parameterAnnotation != null) { String description; if (Enum.class.isAssignableFrom(parameterized.getType()) - && m_parameterAnnotation.description().isEmpty()) { + && parameterAnnotation.description().isEmpty()) { description = "Options: " + EnumSet.allOf((Class<? extends Enum>) parameterized.getType()); }else { - description = m_parameterAnnotation.description(); + description = parameterAnnotation.description(); } - initDescription(description, m_parameterAnnotation.descriptionKey(), - m_parameterAnnotation.names()); - } else if (m_dynamicParameterAnnotation != null) { - initDescription(m_dynamicParameterAnnotation.description(), - m_dynamicParameterAnnotation.descriptionKey(), - m_dynamicParameterAnnotation.names()); + initDescription(description, parameterAnnotation.descriptionKey(), + parameterAnnotation.names()); + } else if (dynamicParameterAnnotation != null) { + initDescription(dynamicParameterAnnotation.description(), + dynamicParameterAnnotation.descriptionKey(), + dynamicParameterAnnotation.names()); } else { throw new AssertionError("Shound never happen"); } try { - m_default = parameterized.get(object); + defaultObject = parameterized.get(object); } catch (Exception e) { } // // Validate default values, if any and if applicable // - if (m_default != null) { - if (m_parameterAnnotation != null) { - validateDefaultValues(m_parameterAnnotation.names()); + if (defaultObject != null) { + if (parameterAnnotation != null) { + validateDefaultValues(parameterAnnotation.names()); } } } private void validateDefaultValues(String[] names) { String name = names.length > 0 ? names[0] : ""; - validateValueParameter(name, m_default); + validateValueParameter(name, defaultObject); } public String getLongestName() { - return m_longestName; + return longestName; } public Object getDefault() { - return m_default; + return defaultObject; } public String getDescription() { - return m_description; + return description; } public Object getObject() { - return m_object; + return object; } public String getNames() { StringBuilder sb = new StringBuilder(); - String[] names = m_wrappedParameter.names(); + String[] names = wrappedParameter.names(); for (int i = 0; i < names.length; i++) { if (i > 0) sb.append(", "); sb.append(names[i]); @@ -192,17 +180,17 @@ public class ParameterDescription { } public WrappedParameter getParameter() { - return m_wrappedParameter; + return wrappedParameter; } public Parameterized getParameterized() { - return m_parameterized; + return parameterized; } private boolean isMultiOption() { - Class<?> fieldType = m_parameterized.getType(); + Class<?> fieldType = parameterized.getType(); return fieldType.equals(List.class) || fieldType.equals(Set.class) - || m_parameterized.isDynamicParameter(); + || parameterized.isDynamicParameter(); } public void addValue(String value) { @@ -213,12 +201,12 @@ public class ParameterDescription { * @return true if this parameter received a value during the parsing phase. */ public boolean isAssigned() { - return m_assigned; + return assigned; } public void setAssigned(boolean b) { - m_assigned = b; + assigned = b; } /** @@ -227,52 +215,132 @@ public class ParameterDescription { * converter, and if we can't find any, throw an exception. */ public void addValue(String value, boolean isDefault) { + addValue(null, value, isDefault, true, -1); + } + + Object addValue(String name, String value, boolean isDefault, boolean validate, int currentIndex) { p("Adding " + (isDefault ? "default " : "") + "value:" + value - + " to parameter:" + m_parameterized.getName()); - String name = m_wrappedParameter.names()[0]; - if (m_assigned && ! isMultiOption() && !m_jCommander.isParameterOverwritingAllowed() || isNonOverwritableForced()) { + + " to parameter:" + parameterized.getName()); + if(name == null) { + name = wrappedParameter.names()[0]; + } + if (currentIndex == 00 && assigned && ! isMultiOption() && !jCommander.isParameterOverwritingAllowed() + || isNonOverwritableForced()) { throw new ParameterException("Can only specify option " + name + " once."); } - validateParameter(name, value); + if (validate) { + validateParameter(name, value); + } - Class<?> type = m_parameterized.getType(); + Class<?> type = parameterized.getType(); - Object convertedValue = m_jCommander.convertValue(this, value); - validateValueParameter(name, convertedValue); + Object convertedValue = jCommander.convertValue(getParameterized(), getParameterized().getType(), name, value); + if (validate) { + validateValueParameter(name, convertedValue); + } boolean isCollection = Collection.class.isAssignableFrom(type); + Object finalValue; if (isCollection) { @SuppressWarnings("unchecked") - Collection<Object> l = (Collection<Object>) m_parameterized.get(m_object); + Collection<Object> l = (Collection<Object>) parameterized.get(object); if (l == null || fieldIsSetForTheFirstTime(isDefault)) { - l = newCollection(type); - m_parameterized.set(m_object, l); + l = newCollection(type); + parameterized.set(object, l); } if (convertedValue instanceof Collection) { - l.addAll((Collection) convertedValue); - } else { // if (isMainParameter || m_parameterAnnotation.arity() > 1) { - l.add(convertedValue); -// } else { -// l. + l.addAll((Collection) convertedValue); + } else { + l.add(convertedValue); } + finalValue = l; } else { - m_wrappedParameter.addValue(m_parameterized, m_object, convertedValue); + // If the field type is not a collection, see if it's a type that contains @SubParameters annotations + List<SubParameterIndex> subParameters = findSubParameters(type); + if (! subParameters.isEmpty()) { + // @SubParameters found + finalValue = handleSubParameters(value, currentIndex, type, subParameters); + } else { + // No, regular parameter + wrappedParameter.addValue(parameterized, object, convertedValue); + finalValue = convertedValue; + } } - if (! isDefault) m_assigned = true; + if (! isDefault) assigned = true; + + return finalValue; + } + + private Object handleSubParameters(String value, int currentIndex, Class<?> type, + List<SubParameterIndex> subParameters) { + Object finalValue;// Yes, assign each following argument to the corresponding field of that object + SubParameterIndex sai = null; + for (SubParameterIndex si: subParameters) { + if (si.order == currentIndex) { + sai = si; + break; + } + } + if (sai != null) { + Object objectValue = parameterized.get(object); + try { + if (objectValue == null) { + objectValue = type.newInstance(); + parameterized.set(object, objectValue); + } + wrappedParameter.addValue(parameterized, objectValue, value, sai.field); + finalValue = objectValue; + } catch (InstantiationException | IllegalAccessException e) { + throw new ParameterException("Couldn't instantiate " + type, e); + } + } else { + throw new ParameterException("Couldn't find where to assign parameter " + value + " in " + type); + } + return finalValue; + } + + public Parameter getParameterAnnotation() { + return parameterAnnotation; + } + + class SubParameterIndex { + int order = -1; + Field field; + + public SubParameterIndex(int order, Field field) { + this.order = order; + this.field = field; + } + } + + private List<SubParameterIndex> findSubParameters(Class<?> type) { + List<SubParameterIndex> result = new ArrayList<>(); + for (Field field: type.getDeclaredFields()) { + Annotation subParameter = field.getAnnotation(SubParameter.class); + if (subParameter != null) { + SubParameter sa = (SubParameter) subParameter; + result.add(new SubParameterIndex(sa.order(), field)); + } + } + return result; } private void validateParameter(String name, String value) { - Class<? extends IParameterValidator> validator = m_wrappedParameter.validateWith(); - if (validator != null) { - validateParameter(this, validator, name, value); + final Class<? extends IParameterValidator> validators[] = wrappedParameter.validateWith(); + if (validators != null && validators.length > 0) { + for(final Class<? extends IParameterValidator> validator: validators) { + validateParameter(this, validator, name, value); + } } } - private void validateValueParameter(String name, Object value) { - Class<? extends IValueValidator> validator = m_wrappedParameter.validateValueWith(); - if (validator != null) { - validateValueParameter(validator, name, value); + void validateValueParameter(String name, Object value) { + final Class<? extends IValueValidator> validators[] = wrappedParameter.validateValueWith(); + if (validators != null && validators.length > 0) { + for(final Class<? extends IValueValidator> validator: validators) { + validateValueParameter(validator, name, value); + } } } @@ -283,9 +351,7 @@ public class ParameterDescription { p("Validating value parameter:" + name + " value:" + value + " validator:" + validator); } validator.newInstance().validate(name, value); - } catch (InstantiationException e) { - throw new ParameterException("Can't instantiate validator:" + e); - } catch (IllegalAccessException e) { + } catch (InstantiationException | IllegalAccessException e) { throw new ParameterException("Can't instantiate validator:" + e); } } @@ -294,6 +360,7 @@ public class ParameterDescription { Class<? extends IParameterValidator> validator, String name, String value) { try { + if (validator != NoValidator.class) { p("Validating parameter:" + name + " value:" + value + " validator:" + validator); } @@ -302,9 +369,7 @@ public class ParameterDescription { IParameterValidator2 instance = (IParameterValidator2) validator.newInstance(); instance.validate(name, value, pd); } - } catch (InstantiationException e) { - throw new ParameterException("Can't instantiate validator:" + e); - } catch (IllegalAccessException e) { + } catch (InstantiationException | IllegalAccessException e) { throw new ParameterException("Can't instantiate validator:" + e); } catch(ParameterException ex) { throw ex; @@ -336,7 +401,7 @@ public class ParameterDescription { * being added to the field. */ private boolean fieldIsSetForTheFirstTime(boolean isDefault) { - return (!isDefault && !m_assigned); + return (!isDefault && !assigned); } private static void p(String string) { @@ -347,18 +412,18 @@ public class ParameterDescription { @Override public String toString() { - return "[ParameterDescription " + m_parameterized.getName() + "]"; + return "[ParameterDescription " + parameterized.getName() + "]"; } public boolean isDynamicParameter() { - return m_dynamicParameterAnnotation != null; + return dynamicParameterAnnotation != null; } public boolean isHelp() { - return m_wrappedParameter.isHelp(); + return wrappedParameter.isHelp(); } public boolean isNonOverwritableForced() { - return m_wrappedParameter.isNonOverwritableForced(); + return wrappedParameter.isNonOverwritableForced(); } } |