From 0ede593b647e11c8372ba816f12204cc1ea1258c Mon Sep 17 00:00:00 2001 From: Jeffrey Phillips Freeman <jeffrey.freeman@syncleus.com> Date: Fri, 26 Jun 2015 00:30:28 -0400 Subject: [PATCH] Began adding nested edges and cross-graph edges --- .../syncleus/ferma/mesh/LinkedMeshGraph.java | 339 ++++++++++++++---- 1 file changed, 265 insertions(+), 74 deletions(-) diff --git a/src/main/java/com/syncleus/ferma/mesh/LinkedMeshGraph.java b/src/main/java/com/syncleus/ferma/mesh/LinkedMeshGraph.java index 713f927..2091d41 100644 --- a/src/main/java/com/syncleus/ferma/mesh/LinkedMeshGraph.java +++ b/src/main/java/com/syncleus/ferma/mesh/LinkedMeshGraph.java @@ -192,6 +192,8 @@ public class LinkedMeshGraph implements MeshGraph { @Override public void moveVertex(Vertex vertex, Object subgraphId) { + // TODO : Implement this + throw new UnsupportedOperationException("This method hasnt been implemented yet, comming soon!"); } @Override @@ -233,13 +235,22 @@ public class LinkedMeshGraph implements MeshGraph { @Override public void removeVertex(Vertex vertex) { - if (!(vertex instanceof NestedVertex)) - throw new IllegalArgumentException("vertex does not belong to this graph"); + if(!(vertex instanceof NestedVertex)) + throw new IllegalArgumentException("vertex is not a member of any subgraphs"); - //obtain the subgraph which has the vertex to be removed final NestedVertex nestedVertex = (NestedVertex) vertex; - //this is where the heavy lifting takes place - nestedVertex.remove(); + + final TransactionalGraph targetGraph = cachedSubgraphs.get(nestedVertex.getParentId()); + + //remove the vertex from the subgraph + pendingTransactions.add(targetGraph); + nestedVertex.getDelegate().remove(); + + //remove any mesh edges which link to this vertex from outside the subgraph + final Object subgraphVertexId = nestedVertex.getId().getSubgraphVertexId(); + pendingTransactions.add(metagraph); + metagraph.v(nestedVertex.getParentId()).inE("link").has("outId", subgraphVertexId).removeAll(); + metagraph.v(nestedVertex.getParentId()).outE("link").has("inId", subgraphVertexId).removeAll(); } @Override @@ -279,38 +290,89 @@ public class LinkedMeshGraph implements MeshGraph { } @Override - public Edge addEdge(Object id, Vertex outVertex, Vertex inVertex, String label) { - return null; + public Edge addEdge(final Object id, final Vertex outVertex, final Vertex inVertex, final String label) { + if ((id != null) && !(id instanceof MeshId)) + throw new IllegalArgumentException("id must either be null or a MeshId"); + if (!(outVertex instanceof NestedVertex)) + throw new IllegalArgumentException("outVertex is not a vertex from any of the subgraphs"); + if (!(inVertex instanceof NestedVertex)) + throw new IllegalArgumentException("inVertex is not a vertex from any of the subgraphs"); + + final MeshId meshId = (MeshId) id; + final NestedVertex nestedOutVertex = (NestedVertex) outVertex; + final NestedVertex nestedInVertex = (NestedVertex) inVertex; + final Object subgraphId; + final Object subgraphEdgeId; + if (meshId == null) + { + subgraphId = null; + subgraphEdgeId = null; + } + else { + subgraphId = meshId.getSubgraphId(); + subgraphEdgeId = meshId.getSubgraphVertexId(); + } + + //if both vertexes belong to the same subgraph than it is easy, just create a edge in that subgraph + if(nestedOutVertex.getId().getSubgraphId().equals(nestedInVertex.getId().getSubgraphId())) { + final Object writeGraphId = nestedOutVertex.getId().getSubgraphId(); + if( subgraphId != null && !subgraphId.equals(writeGraphId)) + throw new IllegalArgumentException("meshId was not null but the subgraphId did not match that of the vertex arguments"); + final TransactionalGraph subgraph = cachedSubgraphs.get(writeGraphId); + this.pendingTransactions.add(subgraph); + return new NestedEdge(subgraph.addEdge(subgraphEdgeId, nestedOutVertex.getDelegate(), nestedInVertex.getDelegate(), label), writeGraphId); + } + //we need to create a cross-graph edge + else { + if( subgraphId != null ) + throw new IllegalArgumentException("vertexs span subgraphs but id has a non null subgraphId"); + final Object inGraphId = nestedInVertex.getId().getSubgraphId(); + final Object outGraphId = nestedOutVertex.getId().getSubgraphId(); + + final Vertex inGraphVertex = metagraph.getVertex(inGraphId); + final Vertex outGraphVertex = metagraph.getVertex(outGraphId); + final Edge subedge = metagraph.addEdge(subgraphEdgeId, outGraphVertex, inGraphVertex, "link"); + subedge.setProperty("sublabel", label); + + // TODO : Finish implementing this, we still need to cast this into a LinkedEdge! + throw new UnsupportedOperationException("This method hasnt been implemented yet, comming soon!"); + } } @Override public Edge getEdge(Object id) { - return null; + // TODO : Implement this + throw new UnsupportedOperationException("This method hasnt been implemented yet, comming soon!"); } @Override public void removeEdge(Edge edge) { - + // TODO : Implement this + throw new UnsupportedOperationException("This method hasnt been implemented yet, comming soon!"); } @Override public Iterable<Edge> getEdges() { - return null; + // TODO : Implement this + throw new UnsupportedOperationException("This method hasnt been implemented yet, comming soon!"); } @Override public Iterable<Edge> getEdges(String key, Object value) { - return null; + // TODO : Implement this + throw new UnsupportedOperationException("This method hasnt been implemented yet, comming soon!"); } @Override public GraphQuery query() { - return null; + // TODO : Implement this + throw new UnsupportedOperationException("This method hasnt been implemented yet, comming soon!"); } @Override public void shutdown() { - + // TODO : Implement this + throw new UnsupportedOperationException("This method hasnt been implemented yet, comming soon!"); } @Override @@ -337,6 +399,8 @@ public class LinkedMeshGraph implements MeshGraph { @Override public void resync() { + // TODO : Implement this + throw new UnsupportedOperationException("This method hasnt been implemented yet, comming soon!"); } @Override @@ -465,47 +529,6 @@ public class LinkedMeshGraph implements MeshGraph { return features; } - /** - * An iterator which encapsulates the iterators provided by each of the subgraphs and unifies them into what appears - * to the enduser to be a single iterator. - */ - private static class SubgraphVertexIterator implements Iterator<Vertex> { - private NestedVertexIterator currentIterator = null; - final Set<NestedVertexIterator> subvertexIterators; - - public SubgraphVertexIterator(Set<NestedVertexIterator> subvertexIterators) { - this.subvertexIterators = subvertexIterators; - } - - @Override - public boolean hasNext() { - // TODO : lets try to get rrid of this while(true) it may be prone to infinite loops - while (true) { - if (currentIterator != null) { - if (currentIterator.hasNext()) - return true; - else if (subvertexIterators.isEmpty()) - return false; - } - - currentIterator = subvertexIterators.iterator().next(); - subvertexIterators.remove(currentIterator); - } - } - - @Override - public Vertex next() { - // TODO : lets try to get rrid of this while(true) it may be prone to infinite loops - while (true) { - if ((currentIterator != null) && (currentIterator.hasNext() || subvertexIterators.isEmpty())) - return currentIterator.next(); - - currentIterator = subvertexIterators.iterator().next(); - subvertexIterators.remove(currentIterator); - } - } - } - /** * A type of Element which encapsulates the element from a subgraph. This is the type of element returned to the user * when traversing this graph. @@ -602,6 +625,142 @@ public class LinkedMeshGraph implements MeshGraph { } } + /** + * An edge representing a link across subgraphs + */ + private class LinkingEdge extends NestedElement<Edge> implements Edge { + public LinkingEdge(final Edge delegate, final Object parentId) { + super(parentId, delegate); + } + + private String encodeKey(final String key) { + //since we use a key called sublabel we want to preface any label with that name with a underscore, + //similarly any variation having some number of prefixed underscores should have one underscore added. + if(key.matches("[_]*sublabel")) + return "_" + key; + else + return key; + } + + private String decodeKey(final String key ) { + //any keys encoded with a suffix of sublabel and underscores as a prefix needs translating + if(key.matches("[_]*sublabel")) { + //we want to hide the sublabel itself, since this is already the label of the edge. + if( key.length() == 8) + return null; + + //the other labels we want to drop one of the prefixed underscores + return key.replaceFirst("_", ""); + } + //all the normal keys that dont need translating + else + return key; + } + + @Override + public <T> T getProperty(String key) { + return super.getProperty(this.encodeKey(key)); + } + + @Override + public Set<String> getPropertyKeys() { + final Set<String> translatedKeys = new HashSet<>(); + for(final String key : super.getPropertyKeys()) { + final String decodedKey = this.decodeKey(key); + if(decodedKey == null) + continue; + translatedKeys.add(decodedKey); + } + return Collections.unmodifiableSet(translatedKeys); + } + + @Override + public void setProperty(String key, Object value) { + super.setProperty(this.encodeKey(key), value); + } + + @Override + public <T> T removeProperty(String key) { + return super.removeProperty(this.encodeKey(key)); + } + + /** + * Return the tail/out or head/in vertex. + * + * @param direction whether to return the tail/out or head/in vertex + * @return the tail/out or head/in vertex + * @throws IllegalArgumentException is thrown if a direction of both is provided + */ + @Override + public Vertex getVertex(Direction direction) throws IllegalArgumentException { + // TODO : Implement this + throw new UnsupportedOperationException("This method hasnt been implemented yet, comming soon!"); + } + + /** + * Return the label associated with the edge. + * + * @return the edge label + */ + @Override + public String getLabel() { + // TODO : Implement this + throw new UnsupportedOperationException("This method hasnt been implemented yet, comming soon!"); + } + + /** + * Remove the element from the graph. + */ + @Override + public void remove() { + // TODO : Implement this + throw new UnsupportedOperationException("This method hasnt been implemented yet, comming soon!"); + } + } + + /** + * A type of Edge which encapsulates the edge from a subgraph. This is the type of vertex returned to the user + * when traversing this graph. + */ + private class NestedEdge extends NestedElement<Edge> implements Edge { + public NestedEdge(final Edge delegate, final Object parentId) { + super(parentId, delegate); + } + + /** + * Return the tail/out or head/in vertex. + * + * @param direction whether to return the tail/out or head/in vertex + * @return the tail/out or head/in vertex + * @throws IllegalArgumentException is thrown if a direction of both is provided + */ + @Override + public Vertex getVertex(Direction direction) throws IllegalArgumentException { + // TODO : Implement this + throw new UnsupportedOperationException("This method hasnt been implemented yet, comming soon!"); + } + + /** + * Return the label associated with the edge. + * + * @return the edge label + */ + @Override + public String getLabel() { + // TODO : Implement this + throw new UnsupportedOperationException("This method hasnt been implemented yet, comming soon!"); + } + + /** + * Remove the element from the graph. + */ + @Override + public void remove() { + // TODO : Implement this + throw new UnsupportedOperationException("This method hasnt been implemented yet, comming soon!"); + } + } + /** * A type of Vertex which encapsulates the vertex from a subgraph. This is the type of vertex returned to the user * when traversing this graph. @@ -613,17 +772,7 @@ public class LinkedMeshGraph implements MeshGraph { @Override public void remove() { - final TransactionalGraph targetGraph = cachedSubgraphs.get(this.getParentId()); - - //remove the vertex from the subgraph - pendingTransactions.add(targetGraph); - this.getDelegate().remove(); - - //remove any mesh edges which link to this vertex from outside the subgraph - final Object subgraphVertexId = this.getId().getSubgraphVertexId(); - pendingTransactions.add(metagraph); - metagraph.v().has("id", this.getParentId()).inE("link").has("outId", subgraphVertexId).removeAll(); - metagraph.v().has("id", this.getParentId()).outE("link").has("inId", subgraphVertexId).removeAll(); + LinkedMeshGraph.this.removeVertex(this); } @Override @@ -645,10 +794,34 @@ public class LinkedMeshGraph implements MeshGraph { @Override public Edge addEdge(String label, Vertex inVertex) { + // TODO : This should be a NestedEdge return this.getDelegate().addEdge(label, inVertex); } } + /** + * An iterator object which encapsulates the iterator from a subgraph insuring it returns the proper element type + */ + private class NestedVertexIterator implements Iterator<Vertex> { + final Object parentId; + final Iterator<Vertex> delegate; + + public NestedVertexIterator(Iterator<Vertex> delegate, Object parentId) { + this.parentId = parentId; + this.delegate = delegate; + } + + @Override + public boolean hasNext() { + return this.delegate.hasNext(); + } + + @Override + public Vertex next() { + return new NestedVertex(this.delegate.next(), this.parentId); + } + } + /** * An iterable object which encapsulates the iterable from a subgraph insuring it returns the proper element type */ @@ -668,25 +841,43 @@ public class LinkedMeshGraph implements MeshGraph { } /** - * An iterator object which encapsulates the iterator from a subgraph insuring it returns the proper element type + * An iterator which encapsulates the iterators provided by each of the subgraphs and unifies them into what appears + * to the enduser to be a single iterator. */ - private class NestedVertexIterator implements Iterator<Vertex> { - final Object parentId; - final Iterator<Vertex> delegate; + private static class SubgraphVertexIterator implements Iterator<Vertex> { + private NestedVertexIterator currentIterator = null; + final Set<NestedVertexIterator> subvertexIterators; - public NestedVertexIterator(Iterator<Vertex> delegate, Object parentId) { - this.parentId = parentId; - this.delegate = delegate; + public SubgraphVertexIterator(Set<NestedVertexIterator> subvertexIterators) { + this.subvertexIterators = subvertexIterators; } @Override public boolean hasNext() { - return this.delegate.hasNext(); + // TODO : lets try to get rrid of this while(true) it may be prone to infinite loops + while (true) { + if (currentIterator != null) { + if (currentIterator.hasNext()) + return true; + else if (subvertexIterators.isEmpty()) + return false; + } + + currentIterator = subvertexIterators.iterator().next(); + subvertexIterators.remove(currentIterator); + } } @Override public Vertex next() { - return new NestedVertex(this.delegate.next(), this.parentId); + // TODO : lets try to get rid of this while(true) it may be prone to infinite loops + while (true) { + if ((currentIterator != null) && (currentIterator.hasNext() || subvertexIterators.isEmpty())) + return currentIterator.next(); + + currentIterator = subvertexIterators.iterator().next(); + subvertexIterators.remove(currentIterator); + } } } -- GitLab