/**
* jetbrick-template
* http://subchen.github.io/jetbrick-template/
*
* Copyright 2010-2014 Guoqiang Chen. All rights reserved.
* Email: subchen@gmail.com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package jetbrick.template.parser.support;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;
public class MethodFinderUtils {
/**
* 根据参数类型,查找最匹配的方法。
*/
public static Method lookupMethod(Class<?> clazz, String methodName, Class<?>... parameterTypes) {
try {
// find matching method
return clazz.getMethod(methodName, parameterTypes);
} catch (NoSuchMethodException e) {
return lookupBestMethod(Arrays.asList(clazz.getMethods()), methodName, parameterTypes);
}
}
public static Method lookupBestMethod(List<Method> methods, String methodName, Class<?>... parameterTypes) {
Method best = null;
for (Method method : methods) {
if (!method.getName().equals(methodName)) continue;
Class<?>[] types = method.getParameterTypes();
if (isParameterTypesCampatible(types, parameterTypes, method.isVarArgs(), false)) {
// 可能有多个方法与实际参数类型兼容。采用就近兼容原则。
if (best == null) {
best = method;
} else if (best.isVarArgs() && (!method.isVarArgs())) {
best = method; // 不可变参数的函数优先
} else if ((!best.isVarArgs()) && method.isVarArgs()) {
// no change
} else if (isParameterTypesCampatible(best.getParameterTypes(), types, best.isVarArgs(), method.isVarArgs())) {
best = method;
}
}
}
return best;
}
/**
* 根据参数类型,查找最匹配的构造函数。
*/
public static Constructor<?> lookupConstructor(Class<?> clazz, Class<?>... parameterTypes) {
try {
// find matching constructor
return clazz.getConstructor(parameterTypes);
} catch (NoSuchMethodException e) {
Constructor<?> best = null;
for (Constructor<?> constructor : clazz.getConstructors()) {
Class<?>[] types = constructor.getParameterTypes();
if (isParameterTypesCampatible(types, parameterTypes, constructor.isVarArgs(), false)) {
// 可能有多个方法与实际参数类型兼容。采用就近兼容原则。
if (best == null) {
best = constructor;
} else if (best.isVarArgs() && (!constructor.isVarArgs())) {
best = constructor; // 不可变参数的函数优先
} else if ((!best.isVarArgs()) && constructor.isVarArgs()) {
// no change
} else if (isParameterTypesCampatible(best.getParameterTypes(), types, best.isVarArgs(), constructor.isVarArgs())) {
best = constructor;
}
}
}
return best;
}
}
/**
* 判断参数列表是否兼容, 支持可变参数
*/
public static boolean isParameterTypesCampatible(Class<?>[] lhs, Class<?>[] rhs, boolean lhsVarArgs, boolean rhsVarArgs) {
if (lhs == null) {
return rhs == null || rhs.length == 0;
}
if (rhs == null) {
return lhs.length == 0;
}
if (lhsVarArgs && rhsVarArgs) {
if (lhs.length != rhs.length) {
return false;
}
//校验前面的固定参数
for (int i = 0; i < lhs.length - 1; i++) {
if (!ClassUtils.isAssignable(lhs[i], rhs[i])) {
return false;
}
}
// 校验最后一个可变参数
Class<?> c1 = lhs[lhs.length - 1].getComponentType();
Class<?> c2 = rhs[rhs.length - 1].getComponentType();
if (!ClassUtils.isAssignable(c1, c2)) {
return false;
}
} else if (lhsVarArgs) {
if (lhs.length - 1 > rhs.length) {
return false;
}
//校验前面的固定参数
for (int i = 0; i < lhs.length - 1; i++) {
if (!ClassUtils.isAssignable(lhs[i], rhs[i])) {
return false;
}
}
// 校验最后一个可变参数
Class<?> varType = lhs[lhs.length - 1].getComponentType();
for (int i = lhs.length - 1; i < rhs.length; i++) {
if (!ClassUtils.isAssignable(varType, rhs[i])) {
return false;
}
}
} else {
if (lhs.length != rhs.length) {
return false;
}
for (int i = 0; i < lhs.length; i++) {
if (!ClassUtils.isAssignable(lhs[i], rhs[i])) {
return false;
}
}
}
return true;
}
}