1 package net.sf.twip.parameterhandler;
2
3 import java.lang.reflect.*;
4 import java.util.*;
5
6 import net.sf.twip.*;
7 import net.sf.twip.internal.*;
8 import net.sf.twip.util.Parameter;
9
10
11
12
13
14
15
16 public abstract class ParameterHandler {
17
18 public static ParameterHandler of(Parameter parameter) {
19 final Class<?> type = parameter.getType();
20 if (type.isEnum()) {
21 return new EnumParameterHandler(parameter);
22 } else if (Boolean.class.isAssignableFrom(type) || Boolean.TYPE.equals(type)) {
23 return new BooleanParameterHandler(parameter);
24 } else if (Byte.class.isAssignableFrom(type) || Byte.TYPE.equals(type)) {
25 return new ByteParameterHandler(parameter);
26 } else if (Character.class.isAssignableFrom(type) || Character.TYPE.equals(type)) {
27 return new CharacterParameterHandler(parameter);
28 } else if (Double.class.isAssignableFrom(type) || Double.TYPE.equals(type)) {
29 return new DoubleParameterHandler(parameter);
30 } else if (Float.class.isAssignableFrom(type) || Float.TYPE.equals(type)) {
31 return new FloatParameterHandler(parameter);
32 } else if (Integer.class.isAssignableFrom(type) || Integer.TYPE.equals(type)) {
33 return new IntegerParameterHandler(parameter);
34 } else if (Long.class.isAssignableFrom(type) || Long.TYPE.equals(type)) {
35 return new LongParameterHandler(parameter);
36 } else if (Short.class.isAssignableFrom(type) || Short.TYPE.equals(type)) {
37 return new ShortParameterHandler(parameter);
38 } else if (String.class.isAssignableFrom(type)) {
39 return new StringParameterHandler(parameter);
40 } else {
41 return new AutoTwipParameterHandler(parameter);
42 }
43 }
44
45 protected final Parameter parameter;
46
47 public ParameterHandler(Parameter parameter) {
48 this.parameter = parameter;
49 }
50
51
52
53
54
55 private Object[] getAnnotatedValues() {
56 final String name = parameter.getAnnotation(Values.class).value();
57 try {
58 final Field field = parameter.getMethod().getDeclaringClass().getField(name);
59 if (!Modifier.isStatic(field.getModifiers()))
60 throw new TwipConfigurationErrorNonStatic("the field '" + name
61 + "' named in the @Values annotation of " + parameter + " must be static.");
62 if (field.getType().isArray()) {
63 if (field.getType().getComponentType().isPrimitive())
64 throw new TwipConfigurationErrorNonPrimitive("the values of the field '" + name
65 + "' named in the @Values annotation of " + parameter
66 + " must not be primitives.");
67 final Object[] result = (Object[]) field.get(null);
68 if (result == null)
69 throw new TwipConfigurationErrorNullPointer("the field '" + name
70 + "' named in the @Values annotation of " + parameter + " is null");
71 return result;
72 } else if (Collection.class.isAssignableFrom(field.getType())) {
73 final Collection<?> result = (Collection<?>) field.get(null);
74 if (result == null)
75 throw new TwipConfigurationErrorNullPointer("the field '" + name
76 + "' named in the @Values annotation of " + parameter + " is null");
77 return result.toArray();
78 } else {
79 throw new TwipConfigurationErrorNotArrayOrCollection("the field '" + name
80 + "' named in the @Values annotation of " + parameter
81 + " must be an array or collection.");
82 }
83 } catch (final IllegalAccessException e) {
84 throw new TwipConfigurationErrorGettingField("can't access field '" + name
85 + "' named in the @Values annotation of " + parameter, e);
86 } catch (final NoSuchFieldException ex) {
87 try {
88 final Method method = parameter.getMethod().getDeclaringClass().getMethod(name);
89 if (!Modifier.isStatic(method.getModifiers()))
90 throw new TwipConfigurationErrorNonStatic("the method '" + name
91 + "' named in the @Values annotation of " + parameter
92 + " must be static.");
93 if (method.getReturnType().isArray()) {
94 if (method.getReturnType().getComponentType().isPrimitive())
95 throw new TwipConfigurationErrorNonPrimitive(
96 "the values returned by the method '" + name
97 + "' named in the @Values annotation of " + parameter
98 + " must not be primitives.");
99 final Object[] result = (Object[]) method.invoke(null);
100 if (result == null)
101 throw new TwipConfigurationErrorNullPointer("the method '" + name
102 + "' named in the @Values annotation of " + parameter
103 + " returns null");
104 return result;
105 } else if (Collection.class.isAssignableFrom(method.getReturnType())) {
106 final Collection<?> collection = (Collection<?>) method.invoke(null);
107 if (collection == null)
108 throw new TwipConfigurationErrorNullPointer("the method '" + name
109 + "' named in the @Values annotation of " + parameter
110 + " returns null.");
111 return collection.toArray();
112 } else {
113 throw new TwipConfigurationErrorNotArrayOrCollection("the method '" + name
114 + "' named in the @Values annotation of " + parameter
115 + " must return an array or collection.");
116 }
117 } catch (final IllegalAccessException e) {
118 throw new TwipConfigurationErrorCallingMethod("can't access the method '" + name
119 + "' named in the @Values annotation of " + parameter, e);
120 } catch (final NoSuchMethodException e) {
121 throw new TwipConfigurationErrorNoSuchMethod("there is no method or field '" + name
122 + "' named in the @Values annotation of " + parameter, e);
123 } catch (final InvocationTargetException e) {
124 throw new TwipConfigurationErrorCallingMethod("can't invoke method '" + name
125 + "' named in the @Values annotation of " + parameter, e);
126 }
127 }
128 }
129
130 protected abstract Object[] getDefaultParameterValues();
131
132 public Object[] getParameterValues() {
133 final Object[] values = (parameter.isAnnotationPresent(Values.class)) ? getAnnotatedValues()
134 : getDefaultParameterValues();
135 if (!parameter.isAnnotationPresent(Assume.class))
136 return values;
137 final List<Object> result = new ArrayList<Object>();
138 for (final Object value : values) {
139 if (test(value)) {
140 result.add(value);
141 }
142 }
143 if (!parameter.isAnnotationPresent(NotNull.class) && !parameter.getType().isPrimitive()) {
144 result.add(null);
145 }
146 return result.toArray();
147 }
148
149
150
151
152
153
154
155 protected boolean test(Object value) {
156 return true;
157 }
158 }