in velocity-engine-core/src/main/java/org/apache/velocity/util/introspection/MethodMap.java [534:648]
private int getApplicability(Method method, Class<?>[] classes)
{
Type[] methodArgs = method.getGenericParameterTypes();
int ret = STRICTLY_CONVERTIBLE;
if (methodArgs.length > classes.length)
{
// if there's just one more methodArg than class arg
// and the last methodArg is an array, then treat it as a vararg
if (methodArgs.length == classes.length + 1 && TypeUtils.isArrayType(methodArgs[methodArgs.length - 1]))
{
// all the args preceding the vararg must match
for (int i = 0; i < classes.length; i++)
{
if (!isStrictConvertible(methodArgs[i], classes[i], false))
{
if (isConvertible(methodArgs[i], classes[i], false))
{
ret = Math.min(ret, IMPLCITLY_CONVERTIBLE);
}
else if (isExplicitlyConvertible(methodArgs[i], classes[i], false))
{
ret = Math.min(ret, EXPLICITLY_CONVERTIBLE);
}
else
{
return NOT_CONVERTIBLE;
}
}
}
return ret;
}
else
{
return NOT_CONVERTIBLE;
}
}
else if (methodArgs.length == classes.length)
{
// this will properly match when the last methodArg
// is an array/varargs and the last class is the type of array
// (e.g. String when the method is expecting String...)
for(int i = 0; i < classes.length; ++i)
{
boolean possibleVararg = i == classes.length - 1 && TypeUtils.isArrayType(methodArgs[i]);
if (!isStrictConvertible(methodArgs[i], classes[i], possibleVararg))
{
if (isConvertible(methodArgs[i], classes[i], possibleVararg))
{
ret = Math.min(ret, IMPLCITLY_CONVERTIBLE);
}
else if (isExplicitlyConvertible(methodArgs[i], classes[i], possibleVararg))
{
ret = Math.min(ret, EXPLICITLY_CONVERTIBLE);
}
else
{
return NOT_CONVERTIBLE;
}
}
}
return ret;
}
else if (methodArgs.length > 0) // more arguments given than the method accepts; check for varargs
{
// check that the last methodArg is an array
Type lastarg = methodArgs[methodArgs.length - 1];
if (!TypeUtils.isArrayType(lastarg))
{
return NOT_CONVERTIBLE;
}
// check that they all match up to the last method arg component type
for (int i = 0; i < methodArgs.length - 1; ++i)
{
if (!isStrictConvertible(methodArgs[i], classes[i], false))
{
if (isConvertible(methodArgs[i], classes[i], false))
{
ret = Math.min(ret, IMPLCITLY_CONVERTIBLE);
}
else if (isExplicitlyConvertible(methodArgs[i], classes[i], false))
{
ret = Math.min(ret, EXPLICITLY_CONVERTIBLE);
}
else
{
return NOT_CONVERTIBLE;
}
}
}
// check that all remaining arguments are convertible to the vararg type
Type vararg = TypeUtils.getArrayComponentType(lastarg);
for (int i = methodArgs.length - 1; i < classes.length; ++i)
{
if (!isStrictConvertible(vararg, classes[i], false))
{
if (isConvertible(vararg, classes[i], false))
{
ret = Math.min(ret, IMPLCITLY_CONVERTIBLE);
}
else if (isExplicitlyConvertible(vararg, classes[i], false))
{
ret = Math.min(ret, EXPLICITLY_CONVERTIBLE);
}
else
{
return NOT_CONVERTIBLE;
}
}
}
return ret;
}
return NOT_CONVERTIBLE;
}