com.algorithmia.development.ReflectionHelper Maven / Gradle / Ivy
package com.algorithmia.development;
import java.io.Serializable;
import java.lang.invoke.SerializedLambda;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.function.BiFunction;
import java.util.function.Function;
/**
* This static class and lambda interface to allow for the recovery of method names and original class names for method references.
* Normally this information is lost due to erasure, but by enforcing the interface to be Serializable, we can recover the name and class, which allows us to perform reflection
* on the primary classes apply method.
*/
// https://stackoverflow.com/questions/31178103/how-can-i-find-the-target-of-a-java8-method-reference
// https://docs.oracle.com/javase/7/docs/api/java/io/Serializable.html
class ReflectionHelper {
static String getMethodName(
DebuggableFunction methodReference) {
SerializedLambda lambda = getLambda(methodReference);
return lambda.getImplMethodName();
}
static String getMethodName(DebuggableBifunction methodReference) {
SerializedLambda lambda = getLambda(methodReference);
return lambda.getImplMethodName();
}
private static SerializedLambda getLambda(Serializable lambda) {
for (Class> cl = lambda.getClass(); cl != null; cl = cl.getSuperclass()) {
try {
Method m = cl.getDeclaredMethod("writeReplace");
m.setAccessible(true);
Object replacement = m.invoke(lambda);
if (!(replacement instanceof SerializedLambda)) {
break; // custom interface implementation
}
SerializedLambda l = (SerializedLambda) replacement;
return l;
} catch (NoSuchMethodException e) {
// In the event that we're provided with a hierarchical class structure, our serializable method might not be found in the final class, it may be in a ancestor.
// If the current scope does not implement serializable, we continue to increase scope until it does, or we exhaust superclasses.
} catch (IllegalAccessException | InvocationTargetException e) {
throw new RuntimeException("The writeReplace method implemented by your algorithm class is incompatible with this framework", e);
}
}
throw new RuntimeException("We were unable to find a Serializable form of your method reference. Please ensure that you're using a compatible version of java.");
}
@FunctionalInterface
public interface DebuggableFunction extends
Serializable,
Function {
}
@FunctionalInterface
public interface DebuggableBifunction extends
Serializable,
BiFunction {
}
}