net.paoding.rose.jade.statement.GenericUtils Maven / Gradle / Ivy
package net.paoding.rose.jade.statement;
import org.apache.commons.lang.ArrayUtils;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Parameter;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
/**
* 实现工具类,检查参数化类型的参数类型。
* @author han.liao
* @author 王志亮 [[email protected]]
*/
@SuppressWarnings({"rawtypes"})
public class GenericUtils {
private static final Class[] EMPTY_CLASSES = new Class[0];
/**
* 从参数, 返回值, 基类的: Generic 类型信息获取传入的实际类信息。
* @param genericType - Generic 类型信息
* @param daoMetaData
* @return 实际类信息
*/
public static Class[] getActualClass(Type genericType, DAOMetaData daoMetaData) {
if (genericType instanceof ParameterizedType) {
Type[] actualTypes = ((ParameterizedType) genericType).getActualTypeArguments();
Class>[] actualClasses = new Class>[actualTypes.length];
for (int i = 0; i < actualTypes.length; i++) {
Type actualType = actualTypes[i];
if (actualType instanceof Class>) {
actualClasses[i] = (Class>) actualType;
} else if (actualType instanceof GenericArrayType) {
Type componentType = ((GenericArrayType) actualType).getGenericComponentType();
actualClasses[i] = Array.newInstance((Class>) componentType, 0).getClass();
} else if (actualType instanceof TypeVariable) {
actualClasses[i] = resolveTypeVariable(daoMetaData, (TypeVariable) actualType);
} else {
throw new IllegalArgumentException("unsupport DAO method: " + daoMetaData.getDAOClass().getName());
}
}
return actualClasses;
}
return EMPTY_CLASSES;
}
/**
* DAO方法实际的返回类型
* @param smd
* @return
*/
public static Class getReturnType(StatementMetaData smd) {
Method method = smd.getMethod();
DAOMetaData daoMetaData = smd.getDAOMetaData();
if (method.getGenericReturnType() instanceof TypeVariable) {
TypeVariable v = (TypeVariable) method.getGenericReturnType();
return resolveTypeVariable(daoMetaData, v);
}
return method.getReturnType();
}
/**
* 求类型变量的值
* @param daoMetaData
* @param key
* @return
*/
public static final Class resolveTypeVariable(DAOMetaData daoMetaData, TypeVariable key) {
Map refs = new HashMap<>();
//
List allSuperTypes = new LinkedList();
allSuperTypes.addAll(Arrays.asList(daoMetaData.getDAOClass().getGenericInterfaces()));
for (int i = 0; i < allSuperTypes.size(); i++) {
Type type = allSuperTypes.get(i);
if (type instanceof ParameterizedType) {
ParameterizedType parameterizedType = ((ParameterizedType) type);
Class interfaceClass = (Class) parameterizedType.getRawType();
int j = 0;
for (Type actualTypeArgument : parameterizedType.getActualTypeArguments()) {
TypeVariable v = interfaceClass.getTypeParameters()[j++];
refs.put(v, actualTypeArgument);
// System.out.println("put " + v + " ---> " + actualTypeArgument);
}
for (Type t : interfaceClass.getGenericInterfaces()) {
if (!allSuperTypes.contains(t)) {
allSuperTypes.add(t);
}
}
} else {
for (Type t : ((Class) type).getGenericInterfaces()) {
if (!allSuperTypes.contains(t)) {
allSuperTypes.add(t);
}
}
}
}
Type returnType = key;
while (true) {
Type old = returnType;
returnType = refs.get(returnType);
if (returnType instanceof Class) {
return (Class) returnType;
}
if (returnType == null) {
returnType = old;
return (Class) ((TypeVariable) returnType).getBounds()[0];
}
}
}
/**
* 收集类的所有常量。
* @param clazz - 收集目标
* @param findAncestor - 是否查找父类
* @param findInterfaces - 是否查找接口
* @return {@link Map} 包含类的所有常量
*/
public static Map getConstantFrom(
Class> clazz, // NL
boolean findAncestor, boolean findInterfaces) {
HashMap map = new HashMap();
if (findInterfaces) {
for (Class> interfaceClass : clazz.getInterfaces()) {
fillConstantFrom(interfaceClass, map);
}
}
if (findAncestor) {
Class> superClass = clazz;
while (superClass != null) {
fillConstantFrom(superClass, map);
superClass = superClass.getSuperclass();
}
}
fillConstantFrom(clazz, map);
return map;
}
// 填充静态常量
protected static void fillConstantFrom(Class> clazz, HashMap map) {
Field fields[] = clazz.getDeclaredFields();
for (Field field : fields) {
if (field.isSynthetic()) {
continue; // 忽略系统常量
}
int modifiers = field.getModifiers();
if (!Modifier.isStatic(modifiers)) {
continue; // 忽略非静态常量
}
try {
if (field.isAccessible()) {
field.setAccessible(true);
}
map.put(field.getName(), field.get(null));
} catch (SecurityException | IllegalAccessException e) {
// Do nothing
}
}
}
/**
* 获取方法的参数名列表
* 如果编译时未开启 parameters,则返回 [arg0,arg1,arg2....]
* @param method
* @return
*/
public static String[] getMethodParamNames(Method method) {
Parameter[] parameters = method.getParameters();
if (ArrayUtils.isEmpty(parameters)) return new String[0];
return Arrays.stream(parameters).map(Parameter::getName).toArray(String[]::new);
}
}