package net.paoding.rose.jade.statement;
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.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.lang.reflect.WildcardType;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
/**
* 实现工具类,检查参数化类型的参数类型。
*
* @author han.liao
* @author 王志亮 [qieqie.wang@gmail.com]
*/
@SuppressWarnings({ "rawtypes" })
public class GenericUtils {
private static final Class[] EMPTY_CLASSES = new Class[0];
/**
* 返回类型List<E>、Map<K,V>中的E、K、V
*
* @param method
* @param daoMetaData
*
*/
public static Class[] resolveTypeParameters(Class invocationClass, Type targetType) {
if (targetType instanceof ParameterizedType) {
Type[] actualTypes = ((ParameterizedType) targetType).getActualTypeArguments();
Class[] actualClasses = new Class[actualTypes.length];
for (int i = 0; i < actualTypes.length; i++) {
actualClasses[i] = resolveTypeVariable(invocationClass, actualTypes[i]);
}
return actualClasses;
}
return EMPTY_CLASSES;
}
/**
* 求declaringClass类中声明的泛型类型变量在invocationClass中真正的值
*
* @param invocationClass 编程时使用的类
* @param declaringClass 声明类型变量typeVarName的类
* @param typeVarName 泛型变量名
* @return
*/
public static final Class resolveTypeVariable(Class invocationClass, Class declaringClass,
String typeVarName) {
TypeVariable typeVariable = null;
for (TypeVariable typeParemeter : declaringClass.getTypeParameters()) {
if (typeParemeter.getName().equals(typeVarName)) {
typeVariable = typeParemeter;
break;
}
}
if (typeVariable == null) {
throw new NullPointerException("not found TypeVariable name " + typeVarName);
}
return resolveTypeVariable(invocationClass, typeVariable);
}
/**
*
* 求给定的invocationClass类中,目标类型type的值
*
* 如果type已是类型,则直接返回它;
* 如果type是类型变量( {@link TypeVariable}),则求他的值;
*
* @param invocationClass
* @param targetType
* @return
*/
public static final Class resolveTypeVariable(Class invocationClass, Type targetType) {
if (targetType == null) {
throw new NullPointerException("TypeVariable is null");
}
// Class类型
if (targetType instanceof Class) {
return (Class) targetType;
}
// 参数容器类型(注意:返回的是容器类型,而非具体的参数类型。不要混淆!)
if (targetType instanceof ParameterizedType) {
return resolveTypeVariable(invocationClass,
(Type) ((ParameterizedType) targetType).getRawType());
}
// 数组类型
if (targetType instanceof GenericArrayType) {
Type componentType = ((GenericArrayType) targetType).getGenericComponentType();
componentType = resolveTypeVariable(invocationClass, componentType);
return Array.newInstance((Class) componentType, 0).getClass();
}
Map<TypeVariable, Type> refs = new HashMap<TypeVariable, Type>();
//
List<Type> allSuperTypes = new LinkedList<Type>();
allSuperTypes.addAll(Arrays.asList(invocationClass.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 = targetType;
while (true) {
Type old = returnType;
returnType = refs.get(returnType);
if (returnType instanceof Class) {
return (Class) returnType;
}
if (returnType == null) {
returnType = old;
if (returnType instanceof WildcardType) {
return (Class) ((WildcardType) returnType).getUpperBounds()[0];
}
return (Class) ((TypeVariable) returnType).getBounds()[0];
}
}
}
/**
* 收集类的所有常量。
*
* @param clazz - 收集目标
* @param findAncestor - 是否查找父类
* @param findInterfaces - 是否查找接口
*
* @return {@link Map} 包含类的所有常量
*/
public static Map<String, Object> getConstantFrom(Class clazz, // NL
boolean findAncestor, boolean findInterfaces) {
HashMap<String, Object> map = new HashMap<String, Object>();
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<String, Object> 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 e) {
// Do nothing
} catch (IllegalAccessException e) {
// Do nothing
}
}
}
// 测试代码
public static void main(String... args) {
// 输出所有常量
System.out.println("输出所有常量");
Map<String, ?> constants = getConstantFrom(Character.class, true, true);
System.out.println(constants);
// 输出方法的返回类型
System.out.println();
System.out.println("输出方法的返回类型" + java.lang.ClassLoader.class.getName());
for (Method method : ClassLoader.class.getMethods()) {
Class<?>[] classes = resolveTypeParameters(ClassLoader.class,
method.getGenericReturnType());
System.out.print(method.getName() + " = ");
System.out.println(Arrays.toString(classes));
}
// 输出超类的类型
System.out.println();
System.out.println("输出超类的类型" + java.util.Properties.class.getName());
Type genericSuperclassType = java.util.Properties.class.getGenericSuperclass();
System.out.print(genericSuperclassType + " = ");
System.out.println(Arrays
.toString(resolveTypeParameters(java.util.Properties.class, genericSuperclassType)));
System.out.println();
System.out.println("输出派生类的类型" + java.util.Properties.class.getName());
for (Type genericInterfaceType : java.util.Properties.class.getGenericInterfaces()) {
// 输出派生类的类型
Class<?>[] classes = resolveTypeParameters(java.util.Properties.class,
genericInterfaceType);
System.out.print(genericInterfaceType + " = ");
System.out.println(Arrays.toString(classes));
}
}
}