com.tinkerpop.frames.modules.javahandler.JavaFrameInitializer Maven / Gradle / Ivy
Go to download
Windup Frames is an extension of the upstream Frames project, with tools to ease debugging and integration within windup.
package com.tinkerpop.frames.modules.javahandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.concurrent.ExecutionException;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.Lists;
import com.tinkerpop.blueprints.Edge;
import com.tinkerpop.blueprints.Element;
import com.tinkerpop.blueprints.Vertex;
import com.tinkerpop.frames.FrameInitializer;
import com.tinkerpop.frames.FramedGraph;
import com.tinkerpop.frames.util.ExceptionUtils;
/**
* Calls the methods annotated with {@link Initializer} on frame
* implementations.
*
* @author Bryn Cooke
*
*/
class JavaFrameInitializer implements FrameInitializer {
private JavaHandlerModule module;
/**
* Caches lists of InitializerMethods for a given frame class. See "doLoad" method below.
*/
private LoadingCache, List> initializerCache = CacheBuilder
.newBuilder().build(new CacheLoader, List>() {
@Override
public List load(final Class> frameClass) throws Exception {
return doLoad(frameClass);
}
});
JavaFrameInitializer(JavaHandlerModule module) {
this.module = module;
}
/**
* Captures the work of calling an "@Initializer" annotated method.
*/
private class InitializerMethod {
private final Class> h;
private final Method method;
private InitializerMethod(Class> h, Method method) {
this.h = h;
this.method = method;
}
void execute(Object framedElement, FramedGraph> framedGraph, Element element)
throws InvocationTargetException, IllegalAccessException {
Object handler = module.createHandler(framedElement, framedGraph, element, h, method);
method.invoke(handler);
}
}
@Override
public void initElement(Class> kind, FramedGraph> framedGraph, Element element) {
Object framedElement;
if (element instanceof Vertex) {
framedElement = framedGraph.frame((Vertex) element, kind);
} else {
framedElement = framedGraph.frame((Edge) element, kind);
}
try {
for (InitializerMethod method : initializerCache.get(kind)) {
try {
method.execute(framedElement, framedGraph, element);
} catch (IllegalArgumentException e) {
throw new JavaHandlerException("Problem calling Java handler", e);
} catch (IllegalAccessException e) {
throw new JavaHandlerException("Problem calling Java handler", e);
} catch (InvocationTargetException e) {
ExceptionUtils.sneakyThrow(e.getTargetException());
}
}
} catch (ExecutionException e) {
throw new JavaHandlerException("Problem calling Java handler", e);
}
}
/**
* Finds all the relevant @Initializer methods for the given class.
*/
private List doLoad(Class> kind) {
// We have to order this correctly. Dependencies should be initialised
// first so we first recursively collect an an array of classes to call
// and then reverse the array before putting them in a linked hash set.
// That way the classes discovered last will be called first.
List> classes = new ArrayList>();
depthFirstClassSearch(classes, kind);
Collections.reverse(classes);
LinkedHashSet> hierarchy = new LinkedHashSet>(classes);
List methods = Lists.newArrayList();
// Now we can store InitializerMethod objects for each method call.
for (Class> h : hierarchy) {
try {
try {
Class> implKind = module.getHandlerClass(h);
for (Method method : implKind.getDeclaredMethods()) {
if (method.isAnnotationPresent(Initializer.class)) {
if (method.getParameterTypes().length != 0) {
throw new JavaHandlerException("Java handler initializer " + method + "cannot have parameters");
}
methods.add(new InitializerMethod(h, method));
}
}
} catch (ClassNotFoundException e) {
// There was no impl class to check
}
} catch (IllegalArgumentException e) {
throw new JavaHandlerException("Problem calling Java handler", e);
}
}
return methods;
}
private void depthFirstClassSearch(List> initializers, Class> kind) {
if (kind == null || kind == Object.class) {
return;
}
initializers.add(kind);
for (Class> i : kind.getInterfaces()) {
depthFirstClassSearch(initializers, i);
}
depthFirstClassSearch(initializers, kind.getSuperclass());
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy