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:05 UTC
[tinkerpop] 01/01: TINKERPOP-2059 Implemented `by()` and `with()`
modulators for `valueMap()` step.
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