You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tinkerpop.apache.org by dk...@apache.org on 2018/01/21 01:09:32 UTC

[1/9] tinkerpop git commit: TINKERPOP-1860 Added tests for valueMap(true) variations [Forced Update!]

Repository: tinkerpop
Updated Branches:
  refs/heads/TINKERPOP-1867 86fa77a2c -> dd83c7809 (forced update)


TINKERPOP-1860 Added tests for valueMap(true) variations

Note that with GraphSON 2.0 we get back string representations of T.id and T.label. That may change for GraphSON 3.0 on the 3.3.x line of code.


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

Branch: refs/heads/TINKERPOP-1867
Commit: caede9c8ca5cad07b947a53b38a9cc145500f6bf
Parents: fbcb044
Author: Stephen Mallette <sp...@genoprime.com>
Authored: Fri Dec 29 08:02:55 2017 -0500
Committer: Stephen Mallette <sp...@genoprime.com>
Committed: Mon Jan 8 09:21:40 2018 -0500

----------------------------------------------------------------------
 .../step/map/GroovyValueMapTest.groovy          | 10 +++
 .../src/main/jython/radish/feature_steps.py     |  8 +-
 gremlin-test/features/map/ValueMap.feature      | 32 +++++++
 .../traversal/step/map/ValueMapTest.java        | 95 ++++++++++++++++++++
 4 files changed, 144 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/caede9c8/gremlin-groovy-test/src/main/groovy/org/apache/tinkerpop/gremlin/process/traversal/step/map/GroovyValueMapTest.groovy
----------------------------------------------------------------------
diff --git a/gremlin-groovy-test/src/main/groovy/org/apache/tinkerpop/gremlin/process/traversal/step/map/GroovyValueMapTest.groovy b/gremlin-groovy-test/src/main/groovy/org/apache/tinkerpop/gremlin/process/traversal/step/map/GroovyValueMapTest.groovy
index c3c20fa..046f4ef 100644
--- a/gremlin-groovy-test/src/main/groovy/org/apache/tinkerpop/gremlin/process/traversal/step/map/GroovyValueMapTest.groovy
+++ b/gremlin-groovy-test/src/main/groovy/org/apache/tinkerpop/gremlin/process/traversal/step/map/GroovyValueMapTest.groovy
@@ -34,11 +34,21 @@ public abstract class GroovyValueMapTest {
         }
 
         @Override
+        public Traversal<Vertex, Map<String, Object>> get_g_V_valueMapXtrueX() {
+            new ScriptTraversal<>(g, "gremlin-groovy", "g.V.valueMap(true)")
+        }
+
+        @Override
         public Traversal<Vertex, Map<String, List>> get_g_V_valueMapXname_ageX() {
             new ScriptTraversal<>(g, "gremlin-groovy", "g.V.valueMap('name', 'age')")
         }
 
         @Override
+        public Traversal<Vertex, Map<String, Object>> get_g_V_valueMapXtrue_name_ageX() {
+            new ScriptTraversal<>(g, "gremlin-groovy", "g.V.valueMap(true, 'name', 'age')")
+        }
+
+        @Override
         public Traversal<Vertex, Map<String, List<String>>> get_g_VX1X_outXcreatedX_valueMap(final Object v1Id) {
             new ScriptTraversal<>(g, "gremlin-groovy", "g.V(v1Id).out('created').valueMap", "v1Id", v1Id)
         }

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/caede9c8/gremlin-python/src/main/jython/radish/feature_steps.py
----------------------------------------------------------------------
diff --git a/gremlin-python/src/main/jython/radish/feature_steps.py b/gremlin-python/src/main/jython/radish/feature_steps.py
index 452eaa4..3de641e 100644
--- a/gremlin-python/src/main/jython/radish/feature_steps.py
+++ b/gremlin-python/src/main/jython/radish/feature_steps.py
@@ -33,6 +33,8 @@ regex_in = re.compile(r"([(.,\s])in\(")
 regex_is = re.compile(r"([(.,\s])is\(")
 regex_not = re.compile(r"([(.,\s])not\(")
 regex_or = re.compile(r"([(.,\s])or\(")
+regex_true = re.compile(r"(true)")
+regex_false = re.compile(r"(false)")
 
 
 ignores = [
@@ -157,6 +159,8 @@ def _convert(val, ctx):
         return Path([set([])], path_objects)
     elif isinstance(val, str) and re.match("^c\[.*\]$", val):         # parse lambda/closure
         return lambda: (val[2:-1], "gremlin-groovy")
+    elif isinstance(val, str) and re.match("^t\[.*\]$", val):         # parse instance of T enum
+        return T[val[2:-1]]
     else:
         return val
 
@@ -209,7 +213,9 @@ def _translate(traversal):
     replaced = regex_is.sub(r"\1is_(", replaced)
     replaced = regex_not.sub(r"\1not_(", replaced)
     replaced = regex_or.sub(r"\1or_(", replaced)
-    return regex_in.sub(r"\1in_(", replaced)
+    replaced = regex_in.sub(r"\1in_(", replaced)
+    replaced = regex_true.sub(r"True", replaced)
+    return regex_false.sub(r"False", replaced)
 
 
 def _make_traversal(g, traversal_string, params):

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/caede9c8/gremlin-test/features/map/ValueMap.feature
----------------------------------------------------------------------
diff --git a/gremlin-test/features/map/ValueMap.feature b/gremlin-test/features/map/ValueMap.feature
index 2390512..0860b15 100644
--- a/gremlin-test/features/map/ValueMap.feature
+++ b/gremlin-test/features/map/ValueMap.feature
@@ -33,6 +33,22 @@ Feature: Step - valueMap()
       | m[{"name": ["lop"], "lang": ["java"]}] |
       | m[{"name": ["ripple"], "lang": ["java"]}] |
 
+  Scenario: g_V_valueMapXtrueX
+    Given the modern graph
+    And the traversal of
+      """
+      g.V().valueMap(true)
+      """
+    When iterated to list
+    Then the result should be unordered
+      | result |
+      | m[{"id": "v[marko].id", "label": "person", "name": ["marko"], "age": [29]}] |
+      | m[{"id": "v[josh].id", "label": "person", "name": ["josh"], "age": [32]}] |
+      | m[{"id": "v[peter].id", "label": "person", "name": ["peter"], "age": [35]}] |
+      | m[{"id": "v[vadas].id", "label": "person", "name": ["vadas"], "age": [27]}] |
+      | m[{"id": "v[lop].id", "label": "software", "name": ["lop"], "lang": ["java"]}] |
+      | m[{"id": "v[ripple].id", "label": "software", "name": ["ripple"], "lang": ["java"]}] |
+
   Scenario: g_V_valueMapXname_ageX
     Given the modern graph
     And the traversal of
@@ -49,6 +65,22 @@ Feature: Step - valueMap()
       | m[{"name": ["lop"]}] |
       | m[{"name": ["ripple"]}] |
 
+  Scenario: g_V_valueMapXtrue_name_ageX
+    Given the modern graph
+    And the traversal of
+      """
+      g.V().valueMap(true, "name", "age")
+      """
+    When iterated to list
+    Then the result should be unordered
+      | result |
+      | m[{"id": "v[marko].id", "label": "person", "name": ["marko"], "age": [29]}] |
+      | m[{"id": "v[josh].id", "label": "person", "name": ["josh"], "age": [32]}] |
+      | m[{"id": "v[peter].id", "label": "person", "name": ["peter"], "age": [35]}] |
+      | m[{"id": "v[vadas].id", "label": "person", "name": ["vadas"], "age": [27]}] |
+      | m[{"id": "v[lop].id", "label": "software", "name": ["lop"]}] |
+      | m[{"id": "v[ripple].id", "label": "software", "name": ["ripple"]}] |
+
   Scenario: g_VX1X_outXcreatedX_valueMap
     Given the modern graph
     And using the parameter v1Id defined as "v[marko].id"

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/caede9c8/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ValueMapTest.java
----------------------------------------------------------------------
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ValueMapTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ValueMapTest.java
index 0935945..d1f08ce 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ValueMapTest.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ValueMapTest.java
@@ -23,6 +23,7 @@ import org.apache.tinkerpop.gremlin.process.AbstractGremlinProcessTest;
 import org.apache.tinkerpop.gremlin.process.GremlinProcessRunner;
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.TraversalEngine;
+import org.apache.tinkerpop.gremlin.structure.T;
 import org.apache.tinkerpop.gremlin.structure.Vertex;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -31,6 +32,7 @@ import java.util.List;
 import java.util.Map;
 
 import static org.apache.tinkerpop.gremlin.LoadGraphWith.GraphData.MODERN;
+import static org.hamcrest.core.Is.is;
 import static org.junit.Assert.*;
 
 /**
@@ -42,8 +44,12 @@ public abstract class ValueMapTest extends AbstractGremlinProcessTest {
 
     public abstract Traversal<Vertex, Map<String, List>> get_g_V_valueMap();
 
+    public abstract Traversal<Vertex, Map<String, Object>> get_g_V_valueMapXtrueX();
+
     public abstract Traversal<Vertex, Map<String, List>> get_g_V_valueMapXname_ageX();
 
+    public abstract Traversal<Vertex, Map<String, Object>> get_g_V_valueMapXtrue_name_ageX();
+
     public abstract Traversal<Vertex, Map<String, List<String>>> get_g_VX1X_outXcreatedX_valueMap(final Object v1Id);
 
     @Test
@@ -78,6 +84,43 @@ public abstract class ValueMapTest extends AbstractGremlinProcessTest {
 
     @Test
     @LoadGraphWith(MODERN)
+    public void g_V_valueMapXtrueX() {
+        final Traversal<Vertex, Map<String, Object>> traversal = get_g_V_valueMapXtrueX();
+        printTraversalForm(traversal);
+        int counter = 0;
+        while (traversal.hasNext()) {
+            counter++;
+            final Map<String, Object> values = traversal.next();
+            final String name = (String) ((List) values.get("name")).get(0);
+            assertEquals(4, values.size());
+            assertThat(values.containsKey(T.id), is(true));
+            if (name.equals("marko")) {
+                assertEquals(29, ((List) values.get("age")).get(0));
+                assertEquals("person", values.get(T.label));
+            } else if (name.equals("josh")) {
+                assertEquals(32, ((List) values.get("age")).get(0));
+                assertEquals("person", values.get(T.label));
+            } else if (name.equals("peter")) {
+                assertEquals(35, ((List) values.get("age")).get(0));
+                assertEquals("person", values.get(T.label));
+            } else if (name.equals("vadas")) {
+                assertEquals(27, ((List) values.get("age")).get(0));
+                assertEquals("person", values.get(T.label));
+            } else if (name.equals("lop")) {
+                assertEquals("java", ((List) values.get("lang")).get(0));
+                assertEquals("software", values.get(T.label));
+            } else if (name.equals("ripple")) {
+                assertEquals("java", ((List) values.get("lang")).get(0));
+                assertEquals("software", values.get(T.label));
+            } else {
+                throw new IllegalStateException("It is not possible to reach here: " + values);
+            }
+        }
+        assertEquals(6, counter);
+    }
+
+    @Test
+    @LoadGraphWith(MODERN)
     public void g_V_valueMapXname_ageX() {
         final Traversal<Vertex, Map<String, List>> traversal = get_g_V_valueMapXname_ageX();
         printTraversalForm(traversal);
@@ -113,6 +156,48 @@ public abstract class ValueMapTest extends AbstractGremlinProcessTest {
 
     @Test
     @LoadGraphWith(MODERN)
+    public void g_V_valueMapXtrue_name_ageX() {
+        final Traversal<Vertex, Map<String, Object>> traversal = get_g_V_valueMapXtrue_name_ageX();
+        printTraversalForm(traversal);
+        int counter = 0;
+        while (traversal.hasNext()) {
+            counter++;
+            final Map<String, Object> values = traversal.next();
+            final String name = (String) ((List) values.get("name")).get(0);
+            assertThat(values.containsKey(T.id), is(true));
+            if (name.equals("marko")) {
+                assertEquals(4, values.size());
+                assertEquals(29, ((List) values.get("age")).get(0));
+                assertEquals("person", values.get(T.label));
+            } else if (name.equals("josh")) {
+                assertEquals(4, values.size());
+                assertEquals(32, ((List) values.get("age")).get(0));
+                assertEquals("person", values.get(T.label));
+            } else if (name.equals("peter")) {
+                assertEquals(4, values.size());
+                assertEquals(35, ((List) values.get("age")).get(0));
+                assertEquals("person", values.get(T.label));
+            } else if (name.equals("vadas")) {
+                assertEquals(4, values.size());
+                assertEquals(27, ((List) values.get("age")).get(0));
+                assertEquals("person", values.get(T.label));
+            } else if (name.equals("lop")) {
+                assertEquals(3, values.size());
+                assertNull(values.get("lang"));
+                assertEquals("software", values.get(T.label));
+            } else if (name.equals("ripple")) {
+                assertEquals(3, values.size());
+                assertNull(values.get("lang"));
+                assertEquals("software", values.get(T.label));
+            } else {
+                throw new IllegalStateException("It is not possible to reach here: " + values);
+            }
+        }
+        assertEquals(6, counter);
+    }
+
+    @Test
+    @LoadGraphWith(MODERN)
     public void g_VX1X_outXcreatedX_valueMap() {
         final Traversal<Vertex, Map<String, List<String>>> traversal = get_g_VX1X_outXcreatedX_valueMap(convertToVertexId("marko"));
         printTraversalForm(traversal);
@@ -132,11 +217,21 @@ public abstract class ValueMapTest extends AbstractGremlinProcessTest {
         }
 
         @Override
+        public Traversal<Vertex, Map<String, Object>> get_g_V_valueMapXtrueX() {
+            return g.V().valueMap(true);
+        }
+
+        @Override
         public Traversal<Vertex, Map<String, List>> get_g_V_valueMapXname_ageX() {
             return g.V().valueMap("name", "age");
         }
 
         @Override
+        public Traversal<Vertex, Map<String, Object>> get_g_V_valueMapXtrue_name_ageX() {
+            return g.V().valueMap(true, "name", "age");
+        }
+
+        @Override
         public Traversal<Vertex, Map<String, List<String>>> get_g_VX1X_outXcreatedX_valueMap(final Object v1Id) {
             return g.V(v1Id).out("created").valueMap();
         }


[8/9] tinkerpop git commit: Implemented `reset()` in `ComputerAwareStep` to reset the `previousIterator` and reset the `finalStep` in `DefaultTraversal`. This fixes TINKERPOP-1867, a falsy behavior, mainly seen in reducing barrier steps.

Posted by dk...@apache.org.
Implemented `reset()` in `ComputerAwareStep` to reset the `previousIterator` and reset the `finalStep` in `DefaultTraversal`.
This fixes TINKERPOP-1867, a falsy behavior, mainly seen in reducing barrier steps.


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

Branch: refs/heads/TINKERPOP-1867
Commit: fa8dae8b7aed18e73f01a6b13cdf01adbcbe4461
Parents: 231bbb6
Author: Daniel Kuppitz <da...@hotmail.com>
Authored: Tue Jan 9 18:40:48 2018 -0700
Committer: Daniel Kuppitz <da...@hotmail.com>
Committed: Sat Jan 20 18:08:31 2018 -0700

----------------------------------------------------------------------
 .../traversal/step/util/ComputerAwareStep.java  |  6 +++++
 .../traversal/util/DefaultTraversal.java        |  1 +
 .../step/branch/GroovyUnionTest.groovy          |  6 +++++
 .../traversal/step/branch/UnionTest.java        | 23 ++++++++++++++------
 4 files changed, 29 insertions(+), 7 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/fa8dae8b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/ComputerAwareStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/ComputerAwareStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/ComputerAwareStep.java
index 7fda097..d025657 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/ComputerAwareStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/ComputerAwareStep.java
@@ -59,6 +59,12 @@ public abstract class ComputerAwareStep<S, E> extends AbstractStep<S, E> impleme
         return clone;
     }
 
+    @Override
+    public void reset() {
+        super.reset();
+        this.previousIterator = EmptyIterator.instance();
+    }
+
     protected abstract Iterator<Traverser.Admin<E>> standardAlgorithm() throws NoSuchElementException;
 
     protected abstract Iterator<Traverser.Admin<E>> computerAlgorithm() throws NoSuchElementException;

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/fa8dae8b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/DefaultTraversal.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/DefaultTraversal.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/DefaultTraversal.java
index b2c9a35..585a82b 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/DefaultTraversal.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/DefaultTraversal.java
@@ -208,6 +208,7 @@ public class DefaultTraversal<S, E> implements Traversal.Admin<S, E> {
     @Override
     public void reset() {
         this.steps.forEach(Step::reset);
+        this.finalEndStep.reset();
         this.lastTraverser = EmptyTraverser.instance();
     }
 

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/fa8dae8b/gremlin-groovy-test/src/main/groovy/org/apache/tinkerpop/gremlin/process/traversal/step/branch/GroovyUnionTest.groovy
----------------------------------------------------------------------
diff --git a/gremlin-groovy-test/src/main/groovy/org/apache/tinkerpop/gremlin/process/traversal/step/branch/GroovyUnionTest.groovy b/gremlin-groovy-test/src/main/groovy/org/apache/tinkerpop/gremlin/process/traversal/step/branch/GroovyUnionTest.groovy
index 5627cdc..50d590e 100644
--- a/gremlin-groovy-test/src/main/groovy/org/apache/tinkerpop/gremlin/process/traversal/step/branch/GroovyUnionTest.groovy
+++ b/gremlin-groovy-test/src/main/groovy/org/apache/tinkerpop/gremlin/process/traversal/step/branch/GroovyUnionTest.groovy
@@ -73,5 +73,11 @@ public abstract class GroovyUnionTest {
                 final Object v1Id, final Object v2Id) {
             new ScriptTraversal<>(g, "gremlin-groovy", "g.V(v1Id, v2Id).local(union(outE().count, inE().count, outE().weight.sum))", "v1Id", v1Id, "v2Id", v2Id);
         }
+
+        @Override
+        public Traversal<Vertex, Number> get_g_VX1_2X_localXunionXcountXX(
+                final Object v1Id, final Object v2Id) {
+            new ScriptTraversal<>(g, "gremlin-groovy", "g.V(v1Id, v2Id).local(union(count()))", "v1Id", v1Id, "v2Id", v2Id);
+        }
     }
 }

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/fa8dae8b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/UnionTest.java
----------------------------------------------------------------------
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/UnionTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/UnionTest.java
index df52f9b..03abc03 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/UnionTest.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/UnionTest.java
@@ -31,13 +31,7 @@ import java.util.HashMap;
 import java.util.Map;
 
 import static org.apache.tinkerpop.gremlin.LoadGraphWith.GraphData.MODERN;
-import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.in;
-import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.inE;
-import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.label;
-import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.out;
-import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.outE;
-import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.repeat;
-import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.union;
+import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.*;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 
@@ -61,6 +55,8 @@ public abstract class UnionTest extends AbstractGremlinProcessTest {
 
     public abstract Traversal<Vertex, Number> get_g_VX1_2X_localXunionXoutE_count__inE_count__outE_weight_sumXX(final Object v1Id, final Object v2Id);
 
+    public abstract Traversal<Vertex, Number> get_g_VX1_2X_localXunionXcountXX(final Object v1Id, final Object v2Id);
+
     @Test
     @LoadGraphWith(MODERN)
     public void g_V_unionXout__inX_name() {
@@ -144,6 +140,14 @@ public abstract class UnionTest extends AbstractGremlinProcessTest {
 
     @Test
     @LoadGraphWith(MODERN)
+    public void g_VX1_2X_localXunionXcountXX() {
+        final Traversal<Vertex, Number> traversal = get_g_VX1_2X_localXunionXcountXX(convertToVertexId("marko"), convertToVertexId("vadas"));
+        printTraversalForm(traversal);
+        checkResults(Arrays.asList(1L, 1L), traversal);
+    }
+
+    @Test
+    @LoadGraphWith(MODERN)
     public void g_VX1_2X_unionXoutE_count__inE_count__outE_weight_sumX() {
         final Traversal<Vertex, Number> traversal = get_g_VX1_2X_unionXoutE_count__inE_count__outE_weight_sumX(convertToVertexId("marko"), convertToVertexId("vadas"));
         printTraversalForm(traversal);
@@ -192,5 +196,10 @@ public abstract class UnionTest extends AbstractGremlinProcessTest {
         public Traversal<Vertex, Number> get_g_VX1_2X_localXunionXoutE_count__inE_count__outE_weight_sumXX(final Object v1Id, final Object v2Id) {
             return g.V(v1Id, v2Id).local(union(outE().count(), inE().count(), (Traversal) outE().values("weight").sum()));
         }
+
+        @Override
+        public Traversal<Vertex, Number> get_g_VX1_2X_localXunionXcountXX(final Object v1Id, final Object v2Id) {
+            return g.V(v1Id, v2Id).local(union((Traversal) count()));
+        }
     }
 }


[5/9] tinkerpop git commit: Expanded more on Map merging in the collections recipe CTR

Posted by dk...@apache.org.
Expanded more on Map merging in the collections recipe CTR


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

Branch: refs/heads/TINKERPOP-1867
Commit: 7b37a256a1c41fb3978a0fbd5716f64a1dd5bc90
Parents: 4eb80bd
Author: Stephen Mallette <sp...@genoprime.com>
Authored: Wed Jan 17 16:40:09 2018 -0500
Committer: Stephen Mallette <sp...@genoprime.com>
Committed: Wed Jan 17 16:40:09 2018 -0500

----------------------------------------------------------------------
 docs/src/recipes/collections.asciidoc | 47 +++++++++++++++++++++++++++++-
 1 file changed, 46 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/7b37a256/docs/src/recipes/collections.asciidoc
----------------------------------------------------------------------
diff --git a/docs/src/recipes/collections.asciidoc b/docs/src/recipes/collections.asciidoc
index 5db1e6b..61fee99 100644
--- a/docs/src/recipes/collections.asciidoc
+++ b/docs/src/recipes/collections.asciidoc
@@ -282,7 +282,7 @@ g.V().has('name','marko').
     by(select(values).unfold())
 ----
 
-The code above, basically deconstruct then reconstructs the `Map`. The key to the pattern is to first `unfold()` the
+The code above, basically deconstructs then reconstructs the `Map`. The key to the pattern is to first `unfold()` the
 `Map` into its key and value entries. Then for each key and value produce a new `Map` using `group()` where the key
 for that map is the key of the entry (those are obviously unique as you picked them out of the `valueMap()`) and the
 value is simply the `unfold()` of the list of values in each entry. Recall that the `select(values).unfold()` only
@@ -340,4 +340,49 @@ g.V().
         group().
           by(keys).
           by(select(values).unfold()))
+----
+
+As there may be a desire to remove entries from a `Map`, there may also be the need to add keys to a `Map`. The pattern
+here involves the use of a `union()` that returns the `Map` instances which can be flattened to entries and then
+reconstructed as a new `Map` that has been merged together:
+
+[gremlin-groovy,modern]
+----
+g.V().
+  has('name','marko').
+  union(project('degree').         <1>
+          by(bothE().count()),
+        valueMap(true)).
+  unfold().                        <2>
+  group().
+    by(keys).
+    by(select(values).unfold())
+----
+
+<1> The `valueMap(true)` of a `Vertex` can be extended with the "degree" of the `Vertex` by performing a `union()` of
+the two traversals that produce that output (both produce `Map` objects).
+<2> The `unfold()` step is used to decompose the `Map` objects into key/value entries that are then constructed back
+into a single new `Map` given the patterns shown earlier. The `Map` objects of both traversals in the `union()` are
+essentially merged together.
+
+When using this pattern, it is important to recognize that if there are non-unique keys produced by the traversals
+supplied to `union()`, they will overwrite one another given the final `by()` modulator above. If changed to
+`by(select(values).unfold().fold())` they will merge to produce a `List` of values. Of course, that change will bring
+a `List` back for all the values of the new `Map`. With some added logic the `Map` values can be flattened out of
+`List` instances when necessary:
+
+[gremlin-groovy,modern]
+----
+g.V().
+  has('name','marko').
+  union(valueMap(true),
+        project('age').
+          by(constant(100))).
+  unfold().
+  group().
+    by(keys).
+    by(select(values).
+       unfold().
+       fold().
+       choose(count(local).is(eq(1)), unfold()))
 ----
\ No newline at end of file


[3/9] tinkerpop git commit: Merge branch 'TINKERPOP-1860' into tp32

Posted by dk...@apache.org.
Merge branch 'TINKERPOP-1860' into tp32


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

Branch: refs/heads/TINKERPOP-1867
Commit: 586e432bbef36eb1e509e63031caa6f2aa44ef3d
Parents: a94baa0 caede9c
Author: Stephen Mallette <sp...@genoprime.com>
Authored: Tue Jan 16 08:11:28 2018 -0500
Committer: Stephen Mallette <sp...@genoprime.com>
Committed: Tue Jan 16 08:11:28 2018 -0500

----------------------------------------------------------------------
 .../step/map/GroovyValueMapTest.groovy          | 10 +++
 .../src/main/jython/radish/feature_steps.py     |  8 +-
 gremlin-test/features/map/ValueMap.feature      | 32 +++++++
 .../traversal/step/map/ValueMapTest.java        | 95 ++++++++++++++++++++
 4 files changed, 144 insertions(+), 1 deletion(-)
----------------------------------------------------------------------



[2/9] tinkerpop git commit: Removed a hardcoded expectation in test suite around metrics serialization CTR

Posted by dk...@apache.org.
Removed a hardcoded expectation in test suite around metrics serialization CTR


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

Branch: refs/heads/TINKERPOP-1867
Commit: a94baa0e017ff40f45642b1b1286e5e1cfc7c391
Parents: c4b0f9d
Author: Stephen Mallette <sp...@genoprime.com>
Authored: Thu Jan 11 09:57:27 2018 -0500
Committer: Stephen Mallette <sp...@genoprime.com>
Committed: Thu Jan 11 09:57:27 2018 -0500

----------------------------------------------------------------------
 CHANGELOG.asciidoc                                             | 1 +
 .../apache/tinkerpop/gremlin/structure/SerializationTest.java  | 6 +++---
 2 files changed, 4 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/a94baa0e/CHANGELOG.asciidoc
----------------------------------------------------------------------
diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc
index ed32f05..c388425 100644
--- a/CHANGELOG.asciidoc
+++ b/CHANGELOG.asciidoc
@@ -24,6 +24,7 @@ image::https://raw.githubusercontent.com/apache/tinkerpop/master/docs/static/ima
 === TinkerPop 3.2.8 (Release Date: NOT OFFICIALLY RELEASED YET)
 
 * Delayed setting of the request identifier until `RequestMessage` construction by the builder.
+* Removed hardcoded expectation in metrics serialization test suite as different providers may have different outputs.
 
 [[release-3-2-7]]
 === TinkerPop 3.2.7 (Release Date: December 17, 2017)

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/a94baa0e/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/structure/SerializationTest.java
----------------------------------------------------------------------
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/structure/SerializationTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/structure/SerializationTest.java
index 4dacf48..1de30de 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/structure/SerializationTest.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/structure/SerializationTest.java
@@ -213,7 +213,7 @@ public class SerializationTest {
             final GryoWriter gryoWriter = gryoIo.writer().create();
             final GryoReader gryoReader = gryoIo.reader().create();
 
-            final TraversalMetrics before = (TraversalMetrics) g.V().both().profile().next();
+            final TraversalMetrics before = g.V().both().profile().next();
             final ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
             gryoWriter.writeObject(outputStream, before);
 
@@ -355,7 +355,7 @@ public class SerializationTest {
         @LoadGraphWith(LoadGraphWith.GraphData.MODERN)
         public void shouldSerializeTraversalMetrics() throws Exception {
             final ObjectMapper mapper = graph.io(GraphSONIo.build()).mapper().create().createMapper();
-            final TraversalMetrics tm = (TraversalMetrics) g.V().both().profile().next();
+            final TraversalMetrics tm = g.V().both().profile().next();
             final String json = mapper.writeValueAsString(tm);
             final Map<String, Object> m = mapper.readValue(json, mapTypeReference);
 
@@ -363,7 +363,7 @@ public class SerializationTest {
             assertTrue(m.containsKey(GraphSONTokens.METRICS));
 
             final List<Map<String, Object>> metrics = (List<Map<String, Object>>) m.get(GraphSONTokens.METRICS);
-            assertEquals(2, metrics.size());
+            assertEquals(tm.getMetrics().size(), metrics.size());
 
             final Map<String, Object> metrics0 = metrics.get(0);
             assertTrue(metrics0.containsKey(GraphSONTokens.ID));


[7/9] tinkerpop git commit: Improved the method for dealing with the python build problem with radish

Posted by dk...@apache.org.
Improved the method for dealing with the python build problem with radish

The issue is definitely related to the colorful version bump with radish (and PyHamcrest, maybe others??) depend on. Rather than exclude the dependencies and manually import stuff which was messy, David Brown suggested the fix that just involved an environment variable. He is currently looking into opening an issue with colorful for the problem. CTR


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

Branch: refs/heads/TINKERPOP-1867
Commit: 231bbb6596646db3a6238b1014f9d43b25fc7cfd
Parents: b54c974
Author: Stephen Mallette <sp...@genoprime.com>
Authored: Thu Jan 18 14:02:05 2018 -0500
Committer: Stephen Mallette <sp...@genoprime.com>
Committed: Thu Jan 18 14:02:05 2018 -0500

----------------------------------------------------------------------
 gremlin-python/pom.xml | 15 +++------------
 1 file changed, 3 insertions(+), 12 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/231bbb65/gremlin-python/pom.xml
----------------------------------------------------------------------
diff --git a/gremlin-python/pom.xml b/gremlin-python/pom.xml
index ec8a8d3..3bbf82c 100644
--- a/gremlin-python/pom.xml
+++ b/gremlin-python/pom.xml
@@ -315,27 +315,17 @@ limitations under the License.
                                               failonerror="true">
                                             <arg line="--python=python2 env"/>
                                         </exec>
-                                        <!-- temporary manual installation of deps to hardcode colorful version given radish/PyHamcrest troubles -->
                                         <exec dir="${project.build.directory}/python2" executable="env/bin/pip"
                                               failonerror="true">
-                                            <arg line="install wheel aenum pysingleton humanize radish-parse_type docopt 'colorful==0.4.0' 'tag-expressions>=1.0.0'"/>
-                                        </exec>
-                                        <exec dir="${project.build.directory}/python2" executable="env/bin/pip"
-                                              failonerror="true">
-                                            <arg line="install radish-bdd PyHamcrest --no-deps"/>
+                                            <arg line="install wheel radish-bdd PyHamcrest aenum"/>
                                         </exec>
                                         <exec dir="${project.build.directory}/python3" executable="virtualenv"
                                               failonerror="true">
                                             <arg line="--python=python3 env"/>
                                         </exec>
-                                        <!-- temporary manual installation of deps to hardcode colorful version given radish/PyHamcrest troubles -->
-                                        <exec dir="${project.build.directory}/python3" executable="env/bin/pip"
-                                              failonerror="true">
-                                            <arg line="install wheel aenum pysingleton humanize radish-parse_type docopt 'colorful==0.4.0' 'tag-expressions>=1.0.0'"/>
-                                        </exec>
                                         <exec dir="${project.build.directory}/python3" executable="env/bin/pip"
                                               failonerror="true">
-                                            <arg line="install radish-bdd PyHamcrest --no-deps"/>
+                                            <arg line="install wheel radish-bdd PyHamcrest aenum"/>
                                         </exec>
                                         <exec dir="${project.build.directory}/python-packaged" executable="virtualenv"
                                               failonerror="true">
@@ -433,6 +423,7 @@ limitations under the License.
                                         <exec executable="env/bin/radish" dir="${project.build.directory}/python2"
                                               failonerror="true">
                                             <env key="PYTHONPATH" value=""/>
+                                            <env key="PYTHONIOENCODING" value="utf-8:surrogateescape"/>
                                             <arg line="-e -t -b ${project.build.directory}/python2/radish ${project.basedir}/../gremlin-test/features/"/> <!-- -no-line-jump -->
                                         </exec>
                                     </target>


[6/9] tinkerpop git commit: Fixed build problems with python given dep issues with radish

Posted by dk...@apache.org.
Fixed build problems with python given dep issues with radish

Radish uses colorful which just bumped version and ends up breaking something in radish. Manually loaded deps for now until that is resolved in radish. CTR


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

Branch: refs/heads/TINKERPOP-1867
Commit: b54c9740ae1efd08b0a26b780ee109641728b9e8
Parents: 7b37a25
Author: Stephen Mallette <sp...@genoprime.com>
Authored: Thu Jan 18 07:10:04 2018 -0500
Committer: Stephen Mallette <sp...@genoprime.com>
Committed: Thu Jan 18 07:10:04 2018 -0500

----------------------------------------------------------------------
 gremlin-python/pom.xml | 14 ++++++++++++--
 1 file changed, 12 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/b54c9740/gremlin-python/pom.xml
----------------------------------------------------------------------
diff --git a/gremlin-python/pom.xml b/gremlin-python/pom.xml
index c6373bd..ec8a8d3 100644
--- a/gremlin-python/pom.xml
+++ b/gremlin-python/pom.xml
@@ -315,17 +315,27 @@ limitations under the License.
                                               failonerror="true">
                                             <arg line="--python=python2 env"/>
                                         </exec>
+                                        <!-- temporary manual installation of deps to hardcode colorful version given radish/PyHamcrest troubles -->
                                         <exec dir="${project.build.directory}/python2" executable="env/bin/pip"
                                               failonerror="true">
-                                            <arg line="install wheel radish-bdd PyHamcrest aenum"/>
+                                            <arg line="install wheel aenum pysingleton humanize radish-parse_type docopt 'colorful==0.4.0' 'tag-expressions>=1.0.0'"/>
+                                        </exec>
+                                        <exec dir="${project.build.directory}/python2" executable="env/bin/pip"
+                                              failonerror="true">
+                                            <arg line="install radish-bdd PyHamcrest --no-deps"/>
                                         </exec>
                                         <exec dir="${project.build.directory}/python3" executable="virtualenv"
                                               failonerror="true">
                                             <arg line="--python=python3 env"/>
                                         </exec>
+                                        <!-- temporary manual installation of deps to hardcode colorful version given radish/PyHamcrest troubles -->
+                                        <exec dir="${project.build.directory}/python3" executable="env/bin/pip"
+                                              failonerror="true">
+                                            <arg line="install wheel aenum pysingleton humanize radish-parse_type docopt 'colorful==0.4.0' 'tag-expressions>=1.0.0'"/>
+                                        </exec>
                                         <exec dir="${project.build.directory}/python3" executable="env/bin/pip"
                                               failonerror="true">
-                                            <arg line="install wheel radish-bdd PyHamcrest aenum"/>
+                                            <arg line="install radish-bdd PyHamcrest --no-deps"/>
                                         </exec>
                                         <exec dir="${project.build.directory}/python-packaged" executable="virtualenv"
                                               failonerror="true">


[9/9] tinkerpop git commit: Updated CHANGELOG

Posted by dk...@apache.org.
Updated CHANGELOG


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

Branch: refs/heads/TINKERPOP-1867
Commit: dd83c7809253bc6e75affaff140bf363f481c2ed
Parents: fa8dae8
Author: Daniel Kuppitz <da...@hotmail.com>
Authored: Tue Jan 16 14:37:44 2018 -0700
Committer: Daniel Kuppitz <da...@hotmail.com>
Committed: Sat Jan 20 18:09:19 2018 -0700

----------------------------------------------------------------------
 CHANGELOG.asciidoc | 1 +
 1 file changed, 1 insertion(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/dd83c780/CHANGELOG.asciidoc
----------------------------------------------------------------------
diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc
index c388425..42574d3 100644
--- a/CHANGELOG.asciidoc
+++ b/CHANGELOG.asciidoc
@@ -25,6 +25,7 @@ image::https://raw.githubusercontent.com/apache/tinkerpop/master/docs/static/ima
 
 * Delayed setting of the request identifier until `RequestMessage` construction by the builder.
 * Removed hardcoded expectation in metrics serialization test suite as different providers may have different outputs.
+* Fixed a bug in `ComputerAwareStep` that didn't handle `reset()` properly and thus occasionally produced some extra traversers.
 
 [[release-3-2-7]]
 === TinkerPop 3.2.7 (Release Date: December 17, 2017)


[4/9] tinkerpop git commit: Added some more details on collections recipe for List CTR

Posted by dk...@apache.org.
Added some more details on collections recipe for List CTR


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

Branch: refs/heads/TINKERPOP-1867
Commit: 4eb80bd4878d455bff761c091b8fcd8414d59660
Parents: 586e432
Author: Stephen Mallette <sp...@genoprime.com>
Authored: Tue Jan 16 14:31:55 2018 -0500
Committer: Stephen Mallette <sp...@genoprime.com>
Committed: Tue Jan 16 14:31:55 2018 -0500

----------------------------------------------------------------------
 docs/src/recipes/collections.asciidoc | 282 ++++++++++++++++++++++++++++-
 1 file changed, 279 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/4eb80bd4/docs/src/recipes/collections.asciidoc
----------------------------------------------------------------------
diff --git a/docs/src/recipes/collections.asciidoc b/docs/src/recipes/collections.asciidoc
index 446ed46..5db1e6b 100644
--- a/docs/src/recipes/collections.asciidoc
+++ b/docs/src/recipes/collections.asciidoc
@@ -21,9 +21,237 @@ image:gremlin-collections.png[width=400]
 
 Lists and maps form the basis for much of the processing in Gremlin traversals. They are core to how side-effects
 are typically held and how results are generally produced. Being able to pick them apart and reformat them is sometimes
-required.
+required. This need to shape the date within a traversal may arise both at the
+link:http://tinkerpop.apache.org/docs/current/reference/#terminal-steps[terminal step] of the traversal (technically
+just prior to the terminal step) or in the middle of a traversal. Considering the former, a transformation just prior
+to iteration will get the result into the form required by the application which would remove the need for additional
+application level manipulation. Moreover, a transformation at this stage may reduce the size of the payload being
+returned which could be useful in remote applications. Examining the latter, there may be times where a `List` or `Map`
+requires some mid-traversal transformation so as to continue with the general logic of the traversal itself. For
+example, a traversal at some point might produce a `Map` of `List` objects where the lists contain vertices, where each
+`List` might need to be sorted by some criteria and then the top item for each extracted to become the basis for the
+continued traversal. Executing transformations for either of these types of situations can be made possible with the
+patterns described in this section.
 
-One of the most common ways to end up with a `Map` is with `valueMap()`:
+The appearance of a `List` as a traverser in Gremlin usually arises as a result of a `fold()` operation, but may also
+appear by way of some side-effect steps like `store()`:
+
+[gremlin-groovy,modern]
+----
+g.V().fold()
+g.V().store('a').cap('a')
+----
+
+It is worth noting that while a `Path` is not technically a `List` it does present like one and can be manipulated in
+similar fashion to lists:
+
+[gremlin-groovy,modern]
+----
+g.V().out().out().path()
+----
+
+These examples are obviously trivial and there are other ways that a traverser might end up in a `List` form, but, at
+this moment, the point here is to focus less on how to get a `List` and more on how to manipulate one within the
+Gremlin language. The examples going forward will also be similarly contrived insofar as producing a usable `List` to
+manipulate. Bear in mind that it may be quite possible to get the same end results of these examples using more direct
+means than what is demonstrated.
+
+It may seem simple, but the most obvious choice to modifying what is in a list is to simply `unfold()` the `List`:
+
+[gremlin-groovy,modern]
+----
+g.V().fold().unfold().values('name')
+g.V().store('a').cap('a').unfold().values('name')
+----
+
+The above examples show that `unfold()` works quite well when you want don't want to preserve the `List` structure of
+the traverser as it just flattens `List` traversers to the traversal stream. The above examples only have one `List`
+as a result, but consider what happens when there is more than one:
+
+[gremlin-groovy,modern]
+----
+g.V().union(fold(),fold())
+g.V().union(fold(),fold()).unfold().values('name')
+----
+
+The two separate `List` traversers are flattened to a single traversal stream and all the results are mixed together.
+While this approach may be acceptable, there are many cases where it might not be so. To preserve the individual
+structure of the `List` traversers "locally" `unfold()` the lists to transform them:
+
+[gremlin-groovy,modern]
+----
+g.V().
+  union(fold(),fold()).
+  local(unfold().values('name').fold())
+----
+
+The call to `local()` executes its anonymous sub-traversal over each individual `List` iterator and as the
+sub-traversal ends with a `fold()` step, the results are reduced back into a `List` to preserve the original structure,
+thus maintaining two traverser results.
+
+This pattern for unfolding and folding `List` traversers ends up having other applications:
+
+[gremlin-groovy,modern]
+----
+g.V().union(limit(3).fold(),tail(3).fold())    <1>
+g.V().union(limit(3).fold(),tail(3).fold()).
+  local(unfold().                              <2>
+        order().
+          by(bothE().count(),decr).
+        limit(1).
+        fold())
+g.V().union(limit(3).fold(),tail(3).fold()).   <3>
+  local(unfold().
+        has('age',gte(29)).
+        values('age').
+        mean())
+----
+
+<1> The output consists of two `List` traversers.
+<2> For each `List` of vertices, order them by their number of edges, and choose the first one which will be the one
+with the highest degree (i.e. number of edges). By ending with `fold()` the `List` traverser structure is preserved
+thus returning two `List` objects. Consider this a method for choosing a "max" or a highly ranked vertex. In this case
+the rank was determined by the number of edges, but it could have just as easily been determined by a vertex property,
+edge property, a calculated value, etc. - one simply needs to alter the `by()` step modulator to `order()`.
+<3> For each `List` of vertices, filter that `List` to only include vertices that have an "age" property with a
+value greater than or equal to "29" and then average the results of each list. More generally, consider how this
+approach performs some kind of reducing calculation on each `List` traverser. In this case, an average was calculated,
+but it might also have been a `sum()`, `count()` or similar operation that reduced the list to a single calculated
+value.
+
+So far, this section has focused on what to do with a `List` traverser once there is one present and there have been
+fairly contrived examples for how to produce one in the first place. The use of `fold()` has been used most frequently
+at this point to achieve list creation and that step should be recalled whenever there is a need to reduce some
+traversal stream to an actual `List`. Of course, it may become necessary to more manually construct a `List`,
+especially in cases where the expected output of the traversal is composed of one or more ordered results in the
+form of a `List`. For example, consider the following three traversals:
+
+[gremlin-groovy,modern]
+----
+g.V().has('name','marko').values('age')     <1>
+g.V().has('name','marko').                  <2>
+  repeat(out()).
+    until(has('lang','java')).
+  path().
+    by('name')
+g.V().has('name','marko').                  <3>
+  repeat(outE().inV()).
+    until(has('lang','java')).
+  path().
+  local(unfold().
+        has('weight').
+        values('weight').
+        mean())
+----
+
+<1> Get the age of "marko"
+<2> get the "name" values of the vertices in the collected paths that traverse out from "marko" to any vertex with
+the "lang" of "java".
+<3> Get the average of the "weight" values of edges in the collected paths that traverse out from "marko" to any vertex
+with the "lang" of "java". Note the use of the earlier defined pattern that used `local()` in conjunction with
+`unfold()`. In this case it filters out vertices from the `Path` as they are not relevant as the concern is only with
+the "weight" property on the edges.
+
+For purposes of this example, the three traversals above happen to represent three pieces of data that are required by
+an application. It is plain to note that all of the above traversals hold a similar pattern that starts with
+"getting 'marko'" and, in the case of the latter two, traversing on outgoing edges away from him and collecting data
+from that path. Ideally, all three of these traversals should execute as one to prevent having to submit three separate
+traversals, thus incurring additional query execution costs for what amounts to be largely the same underlying data but
+with different transformations applied. The goal here would be to return the results of this data as a `List` with
+three results (i.e. triple) that could then be submitted once by the application. The following example demonstrates
+the use of `store()` to aid in construction of this `List`:
+
+[gremlin-groovy,modern]
+----
+g.V().has('name','marko').as('v').                             <1>
+  store('a').                                                  <2>
+    by('age').
+  repeat(outE().as('e').inV().as('v')).                        <3>
+    until(has('lang','java')).
+  aggregate('b').                                              <4>
+    by(select(all,'v').unfold().values('name').fold()).
+  aggregate('c').                                              <5>
+    by(select(all,'e').unfold().values('weight').mean()).
+  fold().                                                      <6>
+  store('a').                                                  <7>
+    by(cap('b')).
+  store('a').                                                  <8>
+    by(cap('c')).
+  cap('a')
+----
+
+<1> Get the "marko" vertex and label that step as "v".
+<2> Store the first "age" of "marko" as the first item in the `List` called "a", which will ultimately be the result.
+<3> Execute the traversal away from "marko" and continue to traverse on outgoing edges until the vertex has the value
+of "java" for the "lang" property. Note the labels of "e" and "v". Note that "e" will contain a `List` of all of the
+edges that have been traversed and "v" will contain a `List` of all the vertices that have been traversed.
+<4> The incoming traverser to `aggregate('b')` are vertices that terminate the `repeat()` (i.e. those with the "lang"
+of "java"). Note however that the `by()` modulator overrides that traverser completely by starting a fresh stream of
+the list of vertices in "v". Those vertices are unfolded to retrieve the name property from each and then are reduced
+with `fold()` back into a list to be stored in the side-effected named "b".
+<5> A similar use of `aggregate()` as the previous step, though this one turns "e" into a stream of edges to calculate
+the `mean()` to store in a `List` called "c". Note that `aggregate()` was used here instead of `store()`, as
+the former is an eager collection of the elements in the stream (`store()` is lazy) and will force the traversal to be
+iterated up to that point before moving forward. Without that eager collection, "v" and "e" would not contain the
+complete information required for the production of "b" and "c".
+<6> Adding `fold()` step here is a bit of a trick. To see the trick, copy and paste all lines of Gremlin up to but
+not including this `fold()` step and run them against the "modern" graph. The output is three vertices and if the
+`profile()` step was added one would also see that the traversal contained three traversers. These three traversers
+with a vertex in each one were produced from the `repeat()` step (i.e. those vertices that had the "lang" of "java"
+when traversing away from "marko"). The `aggregate()` steps are side-effects and just allow the traversers to pass
+through them unchanged. The `fold()` obviously converts those three traversers to a single `List` to make one
+traverser with a `List` inside. That means that the remaining steps following the `fold()` will only be executed one
+time each instead of three, which, as will be shown, is critical to the proper result.
+<7> The single traverser with the `List` of three vertices in it passes to `store()`. The `by()` modulator presents an
+override telling Gremlin to ignore the `List` of three vertices and simply grab the "b" side effect created earlier and
+stick that into "a" as part of the result. The `List` with three vertices passes out unchanged as `store()` is a
+side-effect step.
+<8> Again, the single traverser with the `List` of three vertices passes to `store()` and again, the `by()` modulator
+presents an override to include "c" into the result.
+
+All of the above code and explanation show that `store()` can be used to construct `List` objects as side-effects
+which can then be used as a result. Note that `aggregate()` can be used to similar effect, should it make sense that
+lazy `List` creation is not acceptable with respect to the nature of the traversal. An interesting sub-pattern that
+emerges here is that the `by()` step can modulate its step to completely override the current traverser and ignore its
+contents for purpose of that step. This ability to override a traverser acts as a powerful and flexible tool as it
+means that each traverser can effectively become a completely different object as determined by a sub-traversal.
+
+Another interesting method for `List` creation was demonstrated a bit earlier but not examined in detail - the use of
+`union()`. It was shown earlier in the following context where it helped create a `List` of two lists of three
+vertices each:
+
+[gremlin-groovy,modern]
+----
+g.V().union(limit(3).fold(),tail(3).fold())
+----
+
+By folding the results of `union()`, it becomes possible to essentially construct lists with arbitrary traversal
+results.
+
+[gremlin-groovy,modern]
+----
+g.V().
+  local(union(identity(),                   <1>
+              bothE().count()).
+        fold())
+g.V().
+  store('x').
+    by(union(select('x').count(local),      <2>
+             identity(),
+             bothE().count()).
+             fold()).
+  cap('x')
+----
+
+<1> For each vertex, create a "pair" (i.e. a `List` of two objects) of the vertex itself and its edge count.
+<2> For each vertex, create a "triple" (i.e. a `List`of three objects) of the index of the vertex (starting at zero),
+the vertex itself and its edge count.
+
+The pattern here is to use `union()` in conjunction with `fold()`. As explained earlier, the `fold()` operation reduces
+the stream from `union()` to a single `List` that is then fed forward to the next step in the traversal.
+
+Now that `List` patterns have been explained, there can now be some attention on `Map`. One of the most common ways
+to end up with a `Map` is with `valueMap()`:
 
 [gremlin-groovy,modern]
 ----
@@ -64,4 +292,52 @@ on that sub-traversal (it does not iterate the entire thing).
 Generally speaking, a `Map` constructed as part of `group()` or `project()` will already be in the form required as
 the `by()` modulators would be written in such a fashion as to produce that final output. It would be unnecessary to
 deconstruct/reconstruct it. Be certain that there isn't a way to re-write the `group()` or `project()` to get the
-desired output before taking this approach.
\ No newline at end of file
+desired output before taking this approach.
+
+In the following case, `project()` is used to create a `Map` that does not meet this requirement as it contains some
+unavoidable extraneous keys in the output `Map`:
+
+[gremlin-groovy,modern]
+----
+g.V().
+  project('name','age','lang').
+    by('name').
+    by(coalesce(values('age'),constant('n/a'))).
+    by(coalesce(values('lang'),constant('n/a')))
+----
+
+The use of `coalesce()` works around the problem where "age" and "lang" are not necessarily property keys present on
+every single vertex in the traversal stream. When the "age" or "lang" are not present, the constant of "n/a" is
+supplied. While this may be an acceptable output, it is possible to shape the `Map` to be "nicer":
+
+[gremlin-groovy,modern]
+----
+g.V().
+  project('name','age','lang').
+    by('name').
+    by(coalesce(values('age'),constant('n/a'))).
+    by(coalesce(values('lang'),constant('n/a'))).
+  local(unfold().
+        filter(select(values).is(P.neq('n/a'))).
+        group().
+          by(keys).
+          by(values))
+----
+
+The addition steps above `unfold()` the `Map` to key-value entries and filter the values for "n/a" and remove them
+prior to reconstructing the `Map` with the method shown earlier. To go a step further, apply the pattern presented
+earlier to flatten `List` values within a `Map`:
+
+[gremlin-groovy,modern]
+----
+g.V().
+  project('name','age','lang').
+    by('name').
+    by(coalesce(values('age'),constant('n/a'))).
+    by(coalesce(values('lang'),constant('n/a'))).
+  local(unfold().
+        filter(select(values).is(P.neq('n/a'))).
+        group().
+          by(keys).
+          by(select(values).unfold()))
+----
\ No newline at end of file