feat(util): add ReflectionUtil
This commit is contained in:
		@@ -4,16 +4,34 @@ import java.lang.annotation.Annotation;
 | 
			
		||||
import java.lang.reflect.Method;
 | 
			
		||||
import java.util.ArrayList;
 | 
			
		||||
import java.util.Arrays;
 | 
			
		||||
import java.util.Collection;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
import java.util.Objects;
 | 
			
		||||
import java.util.stream.Stream;
 | 
			
		||||
 | 
			
		||||
public final class ReflectionUtil {
 | 
			
		||||
 | 
			
		||||
    public static <T extends Annotation> boolean isAnnotationPresent(Method method, Class<T> annotationClass) {
 | 
			
		||||
        if (method.isAnnotationPresent(annotationClass) || method.getDeclaringClass().isAnnotationPresent(annotationClass))
 | 
			
		||||
            return true;
 | 
			
		||||
    private ReflectionUtil() {}
 | 
			
		||||
 | 
			
		||||
        return false;
 | 
			
		||||
    private static final Map<Class<?>, Class<?>> PRIMITIVE_TO_BOXED = Map.ofEntries(
 | 
			
		||||
            Map.entry(boolean.class, Boolean.class),
 | 
			
		||||
            Map.entry(byte.class, Byte.class),
 | 
			
		||||
            Map.entry(char.class, Character.class),
 | 
			
		||||
            Map.entry(double.class, Double.class),
 | 
			
		||||
            Map.entry(float.class, Float.class),
 | 
			
		||||
            Map.entry(int.class, Integer.class),
 | 
			
		||||
            Map.entry(long.class, Long.class),
 | 
			
		||||
            Map.entry(short.class, Short.class),
 | 
			
		||||
            Map.entry(void.class, Void.class)
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    public static Class<?> box(Class<?> type) {
 | 
			
		||||
        return type.isPrimitive() ? PRIMITIVE_TO_BOXED.get(type) : type;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static <T extends Annotation> boolean isAnnotationPresent(Method method, Class<T> annotationClass) {
 | 
			
		||||
        return method.isAnnotationPresent(annotationClass) || method.getDeclaringClass().isAnnotationPresent(annotationClass);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static <T extends Annotation> T getAnnotation(Method method, Class<T> annotationClass) {
 | 
			
		||||
@@ -22,6 +40,14 @@ public final class ReflectionUtil {
 | 
			
		||||
            method.getDeclaringClass().getAnnotation(annotationClass);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static Stream<Object> getReturnAsStream(Object ret) {
 | 
			
		||||
        if (ret instanceof Object[] array)
 | 
			
		||||
            return Stream.of(array);
 | 
			
		||||
        if (ret instanceof Collection<?> coll)
 | 
			
		||||
            return coll.stream().map(o -> (Object)o);
 | 
			
		||||
        return Stream.of(ret);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static int getCastDepth(Class<?> child, Class<?> parent) {
 | 
			
		||||
 | 
			
		||||
        if (parent.equals(Object.class))
 | 
			
		||||
@@ -57,19 +83,20 @@ public final class ReflectionUtil {
 | 
			
		||||
            .filter(x -> isMethodCallable(x, parameters))
 | 
			
		||||
            .toList();
 | 
			
		||||
 | 
			
		||||
        if (compatibleMethods.size() == 0)
 | 
			
		||||
        if (compatibleMethods.isEmpty())
 | 
			
		||||
            throw new IllegalArgumentException("There are no compatible Methods provided");
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        for (int i = 0; i < parameters.length; i++) {
 | 
			
		||||
            final int currI = i;
 | 
			
		||||
            Class<?>[] parameterTypes = compatibleMethods.stream()
 | 
			
		||||
                .map(x -> x.getParameterTypes()[currI])
 | 
			
		||||
                .map(x -> getBoxedParameterTypes(x)[currI])
 | 
			
		||||
                .toArray(x -> new Class[x]);
 | 
			
		||||
 | 
			
		||||
            Class<?> mostSpecific = getMostSpecificClass(parameterTypes, parameters[i]);
 | 
			
		||||
 | 
			
		||||
            compatibleMethods = compatibleMethods.stream()
 | 
			
		||||
                .filter(x -> Objects.equals(x.getParameterTypes()[currI], mostSpecific))
 | 
			
		||||
                .filter(x -> Objects.equals(getBoxedParameterTypes(x)[currI], mostSpecific))
 | 
			
		||||
                .toList();
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
@@ -93,7 +120,7 @@ public final class ReflectionUtil {
 | 
			
		||||
        if (!Objects.equals(method.getParameterCount(), parameters.length))
 | 
			
		||||
            return false;
 | 
			
		||||
 | 
			
		||||
        Class<?>[] methodParams = method.getParameterTypes();
 | 
			
		||||
        Class<?>[] methodParams = getBoxedParameterTypes(method);
 | 
			
		||||
        for (int i = 0; i < parameters.length; i++) {
 | 
			
		||||
            if (!methodParams[i].isAssignableFrom(parameters[i]))
 | 
			
		||||
                return false;
 | 
			
		||||
@@ -101,6 +128,12 @@ public final class ReflectionUtil {
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static Class<?>[] getBoxedParameterTypes(Method method) {
 | 
			
		||||
        return Arrays.stream(method.getParameterTypes())
 | 
			
		||||
            .map(ReflectionUtil::box)
 | 
			
		||||
            .toArray(Class<?>[]::new);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static String getFullMethodName(Method method) {
 | 
			
		||||
        return method.getDeclaringClass().getName() + "." + method.getName();
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user