package com.tinkerpop.frames; import com.tinkerpop.blueprints.Direction; import com.tinkerpop.blueprints.Element; import com.tinkerpop.blueprints.util.ElementHelper; import com.tinkerpop.frames.annotations.AnnotationHandler; import com.tinkerpop.frames.modules.MethodHandler; import java.lang.annotation.Annotation; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.util.Map; /** * The proxy class of a framed element. * * @author Marko A. Rodriguez (http://markorodriguez.com) */ public class FramedElement implements InvocationHandler { private final Direction direction; protected final FramedGraph framedGraph; protected final Element element; private static Method hashCodeMethod; private static Method equalsMethod; private static Method toStringMethod; private static Method asVertexMethod; private static Method asEdgeMethod; static { try { hashCodeMethod = Object.class.getMethod("hashCode"); equalsMethod = Object.class.getMethod("equals", new Class[] { Object.class }); toStringMethod = Object.class.getMethod("toString"); asVertexMethod = VertexFrame.class.getMethod("asVertex"); asEdgeMethod = EdgeFrame.class.getMethod("asEdge"); } catch (NoSuchMethodException e) { throw new NoSuchMethodError(e.getMessage()); } } /** * @deprecated The direction field will be dropped in the next major release */ @Deprecated public FramedElement(final FramedGraph framedGraph, final Element element, final Direction direction) { if (null == framedGraph) { throw new IllegalArgumentException("FramedGraph can not be null"); } if (null == element) { throw new IllegalArgumentException("Element can not be null"); } this.element = element; this.framedGraph = framedGraph; this.direction = direction; } public FramedElement(final FramedGraph framedGraph, final Element element) { this(framedGraph, element, Direction.OUT); } @Override public Object invoke(final Object proxy, final Method method, final Object[] arguments) { if (method.equals(hashCodeMethod)) { return this.element.hashCode(); } else if (method.equals(equalsMethod)) { return this.proxyEquals(arguments[0]); } else if (method.equals(toStringMethod)) { return this.element.toString(); } else if (method.equals(asVertexMethod) || method.equals(asEdgeMethod)) { return this.element; } final Annotation[] annotations = method.getAnnotations(); Map<Class<? extends Annotation>, AnnotationHandler<?>> annotationHandlers = this.framedGraph.getConfig() .getAnnotationHandlers(); Map<Class<? extends Annotation>, MethodHandler<?>> methodHandlers = this.framedGraph.getConfig() .getMethodHandlers(); for (final Annotation annotation : annotations) { MethodHandler methodHandler = methodHandlers.get(annotation.annotationType()); if (methodHandler != null) { return methodHandler.processElement(proxy, method, arguments, annotation, this.framedGraph, this.element); } } for (final Annotation annotation : annotations) { AnnotationHandler annotationHandler = annotationHandlers.get(annotation.annotationType()); if (annotationHandler != null) { return annotationHandler.processElement(annotation, method, arguments, this.framedGraph, this.element, this.direction); } } if (method.getAnnotations().length == 0) { throw new UnhandledMethodException("The method " + method.getDeclaringClass().getName() + "." + method.getName() + " has no annotations, therefore frames cannot handle the method."); } throw new UnhandledMethodException( "The method " + method.getDeclaringClass().getName() + "." + method.getName() + " was not annotated with any annotations that the framed graph is configured for. Please check your frame interface and/or graph configuration."); } private Boolean proxyEquals(final Object other) { if (other instanceof VertexFrame) { return this.element.equals(((VertexFrame) other).asVertex()); } if (other instanceof EdgeFrame) { return this.element.equals(((EdgeFrame) other).asEdge()); } else if (other instanceof Element) { return ElementHelper.areEqual(this.element, other); } else { return Boolean.FALSE; } } public Element getElement() { return this.element; } }