mirror of
https://github.com/PolyhedralDev/Terra.git
synced 2026-04-12 10:46:25 +00:00
move reflection utils
This commit is contained in:
@@ -0,0 +1,69 @@
|
||||
package com.dfsek.terra.api.util.reflection;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.AnnotatedElement;
|
||||
import java.lang.reflect.Array;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.GenericArrayType;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.lang.reflect.TypeVariable;
|
||||
import java.lang.reflect.WildcardType;
|
||||
import java.util.Arrays;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
|
||||
public final class ReflectionUtil {
|
||||
public static Field[] getFields(@NotNull Class<?> type) {
|
||||
Field[] result = type.getDeclaredFields();
|
||||
Class<?> parentClass = type.getSuperclass();
|
||||
if(parentClass != null) {
|
||||
result = Stream.concat(Arrays.stream(result), Arrays.stream(getFields(parentClass))).toArray(Field[]::new);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static Method[] getMethods(@NotNull Class<?> type) {
|
||||
Method[] result = type.getDeclaredMethods();
|
||||
Class<?> parentClass = type.getSuperclass();
|
||||
if(parentClass != null) {
|
||||
result = Stream.concat(Arrays.stream(result), Arrays.stream(getMethods(parentClass))).toArray(Method[]::new);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static <T extends Annotation> void ifAnnotationPresent(AnnotatedElement element, Class<? extends T> annotation,
|
||||
Consumer<T> operation) {
|
||||
T a = element.getAnnotation(annotation);
|
||||
if(a != null) operation.accept(a);
|
||||
}
|
||||
|
||||
public static Class<?> getRawType(Type type) {
|
||||
if(type instanceof Class<?>) {
|
||||
return (Class<?>) type;
|
||||
} else if(type instanceof ParameterizedType) {
|
||||
ParameterizedType parameterizedType = (ParameterizedType) type;
|
||||
Type rawType = parameterizedType.getRawType();
|
||||
return (Class<?>) rawType;
|
||||
} else if(type instanceof GenericArrayType) {
|
||||
Type componentType = ((GenericArrayType) type).getGenericComponentType();
|
||||
return Array.newInstance(getRawType(componentType), 0).getClass();
|
||||
} else if(type instanceof TypeVariable) {
|
||||
return Object.class;
|
||||
} else if(type instanceof WildcardType) {
|
||||
return getRawType(((WildcardType) type).getUpperBounds()[0]);
|
||||
} else {
|
||||
String className = type == null ? "null" : type.getClass().getName();
|
||||
throw new IllegalArgumentException("Expected a Class, ParameterizedType, or "
|
||||
+ "GenericArrayType, but <" + type + "> is of type " + className);
|
||||
}
|
||||
}
|
||||
|
||||
public static String typeToString(Type type) {
|
||||
return type instanceof Class ? ((Class<?>) type).getName() : type.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
package com.dfsek.terra.api.util.reflection;
|
||||
|
||||
import java.lang.reflect.AnnotatedParameterizedType;
|
||||
import java.lang.reflect.AnnotatedType;
|
||||
import java.lang.reflect.GenericArrayType;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.lang.reflect.TypeVariable;
|
||||
import java.lang.reflect.WildcardType;
|
||||
import java.util.Arrays;
|
||||
import java.util.Objects;
|
||||
|
||||
|
||||
public class TypeKey<T> {
|
||||
final Class<? super T> rawType;
|
||||
final Type type;
|
||||
|
||||
final AnnotatedType annotatedType;
|
||||
final int hashCode;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected TypeKey() {
|
||||
this.type = getSuperclassTypeParameter(getClass());
|
||||
this.annotatedType = getAnnotatedSuperclassTypeParameter(getClass());
|
||||
this.rawType = (Class<? super T>) ReflectionUtil.getRawType(type);
|
||||
this.hashCode = type.hashCode();
|
||||
}
|
||||
|
||||
public static boolean equals(Type a, Type b) {
|
||||
if(a == b) {
|
||||
return true;
|
||||
} else if(a instanceof Class) {
|
||||
return a.equals(b);
|
||||
} else if(a instanceof ParameterizedType) {
|
||||
if(!(b instanceof ParameterizedType)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ParameterizedType pa = (ParameterizedType) a;
|
||||
ParameterizedType pb = (ParameterizedType) b;
|
||||
return Objects.equals(pa.getOwnerType(), pb.getOwnerType())
|
||||
&& pa.getRawType().equals(pb.getRawType())
|
||||
&& Arrays.equals(pa.getActualTypeArguments(), pb.getActualTypeArguments());
|
||||
} else if(a instanceof GenericArrayType) {
|
||||
if(!(b instanceof GenericArrayType)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
GenericArrayType ga = (GenericArrayType) a;
|
||||
GenericArrayType gb = (GenericArrayType) b;
|
||||
return equals(ga.getGenericComponentType(), gb.getGenericComponentType());
|
||||
} else if(a instanceof WildcardType) {
|
||||
if(!(b instanceof WildcardType)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
WildcardType wa = (WildcardType) a;
|
||||
WildcardType wb = (WildcardType) b;
|
||||
return Arrays.equals(wa.getUpperBounds(), wb.getUpperBounds())
|
||||
&& Arrays.equals(wa.getLowerBounds(), wb.getLowerBounds());
|
||||
} else if(a instanceof TypeVariable) {
|
||||
if(!(b instanceof TypeVariable)) {
|
||||
return false;
|
||||
}
|
||||
TypeVariable<?> va = (TypeVariable<?>) a;
|
||||
TypeVariable<?> vb = (TypeVariable<?>) b;
|
||||
return va.getGenericDeclaration() == vb.getGenericDeclaration()
|
||||
&& va.getName().equals(vb.getName());
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static Type getSuperclassTypeParameter(Class<?> subclass) {
|
||||
Type superclass = subclass.getGenericSuperclass();
|
||||
if(superclass instanceof Class) {
|
||||
throw new RuntimeException("Missing type parameter.");
|
||||
}
|
||||
ParameterizedType parameterized = (ParameterizedType) superclass;
|
||||
return parameterized.getActualTypeArguments()[0];
|
||||
}
|
||||
|
||||
private static AnnotatedType getAnnotatedSuperclassTypeParameter(Class<?> subclass) {
|
||||
AnnotatedType superclass = subclass.getAnnotatedSuperclass();
|
||||
if(superclass.getType() instanceof Class) {
|
||||
throw new RuntimeException("Missing type parameter.");
|
||||
}
|
||||
AnnotatedParameterizedType parameterized = (AnnotatedParameterizedType) superclass;
|
||||
return parameterized.getAnnotatedActualTypeArguments()[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the raw (non-generic) type for this type.
|
||||
*/
|
||||
public final Class<? super T> getRawType() {
|
||||
return rawType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets underlying {@code Type} instance.
|
||||
*/
|
||||
public final Type getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public AnnotatedType getAnnotatedType() {
|
||||
return annotatedType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int hashCode() {
|
||||
return this.hashCode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean equals(Object o) {
|
||||
return o instanceof TypeKey<?>
|
||||
&& equals(type, ((TypeKey<?>) o).type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String toString() {
|
||||
return ReflectionUtil.typeToString(type);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user