add getMostSpecificMethod method to simplify Check method parsing.
This Method searches the The method that has the best matching parameters with the fewest inheritance levels as possible. Left sided priority
This commit is contained in:
parent
f89ae5e425
commit
019ba8f552
@ -2,6 +2,10 @@ package net.tomatentum.marinara.util;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
public final class ReflectionUtil {
|
||||
|
||||
@ -17,5 +21,79 @@ public final class ReflectionUtil {
|
||||
method.getAnnotation(annotationClass) :
|
||||
method.getDeclaringClass().getAnnotation(annotationClass);
|
||||
}
|
||||
|
||||
public static int getCastDepth(Class<?> child, Class<?> parent) {
|
||||
if (!parent.isAssignableFrom(child)) {
|
||||
throw new IllegalArgumentException("The specified class is not a child class of the specified parent.");
|
||||
}
|
||||
|
||||
int depth = 0;
|
||||
Class<?> curr = child;
|
||||
List<Class<?>> parents = new ArrayList<>();
|
||||
|
||||
while (!curr.equals(parent)) {
|
||||
depth++;
|
||||
parents.add(curr.getSuperclass());
|
||||
parents.addAll(Arrays.asList(curr.getInterfaces()));
|
||||
|
||||
for (Class<?> currParent : parents) {
|
||||
if (currParent != null && parent.isAssignableFrom(currParent)) {
|
||||
curr = currParent;
|
||||
break;
|
||||
}
|
||||
}
|
||||
parents.clear();
|
||||
}
|
||||
|
||||
return depth;
|
||||
}
|
||||
|
||||
public static Method getMostSpecificMethod(Method[] methods, Class<?>... parameters) {
|
||||
List<Method> compatibleMethods = Arrays.stream(methods)
|
||||
.filter(x -> isMethodCallable(x, parameters))
|
||||
.toList();
|
||||
|
||||
if (compatibleMethods.size() == 0)
|
||||
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])
|
||||
.toArray(x -> new Class[x]);
|
||||
|
||||
Class<?> mostSpecific = getMostSpecificClass(parameterTypes, parameters[i]);
|
||||
|
||||
compatibleMethods = compatibleMethods.stream()
|
||||
.filter(x -> Objects.equals(x.getParameterTypes()[currI], mostSpecific))
|
||||
.toList();
|
||||
}
|
||||
|
||||
return compatibleMethods.getFirst();
|
||||
}
|
||||
|
||||
public static Class<?> getMostSpecificClass(Class<?>[] classes, Class<?> base) {
|
||||
int min = Integer.MAX_VALUE;
|
||||
Class<?> currMostSpecific = null;
|
||||
for (Class<?> currClass : classes) {
|
||||
int currCastDepth = getCastDepth(base, currClass);
|
||||
if (currCastDepth < min) {
|
||||
min = currCastDepth;
|
||||
currMostSpecific = currClass;
|
||||
}
|
||||
}
|
||||
return currMostSpecific;
|
||||
}
|
||||
|
||||
public static boolean isMethodCallable(Method method, Class<?>... parameters) {
|
||||
if (!Objects.equals(method.getParameterCount(), parameters.length))
|
||||
return false;
|
||||
|
||||
Class<?>[] methodParams = method.getParameterTypes();
|
||||
for (int i = 0; i < parameters.length; i++) {
|
||||
if (!methodParams[i].isAssignableFrom(parameters[i]))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user