package org.openntf.domino.graph2.annotations; import java.lang.annotation.Annotation; import java.lang.reflect.Method; import java.util.Collection; import org.openntf.domino.big.NoteCoordinate; import org.openntf.domino.graph2.DEdgeList; import org.openntf.domino.graph2.DElementStore; import org.openntf.domino.graph2.DVertex; import org.openntf.domino.graph2.impl.DFramedTransactionalGraph; import org.openntf.domino.utils.DominoUtils; import com.tinkerpop.blueprints.Direction; import com.tinkerpop.blueprints.Edge; import com.tinkerpop.blueprints.Vertex; import com.tinkerpop.frames.Adjacency; import com.tinkerpop.frames.ClassUtilities; import com.tinkerpop.frames.EdgeFrame; import com.tinkerpop.frames.FramedGraph; import com.tinkerpop.frames.Incidence; import com.tinkerpop.frames.VertexFrame; public abstract class AbstractIncidenceHandler { public AbstractIncidenceHandler() { // TODO Auto-generated constructor stub } @SuppressWarnings({ "rawtypes", "unchecked" }) public Object processVertexIncidence(final Annotation annotation, final Method method, final Object[] arguments, final FramedGraph framedGraph, final Vertex vertex) { Direction dir = Direction.BOTH; String label = ""; boolean unique = false; if (annotation instanceof Adjacency) { dir = ((Adjacency) annotation).direction(); label = ((Adjacency) annotation).label(); } else if (annotation instanceof AdjacencyUnique) { dir = ((AdjacencyUnique) annotation).direction(); label = ((AdjacencyUnique) annotation).label(); unique = true; } else if (annotation instanceof Incidence) { dir = ((Incidence) annotation).direction(); label = ((Incidence) annotation).label(); } else if (annotation instanceof IncidenceUnique) { dir = ((IncidenceUnique) annotation).direction(); label = ((IncidenceUnique) annotation).label(); unique = true; } if (ClassUtilities.isGetMethod(method)) { Class<?> returnType = method.getReturnType(); if (Iterable.class.isAssignableFrom(returnType)) { DEdgeList edgeList = (DEdgeList) vertex.getEdges(dir, label); edgeList.setUnique(unique); return new FramedEdgeList(framedGraph, vertex, edgeList, ClassUtilities.getGenericClass(method)); } else if (Edge.class.isAssignableFrom(returnType)) { return vertex.getEdges(dir, label).iterator().next(); } else { Edge e = vertex.getEdges(dir, label).iterator().next(); return framedGraph.frame(e, returnType); } } else if (AnnotationUtilities.isFindMethod(method)) { Vertex newVertex; Edge resultEdge = null; newVertex = ((VertexFrame) arguments[0]).asVertex(); resultEdge = findEdge(annotation, framedGraph, vertex, newVertex); if (resultEdge != null) { return framedGraph.frame(resultEdge, method.getReturnType()); } } else if (AnnotationUtilities.isCountMethod(method)) { return countEdges(annotation, vertex); } else if (ClassUtilities.isAddMethod(method)) { Vertex newVertex; Edge resultEdge = null; newVertex = ((VertexFrame) arguments[0]).asVertex(); if (unique) { resultEdge = findEdge(annotation, framedGraph, vertex, newVertex); } if (resultEdge == null) { String replicaid = null; if (framedGraph instanceof DFramedTransactionalGraph) { DElementStore store = ((DFramedTransactionalGraph) framedGraph).getElementStore(method.getReturnType()); long rawkey = store.getStoreKey(); replicaid = NoteCoordinate.Utils.getReplidFromLong(rawkey); } resultEdge = addEdge(annotation, framedGraph, vertex, newVertex, replicaid); } return framedGraph.frame(resultEdge, method.getReturnType()); } else if (ClassUtilities.isRemoveMethod(method)) { framedGraph.removeEdge(((EdgeFrame) arguments[0]).asEdge()); return null; } return null; } @SuppressWarnings({ "rawtypes", "unchecked" }) public Object processVertexAdjacency(final Annotation annotation, final Method method, final Object[] arguments, final FramedGraph framedGraph, final Vertex vertex) { Edge resultEdge = null; Class<?> returnType = method.getReturnType(); Direction dir = Direction.BOTH; String label = ""; boolean unique = false; if (annotation instanceof Adjacency) { dir = ((Adjacency) annotation).direction(); label = ((Adjacency) annotation).label(); } else if (annotation instanceof AdjacencyUnique) { dir = ((AdjacencyUnique) annotation).direction(); label = ((AdjacencyUnique) annotation).label(); unique = true; } else if (annotation instanceof Incidence) { dir = ((Incidence) annotation).direction(); label = ((Incidence) annotation).label(); } else if (annotation instanceof IncidenceUnique) { dir = ((IncidenceUnique) annotation).direction(); label = ((IncidenceUnique) annotation).label(); unique = true; } if (ClassUtilities.isGetMethod(method)) { final FramedVertexList r = new FramedVertexList(framedGraph, vertex, vertex.getVertices(dir, label), ClassUtilities.getGenericClass(method)); if (ClassUtilities.returnsIterable(method)) { return r; } else { return r.iterator().hasNext() ? r.iterator().next() : null; } } else if (ClassUtilities.isAddMethod(method)) { 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(); } if (unique) { resultEdge = findEdge(annotation, framedGraph, vertex, newVertex); } if (resultEdge == null) { String replicaid = null; if (framedGraph instanceof DFramedTransactionalGraph) { DElementStore store = ((DFramedTransactionalGraph) framedGraph).getElementStore(returnType); long rawkey = store.getStoreKey(); replicaid = NoteCoordinate.Utils.getReplidFromLong(rawkey); } resultEdge = addEdge(annotation, framedGraph, vertex, newVertex, replicaid); } if (returnType.isPrimitive()) { return null; } else if (Edge.class.isAssignableFrom(returnType)) { return resultEdge; } else if (EdgeFrame.class.isAssignableFrom(returnType)) { // System.out.println("TEMP DEBUG about to wrap edge with id " + resultEdge.getId()); Object result = framedGraph.frame(resultEdge, returnType); return result; } else { return returnValue; } } else if (ClassUtilities.isRemoveMethod(method)) { removeEdges(dir, label, vertex, ((VertexFrame) arguments[0]).asVertex(), framedGraph); return null; } else if (AnnotationUtilities.isCountMethod(method)) { return countEdges(annotation, vertex); } else if (ClassUtilities.isSetMethod(method)) { removeEdges(dir, label, vertex, null, framedGraph); if (ClassUtilities.acceptsIterable(method)) { for (Object o : (Iterable) arguments[0]) { Vertex v = ((VertexFrame) o).asVertex(); addEdge(annotation, framedGraph, vertex, v, null); } return null; } else { if (null != arguments[0]) { Vertex newVertex = ((VertexFrame) arguments[0]).asVertex(); addEdge(annotation, framedGraph, vertex, newVertex, null); } return null; } } return null; } @SuppressWarnings("rawtypes") private Edge findEdge(final Annotation annotation, final FramedGraph framedGraph, final Vertex vertex, final Vertex newVertex) { Edge result = null; Direction dir = Direction.BOTH; String label = ""; boolean unique = false; if (annotation instanceof Adjacency) { dir = ((Adjacency) annotation).direction(); label = ((Adjacency) annotation).label(); } else if (annotation instanceof AdjacencyUnique) { dir = ((AdjacencyUnique) annotation).direction(); label = ((AdjacencyUnique) annotation).label(); unique = true; } else if (annotation instanceof Incidence) { dir = ((Incidence) annotation).direction(); label = ((Incidence) annotation).label(); } else if (annotation instanceof IncidenceUnique) { dir = ((IncidenceUnique) annotation).direction(); label = ((IncidenceUnique) annotation).label(); unique = true; } switch (dir) { case OUT: result = ((DVertex) vertex).findOutEdge(newVertex, label, unique); break; case IN: result = ((DVertex) vertex).findInEdge(newVertex, label, unique); break; default: break; } return result; } @SuppressWarnings("rawtypes") private int countEdges(final Annotation annotation, final Vertex vertex) { int result = 0; Direction dir = Direction.BOTH; String label = ""; if (annotation instanceof Adjacency) { dir = ((Adjacency) annotation).direction(); label = ((Adjacency) annotation).label(); } else if (annotation instanceof AdjacencyUnique) { dir = ((AdjacencyUnique) annotation).direction(); label = ((AdjacencyUnique) annotation).label(); } else if (annotation instanceof Incidence) { dir = ((Incidence) annotation).direction(); label = ((Incidence) annotation).label(); } else if (annotation instanceof IncidenceUnique) { dir = ((IncidenceUnique) annotation).direction(); label = ((IncidenceUnique) annotation).label(); } switch (dir) { case OUT: if (vertex instanceof DVertex) { result = ((DVertex) vertex).getOutEdgeCount(label); } else { Iterable<Edge> it = vertex.getEdges(Direction.OUT, label); if (it instanceof Collection) { result = ((Collection) it).size(); } else { for (Edge e : it) { result++; } } } break; case IN: if (vertex instanceof DVertex) { result = ((DVertex) vertex).getInEdgeCount(label); } else { Iterable<Edge> it = vertex.getEdges(Direction.IN, label); if (it instanceof Collection) { result = ((Collection) it).size(); } else { for (Edge e : it) { result++; } } } break; case BOTH: throw new UnsupportedOperationException("Direction.BOTH it not supported on 'add' or 'set' methods"); } return result; } protected NoteCoordinate getForcedId(final Vertex outVertex, final Vertex inVertex, final String label, final String replicaid) { String outString = ((NoteCoordinate) outVertex.getId()).toString(); String inString = ((NoteCoordinate) inVertex.getId()).toString(); String targetid = DominoUtils.toUnid(outString + label + inString); return NoteCoordinate.Utils.getNoteCoordinate(replicaid, targetid); } @SuppressWarnings("rawtypes") private Edge addEdge(final Annotation annotation, final FramedGraph framedGraph, final Vertex vertex, final Vertex newVertex, final String replicaid) { Edge result = null; Direction dir = Direction.BOTH; String label = ""; boolean unique = false; if (annotation instanceof Adjacency) { dir = ((Adjacency) annotation).direction(); label = ((Adjacency) annotation).label(); } else if (annotation instanceof AdjacencyUnique) { dir = ((AdjacencyUnique) annotation).direction(); label = ((AdjacencyUnique) annotation).label(); unique = true; } else if (annotation instanceof Incidence) { dir = ((Incidence) annotation).direction(); label = ((Incidence) annotation).label(); } else if (annotation instanceof IncidenceUnique) { dir = ((IncidenceUnique) annotation).direction(); label = ((IncidenceUnique) annotation).label(); unique = true; } NoteCoordinate id = null; switch (dir) { case OUT: if (unique) id = getForcedId(vertex, newVertex, label, replicaid); result = framedGraph.addEdge(id, vertex, newVertex, label); break; case IN: if (unique) id = getForcedId(newVertex, vertex, label, replicaid); result = framedGraph.addEdge(id, newVertex, vertex, label); break; case BOTH: throw new UnsupportedOperationException("Direction.BOTH it not supported on 'add' or 'set' methods"); } return result; } @SuppressWarnings("rawtypes") 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()).getId().equals(otherVertex.getId())) { framedGraph.removeEdge(edge); } } } }