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 4e2edb64ee6ebec300035d1e02d84dca2fd2ecf5 Author: Daniel Kuppitz <daniel_kupp...@hotmail.com> AuthorDate: Thu Nov 1 15:10:58 2018 -0700 final --- 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 +++++ .../traversal/dsl/graph/GraphTraversal.java | 3 +- .../gremlin/process/traversal/dsl/graph/__.java | 3 +- .../traversal/step/map/PropertyMapStep.java | 4 +- .../traversal/step/map/PropertyMapStepTest.java | 11 +- .../TraversalEvaluationTests.cs | 4 +- gremlin-test/features/map/AddVertex.feature | 4 +- gremlin-test/features/map/ValueMap.feature | 39 +++- .../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 +++++++++++++++------ 21 files changed, 326 insertions(+), 137 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..8b16882 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/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 1333f39..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 @@ -37,6 +37,7 @@ import org.apache.tinkerpop.gremlin.structure.VertexProperty; import org.apache.tinkerpop.gremlin.structure.util.StringFactory; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.Iterator; import java.util.LinkedHashMap; @@ -169,7 +170,8 @@ public class PropertyMapStep<K,E> extends MapStep<Element, Map<K, E>> } public String toString() { - return StringFactory.stepString(this, this.traversalRing, this.returnType.name().toLowerCase()); + return StringFactory.stepString(this, Arrays.asList(this.propertyKeys), + this.traversalRing, this.returnType.name().toLowerCase()); } @Override 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/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-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 2d315a4..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,7 +109,7 @@ 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 """ @@ -105,3 +121,16 @@ Feature: Step - valueMap() | 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"}] | + + 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(); + } + } }