org.zodiac.sdk.json.util.ClassUtil Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of zodiac-sdk-json Show documentation
Show all versions of zodiac-sdk-json Show documentation
Zodiac SDK JSON(JavaScript Object Notation)
package org.zodiac.sdk.json.util;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.lang.reflect.WildcardType;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import org.zodiac.sdk.json.reflect.ParameterizedTypeImpl;
public abstract class ClassUtil {
private ClassUtil() {
}
public static Type getCollectionItemType(Type fieldType) {
if (fieldType instanceof ParameterizedType) {
return getCollectionItemType((ParameterizedType) fieldType);
}
if (fieldType instanceof Class>) {
return getCollectionItemType((Class>) fieldType);
}
return Object.class;
}
private static Type getCollectionItemType(Class> clazz) {
return clazz.getName().startsWith("java.")
? Object.class
: getCollectionItemType(getCollectionSuperType(clazz));
}
private static Type getCollectionSuperType(Class> clazz) {
Type assignable = null;
for (Type type : clazz.getGenericInterfaces()) {
Class> rawClass = TypeUtil.getRawClass(type);
if (rawClass == Collection.class) {
return type;
}
if (Collection.class.isAssignableFrom(rawClass)) {
assignable = type;
}
}
return assignable == null ? clazz.getGenericSuperclass() : assignable;
}
private static Type getCollectionItemType(ParameterizedType parameterizedType) {
Type rawType = parameterizedType.getRawType();
Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
if (rawType == Collection.class) {
return getWildcardTypeUpperBounds(actualTypeArguments[0]);
}
Class> rawClass = (Class>) rawType;
Map typeParameterMap = createTypeParameterMap(rawClass.getTypeParameters(), actualTypeArguments);
Type superType = getCollectionSuperType(rawClass);
if (superType instanceof ParameterizedType) {
Class> superClass = TypeUtil.getRawClass(superType);
Type[] superClassTypeParameters = ((ParameterizedType) superType).getActualTypeArguments();
return superClassTypeParameters.length > 0
? getCollectionItemType(makeParameterizedType(superClass, superClassTypeParameters, typeParameterMap))
: getCollectionItemType(superClass);
}
return getCollectionItemType((Class>) superType);
}
private static ParameterizedType makeParameterizedType(Class> rawClass, Type[] typeParameters, Map typeParameterMap) {
int length = typeParameters.length;
Type[] actualTypeArguments = new Type[length];
System.arraycopy(typeParameters, 0, actualTypeArguments, 0, length);
for (int i = 0; i < actualTypeArguments.length; i++) {
Type actualTypeArgument = actualTypeArguments[i];
if (actualTypeArgument instanceof TypeVariable) {
actualTypeArguments[i] = typeParameterMap.get(actualTypeArgument);
}
}
return new ParameterizedTypeImpl(actualTypeArguments, null, rawClass);
}
private static Type getWildcardTypeUpperBounds(Type type) {
if (type instanceof WildcardType) {
WildcardType wildcardType = (WildcardType) type;
Type[] upperBounds = wildcardType.getUpperBounds();
return upperBounds.length > 0 ? upperBounds[0] : Object.class;
}
return type;
}
private static Map createTypeParameterMap(TypeVariable[] typeParameters, Type[] actualTypeArguments) {
int length = typeParameters.length;
Map typeParameterMap = new HashMap(length);
for (int i = 0; i < length; i++) {
typeParameterMap.put(typeParameters[i], actualTypeArguments[i]);
}
return typeParameterMap;
}
}