package com.tinkerpop.frames.annotations; import com.tinkerpop.blueprints.Direction; import com.tinkerpop.blueprints.Edge; import com.tinkerpop.blueprints.Element; import com.tinkerpop.blueprints.Vertex; import com.tinkerpop.frames.Adjacency; import com.tinkerpop.frames.ClassUtilities; import com.tinkerpop.frames.FramedGraph; import com.tinkerpop.frames.VertexFrame; import com.tinkerpop.frames.structures.FramedVertexIterable; import java.lang.reflect.Method; public class AdjacencyAnnotationHandler implements AnnotationHandler<Adjacency> { @Override public Class<Adjacency> getAnnotationType() { return Adjacency.class; } @Override public Object processElement(final Adjacency annotation, final Method method, final Object[] arguments, final FramedGraph framedGraph, final Element element, final Direction direction) { if (element instanceof Vertex) { return processVertex(annotation, method, arguments, framedGraph, (Vertex) element); } else { throw new UnsupportedOperationException(); } } public Object processVertex(final Adjacency adjacency, final Method method, final Object[] arguments, final FramedGraph framedGraph, final Vertex vertex) { if (ClassUtilities.isGetMethod(method)) { final FramedVertexIterable r = new FramedVertexIterable(framedGraph, vertex.getVertices(adjacency.direction(), adjacency.label()), ClassUtilities.getGenericClass(method)); if (ClassUtilities.returnsIterable(method)) { return r; } else { return r.iterator().hasNext() ? r.iterator().next() : null; } } else if (ClassUtilities.isAddMethod(method)) { Class<?> returnType = method.getReturnType(); Vertex newVertex; Object returnValue = null; if (arguments == null) { // Use this method to get the vertex so that the vertex // initializer is called. returnValue = framedGraph.addVertex(null, returnType); newVertex = ((VertexFrame) returnValue).asVertex(); } else { newVertex = ((VertexFrame) arguments[0]).asVertex(); } addEdges(adjacency, framedGraph, vertex, newVertex); if (returnType.isPrimitive()) { return null; } else { return returnValue; } } else if (ClassUtilities.isRemoveMethod(method)) { removeEdges(adjacency.direction(), adjacency.label(), vertex, ((VertexFrame) arguments[0]).asVertex(), framedGraph); return null; } else if (ClassUtilities.isSetMethod(method)) { removeEdges(adjacency.direction(), adjacency.label(), vertex, null, framedGraph); if (ClassUtilities.acceptsIterable(method)) { for (Object o : (Iterable) arguments[0]) { Vertex v = ((VertexFrame) o).asVertex(); addEdges(adjacency, framedGraph, vertex, v); } return null; } else { if (null != arguments[0]) { Vertex newVertex = ((VertexFrame) arguments[0]).asVertex(); addEdges(adjacency, framedGraph, vertex, newVertex); } return null; } } return null; } private void addEdges(final Adjacency adjacency, final FramedGraph framedGraph, final Vertex vertex, Vertex newVertex) { switch(adjacency.direction()) { case OUT: framedGraph.addEdge(null, vertex, newVertex, adjacency.label()); break; case IN: framedGraph.addEdge(null, newVertex, vertex, adjacency.label()); break; case BOTH: throw new UnsupportedOperationException("Direction.BOTH it not supported on 'add' or 'set' methods"); } } private void removeEdges(final Direction direction, final String label, final Vertex element, final Vertex otherVertex, final FramedGraph framedGraph) { for (final Edge edge : element.getEdges(direction, label)) { if (null == otherVertex || edge.getVertex(direction.opposite()).equals(otherVertex)) { framedGraph.removeEdge(edge); } } } }