You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tinkerpop.apache.org by sp...@apache.org on 2015/05/06 14:26:49 UTC
incubator-tinkerpop git commit: Provides a fix for TINKERPOP3-660
with the GraphMLReader.
Repository: incubator-tinkerpop
Updated Branches:
refs/heads/master dcead316c -> da90fd5b9
Provides a fix for TINKERPOP3-660 with the GraphMLReader.
GraphMLReader was not able to properly read <edge> elements before <node> elements. The <edge> would create/cache the vertex, but then when the <node> came along it would only find it in the cache and not set the properties. Note that this comes with a limitation that the vertex label will not be set if the <edge> comes before the <vertex> as per the TinkerPop contract that vertex labels can not be changed. That limitation has been documented.
Project: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/commit/da90fd5b
Tree: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/tree/da90fd5b
Diff: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/diff/da90fd5b
Branch: refs/heads/master
Commit: da90fd5b97caa4ddeb6752faae6f5d5425051c20
Parents: dcead31
Author: Stephen Mallette <sp...@genoprime.com>
Authored: Wed May 6 08:23:38 2015 -0400
Committer: Stephen Mallette <sp...@genoprime.com>
Committed: Wed May 6 08:23:38 2015 -0400
----------------------------------------------------------------------
CHANGELOG.asciidoc | 1 +
docs/src/the-graph.asciidoc | 2 ++
.../structure/io/graphml/GraphMLReader.java | 20 +++++++++++++++-----
.../tinkerpop/gremlin/structure/IoTest.java | 18 ++++++++++++++----
.../io/graphml/tinkerpop-classic-unordered.xml | 1 +
5 files changed, 33 insertions(+), 9 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/da90fd5b/CHANGELOG.asciidoc
----------------------------------------------------------------------
diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc
index f4fae8b..4203262 100644
--- a/CHANGELOG.asciidoc
+++ b/CHANGELOG.asciidoc
@@ -25,6 +25,7 @@ image::http://www.tinkerpop.com/docs/current/images/gremlin-hindu.png[width=225]
TinkerPop 3.0.0.M9 (NOT OFFICIALLY RELEASED YET)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+* Fixed bug in `GraphML` reader that was not allowing `<edge>` elements to come before `<node>` elements as allowable by the GraphML specification.
* Added `VertexFeature.getCardinality`.
* Added `AdjacentToIncidentStrategy` which rewrites `out().count()` to `outE().count()` (and similar such patterns).
* `GryoPool` now takes a `Configuration` object which allows setting the size of the pool and the `IoRegistry` instance.
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/da90fd5b/docs/src/the-graph.asciidoc
----------------------------------------------------------------------
diff --git a/docs/src/the-graph.asciidoc b/docs/src/the-graph.asciidoc
index 88a5127..aeefbea 100644
--- a/docs/src/the-graph.asciidoc
+++ b/docs/src/the-graph.asciidoc
@@ -269,6 +269,8 @@ As GraphML is a specification for the serialization of an entire graph and not t
CAUTION: GraphML is a "lossy" format in that it only supports primitive values for properties and does not have support for `Graph` variables. It will use `toString` to serialize property values outside of those primitives.
+CAUTION: GraphML, as a specification, allows for `<edge>` and `<node>` elements to appear in any order. The `GraphMLReader` will support that, however, that capability comes with a limitation. TinkerPop does not allow the vertex label to be changed after the vertex has been created. Therefore, if an `<edge>` element comes before the `<node>` the label on the vertex will be ignored. It is thus better to order `<node>` elements in the GraphML to appear before all `<edge>` elements if vertex labels are important to the graph.
+
The following code shows how to write a `Graph` instance to file called `tinkerpop-modern.xml` and then how to read that file back into a different instance:
[source,java]
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/da90fd5b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphml/GraphMLReader.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphml/GraphMLReader.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphml/GraphMLReader.java
index 6a50679..f8d3aee 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphml/GraphMLReader.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphml/GraphMLReader.java
@@ -123,8 +123,8 @@ public class GraphMLReader implements GraphReader {
// graphml allows edges and vertices to be mixed in terms of how they are positioned
// in the xml therefore it is possible that an edge is created prior to its definition
// as a vertex.
- edgeOutVertex = findOrCreate(vertexIdOut, graphToWriteTo, supportsVertexIds, cache);
- edgeInVertex = findOrCreate(vertexIdIn, graphToWriteTo, supportsVertexIds, cache);
+ edgeOutVertex = findOrCreate(vertexIdOut, graphToWriteTo, supportsVertexIds, cache, false);
+ edgeInVertex = findOrCreate(vertexIdIn, graphToWriteTo, supportsVertexIds, cache, false);
if (supportsTx && counter.incrementAndGet() % batchSize == 0)
graphToWriteTo.tx().commit();
@@ -163,7 +163,7 @@ public class GraphMLReader implements GraphReader {
final String currentVertexLabel = Optional.ofNullable(vertexLabel).orElse(Vertex.DEFAULT_LABEL);
final Object[] propsAsArray = vertexProps.entrySet().stream().flatMap(e -> Stream.of(e.getKey(), e.getValue())).toArray();
- findOrCreate(currentVertexId, graphToWriteTo, supportsVertexIds, cache, ElementHelper.upsert(propsAsArray, T.label, currentVertexLabel));
+ findOrCreate(currentVertexId, graphToWriteTo, supportsVertexIds, cache, true, ElementHelper.upsert(propsAsArray, T.label, currentVertexLabel));
if (supportsTx && counter.incrementAndGet() % batchSize == 0)
graphToWriteTo.tx().commit();
@@ -278,9 +278,19 @@ public class GraphMLReader implements GraphReader {
}
private static Vertex findOrCreate(final Object id, final Graph graphToWriteTo, final boolean supportsIds,
- final Map<Object,Vertex> cache, final Object... args) {
+ final Map<Object,Vertex> cache, final boolean asVertex, final Object... args) {
if (cache.containsKey(id)) {
- return cache.get(id);
+ // if the request to findOrCreate come from a vertex then AND the vertex was already created, that means
+ // that the vertex was created by an edge that arrived first in the stream (allowable via GraphML
+ // specification). as the edge only carries the vertex id and not its properties, the properties
+ // of the vertex need to be attached at this point.
+ if (asVertex) {
+ final Vertex v = cache.get(id);
+ ElementHelper.attachProperties(v, args);
+ return v;
+ } else {
+ return cache.get(id);
+ }
} else {
final Object [] argsReady = supportsIds ? ElementHelper.upsert(args, T.id, id) : args;
final Vertex v = graphToWriteTo.addVertex(argsReady);
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/da90fd5b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/structure/IoTest.java
----------------------------------------------------------------------
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/structure/IoTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/structure/IoTest.java
index 697b499..cbc3473 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/structure/IoTest.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/structure/IoTest.java
@@ -121,7 +121,18 @@ public class IoTest extends AbstractGremlinTest {
@FeatureRequirement(featureClass = VertexPropertyFeatures.class, feature = FEATURE_INTEGER_VALUES)
@FeatureRequirement(featureClass = EdgePropertyFeatures.class, feature = EdgePropertyFeatures.FEATURE_FLOAT_VALUES)
public void shouldReadGraphML() throws IOException {
- readGraphMLIntoGraph(graph);
+ readGraphMLIntoGraph(graph, "tinkerpop-classic.xml");
+ assertClassicGraph(graph, false, true);
+ }
+
+ @Test
+ @FeatureRequirement(featureClass = Graph.Features.EdgeFeatures.class, feature = Graph.Features.EdgeFeatures.FEATURE_ADD_EDGES)
+ @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_ADD_VERTICES)
+ @FeatureRequirement(featureClass = VertexPropertyFeatures.class, feature = FEATURE_STRING_VALUES)
+ @FeatureRequirement(featureClass = VertexPropertyFeatures.class, feature = FEATURE_INTEGER_VALUES)
+ @FeatureRequirement(featureClass = EdgePropertyFeatures.class, feature = EdgePropertyFeatures.FEATURE_FLOAT_VALUES)
+ public void shouldReadGraphMLUnorderedElements() throws IOException {
+ readGraphMLIntoGraph(graph, "tinkerpop-classic-unordered.xml");
assertClassicGraph(graph, false, true);
}
@@ -2368,10 +2379,9 @@ public class IoTest extends AbstractGremlinTest {
validator.validate(xmlFile);
}
- private static void readGraphMLIntoGraph(final Graph g) throws IOException {
+ private static void readGraphMLIntoGraph(final Graph g, final String file) throws IOException {
final GraphReader reader = GraphMLReader.build().create();
- final String y = TestHelper.convertPackageToResourcePath(GraphMLResourceAccess.class);
- try (final InputStream stream = IoTest.class.getResourceAsStream(TestHelper.convertPackageToResourcePath(GraphMLResourceAccess.class) + "tinkerpop-classic.xml")) {
+ try (final InputStream stream = IoTest.class.getResourceAsStream(TestHelper.convertPackageToResourcePath(GraphMLResourceAccess.class) + file)) {
reader.readGraph(stream, g);
}
}
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/da90fd5b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/structure/io/graphml/tinkerpop-classic-unordered.xml
----------------------------------------------------------------------
diff --git a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/structure/io/graphml/tinkerpop-classic-unordered.xml b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/structure/io/graphml/tinkerpop-classic-unordered.xml
new file mode 100644
index 0000000..04867ba
--- /dev/null
+++ b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/structure/io/graphml/tinkerpop-classic-unordered.xml
@@ -0,0 +1 @@
+<?xml version="1.0" ?><graphml xmlns="http://graphml.graphdrawing.org/xmlns" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns http://graphml.graphdrawing.org/xmlns/1.1/graphml.xsd"><key id="labelV" for="node" attr.name="labelV" attr.type="string"></key><key id="name" for="node" attr.name="name" attr.type="string"></key><key id="lang" for="node" attr.name="lang" attr.type="string"></key><key id="age" for="node" attr.name="age" attr.type="int"></key><key id="labelE" for="edge" attr.name="labelE" attr.type="string"></key><key id="weight" for="edge" attr.name="weight" attr.type="float"></key><graph id="G" edgedefault="directed"><edge id="12" source="6" target="3"><data key="labelE">created</data><data key="weight">0.2</data></edge><node id="1"><data key="labelV">vertex</data><data key="name">marko</data><data key="age">29</data></node><node id="2"><data key="labelV">vertex</data><data key="name">vadas</data><data key="age">2
7</data></node><edge id="11" source="4" target="3"><data key="labelE">created</data><data key="weight">0.4</data></edge><node id="3"><data key="labelV">vertex</data><data key="name">lop</data><data key="lang">java</data></node><node id="4"><data key="labelV">vertex</data><data key="name">josh</data><data key="age">32</data></node><edge id="10" source="4" target="5"><data key="labelE">created</data><data key="weight">1.0</data></edge><node id="5"><data key="labelV">vertex</data><data key="name">ripple</data><data key="lang">java</data></node><node id="6"><data key="labelV">vertex</data><data key="name">peter</data><data key="age">35</data></node><edge id="7" source="1" target="2"><data key="labelE">knows</data><data key="weight">0.5</data></edge><edge id="8" source="1" target="4"><data key="labelE">knows</data><data key="weight">1.0</data></edge><edge id="9" source="1" target="3"><data key="labelE">created</data><data key="weight">0.4</data></edge></graph></graphml>
\ No newline at end of file