package com.jqmobile.core.utils;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.GenericDeclaration;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import com.jqmobile.core.orm.exception.ORMException;
/**
* 泛型类型获取工具
* @author MODI
*
* @project com.jiuqi.mobile.core
* @date 2013年11月22日
*/
public class TypeArgFinder {
private TypeArgFinder() {
}
public static Class<?> tryToClass(Type type) {
if (type instanceof Class<?>) {
return (Class<?>) type;
} else if (type instanceof GenericArrayType) {
Class<?> cc = tryToClass(((GenericArrayType) type)
.getGenericComponentType());
if (cc != null) {
return Array.newInstance(cc, 0).getClass();
}
} else if (type instanceof ParameterizedType) {
return tryToClass(((ParameterizedType) type).getRawType());
}
return null;
}
private static UnsupportedOperationException buildException(
Class<?> targetClass, Class<?> parameterizedClass, int index) {
return new UnsupportedOperationException("无法确定范型类的第" + index + "个范型参数");
}
public static Class<?>[] get(Class<?> targetClass,
Class<?> parameterizedClass) {
ParameterizedType[] paramTypes = new ParameterizedType[8];
int paramTypeCount = 0;
for (; targetClass != parameterizedClass; targetClass = targetClass
.getSuperclass()) {
if (targetClass == Object.class) {
throw new IllegalArgumentException("范型类不是目标类的父类型,无法提取类型参数");
}
Type t = targetClass.getGenericSuperclass();
if (t instanceof ParameterizedType) {
if (paramTypeCount == paramTypes.length) {
ParameterizedType[] newParamTypes = new ParameterizedType[paramTypeCount * 2];
System.arraycopy(paramTypes, 0, newParamTypes, 0,
paramTypeCount);
paramTypes = newParamTypes;
}
paramTypes[paramTypeCount++] = (ParameterizedType) t;
}
}
if (paramTypeCount == 0) {
throw new IllegalArgumentException("所给类型不是范型类");
}
int paramTypeIndex = paramTypeCount - 1;
ParameterizedType pt = paramTypes[paramTypeIndex];
if (pt.getRawType() != parameterizedClass) {
throw new IllegalArgumentException("所给类型不是范型类");
}
Type[] typeArguments = pt.getActualTypeArguments();
int argCount = typeArguments.length;
Class<?>[] typeArgs = new Class[argCount];
int[] typeArgIndexes = new int[argCount];
for (int i = 0; i < argCount; i++) {
typeArgIndexes[i] = i;
}
for (;;) {
TypeVariable<?>[] tvs = null;
for (int i = 0; i < typeArgIndexes.length; i++) {
int argIndex = typeArgIndexes[i];
if (argIndex < 0) {
continue;
}
Type t = typeArguments[argIndex];
if (t instanceof Class<?>) {
typeArgs[i] = (Class<?>) t;
typeArgIndexes[i] = -1;
argCount--;
} else if (t instanceof TypeVariable<?>) {
if (tvs == null) {
tvs = ((TypeVariable<?>) t).getGenericDeclaration()
.getTypeParameters();
}
for (int j = 0; j < tvs.length; j++) {
if (tvs[j] == t) {
typeArgIndexes[i] = j;
break;
}
}
} else {
if ((typeArgs[i] = tryToClass(t)) == null) {
throw buildException(targetClass, parameterizedClass, i);
}
typeArgIndexes[i] = -1;
argCount--;
}
}
if (argCount == 0) {
return typeArgs;
} else if (paramTypeIndex == 0) {
for (int i = 0; i < typeArgs.length; i++) {
if (typeArgs[i] == null) {
throw buildException(targetClass, parameterizedClass, i);
}
}
} else {
pt = paramTypes[--paramTypeIndex];
typeArguments = pt.getActualTypeArguments();
}
}
}
public static Class<?> find(Class<?> targetClass,
Class<?> parameterizedClass, int index) {
return findOrGet(targetClass, parameterizedClass, index, true);
}
public static Class<?> get(Class<?> targetClass,
Class<?> parameterizedClass, int index) {
return findOrGet(targetClass, parameterizedClass, index, false);
}
private static Class<?> findOrGet(Class<?> targetClass,
Class<?> parameterizedClass, int index, boolean find) {
ParameterizedType[] paramTypes = new ParameterizedType[8];
int paramTypeCount = 0;
if (parameterizedClass.isInterface()) {
Type[] gi;
findPts: for (;;) {
for (;;) {
gi = targetClass.getGenericInterfaces();
if (gi.length > 0) {
break;
}
Type t = targetClass.getGenericSuperclass();
if (t instanceof ParameterizedType) {
if (paramTypeCount == paramTypes.length) {
ParameterizedType[] newParamTypes = new ParameterizedType[paramTypeCount * 2];
System.arraycopy(paramTypes, 0, newParamTypes, 0,
paramTypeCount);
paramTypes = newParamTypes;
}
paramTypes[paramTypeCount++] = (ParameterizedType) t;
}
targetClass = targetClass.getSuperclass();
if (targetClass == Object.class) {
if (find) {
return null;
}
throw new IllegalArgumentException(
"范型类不是目标类的父类型,无法提取类型参数");
}
}
fort: for (Type type : gi) {
if (type instanceof ParameterizedType) {
final ParameterizedType pt = (ParameterizedType) type;
final Class<?> rawPt = (Class<?>) pt.getRawType();
if (parameterizedClass.isAssignableFrom(rawPt)) {
if (paramTypeCount == paramTypes.length) {
ParameterizedType[] newParamTypes = new ParameterizedType[paramTypeCount * 2];
System.arraycopy(paramTypes, 0, newParamTypes,
0, paramTypeCount);
paramTypes = newParamTypes;
}
paramTypes[paramTypeCount++] = pt;
if (rawPt == parameterizedClass) {
break findPts;
}
gi = rawPt.getGenericInterfaces();
break fort;
}
}
}
}
} else {
for (; targetClass != parameterizedClass; targetClass = targetClass
.getSuperclass()) {
if (targetClass == Object.class) {
if (find) {
return null;
}
throw new IllegalArgumentException("范型类不是目标类的父类型,无法提取类型参数");
}
final Type t = targetClass.getGenericSuperclass();
if (t instanceof ParameterizedType) {
if (paramTypeCount == paramTypes.length) {
ParameterizedType[] newParamTypes = new ParameterizedType[paramTypeCount * 2];
System.arraycopy(paramTypes, 0, newParamTypes, 0,
paramTypeCount);
paramTypes = newParamTypes;
}
paramTypes[paramTypeCount++] = (ParameterizedType) t;
}
}
}
if (paramTypeCount == 0) {
if (find) {
return null;
}
throw new IllegalArgumentException("所给类型不是范型类");
}
int paramTypeIndex = paramTypeCount - 1;
ParameterizedType pt = paramTypes[paramTypeIndex];
if (pt.getRawType() != parameterizedClass) {
if (find) {
return null;
}
throw new IllegalArgumentException("所给类型不是范型类");
}
Type[] typeArguments = pt.getActualTypeArguments();
int typeArgIndexe = index;
for (;;) {
Type t = typeArguments[typeArgIndexe];
if (t instanceof Class<?>) {
return (Class<?>) t;
} else if (t instanceof TypeVariable<?>) {
TypeVariable<?>[] tvs = ((TypeVariable<?>) t)
.getGenericDeclaration().getTypeParameters();
for (int j = 0; j < tvs.length; j++) {
if (tvs[j] == t) {
typeArgIndexe = j;
break;
}
}
} else {
Class<?> c = tryToClass(t);
if (c == null && !find) {
throw buildException(targetClass, parameterizedClass, index);
}
return c;
}
if (paramTypeIndex == 0) {
if (find) {
return null;
}
throw buildException(targetClass, parameterizedClass, index);
} else {
pt = paramTypes[--paramTypeIndex];
typeArguments = pt.getActualTypeArguments();
}
}
}
public static ParameterizedType findParameterizedType(Class<?> targetClass,
Class<?> parameterizedClass, int index) {
ParameterizedType[] paramTypes = new ParameterizedType[8];
int paramTypeCount = 0;
if (parameterizedClass.isInterface()) {
Type[] gi;
findPts: for (;;) {
for (;;) {
gi = targetClass.getGenericInterfaces();
if (gi.length > 0) {
break;
}
targetClass = targetClass.getSuperclass();
if (targetClass == Object.class) {
return null;
}
}
fort: for (Type type : gi) {
if (type instanceof ParameterizedType) {
final ParameterizedType pt = (ParameterizedType) type;
final Class<?> rawPt = (Class<?>) pt.getRawType();
if (parameterizedClass.isAssignableFrom(rawPt)) {
if (paramTypeCount == paramTypes.length) {
ParameterizedType[] newParamTypes = new ParameterizedType[paramTypeCount * 2];
System.arraycopy(paramTypes, 0, newParamTypes,
0, paramTypeCount);
paramTypes = newParamTypes;
}
paramTypes[paramTypeCount++] = pt;
if (rawPt == parameterizedClass) {
break findPts;
}
gi = rawPt.getGenericInterfaces();
break fort;
}
}
}
}
} else {
for (; targetClass != parameterizedClass; targetClass = targetClass
.getSuperclass()) {
if (targetClass == Object.class) {
return null;
}
final Type t = targetClass.getGenericSuperclass();
if (t instanceof ParameterizedType) {
if (paramTypeCount == paramTypes.length) {
ParameterizedType[] newParamTypes = new ParameterizedType[paramTypeCount * 2];
System.arraycopy(paramTypes, 0, newParamTypes, 0,
paramTypeCount);
paramTypes = newParamTypes;
}
paramTypes[paramTypeCount++] = (ParameterizedType) t;
}
}
}
if (paramTypeCount == 0) {
return null;
}
int paramTypeIndex = paramTypeCount - 1;
ParameterizedType pt = paramTypes[paramTypeIndex];
if (pt.getRawType() != parameterizedClass) {
return null;
}
Type[] typeArguments = pt.getActualTypeArguments();
int typeArgIndexe = index;
for (;;) {
Type t = typeArguments[typeArgIndexe];
if (t instanceof TypeVariable<?>) {
TypeVariable<?>[] tvs = ((TypeVariable<?>) t)
.getGenericDeclaration().getTypeParameters();
for (int j = 0; j < tvs.length; j++) {
if (tvs[j] == t) {
typeArgIndexe = j;
break;
}
}
} else if (t instanceof ParameterizedType) {
return (ParameterizedType) t;
} else {
return null;
}
if (paramTypeIndex == 0) {
return null;
} else {
pt = paramTypes[--paramTypeIndex];
typeArguments = pt.getActualTypeArguments();
}
}
}
@Deprecated
public static Class<?> find(Class<?> ownerClass,
ParameterizedType fieldType, int index) {
Type t = fieldType.getActualTypeArguments()[index];
if (t instanceof Class<?>) {
return (Class<?>) t;
} else if (t instanceof TypeVariable<?>) {
GenericDeclaration gd = ((TypeVariable<?>) t)
.getGenericDeclaration();
if (gd instanceof Class<?>) {
index = 0;
for (TypeVariable<?> tv : gd.getTypeParameters()) {
if (tv == t) {
return findOrGet(ownerClass, (Class<?>) gd, index, true);
}
index++;
}
}
}
return null;
// TODO
}
public static Class<?> getFieldClassGenricType(Field field){
return (Class<?>) ((ParameterizedType)field.getGenericType()).getActualTypeArguments()[0];
}
}