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