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/03/27 21:55:42 UTC

[2/6] incubator-tinkerpop git commit: Built out the existing stub for `ElementIdStrategy` and added tests.

Built out the existing stub for  `ElementIdStrategy` and added tests.


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

Branch: refs/heads/master
Commit: e54d42339cb7e5890a2ba2a56626690b4f50a14f
Parents: b0c70e2
Author: Stephen Mallette <sp...@genoprime.com>
Authored: Fri Mar 27 16:31:42 2015 -0400
Committer: Stephen Mallette <sp...@genoprime.com>
Committed: Fri Mar 27 16:31:42 2015 -0400

----------------------------------------------------------------------
 .../strategy/decoration/ElementIdStrategy.java  | 105 +++++++++++-
 .../gremlin/structure/util/ElementHelper.java   |  13 ++
 .../ElementIdStrategyTraverseTest.java          | 110 +++++++++++++
 .../gremlin/process/ProcessStandardSuite.java   |   2 +
 .../ElementIdStrategyProcessTest.java           | 161 +++++++++++++++++++
 5 files changed, 385 insertions(+), 6 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/e54d4233/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/ElementIdStrategy.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/ElementIdStrategy.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/ElementIdStrategy.java
index 81d78be..ec47787 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/ElementIdStrategy.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/ElementIdStrategy.java
@@ -22,14 +22,28 @@ import org.apache.tinkerpop.gremlin.process.traversal.T;
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.step.HasContainerHolder;
 import org.apache.tinkerpop.gremlin.process.traversal.step.filter.HasStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.AddEdgeByPathStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.AddEdgeStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.AddVertexStartStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.AddVertexStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.IdStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.PropertiesStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.PropertyElementStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.PropertyValueStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.GraphStep;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.AbstractTraversalStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.step.util.HasContainer;
 import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper;
 import org.apache.tinkerpop.gremlin.structure.Contains;
+import org.apache.tinkerpop.gremlin.structure.Element;
+import org.apache.tinkerpop.gremlin.structure.PropertyType;
+import org.apache.tinkerpop.gremlin.structure.util.ElementHelper;
 import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
 
 import java.util.Arrays;
+import java.util.UUID;
+import java.util.function.Supplier;
+import java.util.stream.Stream;
 
 /**
  * @author Marko A. Rodriguez (http://markorodriguez.com)
@@ -38,8 +52,19 @@ public final class ElementIdStrategy extends AbstractTraversalStrategy {
 
     private final String idPropertyKey;
 
-    public ElementIdStrategy(final String idPropertyKey) {
+    private final Supplier<Object> idMaker;
+
+    private ElementIdStrategy(final String idPropertyKey, final Supplier<Object> idMaker) {
         this.idPropertyKey = idPropertyKey;
+        this.idMaker = idMaker;
+    }
+
+    public String getIdPropertyKey() {
+        return idPropertyKey;
+    }
+
+    public Supplier<Object> getIdMaker() {
+        return idMaker;
     }
 
     @Override
@@ -50,18 +75,86 @@ public final class ElementIdStrategy extends AbstractTraversalStrategy {
 
         if (traversal.getStartStep() instanceof GraphStep) {
             final GraphStep graphStep = (GraphStep) traversal.getStartStep();
-            if (graphStep instanceof HasContainerHolder)
-                ((HasContainerHolder) graphStep).addHasContainer(new HasContainer(this.idPropertyKey, Contains.within, Arrays.asList(graphStep.getIds())));
-            else
-                TraversalHelper.insertAfterStep(new HasStep(traversal, new HasContainer(this.idPropertyKey, Contains.within, Arrays.asList(graphStep.getIds()))), graphStep, traversal);
-            graphStep.clearIds();
+
+            // only need to apply the custom id if ids were assigned - otherwise we want the full iterator.
+            // note that it is then only necessary to replace the step if the id is a non-element.  other tests
+            // in the suite validate that items in getIds() is uniform so it is ok to just test the first item
+            // in the list.
+            if (graphStep.getIds().length > 0) {
+                if (graphStep instanceof HasContainerHolder) {
+                    if (!(graphStep.getIds()[0] instanceof Element))
+                        ((HasContainerHolder) graphStep).addHasContainer(new HasContainer(this.idPropertyKey, Contains.within, Arrays.asList(graphStep.getIds())));
+                } else {
+                    if (!(graphStep.getIds()[0] instanceof Element))
+                        TraversalHelper.insertAfterStep(new HasStep(traversal, new HasContainer(this.idPropertyKey, Contains.within, Arrays.asList(graphStep.getIds()))), graphStep, traversal);
+                }
+                graphStep.clearIds();
+            }
         }
 
+        TraversalHelper.getStepsOfAssignableClass(IdStep.class, traversal).stream().forEach(s -> {
+            TraversalHelper.replaceStep(s, new PropertiesStep(traversal, PropertyType.VALUE, idPropertyKey), traversal);
+        });
+
+        // in each case below, determine if the T.id is present and if so, replace T.id with the idPropertyKey or if
+        // it is not present then shove it in there and generate an id
+        TraversalHelper.getStepsOfAssignableClass(AddVertexStep.class, traversal).stream().forEach(s -> {
+            if (ElementHelper.getIdValue(s.getKeyValues()).isPresent())
+                TraversalHelper.replaceStep(s, new AddVertexStep(traversal, ElementHelper.replaceKey(s.getKeyValues(), T.id, idPropertyKey)), traversal);
+            else
+                TraversalHelper.replaceStep(s, new AddVertexStep(traversal, ElementHelper.upsert(s.getKeyValues(), idPropertyKey, idMaker.get())), traversal);
+        });
+
+        TraversalHelper.getStepsOfAssignableClass(AddVertexStartStep.class, traversal).stream().forEach(s -> {
+            if (ElementHelper.getIdValue(s.getKeyValues()).isPresent())
+                TraversalHelper.replaceStep(s, new AddVertexStartStep(traversal, ElementHelper.replaceKey(s.getKeyValues(), T.id, idPropertyKey)), traversal);
+            else
+                TraversalHelper.replaceStep(s, new AddVertexStartStep(traversal, ElementHelper.upsert(s.getKeyValues(), idPropertyKey, idMaker.get())), traversal);
+        });
+
+        TraversalHelper.getStepsOfAssignableClass(AddEdgeStep.class, traversal).stream().forEach(s -> {
+            if (ElementHelper.getIdValue(s.getKeyValues()).isPresent())
+                TraversalHelper.replaceStep(s, new AddEdgeStep(traversal, s.getDirection(), s.getEdgeLabel(), s.getVertices().iterator(), ElementHelper.replaceKey(s.getKeyValues(), T.id, idPropertyKey)), traversal);
+            else
+                TraversalHelper.replaceStep(s, new AddEdgeStep(traversal, s.getDirection(), s.getEdgeLabel(), s.getVertices().iterator(), ElementHelper.upsert(s.getKeyValues(), idPropertyKey, idMaker.get())), traversal);
+        });
+
+        TraversalHelper.getStepsOfAssignableClass(AddEdgeByPathStep.class, traversal).stream().forEach(s -> {
+            if (ElementHelper.getIdValue(s.getKeyValues()).isPresent())
+                TraversalHelper.replaceStep(s, new AddEdgeByPathStep(traversal, s.getDirection(), s.getEdgeLabel(), s.getStepLabel(), ElementHelper.replaceKey(s.getKeyValues(), T.id, idPropertyKey)), traversal);
+            else
+                TraversalHelper.replaceStep(s, new AddEdgeByPathStep(traversal, s.getDirection(), s.getEdgeLabel(), s.getStepLabel(), ElementHelper.upsert(s.getKeyValues(), idPropertyKey, idMaker.get())), traversal);
+        });
+    }
 
+    public static Builder build() {
+        return new Builder();
     }
 
     @Override
     public String toString() {
         return StringFactory.traversalStrategyString(this);
     }
+
+    public static class Builder {
+        private String idPropertyKey = "__id";
+
+        private Supplier<Object> idMaker = () -> UUID.randomUUID().toString();
+
+        private Builder() {}
+
+        public Builder idMaker(final Supplier<Object> idMaker) {
+            this.idMaker = idMaker;
+            return this;
+        }
+
+        public Builder idPropertyKey(final String idPropertyKey) {
+            this.idPropertyKey = idPropertyKey;
+            return this;
+        }
+
+        public ElementIdStrategy create() {
+            return new ElementIdStrategy(idPropertyKey, idMaker);
+        }
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/e54d4233/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/util/ElementHelper.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/util/ElementHelper.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/util/ElementHelper.java
index 7e91edf..94d4a5b 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/util/ElementHelper.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/util/ElementHelper.java
@@ -182,6 +182,19 @@ public final class ElementHelper {
         }
     }
 
+    public static Object[] replaceKey(final Object[] keyValues, final Object oldKey, final Object newKey) {
+        final Object[] kvs = new Object[keyValues.length];
+        for (int i = 0; i < keyValues.length; i = i + 2) {
+            if (keyValues[i].equals(oldKey))
+                kvs[i] = newKey;
+            else
+                kvs[i] = keyValues[i];
+            kvs[i + 1] = keyValues[i + 1];
+        }
+
+        return kvs;
+    }
+
     /**
      * Converts a set of key values to a Map.  Assumes that validations have already taken place to
      * assure that key positions contain strings and that there are an even number of elements.

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/e54d4233/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/ElementIdStrategyTraverseTest.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/ElementIdStrategyTraverseTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/ElementIdStrategyTraverseTest.java
new file mode 100644
index 0000000..75dca11
--- /dev/null
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/ElementIdStrategyTraverseTest.java
@@ -0,0 +1,110 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration;
+
+import org.apache.tinkerpop.gremlin.process.traversal.Step;
+import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.DefaultGraphTraversal;
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.AddEdgeByPathStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.AddEdgeStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.AddVertexStartStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.AddVertexStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.PropertiesStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.GraphStep;
+import org.apache.tinkerpop.gremlin.structure.Direction;
+import org.apache.tinkerpop.gremlin.structure.Graph;
+import org.apache.tinkerpop.gremlin.structure.Vertex;
+import org.apache.tinkerpop.gremlin.structure.util.ElementHelper;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import java.util.Arrays;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.mockito.Mockito.mock;
+
+/**
+ * @author Stephen Mallette (http://stephen.genoprime.com)
+ */
+@RunWith(Parameterized.class)
+public class ElementIdStrategyTraverseTest {
+    private static Traversal traversalWithAddV;
+
+    static {
+        final Graph mockedGraph = mock(Graph.class);
+        final DefaultGraphTraversal t = new DefaultGraphTraversal<>(mockedGraph);
+        t.asAdmin().addStep(new GraphStep<>(t.asAdmin(), Vertex.class));
+        traversalWithAddV = t.addV();
+    }
+
+    @Parameterized.Parameters(name = "{0}")
+    public static Iterable<Object[]> data() {
+        return Arrays.asList(new Object[][]{
+                {"addV()", traversalWithAddV, 1},
+                {"addInE()", __.addInE("test", "x"), 0},
+                {"addOutE()", __.addOutE("test", "x"), 0},
+                {"addInE()", __.addInE("test", "x", "other", "args"), 0},
+                {"addOutE()", __.addOutE("test", "x", "other", "args"), 0},
+                {"addE(OUT)", __.addE(Direction.OUT, "test", "x"), 0},
+                {"addE(IN)", __.addE(Direction.IN, "test", "x"), 0},
+                {"out().id()", __.out().id(), 1},
+                {"in().id()", __.in().id(), 1},
+                {"outE().id()", __.outE().id(), 1},
+                {"inE().id()", __.inE().id(), 1},
+                {"bothE().id()", __.bothE().id(), 1},
+                {"bothE().otherV().id()", __.bothE().otherV().id(), 2},
+                {"in().out().addInE()", __.in().out().addInE("test", "x"), 2},
+                {"in().out().addOutE()", __.in().out().addOutE("test", "x"), 2},
+                {"in().out().addE(OUT)", __.in().out().addE(Direction.OUT, "test", "x"), 2},
+                {"in().out().addE(IN)", __.in().out().addE(Direction.IN, "test", "x"), 2}});
+    }
+
+    @Parameterized.Parameter(value = 0)
+    public String name;
+
+    @Parameterized.Parameter(value = 1)
+    public Traversal traversal;
+
+    @Parameterized.Parameter(value = 2)
+    public int expectedInsertedSteps;
+
+    @Test
+    public void shouldAlterTraversalToIncludeIdWhereNecessary() {
+        final ElementIdStrategy strategy = ElementIdStrategy.build().create();
+        strategy.apply(traversal.asAdmin());
+
+        final Step s = (Step) traversal.asAdmin().getSteps().get(expectedInsertedSteps);
+        if(s instanceof AddVertexStep)
+            assertTrue(ElementHelper.getKeys(((AddVertexStep) s).getKeyValues()).contains(strategy.getIdPropertyKey()));
+        else if(s instanceof AddVertexStartStep)
+            assertTrue(ElementHelper.getKeys(((AddVertexStartStep) s).getKeyValues()).contains(strategy.getIdPropertyKey()));
+        else if(s instanceof AddEdgeByPathStep)
+            assertTrue(ElementHelper.getKeys(((AddEdgeByPathStep) s).getKeyValues()).contains(strategy.getIdPropertyKey()));
+        else if(s instanceof AddEdgeStep)
+            assertTrue(ElementHelper.getKeys(((AddEdgeStep) s).getKeyValues()).contains(strategy.getIdPropertyKey()));
+        else if(s instanceof PropertiesStep)
+            assertEquals(strategy.getIdPropertyKey(), ((PropertiesStep) s).getPropertyKeys()[0]);
+        else
+            fail("Check test definition - the expectedInsertedSteps should be the index of the step to trigger the ID substitution");
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/e54d4233/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/ProcessStandardSuite.java
----------------------------------------------------------------------
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/ProcessStandardSuite.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/ProcessStandardSuite.java
index 72d92b0..c2af8e7 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/ProcessStandardSuite.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/ProcessStandardSuite.java
@@ -74,6 +74,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.StoreTest;
 import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.SubgraphTest;
 import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.TreeTest;
 import org.apache.tinkerpop.gremlin.process.traversal.step.util.PathTest;
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.ElementIdStrategyProcessTest;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.EventStrategyProcessTest;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.PartitionStrategyProcessTest;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.ReadOnlyStrategyProcessTest;
@@ -192,6 +193,7 @@ public class ProcessStandardSuite extends AbstractGremlinSuite {
             // PageRankVertexProgramTest.class
 
             // decorations
+            ElementIdStrategyProcessTest.class,
             EventStrategyProcessTest.class,
             ReadOnlyStrategyProcessTest.class,
             PartitionStrategyProcessTest.class,

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/e54d4233/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/ElementIdStrategyProcessTest.java
----------------------------------------------------------------------
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/ElementIdStrategyProcessTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/ElementIdStrategyProcessTest.java
new file mode 100644
index 0000000..1296164
--- /dev/null
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/ElementIdStrategyProcessTest.java
@@ -0,0 +1,161 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration;
+
+import org.apache.tinkerpop.gremlin.FeatureRequirementSet;
+import org.apache.tinkerpop.gremlin.process.AbstractGremlinProcessTest;
+import org.apache.tinkerpop.gremlin.process.UseEngine;
+import org.apache.tinkerpop.gremlin.process.traversal.T;
+import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
+import org.apache.tinkerpop.gremlin.process.traversal.TraversalEngine;
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
+import org.apache.tinkerpop.gremlin.structure.Direction;
+import org.apache.tinkerpop.gremlin.structure.Edge;
+import org.apache.tinkerpop.gremlin.structure.Vertex;
+import org.apache.tinkerpop.gremlin.util.iterator.IteratorUtils;
+import org.junit.Test;
+
+import java.util.UUID;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * @author Stephen Mallette (http://stephen.genoprime.com)
+ */
+@UseEngine(TraversalEngine.Type.STANDARD)
+public class ElementIdStrategyProcessTest extends AbstractGremlinProcessTest {
+
+    @Test
+    @FeatureRequirementSet(FeatureRequirementSet.Package.VERTICES_ONLY)
+    public void shouldGenerateDefaultIdOnGraphAddVWithGeneratedDefaultId() throws Exception {
+        final ElementIdStrategy strategy = ElementIdStrategy.build().create();
+        final GraphTraversalSource sg = create(strategy);
+        final Vertex v = sg.addV("name", "stephen").next();
+        assertEquals("stephen", v.value("name"));
+
+        final Traversal t1 = graph.traversal().V(v);
+        t1.asAdmin().applyStrategies();
+        System.out.println(t1);
+
+        final Traversal t2 = sg.V(v);
+        t2.asAdmin().applyStrategies();
+        System.out.println(t2);
+
+        assertNotNull(UUID.fromString(sg.V(v).id().next().toString()));
+    }
+
+    @Test
+    @FeatureRequirementSet(FeatureRequirementSet.Package.VERTICES_ONLY)
+    public void shouldGenerateDefaultIdOnGraphAddVWithGeneratedCustomId() throws Exception {
+        final ElementIdStrategy strategy = ElementIdStrategy.build().idMaker(() -> "xxx").create();
+        final GraphTraversalSource sg = create(strategy);
+        final Vertex v = sg.addV("name", "stephen").next();
+        assertEquals("stephen", v.value("name"));
+        assertEquals("xxx", sg.V(v).id().next());
+        assertEquals("xxx", sg.V("xxx").id().next());
+    }
+
+    @Test
+    @FeatureRequirementSet(FeatureRequirementSet.Package.VERTICES_ONLY)
+    public void shouldGenerateDefaultIdOnGraphAddVWithSpecifiedId() throws Exception {
+        final ElementIdStrategy strategy = ElementIdStrategy.build().create();
+        final GraphTraversalSource sg = create(strategy);
+        final Vertex v = sg.addV(T.id, "STEPHEN", "name", "stephen").next();
+        assertEquals("stephen", v.value("name"));
+        assertEquals("STEPHEN", sg.V(v).id().next());
+        assertEquals("STEPHEN", sg.V("STEPHEN").id().next());
+    }
+
+    @Test
+    @FeatureRequirementSet(FeatureRequirementSet.Package.VERTICES_ONLY)
+    public void shouldGenerateDefaultIdOnAddVWithGeneratedDefaultId() throws Exception {
+        final ElementIdStrategy strategy = ElementIdStrategy.build().create();
+        final GraphTraversalSource sg = create(strategy);
+        sg.addV().next();
+        assertEquals(1, IteratorUtils.count(sg.V()));
+
+        final Vertex v = sg.V().addV("name", "stephen").next();
+        assertEquals("stephen", v.value("name"));
+        assertNotNull(UUID.fromString(sg.V(v).id().next().toString()));
+    }
+
+    @Test
+    @FeatureRequirementSet(FeatureRequirementSet.Package.VERTICES_ONLY)
+    public void shouldGenerateDefaultIdOnAddVWithGeneratedCustomId() throws Exception {
+        final AtomicBoolean first = new AtomicBoolean(false);
+        final ElementIdStrategy strategy = ElementIdStrategy.build().idMaker(() -> {
+            final String key = first.get() ? "xxx" : "yyy";
+            first.set(true);
+            return key;
+        }).create();
+        final GraphTraversalSource sg = create(strategy);
+        sg.addV().next();
+        assertEquals(1, IteratorUtils.count(sg.V()));
+
+        final Vertex v = sg.V().addV("name", "stephen").next();
+        assertEquals("stephen", v.value("name"));
+        assertEquals("xxx", sg.V(v).id().next());
+        assertEquals("xxx", sg.V("xxx").id().next());
+        assertEquals("yyy", sg.V("yyy").id().next());
+    }
+
+    @Test
+    @FeatureRequirementSet(FeatureRequirementSet.Package.VERTICES_ONLY)
+    public void shouldGenerateDefaultIdOnAddVWithSpecifiedId() throws Exception {
+        final ElementIdStrategy strategy = ElementIdStrategy.build().create();
+        final GraphTraversalSource sg = create(strategy);
+        sg.addV().next();
+        assertEquals(1, IteratorUtils.count(sg.V()));
+
+        final Vertex v = sg.V().addV(T.id, "STEPHEN", "name", "stephen").next();
+        assertEquals("stephen", v.value("name"));
+        assertEquals("STEPHEN", sg.V(v).id().next());
+        assertEquals("STEPHEN", sg.V("STEPHEN").id().next());
+    }
+
+    @Test
+    @FeatureRequirementSet(FeatureRequirementSet.Package.SIMPLE)
+    public void shouldGenerateDefaultIdOnAddEWithSpecifiedId() throws Exception {
+        final ElementIdStrategy strategy = ElementIdStrategy.build().create();
+        final GraphTraversalSource sg = create(strategy);
+        final Vertex v = sg.addV().next();
+        final Edge e = sg.V(v).addE(Direction.OUT, "self", v, "test", "value", T.id, "some-id").next();
+        assertEquals("value", e.value("test"));
+        assertEquals("some-id", sg.E(e).id().next());
+        assertEquals("some-id", sg.E("some-id").id().next());
+    }
+
+    @Test
+    @FeatureRequirementSet(FeatureRequirementSet.Package.SIMPLE)
+    public void shouldGenerateDefaultIdOnAddEWithGeneratedId() throws Exception {
+        final ElementIdStrategy strategy = ElementIdStrategy.build().create();
+        final GraphTraversalSource sg = create(strategy);
+        final Vertex v = sg.addV().next();
+        final Edge e = sg.V(v).addE(Direction.OUT, "self", v, "test", "value").next();
+        assertEquals("value", e.value("test"));
+        assertNotNull(UUID.fromString(sg.E(e).id().next().toString()));
+    }
+
+    private GraphTraversalSource create(final ElementIdStrategy strategy) {
+        return graphProvider.traversal(graph, strategy);
+    }
+}