cn.maarlakes.enumx.ValueUtils Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of enumx Show documentation
Show all versions of enumx Show documentation
enumx 提供枚举值的统一接口,枚举值扩展接口,以及一些常见的枚举工具方法。
The newest version!
package cn.maarlakes.enumx;
import jakarta.annotation.Nonnull;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
/**
* @author linjpxc
*/
final class ValueUtils {
private ValueUtils() {
}
private static final ConcurrentMap, Class>> VALUE_TYPES = new ConcurrentHashMap<>();
@SuppressWarnings({"unchecked"})
static , V> Class getValueType(@Nonnull Class type) {
if (!Valuable.class.isAssignableFrom(type)) {
throw new IllegalArgumentException("type not is Valuable.");
}
return (Class) VALUE_TYPES.computeIfAbsent(type, key -> {
final Type valueType = getValueTypeArgument(getParentType(type));
if (!(valueType instanceof Class>)) {
throw new IllegalStateException();
}
return (Class>) valueType;
});
}
private static Type getParentType(Class> type) {
final Type[] genericInterfaces = type.getGenericInterfaces();
for (Type item : genericInterfaces) {
Class> midClass;
if (item instanceof ParameterizedType) {
final Type rawType = ((ParameterizedType) item).getRawType();
if (!(rawType instanceof Class>)) {
throw new IllegalStateException("");
}
midClass = (Class>) rawType;
} else if (item instanceof Class>) {
midClass = (Class>) item;
} else {
throw new IllegalStateException();
}
if (Valuable.class.isAssignableFrom(midClass)) {
return item;
}
}
return type.getGenericSuperclass();
}
private static Type getValueTypeArgument(Type type) {
if (type instanceof Class>) {
return getValueTypeArgument((Class>) type);
}
if (type instanceof ParameterizedType) {
return getValueTypeArgument((ParameterizedType) type);
}
return null;
}
private static Type getValueTypeArgument(ParameterizedType parameterizedType) {
final Type rawType = parameterizedType.getRawType();
if (!(rawType instanceof Class>)) {
throw new IllegalStateException("");
}
if (rawType == Valuable.class) {
return parameterizedType.getActualTypeArguments()[0];
}
if (!Valuable.class.isAssignableFrom((Class>) rawType)) {
return null;
}
final Type valueTypeArgument = getValueTypeArgument(rawType);
if (valueTypeArgument instanceof ParameterizedType) {
return parameterizedType.getActualTypeArguments()[0];
}
if (valueTypeArgument instanceof TypeVariable) {
return getValueTypeArgument(parameterizedType, (TypeVariable>) valueTypeArgument);
}
if (valueTypeArgument instanceof Class>) {
return valueTypeArgument;
}
return null;
}
private static Type getValueTypeArgument(ParameterizedType parameterizedType, TypeVariable> typeVariable) {
final Class> rawType = (Class>) parameterizedType.getRawType();
final TypeVariable extends Class>>[] typeParameters = rawType.getTypeParameters();
for (int i = 0; i < typeParameters.length; i++) {
if (typeParameters[i] == typeVariable) {
return parameterizedType.getActualTypeArguments()[i];
}
}
return null;
}
private static Type getValueTypeArgument(Class> type) {
if (!Valuable.class.isAssignableFrom(type)) {
return null;
}
return getValueTypeArgument(getParentType(type));
}
}