package dgm.streaming.blueprints; import com.tinkerpop.blueprints.*; import dgm.streaming.command.GraphCommand; import java.util.*; import static dgm.streaming.command.GraphCommandBuilder.*; public final class StreamingGraph implements Graph { private final List<GraphCommandListener> graphCommandListeners = new ArrayList<GraphCommandListener>(); private final Graph wrapped; public StreamingGraph(Graph wrapped) { this.wrapped = wrapped; } @Override public Features getFeatures() { return wrapped.getFeatures(); } @Override public Vertex addVertex(Object o) { GraphCommand command = addNodeCommand(node(o.toString())).build(); notifyGraphCommandListeners(command); return wrapped.addVertex(o); } @Override public Vertex getVertex(Object o) { return wrapped.getVertex(o); } @Override public void removeVertex(Vertex vertex) { GraphCommand command = deleteNodeCommand(vertex.getId().toString()).build(); notifyGraphCommandListeners(command); wrapped.removeVertex(vertex); } @Override public Iterable<Vertex> getVertices() { return new Iterable<Vertex>() { @Override public Iterator<Vertex> iterator() { return new VertexIteratorWrapper(wrapped.getVertices().iterator()); } }; } @Override public Iterable<Vertex> getVertices(final String s, final Object o) { return new Iterable<Vertex>() { @Override public Iterator<Vertex> iterator() { return new VertexIteratorWrapper(wrapped.getVertices(s, o).iterator()); } }; } @Override public Edge addEdge(Object o, Vertex vertex, Vertex vertex1, String s) { NodeBuilder edgeBuilder = edge(o.toString(), vertex.getId().toString(), vertex1.getId().toString(), true) .set("label", s); notifyGraphCommandListeners(addEdgeCommand(edgeBuilder).build()); return new StreamingEdge(wrapped.addEdge(o, vertex, vertex1, s)); } @Override public Edge getEdge(Object o) { return new StreamingEdge(wrapped.getEdge(o)); } @Override public void removeEdge(Edge edge) { notifyGraphCommandListeners(deleteEdgeCommand(edge.getId().toString()).build()); wrapped.removeEdge(edge); } @Override public Iterable<Edge> getEdges() { return new Iterable<Edge>() { @Override public Iterator<Edge> iterator() { return new EdgeIteratorWrapper(wrapped.getEdges().iterator()); } }; } @Override public Iterable<Edge> getEdges(final String s, final Object o) { return new Iterable<Edge>() { @Override public Iterator<Edge> iterator() { return new EdgeIteratorWrapper(wrapped.getEdges(s, o).iterator()); } }; } @Override public void shutdown() { wrapped.shutdown(); } public void addGraphCommandListener(GraphCommandListener graphCommandListener) { graphCommandListeners.add(graphCommandListener); } public void removeGraphCommandListener(GraphCommandListener graphCommandListener) { graphCommandListeners.remove(graphCommandListener); } public List<GraphCommandListener> findListeners(GraphCommandListenerFilter filter) { List<GraphCommandListener> found = new ArrayList<GraphCommandListener>(); for (GraphCommandListener listener : graphCommandListeners) { if (filter.matches(listener)) found.add(listener); } return Collections.unmodifiableList(found); } protected void notifyGraphCommandListeners(GraphCommand graphCommand) { //simple way to get a consistent view on a possibly changing collection for (GraphCommandListener listener : Collections.unmodifiableList(graphCommandListeners)) { listener.commandCreated(graphCommand); } } public interface GraphCommandListenerFilter { boolean matches(GraphCommandListener listener); } final class StreamingVertex implements Vertex { private final Vertex wrapped; StreamingVertex(Vertex wrapped) { this.wrapped = wrapped; } @Override public Iterable<Edge> getEdges(Direction direction, String... labels) { return wrapped.getEdges(direction, labels); } @Override public Iterable<Vertex> getVertices(final Direction direction, final String... labels) { return new Iterable<Vertex>() { @Override public Iterator<Vertex> iterator() { return new VertexIteratorWrapper(wrapped.getVertices(direction, labels).iterator()); } }; } @Override public Query query() { return wrapped.query(); } @Override public Object getProperty(String key) { return wrapped.getProperty(key); } @Override public Set<String> getPropertyKeys() { return wrapped.getPropertyKeys(); } @Override public void setProperty(String key, Object value) { notifyGraphCommandListeners(updateNodeCommand(node(wrapped.getId().toString()).set(key, value)).build()); wrapped.setProperty(key, value); } /** * Delete the property, and then create a node command to update the existing node with * the remaining properties * */ @Override public Object removeProperty(String key) { notifyGraphCommandListeners(updateNodeCommand(node(wrapped.getId().toString()).set(key, null)).build()); return wrapped.removeProperty(key); } @Override public Object getId() { return wrapped.getId(); } } final class StreamingEdge implements Edge { private final Edge wrapped; StreamingEdge(Edge wrapped) { this.wrapped = wrapped; } @Override public Vertex getVertex(Direction direction) { return new StreamingVertex(wrapped.getVertex(direction)); } @Override public String getLabel() { return wrapped.getLabel(); } @Override public Object getProperty(String key) { return wrapped.getProperty(key); } @Override public Set<String> getPropertyKeys() { return wrapped.getPropertyKeys(); } @Override public void setProperty(String key, Object value) { NodeBuilder edgeBuilder = node(wrapped.getId().toString()).set(key, value); notifyGraphCommandListeners(updateEdgeCommand(edgeBuilder).build()); wrapped.setProperty(key, value); } @Override public Object removeProperty(String key) { NodeBuilder edgeBuilder = node(wrapped.getId().toString()).set(key, null); notifyGraphCommandListeners(updateEdgeCommand(edgeBuilder).build()); return wrapped.removeProperty(key); } @Override public Object getId() { return wrapped.getId(); } } final class VertexIteratorWrapper implements Iterator<Vertex> { private final Iterator<Vertex> wrappedIterator; VertexIteratorWrapper(Iterator<Vertex> wrapped) { this.wrappedIterator = wrapped; } @Override public boolean hasNext() { return wrappedIterator.hasNext(); } @Override public Vertex next() { return new StreamingVertex(wrappedIterator.next()); } @Override public void remove() { wrappedIterator.remove(); } } final class EdgeIteratorWrapper implements Iterator<Edge> { private final Iterator<Edge> edgeIterator; EdgeIteratorWrapper(Iterator<Edge> wrapped) { this.edgeIterator = wrapped; } @Override public boolean hasNext() { return edgeIterator.hasNext(); } @Override public Edge next() { return new StreamingEdge(edgeIterator.next()); } @Override public void remove() { edgeIterator.remove(); } } }