package com.fluentinterface.utils;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
public class GenericsUtils {
private GenericsUtils() {}
/**
* Finds the generic type declared on a single interface implemented by the provided class.
* If the generic type is itself a generic type (ex: <pre>SomeType<SomeOtherType<T>></pre>,
* the actal raw type will be returned (in the example, SomeOtherType would be returned).
*
* @param clazz the class on which we want to find the generic type.
* @return the actual type declared on the provided generic interface.
*/
public static Class<?> getDeclaredGenericType(Class<?> clazz, Class<?> genericInterface) {
Type[] genericInterfaces = clazz.getGenericInterfaces();
for (Type genericType : genericInterfaces) {
if (genericType instanceof ParameterizedType) {
ParameterizedType paramType = (ParameterizedType) genericType;
if (paramType.getRawType().equals(genericInterface)) {
Type type = paramType.getActualTypeArguments()[0];
return getActualRawType(type);
}
}
}
return null;
}
/**
* Java's introspection API differentiates between a raw type and a generic (parameterized) type.
* To determine the actual raw type from a type, we need to take both cases into consideration.
*/
private static Class<?> getActualRawType(Type type) {
Class<?> rawType;
if (type instanceof ParameterizedType) {
rawType = (Class<?>) ((ParameterizedType) type).getRawType();
} else {
rawType = (Class<?>) type;
}
return rawType;
}
}