Skip to content
Browse files

Merge pull request #7 from 0xcaos/master

proposal for annotation extension system -- via seralf.
  • Loading branch information...
2 parents 812bc1e + 637f208 commit 996d790905cd45fa9e977ecd6ff5621804a871a8 @okram okram committed Dec 15, 2011
View
59 src/main/java/com/tinkerpop/frames/FramedEdge.java
@@ -1,59 +0,0 @@
-package com.tinkerpop.frames;
-
-import com.tinkerpop.blueprints.pgm.Edge;
-
-import java.lang.annotation.Annotation;
-import java.lang.reflect.Method;
-
-/**
- * The proxy class of a framed edge.
- *
- * @author Marko A. Rodriguez (http://markorodriguez.com)
- * @author Joshua Shinavier (http://fortytwo.net)
- */
-public class FramedEdge extends FramedElement {
-
- private Direction direction;
-
- public FramedEdge(final FramesManager manager, final Edge edge, final Direction direction) {
- super(manager, edge);
- this.direction = direction;
- }
-
- public Object invoke(final Object proxy, final Method method, final Object[] arguments) {
- final Object returnObject = super.invoke(proxy, method, arguments);
- if (NO_INVOCATION_PATH != returnObject) {
- return returnObject;
- } else {
- if (isEdgeGetter(method)) {
- return getElement();
- }
-
- final Annotation[] anns = method.getAnnotations();
- for (final Annotation ann : anns) {
- if (ann instanceof Domain & isGetMethod(method)) {
- if (this.direction.equals(Direction.STANDARD)) {
- return this.manager.frame(((Edge) element).getOutVertex(), method.getReturnType());
- } else {
- return this.manager.frame(((Edge) element).getInVertex(), method.getReturnType());
- }
- } else if (ann instanceof Range & isGetMethod(method)) {
- if (this.direction.equals(Direction.STANDARD)) {
- return this.manager.frame(((Edge) element).getInVertex(), method.getReturnType());
- } else {
- return this.manager.frame(((Edge) element).getOutVertex(), method.getReturnType());
- }
- }
- }
- throw new RuntimeException("Proxy can not invoke method: " + method);
- }
- }
-
- protected boolean isEdgeGetter(final Method method) {
- return method.getName().equals("asEdge");
- }
-
- protected Edge getEdge() {
- return (Edge) this.element;
- }
-}
View
74 src/main/java/com/tinkerpop/frames/FramedElement.java
@@ -1,6 +1,8 @@
package com.tinkerpop.frames;
+import com.tinkerpop.blueprints.pgm.Edge;
import com.tinkerpop.blueprints.pgm.Element;
+import com.tinkerpop.blueprints.pgm.Vertex;
import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationHandler;
@@ -12,18 +14,15 @@
*
* @author Marko A. Rodriguez (http://markorodriguez.com)
*/
-public abstract class FramedElement implements InvocationHandler {
+public class FramedElement implements InvocationHandler {
- protected final FramesManager manager;
+ private final Direction direction;
+ protected final FramesManager manager;
protected final Element element;
private static Method hashCodeMethod;
private static Method equalsMethod;
private static Method toStringMethod;
- private static final String SET = "set";
- private static final String GET = "get";
- private static final String REMOVE = "remove";
-
protected static Object NO_INVOCATION_PATH = new Object();
@@ -37,12 +36,16 @@
}
}
- public FramedElement(final FramesManager manager, final Element element) {
+ public FramedElement(final FramesManager manager, final Element element, final Direction direction) {
this.element = element;
this.manager = manager;
+ this.direction = direction;
+ }
+ public FramedElement(final FramesManager manager, final Element element) {
+ this(manager, element, null);
}
-
+
public Object invoke(final Object proxy, final Method method, final Object[] arguments) {
if (method.equals(hashCodeMethod)) {
@@ -52,57 +55,56 @@ public Object invoke(final Object proxy, final Method method, final Object[] arg
} else if (method.equals(toStringMethod)) {
return proxyToString(proxy);
}
-
+
+ if (isVertexGetter(method) && element instanceof Vertex) {
+ return (Vertex) getElement();
+ }else if(isEdgeGetter(method) && element instanceof Edge) {
+ return (Edge) getElement();
+ }
+
final Annotation[] annotations = method.getAnnotations();
for (final Annotation annotation : annotations) {
- if (annotation instanceof Property) {
- if (isGetMethod(method)) {
- return this.element.getProperty(((Property) annotation).value());
- } else if (isSetMethod(method)) {
- this.element.setProperty(((Property) annotation).value(), arguments[0]);
- return null;
- } else if (isRemoveMethod(method)) {
- this.element.removeProperty(((Property) annotation).value());
- return null;
- }
+ if(manager.hasAnnotationHandler(annotation.annotationType())){
+ if(element instanceof Vertex){
+ return manager.getAnnotationHandler(annotation.annotationType())
+ .processVertex(annotation, method, arguments, this.manager, (Vertex)this.element);
+ }else if(element instanceof Edge){
+ return manager.getAnnotationHandler(annotation.annotationType())
+ .processEdge(annotation, method, arguments, this.manager, (Edge)this.element, direction);
+ }
}
}
return NO_INVOCATION_PATH;
}
- protected boolean isGetMethod(final Method method) {
- return method.getName().startsWith(GET);
- }
-
- protected boolean isSetMethod(final Method method) {
- return method.getName().startsWith(SET);
- }
-
- protected boolean isRemoveMethod(final Method method) {
- return method.getName().startsWith(REMOVE);
- }
-
- protected Integer proxyHashCode(final Object proxy) {
+ private Integer proxyHashCode(final Object proxy) {
return System.identityHashCode(proxy) + this.element.hashCode();
}
- protected Boolean proxyEquals(final Object proxy, final Object other) {
+ private Boolean proxyEquals(final Object proxy, final Object other) {
if (proxy.getClass().equals(other.getClass())) {
return ((FramedElement) (Proxy.getInvocationHandler(proxy))).getElement().getId().equals(((FramedElement) (Proxy.getInvocationHandler(other))).getElement().getId());
} else {
return Boolean.FALSE;
}
}
- protected String proxyToString(final Object proxy) {
+ private String proxyToString(final Object proxy) {
return "Framed[" + ((FramedElement) Proxy.getInvocationHandler(proxy)).getElement().toString() + "]";
}
- protected Element getElement() {
+ public Element getElement() {
return this.element;
}
-
+
+ protected boolean isVertexGetter(final Method method) {
+ return method.getName().equals("asVertex");
+ }
+
+ protected boolean isEdgeGetter(final Method method) {
+ return method.getName().equals("asEdge");
+ }
}
View
160 src/main/java/com/tinkerpop/frames/FramedVertex.java
@@ -1,160 +0,0 @@
-package com.tinkerpop.frames;
-
-import com.tinkerpop.blueprints.pgm.Edge;
-import com.tinkerpop.blueprints.pgm.Graph;
-import com.tinkerpop.blueprints.pgm.Vertex;
-import com.tinkerpop.frames.util.AdjacencyCollection;
-import com.tinkerpop.frames.util.RelationCollection;
-import sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl;
-
-import java.lang.annotation.Annotation;
-import java.lang.reflect.Method;
-import java.lang.reflect.Proxy;
-import java.lang.reflect.Type;
-import java.util.Collection;
-import java.util.LinkedList;
-import java.util.List;
-
-/**
- * The proxy class of a framed vertex.
- *
- * @author Marko A. Rodriguez (http://markorodriguez.com)
- * @author Joshua Shinavier (http://fortytwo.net)
- */
-public class FramedVertex extends FramedElement {
-
- private static final String ADD = "add";
-
- public FramedVertex(final FramesManager manager, final Vertex vertex) {
- super(manager, vertex);
- }
-
- private boolean returnsCollection(final Method method) {
- return Collection.class.isAssignableFrom(method.getReturnType());
- }
-
- private boolean acceptsCollection(final Method method) {
-
- return 1 == method.getParameterTypes().length
- && Collection.class.isAssignableFrom(method.getParameterTypes()[0]);
- }
-
- public Object invoke(final Object proxy, final Method method, final Object[] arguments) {
- final Object returnObject = super.invoke(proxy, method, arguments);
- if (NO_INVOCATION_PATH != returnObject) {
- return returnObject;
- } else {
- if (isVertexGetter(method)) {
- return getVertex();
- }
-
- final Annotation[] annotations = method.getAnnotations();
- for (final Annotation annotation : annotations) {
- if (annotation instanceof Relation) {
- final Relation relation = (Relation) annotation;
- if (isGetMethod(method)) {
- RelationCollection r = new RelationCollection(this.manager, (Vertex) this.element, relation.label(), relation.direction(), getGenericClass(method));
- if (returnsCollection(method)) {
- return r;
- } else {
- return r.iterator().hasNext() ? r.iterator().next() : null;
- }
- } else if (isAddMethod(method)) {
- if (relation.direction().equals(Direction.STANDARD))
- this.manager.getGraph().addEdge(null, (Vertex) this.element, ((FramedVertex) Proxy.getInvocationHandler(arguments[0])).getVertex(), relation.label());
- else
- this.manager.getGraph().addEdge(null, ((FramedVertex) Proxy.getInvocationHandler(arguments[0])).getVertex(), (Vertex) this.element, relation.label());
- return null;
- } else if (isRemoveMethod(method)) {
- this.removeEdges(relation.direction(), relation.label(), ((FramedVertex) Proxy.getInvocationHandler(arguments[0])).getVertex());
- return null;
- } else if (isSetMethod(method)) {
- this.removeEdges(relation.direction(), relation.label(), null);
- if (acceptsCollection(method)) {
- for (Object o : (Collection) arguments[0]) {
- Vertex v = ((FramedVertex) Proxy.getInvocationHandler(o)).getVertex();
- if (relation.direction().equals(Direction.STANDARD)) {
- this.manager.getGraph().addEdge(null, (Vertex) this.element, v, relation.label());
- } else {
- this.manager.getGraph().addEdge(null, v, (Vertex) this.element, relation.label());
- }
- }
- return null;
- } else {
- if (null != arguments[0]) {
- if (relation.direction().equals(Direction.STANDARD)) {
- this.manager.getGraph().addEdge(null, (Vertex) this.element, ((FramedVertex) Proxy.getInvocationHandler(arguments[0])).getVertex(), relation.label());
- } else {
- this.manager.getGraph().addEdge(null, ((FramedVertex) Proxy.getInvocationHandler(arguments[0])).getVertex(), (Vertex) this.element, relation.label());
- }
- }
- return null;
- }
- }
- } else if (annotation instanceof Adjacency) {
- final Adjacency adjacency = (Adjacency) annotation;
- if (isGetMethod(method)) {
- return new AdjacencyCollection(this.manager, (Vertex) this.element, adjacency.label(), adjacency.direction(), getGenericClass(method));
- } else if (isAddMethod(method)) {
- if (adjacency.direction().equals(Direction.STANDARD))
- return this.manager.frame(this.manager.getGraph().addEdge(null, (Vertex) this.element, ((FramedVertex) Proxy.getInvocationHandler(arguments[0])).getVertex(), adjacency.label()), Direction.STANDARD, method.getReturnType());
- else
- return this.manager.frame(this.manager.getGraph().addEdge(null, ((FramedVertex) Proxy.getInvocationHandler(arguments[0])).getVertex(), (Vertex) this.element, adjacency.label()), Direction.INVERSE, method.getReturnType());
- } else if (isRemoveMethod(method)) {
- this.manager.getGraph().removeEdge(((FramedEdge) Proxy.getInvocationHandler(arguments[0])).getEdge());
- return null;
- }
- } /*else if (annotation instanceof GremlinInference) {
- final GremlinInference gremlinInference = (GremlinInference) annotation;
- if (isGetMethod(method)) {
- Pipe<Vertex, Vertex> pipe = Gremlin.compile(gremlinInference.script());
- pipe.setStarts(new SingleIterator<Vertex>(this.getVertex()));
- return new IterableCollection(new FramingVertexIterable(this.manager, pipe, getGenericClass(method)));
- }
- }*/
- }
- throw new RuntimeException("Proxy can not invoke method: " + method);
- }
- }
-
- protected boolean isVertexGetter(final Method method) {
- return method.getName().equals("asVertex");
- }
-
- private Class getGenericClass(final Method method) {
- final Type returnType = method.getGenericReturnType();
- if (returnType instanceof ParameterizedTypeImpl)
- return (Class) ((ParameterizedTypeImpl) returnType).getActualTypeArguments()[0];
- else
- return method.getReturnType();
- }
-
- private void removeEdges(final Direction direction, final String label, final Vertex otherVertex) {
- final Graph graph = this.manager.getGraph();
- List<Edge> toRemove = new LinkedList<Edge>();
- if (direction.equals(Direction.STANDARD)) {
- for (final Edge edge : this.getVertex().getOutEdges(label)) {
- if (null == otherVertex || edge.getInVertex().equals(otherVertex)) {
- toRemove.add(edge);
- }
- }
- } else {
- for (final Edge edge : this.getVertex().getInEdges(label)) {
- if (null == otherVertex || edge.getOutVertex().equals(otherVertex)) {
- toRemove.add(edge);
- }
- }
- }
- for (final Edge edge : toRemove) {
- graph.removeEdge(edge);
- }
- }
-
- protected boolean isAddMethod(final Method method) {
- return method.getName().startsWith(ADD);
- }
-
- protected Vertex getVertex() {
- return (Vertex) this.element;
- }
-}
View
53 src/main/java/com/tinkerpop/frames/FramesManager.java
@@ -5,10 +5,19 @@
import com.tinkerpop.blueprints.pgm.Index;
import com.tinkerpop.blueprints.pgm.IndexableGraph;
import com.tinkerpop.blueprints.pgm.Vertex;
+import com.tinkerpop.frames.annotations.AdjacencyAnnotationHandler;
+import com.tinkerpop.frames.annotations.AnnotationHandler;
+import com.tinkerpop.frames.annotations.DomainAnnotationHandler;
+import com.tinkerpop.frames.annotations.PropertyAnnotationHandler;
+import com.tinkerpop.frames.annotations.RangeAnnotationHandler;
+import com.tinkerpop.frames.annotations.RelationAnnotationHandler;
import com.tinkerpop.frames.util.FramingEdgeIterable;
import com.tinkerpop.frames.util.FramingVertexIterable;
+import java.lang.annotation.Annotation;
import java.lang.reflect.Proxy;
+import java.util.HashMap;
+import java.util.Map;
/**
* The primary class for interpreting/framing elements of a graph in terms of particulate annotated interfaces.
@@ -18,14 +27,22 @@
public class FramesManager {
private final Graph graph;
-
+ private final Map<Class<? extends Annotation>, AnnotationHandler<? extends Annotation>> annotationHandlers;
+
/**
* Construct a FramesManager that will frame elements of the provided graph.
*
* @param graph the graph whose elements to frame
*/
public FramesManager(final Graph graph) {
this.graph = graph;
+ this.annotationHandlers = new HashMap<Class<? extends Annotation>, AnnotationHandler<? extends Annotation>>();
+
+ registerAnnotationHandler(new PropertyAnnotationHandler());
+ registerAnnotationHandler(new RelationAnnotationHandler());
+ registerAnnotationHandler(new AdjacencyAnnotationHandler());
+ registerAnnotationHandler(new DomainAnnotationHandler());
+ registerAnnotationHandler(new RangeAnnotationHandler());
}
/**
@@ -46,7 +63,7 @@ public Graph getGraph() {
* @return a proxy object backed by the vertex and interpreted from the perspective of the annotate interface
*/
public <T> T frame(final Vertex vertex, final Class<T> kind) {
- return (T) Proxy.newProxyInstance(kind.getClassLoader(), new Class[]{kind}, new FramedVertex(this, vertex));
+ return (T) Proxy.newProxyInstance(kind.getClassLoader(), new Class[]{kind}, new FramedElement(this, vertex));
}
/**
@@ -59,7 +76,7 @@ public Graph getGraph() {
* @return a proxy object backed by the edge and interpreted from the perspective of the annotate interface
*/
public <T> T frame(final Edge edge, final Direction direction, final Class<T> kind) {
- return (T) Proxy.newProxyInstance(kind.getClassLoader(), new Class[]{kind}, new FramedEdge(this, edge, direction));
+ return (T) Proxy.newProxyInstance(kind.getClassLoader(), new Class[]{kind}, new FramedElement(this, edge, direction));
}
/**
@@ -117,6 +134,32 @@ public Graph getGraph() {
final Index<Edge> index = ((IndexableGraph) this.graph).getIndex(indexName, Edge.class);
return new FramingEdgeIterable<T>(this, index.get(key, value), direction, kind);
}
-
-
+
+ /**
+ * The method used to register a new annotation handler
+ * for every new annotation a new annotation handler has to be registered in the manager
+ *
+ * @param handler the annotation handler
+ */
+ public void registerAnnotationHandler(AnnotationHandler<? extends Annotation> handler){
+ annotationHandlers.put(handler.getAnnotationType(), handler);
+ }
+
+ /**
+ *
+ * @param annotationType the type of annotation handled by the annotation handler
+ * @return the annotation handler associated with the specified type
+ */
+ public AnnotationHandler getAnnotationHandler(Class<? extends Annotation> annotationType) {
+ return annotationHandlers.get(annotationType);
+ }
+
+ /**
+ *
+ * @param annotationType the type of annotation handled by the annotation handler
+ * @return a boolean indicating if the manager has registered an annotation handler for the specified type
+ */
+ public boolean hasAnnotationHandler(Class<? extends Annotation> annotationType) {
+ return annotationHandlers.containsKey(annotationType);
+ }
}
View
44 src/main/java/com/tinkerpop/frames/annotations/AdjacencyAnnotationHandler.java
@@ -0,0 +1,44 @@
+package com.tinkerpop.frames.annotations;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+
+import com.tinkerpop.blueprints.pgm.Edge;
+import com.tinkerpop.blueprints.pgm.Vertex;
+import com.tinkerpop.frames.Adjacency;
+import com.tinkerpop.frames.Direction;
+import com.tinkerpop.frames.FramedElement;
+import com.tinkerpop.frames.FramesManager;
+import com.tinkerpop.frames.util.AdjacencyCollection;
+import com.tinkerpop.frames.util.ClassUtils;
+
+public class AdjacencyAnnotationHandler implements AnnotationHandler<Adjacency> {
+
+ @Override
+ public Class<Adjacency> getAnnotationType() {
+ return Adjacency.class;
+ }
+
+ @Override
+ public Object processVertex(Adjacency adjacency, Method method, Object[] arguments, FramesManager manager, Vertex element) {
+ if (ClassUtils.isGetMethod(method)) {
+ return new AdjacencyCollection(manager, element, adjacency.label(), adjacency.direction(), ClassUtils.getGenericClass(method));
+ } else if (ClassUtils.isAddMethod(method)) {
+ if (adjacency.direction().equals(Direction.STANDARD))
+ return manager.frame(manager.getGraph().addEdge(null, element, (Vertex)((FramedElement) Proxy.getInvocationHandler(arguments[0])).getElement(), adjacency.label()), Direction.STANDARD, method.getReturnType());
+ else
+ return manager.frame(manager.getGraph().addEdge(null, (Vertex)((FramedElement) Proxy.getInvocationHandler(arguments[0])).getElement(), element, adjacency.label()), Direction.INVERSE, method.getReturnType());
+ } else if (ClassUtils.isRemoveMethod(method)) {
+ manager.getGraph().removeEdge((Edge)((FramedElement) Proxy.getInvocationHandler(arguments[0])).getElement());
+ return null;
+ }
+
+ return null;
+ }
+
+ @Override
+ public Object processEdge(Adjacency annotation, Method method, Object[] arguments, FramesManager manager, Edge element, Direction direction) {
+ throw new UnsupportedOperationException();
+ }
+
+}
View
15 src/main/java/com/tinkerpop/frames/annotations/AnnotationHandler.java
@@ -0,0 +1,15 @@
+package com.tinkerpop.frames.annotations;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+
+import com.tinkerpop.blueprints.pgm.Edge;
+import com.tinkerpop.blueprints.pgm.Vertex;
+import com.tinkerpop.frames.Direction;
+import com.tinkerpop.frames.FramesManager;
+
+public interface AnnotationHandler<T extends Annotation> {
+ public Class<T> getAnnotationType();
+ public Object processVertex(final T annotation, final Method method, final Object[] arguments, final FramesManager manager, final Vertex element);
+ public Object processEdge(final T annotation, final Method method, final Object[] arguments, final FramesManager manager, final Edge element, final Direction direction);
+}
View
32 src/main/java/com/tinkerpop/frames/annotations/DomainAnnotationHandler.java
@@ -0,0 +1,32 @@
+package com.tinkerpop.frames.annotations;
+
+import java.lang.reflect.Method;
+
+import com.tinkerpop.blueprints.pgm.Edge;
+import com.tinkerpop.blueprints.pgm.Vertex;
+import com.tinkerpop.frames.Direction;
+import com.tinkerpop.frames.Domain;
+import com.tinkerpop.frames.FramesManager;
+
+public class DomainAnnotationHandler implements AnnotationHandler<Domain> {
+
+ @Override
+ public Class<Domain> getAnnotationType() {
+ return Domain.class;
+ }
+
+ @Override
+ public Object processVertex(Domain annotation, Method method, Object[] arguments, FramesManager manager, Vertex element) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public Object processEdge(Domain annotation, Method method, Object[] arguments, FramesManager manager, Edge element, Direction direction) {
+ if (direction.equals(Direction.STANDARD)) {
+ return manager.frame(((Edge) element).getOutVertex(), method.getReturnType());
+ } else {
+ return manager.frame(((Edge) element).getInVertex(), method.getReturnType());
+ }
+ }
+
+}
View
44 src/main/java/com/tinkerpop/frames/annotations/PropertyAnnotationHandler.java
@@ -0,0 +1,44 @@
+package com.tinkerpop.frames.annotations;
+
+import java.lang.reflect.Method;
+
+import com.tinkerpop.blueprints.pgm.Edge;
+import com.tinkerpop.blueprints.pgm.Element;
+import com.tinkerpop.blueprints.pgm.Vertex;
+import com.tinkerpop.frames.Direction;
+import com.tinkerpop.frames.FramesManager;
+import com.tinkerpop.frames.Property;
+import com.tinkerpop.frames.util.ClassUtils;
+
+public class PropertyAnnotationHandler implements AnnotationHandler<Property> {
+
+ @Override
+ public Class<Property> getAnnotationType() {
+ return Property.class;
+ }
+
+ @Override
+ public Object processVertex(Property annotation, Method method, Object[] arguments, FramesManager manager, Vertex element) {
+ return process(annotation, method, arguments, element);
+ }
+
+ @Override
+ public Object processEdge(Property annotation, Method method, Object[] arguments, FramesManager manager, Edge element, Direction direction) {
+ return process(annotation, method, arguments, element);
+ }
+
+ private Object process(Property annotation, Method method, Object[] arguments, Element element){
+ if (ClassUtils.isGetMethod(method)) {
+ return element.getProperty(((Property) annotation).value());
+ } else if (ClassUtils.isSetMethod(method)) {
+ element.setProperty(((Property) annotation).value(), arguments[0]);
+ return null;
+ } else if (ClassUtils.isRemoveMethod(method)) {
+ element.removeProperty(((Property) annotation).value());
+ return null;
+ }
+
+ return null;
+ }
+
+}
View
32 src/main/java/com/tinkerpop/frames/annotations/RangeAnnotationHandler.java
@@ -0,0 +1,32 @@
+package com.tinkerpop.frames.annotations;
+
+import java.lang.reflect.Method;
+
+import com.tinkerpop.blueprints.pgm.Edge;
+import com.tinkerpop.blueprints.pgm.Vertex;
+import com.tinkerpop.frames.Direction;
+import com.tinkerpop.frames.FramesManager;
+import com.tinkerpop.frames.Range;
+
+public class RangeAnnotationHandler implements AnnotationHandler<Range> {
+
+ @Override
+ public Class<Range> getAnnotationType() {
+ return Range.class;
+ }
+
+ @Override
+ public Object processVertex(Range annotation, Method method, Object[] arguments, FramesManager manager, Vertex element) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public Object processEdge(Range annotation, Method method, Object[] arguments, FramesManager manager, Edge element, Direction direction) {
+ if (direction.equals(Direction.STANDARD)) {
+ return manager.frame(((Edge) element).getInVertex(), method.getReturnType());
+ } else {
+ return manager.frame(((Edge) element).getOutVertex(), method.getReturnType());
+ }
+ }
+
+}
View
96 src/main/java/com/tinkerpop/frames/annotations/RelationAnnotationHandler.java
@@ -0,0 +1,96 @@
+package com.tinkerpop.frames.annotations;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.List;
+
+import com.tinkerpop.blueprints.pgm.Edge;
+import com.tinkerpop.blueprints.pgm.Graph;
+import com.tinkerpop.blueprints.pgm.Vertex;
+import com.tinkerpop.frames.Direction;
+import com.tinkerpop.frames.FramedElement;
+import com.tinkerpop.frames.FramesManager;
+import com.tinkerpop.frames.Relation;
+import com.tinkerpop.frames.util.ClassUtils;
+import com.tinkerpop.frames.util.RelationCollection;
+
+public class RelationAnnotationHandler implements AnnotationHandler<Relation> {
+
+ @Override
+ public Class<Relation> getAnnotationType() {
+ return Relation.class;
+ }
+
+ @Override
+ public Object processVertex(Relation relation, Method method, Object[] arguments, FramesManager manager, Vertex element) {
+ if (ClassUtils.isGetMethod(method)) {
+ RelationCollection r = new RelationCollection(manager, (Vertex) element, relation.label(), relation.direction(), ClassUtils.getGenericClass(method));
+ if (ClassUtils.returnsCollection(method)) {
+ return r;
+ } else {
+ return r.iterator().hasNext() ? r.iterator().next() : null;
+ }
+ } else if (ClassUtils.isAddMethod(method)) {
+ if (relation.direction().equals(Direction.STANDARD))
+ manager.getGraph().addEdge(null, element, (Vertex)((FramedElement) Proxy.getInvocationHandler(arguments[0])).getElement(), relation.label());
+ else
+ manager.getGraph().addEdge(null, (Vertex)((FramedElement) Proxy.getInvocationHandler(arguments[0])).getElement(), (Vertex) element, relation.label());
+ return null;
+ } else if (ClassUtils.isRemoveMethod(method)) {
+ removeEdges(relation.direction(), relation.label(), element, (Vertex)((FramedElement) Proxy.getInvocationHandler(arguments[0])).getElement(), manager);
+ return null;
+ } else if (ClassUtils.isSetMethod(method)) {
+ removeEdges(relation.direction(), relation.label(),element, null, manager);
+ if (ClassUtils.acceptsCollection(method)) {
+ for (Object o : (Collection) arguments[0]) {
+ Vertex v = (Vertex)((FramedElement) Proxy.getInvocationHandler(o)).getElement();
+ if (relation.direction().equals(Direction.STANDARD)) {
+ manager.getGraph().addEdge(null, (Vertex) element, v, relation.label());
+ } else {
+ manager.getGraph().addEdge(null, v, (Vertex) element, relation.label());
+ }
+ }
+ return null;
+ } else {
+ if (null != arguments[0]) {
+ if (relation.direction().equals(Direction.STANDARD)) {
+ manager.getGraph().addEdge(null, (Vertex) element, (Vertex)((FramedElement) Proxy.getInvocationHandler(arguments[0])).getElement(), relation.label());
+ } else {
+ manager.getGraph().addEdge(null, (Vertex)((FramedElement) Proxy.getInvocationHandler(arguments[0])).getElement(), (Vertex) element, relation.label());
+ }
+ }
+ return null;
+ }
+ }
+
+ return null;
+ }
+
+ @Override
+ public Object processEdge(Relation annotation, Method method, Object[] arguments, FramesManager manager, Edge element, Direction direction) {
+ throw new UnsupportedOperationException();
+ }
+
+ private void removeEdges(final Direction direction, final String label, final Vertex element, final Vertex otherVertex, final FramesManager manager) {
+ final Graph graph = manager.getGraph();
+ List<Edge> toRemove = new LinkedList<Edge>();
+ if (direction.equals(Direction.STANDARD)) {
+ for (final Edge edge : element.getOutEdges(label)) {
+ if (null == otherVertex || edge.getInVertex().equals(otherVertex)) {
+ toRemove.add(edge);
+ }
+ }
+ } else {
+ for (final Edge edge : element.getInEdges(label)) {
+ if (null == otherVertex || edge.getOutVertex().equals(otherVertex)) {
+ toRemove.add(edge);
+ }
+ }
+ }
+ for (final Edge edge : toRemove) {
+ graph.removeEdge(edge);
+ }
+ }
+}
View
48 src/main/java/com/tinkerpop/frames/util/ClassUtils.java
@@ -0,0 +1,48 @@
+package com.tinkerpop.frames.util;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Type;
+import java.util.Collection;
+
+import sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl;
+
+public class ClassUtils {
+ private static final String SET = "set";
+ private static final String GET = "get";
+ private static final String REMOVE = "remove";
+ private static final String ADD = "add";
+
+ public static boolean isGetMethod(final Method method) {
+ return method.getName().startsWith(GET);
+ }
+
+ public static boolean isSetMethod(final Method method) {
+ return method.getName().startsWith(SET);
+ }
+
+ public static boolean isRemoveMethod(final Method method) {
+ return method.getName().startsWith(REMOVE);
+ }
+
+ public static boolean acceptsCollection(final Method method) {
+ return 1 == method.getParameterTypes().length
+ && Collection.class.isAssignableFrom(method.getParameterTypes()[0]);
+ }
+
+ public static boolean returnsCollection(final Method method) {
+ return Collection.class.isAssignableFrom(method.getReturnType());
+ }
+
+ public static boolean isAddMethod(final Method method) {
+ return method.getName().startsWith(ADD);
+ }
+
+ @SuppressWarnings("rawtypes")
+ public static Class getGenericClass(final Method method) {
+ final Type returnType = method.getGenericReturnType();
+ if (returnType instanceof ParameterizedTypeImpl)
+ return (Class) ((ParameterizedTypeImpl) returnType).getActualTypeArguments()[0];
+ else
+ return method.getReturnType();
+ }
+}

0 comments on commit 996d790

Please sign in to comment.
Something went wrong with that request. Please try again.