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/11/05 16:01:04 UTC

[tinkerpop] branch TINKERPOP-2059 updated (f068f03 -> 8ec155d)

This is an automated email from the ASF dual-hosted git repository.

dkuppitz pushed a change to branch TINKERPOP-2059
in repository https://gitbox.apache.org/repos/asf/tinkerpop.git.


 discard f068f03  omg, I did it
 discard 4e2edb6  final
 discard a034241  TINKERPOP-2059 Fix text case in C#
 discard 1f40a6f  wip
 discard e62f9d3  gremlin-javascript: Expose withOptions as an object instance
 discard 46a889d  wip
 discard 2b0dcb0  wip
 discard d5dd5c9  wip
 discard d5a0735  TINKERPOP-2059 wip
     new 8ec155d  TINKERPOP-2059 Implemented `by()` and `with()` modulators for `valueMap()` step.

This update added new revisions after undoing existing revisions.
That is to say, some revisions that were in the old version of the
branch are not in the new version.  This situation occurs
when a user --force pushes a change and generates a repository
containing something like this:

 * -- * -- B -- O -- O -- O   (f068f03)
            \
             N -- N -- N   refs/heads/TINKERPOP-2059 (8ec155d)

You should already have received notification emails for all of the O
revisions, and so the following emails describe only the N revisions
from the common base, B.

Any revisions marked "omit" are not gone; other references still
refer to them.  Any revisions marked "discard" are gone forever.

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:


[tinkerpop] 01/01: TINKERPOP-2059 Implemented `by()` and `with()` modulators for `valueMap()` step.

Posted by dk...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

dkuppitz pushed a commit to branch TINKERPOP-2059
in repository https://gitbox.apache.org/repos/asf/tinkerpop.git

commit 8ec155da10f6b8e7eb384a8dcce0b66928bde904
Author: Daniel Kuppitz <da...@hotmail.com>
AuthorDate: Tue Oct 23 13:04:20 2018 -0700

    TINKERPOP-2059 Implemented `by()` and `with()` modulators for `valueMap()` step.
---
 CHANGELOG.asciidoc                                 |   1 +
 docs/src/recipes/collections.asciidoc              |   6 +-
 docs/src/recipes/duplicate-edge.asciidoc           |   4 +-
 docs/src/recipes/edge-move.asciidoc                |   4 +-
 docs/src/reference/gremlin-applications.asciidoc   |  10 +-
 docs/src/reference/gremlin-variants.asciidoc       |  10 +-
 docs/src/reference/the-traversal.asciidoc          |  29 ++-
 docs/src/upgrade/release-3.4.x.asciidoc            |  49 +++++
 .../tinkerpop/gremlin/jsr223/CoreImports.java      |   2 +
 .../traversal/dsl/graph/GraphTraversal.java        |   3 +-
 .../gremlin/process/traversal/dsl/graph/__.java    |   3 +-
 .../traversal/step/map/PropertyMapStep.java        | 135 +++++++++----
 .../process/traversal/step/util/WithOptions.java   |  70 +++++++
 .../strategy/decoration/PartitionStrategy.java     |   4 +-
 .../traversal/step/map/PropertyMapStepTest.java    |  11 +-
 gremlin-dotnet/glv/WithOptions.template            |  47 +++++
 gremlin-dotnet/glv/generate.groovy                 |  21 +-
 .../Gremlin.Net/Process/Traversal/WithOptions.cs   |  65 ++++++
 .../TraversalEvaluationTests.cs                    |   4 +-
 .../Gherkin/TraversalEvaluation/TraversalParser.cs |   9 +-
 .../TraversalEvaluation/WithOptionsParameter.cs    |  83 ++++++++
 gremlin-javascript/glv/TraversalSource.template    |   5 +
 gremlin-javascript/glv/generate.groovy             |  11 +-
 .../main/javascript/gremlin-javascript/index.js    |   3 +-
 .../gremlin-javascript/lib/process/traversal.js    |  11 +
 .../test/cucumber/feature-steps.js                 |   3 +-
 gremlin-python/glv/TraversalSource.template        |   8 +
 gremlin-python/glv/generate.groovy                 |   9 +-
 .../gremlin/python/jsr223/SymbolHelper.java        |   1 +
 .../jython/gremlin_python/process/traversal.py     |  20 ++
 .../gremlin_python/structure/io/graphsonV2d0.py    |   2 +-
 .../gremlin_python/structure/io/graphsonV3d0.py    |   2 +-
 .../src/main/jython/radish/feature_steps.py        |   5 +-
 gremlin-test/features/map/AddVertex.feature        |   4 +-
 gremlin-test/features/map/ValueMap.feature         |  43 +++-
 .../process/computer/GraphComputerTest.java        |   2 +-
 .../process/traversal/step/map/AddVertexTest.java  |  19 +-
 .../process/traversal/step/map/PageRankTest.java   |  16 +-
 .../traversal/step/map/PeerPressureTest.java       |  16 +-
 .../process/traversal/step/map/ProgramTest.java    |   8 +-
 .../process/traversal/step/map/ValueMapTest.java   | 221 +++++++++++++++------
 .../tinkergraph/structure/TinkerGraphPlayTest.java | 120 +++--------
 42 files changed, 817 insertions(+), 282 deletions(-)

diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc
index 402ed7c..aed87ed 100644
--- a/CHANGELOG.asciidoc
+++ b/CHANGELOG.asciidoc
@@ -25,6 +25,7 @@ image::https://raw.githubusercontent.com/apache/tinkerpop/master/docs/static/ima
 
 This release also includes changes from <<release-3-3-3, 3.3.3>>.
 
+* Made `valueMap()` aware of `by` and `with` modulators and deprecated `valueMap(boolean)` overloads.
 * Use `Compare.eq` in `Contains` predicates to ensure the same filter behavior for numeric values.
 * Added `OptionsStrategy` to allow traversals to take arbitrary traversal-wide configurations.
 * Added text predicates.
diff --git a/docs/src/recipes/collections.asciidoc b/docs/src/recipes/collections.asciidoc
index ce237ec..ff76925 100644
--- a/docs/src/recipes/collections.asciidoc
+++ b/docs/src/recipes/collections.asciidoc
@@ -352,14 +352,14 @@ g.V().
   has('name','marko').
   union(project('degree').         <1>
           by(bothE().count()),
-        valueMap(true)).
+        valueMap().with(WithOptions.tokens)).
   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
+<1> The `valueMap().with(WithOptions.tokens)` 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
@@ -375,7 +375,7 @@ a `List` back for all the values of the new `Map`. With some added logic the `Ma
 ----
 g.V().
   has('name','marko').
-  union(valueMap(true),
+  union(valueMap().with(WithOptions.tokens),
         project('age').
           by(constant(100))).
   unfold().
diff --git a/docs/src/recipes/duplicate-edge.asciidoc b/docs/src/recipes/duplicate-edge.asciidoc
index 27eae2b..710c6b5 100644
--- a/docs/src/recipes/duplicate-edge.asciidoc
+++ b/docs/src/recipes/duplicate-edge.asciidoc
@@ -133,7 +133,7 @@ demonstration, an additional edge is added to the "modern" graph:
 ----
 g.V(1).as("a").V(3).addE("created").property("weight",0.4d).from("a").iterate()
 g.V(1).as("a").V(3).addE("created").property("weight",0.5d).from("a").iterate()
-g.V(1).outE("created").valueMap(true)
+g.V(1).outE("created").valueMap().with(WithOptions.tokens)
 ----
 
 To identify the duplicate with this revised definition, the previous traversal can be modified to:
@@ -147,5 +147,5 @@ g.withoutStrategies(LazyBarrierStrategy, PathRetractionStrategy).V().as("ov").
   where(neq("e1")).
   where(outV().as("ov")).as("e2").
   where("e1", eq("e2")).by(label).
-  where("e1", eq("e2")).by("weight").valueMap(true)
+  where("e1", eq("e2")).by("weight").valueMap().with(WithOptions.tokens)
 ----
diff --git a/docs/src/recipes/edge-move.asciidoc b/docs/src/recipes/edge-move.asciidoc
index f31b060..02b6911 100644
--- a/docs/src/recipes/edge-move.asciidoc
+++ b/docs/src/recipes/edge-move.asciidoc
@@ -28,7 +28,7 @@ follows:
 ----
 g.V().has('name','marko').
   outE().inV().
-  path().by('name').by(valueMap(true))
+  path().by('name').by(valueMap().with(WithOptions.tokens))
 ----
 
 The "marko" vertex contains a "knows" edge to the "vadas" vertex. The following code shows how to "move" that edge to
@@ -47,7 +47,7 @@ g.V().has('name','marko').as('a').
   select('e1').drop()                                             <4>
 g.V().has('name','marko').
   outE().inV().
-  path().by('name').by(valueMap(true))
+  path().by('name').by(valueMap().with(WithOptions.tokens))
 ----
 
 <1> Find the edge to "move" and label that as "e1". It will be necessary to reference this later to get the edge
diff --git a/docs/src/reference/gremlin-applications.asciidoc b/docs/src/reference/gremlin-applications.asciidoc
index e82fccf..5e93b81 100644
--- a/docs/src/reference/gremlin-applications.asciidoc
+++ b/docs/src/reference/gremlin-applications.asciidoc
@@ -1063,7 +1063,7 @@ the `TraversalSource` be generated with `EmptyGraph` as follows:
 ----
 graph = EmptyGraph.instance()
 g = graph.traversal().withRemote('conf/remote-graph.properties')
-g.V().valueMap(true)
+g.V().valueMap().with(WithOptions.tokens)
 g.close()
 ----
 
@@ -1079,7 +1079,7 @@ then re-use it.
 cluster = Cluster.open('conf/remote-objects.yaml')
 graph = EmptyGraph.instance()
 g = graph.traversal().withRemote(DriverRemoteConnection.using(cluster, "g"))
-g.V().valueMap(true)
+g.V().valueMap().with(WithOptions.tokens)
 g.close()
 cluster.close()
 ----
@@ -1894,7 +1894,7 @@ may still be consumed after the timeout if interruption does not succeed on the
 possible existence of multi-properties and meta-properties. When returning data from Gremlin Server only return the
 data that is required. For example, if only two properties of a `Vertex` are needed then simply return the two rather
 than returning the entire `Vertex` object itself. Even with an entire `Vertex`, it is typically much faster to issue
-the query as `g.V(1).valueMap(true)` than `g.V(1)`, as the former returns a `Map` of the same data as a `Vertex`, but
+the query as `g.V(1).valueMap().with(WithOptions.tokens)` than `g.V(1)`, as the former returns a `Map` of the same data as a `Vertex`, but
 without all the associated structure which can slow the response.
 
 [[parameterized-scripts]]
@@ -1982,12 +1982,12 @@ There is no difference if re-written using the best practice of requesting only
 ----
 Cluster cluster = Cluster.open();
 Client client = cluster.connect();
-ResultSet results = client.submit("g.V().hasLabel('person').valueMap(true,'name')");
+ResultSet results = client.submit("g.V().hasLabel('person').valueMap('name').with(WithOptions.tokens)");
 
 Graph graph = EmptyGraph.instance();
 GraphTraversalSource g = graph.traversal().
                                withRemote('conf/remote-graph.properties');
-List<Vertex> results = g.V().hasLabel("person").valueMap(true,'name').toList();
+List<Vertex> results = g.V().hasLabel("person").valueMap('name').with(WithOptions.tokens).toList();
 ----
 
 Both of the above requests return a list of `Map` instances that contain the `id`, `label` and the "name" property.
diff --git a/docs/src/reference/gremlin-variants.asciidoc b/docs/src/reference/gremlin-variants.asciidoc
index 8c5f8f2..1d85426 100644
--- a/docs/src/reference/gremlin-variants.asciidoc
+++ b/docs/src/reference/gremlin-variants.asciidoc
@@ -261,13 +261,13 @@ In order to add and remove <<traversalstrategy,traversal strategies>> from a tra
 ----
 g = g.withStrategies(SubgraphStrategy(vertices=hasLabel('person'),edges=has('weight',gt(0.5))))
 g.V().name.toList()
-g.V().outE().valueMap(True).toList()
+g.V().outE().valueMap().with_(WithOptions.tokens).toList()
 g = g.withoutStrategies(SubgraphStrategy)
 g.V().name.toList()
-g.V().outE().valueMap(True).toList()
+g.V().outE().valueMap().with_(WithOptions.tokens).toList()
 g = g.withComputer(workers=2,vertices=has('name','marko'))
 g.V().name.toList()
-g.V().outE().valueMap(True).toList()
+g.V().outE().valueMap().with_(WithOptions.tokens).toList()
 ----
 
 NOTE: Many of the `TraversalStrategy` classes in Gremlin-Python are proxies to the respective strategy on
@@ -425,14 +425,14 @@ var names = g.V().Values("name").ToList();  // names: [marko, vadas, josh, peter
 g = g.WithoutStrategies(typeof(SubgraphStrategy));
 names = g.V().Values("name").ToList(); // names: [marko, vadas, lop, josh, ripple, peter]
 
-var edgeValueMaps = g.V().OutE().ValueMap(true).ToList();
+var edgeValueMaps = g.V().OutE().ValueMap().With(WithOptions.Tokens).ToList();
 // edgeValueMaps: [[label:created, id:9, weight:0.4], [label:knows, id:7, weight:0.5], [label:knows, id:8, weight:1.0],
 //     [label:created, id:10, weight:1.0], [label:created, id:11, weight:0.4], [label:created, id:12, weight:0.2]]
 
 g = g.WithComputer(workers: 2, vertices: Has("name", "marko"));
 names = g.V().Values("name").ToList();  // names: [marko]
 
-edgeValueMaps = g.V().OutE().ValueMap(true).ToList();
+edgeValueMaps = g.V().OutE().ValueMap().With(WithOptions.Tokens).ToList();
 // edgeValueMaps: [[label:created, id:9, weight:0.4], [label:knows, id:7, weight:0.5], [label:knows, id:8, weight:1.0]]
 ----
 
diff --git a/docs/src/reference/the-traversal.asciidoc b/docs/src/reference/the-traversal.asciidoc
index 0fb7006..98f8d13 100644
--- a/docs/src/reference/the-traversal.asciidoc
+++ b/docs/src/reference/the-traversal.asciidoc
@@ -758,7 +758,7 @@ has been seen or not.
 
 [gremlin-groovy,modern]
 ----
-g.V().valueMap(true, 'name')
+g.V().valueMap('name').with(WithOptions.tokens)
 g.V().dedup().by(label).values('name')
 ----
 
@@ -1792,7 +1792,7 @@ The term `not` is a reserved word in Python, and therefore must be referred to i
 
 [gremlin-groovy,modern]
 ----
-g.V().not(hasLabel('person')).valueMap(true)
+g.V().not(hasLabel('person')).valueMap().with(WithOptions.tokens)
 g.V().hasLabel('person').
   not(out('created').count().is(gt(1))).values('name')   <1>
 ----
@@ -3170,7 +3170,7 @@ g.E().valueMap()
 
 It is important to note that the map of a vertex maintains a list of values for each key. The map of an edge or
 vertex-property represents a single property (not a list). The reason is that vertices in TinkerPop leverage
-<<vertex-properties,vertex properties>> which are support multiple values per key. Using the <<the-crew-toy-graph,
+<<vertex-properties,vertex properties>> which support multiple values per key. Using the <<the-crew-toy-graph,
 "The Crew">> toy graph, the point is made explicit.
 
 [gremlin-groovy,theCrew]
@@ -3180,19 +3180,26 @@ g.V().has('name','marko').properties('location')
 g.V().has('name','marko').properties('location').valueMap()
 ----
 
-If the `id`, `label`, `key`, and `value` of the `Element` is desired, then a boolean triggers its insertion into the
-returned map.
+To turn list of values into single items, the `by()` modulator can be used as shown below.
 
 [gremlin-groovy,theCrew]
 ----
-g.V().hasLabel('person').valueMap(true)
-g.V().hasLabel('person').valueMap(true,'name')
-g.V().hasLabel('person').properties('location').valueMap(true)
+g.V().valueMap().by(unfold())
+g.V().valueMap('name','location').by().by(unfold())
+----
+
+If the `id`, `label`, `key`, and `value` of the `Element` is desired, then the `with()` modulator can be used to
+trigger its insertion into the returned map.
+
+[gremlin-groovy,theCrew]
+----
+g.V().hasLabel('person').valueMap().with(WithOptions.tokens)
+g.V().hasLabel('person').valueMap('name').with(WithOptions.tokens, WithOptions.labels)
+g.V().hasLabel('person').properties('location').valueMap().with(WithOptions.tokens, WithOptions.values)
 ----
 
 *Additional References*
 
-link:++http://tinkerpop.apache.org/javadocs/x.y.z/core/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.html#valueMap-boolean-java.lang.String...-++[`valueMap(boolean,String...)`],
 link:++http://tinkerpop.apache.org/javadocs/x.y.z/core/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.html#valueMap-java.lang.String...-++[`valueMap(String...)`]
 
 [values-step]]
@@ -3860,8 +3867,8 @@ g = graph.traversal().withStrategies(SubgraphStrategy.build().
   vertices(or(hasNot('location'),properties('location').count().is(gt(3)))).
   edges(hasLabel('develops')).
   vertexProperties(or(hasLabel(neq('location')),hasNot('endTime'))).create())
-g.V().valueMap(true)
-g.E().valueMap(true)
+g.V().valueMap().with(WithOptions.tokens)
+g.E().valueMap().with(WithOptions.tokens)
 g.V().outE().inV().
   path().
     by('name').
diff --git a/docs/src/upgrade/release-3.4.x.asciidoc b/docs/src/upgrade/release-3.4.x.asciidoc
index d412fda..83bb9e6 100644
--- a/docs/src/upgrade/release-3.4.x.asciidoc
+++ b/docs/src/upgrade/release-3.4.x.asciidoc
@@ -29,6 +29,55 @@ Please see the link:https://github.com/apache/tinkerpop/blob/3.4.0/CHANGELOG.asc
 
 === Upgrading for Users
 
+==== Modulation of valueMap()
+
+The `valueMap()` step now supports `by` and `with` modulation, which also led to the deprecation of `valueMap(true)` overloads.
+
+===== by() modulation
+
+===== with() modulation
+
+Thw `with()` modulator can be used to include certain tokens (`id`, `label`, `key` and/or `value`).
+
+The old way (still valid, but deprecated):
+
+```
+gremlin> g.V().hasLabel("software").valueMap(true)
+==>[id:10,label:software,name:[gremlin]]
+==>[id:11,label:software,name:[tinkergraph]]
+gremlin> g.V().has("person","name","marko").properties("location").valueMap(true)
+==>[id:6,key:location,value:san diego,startTime:1997,endTime:2001]
+==>[id:7,key:location,value:santa cruz,startTime:2001,endTime:2004]
+==>[id:8,key:location,value:brussels,startTime:2004,endTime:2005]
+==>[id:9,key:location,value:santa fe,startTime:2005]
+```
+
+The new way:
+
+```
+gremlin> g.V().hasLabel("software").valueMap().with(WithOptions.tokens)
+==>[id:10,label:software,name:[gremlin]]
+==>[id:11,label:software,name:[tinkergraph]]
+gremlin> g.V().has("person","name","marko").properties("location").valueMap().with(WithOptions.tokens)
+==>[id:6,key:location,value:san diego,startTime:1997,endTime:2001]
+==>[id:7,key:location,value:santa cruz,startTime:2001,endTime:2004]
+==>[id:8,key:location,value:brussels,startTime:2004,endTime:2005]
+==>[id:9,key:location,value:santa fe,startTime:2005]
+```
+
+Furthermore there now a finer control over which of the tokens should be included:
+
+```
+gremlin> g.V().hasLabel("software").valueMap().with(WithOptions.tokens, WithOptions.labels)
+==>[label:software,name:[gremlin]]
+==>[label:software,name:[tinkergraph]]
+gremlin> g.V().has("person","name","marko").properties("location").valueMap().with(WithOptions.tokens, WithOptions.values)
+==>[value:san diego,startTime:1997,endTime:2001]
+==>[value:santa cruz,startTime:2001,endTime:2004]
+==>[value:brussels,startTime:2004,endTime:2005]
+==>[value:santa fe,startTime:2005]
+```
+
 ==== Changed number comparison behavior of within()/without() predicates
 
 In previous versions `within()` and `without()` performed strict number comparisons; that means these predicates did not only compare number values, but also the time. This was inconsistent with
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/CoreImports.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/CoreImports.java
index 6ccf2e8..59f8a22 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/CoreImports.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/CoreImports.java
@@ -74,6 +74,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal;
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
 import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalOptionParent;
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.WithOptions;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.ConnectiveStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.ElementIdStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.EventStrategy;
@@ -184,6 +185,7 @@ public final class CoreImports {
         CLASS_IMPORTS.add(TraversalOptionParent.Pick.class);
         CLASS_IMPORTS.add(P.class);
         CLASS_IMPORTS.add(TextP.class);
+        CLASS_IMPORTS.add(WithOptions.class);
         // remote
         CLASS_IMPORTS.add(RemoteConnection.class);
         CLASS_IMPORTS.add(RemoteGraph.class);
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.java
index e984312..fc24459 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.java
@@ -560,7 +560,7 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
      * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#valuemap-step" target="_blank">Reference Documentation - ValueMap Step</a>
      * @since 3.0.0-incubating
      */
-    public default <E2> GraphTraversal<S, Map<String, E2>> valueMap(final String... propertyKeys) {
+    public default <E2> GraphTraversal<S, Map<Object, E2>> valueMap(final String... propertyKeys) {
         this.asAdmin().getBytecode().addStep(Symbols.valueMap, propertyKeys);
         return this.asAdmin().addStep(new PropertyMapStep<>(this.asAdmin(), false, PropertyType.VALUE, propertyKeys));
     }
@@ -576,6 +576,7 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
      * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#valuemap-step" target="_blank">Reference Documentation - ValueMap Step</a>
      * @since 3.0.0-incubating
      */
+    @Deprecated
     public default <E2> GraphTraversal<S, Map<Object, E2>> valueMap(final boolean includeTokens, final String... propertyKeys) {
         this.asAdmin().getBytecode().addStep(Symbols.valueMap, includeTokens, propertyKeys);
         return this.asAdmin().addStep(new PropertyMapStep<>(this.asAdmin(), includeTokens, PropertyType.VALUE, propertyKeys));
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/__.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/__.java
index 02eee79..4361f29 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/__.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/__.java
@@ -256,13 +256,14 @@ public class __ {
     /**
      * @see GraphTraversal#valueMap(String...)
      */
-    public static <A extends Element, B> GraphTraversal<A, Map<String, B>> valueMap(final String... propertyKeys) {
+    public static <A extends Element, B> GraphTraversal<A, Map<Object, B>> valueMap(final String... propertyKeys) {
         return __.<A>start().valueMap(propertyKeys);
     }
 
     /**
      * @see GraphTraversal#valueMap(boolean, String...)
      */
+    @Deprecated
     public static <A extends Element, B> GraphTraversal<A, Map<Object, B>> valueMap(final boolean includeTokens, final String... propertyKeys) {
         return __.<A>start().valueMap(includeTokens, propertyKeys);
     }
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/PropertyMapStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/PropertyMapStep.java
index 9ac7d3d..0357e87 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/PropertyMapStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/PropertyMapStep.java
@@ -20,8 +20,13 @@ package org.apache.tinkerpop.gremlin.process.traversal.step.map;
 
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
+import org.apache.tinkerpop.gremlin.process.traversal.step.ByModulating;
+import org.apache.tinkerpop.gremlin.process.traversal.step.Configuring;
 import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent;
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.Parameters;
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.WithOptions;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
+import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalRing;
 import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalUtil;
 import org.apache.tinkerpop.gremlin.structure.Element;
 import org.apache.tinkerpop.gremlin.structure.Property;
@@ -34,67 +39,117 @@ import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
-import java.util.HashMap;
 import java.util.Iterator;
+import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
 /**
  * @author Marko A. Rodriguez (http://markorodriguez.com)
+ * @author Daniel Kuppitz (http://gremlin.guru)
  */
-public class PropertyMapStep<K,E> extends MapStep<Element, Map<K, E>> implements TraversalParent {
+public class PropertyMapStep<K,E> extends MapStep<Element, Map<K, E>>
+        implements TraversalParent, ByModulating, Configuring {
 
     protected final String[] propertyKeys;
     protected final PropertyType returnType;
-    protected final boolean includeTokens;
+
+    protected int tokens;
     protected Traversal.Admin<Element, ? extends Property> propertyTraversal;
 
+    private Parameters parameters = new Parameters();
+    private TraversalRing<K, E> traversalRing;
+
+    @Deprecated
     public PropertyMapStep(final Traversal.Admin traversal, final boolean includeTokens, final PropertyType propertyType, final String... propertyKeys) {
+        this(traversal, propertyType, propertyKeys);
+        this.configure(WithOptions.tokens, includeTokens ? WithOptions.all : WithOptions.none);
+    }
+
+    public PropertyMapStep(final Traversal.Admin traversal, final PropertyType propertyType, final String... propertyKeys) {
         super(traversal);
-        this.includeTokens = includeTokens;
         this.propertyKeys = propertyKeys;
         this.returnType = propertyType;
         this.propertyTraversal = null;
+        this.traversalRing = new TraversalRing<>();
     }
 
     @Override
     protected Map<K, E> map(final Traverser.Admin<Element> traverser) {
-        final Map<Object, Object> map = new HashMap<>();
+        final Map<Object, Object> map = new LinkedHashMap<>();
         final Element element = traverser.get();
-        final boolean isVertex = traverser.get() instanceof Vertex;
+        final boolean isVertex = element instanceof Vertex;
+        if (this.returnType == PropertyType.VALUE) {
+            if (includeToken(WithOptions.ids)) map.put(T.id, element.id());
+            if (element instanceof VertexProperty) {
+                if (includeToken(WithOptions.keys)) map.put(T.key, ((VertexProperty<?>) element).key());
+                if (includeToken(WithOptions.values)) map.put(T.value, ((VertexProperty<?>) element).value());
+            } else {
+                if (includeToken(WithOptions.labels)) map.put(T.label, element.label());
+            }
+        }
         final Iterator<? extends Property> properties = null == this.propertyTraversal ?
                 element.properties(this.propertyKeys) :
                 TraversalUtil.applyAll(traverser, this.propertyTraversal);
+        //final Iterator<? extends Property> properties = element.properties(this.propertyKeys);
         while (properties.hasNext()) {
             final Property<?> property = properties.next();
+            final Object value = this.returnType == PropertyType.VALUE ? property.value() : property;
             if (isVertex) {
-                List<Object> values = (List<Object>) map.get(property.key());
-                if (null == values) {
-                    values = new ArrayList<>();
-                    map.put(property.key(), values);
-                }
-                values.add(this.returnType == PropertyType.VALUE ? property.value() : property);
-            } else
-                map.put(property.key(), this.returnType == PropertyType.VALUE ? property.value() : property);
-        }
-        if (this.returnType == PropertyType.VALUE && this.includeTokens) {
-        	// add tokens, as string keys
-            if (element instanceof VertexProperty) {
-                map.put(T.id, element.id());
-                map.put(T.key, ((VertexProperty<?>) element).key());
-                map.put(T.value, ((VertexProperty<?>) element).value());
+                map.compute(property.key(), (k, v) -> {
+                    final List<Object> values = v != null ? (List<Object>) v : new ArrayList<>();
+                    values.add(value);
+                    return values;
+                });
             } else {
-                map.put(T.id, element.id());
-                map.put(T.label, element.label());
+                map.put(property.key(), value);
             }
         }
+        if (!traversalRing.isEmpty()) {
+            for (final Object key : map.keySet()) {
+                map.compute(key, (k, v) -> TraversalUtil.applyNullable(v, (Traversal.Admin) this.traversalRing.next()));
+            }
+            this.traversalRing.reset();
+        }
         return (Map) map;
     }
 
     @Override
-    public List<Traversal.Admin<Element, ? extends Property>> getLocalChildren() {
-        return null == this.propertyTraversal ? Collections.emptyList() : Collections.singletonList(this.propertyTraversal);
+    public void configure(final Object... keyValues) {
+        if (keyValues[0].equals(WithOptions.tokens)) {
+            if (keyValues.length == 2 && keyValues[1] instanceof Boolean) {
+                this.tokens = ((boolean) keyValues[1]) ? WithOptions.all : WithOptions.none;
+            } else {
+                for (int i = 1; i < keyValues.length; i++) {
+                    if (!(keyValues[i] instanceof Integer))
+                        throw new IllegalArgumentException("WithOptions.tokens requires Integer arguments (possible " + "" +
+                                "values are: WithOptions.[none|ids|labels|keys|values|all])");
+                    this.tokens |= (int) keyValues[i];
+                }
+            }
+        } else {
+            this.parameters.set(this, keyValues);
+        }
+    }
+
+    @Override
+    public Parameters getParameters() {
+        return parameters;
+    }
+
+    @Override
+    public List<Traversal.Admin<K, E>> getLocalChildren() {
+        final List<Traversal.Admin<K, E>> result = new ArrayList<>();
+        if (null != this.propertyTraversal)
+            result.add((Traversal.Admin) propertyTraversal);
+        result.addAll(this.traversalRing.getTraversals());
+        return Collections.unmodifiableList(result);
+    }
+
+    @Override
+    public void modulateBy(final Traversal.Admin<?, ?> selectTraversal) {
+        this.traversalRing.addTraversal(this.integrateChild(selectTraversal));
     }
 
     public void setPropertyTraversal(final Traversal.Admin<Element, ? extends Property> propertyTraversal) {
@@ -109,14 +164,14 @@ public class PropertyMapStep<K,E> extends MapStep<Element, Map<K, E>> implements
         return propertyKeys;
     }
 
+    @Deprecated
     public boolean isIncludeTokens() {
-        return includeTokens;
+        return this.tokens != WithOptions.none;
     }
 
     public String toString() {
-        return null != this.propertyTraversal ?
-                StringFactory.stepString(this, this.propertyTraversal, this.returnType.name().toLowerCase()) :
-                StringFactory.stepString(this, Arrays.asList(this.propertyKeys), this.returnType.name().toLowerCase());
+        return StringFactory.stepString(this, Arrays.asList(this.propertyKeys),
+                this.traversalRing, this.returnType.name().toLowerCase());
     }
 
     @Override
@@ -124,20 +179,19 @@ public class PropertyMapStep<K,E> extends MapStep<Element, Map<K, E>> implements
         final PropertyMapStep<K,E> clone = (PropertyMapStep<K,E>) super.clone();
         if (null != this.propertyTraversal)
             clone.propertyTraversal = this.propertyTraversal.clone();
+        clone.traversalRing = this.traversalRing.clone();
         return clone;
     }
 
     @Override
     public int hashCode() {
-        int result = super.hashCode() ^ this.returnType.hashCode() ^ Boolean.hashCode(this.includeTokens);
-        if (null == this.propertyTraversal) {
-            for (final String propertyKey : this.propertyKeys) {
-                result ^= propertyKey.hashCode();
-            }
-        } else {
+        int result = super.hashCode() ^ this.returnType.hashCode() ^ Integer.hashCode(this.tokens);
+        if (null != this.propertyTraversal)
             result ^= this.propertyTraversal.hashCode();
+        for (final String propertyKey : this.propertyKeys) {
+            result ^= propertyKey.hashCode();
         }
-        return result;
+        return result ^ this.traversalRing.hashCode();
     }
 
     @Override
@@ -145,10 +199,19 @@ public class PropertyMapStep<K,E> extends MapStep<Element, Map<K, E>> implements
         super.setTraversal(parentTraversal);
         if (null != this.propertyTraversal)
             this.integrateChild(this.propertyTraversal);
+        this.traversalRing.getTraversals().forEach(this::integrateChild);
     }
 
     @Override
     public Set<TraverserRequirement> getRequirements() {
         return this.getSelfAndChildRequirements(TraverserRequirement.OBJECT);
     }
+
+    public int getIncludedTokens() {
+        return this.tokens;
+    }
+
+    private boolean includeToken(final int token) {
+        return 0 != (this.tokens & token);
+    }
 }
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/WithOptions.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/WithOptions.java
new file mode 100644
index 0000000..3faa95d
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/WithOptions.java
@@ -0,0 +1,70 @@
+/*
+ * 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.step.util;
+
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal;
+import org.apache.tinkerpop.gremlin.structure.Graph;
+
+/**
+ * Configuration options to be passed to the {@link GraphTraversal#with(String, Object)}.
+ *
+ * @author Daniel Kuppitz (http://gremlin.guru)
+ */
+public class WithOptions {
+
+    //
+    // PropertyMapStep
+    //
+
+    /**
+     * Configures the tokens to be included in value maps.
+     */
+    public static final String tokens = Graph.Hidden.hide("tinkerpop.valueMap.tokens");
+
+    /**
+     * Include no tokens.
+     */
+    public static int none = 0;
+
+    /**
+     * Include ids (affects all {@link org.apache.tinkerpop.gremlin.structure.Element} value maps).
+     */
+    public static int ids = 1;
+
+    /**
+     * Include labels (affects all {@link org.apache.tinkerpop.gremlin.structure.Vertex} and
+     * {@link org.apache.tinkerpop.gremlin.structure.Edge} value maps).
+     */
+    public static int labels = 2;
+
+    /**
+     * Include keys (affects all {@link org.apache.tinkerpop.gremlin.structure.VertexProperty} value maps).
+     */
+    public static int keys = 4;
+
+    /**
+     * Include keys (affects all {@link org.apache.tinkerpop.gremlin.structure.VertexProperty} value maps).
+     */
+    public static int values = 8;
+
+    /**
+     * Include all tokens.
+     */
+    public static int all = ids | labels | keys | values;
+}
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/PartitionStrategy.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/PartitionStrategy.java
index 15079cb..4059191 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/PartitionStrategy.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/PartitionStrategy.java
@@ -43,6 +43,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.step.map.VertexStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.AddPropertyStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.util.HasContainer;
 import org.apache.tinkerpop.gremlin.process.traversal.step.util.Parameters;
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.WithOptions;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.AbstractTraversalStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper;
 import org.apache.tinkerpop.gremlin.structure.Element;
@@ -180,7 +181,8 @@ public final class PartitionStrategy extends AbstractTraversalStrategy<Traversal
                     // as this is a value map, replace that step with propertiesMap() that returns PropertyType.VALUE.
                     // from there, add the filter as shown above and then unwrap the properties as they would have
                     // been done under valueMap()
-                    final PropertyMapStep propertyMapStep = new PropertyMapStep(traversal, step.isIncludeTokens(), PropertyType.PROPERTY, step.getPropertyKeys());
+                    final PropertyMapStep propertyMapStep = new PropertyMapStep(traversal, PropertyType.PROPERTY, step.getPropertyKeys());
+                    propertyMapStep.configure(WithOptions.tokens, step.getIncludedTokens());
                     TraversalHelper.replaceStep(step, propertyMapStep, traversal);
 
                     final LambdaMapStep mapPropertiesFilterStep = new LambdaMapStep<>(traversal, new MapPropertiesFilter());
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/PropertyMapStepTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/PropertyMapStepTest.java
index cc223dc..c46950e 100644
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/PropertyMapStepTest.java
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/PropertyMapStepTest.java
@@ -21,6 +21,7 @@ package org.apache.tinkerpop.gremlin.process.traversal.step.map;
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
 import org.apache.tinkerpop.gremlin.process.traversal.step.StepTest;
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.WithOptions;
 
 import java.util.Arrays;
 import java.util.List;
@@ -37,10 +38,12 @@ public class PropertyMapStepTest extends StepTest {
                 __.valueMap("name"),
                 __.valueMap("age"),
                 __.valueMap("name", "age"),
-                __.valueMap(true),
-                __.valueMap(true, "name"),
-                __.valueMap(true, "age"),
-                __.valueMap(true, "name", "age"),
+                __.valueMap().with(WithOptions.tokens),
+                __.valueMap("name").with(WithOptions.tokens),
+                __.valueMap("age").with(WithOptions.tokens),
+                __.valueMap("name", "age").with(WithOptions.tokens),
+                __.valueMap("name", "age").with(WithOptions.tokens, WithOptions.ids),
+                __.valueMap("name", "age").with(WithOptions.tokens, WithOptions.labels),
                 __.propertyMap(),
                 __.propertyMap("name"),
                 __.propertyMap("age"),
diff --git a/gremlin-dotnet/glv/WithOptions.template b/gremlin-dotnet/glv/WithOptions.template
new file mode 100644
index 0000000..d8dd6bd
--- /dev/null
+++ b/gremlin-dotnet/glv/WithOptions.template
@@ -0,0 +1,47 @@
+#region License
+
+/*
+ * 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.
+ */
+
+#endregion
+
+// THIS IS A GENERATED FILE - DO NOT MODIFY THIS FILE DIRECTLY - see pom.xml
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+
+namespace Gremlin.Net.Process.Traversal.Step.Util
+{
+#pragma warning disable 1591
+
+    /// <summary>
+    ///     Configuration options to be passed to the <c>With()</c> modulator.
+    /// </summary>
+    public class WithOptions
+    {
+<% withOptions.each { field -> %>
+
+        public static readonly <%= field.type %> <%= field.name %> = <%= field.value %>;
+<% } %>
+    }
+
+#pragma warning restore 1591
+}
diff --git a/gremlin-dotnet/glv/generate.groovy b/gremlin-dotnet/glv/generate.groovy
index 7985ca0..26daa58 100644
--- a/gremlin-dotnet/glv/generate.groovy
+++ b/gremlin-dotnet/glv/generate.groovy
@@ -29,6 +29,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.P
 import org.apache.tinkerpop.gremlin.process.traversal.TextP
 import org.apache.tinkerpop.gremlin.process.traversal.IO
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.WithOptions
 import org.apache.tinkerpop.gremlin.structure.Direction
 import java.lang.reflect.Modifier
 import java.lang.reflect.TypeVariable
@@ -114,6 +115,10 @@ def toCSharpType = { name ->
 
 def toCSharpMethodName = { symbol -> (String) Character.toUpperCase(symbol.charAt(0)) + symbol.substring(1) }
 
+def toCSharpValue = { type, value ->
+  type == String.class && value != null ? ('"' + value + '"') : value
+}
+
 def getJavaGenericTypeParameterTypeNames = { method ->
     def typeArguments = method.genericReturnType.actualTypeArguments
     return typeArguments.
@@ -133,7 +138,7 @@ def getJavaParameterTypeNames = { method ->
     return method.parameters.
             collect { param ->
                 param.type.simpleName
-            } 
+            }
 }
 
 def toCSharpParamString = { param, genTypeName ->
@@ -182,7 +187,7 @@ def getCSharpParamString = { method, useGenericParams ->
                     else if (genType instanceof GenericArrayType) {
                         if (((GenericArrayType)genType).getGenericComponentType() instanceof TypeVariable<?>) {
                             genTypeName = ((TypeVariable<?>)((GenericArrayType)genType).getGenericComponentType()).name + "[]"
-                        }                        
+                        }
                     }
                 }
                 toCSharpParamString(param, genTypeName)
@@ -263,8 +268,8 @@ def binding = ["pmethods": P.class.getMethods().
                             return ["methodName": javaMethod.name, "parameters":parameters, "paramNames":paramNames]
                         },
                "sourceSpawnMethods": GraphTraversalSource.getMethods(). // SPAWN STEPS
-                        findAll { GraphTraversal.class.equals(it.returnType) }.          
-                // Select unique combination of C# parameter types and sort by Java parameter type combination                                                                    
+                        findAll { GraphTraversal.class.equals(it.returnType) }.
+                // Select unique combination of C# parameter types and sort by Java parameter type combination
                         sort { a, b -> a.name <=> b.name ?: getJavaParamTypeString(a) <=> getJavaParamTypeString(b) }.
                         unique { a,b -> a.name <=> b.name ?: getCSharpParamTypeString(a) <=> getCSharpParamTypeString(b) }.
                         collect { javaMethod ->
@@ -321,7 +326,9 @@ def binding = ["pmethods": P.class.getMethods().
                             return ["methodName": javaMethod.name, "t2":t2, "tParam":tParam, "parameters":parameters, "paramNames":paramNames, "callGenericTypeArg":callGenericTypeArg, "graphTraversalT2":graphTraversalT2]
                         },
                "tokens": gatherTokensFrom([IO, ConnectedComponent, ShortestPath, PageRank, PeerPressure]),
-               "toCSharpMethodName": toCSharpMethodName]
+               "toCSharpMethodName": toCSharpMethodName,
+               "withOptions": WithOptions.getDeclaredFields().
+                        collect {["type": toCSharpType(it.type.simpleName), "name": toCSharpMethodName(it.name), "value": toCSharpValue(it.type, it.get(null))]}]
 
 def engine = new groovy.text.GStringTemplateEngine()
 def traversalTemplate = engine.createTemplate(new File("${projectBaseDir}/glv/GraphTraversal.template")).make(binding)
@@ -344,6 +351,10 @@ def tpTemplate = engine.createTemplate(new File("${projectBaseDir}/glv/TextP.tem
 def tpFile = new File("${projectBaseDir}/src/Gremlin.Net/Process/Traversal/TextP.cs")
 tpFile.newWriter().withWriter{ it << tpTemplate }
 
+def withOptionsTemplate = engine.createTemplate(new File("${projectBaseDir}/glv/WithOptions.template")).make(binding)
+def withOptionsFile = new File("${projectBaseDir}/src/Gremlin.Net/Process/Traversal/WithOptions.cs")
+withOptionsFile.newWriter().withWriter{ it << withOptionsTemplate }
+
 binding.tokens.each {k,v ->
     def tokenTemplate = engine.createTemplate(new File("${projectBaseDir}/glv/Token.template")).make([tokenFields: v, tokenName: k])
     def tokenFile = new File("${projectBaseDir}/src/Gremlin.Net/Process/Traversal/${k}.cs")
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/WithOptions.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/WithOptions.cs
new file mode 100644
index 0000000..8b79089
--- /dev/null
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/WithOptions.cs
@@ -0,0 +1,65 @@
+#region License
+
+/*
+ * 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.
+ */
+
+#endregion
+
+// THIS IS A GENERATED FILE - DO NOT MODIFY THIS FILE DIRECTLY - see pom.xml
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+
+namespace Gremlin.Net.Process.Traversal.Step.Util
+{
+#pragma warning disable 1591
+
+    /// <summary>
+    ///     Configuration options to be passed to the <c>With()</c> modulator.
+    /// </summary>
+    public class WithOptions
+    {
+
+
+        public static readonly string Tokens = "~tinkerpop.valueMap.tokens";
+
+
+        public static readonly int None = 0;
+
+
+        public static readonly int Ids = 1;
+
+
+        public static readonly int Labels = 2;
+
+
+        public static readonly int Keys = 4;
+
+
+        public static readonly int Values = 8;
+
+
+        public static readonly int All = 15;
+
+    }
+
+#pragma warning restore 1591
+}
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TraversalEvaluationTests.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TraversalEvaluationTests.cs
index 4e2bfff..081b6f6 100644
--- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TraversalEvaluationTests.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TraversalEvaluationTests.cs
@@ -87,7 +87,7 @@ namespace Gremlin.Net.IntegrationTest.Gherkin.TraversalEvaluation
 //                Tuple.Create("g.V().constant(123L)", 2), // Can be parsed using the new type-safe API
                 Tuple.Create("g.V().has(\"no\").count()", 3),
                 Tuple.Create("g.V().values(\"age\")", 2),
-                Tuple.Create("g.V().valueMap(true, \"name\", \"age\")", 2),
+                Tuple.Create("g.V().valueMap(\"name\", \"age\").with(WithOptions.tokens)", 3),
                 Tuple.Create("g.V().where(__.in(\"created\").count().is(1)).values(\"name\")", 3),
                 Tuple.Create("g.V().count(Scope.local)", 2),
                 Tuple.Create("g.V().values(\"age\").is(P.lte(30))", 3),
@@ -111,4 +111,4 @@ namespace Gremlin.Net.IntegrationTest.Gherkin.TraversalEvaluation
             }
         }
     }
-}
\ No newline at end of file
+}
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TraversalParser.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TraversalParser.cs
index 8d44a57..105932f 100644
--- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TraversalParser.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TraversalParser.cs
@@ -46,6 +46,8 @@ namespace Gremlin.Net.IntegrationTest.Gherkin.TraversalEvaluation
 
         private static readonly Regex RegexIO = new Regex(@"IO.\w+", RegexOptions.Compiled);
 
+        private static readonly Regex RegexWithOptions = new Regex(@"WithOptions.\w+", RegexOptions.Compiled);
+
         private static readonly Regex RegexParam = new Regex(@"\w+", RegexOptions.Compiled);
         
         private static readonly HashSet<Type> NumericTypes = new HashSet<Type>
@@ -126,7 +128,6 @@ namespace Gremlin.Net.IntegrationTest.Gherkin.TraversalEvaluation
             var compatibleMethods = new Dictionary<int, MethodInfo>();
             foreach (var method in ordered)
             {
-                lastMethod = method;
                 var methodParameters = method.GetParameters();
                 var requiredParameters = methodParameters.Length;
                 if (requiredParameters > 0 && IsParamsArray(methodParameters.Last()))
@@ -138,6 +139,7 @@ namespace Gremlin.Net.IntegrationTest.Gherkin.TraversalEvaluation
                 {
                     continue;
                 }
+                lastMethod = method;
                 var matched = true;
                 var exactMatches = 0;
                 for (var i = 0; i < tokenParameters.Count; i++)
@@ -452,6 +454,11 @@ namespace Gremlin.Net.IntegrationTest.Gherkin.TraversalEvaluation
                 i += parameterText.Length - 1;
                 return new IOParameter(parameterText);
             }
+            if (RegexWithOptions.IsMatch(parameterText))
+            {
+                i += parameterText.Length - 1;
+                return new WithOptionsParameter(parameterText);
+            }
             if (RegexEnum.IsMatch(parameterText))
             {
                 i += parameterText.Length - 1;
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/WithOptionsParameter.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/WithOptionsParameter.cs
new file mode 100644
index 0000000..9b055ec
--- /dev/null
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/WithOptionsParameter.cs
@@ -0,0 +1,83 @@
+#region License
+
+/*
+ * 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.
+ */
+
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Dynamic;
+using System.Linq;
+using System.Reflection;
+using Gremlin.Net.Process.Traversal.Step.Util;
+
+namespace Gremlin.Net.IntegrationTest.Gherkin.TraversalEvaluation
+{
+    /// <summary>
+    /// Represents a parameter for the with() step
+    /// </summary>
+    internal class WithOptionsParameter : ITokenParameter, IEquatable<WithOptionsParameter>
+    {
+        private readonly string _text;
+        private readonly string _value;
+        
+        public WithOptionsParameter(string text)
+        {
+            _text = text;
+            var separatorIndex = text.IndexOf('.');
+            var value = text.Substring(separatorIndex + 1);
+            _value = value.Substring(0, 1).ToUpper() + value.Substring(1);
+        }
+
+        public bool Equals(WithOptionsParameter other)
+        {
+            return _text == other._text;
+        }
+
+        public override bool Equals(object obj)
+        {
+            if (ReferenceEquals(null, obj)) return false;
+            if (ReferenceEquals(this, obj)) return true;
+            if (obj.GetType() != GetType()) return false;
+            return Equals((WithOptionsParameter) obj);
+        }
+
+        public override int GetHashCode()
+        {
+            return _text.GetHashCode();
+        }
+
+        public object GetValue()
+        {
+            var field = typeof(WithOptions).GetField(_value, BindingFlags.Static | BindingFlags.Public);
+            return field.GetValue(null);
+        }
+
+        public void SetContextParameterValues(IDictionary<string, object> parameterValues)
+        {
+
+        }
+
+        public Type GetParameterType()
+        {
+            return typeof(object);
+        }
+    }
+}
diff --git a/gremlin-javascript/glv/TraversalSource.template b/gremlin-javascript/glv/TraversalSource.template
index cdbec26..c66cbb4 100644
--- a/gremlin-javascript/glv/TraversalSource.template
+++ b/gremlin-javascript/glv/TraversalSource.template
@@ -215,6 +215,10 @@ class TraversalSideEffects {
 
 }
 
+const withOptions = {
+  <%= withOptions.collect { it.name + ": " + it.value }.join(",\n  ")%>
+};
+
 function toEnum(typeName, keys) {
   const result = {};
   keys.split(' ').forEach(k => {
@@ -242,6 +246,7 @@ module.exports = {
   EnumValue,
   P,
   TextP,
+  withOptions,
   IO,
   Traversal,
   TraversalSideEffects,
diff --git a/gremlin-javascript/glv/generate.groovy b/gremlin-javascript/glv/generate.groovy
index 575f847..cd3e899 100644
--- a/gremlin-javascript/glv/generate.groovy
+++ b/gremlin-javascript/glv/generate.groovy
@@ -31,6 +31,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.P
 import org.apache.tinkerpop.gremlin.process.traversal.TextP
 import org.apache.tinkerpop.gremlin.process.traversal.IO
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.WithOptions
 import java.lang.reflect.Modifier
 
 def toJsMap = ["in": "in_",
@@ -39,6 +40,10 @@ def toJsMap = ["in": "in_",
 
 def toJs = { symbol -> toJsMap.getOrDefault(symbol, symbol) }
 
+def toJSValue = { type, value ->
+  type == String.class && value != null ? ('"' + value + '"') : value
+}
+
 def decapitalize = {
     String string = it;
     if (string == null || string.length() == 0) {
@@ -109,7 +114,9 @@ def binding = ["enums": CoreImports.getClassImports()
                "tokens": gatherTokensFrom([IO, ConnectedComponent, ShortestPath, PageRank, PeerPressure]),
                "toJs": toJs,
                "version": determineVersion(),
-               "decapitalize": decapitalize]
+               "decapitalize": decapitalize,
+               "withOptions": WithOptions.getDeclaredFields().
+                        collect {["name": it.name, "value": toJSValue(it.type, it.get(null))]}]
 
 def engine = new GStringTemplateEngine()
 def graphTraversalTemplate = engine.createTemplate(new File("${project.basedir}/glv/GraphTraversalSource.template"))
@@ -124,4 +131,4 @@ traversalFile.newWriter().withWriter{ it << traversalTemplate }
 
 def packageJsonTemplate = engine.createTemplate(new File("${project.basedir}/glv/PackageJson.template")).make(binding)
 def packageJsonFile = new File("${project.basedir}/src/main/javascript/gremlin-javascript/package.json")
-packageJsonFile.newWriter().withWriter{ it << packageJsonTemplate }
\ No newline at end of file
+packageJsonFile.newWriter().withWriter{ it << packageJsonTemplate }
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/index.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/index.js
index 7f97b40..a7a9acd 100644
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/index.js
+++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/index.js
@@ -73,7 +73,8 @@ module.exports = {
     GraphTraversal: gt.GraphTraversal,
     GraphTraversalSource: gt.GraphTraversalSource,
     statics: gt.statics,
-    Translator
+    Translator,
+    withOptions: t.withOptions
   },
   structure: {
     io: {
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/process/traversal.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/process/traversal.js
index 81853a6..ddf58b0 100644
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/process/traversal.js
+++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/process/traversal.js
@@ -388,6 +388,16 @@ class TraversalSideEffects {
 
 }
 
+const withOptions = {
+  tokens: "~tinkerpop.valueMap.tokens",
+  none: 0,
+  ids: 1,
+  labels: 2,
+  keys: 4,
+  values: 8,
+  all: 15
+};
+
 function toEnum(typeName, keys) {
   const result = {};
   keys.split(' ').forEach(k => {
@@ -415,6 +425,7 @@ module.exports = {
   EnumValue,
   P,
   TextP,
+  withOptions,
   IO,
   Traversal,
   TraversalSideEffects,
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/feature-steps.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/feature-steps.js
index d1d5b52..5f63bff 100644
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/feature-steps.js
+++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/feature-steps.js
@@ -225,7 +225,8 @@ function getSandbox(g, parameters) {
     Scope: traversalModule.scope,
     Operator: traversalModule.operator,
     T: traversalModule.t,
-    toLong: utils.toLong
+    toLong: utils.toLong,
+    WithOptions: traversalModule.withOptions
   };
   // Pass the parameter to the sandbox
   Object.keys(parameters).forEach(paramName => sandbox[paramName] = parameters[paramName]);
diff --git a/gremlin-python/glv/TraversalSource.template b/gremlin-python/glv/TraversalSource.template
index 4f40a5f..5c623c0 100644
--- a/gremlin-python/glv/TraversalSource.template
+++ b/gremlin-python/glv/TraversalSource.template
@@ -344,3 +344,11 @@ class Binding(object):
 
     def __repr__(self):
         return "binding[" + self.key + "=" + str(self.value) + "]"
+
+'''
+WITH OPTIONS
+'''
+class WithOptions(object):
+<% withOptions.each { %>
+    <%= it.name %> = <%= it.value %>
+<% } %>
diff --git a/gremlin-python/glv/generate.groovy b/gremlin-python/glv/generate.groovy
index 60d8381..6f61680 100644
--- a/gremlin-python/glv/generate.groovy
+++ b/gremlin-python/glv/generate.groovy
@@ -29,6 +29,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.P
 import org.apache.tinkerpop.gremlin.process.traversal.TextP
 import org.apache.tinkerpop.gremlin.process.traversal.IO
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.WithOptions
 import java.lang.reflect.Modifier
 
 // this is a bit of a copy of what's in SymbolHelper - no way around it because this code generation task occurs
@@ -52,6 +53,10 @@ def gatherTokensFrom = { tokenClasses ->
     return m
 }
 
+def toPythonValue = { type, value ->
+  type == String.class && value != null ? ('"' + value + '"') : value
+}
+
 def toJavaMap = toPythonMap.collectEntries{k,v -> [(v):k]}
 def toPython = { symbol -> toPythonMap.getOrDefault(symbol, symbol) }
 def toJava = { symbol -> toJavaMap.getOrDefault(symbol, symbol) }
@@ -100,7 +105,9 @@ def binding = ["enums": CoreImports.getClassImports()
                        sort { a, b -> a <=> b },
                "tokens": gatherTokensFrom([IO, ConnectedComponent, ShortestPath, PageRank, PeerPressure]),
                "toPython": toPython,
-               "toJava": toJava]
+               "toJava": toJava,
+               "withOptions": WithOptions.getDeclaredFields().
+                        collect {["name": it.name, "value": toPythonValue(it.type, it.get(null))]}]
 
 def engine = new groovy.text.GStringTemplateEngine()
 def traversalTemplate = engine.createTemplate(new File("${projectBaseDir}/glv/TraversalSource.template")).make(binding)
diff --git a/gremlin-python/src/main/java/org/apache/tinkerpop/gremlin/python/jsr223/SymbolHelper.java b/gremlin-python/src/main/java/org/apache/tinkerpop/gremlin/python/jsr223/SymbolHelper.java
index ce4ad7f..6a7564b 100644
--- a/gremlin-python/src/main/java/org/apache/tinkerpop/gremlin/python/jsr223/SymbolHelper.java
+++ b/gremlin-python/src/main/java/org/apache/tinkerpop/gremlin/python/jsr223/SymbolHelper.java
@@ -42,6 +42,7 @@ public final class SymbolHelper {
         TO_PYTHON_MAP.put("list", "list_");
         TO_PYTHON_MAP.put("set", "set_");
         TO_PYTHON_MAP.put("all", "all_");
+        TO_PYTHON_MAP.put("with", "with_");
         //
         TO_PYTHON_MAP.forEach((k, v) -> FROM_PYTHON_MAP.put(v, k));
     }
diff --git a/gremlin-python/src/main/jython/gremlin_python/process/traversal.py b/gremlin-python/src/main/jython/gremlin_python/process/traversal.py
index c1458bc..13e4504 100644
--- a/gremlin-python/src/main/jython/gremlin_python/process/traversal.py
+++ b/gremlin-python/src/main/jython/gremlin_python/process/traversal.py
@@ -616,3 +616,23 @@ class Binding(object):
 
     def __repr__(self):
         return "binding[" + self.key + "=" + str(self.value) + "]"
+
+'''
+WITH OPTIONS
+'''
+class WithOptions(object):
+
+    tokens = "~tinkerpop.valueMap.tokens"
+
+    none = 0
+
+    ids = 1
+
+    labels = 2
+
+    keys = 4
+
+    values = 8
+
+    all = 15
+
diff --git a/gremlin-python/src/main/jython/gremlin_python/structure/io/graphsonV2d0.py b/gremlin-python/src/main/jython/gremlin_python/structure/io/graphsonV2d0.py
index cfb5171..3046f54 100644
--- a/gremlin-python/src/main/jython/gremlin_python/structure/io/graphsonV2d0.py
+++ b/gremlin-python/src/main/jython/gremlin_python/structure/io/graphsonV2d0.py
@@ -136,7 +136,7 @@ class _GraphSONTypeIO(object):
 
     symbolMap = {"global_": "global", "as_": "as", "in_": "in", "and_": "and",
                  "or_": "or", "is_": "is", "not_": "not", "from_": "from",
-                 "set_": "set", "list_": "list", "all_": "all"}
+                 "set_": "set", "list_": "list", "all_": "all", "with_": "with"}
 
     @classmethod
     def unmangleKeyword(cls, symbol):
diff --git a/gremlin-python/src/main/jython/gremlin_python/structure/io/graphsonV3d0.py b/gremlin-python/src/main/jython/gremlin_python/structure/io/graphsonV3d0.py
index f634361..aeaa6e1 100644
--- a/gremlin-python/src/main/jython/gremlin_python/structure/io/graphsonV3d0.py
+++ b/gremlin-python/src/main/jython/gremlin_python/structure/io/graphsonV3d0.py
@@ -141,7 +141,7 @@ class _GraphSONTypeIO(object):
 
     symbolMap = {"global_": "global", "as_": "as", "in_": "in", "and_": "and",
                  "or_": "or", "is_": "is", "not_": "not", "from_": "from",
-                 "set_": "set", "list_": "list", "all_": "all"}
+                 "set_": "set", "list_": "list", "all_": "all", "with_": "with"}
 
     @classmethod
     def unmangleKeyword(cls, symbol):
diff --git a/gremlin-python/src/main/jython/radish/feature_steps.py b/gremlin-python/src/main/jython/radish/feature_steps.py
index 4777ef3..e206454 100644
--- a/gremlin-python/src/main/jython/radish/feature_steps.py
+++ b/gremlin-python/src/main/jython/radish/feature_steps.py
@@ -21,7 +21,7 @@ import json
 import re
 from gremlin_python.structure.graph import Graph, Path
 from gremlin_python.process.graph_traversal import __
-from gremlin_python.process.traversal import Barrier, Cardinality, P, TextP, Pop, Scope, Column, Order, Direction, T, Pick, Operator, IO
+from gremlin_python.process.traversal import Barrier, Cardinality, P, TextP, Pop, Scope, Column, Order, Direction, T, Pick, Operator, IO, WithOptions
 from radish import given, when, then
 from hamcrest import *
 
@@ -262,7 +262,8 @@ def _make_traversal(g, traversal_string, params):
          "Pop": Pop,
          "Scope": Scope,
          "Operator": Operator,
-         "T": T}
+         "T": T,
+         "WithOptions": WithOptions}
 
     b.update(params)
 
diff --git a/gremlin-test/features/map/AddVertex.feature b/gremlin-test/features/map/AddVertex.feature
index 761916e..a60fefb 100644
--- a/gremlin-test/features/map/AddVertex.feature
+++ b/gremlin-test/features/map/AddVertex.feature
@@ -336,7 +336,7 @@ Feature: Step - addV()
       | marko |
     And the graph should return 2 for count of "g.V().has(\"name\",\"marko\")"
 
-  Scenario: g_V_asXaX_hasXname_markoX_outXcreatedX_asXbX_addVXselectXaX_labelX_propertyXtest_selectXbX_labelX_valueMapXtrueX
+  Scenario: g_V_asXaX_hasXname_markoX_outXcreatedX_asXbX_addVXselectXaX_labelX_propertyXtest_selectXbX_labelX_valueMap_withXtokensX
     Given the empty graph
     And the graph initializer of
       """
@@ -355,7 +355,7 @@ Feature: Step - addV()
       """
     And the traversal of
       """
-      g.V().as("a").has("name", "marko").out("created").as("b").addV(__.select("a").label()).property("test", __.select("b").label()).valueMap(true)
+      g.V().as("a").has("name", "marko").out("created").as("b").addV(__.select("a").label()).property("test", __.select("b").label()).valueMap().with(WithOptions.tokens)
       """
     When iterated to list
     Then the result should have a count of 1
diff --git a/gremlin-test/features/map/ValueMap.feature b/gremlin-test/features/map/ValueMap.feature
index 109318f..e8880f8 100644
--- a/gremlin-test/features/map/ValueMap.feature
+++ b/gremlin-test/features/map/ValueMap.feature
@@ -33,11 +33,11 @@ Feature: Step - valueMap()
       | m[{"name": ["lop"], "lang": ["java"]}] |
       | m[{"name": ["ripple"], "lang": ["java"]}] |
 
-  Scenario: g_V_valueMapXtrueX
+  Scenario: g_V_valueMap_withXtokensX
     Given the modern graph
     And the traversal of
       """
-      g.V().valueMap(true)
+      g.V().valueMap().with(WithOptions.tokens)
       """
     When iterated to list
     Then the result should be unordered
@@ -65,11 +65,11 @@ Feature: Step - valueMap()
       | m[{"name": ["lop"]}] |
       | m[{"name": ["ripple"]}] |
 
-  Scenario: g_V_valueMapXtrue_name_ageX
+  Scenario: g_V_valueMapXname_ageX_withXtokensX
     Given the modern graph
     And the traversal of
       """
-      g.V().valueMap(true, "name", "age")
+      g.V().valueMap("name", "age").with(WithOptions.tokens)
       """
     When iterated to list
     Then the result should be unordered
@@ -81,6 +81,22 @@ Feature: Step - valueMap()
       | m[{"t[id]": "v[lop].id", "t[label]": "software", "name": ["lop"]}] |
       | m[{"t[id]": "v[ripple].id", "t[label]": "software", "name": ["ripple"]}] |
 
+  Scenario: g_V_valueMapXname_ageX_withXtokens_labelsX_byXunfoldX
+    Given the modern graph
+    And the traversal of
+      """
+      g.V().valueMap("name", "age").with(WithOptions.tokens, WithOptions.labels).by(__.unfold())
+      """
+    When iterated to list
+    Then the result should be unordered
+      | result |
+      | m[{"t[label]": "person", "name": "marko", "age": 29}] |
+      | m[{"t[label]": "person", "name": "josh", "age": 32}] |
+      | m[{"t[label]": "person", "name": "peter", "age": 35}] |
+      | m[{"t[label]": "person", "name": "vadas", "age": 27}] |
+      | m[{"t[label]": "software", "name": "lop"}] |
+      | m[{"t[label]": "software", "name": "ripple"}] |
+
   Scenario: g_VX1X_outXcreatedX_valueMap
     Given the modern graph
     And using the parameter v1Id defined as "v[marko].id"
@@ -93,15 +109,28 @@ Feature: Step - valueMap()
       | result |
       | m[{"name": ["lop"], "lang": ["java"]}] |
 
-  Scenario: g_V_hasLabelXpersonX_filterXoutEXcreatedXX_valueMapXtrueX
+  Scenario: g_V_hasLabelXpersonX_filterXoutEXcreatedXX_valueMap_withXtokensX
     Given the modern graph
     And the traversal of
       """
-      g.V().hasLabel("person").filter(__.outE("created")).valueMap(true)
+      g.V().hasLabel("person").filter(__.outE("created")).valueMap().with(WithOptions.tokens)
       """
     When iterated to list
     Then the result should be unordered
       | result |
       | m[{"name": ["marko"], "age": [29], "t[label]":"person", "t[id]":"v[marko].id"}] |
       | m[{"name": ["josh"], "age": [32], "t[label]":"person", "t[id]":"v[josh].id"}] |
-      | m[{"name": ["peter"], "age": [35], "t[label]":"person", "t[id]":"v[peter].id"}] |
\ No newline at end of file
+      | m[{"name": ["peter"], "age": [35], "t[label]":"person", "t[id]":"v[peter].id"}] |
+
+  Scenario: g_VX1X_valueMapXname_locationX_byXunfoldX_by
+    Given the crew graph
+    And using the parameter v1Id defined as "v[marko].id"
+    And the traversal of
+      """
+      g.V(v1Id).valueMap("name", "location").by(__.unfold()).by()
+      """
+    When iterated to list
+    Then the result should be unordered
+      | result |
+      | m[{"name": "marko", "location": ["san diego", "santa cruz", "brussels", "santa fe"]}] |
+
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/computer/GraphComputerTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/computer/GraphComputerTest.java
index 2972ee8..13b573f 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/computer/GraphComputerTest.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/computer/GraphComputerTest.java
@@ -2495,7 +2495,7 @@ public class GraphComputerTest extends AbstractGremlinProcessTest {
 
         try {
             g.V().repeat(__.out()).emit().program(vp).dedup()
-                    .valueMap("name", "pl").forEachRemaining((Map<String, Object> map) -> {
+                    .valueMap("name", "pl").forEachRemaining((Map<Object, Object> map) -> {
 
                 final String name = (String) ((List) map.get("name")).get(0);
                 final List<Integer> pathLengths = (List<Integer>) map.get("pl");
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AddVertexTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AddVertexTest.java
index f732a44..21fbb8c 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AddVertexTest.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AddVertexTest.java
@@ -24,6 +24,7 @@ import org.apache.tinkerpop.gremlin.LoadGraphWith;
 import org.apache.tinkerpop.gremlin.process.GremlinProcessRunner;
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.WithOptions;
 import org.apache.tinkerpop.gremlin.structure.Graph;
 import org.apache.tinkerpop.gremlin.structure.T;
 import org.apache.tinkerpop.gremlin.structure.Vertex;
@@ -65,7 +66,7 @@ public abstract class AddVertexTest extends AbstractGremlinTest {
 
     public abstract Traversal<Vertex, Vertex> get_g_V_addVXanimalX_propertyXname_valuesXnameXX_propertyXname_an_animalX_propertyXvaluesXnameX_labelX();
 
-    public abstract Traversal<Vertex, Map<String, List<String>>> get_g_withSideEffectXa_testX_V_hasLabelXsoftwareX_propertyXtemp_selectXaXX_valueMapXname_tempX();
+    public abstract Traversal<Vertex, Map<Object, List<String>>> get_g_withSideEffectXa_testX_V_hasLabelXsoftwareX_propertyXtemp_selectXaXX_valueMapXname_tempX();
 
     public abstract Traversal<Vertex, String> get_g_withSideEffectXa_markoX_addV_propertyXname_selectXaXX_name();
 
@@ -73,7 +74,7 @@ public abstract class AddVertexTest extends AbstractGremlinTest {
 
     public abstract Traversal<Vertex, String> get_g_withSideEffectXa_nameX_addV_propertyXselectXaX_markoX_name();
 
-    public abstract Traversal<Vertex, Map<Object, Object>> get_g_V_asXaX_hasXname_markoX_outXcreatedX_asXbX_addVXselectXaX_labelX_propertyXtest_selectXbX_labelX_valueMapXtrueX();
+    public abstract Traversal<Vertex, Map<Object, Object>> get_g_V_asXaX_hasXname_markoX_outXcreatedX_asXbX_addVXselectXaX_labelX_propertyXtest_selectXbX_labelX_valueMap_withXtokensX();
 
     @Test
     @LoadGraphWith(MODERN)
@@ -235,12 +236,12 @@ public abstract class AddVertexTest extends AbstractGremlinTest {
     @LoadGraphWith(MODERN)
     @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_ADD_PROPERTY)
     public void g_withSideEffectXa_testX_V_hasLabelXsoftwareX_propertyXtemp_selectXaXX_valueMapXname_tempX() {
-        final Traversal<Vertex, Map<String, List<String>>> traversal = get_g_withSideEffectXa_testX_V_hasLabelXsoftwareX_propertyXtemp_selectXaXX_valueMapXname_tempX();
+        final Traversal<Vertex, Map<Object, List<String>>> traversal = get_g_withSideEffectXa_testX_V_hasLabelXsoftwareX_propertyXtemp_selectXaXX_valueMapXname_tempX();
         printTraversalForm(traversal);
         int counter = 0;
         while (traversal.hasNext()) {
             counter++;
-            final Map<String, List<String>> valueMap = traversal.next();
+            final Map<Object, List<String>> valueMap = traversal.next();
             assertEquals(2, valueMap.size());
             assertEquals(Collections.singletonList("test"), valueMap.get("temp"));
             assertTrue(valueMap.get("name").equals(Collections.singletonList("ripple")) || valueMap.get("name").equals(Collections.singletonList("lop")));
@@ -285,8 +286,8 @@ public abstract class AddVertexTest extends AbstractGremlinTest {
     @LoadGraphWith(MODERN)
     @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_ADD_VERTICES)
     @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_ADD_PROPERTY)
-    public void g_V_asXaX_hasXname_markoX_outXcreatedX_asXbX_addVXselectXaX_labelX_propertyXtest_selectXbX_labelX_valueMapXtrueX() {
-        final Traversal<Vertex, Map<Object,Object>> traversal = get_g_V_asXaX_hasXname_markoX_outXcreatedX_asXbX_addVXselectXaX_labelX_propertyXtest_selectXbX_labelX_valueMapXtrueX();
+    public void g_V_asXaX_hasXname_markoX_outXcreatedX_asXbX_addVXselectXaX_labelX_propertyXtest_selectXbX_labelX_valueMap_withXtokensX() {
+        final Traversal<Vertex, Map<Object,Object>> traversal = get_g_V_asXaX_hasXname_markoX_outXcreatedX_asXbX_addVXselectXaX_labelX_propertyXtest_selectXbX_labelX_valueMap_withXtokensX();
         printTraversalForm(traversal);
         final Map<Object,Object> map = traversal.next();
         assertFalse(traversal.hasNext());
@@ -339,7 +340,7 @@ public abstract class AddVertexTest extends AbstractGremlinTest {
         }
 
         @Override
-        public Traversal<Vertex, Map<String, List<String>>> get_g_withSideEffectXa_testX_V_hasLabelXsoftwareX_propertyXtemp_selectXaXX_valueMapXname_tempX() {
+        public Traversal<Vertex, Map<Object, List<String>>> get_g_withSideEffectXa_testX_V_hasLabelXsoftwareX_propertyXtemp_selectXaXX_valueMapXname_tempX() {
             return g.withSideEffect("a", "test").V().hasLabel("software").property("temp", select("a")).valueMap("name", "temp");
         }
 
@@ -359,8 +360,8 @@ public abstract class AddVertexTest extends AbstractGremlinTest {
         }
 
         @Override
-        public Traversal<Vertex, Map<Object, Object>> get_g_V_asXaX_hasXname_markoX_outXcreatedX_asXbX_addVXselectXaX_labelX_propertyXtest_selectXbX_labelX_valueMapXtrueX() {
-            return g.V().as("a").has("name", "marko").out("created").as("b").addV(select("a").label()).property("test", select("b").label()).valueMap(true);
+        public Traversal<Vertex, Map<Object, Object>> get_g_V_asXaX_hasXname_markoX_outXcreatedX_asXbX_addVXselectXaX_labelX_propertyXtest_selectXbX_labelX_valueMap_withXtokensX() {
+            return g.V().as("a").has("name", "marko").out("created").as("b").addV(select("a").label()).property("test", select("b").label()).valueMap().with(WithOptions.tokens);
         }
     }
 }
\ No newline at end of file
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/PageRankTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/PageRankTest.java
index 107831a..864ebb0 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/PageRankTest.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/PageRankTest.java
@@ -51,7 +51,7 @@ public abstract class PageRankTest extends AbstractGremlinProcessTest {
 
     public abstract Traversal<Vertex, Vertex> get_g_V_pageRank_hasXpageRankX();
 
-    public abstract Traversal<Vertex, Map<String, List<Object>>> get_g_V_outXcreatedX_pageRank_byXbothEX_byXprojectRankX_timesX0X_valueMapXname_projectRankX();
+    public abstract Traversal<Vertex, Map<Object, List<Object>>> get_g_V_outXcreatedX_pageRank_byXbothEX_byXprojectRankX_timesX0X_valueMapXname_projectRankX();
 
     public abstract Traversal<Vertex, String> get_g_V_pageRank_order_byXpageRank_descX_byXnameX_name();
 
@@ -63,7 +63,7 @@ public abstract class PageRankTest extends AbstractGremlinProcessTest {
 
     public abstract Traversal<Vertex, Map<String, Object>> get_g_V_pageRank_byXpageRankX_asXaX_outXknowsX_pageRank_asXbX_selectXa_bX_by_byXmathX();
 
-    public abstract Traversal<Vertex, Map<String, List<Object>>> get_g_V_hasLabelXsoftwareX_hasXname_rippleX_pageRankX1X_byXinEXcreatedXX_timesX1X_byXpriorsX_inXcreatedX_unionXboth__identityX_valueMapXname_priorsX();
+    public abstract Traversal<Vertex, Map<Object, List<Object>>> get_g_V_hasLabelXsoftwareX_hasXname_rippleX_pageRankX1X_byXinEXcreatedXX_timesX1X_byXpriorsX_inXcreatedX_unionXboth__identityX_valueMapXname_priorsX();
 
     public abstract Traversal<Vertex, Map<Object, List<Vertex>>> get_g_V_outXcreatedX_groupXmX_byXlabelX_pageRankX1X_withXpropertyName_pageRankXX_withXedges_inEXX_withXtimes_1X_inXcreatedX_groupXmX_byXpageRankX_capXmX();
 
@@ -80,9 +80,9 @@ public abstract class PageRankTest extends AbstractGremlinProcessTest {
     @Test
     @LoadGraphWith(MODERN)
     public void g_V_outXcreatedX_pageRank_byXbothEX_byXprojectRankX_valueMapXname_projectRankX() {
-        final Traversal<Vertex, Map<String, List<Object>>> traversal = get_g_V_outXcreatedX_pageRank_byXbothEX_byXprojectRankX_timesX0X_valueMapXname_projectRankX();
+        final Traversal<Vertex, Map<Object, List<Object>>> traversal = get_g_V_outXcreatedX_pageRank_byXbothEX_byXprojectRankX_timesX0X_valueMapXname_projectRankX();
         printTraversalForm(traversal);
-        final List<Map<String, List<Object>>> result = traversal.toList();
+        final List<Map<Object, List<Object>>> result = traversal.toList();
         assertEquals(4, result.size());
         final Map<String, Double> map = new HashMap<>();
         result.forEach(m -> map.put((String) m.get("name").get(0), (Double) m.get("projectRank").get(0)));
@@ -184,11 +184,11 @@ public abstract class PageRankTest extends AbstractGremlinProcessTest {
     @Test
     @LoadGraphWith(MODERN)
     public void g_V_hasLabelXsoftwareX_hasXname_rippleX_pageRankX1X_byXinEXcreatedXX_timesX1X_byXpriorsX_inXcreatedX_unionXboth__identityX_valueMapXname_priorsX() {
-        final Traversal<Vertex, Map<String, List<Object>>> traversal = get_g_V_hasLabelXsoftwareX_hasXname_rippleX_pageRankX1X_byXinEXcreatedXX_timesX1X_byXpriorsX_inXcreatedX_unionXboth__identityX_valueMapXname_priorsX();
+        final Traversal<Vertex, Map<Object, List<Object>>> traversal = get_g_V_hasLabelXsoftwareX_hasXname_rippleX_pageRankX1X_byXinEXcreatedXX_timesX1X_byXpriorsX_inXcreatedX_unionXboth__identityX_valueMapXname_priorsX();
         printTraversalForm(traversal);
         int counter = 0;
         while (traversal.hasNext()) {
-            final Map<String, List<Object>> map = traversal.next();
+            final Map<Object, List<Object>> map = traversal.next();
             assertEquals(2, map.size());
             String name = (String) map.get("name").get(0);
             double pageRank = (Double) map.get("priors").get(0);
@@ -274,7 +274,7 @@ public abstract class PageRankTest extends AbstractGremlinProcessTest {
         }
 
         @Override
-        public Traversal<Vertex, Map<String, List<Object>>> get_g_V_outXcreatedX_pageRank_byXbothEX_byXprojectRankX_timesX0X_valueMapXname_projectRankX() {
+        public Traversal<Vertex, Map<Object, List<Object>>> get_g_V_outXcreatedX_pageRank_byXbothEX_byXprojectRankX_timesX0X_valueMapXname_projectRankX() {
             return g.V().out("created").pageRank().by(__.bothE()).by("projectRank").times(0).valueMap("name", "projectRank");
         }
 
@@ -304,7 +304,7 @@ public abstract class PageRankTest extends AbstractGremlinProcessTest {
         }
 
         @Override
-        public Traversal<Vertex, Map<String, List<Object>>> get_g_V_hasLabelXsoftwareX_hasXname_rippleX_pageRankX1X_byXinEXcreatedXX_timesX1X_byXpriorsX_inXcreatedX_unionXboth__identityX_valueMapXname_priorsX() {
+        public Traversal<Vertex, Map<Object, List<Object>>> get_g_V_hasLabelXsoftwareX_hasXname_rippleX_pageRankX1X_byXinEXcreatedXX_timesX1X_byXpriorsX_inXcreatedX_unionXboth__identityX_valueMapXname_priorsX() {
             return g.V().hasLabel("software").has("name", "ripple").pageRank(1.0).by(__.inE("created")).times(1).by("priors").in("created").union(__.both(), __.identity()).valueMap("name", "priors");
         }
 
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/PeerPressureTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/PeerPressureTest.java
index d53ec3e..5087522 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/PeerPressureTest.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/PeerPressureTest.java
@@ -53,9 +53,9 @@ public abstract class PeerPressureTest extends AbstractGremlinProcessTest {
 
     public abstract Traversal<Vertex, Map<Object, Number>> get_g_V_peerPressure_byXclusterX_byXoutEXknowsXX_pageRankX1X_byXrankX_byXoutEXknowsXX_timesX2X_group_byXclusterX_byXrank_sumX_limitX100X();
 
-    public abstract Traversal<Vertex, Map<String, List<Object>>> get_g_V_hasXname_rippleX_inXcreatedX_peerPressure_byXoutEX_byXclusterX_repeatXunionXidentity__bothX_timesX2X_dedup_valueMapXname_clusterX();
+    public abstract Traversal<Vertex, Map<Object, List<Object>>> get_g_V_hasXname_rippleX_inXcreatedX_peerPressure_byXoutEX_byXclusterX_repeatXunionXidentity__bothX_timesX2X_dedup_valueMapXname_clusterX();
 
-    public abstract Traversal<Vertex, Map<String, List<Object>>> get_g_V_hasXname_rippleX_inXcreatedX_peerPressure_withXedges_outEX_withXpropertyName_clusterX_repeatXunionXidentity__bothX_timesX2X_dedup_valueMapXname_clusterX();
+    public abstract Traversal<Vertex, Map<Object, List<Object>>> get_g_V_hasXname_rippleX_inXcreatedX_peerPressure_withXedges_outEX_withXpropertyName_clusterX_repeatXunionXidentity__bothX_timesX2X_dedup_valueMapXname_clusterX();
 
     @Test
     @LoadGraphWith(MODERN)
@@ -83,9 +83,9 @@ public abstract class PeerPressureTest extends AbstractGremlinProcessTest {
     @LoadGraphWith(MODERN)
     public void g_V_hasXname_rippleX_inXcreatedX_peerPressure_byXoutEX_byXclusterX_repeatXunionXidentity__bothX_timesX2X_dedup_valueMapXname_clusterX() {
         TestHelper.assumeNonDeterministic();
-        final Traversal<Vertex, Map<String, List<Object>>> traversal = get_g_V_hasXname_rippleX_inXcreatedX_peerPressure_byXoutEX_byXclusterX_repeatXunionXidentity__bothX_timesX2X_dedup_valueMapXname_clusterX();
+        final Traversal<Vertex, Map<Object, List<Object>>> traversal = get_g_V_hasXname_rippleX_inXcreatedX_peerPressure_byXoutEX_byXclusterX_repeatXunionXidentity__bothX_timesX2X_dedup_valueMapXname_clusterX();
         printTraversalForm(traversal);
-        final List<Map<String, List<Object>>> results = traversal.toList();
+        final List<Map<Object, List<Object>>> results = traversal.toList();
         assertEquals(6, results.size());
         final Map<String, Object> clusters = new HashMap<>();
         results.forEach(m -> clusters.put((String) m.get("name").get(0), m.get("cluster").get(0)));
@@ -105,9 +105,9 @@ public abstract class PeerPressureTest extends AbstractGremlinProcessTest {
     @LoadGraphWith(MODERN)
     public void g_V_hasXname_rippleX_inXcreatedX_peerPressure_withXEDGES_outEX_withXPROPERTY_NAME_clusterX_repeatXunionXidentity__bothX_timesX2X_dedup_valueMapXname_clusterX() {
         TestHelper.assumeNonDeterministic();
-        final Traversal<Vertex, Map<String, List<Object>>> traversal = get_g_V_hasXname_rippleX_inXcreatedX_peerPressure_withXedges_outEX_withXpropertyName_clusterX_repeatXunionXidentity__bothX_timesX2X_dedup_valueMapXname_clusterX();
+        final Traversal<Vertex, Map<Object, List<Object>>> traversal = get_g_V_hasXname_rippleX_inXcreatedX_peerPressure_withXedges_outEX_withXpropertyName_clusterX_repeatXunionXidentity__bothX_timesX2X_dedup_valueMapXname_clusterX();
         printTraversalForm(traversal);
-        final List<Map<String, List<Object>>> results = traversal.toList();
+        final List<Map<Object, List<Object>>> results = traversal.toList();
         assertEquals(6, results.size());
         final Map<String, Object> clusters = new HashMap<>();
         results.forEach(m -> clusters.put((String) m.get("name").get(0), m.get("cluster").get(0)));
@@ -136,12 +136,12 @@ public abstract class PeerPressureTest extends AbstractGremlinProcessTest {
         }
 
         @Override
-        public Traversal<Vertex, Map<String, List<Object>>> get_g_V_hasXname_rippleX_inXcreatedX_peerPressure_byXoutEX_byXclusterX_repeatXunionXidentity__bothX_timesX2X_dedup_valueMapXname_clusterX() {
+        public Traversal<Vertex, Map<Object, List<Object>>> get_g_V_hasXname_rippleX_inXcreatedX_peerPressure_byXoutEX_byXclusterX_repeatXunionXidentity__bothX_timesX2X_dedup_valueMapXname_clusterX() {
             return g.V().has("name", "ripple").in("created").peerPressure().by(__.outE()).by("cluster").repeat(__.union(__.identity(), __.both())).times(2).dedup().valueMap("name", "cluster");
         }
 
         @Override
-        public Traversal<Vertex, Map<String, List<Object>>> get_g_V_hasXname_rippleX_inXcreatedX_peerPressure_withXedges_outEX_withXpropertyName_clusterX_repeatXunionXidentity__bothX_timesX2X_dedup_valueMapXname_clusterX() {
+        public Traversal<Vertex, Map<Object, List<Object>>> get_g_V_hasXname_rippleX_inXcreatedX_peerPressure_withXedges_outEX_withXpropertyName_clusterX_repeatXunionXidentity__bothX_timesX2X_dedup_valueMapXname_clusterX() {
             return g.V().has("name", "ripple").in("created").peerPressure().with(PeerPressure.edges,__.outE()).with(PeerPressure.propertyName, "cluster").repeat(__.union(__.identity(), __.both())).times(2).dedup().valueMap("name", "cluster");
         }
     }
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ProgramTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ProgramTest.java
index 1923352..a0c5b23 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ProgramTest.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ProgramTest.java
@@ -71,7 +71,7 @@ public abstract class ProgramTest extends AbstractGremlinProcessTest {
 
     public abstract Traversal<Vertex, Vertex> get_g_V_programXpageRankX();
 
-    public abstract Traversal<Vertex, Map<String, List<Object>>> get_g_V_hasLabelXpersonX_programXpageRank_rankX_order_byXrank_ascX_valueMapXname_rankX();
+    public abstract Traversal<Vertex, Map<Object, List<Object>>> get_g_V_hasLabelXpersonX_programXpageRank_rankX_order_byXrank_ascX_valueMapXname_rankX();
 
     public abstract Traversal<Vertex, Map<String, Object>> get_g_V_outXcreatedX_aggregateXxX_byXlangX_groupCount_programXTestProgramX_asXaX_selectXa_xX();
 
@@ -92,12 +92,12 @@ public abstract class ProgramTest extends AbstractGremlinProcessTest {
     @Test
     @LoadGraphWith(MODERN)
     public void g_V_hasLabelXpersonX_programXpageRank_rankX_order_byXrank_ascX_valueMapXname_rankX() {
-        final Traversal<Vertex, Map<String, List<Object>>> traversal = get_g_V_hasLabelXpersonX_programXpageRank_rankX_order_byXrank_ascX_valueMapXname_rankX();
+        final Traversal<Vertex, Map<Object, List<Object>>> traversal = get_g_V_hasLabelXpersonX_programXpageRank_rankX_order_byXrank_ascX_valueMapXname_rankX();
         printTraversalForm(traversal);
         int counter = 0;
         double lastRank = Double.MIN_VALUE;
         while (traversal.hasNext()) {
-            final Map<String, List<Object>> map = traversal.next();
+            final Map<Object, List<Object>> map = traversal.next();
             assertEquals(2, map.size());
             assertEquals(1, map.get("name").size());
             assertEquals(1, map.get("rank").size());
@@ -148,7 +148,7 @@ public abstract class ProgramTest extends AbstractGremlinProcessTest {
         }
 
         @Override
-        public Traversal<Vertex, Map<String, List<Object>>> get_g_V_hasLabelXpersonX_programXpageRank_rankX_order_byXrank_ascX_valueMapXname_rankX() {
+        public Traversal<Vertex, Map<Object, List<Object>>> get_g_V_hasLabelXpersonX_programXpageRank_rankX_order_byXrank_ascX_valueMapXname_rankX() {
             return g.V().hasLabel("person").program(PageRankVertexProgram.build().property("rank").create(graph)).order().by("rank", Order.asc).valueMap("name", "rank");
         }
 
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 6962caf..219a6b0 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,14 +23,17 @@ 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.dsl.graph.__;
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.WithOptions;
 import org.apache.tinkerpop.gremlin.structure.T;
 import org.apache.tinkerpop.gremlin.structure.Vertex;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import java.util.Arrays;
 import java.util.List;
 import java.util.Map;
 
+import static org.apache.tinkerpop.gremlin.LoadGraphWith.GraphData.CREW;
 import static org.apache.tinkerpop.gremlin.LoadGraphWith.GraphData.MODERN;
 import static org.hamcrest.core.Is.is;
 import static org.hamcrest.MatcherAssert.assertThat;
@@ -49,27 +52,35 @@ import static org.junit.Assert.assertFalse;
 @RunWith(GremlinProcessRunner.class)
 public abstract class ValueMapTest extends AbstractGremlinProcessTest {
 
-    public abstract Traversal<Vertex, Map<String, List>> get_g_V_valueMap();
+    public abstract Traversal<Vertex, Map<Object, List>> get_g_V_valueMap();
 
     public abstract Traversal<Vertex, Map<Object, Object>> get_g_V_valueMapXtrueX();
 
-    public abstract Traversal<Vertex, Map<String, List>> get_g_V_valueMapXname_ageX();
+    public abstract Traversal<Vertex, Map<Object, Object>> get_g_V_valueMap_withXtokensX();
 
-    public abstract Traversal<Vertex, Map<Object, Object>> get_g_V_hasLabelXpersonX_filterXoutEXcreatedXX_valueMapXtrueX();
+    public abstract Traversal<Vertex, Map<Object, List>> get_g_V_valueMapXname_ageX();
+
+    public abstract Traversal<Vertex, Map<Object, Object>> get_g_V_hasLabelXpersonX_filterXoutEXcreatedXX_valueMap_withXtokensX();
 
     public abstract Traversal<Vertex, Map<Object, Object>> get_g_V_valueMapXtrue_name_ageX();
 
-    public abstract Traversal<Vertex, Map<String, List<String>>> get_g_VX1X_outXcreatedX_valueMap(final Object v1Id);
+    public abstract Traversal<Vertex, Map<Object, Object>> get_g_V_valueMapXname_ageX_withXtokensX();
+
+    public abstract Traversal<Vertex, Map<Object, Object>> get_g_V_valueMapXname_ageX_withXtokens_labelsX_byXunfoldX();
+
+    public abstract Traversal<Vertex, Map<Object, List<String>>> get_g_VX1X_outXcreatedX_valueMap(final Object v1Id);
+
+    public abstract Traversal<Vertex, Map<Object, Object>> get_g_VX1X_valueMapXname_locationX_byXunfoldX_by(final Object v1Id);
 
     @Test
     @LoadGraphWith(MODERN)
     public void g_V_valueMap() {
-        final Traversal<Vertex, Map<String, List>> traversal = get_g_V_valueMap();
+        final Traversal<Vertex, Map<Object, List>> traversal = get_g_V_valueMap();
         printTraversalForm(traversal);
         int counter = 0;
         while (traversal.hasNext()) {
             counter++;
-            final Map<String, List> values = traversal.next();
+            final Map<Object, List> values = traversal.next();
             final String name = (String) values.get("name").get(0);
             assertEquals(2, values.size());
             if (name.equals("marko")) {
@@ -93,50 +104,52 @@ public abstract class ValueMapTest extends AbstractGremlinProcessTest {
 
     @Test
     @LoadGraphWith(MODERN)
-    public void g_V_valueMapXtrueX() {
-        final Traversal<Vertex, Map<Object, Object>> traversal = get_g_V_valueMapXtrueX();
-        printTraversalForm(traversal);
-        int counter = 0;
-        while (traversal.hasNext()) {
-            counter++;
-            final Map<Object, 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);
+    public void g_V_valueMap_withXtokensX() {
+        for (final Traversal<Vertex, Map<Object, Object>> traversal :
+                Arrays.asList(get_g_V_valueMapXtrueX(), get_g_V_valueMap_withXtokensX())) {
+            printTraversalForm(traversal);
+            int counter = 0;
+            while (traversal.hasNext()) {
+                counter++;
+                final Map<Object, 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);
         }
-        assertEquals(6, counter);
     }
 
     @Test
     @LoadGraphWith(MODERN)
     public void g_V_valueMapXname_ageX() {
-        final Traversal<Vertex, Map<String, List>> traversal = get_g_V_valueMapXname_ageX();
+        final Traversal<Vertex, Map<Object, List>> traversal = get_g_V_valueMapXname_ageX();
         printTraversalForm(traversal);
         int counter = 0;
         while (traversal.hasNext()) {
             counter++;
-            final Map<String, List> values = traversal.next();
+            final Map<Object, List> values = traversal.next();
             final String name = (String) values.get("name").get(0);
             if (name.equals("marko")) {
                 assertEquals(29, values.get("age").get(0));
@@ -165,37 +178,81 @@ public abstract class ValueMapTest extends AbstractGremlinProcessTest {
 
     @Test
     @LoadGraphWith(MODERN)
-    public void g_V_valueMapXtrue_name_ageX() {
-        final Traversal<Vertex, Map<Object, Object>> traversal = get_g_V_valueMapXtrue_name_ageX();
+    public void g_V_valueMapXname_ageX_withXtokensX() {
+        for (final Traversal<Vertex, Map<Object, Object>> traversal :
+                Arrays.asList(get_g_V_valueMapXtrue_name_ageX(), get_g_V_valueMapXname_ageX_withXtokensX())) {
+            printTraversalForm(traversal);
+            int counter = 0;
+            while (traversal.hasNext()) {
+                counter++;
+                final Map<Object, 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_V_valueMapXname_ageX_withXtokens_labelsX_byXunfoldX() {
+        final Traversal<Vertex, Map<Object, Object>> traversal = get_g_V_valueMapXname_ageX_withXtokens_labelsX_byXunfoldX();
         printTraversalForm(traversal);
         int counter = 0;
         while (traversal.hasNext()) {
             counter++;
             final Map<Object, Object> values = traversal.next();
-            final String name = (String) ((List) values.get("name")).get(0);
-            assertThat(values.containsKey(T.id), is(true));
+            final String name = (String) values.get("name");
+            assertThat(values.containsKey(T.id), is(false));
             if (name.equals("marko")) {
-                assertEquals(4, values.size());
-                assertEquals(29, ((List) values.get("age")).get(0));
+                assertEquals(3, values.size());
+                assertEquals(29, values.get("age"));
                 assertEquals("person", values.get(T.label));
             } else if (name.equals("josh")) {
-                assertEquals(4, values.size());
-                assertEquals(32, ((List) values.get("age")).get(0));
+                assertEquals(3, values.size());
+                assertEquals(32, values.get("age"));
                 assertEquals("person", values.get(T.label));
             } else if (name.equals("peter")) {
-                assertEquals(4, values.size());
-                assertEquals(35, ((List) values.get("age")).get(0));
+                assertEquals(3, values.size());
+                assertEquals(35, values.get("age"));
                 assertEquals("person", values.get(T.label));
             } else if (name.equals("vadas")) {
-                assertEquals(4, values.size());
-                assertEquals(27, ((List) values.get("age")).get(0));
+                assertEquals(3, values.size());
+                assertEquals(27, values.get("age"));
                 assertEquals("person", values.get(T.label));
             } else if (name.equals("lop")) {
-                assertEquals(3, values.size());
+                assertEquals(2, values.size());
                 assertNull(values.get("lang"));
                 assertEquals("software", values.get(T.label));
             } else if (name.equals("ripple")) {
-                assertEquals(3, values.size());
+                assertEquals(2, values.size());
                 assertNull(values.get("lang"));
                 assertEquals("software", values.get(T.label));
             } else {
@@ -208,15 +265,14 @@ public abstract class ValueMapTest extends AbstractGremlinProcessTest {
     @Test
     @LoadGraphWith(MODERN)
     public void g_VX1X_outXcreatedX_valueMap() {
-        final Traversal<Vertex, Map<String, List<String>>> traversal = get_g_VX1X_outXcreatedX_valueMap(convertToVertexId("marko"));
+        final Traversal<Vertex, Map<Object, List<String>>> traversal = get_g_VX1X_outXcreatedX_valueMap(convertToVertexId("marko"));
         printTraversalForm(traversal);
         assertTrue(traversal.hasNext());
-        final Map<String, List<String>> values = traversal.next();
+        final Map<Object, List<String>> values = traversal.next();
         assertFalse(traversal.hasNext());
         assertEquals("lop", values.get("name").get(0));
         assertEquals("java", values.get("lang").get(0));
         assertEquals(2, values.size());
-
     }
 
     /**
@@ -224,8 +280,8 @@ public abstract class ValueMapTest extends AbstractGremlinProcessTest {
      */
     @Test
     @LoadGraphWith(MODERN)
-    public void g_V_hasLabelXpersonX_filterXoutEXcreatedXX_valueMapXtrueX() {
-    	final Traversal<Vertex,Map<Object,Object>> gt=get_g_V_hasLabelXpersonX_filterXoutEXcreatedXX_valueMapXtrueX();
+    public void g_V_hasLabelXpersonX_filterXoutEXcreatedXX_valueMap_withXtokensX() {
+    	final Traversal<Vertex,Map<Object,Object>> gt = get_g_V_hasLabelXpersonX_filterXoutEXcreatedXX_valueMap_withXtokensX();
     	int cnt = 0;
     	while(gt.hasNext()){
     		final Map<Object,Object> m = gt.next();
@@ -242,9 +298,27 @@ public abstract class ValueMapTest extends AbstractGremlinProcessTest {
     	assertTrue(cnt > 0);
     }
 
+    @Test
+    @LoadGraphWith(CREW)
+    public void g_VX1X_valueMapXname_locationX_byXunfoldX_by() {
+        final Traversal<Vertex,Map<Object,Object>> traversal = get_g_VX1X_valueMapXname_locationX_byXunfoldX_by(convertToVertexId("marko"));
+        printTraversalForm(traversal);
+        assertTrue(traversal.hasNext());
+        final Map<Object, Object> values = traversal.next();
+        assertFalse(traversal.hasNext());
+        assertTrue("name value should be a String", values.containsKey("name") && String.class.equals(values.get("name").getClass()));
+        assertTrue("location value should be a List", values.containsKey("location") && List.class.isAssignableFrom(values.get("location").getClass()));
+        assertEquals("marko", values.get("name"));
+        final List locations = (List) values.get("location");
+        for (final String location : Arrays.asList("san diego", "santa cruz", "brussels", "santa fe")) {
+            assertTrue(locations.contains(location));
+        }
+        assertEquals(2, values.size());
+    }
+
     public static class Traversals extends ValueMapTest {
         @Override
-        public Traversal<Vertex, Map<String, List>> get_g_V_valueMap() {
+        public Traversal<Vertex, Map<Object, List>> get_g_V_valueMap() {
             return g.V().valueMap();
         }
 
@@ -254,7 +328,12 @@ public abstract class ValueMapTest extends AbstractGremlinProcessTest {
         }
 
         @Override
-        public Traversal<Vertex, Map<String, List>> get_g_V_valueMapXname_ageX() {
+        public Traversal<Vertex, Map<Object, Object>> get_g_V_valueMap_withXtokensX() {
+            return g.V().valueMap().with(WithOptions.tokens);
+        }
+
+        @Override
+        public Traversal<Vertex, Map<Object, List>> get_g_V_valueMapXname_ageX() {
             return g.V().valueMap("name", "age");
         }
 
@@ -264,13 +343,29 @@ public abstract class ValueMapTest extends AbstractGremlinProcessTest {
         }
 
         @Override
-        public Traversal<Vertex, Map<String, List<String>>> get_g_VX1X_outXcreatedX_valueMap(final Object v1Id) {
+        public Traversal<Vertex, Map<Object, Object>> get_g_V_valueMapXname_ageX_withXtokensX() {
+            return g.V().valueMap("name", "age").with(WithOptions.tokens);
+        }
+
+        @Override
+        public Traversal<Vertex, Map<Object, Object>> get_g_V_valueMapXname_ageX_withXtokens_labelsX_byXunfoldX() {
+            return g.V().valueMap("name", "age").with(WithOptions.tokens, WithOptions.labels).by(__.unfold());
+        }
+
+        @Override
+        public Traversal<Vertex, Map<Object, List<String>>> get_g_VX1X_outXcreatedX_valueMap(final Object v1Id) {
             return g.V(v1Id).out("created").valueMap();
         }
 
         @Override
-        public Traversal<Vertex, Map<Object, Object>> get_g_V_hasLabelXpersonX_filterXoutEXcreatedXX_valueMapXtrueX() {
-        	return g.V().hasLabel("person").filter(__.outE("created")).valueMap(true);
+        public Traversal<Vertex, Map<Object, Object>> get_g_V_hasLabelXpersonX_filterXoutEXcreatedXX_valueMap_withXtokensX() {
+        	return g.V().hasLabel("person").filter(__.outE("created")).valueMap().with(WithOptions.tokens);
         }
+
+        @Override
+        public Traversal<Vertex, Map<Object, Object>> get_g_VX1X_valueMapXname_locationX_byXunfoldX_by(final Object v1Id) {
+            return g.V(v1Id).valueMap("name","location").by(__.unfold()).by();
+        }
+
     }
 }
diff --git a/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraphPlayTest.java b/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraphPlayTest.java
index a590835..a2019ae 100644
--- a/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraphPlayTest.java
+++ b/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraphPlayTest.java
@@ -19,18 +19,14 @@
 package org.apache.tinkerpop.gremlin.tinkergraph.structure;
 
 import org.apache.tinkerpop.gremlin.process.computer.Computer;
-import org.apache.tinkerpop.gremlin.process.traversal.IO;
-import org.apache.tinkerpop.gremlin.process.traversal.P;
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal;
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.SubgraphStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.PathRetractionStrategy;
 import org.apache.tinkerpop.gremlin.structure.*;
-import org.apache.tinkerpop.gremlin.structure.io.IoTest;
 import org.apache.tinkerpop.gremlin.structure.io.graphml.GraphMLIo;
-import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONReader;
-import org.apache.tinkerpop.gremlin.structure.io.gryo.GryoReader;
 import org.apache.tinkerpop.gremlin.util.TimeUtil;
 import org.junit.Ignore;
 import org.junit.Test;
@@ -38,15 +34,14 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import java.util.Arrays;
-import java.util.HashMap;
 import java.util.List;
-import java.util.Map;
 import java.util.function.BiFunction;
 import java.util.function.Supplier;
 
 import static org.apache.tinkerpop.gremlin.process.traversal.Operator.sum;
 import static org.apache.tinkerpop.gremlin.process.traversal.P.neq;
 import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.*;
+import static org.apache.tinkerpop.gremlin.process.traversal.step.util.WithOptions.*;
 
 /**
  * @author Stephen Mallette (http://stephen.genoprime.com)
@@ -123,92 +118,33 @@ public class TinkerGraphPlayTest {
     @Test
     @Ignore
     public void testPlayDK() throws Exception {
+        TinkerGraph graph = TinkerFactory.createTheCrew();
+        GraphTraversalSource g = graph.traversal().withStrategies(
+                SubgraphStrategy.build().vertexProperties(hasNot("endTime")).create());
 
-        final Map<String, String> aliases = new HashMap<>();
-        aliases.put("marko","okram");
-        final GraphTraversalSource g = TinkerFactory.createModern().traversal();
-        /*g.withSideEffect("a", aliases).V().hasLabel("person").
-                values("name").as("n").
-                optional(select("a").select(select("n"))).
-                forEachRemaining(System.out::println);*/
-
-        // shortest path lengths (by summed weight)
-        g.withSack(0.0).V().has("person", "name", "marko").
-                repeat(__.bothE().
-                        sack(sum).
-                            by("weight").
-                        otherV().
-                        group("m").
-                            by().
-                            by(sack().min()).as("x").
-                        // where(P.eq("m")).by(sack()).by(select(select("x"))). // could be that easy, but "x" is unknown here
-                        filter(project("s","x").
-                                    by(sack()).
-                                    by(select("m").select(select("x"))).
-                                where("s", P.eq("x"))).
-                        group("p").
-                            by().
-                            by(project("path","length").
-                                    by(path().by("name").by("weight")).
-                                    by(sack()))
-                        ).
-                cap("p").unfold().
-                group().
-                    by(select(Column.keys).values("name")).
-                    by(Column.values).next().entrySet().
-                forEach(System.out::println);
-
-        System.out.println("---");
-
-        // longest path lengths (by summed weight)
-        g.withSack(0.0).V().has("person", "name", "marko").
-                repeat(__.bothE().simplePath().
-                        sack(sum).
-                          by("weight").
-                        otherV().
-                        group("m").
-                            by().
-                            by(sack().max()).as("x").
-                        filter(project("s","x").
-                                by(sack()).
-                                by(select("m").select(select("x"))).
-                                where("s", P.eq("x"))).
-                        group("p").
-                                by().
-                                by(project("path","length").
-                                        by(path().by("name").by("weight")).
-                                        by(sack()))
-                        ).
-                cap("p").unfold().
-                group().
-                    by(select(Column.keys).values("name")).
-                    by(Column.values).next().entrySet().
-                forEach(System.out::println);
-
-        System.out.println("---");
-
-        // all shortest paths (by summed weight)
-        g.withSack(0.0).V().as("a").
-                repeat(__.bothE().
-                        sack(sum).
-                            by("weight").
-                        otherV().as("b").
-                        group("m").
-                            by(select("a","b").by("name")).
-                            by(sack().min()).
-                        filter(project("s","x").
-                                by(sack()).
-                                by(select("m").select(select("a", "b").by("name"))).
-                               where("s", P.eq("x"))).
-                        group("p").
-                            by(select("a","b").by("name")).
-                            by(map(union(path().by("name").by("weight"), sack()).fold()))
-                ).
-                cap("p").unfold().
-                order().
-                    by(select(Column.keys).select("a")).
-                    by(select(Column.keys).select("b")).
-                forEachRemaining(System.out::println);
+        System.out.println("\n--- valueMap().by(unfold()) ---");
+        g.V().valueMap().forEachRemaining(System.out::println);
+
+        System.out.println("\n--- valueMap().by(unfold()) ---");
+        g.V().valueMap().by(unfold()).forEachRemaining(System.out::println);
+
+        System.out.println("\n--- valueMap().by(unfold()).with(tokens) ---");
+        g.V().valueMap().by(unfold()).with(tokens).forEachRemaining(System.out::println);
+
+        System.out.println("\n--- valueMap().by(unfold()).with(tokens, false) ---");
+        g.V().valueMap().by(unfold()).with(tokens, false).forEachRemaining(System.out::println);
+
+        System.out.println("\n--- valueMap().by(unfold()).with(tokens, ids) ---");
+        g.V().valueMap().by(unfold()).with(tokens, ids).forEachRemaining(System.out::println);
+
+        System.out.println("\n--- valueMap().by(unfold()).with(tokens, labels) ---");
+        g.V().valueMap().by(unfold()).with(tokens, labels).forEachRemaining(System.out::println);
+
+        System.out.println("\n--- valueMap().by(unfold()).with(tokens, all) ---");
+        g.V().valueMap().by(unfold()).with(tokens, all).forEachRemaining(System.out::println);
+
+        System.out.println("\n--- valueMap().by(unfold()).with(tokens, ids | labels) ---");
+        g.V().valueMap().by(unfold()).with(tokens, ids | labels).forEachRemaining(System.out::println);
     }
 
     @Test