All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.zodiac.sdk.json.util.ClassUtil Maven / Gradle / Ivy

There is a newer version: 1.5.17
Show newest version
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;
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy