1package com.beust.jcommander; 2 3import com.beust.jcommander.internal.Lists; 4 5import java.lang.annotation.Annotation; 6import java.lang.reflect.Field; 7import java.lang.reflect.InvocationTargetException; 8import java.lang.reflect.Method; 9import java.lang.reflect.ParameterizedType; 10import java.lang.reflect.Type; 11import java.util.List; 12 13/** 14 * Encapsulate a field or a method annotated with @Parameter or @DynamicParameter 15 */ 16public class Parameterized { 17 18 // Either a method or a field 19 private Field m_field; 20 private Method m_method; 21 private Method m_getter; 22 23 // Either of these two 24 private WrappedParameter m_wrappedParameter; 25 private ParametersDelegate m_parametersDelegate; 26 27 public Parameterized(WrappedParameter wp, ParametersDelegate pd, 28 Field field, Method method) { 29 m_wrappedParameter = wp; 30 m_method = method; 31 m_field = field; 32 if (m_field != null) { 33 m_field.setAccessible(true); 34 } 35 m_parametersDelegate = pd; 36 } 37 38 public static List<Parameterized> parseArg(Object arg) { 39 List<Parameterized> result = Lists.newArrayList(); 40 41 Class<? extends Object> cls = arg.getClass(); 42 while (!Object.class.equals(cls)) { 43 for (Field f : cls.getDeclaredFields()) { 44 Annotation annotation = f.getAnnotation(Parameter.class); 45 Annotation delegateAnnotation = f.getAnnotation(ParametersDelegate.class); 46 Annotation dynamicParameter = f.getAnnotation(DynamicParameter.class); 47 if (annotation != null) { 48 result.add(new Parameterized(new WrappedParameter((Parameter) annotation), null, 49 f, null)); 50 } else if (dynamicParameter != null) { 51 result.add(new Parameterized(new WrappedParameter((DynamicParameter) dynamicParameter), null, 52 f, null)); 53 } else if (delegateAnnotation != null) { 54 result.add(new Parameterized(null, (ParametersDelegate) delegateAnnotation, 55 f, null)); 56 } 57 } 58 cls = cls.getSuperclass(); 59 } 60 61 // Reassigning 62 cls = arg.getClass(); 63 while (!Object.class.equals(cls)) { 64 for (Method m : cls.getDeclaredMethods()) { 65 Annotation annotation = m.getAnnotation(Parameter.class); 66 Annotation delegateAnnotation = m.getAnnotation(ParametersDelegate.class); 67 Annotation dynamicParameter = m.getAnnotation(DynamicParameter.class); 68 if (annotation != null) { 69 result.add(new Parameterized(new WrappedParameter((Parameter) annotation), null, 70 null, m)); 71 } else if (dynamicParameter != null) { 72 result.add(new Parameterized(new WrappedParameter((DynamicParameter) annotation), null, 73 null, m)); 74 } else if (delegateAnnotation != null) { 75 result.add(new Parameterized(null, (ParametersDelegate) delegateAnnotation, 76 null, m)); 77 } 78 } 79 cls = cls.getSuperclass(); 80 } 81 82 return result; 83 } 84 85 public WrappedParameter getWrappedParameter() { 86 return m_wrappedParameter; 87 } 88 89 public Class<?> getType() { 90 if (m_method != null) { 91 return m_method.getParameterTypes()[0]; 92 } else { 93 return m_field.getType(); 94 } 95 } 96 97 public String getName() { 98 if (m_method != null) { 99 return m_method.getName(); 100 } else { 101 return m_field.getName(); 102 } 103 } 104 105 public Object get(Object object) { 106 try { 107 if (m_method != null) { 108 if (m_getter == null) { 109 m_getter = m_method.getDeclaringClass() 110 .getMethod("g" + m_method.getName().substring(1), 111 new Class[0]); 112 } 113 return m_getter.invoke(object); 114 } else { 115 return m_field.get(object); 116 } 117 } catch (SecurityException e) { 118 throw new ParameterException(e); 119 } catch (NoSuchMethodException e) { 120 // Try to find a field 121 String name = m_method.getName(); 122 String fieldName = Character.toLowerCase(name.charAt(3)) + name.substring(4); 123 Object result = null; 124 try { 125 Field field = m_method.getDeclaringClass().getDeclaredField(fieldName); 126 if (field != null) { 127 field.setAccessible(true); 128 result = field.get(object); 129 } 130 } catch(NoSuchFieldException ex) { 131 // ignore 132 } catch(IllegalAccessException ex) { 133 // ignore 134 } 135 return result; 136 } catch (IllegalArgumentException e) { 137 throw new ParameterException(e); 138 } catch (IllegalAccessException e) { 139 throw new ParameterException(e); 140 } catch (InvocationTargetException e) { 141 throw new ParameterException(e); 142 } 143 } 144 145 @Override 146 public int hashCode() { 147 final int prime = 31; 148 int result = 1; 149 result = prime * result + ((m_field == null) ? 0 : m_field.hashCode()); 150 result = prime * result + ((m_method == null) ? 0 : m_method.hashCode()); 151 return result; 152 } 153 154 @Override 155 public boolean equals(Object obj) { 156 if (this == obj) 157 return true; 158 if (obj == null) 159 return false; 160 if (getClass() != obj.getClass()) 161 return false; 162 Parameterized other = (Parameterized) obj; 163 if (m_field == null) { 164 if (other.m_field != null) 165 return false; 166 } else if (!m_field.equals(other.m_field)) 167 return false; 168 if (m_method == null) { 169 if (other.m_method != null) 170 return false; 171 } else if (!m_method.equals(other.m_method)) 172 return false; 173 return true; 174 } 175 176 public boolean isDynamicParameter(Field field) { 177 if (m_method != null) { 178 return m_method.getAnnotation(DynamicParameter.class) != null; 179 } else { 180 return m_field.getAnnotation(DynamicParameter.class) != null; 181 } 182 } 183 184 public void set(Object object, Object value) { 185 try { 186 if (m_method != null) { 187 m_method.invoke(object, value); 188 } else { 189 m_field.set(object, value); 190 } 191 } catch (IllegalArgumentException ex) { 192 throw new ParameterException(ex); 193 } catch (IllegalAccessException ex) { 194 throw new ParameterException(ex); 195 } catch (InvocationTargetException ex) { 196 // If a ParameterException was thrown, don't wrap it into another one 197 if (ex.getTargetException() instanceof ParameterException) { 198 throw (ParameterException) ex.getTargetException(); 199 } else { 200 throw new ParameterException(ex); 201 } 202 } 203 } 204 205 public ParametersDelegate getDelegateAnnotation() { 206 return m_parametersDelegate; 207 } 208 209 public Type getGenericType() { 210 if (m_method != null) { 211 return m_method.getGenericParameterTypes()[0]; 212 } else { 213 return m_field.getGenericType(); 214 } 215 } 216 217 public Parameter getParameter() { 218 return m_wrappedParameter.getParameter(); 219 } 220 221 /** 222 * @return the generic type of the collection for this field, or null if not applicable. 223 */ 224 public Type findFieldGenericType() { 225 if (m_method != null) { 226 return null; 227 } else { 228 if (m_field.getGenericType() instanceof ParameterizedType) { 229 ParameterizedType p = (ParameterizedType) m_field.getGenericType(); 230 Type cls = p.getActualTypeArguments()[0]; 231 if (cls instanceof Class) { 232 return cls; 233 } 234 } 235 } 236 237 return null; 238 } 239 240 public boolean isDynamicParameter() { 241 return m_wrappedParameter.getDynamicParameter() != null; 242 } 243 244} 245