1
2
3
4
5
6
7 package org.mule.util.generics;
8
9 import java.lang.annotation.Annotation;
10 import java.lang.reflect.Constructor;
11 import java.lang.reflect.Method;
12 import java.lang.reflect.Type;
13 import java.lang.reflect.TypeVariable;
14 import java.util.HashMap;
15 import java.util.Map;
16
17
18
19
20
21
22
23
24 public class MethodParameter
25 {
26
27 private Method method;
28
29 private Constructor constructor;
30
31 private final int parameterIndex;
32
33 private Class<?> parameterType;
34
35 private Type genericParameterType;
36
37 private Annotation[] parameterAnnotations;
38
39 private ParameterNameDiscoverer parameterNameDiscoverer;
40
41 private String parameterName;
42
43 private int nestingLevel = 1;
44
45
46
47
48 private Map<Integer, Integer> typeIndexesPerLevel;
49
50 Map<TypeVariable, Type> typeVariableMap;
51
52
53
54
55
56
57
58
59 public MethodParameter(Method method, int parameterIndex)
60 {
61 this(method, parameterIndex, 1);
62 }
63
64
65
66
67
68
69
70
71
72
73
74
75 public MethodParameter(Method method, int parameterIndex, int nestingLevel)
76 {
77 this.method = method;
78 this.parameterIndex = parameterIndex;
79 this.nestingLevel = nestingLevel;
80 }
81
82
83
84
85
86
87
88 public MethodParameter(Constructor constructor, int parameterIndex)
89 {
90 this(constructor, parameterIndex, 1);
91 }
92
93
94
95
96
97
98
99
100
101
102 public MethodParameter(Constructor constructor, int parameterIndex, int nestingLevel)
103 {
104 this.constructor = constructor;
105 this.parameterIndex = parameterIndex;
106 this.nestingLevel = nestingLevel;
107 }
108
109
110
111
112
113
114
115 public MethodParameter(MethodParameter original)
116 {
117 this.method = original.method;
118 this.constructor = original.constructor;
119 this.parameterIndex = original.parameterIndex;
120 this.parameterType = original.parameterType;
121 this.parameterAnnotations = original.parameterAnnotations;
122 this.typeVariableMap = original.typeVariableMap;
123 }
124
125
126
127
128
129
130
131
132 public Method getMethod()
133 {
134 return this.method;
135 }
136
137
138
139
140
141
142
143 public Constructor getConstructor()
144 {
145 return this.constructor;
146 }
147
148
149
150
151 public Class getDeclaringClass()
152 {
153 return (this.method != null ? this.method.getDeclaringClass() : this.constructor.getDeclaringClass());
154 }
155
156
157
158
159
160
161 public int getParameterIndex()
162 {
163 return this.parameterIndex;
164 }
165
166
167
168
169 void setParameterType(Class<?> parameterType)
170 {
171 this.parameterType = parameterType;
172 }
173
174
175
176
177
178
179 public Class<?> getParameterType()
180 {
181 if (this.parameterType == null)
182 {
183 if (this.parameterIndex < 0)
184 {
185 this.parameterType = (this.method != null ? this.method.getReturnType() : null);
186 }
187 else
188 {
189 this.parameterType = (this.method != null ?
190 this.method.getParameterTypes()[this.parameterIndex] :
191 this.constructor.getParameterTypes()[this.parameterIndex]);
192 }
193 }
194 return this.parameterType;
195 }
196
197
198
199
200
201
202 public Type getGenericParameterType()
203 {
204 if (this.genericParameterType == null)
205 {
206 if (this.parameterIndex < 0)
207 {
208 this.genericParameterType = (this.method != null ? this.method.getGenericReturnType() : null);
209 }
210 else
211 {
212 this.genericParameterType = (this.method != null ?
213 this.method.getGenericParameterTypes()[this.parameterIndex] :
214 this.constructor.getGenericParameterTypes()[this.parameterIndex]);
215 }
216 }
217 return this.genericParameterType;
218 }
219
220
221
222
223 public Annotation[] getMethodAnnotations()
224 {
225 return (this.method != null ? this.method.getAnnotations() : this.constructor.getAnnotations());
226 }
227
228
229
230
231
232
233
234 @SuppressWarnings("unchecked")
235 public <T extends Annotation> T getMethodAnnotation(Class<T> annotationType)
236 {
237 return (this.method != null ? this.method.getAnnotation(annotationType) :
238 (T) this.constructor.getAnnotation(annotationType));
239 }
240
241
242
243
244 public Annotation[] getParameterAnnotations()
245 {
246 if (this.parameterAnnotations == null)
247 {
248 Annotation[][] annotationArray = (this.method != null ?
249 this.method.getParameterAnnotations() : this.constructor.getParameterAnnotations());
250 this.parameterAnnotations = annotationArray[this.parameterIndex];
251 }
252 return this.parameterAnnotations;
253 }
254
255
256
257
258
259
260
261 @SuppressWarnings("unchecked")
262 public <T extends Annotation> T getParameterAnnotation(Class<T> annotationType)
263 {
264 Annotation[] anns = getParameterAnnotations();
265 for (Annotation ann : anns)
266 {
267 if (annotationType.isInstance(ann))
268 {
269 return (T) ann;
270 }
271 }
272 return null;
273 }
274
275
276
277
278
279
280
281 public void initParameterNameDiscovery(ParameterNameDiscoverer parameterNameDiscoverer)
282 {
283 this.parameterNameDiscoverer = parameterNameDiscoverer;
284 }
285
286
287
288
289
290
291
292
293
294 public String getParameterName()
295 {
296 if (this.parameterNameDiscoverer != null)
297 {
298 String[] parameterNames = (this.method != null ?
299 this.parameterNameDiscoverer.getParameterNames(this.method) :
300 this.parameterNameDiscoverer.getParameterNames(this.constructor));
301 if (parameterNames != null)
302 {
303 this.parameterName = parameterNames[this.parameterIndex];
304 }
305 this.parameterNameDiscoverer = null;
306 }
307 return this.parameterName;
308 }
309
310
311
312
313
314
315 public void increaseNestingLevel()
316 {
317 this.nestingLevel++;
318 }
319
320
321
322
323
324
325 public void decreaseNestingLevel()
326 {
327 getTypeIndexesPerLevel().remove(this.nestingLevel);
328 this.nestingLevel--;
329 }
330
331
332
333
334
335
336 public int getNestingLevel()
337 {
338 return this.nestingLevel;
339 }
340
341
342
343
344
345
346
347
348 public void setTypeIndexForCurrentLevel(int typeIndex)
349 {
350 getTypeIndexesPerLevel().put(this.nestingLevel, typeIndex);
351 }
352
353
354
355
356
357
358
359
360 public Integer getTypeIndexForCurrentLevel()
361 {
362 return getTypeIndexForLevel(this.nestingLevel);
363 }
364
365
366
367
368
369
370
371
372 public Integer getTypeIndexForLevel(int nestingLevel)
373 {
374 return getTypeIndexesPerLevel().get(nestingLevel);
375 }
376
377
378
379
380 private Map<Integer, Integer> getTypeIndexesPerLevel()
381 {
382 if (this.typeIndexesPerLevel == null)
383 {
384 this.typeIndexesPerLevel = new HashMap<Integer, Integer>(4);
385 }
386 return this.typeIndexesPerLevel;
387 }
388
389
390
391
392
393
394
395
396
397
398
399 public static MethodParameter forMethodOrConstructor(Object methodOrConstructor, int parameterIndex)
400 {
401 if (methodOrConstructor instanceof Method)
402 {
403 return new MethodParameter((Method) methodOrConstructor, parameterIndex);
404 }
405 else if (methodOrConstructor instanceof Constructor) {
406 return new MethodParameter((Constructor) methodOrConstructor, parameterIndex);
407 }
408 else {
409 throw new IllegalArgumentException(
410 "Given object [" + methodOrConstructor + "] is neither a Method nor a Constructor");
411 }
412 }
413
414 }