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/04/10 21:29:55 UTC

incubator-tinkerpop git commit: Add tests and docs around IdManager for TinkerGraph.

Repository: incubator-tinkerpop
Updated Branches:
  refs/heads/TINKERPOP3-581 3aa7e2153 -> 48bbd1f3e


Add tests and docs around IdManager for TinkerGraph.


Project: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/commit/48bbd1f3
Tree: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/tree/48bbd1f3
Diff: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/diff/48bbd1f3

Branch: refs/heads/TINKERPOP3-581
Commit: 48bbd1f3ef654f5c79da6bf09053b4ee9d505061
Parents: 3aa7e21
Author: Stephen Mallette <sp...@genoprime.com>
Authored: Fri Apr 10 15:29:37 2015 -0400
Committer: Stephen Mallette <sp...@genoprime.com>
Committed: Fri Apr 10 15:29:37 2015 -0400

----------------------------------------------------------------------
 docs/src/implementations.asciidoc               |  24 +++-
 .../tinkergraph/structure/TinkerGraph.java      |  20 ++-
 .../tinkergraph/structure/TinkerHelper.java     |   2 +-
 .../tinkergraph/structure/TinkerVertex.java     |   6 +-
 .../structure/TinkerGraphIdManagerTest.java     | 140 +++++++++++++++++++
 5 files changed, 179 insertions(+), 13 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/48bbd1f3/docs/src/implementations.asciidoc
----------------------------------------------------------------------
diff --git a/docs/src/implementations.asciidoc b/docs/src/implementations.asciidoc
index 44e3c74..d0e9d7d 100644
--- a/docs/src/implementations.asciidoc
+++ b/docs/src/implementations.asciidoc
@@ -243,7 +243,7 @@ Validating with Gremlin-Test
 
 The operational semantics of any OLTP or OLAP implementation are validated by `gremlin-test`. Please provide the following test cases with your implementation, where `XXX` below denotes the name of your graph implementation (e.g. TinkerGraph, Neo4jGraph, HadoopGraph, etc.).
 
-NOTE: It is as important to look at "ignored" tests as it is to look at ones that fail.  The `gremlin-test` suite utilizes the `Feature` implementation exposed by the `Graph` to determine which tests to execute.  If a test utilizes features that are not supported by the graph, it will ignore them.  While that may be fine, implementers should validate that the ignored tests are appropriately bypassed and that there are no mistakes in their feature definitions.
+IMPORTANT: It is as important to look at "ignored" tests as it is to look at ones that fail.  The `gremlin-test` suite utilizes the `Feature` implementation exposed by the `Graph` to determine which tests to execute.  If a test utilizes features that are not supported by the graph, it will ignore them.  While that may be fine, implementers should validate that the ignored tests are appropriately bypassed and that there are no mistakes in their feature definitions.
 
 [source,java]
 ----
@@ -318,7 +318,9 @@ Also note that some of the tests in the Gremlin Test Suite are parameterized tes
 
 The annotation above shows that the name of each parameterized test will be prefixed with "expect" and have parentheses wrapped around the first parameter (at index 0) value supplied to each test.  This information can only be garnered by studying the test set up itself.  Once the pattern is determined and the specific unique name of the parameterized test is identified, add it to the `specific` property on the `OptOut` annotation in addition to the other arguments.
 
-These annotations help provide users a level of transparency into test suite compliance (via the xref:describe-graph[describeGraph()] utility function). It also allows implementers to have a lot of flexibility in terms of how they wish to support TinkerPop.  For example, maybe there is a single test case that prevents an implementer from claiming support of a `Feature`.  The implementer could choose to either not support the `Feature` or support it but "opt-out" of the test with a "reason" as to why so that users understand the limitation.
+These annotations help provide users a level of transparency into test suite compliance (via the xref:describe-graph[describeGraph()] utility function). It also allows implementers to have a lot of flexibility in terms of how they wish to support TinkerPop.  For example, maybe there is a single test case that prevents an implementer from claiming support of a `Feature`.  The implementer could choose to either not support the `Feature` or to support it but "opt-out" of the test with a "reason" as to why so that users understand the limitation.
+
+IMPORTANT: Before using `OptOut` be sure that the reason for using it is sound and it is more of a last resort.  It is possible that a test from the suite is doesn't properly represent the expectations of a feature, is too broad or narrow for the semantics it is trying to enforce or simply contains a bug.  Please consider raising issues in the developer mailing list with such concerns before assuming `OptOut` is the only answer.
 
 Accessibility via GremlinPlugin
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -407,7 +409,7 @@ Given the initial graph construction in the first code block, no index was defin
 Graph g = TinkerGraph.open();
 g.createIndex("name",Vertex.class)
 
-The runtimes for a vertex lookup by property is provided below for both no-index and indexed version of TinkerGraph over the Grateful Dead graph.
+The execution times for a vertex lookup by property is provided below for both no-index and indexed version of TinkerGraph over the Grateful Dead graph.
 
 [gremlin-groovy]
 ----
@@ -429,6 +431,22 @@ IMPORTANT: Each graph vendor will have different mechanism by which indices and
 
 NOTE: TinkerGraph is distributed with Gremlin Server and is therefore automatically available to it for configuration.
 
+Configuration
+~~~~~~~~~~~~~
+
+TinkerGraph has several settings that can be provided on creation via `Configuration` object:
+
+[width="100%",cols="2,10",options="header"]
+|=========================================================
+|Property |Description
+|gremlin.graph |`org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerGraph`
+|gremlin.tinkergraph.vertexIdManager |The `IdManager` implementation to use for vertices.
+|gremlin.tinkergraph.edgeIdManager |The `IdManager` implementation to use for edges.
+|gremlin.tinkergraph.vertexPropertyIdManager |The `IdManager` implementation to use for vertex properties.
+|=========================================================
+
+The `IdManager` settings above refer to how TinkerGraph will control identifiers for vertices, edges and vertex properties.  There are several options for each of these settings: `ANY`, `LONG`, `INTEGER`, `UUID`, or the fully qualified class name of an `IdManager` implementation on the classpath.  When not specified, the default values for all settings is `ANY`, meaning that the graph will work with any object on the JVM as the identifier and will generate new identifiers from `Long` when the identifier is not user supplied.  TinkerGraph will also expect the user to understand the types used for identifiers when querying, meaning that `g.V(1)` and `g.V(1L)` could return two different vertices.  `LONG`, `INTEGER` and `UUID` settings will try to coerce identifier values to the expected type as well as generate new identifiers with that specified type.
+
 [[hadoop-gremlin]]
 Hadoop-Gremlin
 --------------

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/48bbd1f3/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraph.java
----------------------------------------------------------------------
diff --git a/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraph.java b/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraph.java
index aacc223..5eb317d 100644
--- a/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraph.java
+++ b/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraph.java
@@ -71,9 +71,9 @@ public class TinkerGraph implements Graph {
         this.setProperty(Graph.GRAPH, TinkerGraph.class.getName());
     }};
 
-    public static final String CONFIG_VERTEX_ID = "tinkergraph.vertex.id";
-    public static final String CONFIG_EDGE_ID = "tinkergraph.edge.id";
-    public static final String CONFIG_VERTEX_PROPERTY_ID = "tinkergraph.vertex-property.id";
+    public static final String CONFIG_VERTEX_ID = "gremlin.tinkergraph.vertexIdManager";
+    public static final String CONFIG_EDGE_ID = "gremlin.tinkergraph.edgeIdManager";
+    public static final String CONFIG_VERTEX_PROPERTY_ID = "gremlin.tinkergraph.vertexPropertyIdManager";
 
     protected AtomicLong currentId = new AtomicLong(-1l);
     protected Map<Object, Vertex> vertices = new ConcurrentHashMap<>();
@@ -142,7 +142,7 @@ public class TinkerGraph implements Graph {
     @Override
     public Vertex addVertex(final Object... keyValues) {
         ElementHelper.legalPropertyKeyValueArray(keyValues);
-        Object idValue = ElementHelper.getIdValue(keyValues).orElse(null);
+        Object idValue = vertexIdManager.convert(ElementHelper.getIdValue(keyValues).orElse(null));
         final String label = ElementHelper.getLabelValue(keyValues).orElse(Vertex.DEFAULT_LABEL);
 
         if (null != idValue) {
@@ -448,7 +448,9 @@ public class TinkerGraph implements Graph {
 
             @Override
             public Object convert(final Object id) {
-                if (id instanceof Long)
+                if (null == id)
+                    return null;
+                else if (id instanceof Long)
                     return id;
                 else if (id instanceof Number)
                     return ((Number) id).longValue();
@@ -471,7 +473,9 @@ public class TinkerGraph implements Graph {
 
             @Override
             public Object convert(final Object id) {
-                if (id instanceof Integer)
+                if (null == id)
+                    return null;
+                else if (id instanceof Integer)
                     return id;
                 else if (id instanceof Number)
                     return ((Number) id).intValue();
@@ -494,7 +498,9 @@ public class TinkerGraph implements Graph {
 
             @Override
             public Object convert(final Object id) {
-                if (id instanceof java.util.UUID)
+                if (null == id)
+                    return null;
+                else if (id instanceof java.util.UUID)
                     return id;
                 else if (id instanceof String)
                     return java.util.UUID.fromString((String) id);

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/48bbd1f3/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerHelper.java
----------------------------------------------------------------------
diff --git a/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerHelper.java b/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerHelper.java
index 08570c8..3105b7b 100644
--- a/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerHelper.java
+++ b/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerHelper.java
@@ -50,7 +50,7 @@ public final class TinkerHelper {
         ElementHelper.validateLabel(label);
         ElementHelper.legalPropertyKeyValueArray(keyValues);
 
-        Object idValue = ElementHelper.getIdValue(keyValues).orElse(null);
+        Object idValue = graph.edgeIdManager.convert(ElementHelper.getIdValue(keyValues).orElse(null));
 
         final Edge edge;
         if (null != idValue) {

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/48bbd1f3/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerVertex.java
----------------------------------------------------------------------
diff --git a/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerVertex.java b/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerVertex.java
index e9a4632..ec97d0b 100644
--- a/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerVertex.java
+++ b/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerVertex.java
@@ -92,11 +92,13 @@ public class TinkerVertex extends TinkerElement implements Vertex {
         if (optionalVertexProperty.isPresent()) return optionalVertexProperty.get();
 
         if (TinkerHelper.inComputerMode(this.graph)) {
-            VertexProperty<V> vertexProperty = (VertexProperty<V>) this.graph.graphView.addProperty(this, key, value);
+            final VertexProperty<V> vertexProperty = (VertexProperty<V>) this.graph.graphView.addProperty(this, key, value);
             ElementHelper.attachProperties(vertexProperty, keyValues);
             return vertexProperty;
         } else {
-            final Object idValue = optionalId.isPresent() ? optionalId.get() : graph.vertexPropertyIdManager.getNextId(graph);
+            final Object idValue = optionalId.isPresent() ?
+                    graph.vertexPropertyIdManager.convert(optionalId.get()) :
+                    graph.vertexPropertyIdManager.getNextId(graph);
 
             final VertexProperty<V> vertexProperty = new TinkerVertexProperty<V>(idValue, this, key, value);
 

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/48bbd1f3/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraphIdManagerTest.java
----------------------------------------------------------------------
diff --git a/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraphIdManagerTest.java b/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraphIdManagerTest.java
new file mode 100644
index 0000000..6de17ba
--- /dev/null
+++ b/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraphIdManagerTest.java
@@ -0,0 +1,140 @@
+package org.apache.tinkerpop.gremlin.tinkergraph.structure;
+
+import org.apache.commons.configuration.BaseConfiguration;
+import org.apache.commons.configuration.Configuration;
+import org.apache.tinkerpop.gremlin.process.traversal.T;
+import org.apache.tinkerpop.gremlin.structure.Edge;
+import org.apache.tinkerpop.gremlin.structure.Graph;
+import org.apache.tinkerpop.gremlin.structure.Vertex;
+import org.apache.tinkerpop.gremlin.structure.VertexProperty;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.experimental.runners.Enclosed;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import java.util.Arrays;
+import java.util.UUID;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * @author Stephen Mallette (http://stephen.genoprime.com)
+ */
+@RunWith(Enclosed.class)
+public class TinkerGraphIdManagerTest {
+
+    @RunWith(Parameterized.class)
+    public static class NumberIdManagerTest {
+        private static final Configuration longIdManagerConfig = new BaseConfiguration();
+        private static final Configuration integerIdManagerConfig = new BaseConfiguration();
+
+        @Parameterized.Parameters(name = "{0}")
+        public static Iterable<Object[]> data() {
+            return Arrays.asList(new Object[][]{
+                    {"coerceLong", 100l, 200l, 300l},
+                    {"coerceInt", 100, 200, 300},
+                    {"coerceDouble", 100d, 200d, 300d},
+                    {"coerceFloat", 100f, 200f, 300f},
+                    {"coerceString", "100", "200", "300"}});
+        }
+
+        @Parameterized.Parameter(value = 0)
+        public String name;
+
+        @Parameterized.Parameter(value = 1)
+        public Object vertexIdValue;
+
+        @Parameterized.Parameter(value = 2)
+        public Object edgeIdValue;
+
+        @Parameterized.Parameter(value = 3)
+        public Object vertexPropertyIdValue;
+
+
+        @BeforeClass
+        public static void setup() {
+            longIdManagerConfig.addProperty(TinkerGraph.CONFIG_EDGE_ID, TinkerGraph.DefaultIdManager.LONG.name());
+            longIdManagerConfig.addProperty(TinkerGraph.CONFIG_VERTEX_ID, TinkerGraph.DefaultIdManager.LONG.name());
+            longIdManagerConfig.addProperty(TinkerGraph.CONFIG_VERTEX_PROPERTY_ID, TinkerGraph.DefaultIdManager.LONG.name());
+
+            integerIdManagerConfig.addProperty(TinkerGraph.CONFIG_EDGE_ID, TinkerGraph.DefaultIdManager.INTEGER.name());
+            integerIdManagerConfig.addProperty(TinkerGraph.CONFIG_VERTEX_ID, TinkerGraph.DefaultIdManager.INTEGER.name());
+            integerIdManagerConfig.addProperty(TinkerGraph.CONFIG_VERTEX_PROPERTY_ID, TinkerGraph.DefaultIdManager.INTEGER.name());
+        }
+
+        @Test
+        public void shouldUseLongIdManagerToCoerceTypes() {
+            final Graph graph = TinkerGraph.open(longIdManagerConfig);
+            final Vertex v = graph.addVertex(T.id, vertexIdValue);
+            final VertexProperty vp = v.property("test", "value", T.id, vertexPropertyIdValue);
+            final Edge e = v.addEdge("self", v, T.id, edgeIdValue);
+
+            assertEquals(100l, v.id());
+            assertEquals(200l, e.id());
+            assertEquals(300l, vp.id());
+        }
+
+        @Test
+        public void shouldUseIntegerIdManagerToCoerceTypes() {
+            final Graph graph = TinkerGraph.open(integerIdManagerConfig);
+            final Vertex v = graph.addVertex(T.id, vertexIdValue);
+            final VertexProperty vp = v.property("test", "value", T.id, vertexPropertyIdValue);
+            final Edge e = v.addEdge("self", v, T.id, edgeIdValue);
+
+            assertEquals(100, v.id());
+            assertEquals(200, e.id());
+            assertEquals(300, vp.id());
+        }
+    }
+
+
+    @RunWith(Parameterized.class)
+    public static class UuidIdManagerTest {
+        private static final Configuration idManagerConfig = new BaseConfiguration();
+
+        private static final UUID vertexId = UUID.fromString("0E939658-ADD2-4598-A722-2FC178E9B741");
+        private static final UUID edgeId = UUID.fromString("748179AA-E319-8C36-41AE-F3576B73E05C");
+        private static final UUID vertexPropertyId = UUID.fromString("EC27384C-39A0-923D-9410-271B585683B6");
+
+
+        @Parameterized.Parameters(name = "{0}")
+        public static Iterable<Object[]> data() {
+            return Arrays.asList(new Object[][]{
+                    {"coerceUuid", vertexId, edgeId, vertexPropertyId},
+                    {"coerceString", vertexId.toString(), edgeId.toString(), vertexPropertyId.toString()}});
+        }
+
+        @Parameterized.Parameter(value = 0)
+        public String name;
+
+        @Parameterized.Parameter(value = 1)
+        public Object vertexIdValue;
+
+        @Parameterized.Parameter(value = 2)
+        public Object edgeIdValue;
+
+        @Parameterized.Parameter(value = 3)
+        public Object vertexPropertyIdValue;
+
+
+        @BeforeClass
+        public static void setup() {
+            idManagerConfig.addProperty(TinkerGraph.CONFIG_EDGE_ID, TinkerGraph.DefaultIdManager.UUID.name());
+            idManagerConfig.addProperty(TinkerGraph.CONFIG_VERTEX_ID, TinkerGraph.DefaultIdManager.UUID.name());
+            idManagerConfig.addProperty(TinkerGraph.CONFIG_VERTEX_PROPERTY_ID, TinkerGraph.DefaultIdManager.UUID.name());
+        }
+
+        @Test
+        public void shouldUseIdManagerToCoerceTypes() {
+            final Graph graph = TinkerGraph.open(idManagerConfig);
+            final Vertex v = graph.addVertex(T.id, vertexIdValue);
+            final VertexProperty vp = v.property("test", "value", T.id, vertexPropertyIdValue);
+            final Edge e = v.addEdge("self", v, T.id, edgeIdValue);
+
+            assertEquals(vertexId, v.id());
+            assertEquals(edgeId, e.id());
+            assertEquals(vertexPropertyId, vp.id());
+        }
+    }
+}