1
1
/*
2
- * Copyright 2002-2013 the original author or authors.
2
+ * Copyright 2002-2015 the original author or authors.
3
3
*
4
4
* Licensed under the Apache License, Version 2.0 (the "License");
5
5
* you may not use this file except in compliance with the License.
42
42
public class ReflectionHelper {
43
43
44
44
/**
45
- * Compare argument arrays and return information about whether they match. A supplied
46
- * type converter and conversionAllowed flag allow for matches to take into account
47
- * that a type may be transformed into a different type by the converter.
48
- * @param expectedArgTypes the array of types the method/constructor is expecting
49
- * @param suppliedArgTypes the array of types that are being supplied at the point of invocation
45
+ * Compare argument arrays and return information about whether they match.
46
+ * A supplied type converter and conversionAllowed flag allow for matches to take
47
+ * into account that a type may be transformed into a different type by the converter.
48
+ * @param expectedArgTypes the types the method/constructor is expecting
49
+ * @param suppliedArgTypes the types that are being supplied at the point of invocation
50
50
* @param typeConverter a registered type converter
51
- * @return a MatchInfo object indicating what kind of match it was or null if it was not a match
51
+ * @return a MatchInfo object indicating what kind of match it was,
52
+ * or {@code null} if it was not a match
52
53
*/
53
54
static ArgumentsMatchInfo compareArguments (
54
55
List <TypeDescriptor > expectedArgTypes , List <TypeDescriptor > suppliedArgTypes , TypeConverter typeConverter ) {
@@ -111,7 +112,7 @@ public static int getTypeDifferenceWeight(List<TypeDescriptor> paramTypes, List<
111
112
int result = 0 ;
112
113
for (int i = 0 ; i < paramTypes .size (); i ++) {
113
114
TypeDescriptor paramType = paramTypes .get (i );
114
- TypeDescriptor argType = argTypes .get (i );
115
+ TypeDescriptor argType = ( i < argTypes .size () ? argTypes . get (i ) : null );
115
116
if (argType == null ) {
116
117
if (paramType .isPrimitive ()) {
117
118
return Integer .MAX_VALUE ;
@@ -148,13 +149,15 @@ else if (ClassUtils.isAssignable(paramTypeClazz, superClass)) {
148
149
}
149
150
150
151
/**
151
- * Compare argument arrays and return information about whether they match. A supplied type converter and
152
- * conversionAllowed flag allow for matches to take into account that a type may be transformed into a different
153
- * type by the converter. This variant of compareArguments also allows for a varargs match.
154
- * @param expectedArgTypes the array of types the method/constructor is expecting
155
- * @param suppliedArgTypes the array of types that are being supplied at the point of invocation
152
+ * Compare argument arrays and return information about whether they match.
153
+ * A supplied type converter and conversionAllowed flag allow for matches to
154
+ * take into account that a type may be transformed into a different type by the
155
+ * converter. This variant of compareArguments also allows for a varargs match.
156
+ * @param expectedArgTypes the types the method/constructor is expecting
157
+ * @param suppliedArgTypes the types that are being supplied at the point of invocation
156
158
* @param typeConverter a registered type converter
157
- * @return a MatchInfo object indicating what kind of match it was or null if it was not a match
159
+ * @return a MatchInfo object indicating what kind of match it was,
160
+ * or {@code null} if it was not a match
158
161
*/
159
162
static ArgumentsMatchInfo compareArgumentsVarargs (
160
163
List <TypeDescriptor > expectedArgTypes , List <TypeDescriptor > suppliedArgTypes , TypeConverter typeConverter ) {
@@ -264,14 +267,15 @@ else if (typeConverter.canConvert(suppliedArg, TypeDescriptor.valueOf(varargsPar
264
267
}
265
268
266
269
/**
267
- * Takes an input set of argument values and, following the positions specified in the int array,
268
- * it converts them to the types specified as the required parameter types. The arguments are
269
- * converted 'in-place' in the input array.
270
+ * Takes an input set of argument values and converts them to the types specified as the
271
+ * required parameter types. The arguments are converted 'in-place' in the input array.
270
272
* @param converter the type converter to use for attempting conversions
271
273
* @param arguments the actual arguments that need conversion
272
274
* @param methodOrCtor the target Method or Constructor
273
- * @param argumentsRequiringConversion details which of the input arguments for sure need conversion
275
+ * @param argumentsRequiringConversion details which of the input arguments need conversion
274
276
* @param varargsPosition the known position of the varargs argument, if any
277
+ * ({@code null} if not varargs)
278
+ * @return {@code true} if some kind of conversion occurred on an argument
275
279
* @throws EvaluationException if a problem occurs during conversion
276
280
*/
277
281
static void convertArguments (TypeConverter converter , Object [] arguments , Object methodOrCtor ,
@@ -285,18 +289,21 @@ static void convertArguments(TypeConverter converter, Object[] arguments, Object
285
289
}
286
290
}
287
291
else {
292
+ // Convert everything up to the varargs position
288
293
for (int i = 0 ; i < varargsPosition ; i ++) {
289
294
TypeDescriptor targetType = new TypeDescriptor (MethodParameter .forMethodOrConstructor (methodOrCtor , i ));
290
295
Object argument = arguments [i ];
291
296
arguments [i ] = converter .convertValue (argument , TypeDescriptor .forObject (argument ), targetType );
292
297
}
293
298
MethodParameter methodParam = MethodParameter .forMethodOrConstructor (methodOrCtor , varargsPosition );
294
299
if (varargsPosition == arguments .length - 1 ) {
300
+ // If the target is varargs and there is just one more argument then convert it here
295
301
TypeDescriptor targetType = new TypeDescriptor (methodParam );
296
302
Object argument = arguments [varargsPosition ];
297
303
arguments [varargsPosition ] = converter .convertValue (argument , TypeDescriptor .forObject (argument ), targetType );
298
304
}
299
305
else {
306
+ // Convert remaining arguments to the varargs element type
300
307
TypeDescriptor targetType = TypeDescriptor .nested (methodParam , 1 );
301
308
for (int i = varargsPosition ; i < arguments .length ; i ++) {
302
309
Object argument = arguments [i ];
@@ -307,12 +314,14 @@ static void convertArguments(TypeConverter converter, Object[] arguments, Object
307
314
}
308
315
309
316
/**
310
- * Convert a supplied set of arguments into the requested types. If the parameterTypes are related to
311
- * a varargs method then the final entry in the parameterTypes array is going to be an array itself whose
312
- * component type should be used as the conversion target for extraneous arguments. (For example, if the
313
- * parameterTypes are {Integer, String[]} and the input arguments are {Integer, boolean, float} then both
314
- * the boolean and float must be converted to strings). This method does not repackage the arguments
315
- * into a form suitable for the varargs invocation
317
+ * Convert a supplied set of arguments into the requested types.
318
+ * If the parameterTypes are related to a varargs method, then the final entry
319
+ * in the parameterTypes array is going to be an array itself whose component type
320
+ * should be used as the conversion target for extraneous arguments. (For example,
321
+ * if the parameterTypes are {@code {Integer, String[]}} and the input arguments
322
+ * are {@code {Integer, boolean, float}} then both the boolean and float must be
323
+ * converted to Strings). This method does not repackage the arguments into a
324
+ * form suitable for the varargs invocation.
316
325
* @param converter the converter to use for type conversions
317
326
* @param arguments the arguments to convert to the requested parameter types
318
327
* @param method the target Method
@@ -359,10 +368,10 @@ public static void convertAllArguments(TypeConverter converter, Object[] argumen
359
368
}
360
369
361
370
/**
362
- * Package up the arguments so that they correctly match what is expected in parameterTypes. For example, if
363
- * parameterTypes is (int, String[]) because the second parameter was declared String... then if arguments is
364
- * [1,"a","b"] then it must be repackaged as [1,new String[]{ "a","b"}] in order to match the expected
365
- * parameterTypes .
371
+ * Package up the arguments so that they correctly match what is expected in parameterTypes.
372
+ * For example, if parameterTypes is {@code (int, String[])} because the second parameter
373
+ * was declared {@code String...}, then if arguments is {@code [1,"a","b"]} then it must be
374
+ * repackaged as {@code [1,new String[]{"a","b"}]} in order to match the expected types .
366
375
* @param requiredParameterTypes the types of the parameters for the invocation
367
376
* @param args the arguments to be setup ready for the invocation
368
377
* @return a repackaged array of arguments where any varargs setup has been done
@@ -372,7 +381,7 @@ public static Object[] setupArgumentsForVarargsInvocation(Class<?>[] requiredPar
372
381
int parameterCount = requiredParameterTypes .length ;
373
382
int argumentCount = args .length ;
374
383
375
- // Check if repackaging is needed:
384
+ // Check if repackaging is needed...
376
385
if (parameterCount != args .length ||
377
386
requiredParameterTypes [parameterCount - 1 ] !=
378
387
(args [argumentCount - 1 ] != null ? args [argumentCount - 1 ].getClass () : null )) {
@@ -421,10 +430,11 @@ public static enum ArgsMatchKind {
421
430
422
431
423
432
/**
424
- * An instance of ArgumentsMatchInfo describes what kind of match was achieved between two sets of arguments -
425
- * the set that a method/constructor is expecting and the set that are being supplied at the point of invocation.
426
- * If the kind indicates that conversion is required for some of the arguments then the arguments that require
427
- * conversion are listed in the argsRequiringConversion array.
433
+ * An instance of ArgumentsMatchInfo describes what kind of match was achieved
434
+ * between two sets of arguments - the set that a method/constructor is expecting
435
+ * and the set that are being supplied at the point of invocation. If the kind
436
+ * indicates that conversion is required for some of the arguments then the arguments
437
+ * that require conversion are listed in the argsRequiringConversion array.
428
438
*/
429
439
public static class ArgumentsMatchInfo {
430
440
0 commit comments