diff --git a/lib/src/main/java/net/tomatentum/cutin/util/ReflectionUtil.java b/lib/src/main/java/net/tomatentum/cutin/util/ReflectionUtil.java index 0e0d453..ae86982 100644 --- a/lib/src/main/java/net/tomatentum/cutin/util/ReflectionUtil.java +++ b/lib/src/main/java/net/tomatentum/cutin/util/ReflectionUtil.java @@ -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 boolean isAnnotationPresent(Method method, Class annotationClass) { - if (method.isAnnotationPresent(annotationClass) || method.getDeclaringClass().isAnnotationPresent(annotationClass)) - return true; + private ReflectionUtil() {} - return false; + private static final Map, 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 boolean isAnnotationPresent(Method method, Class annotationClass) { + return method.isAnnotationPresent(annotationClass) || method.getDeclaringClass().isAnnotationPresent(annotationClass); } public static T getAnnotation(Method method, Class annotationClass) { @@ -22,6 +40,14 @@ public final class ReflectionUtil { method.getDeclaringClass().getAnnotation(annotationClass); } + public static Stream 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(); }