You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tinkerpop.apache.org by co...@apache.org on 2024/12/07 06:05:11 UTC
(tinkerpop) branch master updated (995fbb448e -> d16b706f64)
This is an automated email from the ASF dual-hosted git repository.
colegreer pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/tinkerpop.git
from 995fbb448e Merge pull request #2938 from apache/archive-past-changelogs
new 8ebcc28f3c TINKERPOP-2959 Allow parameters to work for primitives
new 68866d1b2b TINKERPOP-2959 Restrict Arguments in Grammar
new f6273a5beb TINKERPOP-2959 Anonymous traversal tests
new f7711ada7a TINKERPOP-2959 Add additional feature tests for GValue
new d16b706f64 TINKERPOP-2959 GValue fixes, cleanup, and docs
The 5 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
Summary of changes:
docs/src/dev/developer/for-committers.asciidoc | 2 +
docs/src/reference/gremlin-applications.asciidoc | 20 +-
docs/src/reference/gremlin-variants.asciidoc | 40 +
docs/src/reference/the-traversal.asciidoc | 50 +
docs/src/upgrade/release-4.x.x.asciidoc | 35 +-
.../gremlin/jsr223/GremlinLangScriptEngine.java | 17 +-
.../VariableResolverCustomizer.java} | 29 +-
.../gremlin/jsr223/VariableResolverPlugin.java | 95 ++
.../gremlin/language/grammar/ArgumentVisitor.java | 107 +-
.../grammar/DefaultGremlinBaseVisitor.java | 24 +-
.../language/grammar/GenericLiteralVisitor.java | 26 +-
.../language/grammar/TraversalMethodVisitor.java | 415 ++++--
.../grammar/TraversalSourceSelfMethodVisitor.java | 8 +-
.../grammar/TraversalSourceSpawnMethodVisitor.java | 53 +-
.../gremlin/language/grammar/VariableResolver.java | 37 +-
.../translator/DotNetTranslateVisitor.java | 118 +-
.../translator/GroovyTranslateVisitor.java | 31 +-
.../language/translator/TranslateVisitor.java | 16 +-
.../gremlin/process/traversal/GremlinLang.java | 41 +-
.../tinkerpop/gremlin/process/traversal/P.java | 10 +-
.../gremlin/process/traversal/SackFunctions.java | 5 +-
.../traversal/dsl/graph/GraphTraversal.java | 639 +++++++-
.../traversal/dsl/graph/GraphTraversalSource.java | 87 ++
.../gremlin/process/traversal/dsl/graph/__.java | 241 ++-
.../traversal/lambda/ConstantTraversal.java | 15 +-
.../gremlin/process/traversal/step/GType.java | 105 ++
.../gremlin/process/traversal/step/GValue.java | 398 +++++
.../process/traversal/step/branch/RepeatStep.java | 4 +-
.../process/traversal/step/filter/CoinStep.java | 24 +-
.../traversal/step/map/AddEdgeStartStep.java | 6 +
.../process/traversal/step/map/AddEdgeStep.java | 22 +-
.../traversal/step/map/AddVertexStartStep.java | 7 +
.../process/traversal/step/map/AddVertexStep.java | 5 +
.../process/traversal/step/map/CallStep.java | 36 +-
.../process/traversal/step/map/CombineStep.java | 15 +-
.../process/traversal/step/map/ConjoinStep.java | 19 +-
.../process/traversal/step/map/ConstantStep.java | 18 +-
.../process/traversal/step/map/DifferenceStep.java | 20 +-
.../process/traversal/step/map/DisjunctStep.java | 14 +-
.../process/traversal/step/map/GraphStep.java | 88 +-
.../process/traversal/step/map/IntersectStep.java | 15 +-
.../process/traversal/step/map/MergeEdgeStep.java | 5 +
.../traversal/step/map/MergeElementStep.java | 14 +-
.../process/traversal/step/map/MergeStep.java | 25 +-
.../traversal/step/map/MergeVertexStep.java | 5 +
.../process/traversal/step/map/ProductStep.java | 19 +-
.../process/traversal/step/map/VertexStep.java | 27 +-
.../traversal/step/sideEffect/InjectStep.java | 23 +-
.../process/traversal/step/util/AbstractStep.java | 1 -
.../process/traversal/step/util/HasContainer.java | 6 +-
.../process/traversal/step/util/Parameters.java | 19 +-
.../strategy/decoration/ElementIdStrategy.java | 7 +-
.../strategy/decoration/SideEffectStrategy.java | 10 +-
.../strategy/decoration/SubgraphStrategy.java | 2 +-
.../optimization/AdjacentToIncidentStrategy.java | 2 +-
.../optimization/IncidentToAdjacentStrategy.java | 2 +-
.../optimization/InlineFilterStrategy.java | 19 +-
.../process/traversal/util/ListFunction.java | 16 +-
.../gremlin/structure/VertexProperty.java | 3 -
.../gremlin/structure/io/binary/DataType.java | 1 +
.../io/binary/TypeSerializerRegistry.java | 2 +
.../structure/io/binary/types/EnumSerializer.java | 1 +
.../structure/io/graphson/GraphSONModule.java | 2 +
.../gremlin/structure/io/gryo/GryoVersion.java | 12 +-
.../gremlin/structure/util/ElementHelper.java | 10 +-
.../tinkerpop/gremlin/util/CollectionUtil.java | 40 +-
.../gremlin/jsr223/VariableResolverPluginTest.java | 117 ++
.../language/grammar/ArgumentVisitorTest.java | 52 +-
.../language/grammar/GremlinQueryParserTest.java | 8 +-
.../grammar/TraversalMethodVisitorTest.java | 2 +-
.../language/grammar/TraversalRootVisitorTest.java | 1574 +++++++++++++++++++-
.../language/translator/GremlinTranslatorTest.java | 66 +-
.../remote/EmbeddedRemoteConnectionTest.java | 5 +-
.../gremlin/process/traversal/GremlinLangTest.java | 20 +-
.../dsl/graph/GraphTraversalSourceTest.java | 14 +-
.../traversal/dsl/graph/GraphTraversalTest.java | 21 +
.../gremlin/process/traversal/step/GTypeTest.java | 91 ++
.../gremlin/process/traversal/step/GValueTest.java | 596 ++++++++
.../traversal/step/map/ConjoinStepTest.java | 2 +-
.../traversal/step/util/ParametersTest.java | 11 +
.../strategy/decoration/PartitionStrategyTest.java | 3 +-
.../tinkerpop/gremlin/util/CollectionUtilTest.java | 110 ++
.../Gherkin/CommonSteps.cs | 7 -
.../Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs | 61 +-
gremlin-go/driver/cucumber/cucumberSteps_test.go | 15 +-
gremlin-go/driver/cucumber/gremlin.go | 15 +-
gremlin-javascript/build/generate.groovy | 2 +-
.../test/cucumber/feature-steps.js | 4 -
.../gremlin-javascript/test/cucumber/gremlin.js | 97 +-
gremlin-language/src/main/antlr4/Gremlin.g4 | 171 ++-
.../language/grammar/ReferenceGrammarTest.java | 6 +
gremlin-python/docker-compose.yml | 4 +-
.../python/gremlin_python/process/traversal.py | 33 +-
.../gremlin_python/structure/io/graphbinaryV4.py | 8 +-
.../gremlin_python/structure/io/graphsonV4.py | 9 +
.../src/main/python/radish/feature_steps.py | 24 +-
gremlin-python/src/main/python/radish/gremlin.py | 93 +-
.../src/main/python/tests/driver/test_client.py | 4 +-
.../tests/driver/test_driver_remote_connection.py | 4 +-
.../main/python/tests/process/test_gremlin_lang.py | 35 +-
...inaryGroovyRemoteParameterizedFeatureTest.java} | 8 +-
...hBinaryLangRemoteParameterizedFeatureTest.java} | 6 +-
...raphSONLangRemoteParameterizedFeatureTest.java} | 6 +-
.../gremlin/driver/remote/RemoteWorld.java | 21 +
.../gremlin/server/HttpDriverIntegrateTest.java | 5 +-
.../io.cucumber.core.backend.ObjectFactory | 3 +
.../tinkerpop/gremlin/features/StepDefinition.java | 109 +-
.../apache/tinkerpop/gremlin/features/World.java | 9 +
.../gremlin/test/features/filter/Coin.feature | 17 +
.../gremlin/test/features/filter/Has.feature | 50 +
.../gremlin/test/features/filter/HasId.feature | 43 +-
.../gremlin/test/features/filter/HasLabel.feature | 45 +
.../gremlin/test/features/filter/Is.feature | 39 +
.../gremlin/test/features/filter/Where.feature | 3 +-
.../gremlin/test/features/map/AddEdge.feature | 66 +-
.../gremlin/test/features/map/AddVertex.feature | 88 ++
.../gremlin/test/features/map/Call.feature | 1 +
.../gremlin/test/features/map/Combine.feature | 10 +
.../gremlin/test/features/map/Conjoin.feature | 14 +-
.../gremlin/test/features/map/Difference.feature | 10 +
.../gremlin/test/features/map/Disjunct.feature | 10 +
.../gremlin/test/features/map/Edge.feature | 274 +++-
.../gremlin/test/features/map/Intersect.feature | 10 +
.../gremlin/test/features/map/MergeEdge.feature | 98 ++
.../gremlin/test/features/map/MergeVertex.feature | 17 +
.../gremlin/test/features/map/Product.feature | 10 +
.../gremlin/test/features/map/Vertex.feature | 244 +--
.../test/features/sideEffect/Inject.feature | 73 +-
.../process/TraversalConstructionBenchmark.java | 6 +-
.../hadoop/HadoopGraphFeatureIntegrateTest.java | 5 +
.../traversal/step/sideEffect/Neo4jGraphStep.java | 4 +-
.../gremlin/neo4j/Neo4jGraphFeatureTest.java | 2 +-
.../spark/SparkGraphFeatureIntegrateTest.java | 5 +
.../process/traversal/strategy/SparqlStrategy.java | 1 -
.../traversal/step/sideEffect/TinkerGraphStep.java | 14 +-
...va => TinkerGraphParameterizedFeatureTest.java} | 6 +-
.../tinkerpop/gremlin/tinkergraph/TinkerWorld.java | 7 +
.../tinkergraph/structure/TinkerGraphPlayTest.java | 34 +-
.../io.cucumber.core.backend.ObjectFactory | 1 +
139 files changed, 6744 insertions(+), 1144 deletions(-)
copy gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/{process/traversal/util/TraversalObjectFunction.java => jsr223/VariableResolverCustomizer.java} (54%)
create mode 100644 gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/VariableResolverPlugin.java
create mode 100644 gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/GType.java
create mode 100644 gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/GValue.java
create mode 100644 gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/jsr223/VariableResolverPluginTest.java
create mode 100644 gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/GTypeTest.java
create mode 100644 gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/GValueTest.java
copy gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/{GraphBinaryLangRemoteFeatureTest.java => GraphBinaryGroovyRemoteParameterizedFeatureTest.java} (84%)
copy gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/{GraphBinaryLangRemoteFeatureTest.java => GraphBinaryLangRemoteParameterizedFeatureTest.java} (87%)
copy gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/{GraphBinaryGroovyRemoteFeatureTest.java => GraphSONLangRemoteParameterizedFeatureTest.java} (87%)
copy tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/{TinkerGraphFeatureTest.java => TinkerGraphParameterizedFeatureTest.java} (89%)
(tinkerpop) 05/05: TINKERPOP-2959 GValue fixes, cleanup, and docs
Posted by co...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
colegreer pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/tinkerpop.git
commit d16b706f648faa79ce0ebcf308735861e7d0fed4
Author: Cole-Greer <Co...@improving.com>
AuthorDate: Fri Dec 6 18:47:02 2024 -0800
TINKERPOP-2959 GValue fixes, cleanup, and docs
Co-authored-by: Yang Xia <55...@users.noreply.github.com>
---
docs/src/dev/developer/for-committers.asciidoc | 2 +
docs/src/reference/gremlin-applications.asciidoc | 20 ++---
docs/src/reference/gremlin-variants.asciidoc | 40 ++++++++++
docs/src/reference/the-traversal.asciidoc | 50 ++++++++++++
docs/src/upgrade/release-4.x.x.asciidoc | 35 +++++++-
.../gremlin/language/grammar/ArgumentVisitor.java | 2 -
.../grammar/DefaultGremlinBaseVisitor.java | 4 +
.../language/grammar/GenericLiteralVisitor.java | 1 -
.../language/grammar/TraversalMethodVisitor.java | 16 +---
.../language/translator/TranslateVisitor.java | 5 ++
.../gremlin/process/traversal/GremlinLang.java | 2 -
.../tinkerpop/gremlin/process/traversal/P.java | 12 +--
.../traversal/dsl/graph/GraphTraversal.java | 63 +++++----------
.../gremlin/process/traversal/step/GType.java | 30 +++----
.../gremlin/process/traversal/step/GValue.java | 64 ++-------------
.../process/traversal/step/map/GraphStep.java | 7 +-
.../process/traversal/step/util/AbstractStep.java | 1 -
.../process/traversal/step/util/Parameters.java | 4 +-
.../strategy/decoration/SideEffectStrategy.java | 7 +-
.../gremlin/structure/util/ElementHelper.java | 10 ++-
.../tinkerpop/gremlin/util/CollectionUtil.java | 6 +-
.../traversal/dsl/graph/GraphTraversalTest.java | 21 +++++
.../gremlin/process/traversal/step/GTypeTest.java | 22 ++++-
.../gremlin/process/traversal/step/GValueTest.java | 93 ++++++----------------
.../gremlin-javascript/test/cucumber/gremlin.js | 15 ++++
gremlin-language/src/main/antlr4/Gremlin.g4 | 7 +-
gremlin-python/src/main/python/radish/gremlin.py | 31 ++++----
.../src/main/python/tests/driver/test_client.py | 2 +-
...inaryGroovyRemoteParameterizedFeatureTest.java} | 9 +--
.../remote/GraphBinaryLangRemoteFeatureTest.java | 1 -
...hBinaryLangRemoteParameterizedFeatureTest.java} | 7 +-
...raphSONLangRemoteParameterizedFeatureTest.java} | 7 +-
.../gremlin/driver/remote/RemoteWorld.java | 11 +++
.../io.cucumber.core.backend.ObjectFactory | 3 +
.../tinkerpop/gremlin/features/StepDefinition.java | 42 +++++++++-
.../gremlin/test/features/map/MergeEdge.feature | 4 +-
.../gremlin/test/features/map/MergeVertex.feature | 19 +----
.../test/features/sideEffect/Inject.feature | 12 +--
.../hadoop/HadoopGraphFeatureIntegrateTest.java | 5 ++
.../gremlin/neo4j/Neo4jGraphFeatureTest.java | 2 +-
.../spark/SparkGraphFeatureIntegrateTest.java | 5 ++
.../tinkergraph/TinkerGraphFeatureTest.java | 1 -
...va => TinkerGraphParameterizedFeatureTest.java} | 7 +-
.../tinkerpop/gremlin/tinkergraph/TinkerWorld.java | 2 +
.../tinkergraph/structure/TinkerGraphPlayTest.java | 1 -
.../io.cucumber.core.backend.ObjectFactory | 1 +
46 files changed, 398 insertions(+), 313 deletions(-)
diff --git a/docs/src/dev/developer/for-committers.asciidoc b/docs/src/dev/developer/for-committers.asciidoc
index bb4a004458..b978148b28 100644
--- a/docs/src/dev/developer/for-committers.asciidoc
+++ b/docs/src/dev/developer/for-committers.asciidoc
@@ -576,6 +576,8 @@ tries to reference inaccessible properties that are on elements only available b
`GraphComputer`.
* `@GraphComputerVerificationStarGraphExceeded` - The scenario itself is not written to support `GraphComputer` because
the traversal does not mind the star graph limitation.
+* `@GremlinGroovyNotSupported` - The scenario uses `gremlin-lang` syntax which is incompatible with `gremlin-groovy` and
+cannot be resolved with the groovy translator. This is typically for scenarios using ambiguously-types `null` parameters.
* `@InsertionOrderingRequired` - The scenario is reliant on the graph system predictably returning results (vertices, edges, properties) in the same order in which they were inserted into the graph.
* `@MetaProperties` - The scenario makes use of meta-properties.
* `@MultiProperties` - The scenario makes use of multi-properties.
diff --git a/docs/src/reference/gremlin-applications.asciidoc b/docs/src/reference/gremlin-applications.asciidoc
index 037222e3d3..509baf721d 100644
--- a/docs/src/reference/gremlin-applications.asciidoc
+++ b/docs/src/reference/gremlin-applications.asciidoc
@@ -1788,7 +1788,7 @@ without all the associated structure which can slow the response.
[[parameterized-scripts]]
==== Parameterized Scripts
-image:gremlin-parameterized.png[width=150,float=left] If using the standard `GremlinGroovyScriptEngine` in Gremlin
+image:gremlin-parameterized.png[width=150,float=left] If using `GremlinGroovyScriptEngine` in Gremlin
Server, it is imperative to use script parameterization. Period. There are at least two good
reasons for doing so: script caching and protection from "Gremlin injection" (conceptually the same as the notion of
SQL injection).
@@ -1799,7 +1799,7 @@ scripts. This processing is different from the processing performed by Groovy an
concerns of this section. When considering parameterization, users should also consider the graph database they are
using to determine if it has native mechanisms that preclude the need for parameterization.
-With respect to caching, Gremlin Server caches all scripts that are passed to it. The cache is keyed based on the a
+With respect to caching, Gremlin Server caches all scripts that are passed to it. The cache is keyed based on the
hash of the script. Therefore `g.V(1)` and `g.V(2)` will be recognized as two separate scripts in the cache. If that
script is parameterized to `g.V(x)` where `x` is passed as a parameter from the client, there will be no additional
compilation cost for future requests on that script. Compilation of a script should be considered "expensive" and
@@ -1852,21 +1852,14 @@ params.put("nodeId",nodeId);
client.submit(query, params);
----
-Gremlin injection should not be possible with `Bytecode` based traversals - only scripts - because `Bytecode`
-traversals will treat all arguments as literal values. There is potential for concern if lambda based steps are
-utilized as they execute arbitrary code, which is string based, but configuring `TraversalSource` instances with
-`LambdaRestrictionStrategy`, which prevents lambdas all together, using a graph that does not allow lambdas at all, or
-configuring appropriate <<script-execution,sandbox options>> in Gremlin Server (or such options available to the graph
-database in use) should each help mitigate problems related to this issue.
-
-Scripts create classes which get loaded to the JVM metaspace and to a `Class` cache. For those using script
+Groovy scripts create classes which get loaded to the JVM metaspace and to a `Class` cache. For those using script
parameterization, a typical application should not generate an overabundance of pressure on these two components of
Gremlin Server's memory footprint. On the other hand, it's not too hard to imagine a situation where problems might
emerge:
* An application use case makes parameterization impossible and therefore all scripts are unique.
* There is a bug in an applications parameterization code that is actually instead producing unique scripts.
-* A long running Gremln Server takes lots of non-parameterized scripts from Gremlin Console or similar tools.
+* A long running Gremlin Server takes lots of non-parameterized scripts from Gremlin Console or similar tools.
In these sorts of cases, Gremlin Server's performance can be affected adversely as without some additional configuration
the metaspace will grow indefinitely (possibly along with the general heap) triggering longer and more frequent rounds
@@ -1878,7 +1871,7 @@ such that cache hits will be low there is little need to keep such references ar
Perhaps the more important guards are related to the JVM metaspace. Start by setting the initial size of this space
with `-XX:MetaspaceSize`. When this value is exceeded it will trigger a GC round - it is essentially a threshold for
-GC. The grow of this value can be capped with `-XX:MaxMetaspaceSize` (this value is unlimited by default). In an ideal
+GC. The growth of this value can be capped with `-XX:MaxMetaspaceSize` (this value is unlimited by default). In an ideal
situation (i.e. parameterization), the `-XX:MetaspaceSize` should have a large enough setting so as to avoid early GC
rounds for metaspace, but outside of an ideal world (i.e. non-parameterization) it may not be smart to make this number
too large. Making the setting too large (and thus the `-XX:MaxMetaspaceSize` even larger) may trigger longer GC rounds
@@ -1901,9 +1894,6 @@ There really aren't any general guidelines for how to initially set these values
trends is likely the best way to understand how a particular workload is affecting the metaspace and its relation to
GC. Getting these settings "right" however will help ensure much more predictable Gremlin Server operations.
-IMPORTANT: A lambda used in a bytecode-based request will be treated as a script, so issues related to raw script-based
-requests apply equally well to lambda-bytecode requests.
-
==== Properties of Elements
It was mentioned above at the start of this "Best Practices" section that serialization of graph elements (i.e.
diff --git a/docs/src/reference/gremlin-variants.asciidoc b/docs/src/reference/gremlin-variants.asciidoc
index 8f9440a945..803ef85681 100644
--- a/docs/src/reference/gremlin-variants.asciidoc
+++ b/docs/src/reference/gremlin-variants.asciidoc
@@ -869,6 +869,33 @@ ensure compatibility when making requests. Obviously, it is possible to switch t
the appropriate `MessageSerializer` (e.g. `GraphSONMessageSerializerV4` or `GraphBinaryMessageSerializerV4` respectively)
in the same way and building that into the `Cluster` object.
+[[gremlin-java-gvalue]]
+=== GValue Parameterization
+
+A `GValue` is an encapsulation of a parameter name and value. The GValue class has a series of static methods to
+construct GValues of various types from a given parameter name and value. Some of the most common examples are listed
+below, see the
+link:++https://tinkerpop.apache.org/javadocs/x.y.z/full/org/apache/tinkerpop/gremlin/process/traversal/step/GValue.html#method.summary++[Javadocs]
+for a complete listing.
+
+[source,java]
+----
+GValue<String> stringArg = GValue.ofString("name", "value");
+GValue<Integer> intArg = GValue.ofInteger("name", 1);
+GValue<Map> mapArg = GValue.ofMap("name", Collections.emptyMap());
+GValue<?> autoTypedArg = GValue.of("name", "value"); // GValue will attempt to automatically detect correct type
+----
+
+A <<traversal-parameterization,subset of gremlin steps>> are able to accept `GValues`. When constructing a
+`GraphTraversal` with such steps in Java, a GValue may be passed in the traversal to utilize a parameter in place of a
+literal.
+
+[source,java]
+----
+g.V().has("name", GValue.ofString("name", "marko"));
+g.mergeV(GValue.ofMap("vertexPattern", Collections.singletonMap("name", "marko")));
+----
+
[[gremlin-java-lambda]]
=== The Lambda Solution
@@ -2345,6 +2372,19 @@ except Exception as e:
----
+[[gremlin-python-gvalue]]
+=== GValue Parameterization
+
+A `GValue` is an encapsulation of a parameter name and value. A <<traversal-parameterization,subset of gremlin steps>>
+are able to accept GValues. When constructing a `GraphTraversal` with such steps in Python, a GValue may be passed in
+the traversal to utilize a parameter in place of a literal.
+
+[source,python]
+----
+g.V().has('name', GValue('name', 'marko'))
+g.merge_v(GValue('vertexPattern', {'name': 'marko'}))
+----
+
[[gremlin-python-scripts]]
=== Submitting Scripts
diff --git a/docs/src/reference/the-traversal.asciidoc b/docs/src/reference/the-traversal.asciidoc
index 36a7d81667..23800064cf 100644
--- a/docs/src/reference/the-traversal.asciidoc
+++ b/docs/src/reference/the-traversal.asciidoc
@@ -5175,6 +5175,56 @@ location. Please see the <<io-step,documentation>> for `io()`-step for more comp
link:++https://tinkerpop.apache.org/javadocs/x.y.z/full/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.html#write()++[`write()`]
+[[traversal-parameterization]]
+== Traversal Parameterization
+
+A subset of gremlin steps are able to accept parameterized arguments also known as GValues. GValues can be used to
+provide protection against gremlin-injection attacks in cases where untrusted and unsanitized inputs must be passed as
+step arguments. Additionally, use of GValues may offer performance benefits in certain environments by making use of
+some query caching capabilities. Note that the reference implementation of the gremlin language and `gremlin-server` do
+not have such a query caching mechanism, and thus will not see any performance improvements through parameterization. Users
+should consult the documentation of their specific graph system details of potential performance benefits via parameterization.
+
+NOTE: There are unique considerations regarding parameters when using `gremlin-groovy` scripts. Groovy allows for parameterization
+at arbitrary points in the query in addition to the subset of parameterizable steps documented here. Groovy is also bound by
+a comparatively slow script compilation, which makes parameterization essential for performant execution of `gremlin-groovy` scripts.
+
+[cols="1,1"]
+|===
+|Step | Parameterizable arguments
+
+|<<addedge-step,addE()>> | String edgeLabel
+|<<addvertex-step,addV()>> | String vertexLabel
+|<<vertex-steps,both()>> | String...edgeLabels
+|<<vertex-steps,bothE()>> | String...edgeLabels
+|<<call-step,call()>> | Map params
+|<<coin-step,coin()>> | double probability
+|<<combine-step,combine()>> | Object values
+|<<conjoin-step,conjoin()>> | String delimiter
+|<<constant-step,constant()>> | E e/value
+|<<difference-step,difference()>> | Object values
+|<<disjunct-step,disjunct()>> | Object values
+|<<from-step,from()>> | Vertex fromVertex
+|<<has-step,has()>> | String label
+|<<has-step,hasLabel()>> | String label, String... labels
+|<<vertex-steps,in()>> | String...edgeLabels
+|<<vertex-steps,inE()>> | String...edgeLabels
+|<<intersect-step,intersect()>> | Object values
+|<<merge-step,merge()>> | Object values
+|<<mergeedge-step,mergeE()>> | Map searchCreate
+|<<mergevertex-step,mergeV()>> | Map searchCreate
+|<<option-step,option()>> | M token, Map m
+|<<vertex-steps,out()>> | String...edgeLabels
+|<<vertex-steps,outE()>> | String...edgeLabels
+|<<product-step,product()>> | Object values
+|<<to-step,to()>> | String... edgeLabels, Vertex toVertex
+|<<vertex-steps,toE()>> | String...edgeLabels
+|===
+
+*Additional References*
+
+<<gremlin-java-gvalue,Java>>, <<gremlin-python-gvalue,Python>>, <<parameterized-scripts,Server>>
+
[[a-note-on-predicates]]
== A Note on Predicates
diff --git a/docs/src/upgrade/release-4.x.x.asciidoc b/docs/src/upgrade/release-4.x.x.asciidoc
index ba57204d12..3a86e003ea 100644
--- a/docs/src/upgrade/release-4.x.x.asciidoc
+++ b/docs/src/upgrade/release-4.x.x.asciidoc
@@ -356,6 +356,25 @@ available if the driver has been idle for a while.
The Java driver can currently handle a response that is a maximum of 2^31-1 (`Integer.MAX_VALUE`) bytes in size.
Queries that return more data will have to be separated into multiple queries that return less data.
+==== Introduction of GValue and Update to Parameterization in Gremlin-Lang
+
+A new construct to parameterize traversals called `GValue` has been added to gremlin. A `GValue` wraps a parameter name
+and value, and can be provided as input to parameterizable steps when building a `GraphTraversal`. The following
+examples will produce a gremlin script of `g.V().hasLabel(label)` with a parameter map of `["label": "person"]`:
+
+[source,java]
+----
+g.V().hasLabel(GValue.of("label", "person"));
+----
+
+[source,python]
+----
+g.V().has_label(GValue('label', 'person'))
+----
+
+Use of `GValue` in traversals with repeated patterns may lead to improved performance in certain graphs. Consult the
+documentation for your specific graph provider for recommendations on how to best utilize `GValue` in traversals.
+
=== Upgrading for Providers
==== Renaming NoneStep to DiscardStep
@@ -366,7 +385,7 @@ no elements matching the predicate.
==== Changes to Serialization
The V4 versions of GraphBinary and GraphSON are being introduced. Support for the older versions of GraphBinary (V1)
-and GraphSON (V1-3) is removed. Upon the full release of 4.0, the GLVs will only use GraphBinary, however, the Gremlin
+and GraphSON (V1-3) is removed. Upon the full release of 4.0, the GLVs will only use GraphBinary, however, the Gremlin
Server will support both GraphSON and GraphBinary. The following is a list of the major changes to the GraphBinary
format:
@@ -449,6 +468,20 @@ some of the fields no longer exist. See link:https://tinkerpop.apache.org/docs/4
for an updated list. One of the most important changes is to the `Channelizer` configuration as only the
`HttpChannelizer` remains and the rest have been removed.
+===== Introduction of GValue and Update to Parameterization in Gremlin-Lang
+
+Parameterization was first added to gremlin-lang in TinkerPop 3.7.0, however was limited in that variables were
+immediately resolved to literals during the compilation of a gremlin script. This direct resolution of variables limited
+providers ability to detect and optimize recurring query patterns.
+
+With this update, a new class `GValue` is introduced which wraps a parameter name and value. Steps which will benefit
+from parameterization have been given overloads to accept GValues. Users can pass GValue's into their traversals to
+inject parameters.
+
+A new `DefaultVariableResolver` has also been introduced with this change. The grammar will now resolve variables into
+`GValue` which are passed to the constructed traversal, instead of directly resolving them to literals. The old variable
+resolution behavior can still be obtained via the `DirectVariableResolver` if desired.
+
==== Graph Driver Providers
===== Application Layer Protocol Support
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/ArgumentVisitor.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/ArgumentVisitor.java
index 9c0a1eca4e..e9eec826f4 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/ArgumentVisitor.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/ArgumentVisitor.java
@@ -20,11 +20,9 @@ package org.apache.tinkerpop.gremlin.language.grammar;
import org.apache.tinkerpop.gremlin.process.traversal.step.GType;
import org.apache.tinkerpop.gremlin.process.traversal.step.GValue;
-import org.apache.tinkerpop.gremlin.structure.Vertex;
import org.apache.tinkerpop.gremlin.util.iterator.IteratorUtils;
import java.lang.reflect.Array;
-import java.time.OffsetDateTime;
import java.util.Map;
import java.util.Objects;
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/DefaultGremlinBaseVisitor.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/DefaultGremlinBaseVisitor.java
index 4f7dec68ff..2d20e5d846 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/DefaultGremlinBaseVisitor.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/DefaultGremlinBaseVisitor.java
@@ -1311,6 +1311,10 @@ public class DefaultGremlinBaseVisitor<T> extends AbstractParseTreeVisitor<T> im
* {@inheritDoc}
*/
@Override public T visitGenericLiteralMap(final GremlinParser.GenericLiteralMapContext ctx) { notImplemented(ctx); return null; }
+ /**
+ * {@inheritDoc}
+ */
+ @Override public T visitNullableGenericLiteralMap(final GremlinParser.NullableGenericLiteralMapContext ctx) { notImplemented(ctx); return null; }
/**
* {@inheritDoc}
*/
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/GenericLiteralVisitor.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/GenericLiteralVisitor.java
index 0f86540636..1015d51cec 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/GenericLiteralVisitor.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/GenericLiteralVisitor.java
@@ -25,7 +25,6 @@ import org.apache.tinkerpop.gremlin.process.traversal.Merge;
import org.apache.tinkerpop.gremlin.process.traversal.Pick;
import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategy;
-import org.apache.tinkerpop.gremlin.process.traversal.step.GValue;
import org.apache.tinkerpop.gremlin.structure.T;
import org.apache.tinkerpop.gremlin.structure.VertexProperty;
import org.apache.tinkerpop.gremlin.util.DatetimeHelper;
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalMethodVisitor.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalMethodVisitor.java
index a31b01b0c4..066b550b67 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalMethodVisitor.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalMethodVisitor.java
@@ -1246,20 +1246,12 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
*/
@Override
public Traversal visitTraversalMethod_option_Merge_Map_Cardinality(final GremlinParser.TraversalMethod_option_Merge_Map_CardinalityContext ctx) {
- if (ctx.genericLiteralMapNullableArgument().nullLiteral() != null) {
+ if (ctx.nullableGenericLiteralMap().nullLiteral() != null) {
return this.graphTraversal.option(TraversalEnumParser.parseTraversalEnumFromContext(Merge.class, ctx.traversalMerge()), (Map) null);
}
-
- final Object literalOrVar = antlr.argumentVisitor.visitGenericLiteralMapNullableArgument(ctx.genericLiteralMapNullableArgument());
- if (GValue.valueInstanceOf(literalOrVar, GType.MAP)) {
- return graphTraversal.option(TraversalEnumParser.parseTraversalEnumFromContext(Merge.class, ctx.traversalMerge()),
- (GValue<Map<Object, Object>>) literalOrVar,
- TraversalEnumParser.parseTraversalEnumFromContext(Cardinality.class, ctx.traversalCardinality()));
- } else {
- return graphTraversal.option(TraversalEnumParser.parseTraversalEnumFromContext(Merge.class, ctx.traversalMerge()),
- (Map<Object, Object>) literalOrVar,
- TraversalEnumParser.parseTraversalEnumFromContext(Cardinality.class, ctx.traversalCardinality()));
- }
+ return graphTraversal.option(TraversalEnumParser.parseTraversalEnumFromContext(Merge.class, ctx.traversalMerge()),
+ antlr.genericVisitor.parseMap(ctx.nullableGenericLiteralMap().genericLiteralMap()),
+ TraversalEnumParser.parseTraversalEnumFromContext(Cardinality.class, ctx.traversalCardinality()));
}
/**
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/translator/TranslateVisitor.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/translator/TranslateVisitor.java
index 7d70c7bbb7..14897a2339 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/translator/TranslateVisitor.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/translator/TranslateVisitor.java
@@ -2089,6 +2089,11 @@ public class TranslateVisitor extends AbstractParseTreeVisitor<Void> implements
return visitChildren(ctx);
}
+ @Override
+ public Void visitNullableGenericLiteralMap(final GremlinParser.NullableGenericLiteralMapContext ctx) {
+ return visitChildren(ctx);
+ }
+
@Override
public Void visitStructureVertexArgument(final GremlinParser.StructureVertexArgumentContext ctx) {
return visitChildren(ctx);
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/GremlinLang.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/GremlinLang.java
index 13f2c67c9f..608d709abf 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/GremlinLang.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/GremlinLang.java
@@ -28,7 +28,6 @@ import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.Option
import org.apache.tinkerpop.gremlin.process.traversal.util.ConnectiveP;
import org.apache.tinkerpop.gremlin.process.traversal.util.DefaultTraversal;
import org.apache.tinkerpop.gremlin.structure.Column;
-import org.apache.tinkerpop.gremlin.structure.Direction;
import org.apache.tinkerpop.gremlin.structure.T;
import org.apache.tinkerpop.gremlin.structure.Vertex;
import org.apache.tinkerpop.gremlin.util.NumberHelper;
@@ -39,7 +38,6 @@ import java.math.BigDecimal;
import java.math.BigInteger;
import java.time.OffsetDateTime;
import java.util.ArrayList;
-import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/P.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/P.java
index a878bbb839..ecb2622140 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/P.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/P.java
@@ -77,15 +77,11 @@ public class P<V> implements Predicate<V>, Serializable, Cloneable {
@Override
public boolean test(final V testValue) {
- if (this.value instanceof GValue) {
- return this.biPredicate.test(testValue, ((GValue<V>) this.value).get());
+ // this might be a bunch of GValue that need to be resolved. zomg
+ if (this.value instanceof List) {
+ return this.biPredicate.test(testValue, (V) ((List) this.value).stream().map(GValue::valueOf).collect(Collectors.toList()));
} else {
- // this might be a bunch of GValue that need to be resolved. zomg
- if (this.value instanceof List) {
- return this.biPredicate.test(testValue, (V) ((List) this.value).stream().map(GValue::valueOf).collect(Collectors.toList()));
- } else {
- return this.biPredicate.test(testValue, this.value);
- }
+ return this.biPredicate.test(testValue, (V) GValue.valueOf(this.value));
}
}
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 77c4b838e6..a876193578 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
@@ -25,7 +25,6 @@ import org.apache.tinkerpop.gremlin.process.computer.traversal.step.map.PageRank
import org.apache.tinkerpop.gremlin.process.computer.traversal.step.map.PeerPressureVertexProgramStep;
import org.apache.tinkerpop.gremlin.process.computer.traversal.step.map.ProgramVertexProgramStep;
import org.apache.tinkerpop.gremlin.process.computer.traversal.step.map.ShortestPathVertexProgramStep;
-import org.apache.tinkerpop.gremlin.process.traversal.Contains;
import org.apache.tinkerpop.gremlin.process.traversal.DT;
import org.apache.tinkerpop.gremlin.process.traversal.Failure;
import org.apache.tinkerpop.gremlin.process.traversal.Merge;
@@ -434,7 +433,7 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
/**
* Map the {@link Vertex} to its adjacent vertices given a direction and edge labels. The arguments for the
- * labels must be either a {@code String} or a {@link GValue<String>}. For internal use for parameterization.
+ * labels must be either a {@code String} or a {@link GValue<String>}. For internal use for parameterization.
*
* @param direction the direction to traverse from the current vertex
* @param edgeLabels the edge labels to traverse
@@ -2865,15 +2864,21 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
} else {
this.asAdmin().getGremlinLang().addStep(Symbols.hasId, id, otherIds);
- // the logic for dealing with hasId([]) is sketchy historically, just trying to maintain what we were
- // originally testing prior to GValue.
- if (id instanceof GValue && ((GValue) id).getType().isCollection()) {
- return TraversalHelper.addHasContainer(this.asAdmin(), new HasContainer(T.id.getAccessor(), new P(Contains.within, id)));
- }
-
//using ArrayList given P.within() turns all arguments into lists
final List<Object> ids = new ArrayList<>();
- if (id instanceof Object[]) {
+
+ if (id instanceof GValue) {
+ // the logic for dealing with hasId([]) is sketchy historically, just trying to maintain what we were
+ // originally testing prior to GValue.
+ Object value = ((GValue) id).get();
+ if (value instanceof Object[]) {
+ ids.addAll(Arrays.asList(GValue.ensureGValues((Object[]) value)));
+ } else if (value instanceof Collection) {
+ ids.addAll(Arrays.asList(GValue.ensureGValues(((Collection<?>) value).toArray())));
+ } else {
+ ids.add(id);
+ }
+ } else if (id instanceof Object[]) {
Collections.addAll(ids, (Object[]) id);
} else if (id instanceof Collection) {
// as ids are unrolled when it's in array, they should also be unrolled when it's a list.
@@ -2891,22 +2896,10 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
// For example, GValue.of([1, 2]) is processed to [GValue.of(1), GValue.of(2)]
if(i instanceof GValue) {
Object value = ((GValue) i).get();
- if (i instanceof Object[]) {
- for (Object o : (Object[]) value) {
- if(o instanceof GValue) {
- ids.add(o);
- } else {
- ids.add(GValue.of(null, o));
- }
- }
+ if (value instanceof Object[]) {
+ ids.addAll(Arrays.asList(GValue.ensureGValues((Object[]) value)));
} else if(value instanceof Collection) {
- for (Object o : (Collection<?>) value) {
- if(o instanceof GValue) {
- ids.add(o);
- } else {
- ids.add(GValue.of(null, o));
- }
- }
+ ids.addAll(Arrays.asList(GValue.ensureGValues(((Collection<?>) value).toArray())));
} else {
ids.add(i);
}
@@ -4511,7 +4504,7 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
* @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#choose-step" target="_blank">Reference Documentation - Choose Step</a>
* @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#mergev-step" target="_blank">Reference Documentation - MergeV Step</a>
* @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#mergee-step" target="_blank">Reference Documentation - MergeE Step</a>
- * @since 3.0.0-incubating
+ * @since 4.0.0
*/
public default <M, E2> GraphTraversal<S, E> option(final GValue<M> token, final Traversal<?, E2> traversalOption) {
this.asAdmin().getGremlinLang().addStep(GraphTraversal.Symbols.option, token, traversalOption);
@@ -4532,7 +4525,7 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
* @return the traversal with the modulated step
* @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#mergev-step" target="_blank">Reference Documentation - MergeV Step</a>
* @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#mergee-step" target="_blank">Reference Documentation - MergeE Step</a>
- * @since 3.7.3
+ * @since 4.0.0
*/
public default <M, E2> GraphTraversal<S, E> option(final M token, final GValue<Map<Object, Object>> m) {
this.asAdmin().getGremlinLang().addStep(GraphTraversal.Symbols.option, token, m);
@@ -4540,24 +4533,6 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
return this;
}
- /**
- * This is a step modulator to a {@link TraversalOptionParent} like {@code choose()} or {@code mergeV()} where the
- * provided argument associated to the {@code token} is applied according to the semantics of the step. Please see
- * the documentation of such steps to understand the usage context.
- *
- * @param m Provides a {@code Map} as the option which is the same as doing {@code constant(m)}.
- * @return the traversal with the modulated step
- * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#mergev-step" target="_blank">Reference Documentation - MergeV Step</a>
- * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#mergee-step" target="_blank">Reference Documentation - MergeE Step</a>
- * @since 3.7.3
- */
- public default <M, E2> GraphTraversal<S, E> option(final Merge merge, final GValue<Map<Object, Object>> m, final VertexProperty.Cardinality cardinality) {
- this.asAdmin().getGremlinLang().addStep(GraphTraversal.Symbols.option, merge, m, cardinality);
-
- ((TraversalOptionParent<M, E, E2>) this.asAdmin().getEndStep()).addChildOption((M) merge, (Traversal.Admin<E, E2>) new ConstantTraversal<>(m).asAdmin());
- return this;
- }
-
////
///////////////////// IO STEPS /////////////////////
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/GType.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/GType.java
index 4c8777d290..817b2670d8 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/GType.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/GType.java
@@ -25,9 +25,11 @@ import org.apache.tinkerpop.gremlin.structure.Vertex;
import java.math.BigDecimal;
import java.math.BigInteger;
+import java.time.OffsetDateTime;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.UUID;
/**
* An enum that describes types that are used in the Gremlin language.
@@ -36,17 +38,20 @@ public enum GType {
BIG_DECIMAL(BigDecimal.class),
BIG_INTEGER(BigInteger.class),
BOOLEAN(Boolean.class),
+ BYTE(Byte.class),
+ CHARACTER(Character.class),
+ DATETIME(OffsetDateTime.class),
DOUBLE(Double.class),
- EDGE(Edge.class),
+ FLOAT(Float.class),
INTEGER(Integer.class),
LIST(List.class),
LONG(Long.class),
MAP(Map.class),
- PATH(Path.class),
- PROPERTY(Property.class),
SET(Set.class),
+ SHORT(Short.class),
STRING(String.class),
UNKNOWN(null),
+ UUID(UUID.class),
VERTEX(Vertex.class);
private Class<?> javaType;
@@ -63,7 +68,8 @@ public enum GType {
* Returns {@code true} if the type is a number.
*/
public boolean isNumeric() {
- return this == INTEGER || this == DOUBLE || this == LONG || this == BIG_INTEGER || this == BIG_DECIMAL;
+ return this == BYTE || this == SHORT || this == INTEGER || this == LONG ||
+ this == FLOAT || this == DOUBLE || this == BIG_INTEGER || this == BIG_DECIMAL;
}
/**
@@ -73,31 +79,27 @@ public enum GType {
return this == LIST || this == SET;
}
- /**
- * Returns {@code true} if the type is an element.
- */
- public boolean isElement() {
- return this == VERTEX || this == EDGE;
- }
-
/**
* Convert an object to a matching {@link GType} and if not matched return {@link GType#UNKNOWN}.
*/
public static GType getType(final Object object) {
if (object instanceof String) return STRING;
+ else if (object instanceof Byte) return BYTE;
+ else if (object instanceof Short) return SHORT;
+ else if (object instanceof Character) return CHARACTER;
else if (object instanceof Integer) return INTEGER;
else if (object instanceof Boolean) return BOOLEAN;
+ else if (object instanceof Float) return FLOAT;
else if (object instanceof Double) return DOUBLE;
else if (object instanceof Long) return LONG;
else if (object instanceof Map) return MAP;
else if (object instanceof List) return LIST;
else if (object instanceof Set) return SET;
else if (object instanceof Vertex) return VERTEX;
- else if (object instanceof Edge) return EDGE;
- else if (object instanceof Path) return PATH;
- else if (object instanceof Property) return PROPERTY;
else if (object instanceof BigInteger) return BIG_INTEGER;
else if (object instanceof BigDecimal) return BIG_DECIMAL;
+ else if (object instanceof OffsetDateTime) return DATETIME;
+ else if (object instanceof UUID) return UUID;
else return UNKNOWN;
}
}
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/GValue.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/GValue.java
index b9f88684e3..ab368d0814 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/GValue.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/GValue.java
@@ -41,7 +41,7 @@ import java.util.stream.Stream;
* the name is not given, the value was provided literally in the traversal. The value of the variable can be any
* object. The {@code GValue} also includes the {@link GType} that describes the type it contains.
*/
-public class GValue<V> implements Cloneable, Serializable {
+public class GValue<V> implements Serializable {
private final String name;
private final GType type;
@@ -69,7 +69,7 @@ public class GValue<V> implements Cloneable, Serializable {
}
/**
- * Gets the name of the variable if it was defined as such and returns empty if the value was a literal.
+ * Gets the name of the variable if it was defined as such and returns null if the value was a literal.
*/
public String getName() {
return this.name;
@@ -101,7 +101,7 @@ public class GValue<V> implements Cloneable, Serializable {
@Override
public String toString() {
return isVariable() ?
- String.format("%s&%s", name, value) : Objects.toString(value);
+ String.format("%s=%s", name, value) : Objects.toString(value);
}
@Override
@@ -129,11 +129,12 @@ public class GValue<V> implements Cloneable, Serializable {
}
/**
- * Create a new {@code Var} with the specified name and value.. If the argument provide is already a
- * {@code GValue} then it is returned as-is.
+ * Create a new {@code Var} with the specified name and value. If the argument provide is already a
+ * {@code GValue} then an IllegalArgumentException is thrown.
*
* @param name the name of the variable
* @param value the value of the variable
+ * @throws IllegalArgumentException if value is already a {@code GValue}
*/
public static <V> GValue<V> of(final String name, final V value) {
if (value instanceof GValue) throw new IllegalArgumentException("value cannot be a GValue");
@@ -294,48 +295,6 @@ public class GValue<V> implements Cloneable, Serializable {
return new GValue<>(name, GType.VERTEX, value);
}
- /**
- * Create a new {@code GValue} for an edge value.
- */
- static GValue<Edge> ofEdge(final Edge value) {
- return new GValue<>(GType.EDGE, value);
- }
-
- /**
- * Create a new {@code GValue} for an edge value with a specified name.
- */
- public static GValue<Edge> ofEdge(final String name, final Edge value) {
- return new GValue<>(name, GType.EDGE, value);
- }
-
- /**
- * Create a new {@code GValue} for a path value.
- */
- static GValue<Path> ofPath(final Path value) {
- return new GValue<>(GType.PATH, value);
- }
-
- /**
- * Create a new {@code GValue} for a path value with a specified name.
- */
- public static GValue<Path> ofPath(final String name, final Path value) {
- return new GValue<>(name, GType.PATH, value);
- }
-
- /**
- * Create a new {@code GValue} for a property value.
- */
- static GValue<Property> ofProperty(final Property value) {
- return new GValue<>(GType.PROPERTY, value);
- }
-
- /**
- * Create a new {@code GValue} for a property value with a specified name.
- */
- public static GValue<Property> ofProperty(final String name, final Property value) {
- return new GValue<>(name, GType.PROPERTY, value);
- }
-
/**
* If the object is a {@code GValue} then get its value, otherwise return the object as-is.
*/
@@ -383,21 +342,14 @@ public class GValue<V> implements Cloneable, Serializable {
* Returns {@code true} if the object is a collection or a {@link GValue} that contains a {@link Collection}.
*/
public static boolean instanceOfCollection(final Object o) {
- return o instanceof Collection || (o instanceof GValue && ((GValue) o).getType().isCollection());
- }
-
- /**
- * Returns {@code true} if the object is an element or a {@link GValue} that contains an {@link Element}.
- */
- public static boolean instanceOfElement(final Object o) {
- return o instanceof Element || (o instanceof GValue && ((GValue) o).getType().isElement());
+ return o instanceof Collection || valueInstanceOfCollection(o);
}
/**
* Returns {@code true} if the object is a number or a {@link GValue} that contains a number.
*/
public static boolean instanceOfNumber(final Object o) {
- return o instanceof Number || (o instanceof GValue && ((GValue) o).getType().isNumeric());
+ return o instanceof Number || valueInstanceOfNumeric(o);
}
/**
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/GraphStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/GraphStep.java
index c009588864..41bce05417 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/GraphStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/GraphStep.java
@@ -74,9 +74,10 @@ public class GraphStep<S, E extends Element> extends AbstractStep<S, E> implemen
this.isStart = isStart;
+ Object[] idValues = GValue.resolveToValues(this.ids);
this.iteratorSupplier = () -> (Iterator<E>) (Vertex.class.isAssignableFrom(this.returnClass) ?
- this.getTraversal().getGraph().get().vertices(GValue.resolveToValues(this.ids)) :
- this.getTraversal().getGraph().get().edges(GValue.resolveToValues(this.ids)));
+ this.getTraversal().getGraph().get().vertices(idValues) :
+ this.getTraversal().getGraph().get().edges(idValues));
}
/**
@@ -188,7 +189,7 @@ public class GraphStep<S, E extends Element> extends AbstractStep<S, E> implemen
// if this is going to OLAP, convert to ids so you don't serialize elements
for (int i = 0; i < this.ids.length; i++) {
final GValue<?> current = this.ids[i];
- if (current.getType().isElement()) {
+ if (current.get() instanceof Element) {
this.ids[i] = GValue.of(current.getName(), ((Element) current.get()).id());
}
}
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/AbstractStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/AbstractStep.java
index f0af790c73..72f03b5a95 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/AbstractStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/AbstractStep.java
@@ -27,7 +27,6 @@ import org.apache.tinkerpop.gremlin.process.traversal.util.EmptyTraversal;
import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalInterruptedException;
import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
-import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashSet;
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/Parameters.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/Parameters.java
index 9b4a926c74..6c775a53f4 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/Parameters.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/Parameters.java
@@ -189,10 +189,8 @@ public class Parameters implements Cloneable, Serializable {
private static <S> Object resolve(final Object object, final Traverser.Admin<S> traverser) {
if (object instanceof Traversal.Admin) {
return TraversalUtil.apply(traverser, (Traversal.Admin<S, ?>) object);
- } else if (object instanceof GValue) {
- return ((GValue) object).get();
} else {
- return object;
+ return GValue.valueOf(object);
}
}
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/SideEffectStrategy.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/SideEffectStrategy.java
index 9b309dba3f..42aaf1a058 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/SideEffectStrategy.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/SideEffectStrategy.java
@@ -28,6 +28,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.strategy.AbstractTraversal
import org.apache.tinkerpop.gremlin.util.function.ConstantSupplier;
import org.javatuples.Triplet;
+import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.function.BinaryOperator;
@@ -64,8 +65,10 @@ public final class SideEffectStrategy extends AbstractTraversalStrategy<Traversa
// don't want the GValue to leak beyond strategy application or else the Supplier will start producing it
// during execution
- final ConstantSupplier initialValue = value instanceof GValue ? new ConstantSupplier<>(((GValue) value).get()) : new ConstantSupplier<>(value);
- strategy.sideEffects.add(new Triplet<>(key, value instanceof Supplier ? (Supplier) value : initialValue, reducer));
+ strategy.sideEffects.add(new Triplet<>(key, (Supplier & Serializable) (() -> {
+ Object initialValue = value instanceof Supplier ? ((Supplier) value).get() : value;
+ return GValue.valueOf(initialValue);
+ }), reducer));
}
public boolean contains(final String sideEffectKey) {
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/util/ElementHelper.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/util/ElementHelper.java
index a5e3765094..40dc7014c3 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/util/ElementHelper.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/util/ElementHelper.java
@@ -18,6 +18,7 @@
*/
package org.apache.tinkerpop.gremlin.structure.util;
+import org.apache.tinkerpop.gremlin.process.traversal.step.GValue;
import org.apache.tinkerpop.gremlin.structure.Edge;
import org.apache.tinkerpop.gremlin.structure.Element;
import org.apache.tinkerpop.gremlin.structure.Graph;
@@ -549,12 +550,15 @@ public final class ElementHelper {
public static boolean idExists(final Object id, final Object... providedIds) {
if (0 == providedIds.length) return true;
+ //unbox any GValues which may be present in providedIds
+ Object[] idValues = GValue.resolveToValues(GValue.ensureGValues(providedIds));
+
// it is OK to evaluate equality of ids via toString() now given that the toString() the test suite
// enforces the value of id.()toString() to be a first class representation of the identifier
- if (1 == providedIds.length) {
- return id != null && providedIds[0] != null && id.toString().equals(providedIds[0].toString());
+ if (1 == idValues.length) {
+ return id != null && idValues[0] != null && id.toString().equals(idValues[0].toString());
} else {
- for (final Object temp : providedIds) {
+ for (final Object temp : idValues) {
if (id != null && temp != null && temp.toString().equals(id.toString()))
return true;
}
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/CollectionUtil.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/CollectionUtil.java
index 27d41d8e18..1efc1367b3 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/CollectionUtil.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/CollectionUtil.java
@@ -102,11 +102,7 @@ public final class CollectionUtil {
* element as a new array with just that item in it.
*/
public static <T> T[] addFirst(final T[] array, final T element, final Class<T> clazz) {
- if (null == array && null == element) {
- final T[] singleElementArray = (T[]) Array.newInstance(clazz, 1);
- singleElementArray[0] = null;
- return singleElementArray;
- } else if (null == array) {
+ if (null == array) {
final T[] singleElementArray = (T[]) Array.newInstance(clazz, 1);
singleElementArray[0] = element;
return singleElementArray;
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversalTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversalTest.java
index 7a7ab36f65..a01d677370 100644
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversalTest.java
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversalTest.java
@@ -20,6 +20,7 @@ package org.apache.tinkerpop.gremlin.process.traversal.dsl.graph;
import org.apache.tinkerpop.gremlin.process.traversal.Merge;
import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
+import org.apache.tinkerpop.gremlin.process.traversal.step.GValue;
import org.apache.tinkerpop.gremlin.structure.T;
import org.apache.tinkerpop.gremlin.structure.VertexProperty;
import org.apache.tinkerpop.gremlin.structure.util.empty.EmptyGraph;
@@ -36,6 +37,7 @@ import java.util.Map;
import java.util.Set;
import static org.apache.tinkerpop.gremlin.process.traversal.AnonymousTraversalSource.traversal;
+import static org.junit.Assert.assertEquals;
/**
* @author Marko A. Rodriguez (http://markorodriguez.com)
@@ -131,4 +133,23 @@ public class GraphTraversalTest {
}
}
}
+
+ @Test
+ public void hasIdShouldUnrollListOfIds() {
+ assertEquals(g.V().hasId(1,2,3,4,5,6,7,8),
+ g.V().hasId(new Integer[]{1, 2, 3}, new Integer[]{4, 5}, Arrays.asList(6, 7), 8));
+ }
+
+ @Test
+ public void hasIdShouldUnrollGValueListOfIds() {
+ assertEquals(
+ g.V().hasId(
+ GValue.ofInteger(null, 1), GValue.ofInteger(null, 2), GValue.ofInteger(null, 3),
+ GValue.ofInteger(null, 4), GValue.ofInteger(null, 5), GValue.ofInteger(null, 6),
+ GValue.ofInteger(null, 7), GValue.ofInteger("d", 8)
+ ),
+ g.V().hasId(
+ GValue.of("a", new Integer[]{1, 2, 3}), GValue.of("b", new Integer[]{4, 5}),
+ GValue.of("c", Arrays.asList(6, 7)), GValue.ofInteger("d", 8)));
+ }
}
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/GTypeTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/GTypeTest.java
index 9596445860..539cbfc824 100644
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/GTypeTest.java
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/GTypeTest.java
@@ -26,7 +26,9 @@ import org.junit.Test;
import java.math.BigDecimal;
import java.math.BigInteger;
+import java.time.OffsetDateTime;
import java.util.Collections;
+import java.util.UUID;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
@@ -37,7 +39,10 @@ public class GTypeTest {
@Test
public void shouldReturnTrueForNumericTypes() {
+ assertThat(GType.BYTE.isNumeric(), is(true));
+ assertThat(GType.SHORT.isNumeric(), is(true));
assertThat(GType.INTEGER.isNumeric(), is(true));
+ assertThat(GType.FLOAT.isNumeric(), is(true));
assertThat(GType.DOUBLE.isNumeric(), is(true));
assertThat(GType.LONG.isNumeric(), is(true));
assertThat(GType.BIG_INTEGER.isNumeric(), is(true));
@@ -48,8 +53,14 @@ public class GTypeTest {
public void shouldReturnFalseForNonNumericTypes() {
assertThat(GType.STRING.isNumeric(), is(false));
assertThat(GType.BOOLEAN.isNumeric(), is(false));
- assertThat(GType.EDGE.isNumeric(), is(false));
assertThat(GType.VERTEX.isNumeric(), is(false));
+ assertThat(GType.CHARACTER.isNumeric(), is(false));
+ assertThat(GType.DATETIME.isNumeric(), is(false));
+ assertThat(GType.LIST.isNumeric(), is(false));
+ assertThat(GType.MAP.isNumeric(), is(false));
+ assertThat(GType.SET.isNumeric(), is(false));
+ assertThat(GType.UUID.isNumeric(), is(false));
+ assertThat(GType.UNKNOWN.isNumeric(), is(false));
}
@Test
@@ -63,11 +74,14 @@ public class GTypeTest {
assertEquals(GType.LIST, GType.getType(Collections.emptyList()));
assertEquals(GType.SET, GType.getType(Collections.emptySet()));
assertEquals(GType.VERTEX, GType.getType(mock(Vertex.class)));
- assertEquals(GType.EDGE, GType.getType(mock(Edge.class)));
- assertEquals(GType.PATH, GType.getType(mock(Path.class)));
- assertEquals(GType.PROPERTY, GType.getType(mock(Property.class)));
assertEquals(GType.BIG_INTEGER, GType.getType(BigInteger.ONE));
assertEquals(GType.BIG_DECIMAL, GType.getType(BigDecimal.ONE));
+ assertEquals(GType.BYTE, GType.getType((byte) 123));
+ assertEquals(GType.CHARACTER, GType.getType('A'));
+ assertEquals(GType.DATETIME, GType.getType(OffsetDateTime.now()));
+ assertEquals(GType.FLOAT, GType.getType(123.45f));
+ assertEquals(GType.SHORT, GType.getType((short) 123));
+ assertEquals(GType.UUID, GType.getType(UUID.randomUUID()));
}
@Test
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/GValueTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/GValueTest.java
index 0335d4a89c..c5d9a6ac56 100644
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/GValueTest.java
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/GValueTest.java
@@ -274,63 +274,6 @@ public class GValueTest {
assertThat(gValue.isVariable(), is(true));
}
- @Test
- public void shouldCreateGValueFromEdge() {
- final Edge edge = mock(Edge.class);
- final GValue<Edge> gValue = GValue.ofEdge(edge);
- assertEquals(edge, gValue.get());
- assertEquals(GType.EDGE, gValue.getType());
- assertThat(gValue.isVariable(), is(false));
- }
-
- @Test
- public void shouldCreateGValueFromEdgeWithName() {
- final Edge edge = mock(Edge.class);
- final GValue<Edge> gValue = GValue.ofEdge("varName", edge);
- assertEquals(edge, gValue.get());
- assertEquals(GType.EDGE, gValue.getType());
- assertEquals("varName", gValue.getName());
- assertThat(gValue.isVariable(), is(true));
- }
-
- @Test
- public void shouldCreateGValueFromPath() {
- final Path path = mock(Path.class);
- final GValue<Path> gValue = GValue.ofPath(path);
- assertEquals(path, gValue.get());
- assertEquals(GType.PATH, gValue.getType());
- assertThat(gValue.isVariable(), is(false));
- }
-
- @Test
- public void shouldCreateGValueFromPathWithName() {
- final Path path = mock(Path.class);
- final GValue<Path> gValue = GValue.ofPath("varName", path);
- assertEquals(path, gValue.get());
- assertEquals(GType.PATH, gValue.getType());
- assertEquals("varName", gValue.getName());
- assertThat(gValue.isVariable(), is(true));
- }
-
- @Test
- public void shouldCreateGValueFromProperty() {
- final Property property = mock(Property.class);
- final GValue<Property> gValue = GValue.ofProperty(property);
- assertEquals(property, gValue.get());
- assertEquals(GType.PROPERTY, gValue.getType());
- assertThat(gValue.isVariable(), is(false));
- }
-
- @Test
- public void shouldCreateGValueFromPropertyWithName() {
- final Property property = mock(Property.class);
- final GValue<Property> gValue = GValue.ofProperty("varName", property);
- assertEquals(property, gValue.get());
- assertEquals(GType.PROPERTY, gValue.getType());
- assertEquals("varName", gValue.getName());
- assertThat(gValue.isVariable(), is(true));
- }
-
@Test
public void shouldBeAnInstanceOf() {
assertThat(GValue.instanceOf(GValue.of("string"), GType.STRING), is(true));
@@ -383,18 +326,6 @@ public class GValueTest {
assertThat(GValue.instanceOfNumber(GValue.of(Arrays.asList("string"))), is(false));
}
- @Test
- public void shouldBeAnInstanceOfElement() {
- assertThat(GValue.instanceOfElement(GValue.ofVertex(mock(Vertex.class))), is(true));
- assertThat(GValue.instanceOfElement(GValue.ofEdge(mock(Edge.class))), is(true));
- }
-
- @Test
- public void shouldNotBeAnInstanceOfElement() {
- assertThat(GValue.instanceOfElement(GValue.of("string")), is(false));
- assertThat(GValue.instanceOfElement(GValue.of(Arrays.asList("string"))), is(false));
- }
-
@Test
public void shouldHaveForMatchingType() {
final GValue<Integer> gValue = GValue.of(123);
@@ -638,4 +569,28 @@ public class GValueTest {
public void numberOfShouldThrowBecauseNullObject() {
GValue.numberOf(null);
}
+
+ @Test
+ public void numberOfShouldAcceptAllNumericTypeLiterals() {
+ assertEquals((byte) 123, GValue.numberOf((byte) 123));
+ assertEquals((short) 123, GValue.numberOf((short) 123));
+ assertEquals(123, GValue.numberOf(123));
+ assertEquals(123l, GValue.numberOf(123l));
+ assertEquals(123.45f, GValue.numberOf(123.45f));
+ assertEquals(123.45, GValue.numberOf(123.45));
+ assertEquals(BigInteger.ONE, GValue.numberOf(BigInteger.ONE));
+ assertEquals(BigDecimal.ONE, GValue.numberOf(BigDecimal.ONE));
+ }
+
+ @Test
+ public void numberOfShouldAcceptAllNumericTypeGValues() {
+ assertEquals((byte) 123, GValue.numberOf(GValue.of((byte) 123)));
+ assertEquals((short) 123, GValue.numberOf((GValue.of((short) 123))));
+ assertEquals(123, GValue.numberOf((GValue.of(123))));
+ assertEquals(123l, GValue.numberOf((GValue.of(123l))));
+ assertEquals(123.45f, GValue.numberOf((GValue.of(123.45f))));
+ assertEquals(123.45, GValue.numberOf((GValue.of(123.45))));
+ assertEquals(BigInteger.ONE, GValue.numberOf((GValue.of(BigInteger.ONE))));
+ assertEquals(BigDecimal.ONE, GValue.numberOf((GValue.of(BigDecimal.ONE))));
+ }
}
\ No newline at end of file
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/gremlin.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/gremlin.js
index 800d2fb85e..ac6b67bd2f 100644
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/gremlin.js
+++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/gremlin.js
@@ -156,6 +156,7 @@ const gremlins = {
g_injectXnull_nullX_anyXeqXnullXX: [function({g, xx1}) { return g.inject(xx1).any(P.eq(null)) }],
g_injectX3_threeX_anyXeqX3XX: [function({g, xx1}) { return g.inject(xx1).any(P.eq(3)) }],
g_V_coinX1X: [function({g}) { return g.V().coin(1.0) }],
+ g_V_coinX1varX: [function({g, xx1}) { return g.V().coin(xx1) }],
g_V_coinX0X: [function({g}) { return g.V().coin(0.0) }],
g_withStrategiesXSeedStrategyX_V_order_byXnameX_coinX50X: [function({g}) { return g.withStrategies(new SeedStrategy({seed: 999999})).V().order().by("name").coin(0.5) }],
g_VX1X_outXcreatedX_inXcreatedX_cyclicPath: [function({g, vid1}) { return g.V(vid1).out("created").in_("created").cyclicPath() }],
@@ -220,6 +221,7 @@ const gremlins = {
g_V_hasXage_isXgt_30XX: [function({g}) { return g.V().has("age", __.is(P.gt(30))) }],
g_V_hasXlabel_isXsoftwareXX: [function({g}) { return g.V().has(T.label, __.is("software")) }],
g_VX1X_hasXage_gt_30X: [function({g, vid1}) { return g.V(vid1).has("age", P.gt(30)) }],
+ g_V_hasXpersonvar_age_gt_30X: [function({g, xx1}) { return g.V().has(xx1, "age", P.gt(30)) }],
g_VX4X_hasXage_gt_30X: [function({g, vid4}) { return g.V(vid4).has("age", P.gt(30)) }],
g_VXv1X_hasXage_gt_30X: [function({g, v1}) { return g.V(v1).has("age", P.gt(30)) }],
g_VXv4X_hasXage_gt_30X: [function({g, v4}) { return g.V(v4).has("age", P.gt(30)) }],
@@ -269,6 +271,8 @@ const gremlins = {
g_V_hasIdXnullX: [function({g}) { return g.V().hasId(null) }],
g_V_hasIdXeqXnullXX: [function({g}) { return g.V().hasId(P.eq(null)) }],
g_V_hasIdX2_nullX: [function({g, vid2}) { return g.V().hasId(vid2, null) }],
+ g_V_hasIdXmarkovar_vadasvarX: [function({g, vid2, vid1}) { return g.V().hasId(vid1, vid2) }],
+ g_V_hasIdXmarkovar_vadasvar_petervarX: [function({g, vid2, vid1}) { return g.V().hasId(vid1, vid2) }],
g_V_hasIdX2AsString_nullX: [function({g, vid2}) { return g.V().hasId(vid2, null) }],
g_V_hasIdX1AsString_2AsString_nullX: [function({g, vid2, vid1}) { return g.V().hasId(vid1, vid2, null) }],
g_V_hasIdXnull_2X: [function({g, vid2}) { return g.V().hasId(null, vid2) }],
@@ -295,6 +299,7 @@ const gremlins = {
g_E_hasLabelXknowsX: [function({g}) { return g.E().hasLabel("knows") }],
g_E_hasLabelXuses_traversesX: [function({g}) { return g.E().hasLabel("uses", "traverses") }],
g_V_hasLabelXperson_software_blahX: [function({g}) { return g.V().hasLabel("person", "software", "blah") }],
+ g_V_hasLabelXperson_softwarevarX: [function({g, xx1}) { return g.V().hasLabel("person", xx1) }],
g_V_hasLabelXpersonX_hasLabelXsoftwareX: [function({g}) { return g.V().hasLabel("person").hasLabel("software") }],
g_V_hasLabelXpersonvarX_hasLabelXsoftwareX: [function({g, xx1}) { return g.V().hasLabel(xx1).hasLabel("software") }],
g_V_hasLabelXpersonvar_softwarevarX: [function({g, xx1, xx2}) { return g.V().hasLabel(xx1, xx2) }],
@@ -592,6 +597,7 @@ const gremlins = {
g_VXaX_addEXknowsX_toXbX_propertyXweight_0_1X: [function({g, v6, xx1, v1}) { return g.addV("person").property("name", "marko").property("age", 29).as("marko").addV("person").property("name", "vadas").property("age", 27).as("vadas").addV("software").property("name", "lop").property("lang", "java").as("lop").addV("person").property("name", "josh").property("age", 32).as("josh").addV("software").property("name", "ripple").property("lang", "java").as("ripple").addV("person").property("na [...]
g_addEXknowsXpropertyXweight_nullXfromXV_hasXname_markoXX_toXV_hasXname_vadasXX: [function({g}) { return g.addV("person").property("name", "marko").property("age", 29).addV("person").property("name", "vadas").property("age", 27) }, function({g}) { return g.addE("knows").property("weight", null).from_(__.V().has("name", "marko")).to(__.V().has("name", "vadas")) }, function({g}) { return g.E().has("knows", "weight", null) }],
g_addEXknowsvarXpropertyXweight_nullXfromXV_hasXname_markoXX_toXV_hasXname_vadasXX: [function({g, xx1}) { return g.addV("person").property("name", "marko").property("age", 29).addV("person").property("name", "vadas").property("age", 27) }, function({g, xx1}) { return g.addE(xx1).property("weight", null).from_(__.V().has("name", "marko")).to(__.V().has("name", "vadas")) }, function({g, xx1}) { return g.E().has("knows", "weight", null) }],
+ g_unionXaddEXknowsvarXpropertyXweight_nullXfromXV_hasXname_markoXX_toXV_hasXname_vadasXXX: [function({g, xx1}) { return g.addV("person").property("name", "marko").property("age", 29).addV("person").property("name", "vadas").property("age", 27) }, function({g, xx1}) { return g.union(__.addE(xx1).property("weight", 1).from_(__.V().has("name", "marko")).to(__.V().has("name", "vadas"))) }, function({g, xx1}) { return g.E().has("knows", "weight", 1) }],
g_VX1X_addVXanimalX_propertyXage_selectXaX_byXageXX_propertyXname_puppyX: [function({g, vid1}) { return g.addV("person").property("name", "marko").property("age", 29).as("marko").addV("person").property("name", "vadas").property("age", 27).as("vadas").addV("software").property("name", "lop").property("lang", "java").as("lop").addV("person").property("name", "josh").property("age", 32).as("josh").addV("software").property("name", "ripple").property("lang", "java").as("ripple").addV("p [...]
g_V_addVXanimalX_propertyXage_0X: [function({g}) { return g.addV("person").property("name", "marko").property("age", 29).as("marko").addV("person").property("name", "vadas").property("age", 27).as("vadas").addV("software").property("name", "lop").property("lang", "java").as("lop").addV("person").property("name", "josh").property("age", 32).as("josh").addV("software").property("name", "ripple").property("lang", "java").as("ripple").addV("person").property("name", "peter").property("ag [...]
g_V_addVXanimalvarX_propertyXage_0varX: [function({g, xx1, xx2}) { return g.addV("person").property("name", "marko").property("age", 29).as("marko").addV("person").property("name", "vadas").property("age", 27).as("vadas").addV("software").property("name", "lop").property("lang", "java").as("lop").addV("person").property("name", "josh").property("age", 32).as("josh").addV("software").property("name", "ripple").property("lang", "java").as("ripple").addV("person").property("name", "pete [...]
@@ -677,6 +683,7 @@ const gremlins = {
g_V_fold_combineXconstantXnullXX: [function({g}) { return g.V().fold().combine(__.constant(null)) }],
g_V_fold_combineXVX: [function({g}) { return g.V().fold().combine(__.V()) }],
g_V_valuesXnameX_fold_combineX2X: [function({g}) { return g.V().values("name").fold().combine(2) }],
+ g_V_valuesXnameX_fold_combineX2varX: [function({g, xx1}) { return g.V().values("name").fold().combine(xx1) }],
g_V_valuesXnameX_fold_combineXnullX: [function({g}) { return g.V().values("name").fold().combine(null) }],
g_V_valuesXnonexistantX_fold_combineXV_valuesXnameX_foldX_unfold: [function({g}) { return g.V().values("nonexistant").fold().combine(__.V().values("name").fold()).unfold() }],
g_V_valuesXnameX_fold_combineXV_valuesXnonexistantX_foldX_unfold: [function({g}) { return g.V().values("name").fold().combine(__.V().values("nonexistant").fold()).unfold() }],
@@ -753,6 +760,7 @@ const gremlins = {
g_V_fold_differenceXconstantXnullXX: [function({g}) { return g.V().fold().difference(__.constant(null)) }],
g_V_fold_differenceXVX: [function({g}) { return g.V().fold().difference(__.V()) }],
g_V_valuesXnameX_fold_differenceX2X: [function({g}) { return g.V().values("name").fold().difference(2) }],
+ g_V_valuesXnameX_fold_differenceX2varX: [function({g, xx1}) { return g.V().values("name").fold().difference(xx1) }],
g_V_valuesXnameX_fold_differenceXnullX: [function({g}) { return g.V().values("name").fold().difference(null) }],
g_V_valuesXnonexistantX_fold_differenceXV_valuesXnameX_foldX: [function({g}) { return g.V().values("nonexistant").fold().difference(__.V().values("name").fold()) }],
g_V_valuesXnameX_fold_differenceXV_valuesXnonexistantX_foldX: [function({g}) { return g.V().values("name").fold().difference(__.V().values("nonexistant").fold()) }],
@@ -772,6 +780,7 @@ const gremlins = {
g_V_fold_disjunctXconstantXnullXX: [function({g}) { return g.V().fold().disjunct(__.constant(null)) }],
g_V_fold_disjunctXVX: [function({g}) { return g.V().fold().disjunct(__.V()) }],
g_V_valuesXnameX_fold_disjunctX2X: [function({g}) { return g.V().values("name").fold().disjunct(2) }],
+ g_V_valuesXnameX_fold_disjunctX3varX: [function({g, xx1}) { return g.V().values("name").fold().disjunct(xx1) }],
g_V_valuesXnameX_fold_disjunctXnullX: [function({g}) { return g.V().values("name").fold().disjunct(null) }],
g_V_valuesXnonexistantX_fold_disjunctXV_valuesXnameX_foldX: [function({g}) { return g.V().values("nonexistant").fold().disjunct(__.V().values("name").fold()) }],
g_V_valuesXnameX_fold_disjunctXV_valuesXnonexistantX_foldX: [function({g}) { return g.V().values("name").fold().disjunct(__.V().values("nonexistant").fold()) }],
@@ -810,6 +819,7 @@ const gremlins = {
g_VX1X_outEXknows_createdX_inV: [function({g, vid1}) { return g.V(vid1).outE("knows", "created").inV() }],
g_VX1X_outEXknowsX_bothV: [function({g, vid1}) { return g.V(vid1).outE("knows").bothV() }],
g_VX1X_outEXknowsX_bothV_name: [function({g, vid1}) { return g.V(vid1).outE("knows").bothV().values("name") }],
+ g_V_toEXout_knowsvarX_valuesXweightX: [function({g, xx1}) { return g.V().toE(Direction.OUT, xx1).values("weight") }],
g_VX1X_properties_element: [function({g, v2}) { return g.V(v2).properties().element().limit(1) }],
g_V_properties_element: [function({g}) { return g.V().properties().element() }],
g_V_propertiesXageX_element: [function({g}) { return g.V().properties("age").element() }],
@@ -852,6 +862,7 @@ const gremlins = {
g_V_fold_intersectXconstantXnullXX: [function({g}) { return g.V().fold().intersect(__.constant(null)) }],
g_V_fold_intersectXVX: [function({g}) { return g.V().fold().intersect(__.V()) }],
g_V_valuesXnameX_fold_intersectX2X: [function({g}) { return g.V().values("name").fold().intersect(2) }],
+ g_V_valuesXnameX_fold_intersectX5varX: [function({g, xx1}) { return g.V().values("name").fold().intersect(xx1) }],
g_V_valuesXnameX_fold_intersectXnullX: [function({g}) { return g.V().values("name").fold().intersect(null) }],
g_V_valuesXnonexistantX_fold_intersectXV_valuesXnameX_foldX: [function({g}) { return g.V().values("nonexistant").fold().intersect(__.V().values("name").fold()) }],
g_V_valuesXnameX_fold_intersectXV_valuesXnonexistantX_foldX: [function({g}) { return g.V().values("name").fold().intersect(__.V().values("nonexistant").fold()) }],
@@ -1000,6 +1011,8 @@ const gremlins = {
g_V_mergeEXemptyX_two_exist: [function({g, xx1}) { return g.addV("person").property("name", "marko").property("age", 29).addV("person").property("name", "vadas").property("age", 27) }, function({g, xx1}) { return g.V().as("v").mergeE(xx1).option(Merge.outV, __.select("v")).option(Merge.inV, __.select("v")) }, function({g, xx1}) { return g.E() }, function({g, xx1}) { return g.V() }],
g_V_mergeE_inlineXemptyX_two_exist: [function({g}) { return g.addV("person").property("name", "marko").property("age", 29).addV("person").property("name", "vadas").property("age", 27) }, function({g}) { return g.V().as("v").mergeE(new Map([[T.label, "self"], [Direction.OUT, Merge.outV], [Direction.IN, Merge.inV]])).option(Merge.outV, __.select("v")).option(Merge.inV, __.select("v")) }, function({g}) { return g.E() }, function({g}) { return g.V() }],
g_mergeEXnullX: [function({g}) { return g.addV("person").property("name", "marko").property("age", 29) }, function({g}) { return g.mergeE(null) }],
+ g_mergeEXnullvarX: [function({g, xx1}) { return g.addV("person").property("name", "marko").property("age", 29) }, function({g, xx1}) { return g.mergeE(xx1) }],
+ g_V_limitX1X_mergeEXnullvarX: [function({g, xx1}) { return g.addV("person").property("name", "marko").property("age", 29) }, function({g, xx1}) { return g.V().limit(1).mergeE(xx1) }],
g_V_mergeEXnullX: [function({g}) { return g.addV("person").property("name", "marko").property("age", 29) }, function({g}) { return g.V().mergeE(null) }],
g_mergeEXlabel_knows_out_marko_in_vadasX: [function({g, xx1}) { return g.addV("person").property("name", "marko").addV("person").property("name", "vadas") }, function({g, xx1}) { return g.mergeE(xx1) }, function({g, xx1}) { return g.V().has("person", "name", "marko").out("knows").has("person", "name", "vadas") }],
g_withSideEffectXa_label_knows_out_marko_in_vadasX_mergeEXselectXaXX: [function({g, xx1}) { return g.addV("person").property("name", "marko").addV("person").property("name", "vadas") }, function({g, xx1}) { return g.withSideEffect("a", xx1).mergeE(__.select("a")) }, function({g, xx1}) { return g.V().has("person", "name", "marko").out("knows").has("person", "name", "vadas") }],
@@ -1051,6 +1064,7 @@ const gremlins = {
g_mergeVXemptyX: [function({g}) { return g.addV("person").property("name", "marko").property("age", 29) }, function({g}) { return g.mergeV(new Map([])) }, function({g}) { return g.V().has("person", "name", "marko").has("age", 29) }],
g_V_mergeVXemptyX_two_exist: [function({g}) { return g.addV("person").property("name", "marko").property("age", 29).addV("person").property("name", "vadas").property("age", 27) }, function({g}) { return g.V().mergeV(new Map([])) }, function({g}) { return g.V() }, function({g}) { return g.V().has("person", "name", "marko").has("age", 29) }, function({g}) { return g.V().has("person", "name", "vadas").has("age", 27) }],
g_mergeVXnullX: [function({g}) { return g.addV("person").property("name", "marko").property("age", 29) }, function({g}) { return g.mergeV(null) }, function({g}) { return g.V() }],
+ g_mergeVXnullvarX: [function({g, xx1}) { return g.addV("person").property("name", "marko").property("age", 29) }, function({g, xx1}) { return g.mergeV(xx1) }, function({g, xx1}) { return g.V() }],
g_V_mergeVXnullX: [function({g}) { return g.addV("person").property("name", "marko").property("age", 29) }, function({g}) { return g.V().mergeV(null) }, function({g}) { return g.V() }],
g_mergeVXlabel_person_name_stephenX: [function({g, xx1}) { return g.addV("person").property("name", "marko").property("age", 29) }, function({g, xx1}) { return g.mergeV(xx1) }, function({g, xx1}) { return g.V().has("person", "name", "stephen") }],
g_mergeVXlabel_person_name_markoX: [function({g, xx1}) { return g.addV("person").property("name", "marko").property("age", 29) }, function({g, xx1}) { return g.mergeV(xx1) }, function({g, xx1}) { return g.V().has("person", "name", "marko") }],
@@ -1175,6 +1189,7 @@ const gremlins = {
g_V_fold_productXconstantXnullXX: [function({g}) { return g.V().fold().product(__.constant(null)) }],
g_V_fold_productXVX: [function({g}) { return g.V().fold().product(__.V()) }],
g_V_valuesXnameX_fold_productX2X: [function({g}) { return g.V().values("name").fold().product(2) }],
+ g_V_valuesXnameX_fold_productX7varX: [function({g, xx1}) { return g.V().values("name").fold().product(xx1) }],
g_V_valuesXnameX_fold_productXnullX: [function({g}) { return g.V().values("name").fold().product(null) }],
g_V_valuesXnonexistantX_fold_productXV_valuesXnameX_foldX: [function({g}) { return g.V().values("nonexistant").fold().product(__.V().values("name").fold()) }],
g_V_valuesXnameX_fold_productXV_valuesXnonexistantX_foldX: [function({g}) { return g.V().values("name").fold().product(__.V().values("nonexistant").fold()) }],
diff --git a/gremlin-language/src/main/antlr4/Gremlin.g4 b/gremlin-language/src/main/antlr4/Gremlin.g4
index fcf0d3f0da..8133e751ad 100644
--- a/gremlin-language/src/main/antlr4/Gremlin.g4
+++ b/gremlin-language/src/main/antlr4/Gremlin.g4
@@ -643,7 +643,7 @@ traversalMethod_not
traversalMethod_option
: 'option' LPAREN traversalPredicate COMMA nestedTraversal RPAREN #traversalMethod_option_Predicate_Traversal
| 'option' LPAREN traversalMerge COMMA genericLiteralMapNullableArgument RPAREN #traversalMethod_option_Merge_Map
- | 'option' LPAREN traversalMerge COMMA genericLiteralMapNullableArgument COMMA traversalCardinality RPAREN #traversalMethod_option_Merge_Map_Cardinality
+ | 'option' LPAREN traversalMerge COMMA nullableGenericLiteralMap COMMA traversalCardinality RPAREN #traversalMethod_option_Merge_Map_Cardinality
| 'option' LPAREN traversalMerge COMMA nestedTraversal RPAREN #traversalMethod_option_Merge_Traversal
| 'option' LPAREN genericLiteralArgument COMMA nestedTraversal RPAREN #traversalMethod_option_Object_Traversal
| 'option' LPAREN nestedTraversal RPAREN #traversalMethod_option_Traversal
@@ -1493,6 +1493,11 @@ genericLiteralMapNullableArgument
| variable
;
+nullableGenericLiteralMap
+ : genericLiteralMap
+ | nullLiteral
+ ;
+
structureVertexArgument
: structureVertex
| variable
diff --git a/gremlin-python/src/main/python/radish/gremlin.py b/gremlin-python/src/main/python/radish/gremlin.py
index 3385d0f6a7..247f98b86f 100644
--- a/gremlin-python/src/main/python/radish/gremlin.py
+++ b/gremlin-python/src/main/python/radish/gremlin.py
@@ -857,6 +857,13 @@ world.gremlins = {
'g_injectXa_null_bX_intersectXa_cX': [(lambda g, xx1=None,xx2=None:g.inject(xx1).intersect(xx2))],
'g_injectXa_null_bX_intersectXa_null_cX': [(lambda g, xx1=None,xx2=None:g.inject(xx1).intersect(xx2))],
'g_injectX3_threeX_intersectXfive_three_7X': [(lambda g, xx1=None,xx2=None:g.inject(xx1).intersect(xx2))],
+ 'g_injectX__feature___test__nullX_lTrim': [(lambda g:g.inject(' feature', ' one test', None, '', ' ', ' abc', 'abc ', ' abc ', '  ').l_trim())],
+ 'g_injectX__feature___test__nullX_lTrimXlocalX': [(lambda g:g.inject([' feature ', ' one test ', None, '', ' ', ' abc', 'abc ', ' abc ', '  ']).l_trim(Scope.local))],
+ 'g_injectX__feature__X_lTrim': [(lambda g:g.inject(' feature ').l_trim())],
+ 'g_injectXListXa_bXX_lTrim': [(lambda g, xx1=None:g.inject(xx1).l_trim())],
+ 'g_injectXListX1_2XX_lTrimXlocalX': [(lambda g, xx1=None:g.inject(xx1).l_trim(Scope.local))],
+ 'g_V_valuesXnameX_lTrim': [(lambda g:g.add_v('person').property('name', ' marko ').property('age', 29).as_('marko').add_v('person').property('name', ' vadas ').property('age', 27).as_('vadas').add_v('software').property('name', ' lop').property('lang', 'java').as_('lop').add_v('person').property('name', 'josh ').property('age', 32).as_('josh').add_v('software').property('name', ' ripple ').property('lang', 'java').as_('ripple').add_v('person').property('name', 'peter').proper [...]
+ 'g_V_valuesXnameX_order_fold_lTrimXlocalX': [(lambda g:g.add_v('person').property('name', ' marko ').property('age', 29).as_('marko').add_v('person').property('name', ' vadas ').property('age', 27).as_('vadas').add_v('software').property('name', ' lop').property('lang', 'java').as_('lop').add_v('person').property('name', 'josh ').property('age', 32).as_('josh').add_v('software').property('name', ' ripple ').property('lang', 'java').as_('ripple').add_v('person').property('name [...]
'g_injectXfeature_test_nullX_length': [(lambda g:g.inject('feature', 'test', None).length())],
'g_injectXfeature_test_nullX_lengthXlocalX': [(lambda g:g.inject('feature', 'test', None).length(Scope.local))],
'g_injectXListXa_bXX_length': [(lambda g, xx1=None:g.inject(xx1).length())],
@@ -866,13 +873,6 @@ world.gremlins = {
'g_VX1X_repeatXboth_simplePathX_untilXhasXname_peterX_or_loops_isX2XX_hasXname_peterX_path_byXnameX': [(lambda g, vid1=None:g.V(vid1).repeat(__.both().simple_path()).until(__.has('name', 'peter').or_().loops().is_(2)).has('name', 'peter').path().by('name'))],
'g_VX1X_repeatXboth_simplePathX_untilXhasXname_peterX_and_loops_isX3XX_hasXname_peterX_path_byXnameX': [(lambda g, vid1=None:g.V(vid1).repeat(__.both().simple_path()).until(__.has('name', 'peter').and_().loops().is_(3)).has('name', 'peter').path().by('name'))],
'g_V_emitXhasXname_markoX_or_loops_isX2XX_repeatXoutX_valuesXnameX': [(lambda g:g.V().emit(__.has('name', 'marko').or_().loops().is_(2)).repeat(__.out()).values('name'))],
- 'g_injectX__feature___test__nullX_lTrim': [(lambda g:g.inject(' feature', ' one test', None, '', ' ', ' abc', 'abc ', ' abc ', '  ').l_trim())],
- 'g_injectX__feature___test__nullX_lTrimXlocalX': [(lambda g:g.inject([' feature ', ' one test ', None, '', ' ', ' abc', 'abc ', ' abc ', '  ']).l_trim(Scope.local))],
- 'g_injectX__feature__X_lTrim': [(lambda g:g.inject(' feature ').l_trim())],
- 'g_injectXListXa_bXX_lTrim': [(lambda g, xx1=None:g.inject(xx1).l_trim())],
- 'g_injectXListX1_2XX_lTrimXlocalX': [(lambda g, xx1=None:g.inject(xx1).l_trim(Scope.local))],
- 'g_V_valuesXnameX_lTrim': [(lambda g:g.add_v('person').property('name', ' marko ').property('age', 29).as_('marko').add_v('person').property('name', ' vadas ').property('age', 27).as_('vadas').add_v('software').property('name', ' lop').property('lang', 'java').as_('lop').add_v('person').property('name', 'josh ').property('age', 32).as_('josh').add_v('software').property('name', ' ripple ').property('lang', 'java').as_('ripple').add_v('person').property('name', 'peter').proper [...]
- 'g_V_valuesXnameX_order_fold_lTrimXlocalX': [(lambda g:g.add_v('person').property('name', ' marko ').property('age', 29).as_('marko').add_v('person').property('name', ' vadas ').property('age', 27).as_('vadas').add_v('software').property('name', ' lop').property('lang', 'java').as_('lop').add_v('person').property('name', 'josh ').property('age', 32).as_('josh').add_v('software').property('name', ' ripple ').property('lang', 'java').as_('ripple').add_v('person').property('name [...]
'g_VX1X_mapXnameX': [], # skipping as it contains a lambda
'g_VX1X_outE_label_mapXlengthX': [], # skipping as it contains a lambda
'g_VX1X_out_mapXnameX_mapXlengthX': [], # skipping as it contains a lambda
@@ -1046,7 +1046,7 @@ world.gremlins = {
'g_mergeVXemptyX': [(lambda g:g.add_v('person').property('name', 'marko').property('age', 29)), (lambda g:g.merge_v({ })), (lambda g:g.V().has('person', 'name', 'marko').has('age', 29))],
'g_V_mergeVXemptyX_two_exist': [(lambda g:g.add_v('person').property('name', 'marko').property('age', 29).add_v('person').property('name', 'vadas').property('age', 27)), (lambda g:g.V().merge_v({ })), (lambda g:g.V()), (lambda g:g.V().has('person', 'name', 'marko').has('age', 29)), (lambda g:g.V().has('person', 'name', 'vadas').has('age', 27))],
'g_mergeVXnullX': [(lambda g:g.add_v('person').property('name', 'marko').property('age', 29)), (lambda g:g.merge_v(None)), (lambda g:g.V())],
- 'g_mergeVXnullvarX': [(lambda g, xx1=None:g.merge_v(xx1)), (lambda g, xx1=None:g.V())],
+ 'g_mergeVXnullvarX': [(lambda g, xx1=None:g.add_v('person').property('name', 'marko').property('age', 29)), (lambda g, xx1=None:g.merge_v(xx1)), (lambda g, xx1=None:g.V())],
'g_V_mergeVXnullX': [(lambda g:g.add_v('person').property('name', 'marko').property('age', 29)), (lambda g:g.V().merge_v(None)), (lambda g:g.V())],
'g_mergeVXlabel_person_name_stephenX': [(lambda g, xx1=None:g.add_v('person').property('name', 'marko').property('age', 29)), (lambda g, xx1=None:g.merge_v(xx1)), (lambda g, xx1=None:g.V().has('person', 'name', 'stephen'))],
'g_mergeVXlabel_person_name_markoX': [(lambda g, xx1=None:g.add_v('person').property('name', 'marko').property('age', 29)), (lambda g, xx1=None:g.merge_v(xx1)), (lambda g, xx1=None:g.V().has('person', 'name', 'marko'))],
@@ -1088,7 +1088,6 @@ world.gremlins = {
'g_mergeVXname_markoX_optionXonMatch_age_singleX33XX': [(lambda g:g.add_v('person').property('name', 'marko').property(Cardinality.list_, 'age', 29).property(Cardinality.list_, 'age', 31).property(Cardinality.list_, 'age', 32)), (lambda g:g.merge_v({ 'name': 'marko' }).option(Merge.on_match, { 'age': CardinalityValue.single(33) })), (lambda g:g.V().has('person', 'name', 'marko').has('age', 33)), (lambda g:g.V().has('person', 'name', 'marko').has('age')), (lambda g:g.V().has('person', [...]
'g_mergeVXname_markoX_optionXonMatch_age_33_singleX': [(lambda g:g.add_v('person').property('name', 'marko').property(Cardinality.list_, 'age', 29).property(Cardinality.list_, 'age', 31).property(Cardinality.list_, 'age', 32)), (lambda g:g.merge_v({ 'name': 'marko' }).option(Merge.on_match, { 'age': 33 }, Cardinality.single)), (lambda g:g.V().has('person', 'name', 'marko').has('age', 33)), (lambda g:g.V().has('person', 'name', 'marko').has('age')), (lambda g:g.V().has('person', 'name [...]
'g_mergeVXname_markoX_optionXonMatch_name_allen_age_setX31X_singleX': [(lambda g:g.add_v('person').property('name', 'marko').property(Cardinality.list_, 'age', 29).property(Cardinality.list_, 'age', 31).property(Cardinality.list_, 'age', 32)), (lambda g:g.merge_v({ 'name': 'marko' }).option(Merge.on_match, { 'name': 'allen', 'age': CardinalityValue.set_(31) }, Cardinality.single)), (lambda g:g.V().has('person', 'name', 'marko')), (lambda g:g.V().has('person', 'name', 'allen').has('ag [...]
- 'g_mergeVXname_markoX_optionXonMatch_name_allen_var_singleX': [(lambda g, xx1=None:g.add_v('person').property('name', 'marko')), (lambda g, xx1=None:g.merge_v({ 'name': 'marko' }).option(Merge.on_match, xx1, Cardinality.single)), (lambda g, xx1=None:g.V().has('person', 'name', 'marko')), (lambda g, xx1=None:g.V().has('person', 'name', 'allen'))],
'g_mergeVXname_markoX_optionXonMatch_name_allen_age_singleX31X_singleX': [(lambda g:g.add_v('person').property('name', 'marko').property(Cardinality.list_, 'age', 29).property(Cardinality.list_, 'age', 31).property(Cardinality.list_, 'age', 32)), (lambda g:g.merge_v({ 'name': 'marko' }).option(Merge.on_match, { 'name': 'allen', 'age': CardinalityValue.single(31) }, Cardinality.single)), (lambda g:g.V().has('person', 'name', 'marko')), (lambda g:g.V().has('person', 'name', 'allen').ha [...]
'g_mergeVXname_aliceX_optionXonCreate_age_singleX81XX': [(lambda g:g.merge_v({ 'name': 'alice', T.label: 'person' }).option(Merge.on_create, { 'age': CardinalityValue.single(81) })), (lambda g:g.V().has('person', 'name', 'alice').has('age', 81)), (lambda g:g.V().has('person', 'name', 'alice').has('age')), (lambda g:g.V().has('person', 'name', 'alice').properties('age'))],
'g_mergeVXname_aliceX_optionXonCreate_age_setX81XX': [(lambda g:g.merge_v({ 'name': 'alice', T.label: 'person' }).option(Merge.on_create, { 'age': CardinalityValue.set_(81) })), (lambda g:g.V().has('person', 'name', 'alice').has('age', 81)), (lambda g:g.V().has('person', 'name', 'alice').has('age')), (lambda g:g.V().has('person', 'name', 'alice').properties('age'))],
@@ -1195,6 +1194,13 @@ world.gremlins = {
'g_V_hasXageX_propertiesXage_nameX_value': [(lambda g:g.V().has('age').properties('age', 'name').value())],
'g_V_propertiesXname_age_nullX_value': [(lambda g:g.V().properties('name', 'age', None).value())],
'g_V_valuesXname_age_nullX': [(lambda g:g.V().values('name', 'age', None))],
+ 'g_injectX__feature___test__nullX_rTrim': [(lambda g:g.inject('feature ', 'one test ', None, '', ' ', ' abc', 'abc ', ' abc ', '  ').r_trim())],
+ 'g_injectX__feature___test__nullX_rTrimXlocalX': [(lambda g:g.inject([' feature ', ' one test ', None, '', ' ', ' abc', 'abc ', ' abc ', '  ']).r_trim(Scope.local))],
+ 'g_injectX__feature__X_rTrim': [(lambda g:g.inject(' feature ').r_trim())],
+ 'g_injectXListXa_bXX_rTrim': [(lambda g, xx1=None:g.inject(xx1).r_trim())],
+ 'g_injectXListX1_2XX_rTrimXlocalX': [(lambda g, xx1=None:g.inject(xx1).r_trim(Scope.local))],
+ 'g_V_valuesXnameX_rTrim': [(lambda g:g.add_v('person').property('name', ' marko ').property('age', 29).as_('marko').add_v('person').property('name', ' vadas ').property('age', 27).as_('vadas').add_v('software').property('name', ' lop').property('lang', 'java').as_('lop').add_v('person').property('name', 'josh ').property('age', 32).as_('josh').add_v('software').property('name', ' ripple ').property('lang', 'java').as_('ripple').add_v('person').property('name', 'peter').proper [...]
+ 'g_V_valuesXnameX_order_fold_rTrimXlocalX': [(lambda g:g.add_v('person').property('name', ' marko ').property('age', 29).as_('marko').add_v('person').property('name', ' vadas ').property('age', 27).as_('vadas').add_v('software').property('name', ' lop').property('lang', 'java').as_('lop').add_v('person').property('name', 'josh ').property('age', 32).as_('josh').add_v('software').property('name', ' ripple ').property('lang', 'java').as_('ripple').add_v('person').property('name [...]
'g_injectXthat_this_test_nullX_replaceXh_jX': [(lambda g:g.inject('that', 'this', 'test', None).replace('h', 'j'))],
'g_injectXthat_this_test_nullX_fold_replaceXlocal_h_jX': [(lambda g:g.inject('that', 'this', 'test', None).fold().replace(Scope.local, 'h', 'j'))],
'g_injectXListXa_bXcX_replaceXa_bX': [(lambda g, xx1=None:g.inject(xx1).replace('a', 'b'))],
@@ -1211,13 +1217,6 @@ world.gremlins = {
'g_injectXnullX_reverse': [(lambda g:g.inject(None).reverse())],
'g_injectXbX_reverse': [(lambda g:g.inject('b').reverse())],
'g_injectX3_threeX_reverse': [(lambda g, xx1=None:g.inject(xx1).reverse())],
- 'g_injectX__feature___test__nullX_rTrim': [(lambda g:g.inject('feature ', 'one test ', None, '', ' ', ' abc', 'abc ', ' abc ', '  ').r_trim())],
- 'g_injectX__feature___test__nullX_rTrimXlocalX': [(lambda g:g.inject([' feature ', ' one test ', None, '', ' ', ' abc', 'abc ', ' abc ', '  ']).r_trim(Scope.local))],
- 'g_injectX__feature__X_rTrim': [(lambda g:g.inject(' feature ').r_trim())],
- 'g_injectXListXa_bXX_rTrim': [(lambda g, xx1=None:g.inject(xx1).r_trim())],
- 'g_injectXListX1_2XX_rTrimXlocalX': [(lambda g, xx1=None:g.inject(xx1).r_trim(Scope.local))],
- 'g_V_valuesXnameX_rTrim': [(lambda g:g.add_v('person').property('name', ' marko ').property('age', 29).as_('marko').add_v('person').property('name', ' vadas ').property('age', 27).as_('vadas').add_v('software').property('name', ' lop').property('lang', 'java').as_('lop').add_v('person').property('name', 'josh ').property('age', 32).as_('josh').add_v('software').property('name', ' ripple ').property('lang', 'java').as_('ripple').add_v('person').property('name', 'peter').proper [...]
- 'g_V_valuesXnameX_order_fold_rTrimXlocalX': [(lambda g:g.add_v('person').property('name', ' marko ').property('age', 29).as_('marko').add_v('person').property('name', ' vadas ').property('age', 27).as_('vadas').add_v('software').property('name', ' lop').property('lang', 'java').as_('lop').add_v('person').property('name', 'josh ').property('age', 32).as_('josh').add_v('software').property('name', ' ripple ').property('lang', 'java').as_('ripple').add_v('person').property('name [...]
'g_VX1X_asXaX_outXknowsX_asXbX_selectXa_bX': [(lambda g, vid1=None:g.V(vid1).as_('a').out('knows').as_('b').select('a', 'b'))],
'g_VX1X_asXaX_outXknowsX_asXbX_selectXa_bX_byXnameX': [(lambda g, vid1=None:g.V(vid1).as_('a').out('knows').as_('b').select('a', 'b').by('name'))],
'g_VX1X_asXaX_outXknowsX_asXbX_selectXaX': [(lambda g, vid1=None:g.V(vid1).as_('a').out('knows').as_('b').select('a'))],
diff --git a/gremlin-python/src/main/python/tests/driver/test_client.py b/gremlin-python/src/main/python/tests/driver/test_client.py
index c04bf9d26d..ba33ac9677 100644
--- a/gremlin-python/src/main/python/tests/driver/test_client.py
+++ b/gremlin-python/src/main/python/tests/driver/test_client.py
@@ -265,7 +265,7 @@ def test_client_gremlin_lang_request_options_with_binding(client):
g = GraphTraversalSource(Graph(), TraversalStrategies())
# Note that bindings for constructed traversals is done via Parameter only
t = g.with_('language', 'gremlin-lang').V(GValue('x', [1, 2, 3])).count()
- request_opts = DriverRemoteConnection.extract_request_options(t.gremlin_lang)
+ request_opts = {'language': 'gremlin-lang', 'params': {'x': [1, 2, 3]}}
message = create_basic_request_message(t)
result_set = client.submit(message, request_options=request_opts)
assert result_set.all().result()[0] == 3
diff --git a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/GraphBinaryLangRemoteFeatureTest.java b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/GraphBinaryGroovyRemoteParameterizedFeatureTest.java
similarity index 84%
copy from gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/GraphBinaryLangRemoteFeatureTest.java
copy to gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/GraphBinaryGroovyRemoteParameterizedFeatureTest.java
index 205db5884a..079ce2f655 100644
--- a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/GraphBinaryLangRemoteFeatureTest.java
+++ b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/GraphBinaryGroovyRemoteParameterizedFeatureTest.java
@@ -30,13 +30,12 @@ import org.junit.runner.RunWith;
@RunWith(Cucumber.class)
@CucumberOptions(
- tags = "not @RemoteOnly and not @GraphComputerOnly and not @AllowNullPropertyValues",
+ tags = "not @RemoteOnly and not @GraphComputerOnly and not @AllowNullPropertyValues and not @GremlinGroovyNotSupported",
glue = { "org.apache.tinkerpop.gremlin.features" },
- objectFactory = GraphBinaryLangRemoteFeatureTest.RemoteGuiceFactory.class,
+ objectFactory = GraphBinaryGroovyRemoteParameterizedFeatureTest.RemoteGuiceFactory.class,
features = { "classpath:/org/apache/tinkerpop/gremlin/test/features" },
-// name= {"g_addEXknowsX_fromXaX_toXbX_propertyXweight_0_1X"},
plugin = {"progress", "junit:target/cucumber.xml"})
-public class GraphBinaryLangRemoteFeatureTest extends AbstractFeatureTest {
+public class GraphBinaryGroovyRemoteParameterizedFeatureTest extends AbstractFeatureTest {
public static class RemoteGuiceFactory extends AbstractGuiceFactory {
public RemoteGuiceFactory() {
super(Guice.createInjector(Stage.PRODUCTION, CucumberModules.createScenarioModule(), new ServiceModule()));
@@ -46,7 +45,7 @@ public class GraphBinaryLangRemoteFeatureTest extends AbstractFeatureTest {
public static final class ServiceModule extends AbstractModule {
@Override
protected void configure() {
- bind(World.class).to(RemoteWorld.GraphBinaryLangRemoteWorld.class);
+ bind(World.class).to(RemoteWorld.GraphBinaryGroovyParameterizedRemoteWorld.class);
}
}
}
diff --git a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/GraphBinaryLangRemoteFeatureTest.java b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/GraphBinaryLangRemoteFeatureTest.java
index 205db5884a..d02ad5cc5f 100644
--- a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/GraphBinaryLangRemoteFeatureTest.java
+++ b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/GraphBinaryLangRemoteFeatureTest.java
@@ -34,7 +34,6 @@ import org.junit.runner.RunWith;
glue = { "org.apache.tinkerpop.gremlin.features" },
objectFactory = GraphBinaryLangRemoteFeatureTest.RemoteGuiceFactory.class,
features = { "classpath:/org/apache/tinkerpop/gremlin/test/features" },
-// name= {"g_addEXknowsX_fromXaX_toXbX_propertyXweight_0_1X"},
plugin = {"progress", "junit:target/cucumber.xml"})
public class GraphBinaryLangRemoteFeatureTest extends AbstractFeatureTest {
public static class RemoteGuiceFactory extends AbstractGuiceFactory {
diff --git a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/GraphBinaryLangRemoteFeatureTest.java b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/GraphBinaryLangRemoteParameterizedFeatureTest.java
similarity index 86%
copy from gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/GraphBinaryLangRemoteFeatureTest.java
copy to gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/GraphBinaryLangRemoteParameterizedFeatureTest.java
index 205db5884a..a50a3ed367 100644
--- a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/GraphBinaryLangRemoteFeatureTest.java
+++ b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/GraphBinaryLangRemoteParameterizedFeatureTest.java
@@ -32,11 +32,10 @@ import org.junit.runner.RunWith;
@CucumberOptions(
tags = "not @RemoteOnly and not @GraphComputerOnly and not @AllowNullPropertyValues",
glue = { "org.apache.tinkerpop.gremlin.features" },
- objectFactory = GraphBinaryLangRemoteFeatureTest.RemoteGuiceFactory.class,
+ objectFactory = GraphBinaryLangRemoteParameterizedFeatureTest.RemoteGuiceFactory.class,
features = { "classpath:/org/apache/tinkerpop/gremlin/test/features" },
-// name= {"g_addEXknowsX_fromXaX_toXbX_propertyXweight_0_1X"},
plugin = {"progress", "junit:target/cucumber.xml"})
-public class GraphBinaryLangRemoteFeatureTest extends AbstractFeatureTest {
+public class GraphBinaryLangRemoteParameterizedFeatureTest extends AbstractFeatureTest {
public static class RemoteGuiceFactory extends AbstractGuiceFactory {
public RemoteGuiceFactory() {
super(Guice.createInjector(Stage.PRODUCTION, CucumberModules.createScenarioModule(), new ServiceModule()));
@@ -46,7 +45,7 @@ public class GraphBinaryLangRemoteFeatureTest extends AbstractFeatureTest {
public static final class ServiceModule extends AbstractModule {
@Override
protected void configure() {
- bind(World.class).to(RemoteWorld.GraphBinaryLangRemoteWorld.class);
+ bind(World.class).to(RemoteWorld.GraphBinaryLangParameterizedRemoteWorld.class);
}
}
}
diff --git a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/GraphBinaryLangRemoteFeatureTest.java b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/GraphSONLangRemoteParameterizedFeatureTest.java
similarity index 86%
copy from gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/GraphBinaryLangRemoteFeatureTest.java
copy to gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/GraphSONLangRemoteParameterizedFeatureTest.java
index 205db5884a..46c4af6ca7 100644
--- a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/GraphBinaryLangRemoteFeatureTest.java
+++ b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/GraphSONLangRemoteParameterizedFeatureTest.java
@@ -32,11 +32,10 @@ import org.junit.runner.RunWith;
@CucumberOptions(
tags = "not @RemoteOnly and not @GraphComputerOnly and not @AllowNullPropertyValues",
glue = { "org.apache.tinkerpop.gremlin.features" },
- objectFactory = GraphBinaryLangRemoteFeatureTest.RemoteGuiceFactory.class,
+ objectFactory = GraphSONLangRemoteParameterizedFeatureTest.RemoteGuiceFactory.class,
features = { "classpath:/org/apache/tinkerpop/gremlin/test/features" },
-// name= {"g_addEXknowsX_fromXaX_toXbX_propertyXweight_0_1X"},
plugin = {"progress", "junit:target/cucumber.xml"})
-public class GraphBinaryLangRemoteFeatureTest extends AbstractFeatureTest {
+public class GraphSONLangRemoteParameterizedFeatureTest extends AbstractFeatureTest {
public static class RemoteGuiceFactory extends AbstractGuiceFactory {
public RemoteGuiceFactory() {
super(Guice.createInjector(Stage.PRODUCTION, CucumberModules.createScenarioModule(), new ServiceModule()));
@@ -46,7 +45,7 @@ public class GraphBinaryLangRemoteFeatureTest extends AbstractFeatureTest {
public static final class ServiceModule extends AbstractModule {
@Override
protected void configure() {
- bind(World.class).to(RemoteWorld.GraphBinaryLangRemoteWorld.class);
+ bind(World.class).to(RemoteWorld.GraphSONLangParameterizedRemoteWorld.class);
}
}
}
diff --git a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/RemoteWorld.java b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/RemoteWorld.java
index 4154bdc671..17f225b747 100644
--- a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/RemoteWorld.java
+++ b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/RemoteWorld.java
@@ -167,7 +167,9 @@ public abstract class RemoteWorld implements World {
final GraphTraversalSource g = super.getGraphTraversalSource(graphData);
return g.with("language", "gremlin-lang");
}
+ }
+ public static class GraphBinaryLangParameterizedRemoteWorld extends GraphBinaryLangRemoteWorld {
@Override
public boolean useParametersLiterally() {
return false;
@@ -194,6 +196,13 @@ public abstract class RemoteWorld implements World {
}
}
+ public static class GraphBinaryGroovyParameterizedRemoteWorld extends GraphBinaryGroovyRemoteWorld {
+ @Override
+ public boolean useParametersLiterally() {
+ return false;
+ }
+ }
+
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public static class GraphBinaryRemoteComputerWorld extends RemoteComputerWorld {
@@ -216,7 +225,9 @@ public abstract class RemoteWorld implements World {
final GraphTraversalSource g = super.getGraphTraversalSource(graphData);
return g.with("language", "gremlin-lang");
}
+ }
+ public static class GraphSONLangParameterizedRemoteWorld extends GraphSONLangRemoteWorld {
@Override
public boolean useParametersLiterally() {
return false;
diff --git a/gremlin-server/src/test/resources/META-INF/services/io.cucumber.core.backend.ObjectFactory b/gremlin-server/src/test/resources/META-INF/services/io.cucumber.core.backend.ObjectFactory
index d7c53bc1bd..409c7dc485 100644
--- a/gremlin-server/src/test/resources/META-INF/services/io.cucumber.core.backend.ObjectFactory
+++ b/gremlin-server/src/test/resources/META-INF/services/io.cucumber.core.backend.ObjectFactory
@@ -1,6 +1,9 @@
org.apache.tinkerpop.gremlin.driver.remote.GraphBinaryLangRemoteFeatureTest$RemoteGuiceFactory
+org.apache.tinkerpop.gremlin.driver.remote.GraphBinaryLangRemoteParameterizedFeatureTest$RemoteGuiceFactory
org.apache.tinkerpop.gremlin.driver.remote.GraphBinaryLangBulkedRemoteFeatureTest$RemoteGuiceFactory
org.apache.tinkerpop.gremlin.driver.remote.GraphBinaryGroovyRemoteFeatureTest$RemoteGuiceFactory
+org.apache.tinkerpop.gremlin.driver.remote.GraphBinaryGroovyRemoteParameterizedFeatureTest$RemoteGuiceFactory
org.apache.tinkerpop.gremlin.driver.remote.GraphBinaryRemoteComputerFeatureTest$RemoteGuiceFactory
org.apache.tinkerpop.gremlin.driver.remote.GraphSONLangRemoteFeatureTest$RemoteGuiceFactory
+org.apache.tinkerpop.gremlin.driver.remote.GraphSONLangRemoteParameterizedFeatureTest$RemoteGuiceFactory
org.apache.tinkerpop.gremlin.driver.remote.GraphSONRemoteComputerFeatureTest$RemoteGuiceFactory
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/features/StepDefinition.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/features/StepDefinition.java
index ae19a1c613..fa622dd0b7 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/features/StepDefinition.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/features/StepDefinition.java
@@ -43,9 +43,13 @@ import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSo
import org.apache.tinkerpop.gremlin.process.traversal.step.util.ImmutablePath;
import org.apache.tinkerpop.gremlin.structure.Direction;
import org.apache.tinkerpop.gremlin.structure.Edge;
+import org.apache.tinkerpop.gremlin.structure.Property;
import org.apache.tinkerpop.gremlin.structure.T;
import org.apache.tinkerpop.gremlin.structure.Vertex;
import org.apache.tinkerpop.gremlin.structure.VertexProperty;
+import org.apache.tinkerpop.gremlin.structure.util.detached.DetachedEdge;
+import org.apache.tinkerpop.gremlin.structure.util.detached.DetachedVertex;
+import org.apache.tinkerpop.gremlin.structure.util.detached.DetachedVertexProperty;
import org.apache.tinkerpop.gremlin.util.DatetimeHelper;
import org.apache.tinkerpop.gremlin.util.iterator.IteratorUtils;
import org.apache.tinkerpop.shaded.jackson.databind.JsonNode;
@@ -230,7 +234,7 @@ public final class StepDefinition {
add(Pair.with(Pattern.compile("v\\[(.+)\\]\\.id"), s -> g.V().has("name", s).id().next()));
add(Pair.with(Pattern.compile("v\\[(.+)\\]\\.sid"), s -> g.V().has("name", s).id().next().toString()));
- add(Pair.with(Pattern.compile("v\\[(.+)\\]"), s -> g.V().has("name", s).next()));
+ add(Pair.with(Pattern.compile("v\\[(.+)\\]"), s -> detachVertex(g.V().has("name", s).next())));
add(Pair.with(Pattern.compile("e\\[(.+)\\]\\.id"), s -> getEdgeId(g, s)));
add(Pair.with(Pattern.compile("e\\[(.+)\\]\\.sid"), s -> getEdgeIdString(g, s)));
add(Pair.with(Pattern.compile("e\\[(.+)\\]"), s -> getEdge(g, s)));
@@ -248,6 +252,38 @@ public final class StepDefinition {
add(Pair.with(Pattern.compile("(false)"), s -> false));
}};
+ /**
+ * Some implementations of {@link Vertex} are not {@code Serializable} and may lead to test failures when passed as
+ * parameters. One such instance is {@code HadoopVertex}. This method detaches vertices as tests should never
+ * require implementation-specific elements.
+ */
+ private static DetachedVertex detachVertex(final Vertex vertex) {
+ return new DetachedVertex(vertex.id(), vertex.label(),
+ (List<VertexProperty>) IteratorUtils.asList(vertex.properties()).stream()
+ .map(vp -> detachVertexProperty((VertexProperty) vp)).collect(Collectors.toList()));
+ }
+
+ /**
+ * Some implementations of {@link Edge} are not {@code Serializable} and may lead to test failures when passed as
+ * parameters. One such instance is {@code HadoopEdge}. This method detaches edges as tests should never
+ * require implementation-specific elements.
+ */
+ private static DetachedEdge detachEdge(final Edge edge) {
+ return new DetachedEdge(edge.id(), edge.label(), IteratorUtils.asList(edge.properties()),
+ edge.outVertex().id(), edge.outVertex().label(), edge.inVertex().id(), edge.inVertex().label());
+ }
+
+ /**
+ * Some implementations of {@link VertexProperty} are not {@code Serializable} and may lead to test failures when passed as
+ * parameters. One such instance is {@code HadoopVertexProperty}. This method detaches vertex properties as tests
+ * should never require implementation-specific elements.
+ */
+ private static DetachedVertexProperty detachVertexProperty(final VertexProperty vp) {
+ Map<String, Object> properties = new HashMap<>();
+ vp.properties().forEachRemaining(p -> properties.put(((Property) p).key(), ((Property) p).value()));
+ return new DetachedVertexProperty(vp.id(), vp.label(), vp.value(), properties, vp.element());
+ }
+
@Inject
public StepDefinition(final World world) {
this.world = Objects.requireNonNull(world, "world must not be null");
@@ -562,8 +598,8 @@ public final class StepDefinition {
final Triplet<String,String,String> t = getEdgeTriplet(e);
// make this OLAP proof since you can't leave the star graph
- return g.V().has("name", t.getValue0()).outE(t.getValue1()).toStream().
- filter(edge -> g.V(edge.inVertex().id()).has("name", t.getValue2()).hasNext()).findFirst().get();
+ return detachEdge(g.V().has("name", t.getValue0()).outE(t.getValue1()).toStream().
+ filter(edge -> g.V(edge.inVertex().id()).has("name", t.getValue2()).hasNext()).findFirst().get());
}
/**
diff --git a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/MergeEdge.feature b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/MergeEdge.feature
index 43642f3dcc..f8fa2caf20 100644
--- a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/MergeEdge.feature
+++ b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/MergeEdge.feature
@@ -180,7 +180,6 @@ Feature: Step - mergeE()
And the graph should return 1 for count of "g.E()"
And the graph should return 1 for count of "g.V()"
- @GremlinLangScriptOnly
Scenario: g_V_mergeE_inlineXemptyX_optionXonCreate_nullX
Given the empty graph
And the graph initializer of
@@ -258,7 +257,6 @@ Feature: Step - mergeE()
And the graph should return 2 for count of "g.E()"
And the graph should return 2 for count of "g.V()"
- @GremlinLangScriptOnly
Scenario: g_mergeEXnullX
Given the empty graph
And the graph initializer of
@@ -272,6 +270,7 @@ Feature: Step - mergeE()
When iterated to list
Then the traversal will raise an error with message containing text of "Out Vertex not specified"
+ @GremlinGroovyNotSupported
Scenario: g_mergeEXnullvarX
Given the empty graph
And the graph initializer of
@@ -286,6 +285,7 @@ Feature: Step - mergeE()
When iterated to list
Then the traversal will raise an error with message containing text of "Out Vertex not specified"
+ @GremlinGroovyNotSupported
Scenario: g_V_limitX1X_mergeEXnullvarX
Given the empty graph
And the graph initializer of
diff --git a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/MergeVertex.feature b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/MergeVertex.feature
index 22c1457fad..b5d211f38f 100644
--- a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/MergeVertex.feature
+++ b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/MergeVertex.feature
@@ -286,7 +286,7 @@ Feature: Step - mergeV()
Then the result should have a count of 1
And the graph should return 1 for count of "g.V()"
- @GremlinLangScriptOnly
+ @GremlinGroovyNotSupported
Scenario: g_mergeVXnullvarX
Given the empty graph
And the graph initializer of
@@ -302,7 +302,6 @@ Feature: Step - mergeV()
Then the result should have a count of 1
And the graph should return 1 for count of "g.V()"
- @GremlinLangScriptOnly
Scenario: g_V_mergeVXnullX
Given the empty graph
And the graph initializer of
@@ -955,22 +954,6 @@ Feature: Step - mergeV()
And the graph should return 1 for count of "g.V().has(\"person\",\"name\",\"allen\").has(\"age\")"
And the graph should return 3 for count of "g.V().has(\"person\",\"name\",\"allen\").properties(\"age\")"
- Scenario: g_mergeVXname_markoX_optionXonMatch_name_allen_var_singleX
- Given the empty graph
- And the graph initializer of
- """
- g.addV("person").property("name", "marko")
- """
- And using the parameter xx1 defined as "m[{\"name\":\"allen\"}]"
- And the traversal of
- """
- g.mergeV([name: "marko"]).option(Merge.onMatch, xx1, single)
- """
- When iterated to list
- Then the result should have a count of 1
- And the graph should return 0 for count of "g.V().has(\"person\",\"name\",\"marko\")"
- And the graph should return 1 for count of "g.V().has(\"person\",\"name\",\"allen\")"
-
@MultiProperties
Scenario: g_mergeVXname_markoX_optionXonMatch_name_allen_age_singleX31X_singleX
Given the empty graph
diff --git a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/sideEffect/Inject.feature b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/sideEffect/Inject.feature
index 678705d19b..7e7631599a 100644
--- a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/sideEffect/Inject.feature
+++ b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/sideEffect/Inject.feature
@@ -250,7 +250,7 @@ Feature: Step - inject()
| result |
| l[d[1].i,d[3].i,d[100].i,d[300].i] |
- @GraphComputerVerificationInjectionNotSupported @GremlinLangScriptOnly
+ @GraphComputerVerificationInjectionNotSupported
Scenario: g_injectX1_3_100_300X_listvar
Given the modern graph
And using the parameter xx1 defined as "l[d[1].i,d[3].i,d[100].i,d[300].i]"
@@ -263,7 +263,7 @@ Feature: Step - inject()
| result |
| l[d[1].i,d[3].i,d[100].i,d[300].i] |
- @GraphComputerVerificationInjectionNotSupported @GremlinLangScriptOnly
+ @GraphComputerVerificationInjectionNotSupported
Scenario: g_injectX1_3_100_300X_set
Given the modern graph
And the traversal of
@@ -275,7 +275,7 @@ Feature: Step - inject()
| result |
| s[d[100].i,d[300].i,d[1].i,d[3].i] |
- @GraphComputerVerificationInjectionNotSupported @GremlinLangScriptOnly
+ @GraphComputerVerificationInjectionNotSupported
Scenario: g_injectX1_3_100_300X_setvar
Given the modern graph
And using the parameter xx1 defined as "s[d[100].i,d[300].i,d[1].i,d[3].i]"
@@ -288,7 +288,7 @@ Feature: Step - inject()
| result |
| s[d[100].i,d[300].i,d[1].i,d[3].i] |
- @GraphComputerVerificationInjectionNotSupported @GremlinLangScriptOnly
+ @GraphComputerVerificationInjectionNotSupported
Scenario: g_injectX1_1X_set
Given the modern graph
And the traversal of
@@ -300,7 +300,7 @@ Feature: Step - inject()
| result |
| s[d[1].i] |
- @GraphComputerVerificationInjectionNotSupported @GremlinLangScriptOnly
+ @GraphComputerVerificationInjectionNotSupported
Scenario: g_injectX1_1X_setvar
Given the modern graph
And using the parameter xx1 defined as "s[d[1].i,d[1].i]"
@@ -313,7 +313,7 @@ Feature: Step - inject()
| result |
| s[d[1].i] |
- @GraphComputerVerificationInjectionNotSupported @GremlinLangScriptOnly
+ @GraphComputerVerificationInjectionNotSupported
Scenario: g_injectX_set
Given the modern graph
And using the parameter xx1 defined as "s[]"
diff --git a/hadoop-gremlin/src/test/java/org/apache/tinkerpop/gremlin/hadoop/HadoopGraphFeatureIntegrateTest.java b/hadoop-gremlin/src/test/java/org/apache/tinkerpop/gremlin/hadoop/HadoopGraphFeatureIntegrateTest.java
index d98aa132c0..7031279631 100644
--- a/hadoop-gremlin/src/test/java/org/apache/tinkerpop/gremlin/hadoop/HadoopGraphFeatureIntegrateTest.java
+++ b/hadoop-gremlin/src/test/java/org/apache/tinkerpop/gremlin/hadoop/HadoopGraphFeatureIntegrateTest.java
@@ -143,6 +143,11 @@ public class HadoopGraphFeatureIntegrateTest {
put(Constants.GREMLIN_HADOOP_JARS_IN_DISTRIBUTED_CACHE, false);
}};
}
+
+ @Override
+ public boolean useParametersLiterally() {
+ return false;
+ }
}
public static final class WorldInjectorSource implements InjectorSource {
diff --git a/neo4j-gremlin/src/test/java/org/apache/tinkerpop/gremlin/neo4j/Neo4jGraphFeatureTest.java b/neo4j-gremlin/src/test/java/org/apache/tinkerpop/gremlin/neo4j/Neo4jGraphFeatureTest.java
index b02a9fb7e0..435f48937c 100644
--- a/neo4j-gremlin/src/test/java/org/apache/tinkerpop/gremlin/neo4j/Neo4jGraphFeatureTest.java
+++ b/neo4j-gremlin/src/test/java/org/apache/tinkerpop/gremlin/neo4j/Neo4jGraphFeatureTest.java
@@ -50,7 +50,7 @@ import static org.apache.tinkerpop.gremlin.LoadGraphWith.GraphData;
@RunWith(Cucumber.class)
@CucumberOptions(
- tags = "not @RemoteOnly and not @MultiProperties and not @MetaProperties and not @GraphComputerOnly and not @AllowNullPropertyValues and not @UserSuppliedVertexPropertyIds and not @UserSuppliedEdgeIds and not @UserSuppliedVertexIds and not @TinkerServiceRegistry",
+ tags = "not @RemoteOnly and not @MultiProperties and not @MetaProperties and not @GraphComputerOnly and not @AllowNullPropertyValues and not @UserSuppliedVertexPropertyIds and not @UserSuppliedEdgeIds and not @UserSuppliedVertexIds and not @TinkerServiceRegistry and not @StepHasId",
glue = { "org.apache.tinkerpop.gremlin.features" },
objectFactory = GuiceFactory.class,
features = { "classpath:/org/apache/tinkerpop/gremlin/test/features" },
diff --git a/spark-gremlin/src/test/java/org/apache/tinkerpop/gremlin/spark/SparkGraphFeatureIntegrateTest.java b/spark-gremlin/src/test/java/org/apache/tinkerpop/gremlin/spark/SparkGraphFeatureIntegrateTest.java
index 03bd30c185..ed6f4119a7 100644
--- a/spark-gremlin/src/test/java/org/apache/tinkerpop/gremlin/spark/SparkGraphFeatureIntegrateTest.java
+++ b/spark-gremlin/src/test/java/org/apache/tinkerpop/gremlin/spark/SparkGraphFeatureIntegrateTest.java
@@ -162,6 +162,11 @@ public class SparkGraphFeatureIntegrateTest {
put(Constants.SPARK_KRYO_REGISTRATION_REQUIRED, true);
}};
}
+
+ @Override
+ public boolean useParametersLiterally() {
+ return false;
+ }
}
public static final class WorldInjectorSource implements InjectorSource {
diff --git a/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/TinkerGraphFeatureTest.java b/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/TinkerGraphFeatureTest.java
index 6df6140206..8f03a7e991 100644
--- a/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/TinkerGraphFeatureTest.java
+++ b/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/TinkerGraphFeatureTest.java
@@ -34,7 +34,6 @@ import org.junit.runner.RunWith;
glue = { "org.apache.tinkerpop.gremlin.features" },
objectFactory = TinkerGraphFeatureTest.TinkerGraphGuiceFactory.class,
features = { "classpath:/org/apache/tinkerpop/gremlin/test/features" },
-// name= {"g_VX1X_outXknowsvar_createdvarX"},
plugin = {"progress", "junit:target/cucumber.xml"})
public class TinkerGraphFeatureTest {
diff --git a/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/TinkerGraphFeatureTest.java b/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/TinkerGraphParameterizedFeatureTest.java
similarity index 89%
copy from tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/TinkerGraphFeatureTest.java
copy to tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/TinkerGraphParameterizedFeatureTest.java
index 6df6140206..e224a4a232 100644
--- a/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/TinkerGraphFeatureTest.java
+++ b/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/TinkerGraphParameterizedFeatureTest.java
@@ -32,11 +32,10 @@ import org.junit.runner.RunWith;
@CucumberOptions(
tags = "not @RemoteOnly and not @GraphComputerOnly and not @AllowNullPropertyValues",
glue = { "org.apache.tinkerpop.gremlin.features" },
- objectFactory = TinkerGraphFeatureTest.TinkerGraphGuiceFactory.class,
+ objectFactory = TinkerGraphParameterizedFeatureTest.TinkerGraphGuiceFactory.class,
features = { "classpath:/org/apache/tinkerpop/gremlin/test/features" },
-// name= {"g_VX1X_outXknowsvar_createdvarX"},
plugin = {"progress", "junit:target/cucumber.xml"})
-public class TinkerGraphFeatureTest {
+public class TinkerGraphParameterizedFeatureTest {
public static class TinkerGraphGuiceFactory extends AbstractGuiceFactory {
public TinkerGraphGuiceFactory() {
@@ -47,7 +46,7 @@ public class TinkerGraphFeatureTest {
public static final class ServiceModule extends AbstractModule {
@Override
protected void configure() {
- bind(World.class).to(TinkerWorld.TinkerGraphWorld.class);
+ bind(World.class).to(TinkerWorld.TinkerGraphParameterizedWorld.class);
}
}
}
diff --git a/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/TinkerWorld.java b/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/TinkerWorld.java
index 52fd414164..87fa570659 100644
--- a/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/TinkerWorld.java
+++ b/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/TinkerWorld.java
@@ -109,7 +109,9 @@ public abstract class TinkerWorld implements World {
public AbstractTinkerGraph open(final Configuration configuration) {
return TinkerGraph.open(configuration);
}
+ }
+ public static class TinkerGraphParameterizedWorld extends TinkerGraphWorld {
@Override
public boolean useParametersLiterally() {
return false;
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 e1d908045b..6aa8ef3f41 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
@@ -256,7 +256,6 @@ public class TinkerGraphPlayTest {
}
@Test
- @Ignore
public void testPlay6() throws Exception {
final Graph graph = TinkerGraph.open();
final GraphTraversalSource g = graph.traversal();
diff --git a/tinkergraph-gremlin/src/test/resources/META-INF/services/io.cucumber.core.backend.ObjectFactory b/tinkergraph-gremlin/src/test/resources/META-INF/services/io.cucumber.core.backend.ObjectFactory
index 1e9b622ffb..10135549c0 100644
--- a/tinkergraph-gremlin/src/test/resources/META-INF/services/io.cucumber.core.backend.ObjectFactory
+++ b/tinkergraph-gremlin/src/test/resources/META-INF/services/io.cucumber.core.backend.ObjectFactory
@@ -1,4 +1,5 @@
org.apache.tinkerpop.gremlin.tinkergraph.TinkerGraphFeatureTest$TinkerGraphGuiceFactory
+org.apache.tinkerpop.gremlin.tinkergraph.TinkerGraphParameterizedFeatureTest$TinkerGraphGuiceFactory
org.apache.tinkerpop.gremlin.tinkergraph.TinkerGraphComputerFeatureTest$TinkerGraphGuiceFactory
org.apache.tinkerpop.gremlin.tinkergraph.TinkerGraphAllowNullFeatureTest$TinkerGraphGuiceFactory
org.apache.tinkerpop.gremlin.tinkergraph.TinkerTransactionGraphFeatureTest$TinkerGraphGuiceFactory
(tinkerpop) 03/05: TINKERPOP-2959 Anonymous traversal tests
Posted by co...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
colegreer pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/tinkerpop.git
commit f6273a5bebbb938b0888942e2c0ccc2d857f3619
Author: andreachild <an...@improving.com>
AuthorDate: Tue Nov 26 18:24:30 2024 -0800
TINKERPOP-2959 Anonymous traversal tests
Added tests for anonymous traversals to TraversalRootVisitorTest which increased __.java to 96% line coverage.
---
.../gremlin/process/traversal/dsl/graph/__.java | 5 -
.../language/grammar/TraversalRootVisitorTest.java | 1574 +++++++++++++++++++-
2 files changed, 1565 insertions(+), 14 deletions(-)
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 615a3a96f1..ac882fe31a 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
@@ -26,12 +26,8 @@ import org.apache.tinkerpop.gremlin.process.traversal.Scope;
import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
import org.apache.tinkerpop.gremlin.process.traversal.step.GValue;
-import org.apache.tinkerpop.gremlin.process.traversal.step.filter.HasStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.map.FormatStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.util.HasContainer;
import org.apache.tinkerpop.gremlin.process.traversal.step.util.Tree;
import org.apache.tinkerpop.gremlin.process.traversal.traverser.util.TraverserSet;
-import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper;
import org.apache.tinkerpop.gremlin.structure.Column;
import org.apache.tinkerpop.gremlin.structure.Direction;
import org.apache.tinkerpop.gremlin.structure.Edge;
@@ -43,7 +39,6 @@ import org.apache.tinkerpop.gremlin.structure.VertexProperty;
import java.time.OffsetDateTime;
import java.util.Collection;
-import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalRootVisitorTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalRootVisitorTest.java
index 773ac6b309..f59057d017 100644
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalRootVisitorTest.java
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalRootVisitorTest.java
@@ -18,16 +18,53 @@
*/
package org.apache.tinkerpop.gremlin.language.grammar;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.function.Function;
import org.antlr.v4.runtime.CharStreams;
import org.antlr.v4.runtime.CommonTokenStream;
+import org.apache.tinkerpop.gremlin.process.traversal.DT;
+import org.apache.tinkerpop.gremlin.process.traversal.Operator;
+import org.apache.tinkerpop.gremlin.process.traversal.Order;
+import org.apache.tinkerpop.gremlin.process.traversal.P;
+import org.apache.tinkerpop.gremlin.process.traversal.Pop;
+import org.apache.tinkerpop.gremlin.process.traversal.Scope;
import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.DefaultGraphTraversal;
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.GValue;
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.WithOptions;
+import org.apache.tinkerpop.gremlin.structure.Column;
+import org.apache.tinkerpop.gremlin.structure.Direction;
+import org.apache.tinkerpop.gremlin.structure.T;
+import org.apache.tinkerpop.gremlin.structure.VertexProperty.Cardinality;
+import org.apache.tinkerpop.gremlin.structure.util.ElementHelper;
import org.apache.tinkerpop.gremlin.structure.util.empty.EmptyGraph;
-
+import org.apache.tinkerpop.gremlin.util.CollectionUtil;
+import org.apache.tinkerpop.gremlin.util.DatetimeHelper;
import org.junit.Before;
import org.junit.Test;
+import static org.apache.tinkerpop.gremlin.process.traversal.P.eq;
+import static org.apache.tinkerpop.gremlin.process.traversal.P.gt;
+import static org.apache.tinkerpop.gremlin.process.traversal.SackFunctions.Barrier.normSack;
+import static org.apache.tinkerpop.gremlin.process.traversal.Scope.global;
+import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.E;
+import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.V;
+import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.addE;
+import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.as;
+import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.both;
+import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.bothE;
+import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.constant;
+import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.has;
+import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.in;
+import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.is;
+import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.min;
+import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.out;
+import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.outE;
+import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.values;
+import static org.apache.tinkerpop.gremlin.structure.T.label;
import static org.junit.Assert.assertEquals;
public class TraversalRootVisitorTest {
@@ -37,7 +74,7 @@ public class TraversalRootVisitorTest {
@Before
public void setup() {
g = new GraphTraversalSource(EmptyGraph.instance());
- antlrToLanguage = new GremlinAntlrToJava();
+ antlrToLanguage = createAntlr(new VariableResolver.DefaultVariableResolver(ElementHelper.asMap("foo", "bar")));
}
@Test
@@ -46,14 +83,1533 @@ public class TraversalRootVisitorTest {
compare(g.V().union(__.identity().discard()), eval("g.V().union(__.identity().discard())"));
}
- private void compare(Object expected, Object actual) {
- assertEquals(((DefaultGraphTraversal) expected).asAdmin().getGremlinLang(),
- ((DefaultGraphTraversal) actual).asAdmin().getGremlinLang());
+ @Test
+ public void shouldParseChainedTraversal() {
+ // a random chain traversal.
+ compare(g.V().map(__.addE("person")), eval("g.V().map(__.addE('person'))"));
}
- private Object eval(String query) {
- final GremlinLexer lexer = new GremlinLexer(CharStreams.fromString(query));
- final GremlinParser parser = new GremlinParser(new CommonTokenStream(lexer));
- return antlrToLanguage.visit(parser.queryList());
+ @Test
+ public void shouldParseTraversalMethod_addE_String() {
+ // same with chained traversal but uses double quotes
+ compare(g.V().map(__.addE("person")), eval("g.V().map(__.addE(\"person\"))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_addE_Traversal() {
+ // same with chained traversal but uses double quotes
+ compare(g.V().map(__.addE(V().hasLabel("person").label())), eval("g.V().map(__.addE(V().hasLabel(\"person\").label()))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_addE_GValue() {
+ compare(g.V().map(__.addE(GValue.of("foo", "bar"))), eval("g.V().map(__.addE(foo))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_mergeE() {
+ compare(g.V().map(__.mergeE()), eval("g.V().map(__.mergeE())"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_mergeE_GValue() {
+ antlrToLanguage = new GremlinAntlrToJava("g", EmptyGraph.instance(), __::start, g,
+ new VariableResolver.DefaultVariableResolver(ElementHelper.asMap("foo", Collections.singletonMap("x", "y"))));
+ compare(g.V().map(__.mergeE(GValue.of("foo", Collections.singletonMap("x", "y")))), eval("g.V().map(__.mergeE(foo))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_mergeE_Traversal() {
+ compare(g.V().map(__.mergeE(__.hasLabel("person"))), eval("g.V().map(__.mergeE(__.hasLabel(\"person\")))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_mergeE_Map() {
+ compare(g.V().map(__.mergeE(CollectionUtil.asMap("x", "y"))), eval("g.V().map(__.mergeE([\"x\":\"y\"]))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_addV_Empty() {
+ compare(g.V().map(__.addV()), eval("g.V().map(__.addV())"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_addV_String() {
+ compare(g.V().map(__.addV("test")), eval("g.V().map(__.addV(\"test\"))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_addV_Traversal() {
+ compare(g.V().map(__.addV(V().hasLabel("person").label())), eval("g.V().map(__.addV(V().hasLabel(\"person\").label()))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_addV_GValue() {
+ compare(g.V().map(__.addV(GValue.of("foo", "bar"))), eval("g.V().map(__.addV(foo))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_mergeV() {
+ compare(g.V().map(__.mergeV()), eval("g.V().map(__.mergeV())"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_mergeV_GValue() {
+ antlrToLanguage = new GremlinAntlrToJava("g", EmptyGraph.instance(), __::start, g,
+ new VariableResolver.DefaultVariableResolver(ElementHelper.asMap("foo", Collections.singletonMap("x", "y"))));
+ compare(g.V().map(__.mergeV(GValue.of("foo", Collections.singletonMap("x", "y")))), eval("g.V().map(__.mergeV(foo))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_mergeV_Traversal() {
+ compare(g.V().map(__.mergeV(__.hasLabel("person"))), eval("g.V().map(__.mergeV(__.hasLabel(\"person\")))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_mergeV_Map() {
+ compare(g.V().map(__.mergeV(CollectionUtil.asMap("x", "y"))), eval("g.V().map(__.mergeV([\"x\": \"y\"]))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_aggregate() {
+ compare(g.V().map(__.aggregate("test")), eval("g.V().map(__.aggregate('test'))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_aggregate_Scope() {
+ compare(g.V().map(__.aggregate(global, "test")), eval("g.V().map(__.aggregate(global, 'test'))"));
+ compare(g.V().map(__.aggregate(Scope.local, "test")), eval("g.V().map(__.aggregate(Scope.local, 'test'))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_all_P() {
+ compare(g.V().map(__.id().fold().all(gt(1))), eval("g.V().map(__.id().fold().all(gt(1)))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_and() {
+ compare(g.V().map(__.and(outE("knows"))), eval("g.V().map(__.and(outE('knows')))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_any_P() {
+ compare(g.V().map(__.id().fold().any(gt(1))), eval("g.V().map(__.id().fold().any(gt(1)))"));
+ }
+ @Test
+ public void shouldParseTraversalMethod_as() {
+ compare(g.V().map(__.as("test")), eval("g.V().map(__.as('test'))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_barrier_Consumer() {
+ compare(g.V().map(__.barrier(normSack)), eval("g.V().map(__.barrier(normSack))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_barrier_Empty() {
+ compare(g.V().map(__.barrier()), eval("g.V().map(__.barrier())"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_barrier_int() {
+ compare(g.V().map(__.barrier(4)), eval("g.V().map(__.barrier(4))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_both_Empty() {
+ compare(g.V().map(__.both()), eval("g.V().map(__.both())"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_both_SingleString() {
+ compare(g.V().map(__.both("test")), eval("g.V().map(__.both('test'))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_both_MultiString() {
+ compare(g.V().map(__.both("a", "b")), eval("g.V().map(__.both('a', 'b'))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_both_GValue() {
+ compare(g.V().map(__.both(GValue.ofString("foo", "bar"))), eval("g.V().map(__.both(foo))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_bothE() {
+ compare(g.V().map(__.bothE("test")), eval("g.V().map(__.bothE('test'))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_bothE_GValue() {
+ compare(g.V().map(__.bothE(GValue.ofString("foo", "bar"))), eval("g.V().map(__.bothE(foo))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_bothV() {
+ compare(g.V().map(__.bothV()), eval("g.V().map(__.bothV())"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_branch_Traversal() {
+ compare(g.V().map(__.branch(values("name"))), eval("g.V().map(__.branch(values('name')))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_by_Comparator() {
+ compare(g.V().map(__.order().by(Order.asc)), eval("g.V().map(__.order().by(asc))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_by_Empty() {
+ compare(g.V().map(__.cyclicPath().by()), eval("g.V().map(__.cyclicPath().by())"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_by_Function() {
+ compare(g.V().map(__.order().by(T.id)), eval("g.V().map(__.order().by(id))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_by_Function_Comparator() {
+ compare(g.V().map(__.order().by(Column.keys, Order.asc)), eval("g.V().map(__.order().by(keys, asc))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_by_Order() {
+ compare(g.V().map(__.order().by(Order.shuffle)), eval("g.V().map(__.order().by(shuffle))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_by_String() {
+ compare(g.V().map(__.order().by("name")), eval("g.V().map(__.order().by('name'))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_by_String_Comparator() {
+ compare(g.V().map(__.order().by("name", Order.asc)), eval("g.V().map(__.order().by('name', asc))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_by_T() {
+ compare(g.V().map(__.order().by(T.id)), eval("g.V().map(__.order().by(id))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_by_Traversal() {
+ compare(g.V().map(__.group().by(bothE().count())), eval("g.V().map(__.group().by(bothE().count()))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_by_Traversal_Comparator() {
+ compare(g.V().map(__.order().by(bothE().count(), Order.asc)), eval("g.V().map(__.order().by(bothE().count(), asc))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_cap() {
+ compare(g.V().map(__.cap("test")), eval("g.V().map(__.cap('test'))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_choose_Function() {
+ compare(g.V().map(__.choose((Function) label)), eval("g.V().map(__.choose(label))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_choose_Predicate() {
+ compare(g.V().map(__.choose(P.eq("test"), out("knows"))), eval("g.V().map(__.choose(P.eq(\"test\"), out(\"knows\")))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_choose_Predicate_Traversal() {
+ compare(g.V().map(__.choose(is(12), values("age"))), eval("g.V().map(__.choose(is(12), values(\"age\")))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_choose_Predicate_Traversal_Traversal() {
+ compare(g.V().map(__.choose(is(12), values("age"), values("count"))),
+ eval("g.V().map(__.choose(is(12), values(\"age\"), values(\"count\")))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_choose_Traversal() {
+ compare(g.V().map(__.choose(values("age"))), eval("g.V().map(__.choose(values('age')))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_choose_Traversal_Traversal() {
+ compare(g.V().map(__.choose(values("age"), bothE())), eval("g.V().map(__.choose(values('age'), bothE()))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_choose_Traversal_Traversal_Traversal() {
+ compare(g.V().map(__.choose(values("age"), bothE(), bothE())), eval("g.V().map(__.choose(values('age'), bothE(), bothE()))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_coalesce() {
+ compare(g.V().map(__.coalesce(outE("knows"))), eval("g.V().map(__.coalesce(outE('knows')))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_coin() {
+ compare(g.V().map(__.coin(2.5)), eval("g.V().map(__.coin(2.5))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_coin_GValue() {
+ antlrToLanguage = createAntlr(new VariableResolver.DefaultVariableResolver(ElementHelper.asMap("probability", 2.5)));
+ compare(g.V().map(__.coin(GValue.of("probability", 2.5))), eval("g.V().map(__.coin(probability))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_combine_Object() {
+ final ArrayList<Integer> list = new ArrayList<>();
+ list.add(1);
+ list.add(2);
+ compare(g.V().map(__.values("name").fold().combine(list)),
+ eval("g.V().map(__.values(\"name\").fold().combine([1,2]))"));
+ compare(g.V().map(__.values("name").fold().combine(V().fold())),
+ eval("g.V().map(__.values(\"name\").fold().combine(__.V().fold()))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_constant() {
+ compare(g.V().map(__.constant("yigit")), eval("g.V().map(__.constant('yigit'))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_constant_gValue() {
+ compare(g.V().map(__.constant(GValue.of("foo", "bar"))), eval("g.V().map(__.constant(foo))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_count_Empty() {
+ compare(g.V().map(__.count()), eval("g.V().map(__.count())"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_count_Scope() {
+ compare(g.V().map(__.count(global)), eval("g.V().map(__.count(global))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_cyclicPath() {
+ compare(g.V().map(__.cyclicPath()), eval("g.V().map(__.cyclicPath())"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_dedup_Scope_String() {
+ compare(g.V().map(__.dedup(Scope.local, "age")), eval("g.V().map(__.dedup(local, 'age'))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_dedup_String() {
+ compare(g.V().map(__.dedup()), eval("g.V().map(__.dedup())"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_difference_Object() {
+ final ArrayList<Integer> list = new ArrayList<>();
+ list.add(1);
+ list.add(2);
+ compare(g.V().map(__.values("name").fold().difference(list)),
+ eval("g.V().map(__.values(\"name\").fold().difference([1,2]))"));
+ compare(g.V().map(__.values("name").fold().difference(V().fold())),
+ eval("g.V().map(__.values(\"name\").fold().difference(__.V().fold()))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_disjunct_Object() {
+ final ArrayList<Integer> list = new ArrayList<>();
+ list.add(1);
+ list.add(2);
+ compare(g.V().map(__.values("name").fold().disjunct(list)),
+ eval("g.V().map(__.values(\"name\").fold().disjunct([1,2]))"));
+ compare(g.V().map(__.values("name").fold().disjunct(V().fold())),
+ eval("g.V().map(__.values(\"name\").fold().disjunct(__.V().fold()))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_drop() {
+ compare(g.V().map(__.drop()), eval("g.V().map(__.drop())"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_emit_Empty() {
+ compare(g.V().map(__.emit()), eval("g.V().map(__.emit())"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_emit_Predicate() {
+ compare(g.V().map(__.repeat(out()).emit(is("asd"))), eval("g.V().map(__.repeat(out()).emit(is(\"asd\")))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_emit_Traversal() {
+ compare(g.V().map(__.emit(has("name"))), eval("g.V().map(__.emit(has('name')))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_filter_Predicate() {
+ compare(g.V().map(__.repeat(out()).filter(is("2"))), eval("g.V().map(__.repeat(out()).filter(is(\"2\")))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_filter_Traversal() {
+ compare(g.V().map(__.filter(has("name"))), eval("g.V().map(__.filter(has('name')))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_flatMap_Traversal() {
+ compare(g.V().map(__.flatMap(has("name"))), eval("g.V().map(__.flatMap(has('name')))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_fold_Empty() {
+ compare(g.V().map(__.fold()), eval("g.V().map(__.fold())"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_fold_Function() {
+ compare(g.V().values("age").map(__.fold(0, Operator.max)), eval("g.V().values('age').map(__.fold(0, max))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_fold_Object_BiFunction() {
+ compare(g.V().map(__.values("age").fold(0, Operator.max)), eval("g.V().map(__.values('age').fold(0, max))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_from_String() {
+ compare(g.V().map(__.cyclicPath().from("name")), eval("g.V().map(__.cyclicPath().from('name'))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_from_Traversal() {
+ compare(g.V().map(__.addE("as").from(V())), eval("g.V().map(__.addE('as').from(V()))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_group_Empty() {
+ compare(g.V().map(__.group()), eval("g.V().map(__.group())"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_group_String() {
+ compare(g.V().map(__.group("age")), eval("g.V().map(__.group('age'))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_groupCount_Empty() {
+ compare(g.V().map(__.groupCount()), eval("g.V().map(__.groupCount())"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_groupCount_String() {
+ compare(g.V().map(__.groupCount("age")), eval("g.V().map(__.groupCount('age'))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_has_String() {
+ compare(g.V().map(__.has("age")), eval("g.V().map(__.has('age'))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_has_String_Object() {
+ compare(g.V().map(__.has("age", 132)), eval("g.V().map(__.has('age', 132))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_has_String_P() {
+ compare(g.V().map(__.has("a", eq("b"))), eval("g.V().map(__.has(\"a\", eq(\"b\")))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_has_String_String_Object() {
+ compare(g.V().map(__.has("a", "b", 3)), eval("g.V().map(__.has(\"a\", \"b\", 3))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_has_String_String_P() {
+ compare(g.V().map(__.has("a", "b", eq("c"))), eval("g.V().map(__.has(\"a\", \"b\", eq(\"c\")))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_has_String_Traversal() {
+ compare(g.V().map(__.has("age", bothE())), eval("g.V().map(__.has('age', bothE()))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_has_T_Object() {
+ compare(g.V().map(__.has(T.id, 6)), eval("g.V().map(__.has(id, 6))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_has_T_P() {
+ compare(g.V().map(__.has(T.id, eq("asd"))), eval("g.V().map(__.has(id, eq('asd')))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_has_T_Traversal() {
+ compare(g.V().map(__.has(T.id, bothE())), eval("g.V().map(__.has(id, bothE()))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_has_GValue() {
+ compare(g.V().map(__.has(GValue.of("foo", "bar"), "b", eq("c"))), eval("g.V().map(__.has(foo, \"b\", eq(\"c\")))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_has_GValue_String_String() {
+ compare(g.V().map(__.has(GValue.of("foo", "bar"), "b", "c")), eval("g.V().map(__.has(foo, \"b\", \"c\"))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_hasId_Object_Object() {
+ compare(g.V().map(__.hasId(3, 4)), eval("g.V().map(__.hasId(3, 4))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_hasId_P() {
+ compare(g.V().map(__.hasId(gt(4))), eval("g.V().map(__.hasId(gt(4)))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_hasKey_P() {
+ compare(g.V().map(__.hasKey(eq("asd"))), eval("g.V().map(__.hasKey(eq(\"asd\")))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_hasKey_String_String() {
+ compare(g.V().map(__.hasKey("age")), eval("g.V().map(__.hasKey('age'))"));
+ compare(g.V().map(__.hasKey("age", "3")), eval("g.V().map(__.hasKey('age', '3'))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_hasLabel_P() {
+ compare(g.V().map(__.hasLabel(eq("asd"))), eval("g.V().map(__.hasLabel(eq(\"asd\")))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_hasLabel_String_String() {
+ compare(g.V().map(__.hasLabel("age")), eval("g.V().map(__.hasLabel('age'))"));
+ compare(g.V().map(__.hasLabel("age", "3")), eval("g.V().map(__.hasLabel('age', '3'))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_hasLabel_GValue() {
+ compare(g.V().map(__.hasLabel(GValue.of("foo", "bar"))), eval("g.V().map(__.hasLabel(foo))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_hasNot() {
+ compare(g.V().map(__.hasNot("know")), eval("g.V().map(__.hasNot('know'))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_hasValue_Object_Object() {
+ compare(g.V().map(__.hasValue(3, 4)), eval("g.V().map(__.hasValue(3, 4))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_hasValue_P() {
+ compare(g.V().map(__.hasValue(eq(2))), eval("g.V().map(__.hasValue(eq(2)))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_id() {
+ compare(g.V().map(__.id()), eval("g.V().map(__.id())"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_identity() {
+ compare(g.V().map(__.identity()), eval("g.V().map(__.identity())"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_in_String() {
+ compare(g.V().map(__.in("created")), eval("g.V().map(__.in('created'))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethodl_in_GValue() {
+ compare(g.V().map(__.in(GValue.ofString("foo", "bar"))), eval("g.V().map(__.in(foo))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_in() {
+ compare(g.V().map(__.in()), eval("g.V().map(__.in())"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_index() {
+ compare(g.V().map(__.hasLabel("software").index()), eval("g.V().map(__.hasLabel('software').index())"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_inE() {
+ compare(g.V().map(__.inE()), eval("g.V().map(__.inE())")); }
+
+ @Test
+ public void shouldParseTraversalMethod_inE_String() {
+ compare(g.V().map(__.inE("created")), eval("g.V().map(__.inE('created'))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_inE_GValue() {
+ compare(g.V().map(__.inE(GValue.ofString("foo", "bar"))), eval("g.V().map(__.inE(foo))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_inV() {
+ compare(g.V().map(__.inV()), eval("g.V().map(__.inV())"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_inject() {
+ compare(g.V(4).out().values("name").map(__.inject("daniel")),
+ eval("g.V(4).out().values(\"name\").map(__.inject(\"daniel\"))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_intersect_Object() {
+ final ArrayList<Integer> list = new ArrayList<>();
+ list.add(1);
+ list.add(2);
+ compare(g.V().map(__.values("name").fold().intersect(list)),
+ eval("g.V().map(__.values(\"name\").fold().intersect([1,2]))"));
+ compare(g.V().map(__.values("name").fold().intersect(V().fold())),
+ eval("g.V().map(__.values(\"name\").fold().intersect(__.V().fold()))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_is_Object() {
+ compare(g.V().map(__.is(4)), eval("g.V().map(__.is(4))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_is_P() {
+ compare(g.V().map(__.is(gt(4))), eval("g.V().map(__.is(gt(4)))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_conjoin_Object() {
+ compare(g.V().map(__.values("name").fold().conjoin(";")),
+ eval("g.V().map(__.values(\"name\").fold().conjoin(\";\"))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_key() {
+ compare(g.V().map(__.key()), eval("g.V().map(__.key())"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_label() {
+ compare(g.V().map(__.label()), eval("g.V().map(__.label())"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_limit_Scope_long() {
+ compare(g.V().map(__.limit(global, 3)), eval("g.V().map(__.limit(global, 3))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_limit_long() {
+ compare(g.V().map(__.limit(2)), eval("g.V().map(__.limit(2))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_local() {
+ compare(g.V().map(__.local(bothE())), eval("g.V().map(__.local(bothE()))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_loops() {
+ compare(g.V().map(__.loops()), eval("g.V().map(__.loops())"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_loops_String() {
+ compare(g.V().map(__.loops("test")), eval("g.V().map(__.loops(\"test\"))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_map_Traversal() {
+ compare(g.V().map(__.map(bothE())), eval("g.V().map(__.map(bothE()))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_flatMap() {
+ compare(g.V().map(__.flatMap(bothE())), eval("g.V().map(__.flatMap(bothE()))")); }
+
+ @Test
+ public void shouldParseTraversalMethod_match() {
+ compare(g.V().map(__.match(as("a"), as("b"))), eval("g.V().map(__.match(as(\"a\"), as(\"b\")))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_max_Empty() {
+ compare(g.V().map(__.max()), eval("g.V().map(__.max())"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_max_Scope() {
+ compare(g.V().map(__.max(Scope.local)), eval("g.V().map(__.max(local))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_math() {
+ compare(g.V().count().map(__.math("_ + 10")), eval("g.V().count().map(__.math('_ + 10'))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_mean_Empty() {
+ compare(g.V().map(__.mean()), eval("g.V().map(__.mean())"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_mean_Scope() {
+ compare(g.V().map(__.mean(global)), eval("g.V().map(__.mean(global))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_merge_Object() {
+ final ArrayList<Integer> list = new ArrayList<>();
+ list.add(1);
+ list.add(2);
+ compare(g.V().map(__.values("name").fold().merge(list)),
+ eval("g.V().map(__.values(\"name\").fold().merge([1,2]))"));
+ compare(g.V().map(__.values("name").fold().merge(V().fold())),
+ eval("g.V().map(__.values(\"name\").fold().merge(__.V().fold()))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_min_Empty() {
+ compare(g.V().map(__.min()), eval("g.V().map(__.min())"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_min_Scope() {
+ compare(g.V().map(__.min(Scope.local)), eval("g.V().map(__.min(local))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_not() {
+ compare(g.V().map(__.not(both())), eval("g.V().map(__.not(both()))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_option_Object_Traversal() {
+ compare(g.V().map(__.branch(values("name")).option(2, bothE())),
+ eval("g.V().map(__.branch(values(\"name\")).option(2, bothE()))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_option_Traversal() {
+ compare(g.V().map(__.branch(values("name")).option(both())), eval("g.V().map(__.branch(values(\"name\")).option(both()))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_optional() {
+ compare(g.V().map(__.optional(min())), eval("g.V().map(__.optional(min()))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_or() {
+ compare(g.V().map(__.or(as("a"), as("b"))), eval("g.V().map(__.or(as(\"a\"), as(\"b\")))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_order_Empty() {
+ compare(g.V().map(__.order()), eval("g.V().map(__.order())"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_order_Scope() {
+ compare(g.V().map(__.order(global)), eval("g.V().map(__.order(global))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_otherV() {
+ compare(g.V().map(__.otherV()), eval("g.V().map(__.otherV())"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_out_String() {
+ compare(g.V().map(__.out("a", "b")), eval("g.V().map(__.out(\"a\", \"b\"))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_out_GValue() {
+ compare(g.V().map(__.out(GValue.ofString("foo", "bar"))), eval("g.V().map(__.out(foo))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_out() {
+ compare(g.V().map(__.out()), eval("g.V().map(__.out())"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_outE() {
+ compare(g.V().map(__.outE()), eval("g.V().map(__.outE())"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_outE_String() {
+ compare(g.V().map(__.outE("a", "b")), eval("g.V().map(__.outE(\"a\", \"b\"))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_outE_GValue() {
+ compare(g.V().map(__.outE(GValue.ofString("foo", "bar"))), eval("g.V().map(__.outE(foo))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_outV() {
+ compare(g.V().map(__.outV()), eval("g.V().map(__.outV())"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_path() {
+ compare(g.V().map(__.path()), eval("g.V().map(__.path())"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_product_Object() {
+ final ArrayList<Integer> list = new ArrayList<>();
+ list.add(1);
+ list.add(2);
+ compare(g.V().map(__.values("name").fold().product(list)),
+ eval("g.V().map(__.values(\"name\").fold().product([1,2]))"));
+ compare(g.V().map(__.values("name").fold().product(V().fold())),
+ eval("g.V().map(__.values(\"name\").fold().product(__.V().fold()))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_project() {
+ compare(g.V().map(__.project("neptune")), eval("g.V().map(__.project('neptune'))"));
+ compare(g.V().map(__.project("neptune", "uranus")), eval("g.V().map(__.project('neptune', 'uranus'))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_properties() {
+ compare(g.V().map(__.properties("venus", "mars")), eval("g.V().map(__.properties('venus', 'mars'))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_property_Cardinality_Object_Object_Object() {
+ compare(g.V().map(__.property(Cardinality.list,1,2,"key", 4)),
+ eval("g.V().map(__.property(list, 1,2,'key',4))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_property_Object_Object_Object() {
+ compare(g.V().map(__.property(1,2,"key", 4)), eval("g.V().map(__.property(1,2,'key',4))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_property_Object() {
+ final LinkedHashMap<Object, Object> map = new LinkedHashMap<>();
+ map.put("key", "foo");
+ map.put("key1", "bar");
+ compare(g.V().map(__.property(map)), eval("g.V().map(__.property(['key': 'foo', 'key1': 'bar']))"));
+ map.clear();
+ map.put("name", "foo");
+ map.put("age", 42);
+ compare(g.V().map(__.addV().property(map)), eval("g.V().map(__.addV().property([\"name\": \"foo\", \"age\": 42 ]))"));
+ map.clear();
+ map.put(label, "foo");
+ map.put("age", 42);
+ compare(g.V().map(__.addV().property(map)), eval("g.V().map(__.addV().property([T.label: \"foo\", \"age\": 42 ]))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_property_Cardinality_Object() {
+ final LinkedHashMap<Object, Object> map = new LinkedHashMap<>();
+ map.put("key", "foo");
+ map.put("key1", "bar");
+ compare(g.V().map(__.property(Cardinality.list, map)), eval("g.V().map(__.property(list, ['key': 'foo', 'key1': 'bar']))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_propertyMap() {
+ compare(g.V().map(__.propertyMap("venus", "mars")), eval("g.V().map(__.propertyMap('venus', 'mars'))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_elementMap() {
+ compare(g.V().map(__.elementMap("test")), eval("g.V().map(__.elementMap(\"test\"))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_range_Scope_long_long() {
+ compare(g.V().map(__.range(global, 3,5)), eval("g.V().map(__.range(global, 3,5))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_range_long_long() {
+ compare(g.V().map(__.range(3,5)), eval("g.V().map(__.range(3,5))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_repeat() {
+ compare(g.V().map(__.repeat(both())), eval("g.V().map(__.repeat(both()))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_repeat_String_Traversal() {
+ compare(g.V().map(__.repeat("test", both())), eval("g.V().map(__.repeat(\"test\", both()))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_sack_BiFunction() {
+ compare(g.V().map(__.sack()), eval("g.V().map(__.sack())"));
+ compare(g.V().map(__.sack(Operator.addAll)), eval("g.V().map(__.sack(addAll))"));
+ compare(g.V().map(__.sack(Operator.and)), eval("g.V().map(__.sack(and))"));
+ compare(g.V().map(__.sack(Operator.assign)), eval("g.V().map(__.sack(assign))"));
+ compare(g.V().map(__.sack(Operator.div)), eval("g.V().map(__.sack(div))"));
+ compare(g.V().map(__.sack(Operator.max)), eval("g.V().map(__.sack(max))"));
+ compare(g.V().map(__.sack(Operator.min)), eval("g.V().map(__.sack(min))"));
+ compare(g.V().map(__.sack(Operator.minus)), eval("g.V().map(__.sack(minus))"));
+ compare(g.V().map(__.sack(Operator.mult)), eval("g.V().map(__.sack(mult))"));
+ compare(g.V().map(__.sack(Operator.or)), eval("g.V().map(__.sack(or))"));
+ compare(g.V().map(__.sack(Operator.sum)), eval("g.V().map(__.sack(sum))"));
+ compare(g.V().map(__.sack(Operator.sumLong)), eval("g.V().map(__.sack(sumLong))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_sack_Empty() {
+ compare(g.V().map(__.sack()), eval("g.V().map(__.sack())"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_sample_Scope_int() {
+ compare(g.V().map(__.sample(global, 2)), eval("g.V().map(__.sample(global, 2))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_sample_int() {
+ compare(g.V().map(__.sample(4)), eval("g.V().map(__.sample(4))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_select_Column() {
+ compare(g.V().map(__.select(Column.keys)), eval("g.V().map(__.select(keys))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_select_Pop_String() {
+ compare(g.V().map(__.select(Pop.first, "asd")), eval("g.V().map(__.select(first, 'asd'))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_select_Pop_String_String_String() {
+ compare(g.V().map(__.select(Pop.all, "a", "b", "c", "d")), eval("g.V().map(__.select(all, \"a\", \"b\", \"c\", \"d\"))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_select_Pop_Traversal() {
+ compare(g.V().map(__.select(Pop.all, out().properties("a"))), eval("g.V().map(__.select(all, out().properties(\"a\")))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_select_String() {
+ compare(g.V().map(__.select("yigit")), eval("g.V().map(__.select(\"yigit\"))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_select_String_String_String() {
+ compare(g.V().map(__.select("a", "b", "c", "d")), eval("g.V().map(__.select(\"a\", \"b\", \"c\", \"d\"))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_select_Traversal() {
+ compare(g.V().map(__.select(out().properties("a"))), eval("g.V().map(__.select(out().properties(\"a\")))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_sideEffect() {
+ compare(g.V().map(__.sideEffect(bothE())), eval("g.V().map(__.sideEffect(bothE()))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_simplePath() {
+ compare(g.V().map(__.simplePath()), eval("g.V().map(__.simplePath())"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_skip_Scope_long() {
+ compare(g.V().map(__.skip(global, 8)), eval("g.V().map(__.skip(global, 8))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_skip_long() {
+ compare(g.V().map(__.skip(8)), eval("g.V().map(__.skip(8))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_store() {
+ compare(g.V().map(__.store("asd")), eval("g.V().map(__.store(\"asd\"))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_subgraph() {
+ compare(g.V().map(__.subgraph("asd")), eval("g.V().map(__.subgraph('asd'))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_sum_Empty() {
+ compare(g.V().map(__.sum()), eval("g.V().map(__.sum())"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_sum_Scope() {
+ compare(g.V().map(__.sum(Scope.local)), eval("g.V().map(__.sum(local))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_tail_Empty() {
+ compare(g.V().map(__.tail()), eval("g.V().map(__.tail())"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_tail_Scope() {
+ compare(g.V().map(__.tail(Scope.local)), eval("g.V().map(__.tail(local))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_tail_Scope_long() {
+ compare(g.V().map(__.tail(Scope.local, 3)), eval("g.V().map(__.tail(local, 3))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_tail_long() {
+ compare(g.V().map(__.tail(4)), eval("g.V().map(__.tail(4))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_timeLimit() {
+ compare(g.V().map(__.timeLimit(5)), eval("g.V().map(__.timeLimit(5))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_times() {
+ compare(g.V().map(__.times(6)), eval("g.V().map(__.times(6))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_to_Direction_String() {
+ compare(g.V().map(__.to(Direction.IN, "asd")), eval("g.V().map(__.to(IN, 'asd'))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_GValue() {
+ compare(g.V().map(__.to(Direction.OUT, GValue.ofString("foo", "bar"))), eval("g.V().map(__.to(Direction.OUT,foo))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_Direction() {
+ compare(g.V().map(__.to(Direction.OUT)), eval("g.V().map(__.to(Direction.OUT))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_to_String() {
+ compare(g.V().map(__.path().to("home")), eval("g.V().map(__.path().to(\"home\"))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_to_Traversal() {
+ compare(g.V().map(__.addE("as").to(V())), eval("g.V().map(__.addE('as').to(V()))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_toE() {
+ compare(g.V().map(__.toE(Direction.IN, "asd")), eval("g.V().map(__.toE(IN, 'asd'))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_toE_Direction() {
+ compare(g.V().map(__.toE(Direction.OUT)), eval("g.V().map(__.toE(Direction.OUT))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_toE_Direction_GValue() {
+ compare(g.V().map(__.toE(Direction.OUT, GValue.ofString("foo", "bar"))), eval("g.V().map(__.toE(Direction.OUT,foo))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_toV() {
+ compare(g.V().map(__.toV(Direction.IN)), eval("g.V().map(__.toV(IN))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_tree_Empty() {
+ compare(g.V().map(__.tree()), eval("g.V().map(__.tree())"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_tree_String() {
+ compare(g.V().map(__.tree("hello")), eval("g.V().map(__.tree(\"hello\"))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_unfold() {
+ compare(g.V().map(__.unfold()), eval("g.V().map(__.unfold())"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_union() {
+ compare(g.V().map(__.union(in(), out())), eval("g.V().map(__.union(in(), out()))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_until_Predicate() {
+ compare(g.V().map(__.until(is("123"))), eval("g.V().map(__.until(is(\"123\")))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_until_Traversal() {
+ compare(g.V().map(__.until(has("ripple"))), eval("g.V().map(__.until(has(\"ripple\")))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_value() {
+ compare(g.V().map(__.value()), eval("g.V().map(__.value())"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_valueMap_String() {
+ compare(g.V().map(__.valueMap("yigit")), eval("g.V().map(__.valueMap(\"yigit\"))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_valueMap_boolean_String1() {
+ compare(g.V().map(__.valueMap(true)), eval("g.V().map(__.valueMap(true))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_valueMap_boolean_String2() {
+ compare(g.V().map(__.valueMap(true, "that")), eval("g.V().map(__.valueMap(true, \"that\"))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_valueMap_withOption() {
+ compare(g.V().map(__.valueMap().with(WithOptions.tokens, WithOptions.labels)),
+ eval("g.V().map(__.valueMap().with(WithOptions.tokens, WithOptions.labels))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_values() {
+ compare(g.V().map(__.values("earth", "mars")), eval("g.V().map(__.values(\"earth\", \"mars\"))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_where_P() {
+ compare(g.V().map(__.where(eq("123"))), eval("g.V().map(__.where(eq(\"123\")))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_where_String_P() {
+ compare(g.V().map(__.where("age", eq("123"))), eval("g.V().map(__.where('age', eq(\"123\")))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_where_Traversal() {
+ compare(g.V().map(__.where(both())), eval("g.V().map(__.where(both()))"));
+ }
+
+ @Test
+ public void visitTraversalMethod_with_String() {
+ compare(g.V().map(__.valueMap().with("hakuna")), eval("g.V().map(__.valueMap().with('hakuna'))"));
+ }
+
+ @Test
+ public void visitTraversalMethod_with_String_Object() {
+ compare(g.V().map(__.index().with(WithOptions.indexer, WithOptions.map)),
+ eval("g.V().map(__.index().with(WithOptions.indexer, WithOptions.map))"));
+ }
+
+ @Test
+ public void visitTraversalMethod_withOptionsTokensAll() {
+ compare(g.V().map(__.has("code","AUS").valueMap().with(WithOptions.tokens,WithOptions.all).unfold()),
+ eval("g.V().map(__.has('code','AUS').valueMap().with(WithOptions.tokens,WithOptions.all).unfold())"));
+ }
+
+ @Test
+ public void visitTraversalMethod_withOptionsTokensNone() {
+ compare(g.V().map(__.has("code","AUS").valueMap().with(WithOptions.tokens,WithOptions.none)),
+ eval("g.V().map(__.has('code','AUS').valueMap().with(WithOptions.tokens,WithOptions.none))"));
+ }
+
+ @Test
+ public void visitTraversalMethod_withOptionsTokensIds() {
+ compare(g.V().map(__.has("code","AUS").valueMap().with(WithOptions.tokens,WithOptions.ids)),
+ eval("g.V().map(__.has('code','AUS').valueMap().with(WithOptions.tokens,WithOptions.ids))"));
+ }
+
+ @Test
+ public void visitTraversalMethod_withOptionsTokensLabels() {
+ compare(g.V().map(__.has("code","AUS").valueMap().with(WithOptions.tokens,WithOptions.labels)),
+ eval("g.V().map(__.has('code','AUS').valueMap().with(WithOptions.tokens,WithOptions.labels))"));
+ }
+
+ @Test
+ public void visitTraversalMethod_withOptionsTokensKeys() {
+ compare(g.V().map(__.has("code","AUS").valueMap().with(WithOptions.tokens,WithOptions.keys)),
+ eval("g.V().map(__.has('code','AUS').valueMap().with(WithOptions.tokens,WithOptions.keys))"));
+ }
+
+ @Test
+ public void visitTraversalMethod_withOptionsTokensValues() {
+ compare(g.V().map(__.has("code","AUS").valueMap().with(WithOptions.tokens,WithOptions.values)),
+ eval("g.V().map(__.has('code','AUS').valueMap().with(WithOptions.tokens,WithOptions.values))"));
+ }
+
+ @Test
+ public void visitTraversalMethod_withOptionsIndexerList() {
+ compare(g.V().map(__.has("code","AUS").valueMap().with(WithOptions.indexer,WithOptions.list)),
+ eval("g.V().map(__.has('code','AUS').valueMap().with(WithOptions.indexer,WithOptions.list))"));
+ }
+ @Test
+ public void visitTraversalMethod_withOptionsIndexerMap() {
+ compare(g.V().map(__.has("code","AUS").valueMap().with(WithOptions.indexer,WithOptions.map)),
+ eval("g.V().map(__.has('code','AUS').valueMap().with(WithOptions.indexer,WithOptions.map))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_midTraversal_E() {
+ compare(g.V().map(__.inject(1).E()), eval("g.V().map(__.inject(1).E())"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_midTraversal_E_multipleArgs() {
+ compare(g.V().map(__.inject(1).E(2,null)), eval("g.V().map(__.inject(1).E(2,null))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_midTraversal_E_spawning() {
+ compare(g.V().map(__.coalesce(E(),addE("person"))), eval("g.V().map(__.coalesce(__.E(),__.addE('person')))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_midTraversal_E_multipleArgs_spawning() {
+ compare(g.V().map(__.coalesce(E(1,2),addE("person"))),
+ eval("g.V().map(__.coalesce(__.E(1,2),__.addE('person')))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_concat_Empty() {
+ compare(g.V().map(__.concat()), eval("g.V().map(__.concat())"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_concat_multipleStringArgs() {
+ compare(g.V().map(__.concat("hello", "world")), eval("g.V().map(__.concat('hello', 'world'))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_concat_traversal() {
+ compare(g.V().map(__.concat(constant("hello"))),
+ eval("g.V().map(__.concat(__.constant('hello')))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_concat_multipleTraversalArgs() {
+ compare(g.V().map(__.concat(constant("hello"), constant("world"))),
+ eval("g.V().map(__.concat(__.constant('hello'), __.constant('world')))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_concat_ArgsWithNulls() {
+ compare(g.V().map(__.concat(null, "hello")),
+ eval("g.V().map(__.concat(null, 'hello'))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_asString_Empty() {
+ compare(g.V().map(__.asString()), eval("g.V().map(__.asString())"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_asString__Scope() {
+ compare(g.V().map(__.asString(Scope.global)), eval("g.V().map(__.asString(Scope.global))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_format_String() {
+ compare(g.V().map(__.format("Hello %{name}")), eval("g.V().map(__.format(\"Hello %{name}\"))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_toLower_Empty() {
+ compare(g.V().map(__.toLower()), eval("g.V().map(__.toLower())"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_toLower_Scope() {
+ compare(g.V().map(__.toLower(Scope.global)), eval("g.V().map(__.toLower(Scope.global))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_toUpper_Empty() {
+ compare(g.V().map(__.toUpper()), eval("g.V().map(__.toUpper())"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_toUpper_Scope() {
+ compare(g.V().map(__.toUpper(Scope.global)), eval("g.V().map(__.toUpper(Scope.global))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_trim() {
+ compare(g.V().map(__.trim()), eval("g.V().map(__.trim())"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_trim_Scope() {
+ compare(g.V().map(__.trim(Scope.global)), eval("g.V().map(__.trim(Scope.global))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_lTrim() {
+ compare(g.V().map(__.lTrim()), eval("g.V().map(__.lTrim())"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_lTrim_Scope() {
+ compare(g.V().map(__.lTrim(Scope.global)), eval("g.V().map(__.lTrim(Scope.global))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_rTrim() {
+ compare(g.V().map(__.rTrim()), eval("g.V().map(__.rTrim())"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_rTrim_Scope() {
+ compare(g.V().map(__.rTrim(Scope.global)), eval("g.V().map(__.rTrim(Scope.global))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_reverse() {
+ compare(g.V().map(__.reverse()), eval("g.V().map(__.reverse())"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_length_Empty() {
+ compare(g.V().map(__.length()), eval("g.V().map(__.length())"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_length_Scope() {
+ compare(g.V().map(__.length(Scope.global)), eval("g.V().map(__.length(Scope.global))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_replace_string_string() {
+ compare(g.V().map(__.replace("a", "b")), eval("g.V().map(__.replace('a', 'b'))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_replace_Scope() {
+ compare(g.V().map(__.replace(Scope.global, "hello", "world")), eval("g.V().map(__.replace(Scope.global, \"hello\", \"world\"))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_split_string() {
+ compare(g.V().map(__.split("a")), eval("g.V().map(__.split('a'))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_split_Scope() {
+ compare(g.V().map(__.split(Scope.global, ",")), eval("g.V().map(__.split(Scope.global, \",\"))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_substring_long() {
+ compare(g.V().map(__.substring(1)), eval("g.V().map(__.substring(1))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_substring_long_long() {
+ compare(g.V().map(__.substring(1, 3)), eval("g.V().map(__.substring(1, 3))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_substring_long_Scope() {
+ compare(g.V().map(__.substring(Scope.global, 5)), eval("g.V().map(__.substring(Scope.global, 5))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_substring_long_long_Scope() {
+ compare(g.V().map(__.substring(Scope.global, 5, 9)), eval("g.V().map(__.substring(Scope.global, 5, 9))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_asDate() {
+ compare(g.V().map(__.asDate()), eval("g.V().map(__.asDate())"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_dateAdd() {
+ compare(g.V().map(__.dateAdd(DT.day, 2)), eval("g.V().map(__.dateAdd(DT.day, 2))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_dateDiff() {
+ compare(g.V().map(__.dateDiff(DatetimeHelper.datetime("2024-11-26"))), eval("g.V().map(__.dateDiff(datetime(\"2024-11-26\")))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_dateDiff_Traversal() {
+ compare(g.V().map(__.dateDiff(__.constant(DatetimeHelper.datetime("2024-11-26")))), eval("g.V().map(__.dateDiff(__.constant(datetime(\"2024-11-26\"))))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_difference() {
+ compare(g.V().map(__.difference("test")), eval("g.V().map(__.difference(\"test\"))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_difference_GValue() {
+ compare(g.V().map(__.difference(GValue.of("foo", "bar"))), eval("g.V().map(__.difference(foo))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_disjunct() {
+ compare(g.V().map(__.disjunct("test")), eval("g.V().map(__.disjunct(\"test\"))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_disjunct_GValue() {
+ compare(g.V().map(__.disjunct(GValue.of("foo", "bar"))), eval("g.V().map(__.disjunct(foo))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_intersect() {
+ compare(g.V().map(__.intersect("test")), eval("g.V().map(__.intersect(\"test\"))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_intersect_GValue() {
+ compare(g.V().map(__.intersect(GValue.of("foo", "bar"))), eval("g.V().map(__.intersect(foo))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_conjoin() {
+ compare(g.V().map(__.conjoin("test")), eval("g.V().map(__.conjoin(\"test\"))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_conjoin_GValue() {
+ compare(g.V().map(__.conjoin(GValue.of("foo", "bar"))), eval("g.V().map(__.conjoin(foo))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_merge() {
+ compare(g.V().map(__.merge("test")), eval("g.V().map(__.merge(\"test\"))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_merge_GValue() {
+ compare(g.V().map(__.merge(GValue.of("foo", "bar"))), eval("g.V().map(__.merge(foo))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_combine() {
+ compare(g.V().map(__.combine("test")), eval("g.V().map(__.combine(\"test\"))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_combine_GValue() {
+ compare(g.V().map(__.combine(GValue.of("foo", "bar"))), eval("g.V().map(__.combine(foo))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_product() {
+ compare(g.V().map(__.product("test")), eval("g.V().map(__.product(\"test\"))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_product_GValue() {
+ compare(g.V().map(__.product(GValue.of("foo", "bar"))), eval("g.V().map(__.product(foo))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_all() {
+ compare(g.V().map(__.all(P.eq("test"))), eval("g.V().map(__.all(P.eq(\"test\")))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_any() {
+ compare(g.V().map(__.any(P.eq("test"))), eval("g.V().map(__.any(P.eq(\"test\")))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_none() {
+ compare(g.V().map(__.none(P.eq("test"))), eval("g.V().map(__.none(P.eq(\"test\")))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_fail() {
+ compare(g.V().map(__.fail()), eval("g.V().map(__.fail())"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_fail_String() {
+ compare(g.V().map(__.fail("test")), eval("g.V().map(__.fail(\"test\"))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_element() {
+ compare(g.V().map(__.element()), eval("g.V().map(__.element())"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_call() {
+ compare(g.V().map(__.call("test")), eval("g.V().map(__.call(\"test\"))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_call_String_Traversal() {
+ compare(g.V().map(__.call("test", __.inject(CollectionUtil.asMap("a", "b")))), eval("g.V().map(__.call(\"test\", __.inject([\"a\":\"b\"])))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_call_Map() {
+ compare(g.V().map(__.call("test", CollectionUtil.asMap("x", "y"))), eval("g.V().map(__.call(\"test\", [\"x\":\"y\"]))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_call_Map_Traversal() {
+ compare(g.V().map(__.call("test", CollectionUtil.asMap("x", "y"), __.inject(CollectionUtil.asMap("a", "b")))), eval("g.V().map(__.call(\"test\", [\"x\":\"y\"], __.inject([\"a\":\"b\"])))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_call_GValue() {
+ antlrToLanguage = createAntlr(new VariableResolver.DefaultVariableResolver(ElementHelper.asMap("test", CollectionUtil.asMap("foo", "bar"))));
+ compare(g.V().map(__.call("svc", GValue.ofMap("test", CollectionUtil.asMap("foo", "bar")))), eval("g.V().map(__.call(\"svc\", test))"));
+ }
+
+ @Test
+ public void shouldParseTraversalMethod_call_GValue_Traversal() {
+ antlrToLanguage = createAntlr(new VariableResolver.DefaultVariableResolver(ElementHelper.asMap("test", CollectionUtil.asMap("foo", "bar"))));
+ compare(g.V().map(__.call("svc", GValue.ofMap("test", CollectionUtil.asMap("foo", "bar")), __.inject(CollectionUtil.asMap("a", "b")))), eval("g.V().map(__.call(\"svc\", test, __.inject([\"a\":\"b\"])))"));
+ }
+
+ private void compare(Object expected, Object actual) {
+ assertEquals(((DefaultGraphTraversal) expected).asAdmin().getGremlinLang(),
+ ((DefaultGraphTraversal) actual).asAdmin().getGremlinLang());
+ }
+
+ private Object eval(String query) {
+ final GremlinLexer lexer = new GremlinLexer(CharStreams.fromString(query));
+ final GremlinParser parser = new GremlinParser(new CommonTokenStream(lexer));
+ return antlrToLanguage.visit(parser.queryList());
+ }
+
+ private GremlinAntlrToJava createAntlr(final VariableResolver resolver) {
+ return new GremlinAntlrToJava("g", EmptyGraph.instance(), __::start, g, resolver);
}
}
(tinkerpop) 04/05: TINKERPOP-2959 Add additional feature tests for GValue
Posted by co...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
colegreer pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/tinkerpop.git
commit f7711ada7a244917d0079823549b7033e04c399d
Author: Ken Hu <10...@users.noreply.github.com>
AuthorDate: Tue Nov 26 22:28:58 2024 -0800
TINKERPOP-2959 Add additional feature tests for GValue
---
.../language/grammar/TraversalMethodVisitor.java | 15 +++++---
.../grammar/TraversalSourceSpawnMethodVisitor.java | 4 ++
.../traversal/dsl/graph/GraphTraversal.java | 35 ++++++++++++-----
gremlin-python/src/main/python/radish/gremlin.py | 44 +++++++++++++++-------
.../gremlin/driver/remote/RemoteWorld.java | 5 ---
.../gremlin/test/features/filter/Coin.feature | 17 +++++++++
.../gremlin/test/features/filter/Has.feature | 13 +++++++
.../gremlin/test/features/filter/HasId.feature | 29 ++++++++++++++
.../gremlin/test/features/filter/HasLabel.feature | 17 +++++++++
.../gremlin/test/features/map/AddEdge.feature | 18 ++++++++-
.../gremlin/test/features/map/Combine.feature | 10 +++++
.../gremlin/test/features/map/Difference.feature | 10 +++++
.../gremlin/test/features/map/Disjunct.feature | 10 +++++
.../gremlin/test/features/map/Edge.feature | 15 +++++++-
.../gremlin/test/features/map/Intersect.feature | 10 +++++
.../gremlin/test/features/map/MergeEdge.feature | 29 ++++++++++++++
.../gremlin/test/features/map/MergeVertex.feature | 34 +++++++++++++++++
.../gremlin/test/features/map/Product.feature | 10 +++++
18 files changed, 288 insertions(+), 37 deletions(-)
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalMethodVisitor.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalMethodVisitor.java
index 55c74aeea8..a31b01b0c4 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalMethodVisitor.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalMethodVisitor.java
@@ -143,6 +143,8 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
final Object literalOrVar = antlr.argumentVisitor.visitGenericLiteralMapNullableArgument(ctx.genericLiteralMapNullableArgument());
if (GValue.valueInstanceOf(literalOrVar, GType.MAP))
return graphTraversal.mergeE((GValue<Map<Object, Object>>) literalOrVar);
+ else if (GValue.valueInstanceOf(literalOrVar, GType.UNKNOWN) && ((GValue) literalOrVar).get() == null)
+ return graphTraversal.mergeE(GValue.ofMap(((GValue) literalOrVar).getName(), null));
else
return graphTraversal.mergeE((Map) literalOrVar);
}
@@ -1248,15 +1250,16 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
return this.graphTraversal.option(TraversalEnumParser.parseTraversalEnumFromContext(Merge.class, ctx.traversalMerge()), (Map) null);
}
- if (ctx.genericLiteralMapNullableArgument().variable() != null) {
+ final Object literalOrVar = antlr.argumentVisitor.visitGenericLiteralMapNullableArgument(ctx.genericLiteralMapNullableArgument());
+ if (GValue.valueInstanceOf(literalOrVar, GType.MAP)) {
return graphTraversal.option(TraversalEnumParser.parseTraversalEnumFromContext(Merge.class, ctx.traversalMerge()),
- (Map) antlr.argumentVisitor.visitVariable(ctx.genericLiteralMapNullableArgument().variable()),
+ (GValue<Map<Object, Object>>) literalOrVar,
+ TraversalEnumParser.parseTraversalEnumFromContext(Cardinality.class, ctx.traversalCardinality()));
+ } else {
+ return graphTraversal.option(TraversalEnumParser.parseTraversalEnumFromContext(Merge.class, ctx.traversalMerge()),
+ (Map<Object, Object>) literalOrVar,
TraversalEnumParser.parseTraversalEnumFromContext(Cardinality.class, ctx.traversalCardinality()));
}
-
- return graphTraversal.option(TraversalEnumParser.parseTraversalEnumFromContext(Merge.class, ctx.traversalMerge()),
- (Map) new GenericLiteralVisitor(antlr).visitGenericLiteralMap(ctx.genericLiteralMapNullableArgument().genericLiteralMap()),
- TraversalEnumParser.parseTraversalEnumFromContext(Cardinality.class, ctx.traversalCardinality()));
}
/**
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalSourceSpawnMethodVisitor.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalSourceSpawnMethodVisitor.java
index c65b283b0a..4c57cd4a67 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalSourceSpawnMethodVisitor.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalSourceSpawnMethodVisitor.java
@@ -134,6 +134,8 @@ public class TraversalSourceSpawnMethodVisitor extends DefaultGremlinBaseVisitor
final Object literalOrVar = antlr.argumentVisitor.visitGenericLiteralMapNullableArgument(ctx.genericLiteralMapNullableArgument());
if (GValue.valueInstanceOf(literalOrVar, GType.MAP))
return this.traversalSource.mergeV((GValue) literalOrVar);
+ else if (GValue.valueInstanceOf(literalOrVar, GType.UNKNOWN) && ((GValue) literalOrVar).get() == null)
+ return this.traversalSource.mergeV((GValue) GValue.ofMap(((GValue) literalOrVar).getName(), null));
else
return this.traversalSource.mergeV((Map) literalOrVar);
}
@@ -162,6 +164,8 @@ public class TraversalSourceSpawnMethodVisitor extends DefaultGremlinBaseVisitor
final Object literalOrVar = antlr.argumentVisitor.visitGenericLiteralMapNullableArgument(ctx.genericLiteralMapNullableArgument());
if (GValue.valueInstanceOf(literalOrVar, GType.MAP))
return this.traversalSource.mergeE((GValue) literalOrVar);
+ else if (GValue.valueInstanceOf(literalOrVar, GType.UNKNOWN) && ((GValue) literalOrVar).get() == null)
+ return this.traversalSource.mergeE((GValue) GValue.ofMap(((GValue) literalOrVar).getName(), null));
else
return this.traversalSource.mergeE((Map) literalOrVar);
}
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 624e3cfb2e..77c4b838e6 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
@@ -208,7 +208,6 @@ import org.apache.tinkerpop.gremlin.structure.VertexProperty;
import org.apache.tinkerpop.gremlin.util.CollectionUtil;
import org.apache.tinkerpop.gremlin.util.function.ConstantSupplier;
-import java.lang.reflect.Array;
import java.time.OffsetDateTime;
import java.util.ArrayList;
import java.util.Arrays;
@@ -2888,7 +2887,31 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
// be turned into array first
if (otherIds != null) {
for (final Object i : otherIds) {
- if (id instanceof Object[]) {
+ // to retain existing behavior, GValue's containing collections are unrolled by 1 layer.
+ // For example, GValue.of([1, 2]) is processed to [GValue.of(1), GValue.of(2)]
+ if(i instanceof GValue) {
+ Object value = ((GValue) i).get();
+ if (i instanceof Object[]) {
+ for (Object o : (Object[]) value) {
+ if(o instanceof GValue) {
+ ids.add(o);
+ } else {
+ ids.add(GValue.of(null, o));
+ }
+ }
+ } else if(value instanceof Collection) {
+ for (Object o : (Collection<?>) value) {
+ if(o instanceof GValue) {
+ ids.add(o);
+ } else {
+ ids.add(GValue.of(null, o));
+ }
+ }
+ } else {
+ ids.add(i);
+ }
+ }
+ else if (i instanceof Object[]) {
Collections.addAll(ids, (Object[]) i);
} else if (i instanceof Collection) {
ids.addAll((Collection<?>) i);
@@ -4531,14 +4554,6 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
public default <M, E2> GraphTraversal<S, E> option(final Merge merge, final GValue<Map<Object, Object>> m, final VertexProperty.Cardinality cardinality) {
this.asAdmin().getGremlinLang().addStep(GraphTraversal.Symbols.option, merge, m, cardinality);
- final Map<Object, Object> map = m.get();
-
- // do explicit cardinality for every single pair in the map
- for (Object k : map.keySet()) {
- final Object o = map.get(k);
- if (!(o instanceof CardinalityValueTraversal))
- map.put(k, new CardinalityValueTraversal(cardinality, o));
- }
((TraversalOptionParent<M, E, E2>) this.asAdmin().getEndStep()).addChildOption((M) merge, (Traversal.Admin<E, E2>) new ConstantTraversal<>(m).asAdmin());
return this;
}
diff --git a/gremlin-python/src/main/python/radish/gremlin.py b/gremlin-python/src/main/python/radish/gremlin.py
index a2db50be54..3385d0f6a7 100644
--- a/gremlin-python/src/main/python/radish/gremlin.py
+++ b/gremlin-python/src/main/python/radish/gremlin.py
@@ -138,6 +138,7 @@ world.gremlins = {
'g_injectXnull_nullX_anyXeqXnullXX': [(lambda g, xx1=None:g.inject(xx1).any_(P.eq(None)))],
'g_injectX3_threeX_anyXeqX3XX': [(lambda g, xx1=None:g.inject(xx1).any_(P.eq(3)))],
'g_V_coinX1X': [(lambda g:g.V().coin(1.0))],
+ 'g_V_coinX1varX': [(lambda g, xx1=None:g.V().coin(xx1))],
'g_V_coinX0X': [(lambda g:g.V().coin(0.0))],
'g_withStrategiesXSeedStrategyX_V_order_byXnameX_coinX50X': [(lambda g:g.with_strategies(SeedStrategy(seed=999999)).V().order().by('name').coin(0.5))],
'g_VX1X_outXcreatedX_inXcreatedX_cyclicPath': [(lambda g, vid1=None:g.V(vid1).out('created').in_('created').cyclic_path())],
@@ -202,6 +203,7 @@ world.gremlins = {
'g_V_hasXage_isXgt_30XX': [(lambda g:g.V().has('age', __.is_(P.gt(30))))],
'g_V_hasXlabel_isXsoftwareXX': [(lambda g:g.V().has(T.label, __.is_('software')))],
'g_VX1X_hasXage_gt_30X': [(lambda g, vid1=None:g.V(vid1).has('age', P.gt(30)))],
+ 'g_V_hasXpersonvar_age_gt_30X': [(lambda g, xx1=None:g.V().has(xx1, 'age', P.gt(30)))],
'g_VX4X_hasXage_gt_30X': [(lambda g, vid4=None:g.V(vid4).has('age', P.gt(30)))],
'g_VXv1X_hasXage_gt_30X': [(lambda g, v1=None:g.V(v1).has('age', P.gt(30)))],
'g_VXv4X_hasXage_gt_30X': [(lambda g, v4=None:g.V(v4).has('age', P.gt(30)))],
@@ -251,6 +253,8 @@ world.gremlins = {
'g_V_hasIdXnullX': [(lambda g:g.V().has_id(None))],
'g_V_hasIdXeqXnullXX': [(lambda g:g.V().has_id(P.eq(None)))],
'g_V_hasIdX2_nullX': [(lambda g, vid2=None:g.V().has_id(vid2, None))],
+ 'g_V_hasIdXmarkovar_vadasvarX': [(lambda g, vid2=None,vid1=None:g.V().has_id(vid1, vid2))],
+ 'g_V_hasIdXmarkovar_vadasvar_petervarX': [(lambda g, vid2=None,vid1=None:g.V().has_id(vid1, vid2))],
'g_V_hasIdX2AsString_nullX': [(lambda g, vid2=None:g.V().has_id(vid2, None))],
'g_V_hasIdX1AsString_2AsString_nullX': [(lambda g, vid2=None,vid1=None:g.V().has_id(vid1, vid2, None))],
'g_V_hasIdXnull_2X': [(lambda g, vid2=None:g.V().has_id(None, vid2))],
@@ -277,6 +281,7 @@ world.gremlins = {
'g_E_hasLabelXknowsX': [(lambda g:g.E().has_label('knows'))],
'g_E_hasLabelXuses_traversesX': [(lambda g:g.E().has_label('uses', 'traverses'))],
'g_V_hasLabelXperson_software_blahX': [(lambda g:g.V().has_label('person', 'software', 'blah'))],
+ 'g_V_hasLabelXperson_softwarevarX': [(lambda g, xx1=None:g.V().has_label('person', xx1))],
'g_V_hasLabelXpersonX_hasLabelXsoftwareX': [(lambda g:g.V().has_label('person').has_label('software'))],
'g_V_hasLabelXpersonvarX_hasLabelXsoftwareX': [(lambda g, xx1=None:g.V().has_label(xx1).has_label('software'))],
'g_V_hasLabelXpersonvar_softwarevarX': [(lambda g, xx1=None,xx2=None:g.V().has_label(xx1, xx2))],
@@ -574,6 +579,7 @@ world.gremlins = {
'g_VXaX_addEXknowsX_toXbX_propertyXweight_0_1X': [(lambda g, v6=None,xx1=None,v1=None:g.add_v('person').property('name', 'marko').property('age', 29).as_('marko').add_v('person').property('name', 'vadas').property('age', 27).as_('vadas').add_v('software').property('name', 'lop').property('lang', 'java').as_('lop').add_v('person').property('name', 'josh').property('age', 32).as_('josh').add_v('software').property('name', 'ripple').property('lang', 'java').as_('ripple').add_v('person') [...]
'g_addEXknowsXpropertyXweight_nullXfromXV_hasXname_markoXX_toXV_hasXname_vadasXX': [(lambda g:g.add_v('person').property('name', 'marko').property('age', 29).add_v('person').property('name', 'vadas').property('age', 27)), (lambda g:g.add_e('knows').property('weight', None).from_(__.V().has('name', 'marko')).to(__.V().has('name', 'vadas'))), (lambda g:g.E().has('knows', 'weight', None))],
'g_addEXknowsvarXpropertyXweight_nullXfromXV_hasXname_markoXX_toXV_hasXname_vadasXX': [(lambda g, xx1=None:g.add_v('person').property('name', 'marko').property('age', 29).add_v('person').property('name', 'vadas').property('age', 27)), (lambda g, xx1=None:g.add_e(xx1).property('weight', None).from_(__.V().has('name', 'marko')).to(__.V().has('name', 'vadas'))), (lambda g, xx1=None:g.E().has('knows', 'weight', None))],
+ 'g_unionXaddEXknowsvarXpropertyXweight_nullXfromXV_hasXname_markoXX_toXV_hasXname_vadasXXX': [(lambda g, xx1=None:g.add_v('person').property('name', 'marko').property('age', 29).add_v('person').property('name', 'vadas').property('age', 27)), (lambda g, xx1=None:g.union(__.add_e(xx1).property('weight', 1).from_(__.V().has('name', 'marko')).to(__.V().has('name', 'vadas')))), (lambda g, xx1=None:g.E().has('knows', 'weight', 1))],
'g_VX1X_addVXanimalX_propertyXage_selectXaX_byXageXX_propertyXname_puppyX': [(lambda g, vid1=None:g.add_v('person').property('name', 'marko').property('age', 29).as_('marko').add_v('person').property('name', 'vadas').property('age', 27).as_('vadas').add_v('software').property('name', 'lop').property('lang', 'java').as_('lop').add_v('person').property('name', 'josh').property('age', 32).as_('josh').add_v('software').property('name', 'ripple').property('lang', 'java').as_('ripple').add [...]
'g_V_addVXanimalX_propertyXage_0X': [(lambda g:g.add_v('person').property('name', 'marko').property('age', 29).as_('marko').add_v('person').property('name', 'vadas').property('age', 27).as_('vadas').add_v('software').property('name', 'lop').property('lang', 'java').as_('lop').add_v('person').property('name', 'josh').property('age', 32).as_('josh').add_v('software').property('name', 'ripple').property('lang', 'java').as_('ripple').add_v('person').property('name', 'peter').property('ag [...]
'g_V_addVXanimalvarX_propertyXage_0varX': [(lambda g, xx1=None,xx2=None:g.add_v('person').property('name', 'marko').property('age', 29).as_('marko').add_v('person').property('name', 'vadas').property('age', 27).as_('vadas').add_v('software').property('name', 'lop').property('lang', 'java').as_('lop').add_v('person').property('name', 'josh').property('age', 32).as_('josh').add_v('software').property('name', 'ripple').property('lang', 'java').as_('ripple').add_v('person').property('nam [...]
@@ -659,6 +665,7 @@ world.gremlins = {
'g_V_fold_combineXconstantXnullXX': [(lambda g:g.V().fold().combine(__.constant(None)))],
'g_V_fold_combineXVX': [(lambda g:g.V().fold().combine(__.V()))],
'g_V_valuesXnameX_fold_combineX2X': [(lambda g:g.V().values('name').fold().combine(2))],
+ 'g_V_valuesXnameX_fold_combineX2varX': [(lambda g, xx1=None:g.V().values('name').fold().combine(xx1))],
'g_V_valuesXnameX_fold_combineXnullX': [(lambda g:g.V().values('name').fold().combine(None))],
'g_V_valuesXnonexistantX_fold_combineXV_valuesXnameX_foldX_unfold': [(lambda g:g.V().values('nonexistant').fold().combine(__.V().values('name').fold()).unfold())],
'g_V_valuesXnameX_fold_combineXV_valuesXnonexistantX_foldX_unfold': [(lambda g:g.V().values('name').fold().combine(__.V().values('nonexistant').fold()).unfold())],
@@ -735,6 +742,7 @@ world.gremlins = {
'g_V_fold_differenceXconstantXnullXX': [(lambda g:g.V().fold().difference(__.constant(None)))],
'g_V_fold_differenceXVX': [(lambda g:g.V().fold().difference(__.V()))],
'g_V_valuesXnameX_fold_differenceX2X': [(lambda g:g.V().values('name').fold().difference(2))],
+ 'g_V_valuesXnameX_fold_differenceX2varX': [(lambda g, xx1=None:g.V().values('name').fold().difference(xx1))],
'g_V_valuesXnameX_fold_differenceXnullX': [(lambda g:g.V().values('name').fold().difference(None))],
'g_V_valuesXnonexistantX_fold_differenceXV_valuesXnameX_foldX': [(lambda g:g.V().values('nonexistant').fold().difference(__.V().values('name').fold()))],
'g_V_valuesXnameX_fold_differenceXV_valuesXnonexistantX_foldX': [(lambda g:g.V().values('name').fold().difference(__.V().values('nonexistant').fold()))],
@@ -754,6 +762,7 @@ world.gremlins = {
'g_V_fold_disjunctXconstantXnullXX': [(lambda g:g.V().fold().disjunct(__.constant(None)))],
'g_V_fold_disjunctXVX': [(lambda g:g.V().fold().disjunct(__.V()))],
'g_V_valuesXnameX_fold_disjunctX2X': [(lambda g:g.V().values('name').fold().disjunct(2))],
+ 'g_V_valuesXnameX_fold_disjunctX3varX': [(lambda g, xx1=None:g.V().values('name').fold().disjunct(xx1))],
'g_V_valuesXnameX_fold_disjunctXnullX': [(lambda g:g.V().values('name').fold().disjunct(None))],
'g_V_valuesXnonexistantX_fold_disjunctXV_valuesXnameX_foldX': [(lambda g:g.V().values('nonexistant').fold().disjunct(__.V().values('name').fold()))],
'g_V_valuesXnameX_fold_disjunctXV_valuesXnonexistantX_foldX': [(lambda g:g.V().values('name').fold().disjunct(__.V().values('nonexistant').fold()))],
@@ -792,6 +801,7 @@ world.gremlins = {
'g_VX1X_outEXknows_createdX_inV': [(lambda g, vid1=None:g.V(vid1).out_e('knows', 'created').in_v())],
'g_VX1X_outEXknowsX_bothV': [(lambda g, vid1=None:g.V(vid1).out_e('knows').both_v())],
'g_VX1X_outEXknowsX_bothV_name': [(lambda g, vid1=None:g.V(vid1).out_e('knows').both_v().values('name'))],
+ 'g_V_toEXout_knowsvarX_valuesXweightX': [(lambda g, xx1=None:g.V().to_e(Direction.OUT, xx1).values('weight'))],
'g_VX1X_properties_element': [(lambda g, v2=None:g.V(v2).properties().element().limit(1))],
'g_V_properties_element': [(lambda g:g.V().properties().element())],
'g_V_propertiesXageX_element': [(lambda g:g.V().properties('age').element())],
@@ -834,6 +844,7 @@ world.gremlins = {
'g_V_fold_intersectXconstantXnullXX': [(lambda g:g.V().fold().intersect(__.constant(None)))],
'g_V_fold_intersectXVX': [(lambda g:g.V().fold().intersect(__.V()))],
'g_V_valuesXnameX_fold_intersectX2X': [(lambda g:g.V().values('name').fold().intersect(2))],
+ 'g_V_valuesXnameX_fold_intersectX5varX': [(lambda g, xx1=None:g.V().values('name').fold().intersect(xx1))],
'g_V_valuesXnameX_fold_intersectXnullX': [(lambda g:g.V().values('name').fold().intersect(None))],
'g_V_valuesXnonexistantX_fold_intersectXV_valuesXnameX_foldX': [(lambda g:g.V().values('nonexistant').fold().intersect(__.V().values('name').fold()))],
'g_V_valuesXnameX_fold_intersectXV_valuesXnonexistantX_foldX': [(lambda g:g.V().values('name').fold().intersect(__.V().values('nonexistant').fold()))],
@@ -846,13 +857,6 @@ world.gremlins = {
'g_injectXa_null_bX_intersectXa_cX': [(lambda g, xx1=None,xx2=None:g.inject(xx1).intersect(xx2))],
'g_injectXa_null_bX_intersectXa_null_cX': [(lambda g, xx1=None,xx2=None:g.inject(xx1).intersect(xx2))],
'g_injectX3_threeX_intersectXfive_three_7X': [(lambda g, xx1=None,xx2=None:g.inject(xx1).intersect(xx2))],
- 'g_injectX__feature___test__nullX_lTrim': [(lambda g:g.inject(' feature', ' one test', None, '', ' ', ' abc', 'abc ', ' abc ', '  ').l_trim())],
- 'g_injectX__feature___test__nullX_lTrimXlocalX': [(lambda g:g.inject([' feature ', ' one test ', None, '', ' ', ' abc', 'abc ', ' abc ', '  ']).l_trim(Scope.local))],
- 'g_injectX__feature__X_lTrim': [(lambda g:g.inject(' feature ').l_trim())],
- 'g_injectXListXa_bXX_lTrim': [(lambda g, xx1=None:g.inject(xx1).l_trim())],
- 'g_injectXListX1_2XX_lTrimXlocalX': [(lambda g, xx1=None:g.inject(xx1).l_trim(Scope.local))],
- 'g_V_valuesXnameX_lTrim': [(lambda g:g.add_v('person').property('name', ' marko ').property('age', 29).as_('marko').add_v('person').property('name', ' vadas ').property('age', 27).as_('vadas').add_v('software').property('name', ' lop').property('lang', 'java').as_('lop').add_v('person').property('name', 'josh ').property('age', 32).as_('josh').add_v('software').property('name', ' ripple ').property('lang', 'java').as_('ripple').add_v('person').property('name', 'peter').proper [...]
- 'g_V_valuesXnameX_order_fold_lTrimXlocalX': [(lambda g:g.add_v('person').property('name', ' marko ').property('age', 29).as_('marko').add_v('person').property('name', ' vadas ').property('age', 27).as_('vadas').add_v('software').property('name', ' lop').property('lang', 'java').as_('lop').add_v('person').property('name', 'josh ').property('age', 32).as_('josh').add_v('software').property('name', ' ripple ').property('lang', 'java').as_('ripple').add_v('person').property('name [...]
'g_injectXfeature_test_nullX_length': [(lambda g:g.inject('feature', 'test', None).length())],
'g_injectXfeature_test_nullX_lengthXlocalX': [(lambda g:g.inject('feature', 'test', None).length(Scope.local))],
'g_injectXListXa_bXX_length': [(lambda g, xx1=None:g.inject(xx1).length())],
@@ -862,6 +866,13 @@ world.gremlins = {
'g_VX1X_repeatXboth_simplePathX_untilXhasXname_peterX_or_loops_isX2XX_hasXname_peterX_path_byXnameX': [(lambda g, vid1=None:g.V(vid1).repeat(__.both().simple_path()).until(__.has('name', 'peter').or_().loops().is_(2)).has('name', 'peter').path().by('name'))],
'g_VX1X_repeatXboth_simplePathX_untilXhasXname_peterX_and_loops_isX3XX_hasXname_peterX_path_byXnameX': [(lambda g, vid1=None:g.V(vid1).repeat(__.both().simple_path()).until(__.has('name', 'peter').and_().loops().is_(3)).has('name', 'peter').path().by('name'))],
'g_V_emitXhasXname_markoX_or_loops_isX2XX_repeatXoutX_valuesXnameX': [(lambda g:g.V().emit(__.has('name', 'marko').or_().loops().is_(2)).repeat(__.out()).values('name'))],
+ 'g_injectX__feature___test__nullX_lTrim': [(lambda g:g.inject(' feature', ' one test', None, '', ' ', ' abc', 'abc ', ' abc ', '  ').l_trim())],
+ 'g_injectX__feature___test__nullX_lTrimXlocalX': [(lambda g:g.inject([' feature ', ' one test ', None, '', ' ', ' abc', 'abc ', ' abc ', '  ']).l_trim(Scope.local))],
+ 'g_injectX__feature__X_lTrim': [(lambda g:g.inject(' feature ').l_trim())],
+ 'g_injectXListXa_bXX_lTrim': [(lambda g, xx1=None:g.inject(xx1).l_trim())],
+ 'g_injectXListX1_2XX_lTrimXlocalX': [(lambda g, xx1=None:g.inject(xx1).l_trim(Scope.local))],
+ 'g_V_valuesXnameX_lTrim': [(lambda g:g.add_v('person').property('name', ' marko ').property('age', 29).as_('marko').add_v('person').property('name', ' vadas ').property('age', 27).as_('vadas').add_v('software').property('name', ' lop').property('lang', 'java').as_('lop').add_v('person').property('name', 'josh ').property('age', 32).as_('josh').add_v('software').property('name', ' ripple ').property('lang', 'java').as_('ripple').add_v('person').property('name', 'peter').proper [...]
+ 'g_V_valuesXnameX_order_fold_lTrimXlocalX': [(lambda g:g.add_v('person').property('name', ' marko ').property('age', 29).as_('marko').add_v('person').property('name', ' vadas ').property('age', 27).as_('vadas').add_v('software').property('name', ' lop').property('lang', 'java').as_('lop').add_v('person').property('name', 'josh ').property('age', 32).as_('josh').add_v('software').property('name', ' ripple ').property('lang', 'java').as_('ripple').add_v('person').property('name [...]
'g_VX1X_mapXnameX': [], # skipping as it contains a lambda
'g_VX1X_outE_label_mapXlengthX': [], # skipping as it contains a lambda
'g_VX1X_out_mapXnameX_mapXlengthX': [], # skipping as it contains a lambda
@@ -982,6 +993,8 @@ world.gremlins = {
'g_V_mergeEXemptyX_two_exist': [(lambda g, xx1=None:g.add_v('person').property('name', 'marko').property('age', 29).add_v('person').property('name', 'vadas').property('age', 27)), (lambda g, xx1=None:g.V().as_('v').merge_e(xx1).option(Merge.out_v, __.select('v')).option(Merge.in_v, __.select('v'))), (lambda g, xx1=None:g.E()), (lambda g, xx1=None:g.V())],
'g_V_mergeE_inlineXemptyX_two_exist': [(lambda g:g.add_v('person').property('name', 'marko').property('age', 29).add_v('person').property('name', 'vadas').property('age', 27)), (lambda g:g.V().as_('v').merge_e({ T.label: 'self', Direction.OUT: Merge.out_v, Direction.IN: Merge.in_v }).option(Merge.out_v, __.select('v')).option(Merge.in_v, __.select('v'))), (lambda g:g.E()), (lambda g:g.V())],
'g_mergeEXnullX': [(lambda g:g.add_v('person').property('name', 'marko').property('age', 29)), (lambda g:g.merge_e(None))],
+ 'g_mergeEXnullvarX': [(lambda g, xx1=None:g.add_v('person').property('name', 'marko').property('age', 29)), (lambda g, xx1=None:g.merge_e(xx1))],
+ 'g_V_limitX1X_mergeEXnullvarX': [(lambda g, xx1=None:g.add_v('person').property('name', 'marko').property('age', 29)), (lambda g, xx1=None:g.V().limit(1).merge_e(xx1))],
'g_V_mergeEXnullX': [(lambda g:g.add_v('person').property('name', 'marko').property('age', 29)), (lambda g:g.V().merge_e(None))],
'g_mergeEXlabel_knows_out_marko_in_vadasX': [(lambda g, xx1=None:g.add_v('person').property('name', 'marko').add_v('person').property('name', 'vadas')), (lambda g, xx1=None:g.merge_e(xx1)), (lambda g, xx1=None:g.V().has('person', 'name', 'marko').out('knows').has('person', 'name', 'vadas'))],
'g_withSideEffectXa_label_knows_out_marko_in_vadasX_mergeEXselectXaXX': [(lambda g, xx1=None:g.add_v('person').property('name', 'marko').add_v('person').property('name', 'vadas')), (lambda g, xx1=None:g.with_side_effect('a', xx1).merge_e(__.select('a'))), (lambda g, xx1=None:g.V().has('person', 'name', 'marko').out('knows').has('person', 'name', 'vadas'))],
@@ -1033,6 +1046,7 @@ world.gremlins = {
'g_mergeVXemptyX': [(lambda g:g.add_v('person').property('name', 'marko').property('age', 29)), (lambda g:g.merge_v({ })), (lambda g:g.V().has('person', 'name', 'marko').has('age', 29))],
'g_V_mergeVXemptyX_two_exist': [(lambda g:g.add_v('person').property('name', 'marko').property('age', 29).add_v('person').property('name', 'vadas').property('age', 27)), (lambda g:g.V().merge_v({ })), (lambda g:g.V()), (lambda g:g.V().has('person', 'name', 'marko').has('age', 29)), (lambda g:g.V().has('person', 'name', 'vadas').has('age', 27))],
'g_mergeVXnullX': [(lambda g:g.add_v('person').property('name', 'marko').property('age', 29)), (lambda g:g.merge_v(None)), (lambda g:g.V())],
+ 'g_mergeVXnullvarX': [(lambda g, xx1=None:g.merge_v(xx1)), (lambda g, xx1=None:g.V())],
'g_V_mergeVXnullX': [(lambda g:g.add_v('person').property('name', 'marko').property('age', 29)), (lambda g:g.V().merge_v(None)), (lambda g:g.V())],
'g_mergeVXlabel_person_name_stephenX': [(lambda g, xx1=None:g.add_v('person').property('name', 'marko').property('age', 29)), (lambda g, xx1=None:g.merge_v(xx1)), (lambda g, xx1=None:g.V().has('person', 'name', 'stephen'))],
'g_mergeVXlabel_person_name_markoX': [(lambda g, xx1=None:g.add_v('person').property('name', 'marko').property('age', 29)), (lambda g, xx1=None:g.merge_v(xx1)), (lambda g, xx1=None:g.V().has('person', 'name', 'marko'))],
@@ -1074,6 +1088,7 @@ world.gremlins = {
'g_mergeVXname_markoX_optionXonMatch_age_singleX33XX': [(lambda g:g.add_v('person').property('name', 'marko').property(Cardinality.list_, 'age', 29).property(Cardinality.list_, 'age', 31).property(Cardinality.list_, 'age', 32)), (lambda g:g.merge_v({ 'name': 'marko' }).option(Merge.on_match, { 'age': CardinalityValue.single(33) })), (lambda g:g.V().has('person', 'name', 'marko').has('age', 33)), (lambda g:g.V().has('person', 'name', 'marko').has('age')), (lambda g:g.V().has('person', [...]
'g_mergeVXname_markoX_optionXonMatch_age_33_singleX': [(lambda g:g.add_v('person').property('name', 'marko').property(Cardinality.list_, 'age', 29).property(Cardinality.list_, 'age', 31).property(Cardinality.list_, 'age', 32)), (lambda g:g.merge_v({ 'name': 'marko' }).option(Merge.on_match, { 'age': 33 }, Cardinality.single)), (lambda g:g.V().has('person', 'name', 'marko').has('age', 33)), (lambda g:g.V().has('person', 'name', 'marko').has('age')), (lambda g:g.V().has('person', 'name [...]
'g_mergeVXname_markoX_optionXonMatch_name_allen_age_setX31X_singleX': [(lambda g:g.add_v('person').property('name', 'marko').property(Cardinality.list_, 'age', 29).property(Cardinality.list_, 'age', 31).property(Cardinality.list_, 'age', 32)), (lambda g:g.merge_v({ 'name': 'marko' }).option(Merge.on_match, { 'name': 'allen', 'age': CardinalityValue.set_(31) }, Cardinality.single)), (lambda g:g.V().has('person', 'name', 'marko')), (lambda g:g.V().has('person', 'name', 'allen').has('ag [...]
+ 'g_mergeVXname_markoX_optionXonMatch_name_allen_var_singleX': [(lambda g, xx1=None:g.add_v('person').property('name', 'marko')), (lambda g, xx1=None:g.merge_v({ 'name': 'marko' }).option(Merge.on_match, xx1, Cardinality.single)), (lambda g, xx1=None:g.V().has('person', 'name', 'marko')), (lambda g, xx1=None:g.V().has('person', 'name', 'allen'))],
'g_mergeVXname_markoX_optionXonMatch_name_allen_age_singleX31X_singleX': [(lambda g:g.add_v('person').property('name', 'marko').property(Cardinality.list_, 'age', 29).property(Cardinality.list_, 'age', 31).property(Cardinality.list_, 'age', 32)), (lambda g:g.merge_v({ 'name': 'marko' }).option(Merge.on_match, { 'name': 'allen', 'age': CardinalityValue.single(31) }, Cardinality.single)), (lambda g:g.V().has('person', 'name', 'marko')), (lambda g:g.V().has('person', 'name', 'allen').ha [...]
'g_mergeVXname_aliceX_optionXonCreate_age_singleX81XX': [(lambda g:g.merge_v({ 'name': 'alice', T.label: 'person' }).option(Merge.on_create, { 'age': CardinalityValue.single(81) })), (lambda g:g.V().has('person', 'name', 'alice').has('age', 81)), (lambda g:g.V().has('person', 'name', 'alice').has('age')), (lambda g:g.V().has('person', 'name', 'alice').properties('age'))],
'g_mergeVXname_aliceX_optionXonCreate_age_setX81XX': [(lambda g:g.merge_v({ 'name': 'alice', T.label: 'person' }).option(Merge.on_create, { 'age': CardinalityValue.set_(81) })), (lambda g:g.V().has('person', 'name', 'alice').has('age', 81)), (lambda g:g.V().has('person', 'name', 'alice').has('age')), (lambda g:g.V().has('person', 'name', 'alice').properties('age'))],
@@ -1157,6 +1172,7 @@ world.gremlins = {
'g_V_fold_productXconstantXnullXX': [(lambda g:g.V().fold().product(__.constant(None)))],
'g_V_fold_productXVX': [(lambda g:g.V().fold().product(__.V()))],
'g_V_valuesXnameX_fold_productX2X': [(lambda g:g.V().values('name').fold().product(2))],
+ 'g_V_valuesXnameX_fold_productX7varX': [(lambda g, xx1=None:g.V().values('name').fold().product(xx1))],
'g_V_valuesXnameX_fold_productXnullX': [(lambda g:g.V().values('name').fold().product(None))],
'g_V_valuesXnonexistantX_fold_productXV_valuesXnameX_foldX': [(lambda g:g.V().values('nonexistant').fold().product(__.V().values('name').fold()))],
'g_V_valuesXnameX_fold_productXV_valuesXnonexistantX_foldX': [(lambda g:g.V().values('name').fold().product(__.V().values('nonexistant').fold()))],
@@ -1179,13 +1195,6 @@ world.gremlins = {
'g_V_hasXageX_propertiesXage_nameX_value': [(lambda g:g.V().has('age').properties('age', 'name').value())],
'g_V_propertiesXname_age_nullX_value': [(lambda g:g.V().properties('name', 'age', None).value())],
'g_V_valuesXname_age_nullX': [(lambda g:g.V().values('name', 'age', None))],
- 'g_injectX__feature___test__nullX_rTrim': [(lambda g:g.inject('feature ', 'one test ', None, '', ' ', ' abc', 'abc ', ' abc ', '  ').r_trim())],
- 'g_injectX__feature___test__nullX_rTrimXlocalX': [(lambda g:g.inject([' feature ', ' one test ', None, '', ' ', ' abc', 'abc ', ' abc ', '  ']).r_trim(Scope.local))],
- 'g_injectX__feature__X_rTrim': [(lambda g:g.inject(' feature ').r_trim())],
- 'g_injectXListXa_bXX_rTrim': [(lambda g, xx1=None:g.inject(xx1).r_trim())],
- 'g_injectXListX1_2XX_rTrimXlocalX': [(lambda g, xx1=None:g.inject(xx1).r_trim(Scope.local))],
- 'g_V_valuesXnameX_rTrim': [(lambda g:g.add_v('person').property('name', ' marko ').property('age', 29).as_('marko').add_v('person').property('name', ' vadas ').property('age', 27).as_('vadas').add_v('software').property('name', ' lop').property('lang', 'java').as_('lop').add_v('person').property('name', 'josh ').property('age', 32).as_('josh').add_v('software').property('name', ' ripple ').property('lang', 'java').as_('ripple').add_v('person').property('name', 'peter').proper [...]
- 'g_V_valuesXnameX_order_fold_rTrimXlocalX': [(lambda g:g.add_v('person').property('name', ' marko ').property('age', 29).as_('marko').add_v('person').property('name', ' vadas ').property('age', 27).as_('vadas').add_v('software').property('name', ' lop').property('lang', 'java').as_('lop').add_v('person').property('name', 'josh ').property('age', 32).as_('josh').add_v('software').property('name', ' ripple ').property('lang', 'java').as_('ripple').add_v('person').property('name [...]
'g_injectXthat_this_test_nullX_replaceXh_jX': [(lambda g:g.inject('that', 'this', 'test', None).replace('h', 'j'))],
'g_injectXthat_this_test_nullX_fold_replaceXlocal_h_jX': [(lambda g:g.inject('that', 'this', 'test', None).fold().replace(Scope.local, 'h', 'j'))],
'g_injectXListXa_bXcX_replaceXa_bX': [(lambda g, xx1=None:g.inject(xx1).replace('a', 'b'))],
@@ -1202,6 +1211,13 @@ world.gremlins = {
'g_injectXnullX_reverse': [(lambda g:g.inject(None).reverse())],
'g_injectXbX_reverse': [(lambda g:g.inject('b').reverse())],
'g_injectX3_threeX_reverse': [(lambda g, xx1=None:g.inject(xx1).reverse())],
+ 'g_injectX__feature___test__nullX_rTrim': [(lambda g:g.inject('feature ', 'one test ', None, '', ' ', ' abc', 'abc ', ' abc ', '  ').r_trim())],
+ 'g_injectX__feature___test__nullX_rTrimXlocalX': [(lambda g:g.inject([' feature ', ' one test ', None, '', ' ', ' abc', 'abc ', ' abc ', '  ']).r_trim(Scope.local))],
+ 'g_injectX__feature__X_rTrim': [(lambda g:g.inject(' feature ').r_trim())],
+ 'g_injectXListXa_bXX_rTrim': [(lambda g, xx1=None:g.inject(xx1).r_trim())],
+ 'g_injectXListX1_2XX_rTrimXlocalX': [(lambda g, xx1=None:g.inject(xx1).r_trim(Scope.local))],
+ 'g_V_valuesXnameX_rTrim': [(lambda g:g.add_v('person').property('name', ' marko ').property('age', 29).as_('marko').add_v('person').property('name', ' vadas ').property('age', 27).as_('vadas').add_v('software').property('name', ' lop').property('lang', 'java').as_('lop').add_v('person').property('name', 'josh ').property('age', 32).as_('josh').add_v('software').property('name', ' ripple ').property('lang', 'java').as_('ripple').add_v('person').property('name', 'peter').proper [...]
+ 'g_V_valuesXnameX_order_fold_rTrimXlocalX': [(lambda g:g.add_v('person').property('name', ' marko ').property('age', 29).as_('marko').add_v('person').property('name', ' vadas ').property('age', 27).as_('vadas').add_v('software').property('name', ' lop').property('lang', 'java').as_('lop').add_v('person').property('name', 'josh ').property('age', 32).as_('josh').add_v('software').property('name', ' ripple ').property('lang', 'java').as_('ripple').add_v('person').property('name [...]
'g_VX1X_asXaX_outXknowsX_asXbX_selectXa_bX': [(lambda g, vid1=None:g.V(vid1).as_('a').out('knows').as_('b').select('a', 'b'))],
'g_VX1X_asXaX_outXknowsX_asXbX_selectXa_bX_byXnameX': [(lambda g, vid1=None:g.V(vid1).as_('a').out('knows').as_('b').select('a', 'b').by('name'))],
'g_VX1X_asXaX_outXknowsX_asXbX_selectXaX': [(lambda g, vid1=None:g.V(vid1).as_('a').out('knows').as_('b').select('a'))],
diff --git a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/RemoteWorld.java b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/RemoteWorld.java
index 6ec1bafe9f..4154bdc671 100644
--- a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/RemoteWorld.java
+++ b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/RemoteWorld.java
@@ -192,11 +192,6 @@ public abstract class RemoteWorld implements World {
final GraphTraversalSource g = super.getGraphTraversalSource(graphData);
return g.with("language", "groovy-test");
}
-
- @Override
- public boolean useParametersLiterally() {
- return false;
- }
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/filter/Coin.feature b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/filter/Coin.feature
index fd007fb320..8ba4265b8c 100644
--- a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/filter/Coin.feature
+++ b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/filter/Coin.feature
@@ -34,6 +34,23 @@ Feature: Step - coin()
| v[ripple] |
| v[peter] |
+ Scenario: g_V_coinX1varX
+ Given the modern graph
+ And using the parameter xx1 defined as "d[1.0].d"
+ And the traversal of
+ """
+ g.V().coin(xx1)
+ """
+ When iterated to list
+ Then the result should be unordered
+ | result |
+ | v[marko] |
+ | v[vadas] |
+ | v[lop] |
+ | v[josh] |
+ | v[ripple] |
+ | v[peter] |
+
Scenario: g_V_coinX0X
Given the modern graph
And the traversal of
diff --git a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/filter/Has.feature b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/filter/Has.feature
index 42059bccdb..2cb5e0bab1 100644
--- a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/filter/Has.feature
+++ b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/filter/Has.feature
@@ -153,6 +153,19 @@ Feature: Step - has()
When iterated to list
Then the result should be empty
+ Scenario: g_V_hasXpersonvar_age_gt_30X
+ Given the modern graph
+ And using the parameter xx1 defined as "person"
+ And the traversal of
+ """
+ g.V().has(xx1, "age", P.gt(30))
+ """
+ When iterated to list
+ Then the result should be unordered
+ | result |
+ | v[peter] |
+ | v[josh] |
+
Scenario: g_VX4X_hasXage_gt_30X
Given the modern graph
And using the parameter vid4 defined as "v[josh].id"
diff --git a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/filter/HasId.feature b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/filter/HasId.feature
index 2cb6992510..0fd1de7e52 100644
--- a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/filter/HasId.feature
+++ b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/filter/HasId.feature
@@ -93,6 +93,35 @@ Feature: Step - hasId()
| result |
| v[vadas] |
+ Scenario: g_V_hasIdXmarkovar_vadasvarX
+ Given the modern graph
+ And using the parameter vid1 defined as "v[marko].id"
+ And using the parameter vid2 defined as "v[vadas].id"
+ And the traversal of
+ """
+ g.V().hasId(vid1, vid2)
+ """
+ When iterated to list
+ Then the result should be unordered
+ | result |
+ | v[marko] |
+ | v[vadas] |
+
+ Scenario: g_V_hasIdXmarkovar_vadasvar_petervarX
+ Given the modern graph
+ And using the parameter vid1 defined as "v[marko].id"
+ And using the parameter vid2 defined as "l[v[vadas].id,v[peter].id]"
+ And the traversal of
+ """
+ g.V().hasId(vid1, vid2)
+ """
+ When iterated to list
+ Then the result should be unordered
+ | result |
+ | v[marko] |
+ | v[vadas] |
+ | v[peter] |
+
Scenario: g_V_hasIdX2AsString_nullX
Given the modern graph
And using the parameter vid2 defined as "v[vadas].sid"
diff --git a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/filter/HasLabel.feature b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/filter/HasLabel.feature
index 2da655e7e6..c9484790ca 100644
--- a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/filter/HasLabel.feature
+++ b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/filter/HasLabel.feature
@@ -78,6 +78,23 @@ Feature: Step - hasLabel()
| v[lop] |
| v[ripple] |
+ Scenario: g_V_hasLabelXperson_softwarevarX
+ Given the modern graph
+ And using the parameter xx1 defined as "software"
+ And the traversal of
+ """
+ g.V().hasLabel("person",xx1)
+ """
+ When iterated to list
+ Then the result should be unordered
+ | result |
+ | v[marko] |
+ | v[vadas] |
+ | v[josh] |
+ | v[peter] |
+ | v[lop] |
+ | v[ripple] |
+
Scenario: g_V_hasLabelXpersonX_hasLabelXsoftwareX
Given the modern graph
And the traversal of
diff --git a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/AddEdge.feature b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/AddEdge.feature
index b2cd709619..827eaa6dc6 100644
--- a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/AddEdge.feature
+++ b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/AddEdge.feature
@@ -479,4 +479,20 @@ Feature: Step - addE()
"""
When iterated to list
Then the result should have a count of 1
- And the graph should return 1 for count of "g.E().has(\"knows\",\"weight\",null)"
\ No newline at end of file
+ And the graph should return 1 for count of "g.E().has(\"knows\",\"weight\",null)"
+
+ Scenario: g_unionXaddEXknowsvarXpropertyXweight_nullXfromXV_hasXname_markoXX_toXV_hasXname_vadasXXX
+ Given the empty graph
+ And the graph initializer of
+ """
+ g.addV("person").property("name", "marko").property("age", 29).
+ addV("person").property("name", "vadas").property("age", 27)
+ """
+ And using the parameter xx1 defined as "knows"
+ And the traversal of
+ """
+ g.union(addE(xx1).property("weight", 1).from(V().has("name","marko")).to(V().has("name","vadas")))
+ """
+ When iterated to list
+ Then the result should have a count of 1
+ And the graph should return 1 for count of "g.E().has(\"knows\",\"weight\", 1)"
\ No newline at end of file
diff --git a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/Combine.feature b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/Combine.feature
index f40f5cbe51..d09a295406 100644
--- a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/Combine.feature
+++ b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/Combine.feature
@@ -66,6 +66,16 @@ Feature: Step - combine()
When iterated to list
Then the traversal will raise an error with message containing text of "combine step can only take an array or an Iterable as an argument, encountered"
+ Scenario: g_V_valuesXnameX_fold_combineX2varX
+ Given the modern graph
+ And using the parameter xx1 defined as "2"
+ And the traversal of
+ """
+ g.V().values("name").fold().combine(xx1)
+ """
+ When iterated to list
+ Then the traversal will raise an error with message containing text of "combine step can only take an array or an Iterable as an argument, encountered"
+
Scenario: g_V_valuesXnameX_fold_combineXnullX
Given the modern graph
And the traversal of
diff --git a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/Difference.feature b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/Difference.feature
index 18d5043f3c..67e871cbbc 100644
--- a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/Difference.feature
+++ b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/Difference.feature
@@ -66,6 +66,16 @@ Feature: Step - difference()
When iterated to list
Then the traversal will raise an error with message containing text of "difference step can only take an array or an Iterable as an argument, encountered"
+ Scenario: g_V_valuesXnameX_fold_differenceX2varX
+ Given the modern graph
+ And using the parameter xx1 defined as "2"
+ And the traversal of
+ """
+ g.V().values("name").fold().difference(xx1)
+ """
+ When iterated to list
+ Then the traversal will raise an error with message containing text of "difference step can only take an array or an Iterable as an argument, encountered"
+
Scenario: g_V_valuesXnameX_fold_differenceXnullX
Given the modern graph
And the traversal of
diff --git a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/Disjunct.feature b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/Disjunct.feature
index e6fcee1535..90fcafdd3a 100644
--- a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/Disjunct.feature
+++ b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/Disjunct.feature
@@ -66,6 +66,16 @@ Feature: Step - disjunct()
When iterated to list
Then the traversal will raise an error with message containing text of "disjunct step can only take an array or an Iterable as an argument, encountered"
+ Scenario: g_V_valuesXnameX_fold_disjunctX3varX
+ Given the modern graph
+ And using the parameter xx1 defined as "3"
+ And the traversal of
+ """
+ g.V().values("name").fold().disjunct(xx1)
+ """
+ When iterated to list
+ Then the traversal will raise an error with message containing text of "disjunct step can only take an array or an Iterable as an argument, encountered"
+
Scenario: g_V_valuesXnameX_fold_disjunctXnullX
Given the modern graph
And the traversal of
diff --git a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/Edge.feature b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/Edge.feature
index 7d75a251af..c1c8ded961 100644
--- a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/Edge.feature
+++ b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/Edge.feature
@@ -355,4 +355,17 @@ Feature: Step - E(), inV(), outV(), bothV(), otherV()
| marko |
| marko |
| josh |
- | vadas |
\ No newline at end of file
+ | vadas |
+
+ Scenario: g_V_toEXout_knowsvarX_valuesXweightX
+ Given the modern graph
+ And using the parameter xx1 defined as "knows"
+ And the traversal of
+ """
+ g.V().toE(Direction.OUT, xx1).values("weight")
+ """
+ When iterated to list
+ Then the result should be unordered
+ | result |
+ | d[0.5].d |
+ | d[1.0].d |
\ No newline at end of file
diff --git a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/Intersect.feature b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/Intersect.feature
index c6b44844f0..37ba287a20 100644
--- a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/Intersect.feature
+++ b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/Intersect.feature
@@ -66,6 +66,16 @@ Feature: Step - intersect()
When iterated to list
Then the traversal will raise an error with message containing text of "intersect step can only take an array or an Iterable as an argument, encountered"
+ Scenario: g_V_valuesXnameX_fold_intersectX5varX
+ Given the modern graph
+ And using the parameter xx1 defined as "5"
+ And the traversal of
+ """
+ g.V().values("name").fold().intersect(xx1)
+ """
+ When iterated to list
+ Then the traversal will raise an error with message containing text of "intersect step can only take an array or an Iterable as an argument, encountered"
+
Scenario: g_V_valuesXnameX_fold_intersectXnullX
Given the modern graph
And the traversal of
diff --git a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/MergeEdge.feature b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/MergeEdge.feature
index 5c085da304..43642f3dcc 100644
--- a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/MergeEdge.feature
+++ b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/MergeEdge.feature
@@ -86,6 +86,7 @@ Feature: Step - mergeE()
# - vertices already exists
# - results in two new edges
# g_mergeEXnullX
+ # g_mergeEXnullvarX
# g_V_mergeEXnullX
# - mergeE(null) and no option
# - vertices already exists
@@ -271,6 +272,34 @@ Feature: Step - mergeE()
When iterated to list
Then the traversal will raise an error with message containing text of "Out Vertex not specified"
+ Scenario: g_mergeEXnullvarX
+ Given the empty graph
+ And the graph initializer of
+ """
+ g.addV("person").property("name", "marko").property("age", 29)
+ """
+ And using the parameter xx1 defined as "null"
+ And the traversal of
+ """
+ g.mergeE(xx1)
+ """
+ When iterated to list
+ Then the traversal will raise an error with message containing text of "Out Vertex not specified"
+
+ Scenario: g_V_limitX1X_mergeEXnullvarX
+ Given the empty graph
+ And the graph initializer of
+ """
+ g.addV("person").property("name", "marko").property("age", 29)
+ """
+ And using the parameter xx1 defined as "null"
+ And the traversal of
+ """
+ g.V().limit(1).mergeE(xx1)
+ """
+ When iterated to list
+ Then the traversal will raise an error with message containing text of "Out Vertex not specified"
+
# Directions not specified
Scenario: g_V_mergeEXnullX
Given the empty graph
diff --git a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/MergeVertex.feature b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/MergeVertex.feature
index 4d678ea1af..22c1457fad 100644
--- a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/MergeVertex.feature
+++ b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/MergeVertex.feature
@@ -65,6 +65,7 @@ Feature: Step - mergeV()
# - mergeV(Map) with no option() - testing child traversal usage
# - results in one new vertex and one existing vertex that was just created
# g_mergeVXnullX
+ # g_mergeVXnullvarX
# g_V_mergeVXnullX
# - mergeV(null) with no option()
# - results in no new vertex and nothing returned
@@ -285,6 +286,23 @@ Feature: Step - mergeV()
Then the result should have a count of 1
And the graph should return 1 for count of "g.V()"
+ @GremlinLangScriptOnly
+ Scenario: g_mergeVXnullvarX
+ Given the empty graph
+ And the graph initializer of
+ """
+ g.addV("person").property("name", "marko").property("age", 29)
+ """
+ And using the parameter xx1 defined as "null"
+ And the traversal of
+ """
+ g.mergeV(xx1)
+ """
+ When iterated to list
+ Then the result should have a count of 1
+ And the graph should return 1 for count of "g.V()"
+
+ @GremlinLangScriptOnly
Scenario: g_V_mergeVXnullX
Given the empty graph
And the graph initializer of
@@ -937,6 +955,22 @@ Feature: Step - mergeV()
And the graph should return 1 for count of "g.V().has(\"person\",\"name\",\"allen\").has(\"age\")"
And the graph should return 3 for count of "g.V().has(\"person\",\"name\",\"allen\").properties(\"age\")"
+ Scenario: g_mergeVXname_markoX_optionXonMatch_name_allen_var_singleX
+ Given the empty graph
+ And the graph initializer of
+ """
+ g.addV("person").property("name", "marko")
+ """
+ And using the parameter xx1 defined as "m[{\"name\":\"allen\"}]"
+ And the traversal of
+ """
+ g.mergeV([name: "marko"]).option(Merge.onMatch, xx1, single)
+ """
+ When iterated to list
+ Then the result should have a count of 1
+ And the graph should return 0 for count of "g.V().has(\"person\",\"name\",\"marko\")"
+ And the graph should return 1 for count of "g.V().has(\"person\",\"name\",\"allen\")"
+
@MultiProperties
Scenario: g_mergeVXname_markoX_optionXonMatch_name_allen_age_singleX31X_singleX
Given the empty graph
diff --git a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/Product.feature b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/Product.feature
index 5c12867440..a16c62bae2 100644
--- a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/Product.feature
+++ b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/Product.feature
@@ -66,6 +66,16 @@ Feature: Step - product()
When iterated to list
Then the traversal will raise an error with message containing text of "product step can only take an array or an Iterable as an argument, encountered"
+ Scenario: g_V_valuesXnameX_fold_productX7varX
+ Given the modern graph
+ And using the parameter xx1 defined as "7"
+ And the traversal of
+ """
+ g.V().values("name").fold().product(xx1)
+ """
+ When iterated to list
+ Then the traversal will raise an error with message containing text of "product step can only take an array or an Iterable as an argument, encountered"
+
Scenario: g_V_valuesXnameX_fold_productXnullX
Given the modern graph
And the traversal of
(tinkerpop) 02/05: TINKERPOP-2959 Restrict Arguments in Grammar
Posted by co...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
colegreer pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/tinkerpop.git
commit 68866d1b2bb1ec7aebce9bb8a810c9c10da304ef
Author: Cole-Greer <Co...@improving.com>
AuthorDate: Fri Dec 6 18:53:47 2024 -0800
TINKERPOP-2959 Restrict Arguments in Grammar
The change from DirectVariableResolver (always produces literals) to the new
DefaultVariableResolver (produces GValues) leads to unintended consequences
if users attempt to pass a variable into a step which does not accept GValue.
The grammar is being reduced to only accept variables in places which parameterization
is explicitly intended, in steps which accept GValue.
This commit additionally adds many more tests to ensure appropriate coverage for all
parameterizable steps.
Serializers for the Merge enum have been reintroduced in order to allow parameterization
of the maps for mergeE().
Note that currently, the grammar uses a naming convention for
varargs such that "stringLiteralVarargs" is defined as 0 or more
"StringNullableArgument", not "StringNullableLiteral". This
naming convention for varargs is misleading, although I have not
addressed it in this commit to avoid unnecessary clutter to the
diff. This commit introduces a new type "stringLiteralVarargsLiterals"
as a temporary placeholder for varargs of actual "StringNullableLiteral".
This work is intended to be followed by a CTR
which renames stringLiteralVarargs to stringArgumentVarargs, and then
the new stringLiteralVarargsLiterals can assume the correct name of
stringLiteralVarargs.
Co-authored-by: Yang Xia <55...@users.noreply.github.com>
Co-authored-by: Ken Hu <10...@users.noreply.github.com>
---
.../gremlin/language/grammar/ArgumentVisitor.java | 105 +++++-----
.../grammar/DefaultGremlinBaseVisitor.java | 4 +
.../language/grammar/GenericLiteralVisitor.java | 13 +-
.../language/grammar/TraversalMethodVisitor.java | 227 +++++++++++----------
.../grammar/TraversalSourceSelfMethodVisitor.java | 8 +-
.../grammar/TraversalSourceSpawnMethodVisitor.java | 28 ++-
.../translator/DotNetTranslateVisitor.java | 56 ++---
.../language/translator/TranslateVisitor.java | 5 +
.../gremlin/process/traversal/GremlinLang.java | 41 +---
.../traversal/dsl/graph/GraphTraversal.java | 166 ++++++++++++---
.../traversal/dsl/graph/GraphTraversalSource.java | 28 ++-
.../gremlin/process/traversal/dsl/graph/__.java | 115 ++++++++---
.../traversal/lambda/ConstantTraversal.java | 4 +-
.../gremlin/process/traversal/step/GValue.java | 35 ++--
.../process/traversal/step/branch/RepeatStep.java | 4 +-
.../process/traversal/step/filter/CoinStep.java | 4 +-
.../traversal/step/map/AddEdgeStartStep.java | 6 +
.../process/traversal/step/map/AddEdgeStep.java | 9 +-
.../traversal/step/map/AddVertexStartStep.java | 7 +
.../process/traversal/step/map/CallStep.java | 4 +-
.../process/traversal/step/map/CombineStep.java | 2 +-
.../process/traversal/step/map/ConjoinStep.java | 2 +-
.../process/traversal/step/map/ConstantStep.java | 4 +-
.../process/traversal/step/map/DifferenceStep.java | 2 +-
.../process/traversal/step/map/DisjunctStep.java | 2 +-
.../process/traversal/step/map/IntersectStep.java | 2 +-
.../process/traversal/step/map/MergeStep.java | 4 +-
.../process/traversal/step/map/ProductStep.java | 2 +-
.../gremlin/structure/io/binary/DataType.java | 1 +
.../io/binary/TypeSerializerRegistry.java | 2 +
.../structure/io/binary/types/EnumSerializer.java | 1 +
.../structure/io/graphson/GraphSONModule.java | 2 +
.../language/grammar/ArgumentVisitorTest.java | 96 +++++----
.../grammar/TraversalMethodVisitorTest.java | 2 +-
.../language/translator/GremlinTranslatorTest.java | 10 +-
.../remote/EmbeddedRemoteConnectionTest.java | 5 +-
.../gremlin/process/traversal/GremlinLangTest.java | 20 +-
.../dsl/graph/GraphTraversalSourceTest.java | 14 +-
.../gremlin/process/traversal/step/GValueTest.java | 2 +-
.../strategy/decoration/PartitionStrategyTest.java | 3 +-
gremlin-javascript/build/generate.groovy | 2 +-
.../gremlin-javascript/test/cucumber/gremlin.js | 28 ++-
gremlin-language/src/main/antlr4/Gremlin.g4 | 160 ++++++++-------
.../language/grammar/ReferenceGrammarTest.java | 6 +
gremlin-python/docker-compose.yml | 4 +-
.../python/gremlin_python/process/traversal.py | 33 +--
.../gremlin_python/structure/io/graphbinaryV4.py | 8 +-
.../gremlin_python/structure/io/graphsonV4.py | 9 +
.../src/main/python/radish/feature_steps.py | 13 +-
gremlin-python/src/main/python/radish/gremlin.py | 24 ++-
.../src/main/python/tests/driver/test_client.py | 6 +-
.../tests/driver/test_driver_remote_connection.py | 4 +-
.../main/python/tests/process/test_gremlin_lang.py | 35 ++--
.../remote/GraphBinaryLangRemoteFeatureTest.java | 1 +
.../gremlin/driver/remote/RemoteWorld.java | 15 ++
.../gremlin/server/HttpDriverIntegrateTest.java | 5 +-
.../tinkerpop/gremlin/features/StepDefinition.java | 12 +-
.../gremlin/test/features/filter/Has.feature | 13 ++
.../gremlin/test/features/filter/HasId.feature | 1 +
.../gremlin/test/features/filter/Is.feature | 39 ++++
.../gremlin/test/features/filter/Where.feature | 3 +-
.../gremlin/test/features/map/AddEdge.feature | 48 +++++
.../gremlin/test/features/map/AddVertex.feature | 88 ++++++++
.../gremlin/test/features/map/Call.feature | 1 +
.../gremlin/test/features/map/MergeEdge.feature | 69 +++++++
.../gremlin/test/features/map/Vertex.feature | 30 +++
.../test/features/sideEffect/Inject.feature | 77 ++++++-
.../process/TraversalConstructionBenchmark.java | 6 +-
.../tinkergraph/TinkerGraphFeatureTest.java | 1 +
69 files changed, 1239 insertions(+), 549 deletions(-)
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/ArgumentVisitor.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/ArgumentVisitor.java
index 4daa11d9b1..9c0a1eca4e 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/ArgumentVisitor.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/ArgumentVisitor.java
@@ -18,12 +18,15 @@
*/
package org.apache.tinkerpop.gremlin.language.grammar;
+import org.apache.tinkerpop.gremlin.process.traversal.step.GType;
+import org.apache.tinkerpop.gremlin.process.traversal.step.GValue;
import org.apache.tinkerpop.gremlin.structure.Vertex;
import org.apache.tinkerpop.gremlin.util.iterator.IteratorUtils;
import java.lang.reflect.Array;
import java.time.OffsetDateTime;
import java.util.Map;
+import java.util.Objects;
public class ArgumentVisitor extends DefaultGremlinBaseVisitor<Object> {
@@ -36,67 +39,16 @@ public class ArgumentVisitor extends DefaultGremlinBaseVisitor<Object> {
this.antlr = antlr;
}
- /**
- * Wrapper to visit function for boolean.
- */
- public boolean parseBoolean(final GremlinParser.BooleanArgumentContext ctx) {
- return (boolean) visitBooleanArgument(ctx);
- }
-
- /**
- * Wrapper to visit function for integer types.
- */
- public Number parseNumber(final GremlinParser.IntegerArgumentContext ctx) {
- return (Number) visitIntegerArgument(ctx);
- }
-
- /**
- * Wrapper to visit function for float types.
- */
- public Number parseNumber(final GremlinParser.FloatArgumentContext ctx) {
- return (Number) visitFloatArgument(ctx);
- }
-
- /**
- * Wrapper to visit function for string types.
- */
- public String parseString(final GremlinParser.StringArgumentContext ctx) {
- return (String) visitStringArgument(ctx);
- }
-
- /**
- * Wrapper to visit function for Date type.
- */
- public OffsetDateTime parseDate(final GremlinParser.DateArgumentContext ctx) {
- return (OffsetDateTime) visitDateArgument(ctx);
- }
-
- /**
- * Wrapper for visit function for object types.
- */
- public Object parseObject(final GremlinParser.GenericLiteralArgumentContext ctx) {
- return visitGenericLiteralArgument(ctx);
- }
-
- /**
- * Wrapper for visit function for {@link Vertex} types.
- */
- public Vertex parseVertex(final GremlinParser.StructureVertexArgumentContext ctx) {
- return (Vertex) visitStructureVertexArgument(ctx);
- }
-
- /**
- * Wrapper for visit function for {@code Map} types.
- */
- public Map parseMap(final GremlinParser.GenericLiteralMapArgumentContext ctx) {
- return (Map) visitGenericLiteralMapArgument(ctx);
- }
-
/**
* Wrapper for visit function for {@code Map} types.
*/
public Map parseMap(final GremlinParser.GenericLiteralMapNullableArgumentContext ctx) {
- return (Map) visitGenericLiteralMapNullableArgument(ctx);
+ Object literalOrVar = visitGenericLiteralMapNullableArgument(ctx);
+ if (GValue.valueInstanceOf(literalOrVar, GType.MAP)) {
+ return ((GValue<Map>) literalOrVar).get();
+ } else {
+ return (Map) literalOrVar;
+ }
}
/**
@@ -124,11 +76,30 @@ public class ArgumentVisitor extends DefaultGremlinBaseVisitor<Object> {
}
}
+ /**
+ * Parse a string argument varargs, and return an string array
+ */
+ public GValue<String>[] parseStringVarargs(final GremlinParser.StringLiteralVarargsContext varargsContext) {
+ if (varargsContext == null || varargsContext.stringNullableArgument() == null) {
+ return new GValue[0];
+ }
+ return varargsContext.stringNullableArgument()
+ .stream()
+ .filter(Objects::nonNull)
+ .map(antlr.argumentVisitor::parseString)
+ .toArray(GValue[]::new);
+ }
+
/**
* Wrapper to visit function for string types.
*/
- public String parseString(final GremlinParser.StringNullableArgumentContext ctx) {
- return (String) visitStringNullableArgument(ctx);
+ public GValue<String> parseString(final GremlinParser.StringNullableArgumentContext ctx) {
+ Object literalOrVar = visitStringNullableArgument((ctx));
+ if (GValue.valueInstanceOf(literalOrVar, GType.STRING)) {
+ return (GValue<String>) literalOrVar;
+ } else {
+ return GValue.ofString(null, (String) literalOrVar);
+ }
}
@Override
@@ -194,6 +165,11 @@ public class ArgumentVisitor extends DefaultGremlinBaseVisitor<Object> {
}
}
+ @Override
+ public Object visitGenericLiteral(final GremlinParser.GenericLiteralContext ctx) {
+ return antlr.genericVisitor.visitGenericLiteral(ctx);
+ }
+
@Override
public Object visitGenericLiteralListArgument(final GremlinParser.GenericLiteralListArgumentContext ctx) {
if (ctx.genericLiteralList() != null) {
@@ -236,4 +212,15 @@ public class ArgumentVisitor extends DefaultGremlinBaseVisitor<Object> {
public Object visitVariable(final GremlinParser.VariableContext ctx) {
return resolver.apply(ctx.getText(), ctx);
}
+
+ /**
+ * Create a new {@code GValue} from a particular value but without the specified name. If the argument provide is
+ * already a {@code GValue} then it is returned as-is.
+ *
+ * @param value the value of the variable
+ */
+ public static <V> GValue<V> asGValue(final V value) {
+ if (value instanceof GValue) return (GValue) value;
+ return GValue.of(null, value);
+ }
}
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/DefaultGremlinBaseVisitor.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/DefaultGremlinBaseVisitor.java
index c7a255cd34..4f7dec68ff 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/DefaultGremlinBaseVisitor.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/DefaultGremlinBaseVisitor.java
@@ -1645,6 +1645,10 @@ public class DefaultGremlinBaseVisitor<T> extends AbstractParseTreeVisitor<T> im
* {@inheritDoc}
*/
@Override public T visitStringLiteralVarargs(final GremlinParser.StringLiteralVarargsContext ctx) { notImplemented(ctx); return null; }
+ /**
+ * {@inheritDoc}
+ */
+ @Override public T visitStringLiteralVarargsLiterals(final GremlinParser.StringLiteralVarargsLiteralsContext ctx) { notImplemented(ctx); return null; }
/**
* {@inheritDoc}
*/
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/GenericLiteralVisitor.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/GenericLiteralVisitor.java
index fb124ec910..0f86540636 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/GenericLiteralVisitor.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/GenericLiteralVisitor.java
@@ -25,6 +25,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.Merge;
import org.apache.tinkerpop.gremlin.process.traversal.Pick;
import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.step.GValue;
import org.apache.tinkerpop.gremlin.structure.T;
import org.apache.tinkerpop.gremlin.structure.VertexProperty;
import org.apache.tinkerpop.gremlin.util.DatetimeHelper;
@@ -140,16 +141,16 @@ public class GenericLiteralVisitor extends DefaultGremlinBaseVisitor<Object> {
}
/**
- * Parse a string literal varargs, and return an string array
+ * Parse a string literal varargs, and return a string array
*/
- public String[] parseStringVarargs(final GremlinParser.StringLiteralVarargsContext varargsContext) {
- if (varargsContext == null || varargsContext.stringNullableArgument() == null) {
+ public String[] parseStringVarargsLiterals(final GremlinParser.StringLiteralVarargsLiteralsContext varargsContext) {
+ if (varargsContext == null || varargsContext.stringNullableLiteral() == null) {
return new String[0];
}
- return varargsContext.stringNullableArgument()
+ return varargsContext.stringNullableLiteral()
.stream()
.filter(Objects::nonNull)
- .map(antlr.argumentVisitor::parseString)
+ .map(antlr.genericVisitor::parseString)
.toArray(String[]::new);
}
@@ -364,8 +365,6 @@ public class GenericLiteralVisitor extends DefaultGremlinBaseVisitor<Object> {
return literalMap;
}
-
-
/**
* {@inheritDoc}
*/
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalMethodVisitor.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalMethodVisitor.java
index 1d107e6a88..55c74aeea8 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalMethodVisitor.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalMethodVisitor.java
@@ -91,7 +91,12 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
*/
@Override
public GraphTraversal visitTraversalMethod_addV_String(final GremlinParser.TraversalMethod_addV_StringContext ctx) {
- return this.graphTraversal.addV(antlr.argumentVisitor.parseString(ctx.stringArgument()));
+ final Object literalOrVar = antlr.argumentVisitor.visitStringArgument(ctx.stringArgument());
+ if (GValue.valueInstanceOf(literalOrVar, GType.STRING)) {
+ return this.graphTraversal.addV((GValue<String>) literalOrVar);
+ } else {
+ return this.graphTraversal.addV((String) literalOrVar);
+ }
}
/**
@@ -171,7 +176,12 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
*/
@Override
public GraphTraversal visitTraversalMethod_addE_String(final GremlinParser.TraversalMethod_addE_StringContext ctx) {
- return this.graphTraversal.addE(antlr.argumentVisitor.parseString(ctx.stringArgument()));
+ final Object literalOrVar = antlr.argumentVisitor.visitStringArgument(ctx.stringArgument());
+ if (GValue.valueInstanceOf(literalOrVar, GType.STRING)) {
+ return this.graphTraversal.addE((GValue<String>) literalOrVar);
+ } else {
+ return this.graphTraversal.addE((String) literalOrVar);
+ }
}
/**
@@ -179,7 +189,7 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
*/
@Override
public GraphTraversal visitTraversalMethod_aggregate_String(final GremlinParser.TraversalMethod_aggregate_StringContext ctx) {
- return graphTraversal.aggregate(antlr.argumentVisitor.parseString(ctx.stringArgument()));
+ return graphTraversal.aggregate(antlr.genericVisitor.parseString(ctx.stringLiteral()));
}
/**
@@ -189,7 +199,7 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
public GraphTraversal visitTraversalMethod_aggregate_Scope_String(final GremlinParser.TraversalMethod_aggregate_Scope_StringContext ctx) {
return graphTraversal.aggregate(
TraversalEnumParser.parseTraversalEnumFromContext(Scope.class, ctx.traversalScope()),
- antlr.argumentVisitor.parseString(ctx.stringArgument()));
+ antlr.genericVisitor.parseString(ctx.stringLiteral()));
}
/**
@@ -223,10 +233,10 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
@Override
public GraphTraversal visitTraversalMethod_as(final GremlinParser.TraversalMethod_asContext ctx) {
if (ctx.getChildCount() == 4) {
- return graphTraversal.as(antlr.argumentVisitor.parseString(ctx.stringArgument()));
+ return graphTraversal.as(antlr.genericVisitor.parseString(ctx.stringLiteral()));
} else {
- return graphTraversal.as(antlr.argumentVisitor.parseString(ctx.stringArgument()),
- antlr.genericVisitor.parseStringVarargs(ctx.stringLiteralVarargs()));
+ return graphTraversal.as(antlr.genericVisitor.parseString(ctx.stringLiteral()),
+ antlr.genericVisitor.parseStringVarargsLiterals(ctx.stringLiteralVarargsLiterals()));
}
}
@@ -251,7 +261,7 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
*/
@Override
public GraphTraversal visitTraversalMethod_barrier_int(final GremlinParser.TraversalMethod_barrier_intContext ctx) {
- return graphTraversal.barrier(antlr.argumentVisitor.parseNumber(ctx.integerArgument()).intValue());
+ return graphTraversal.barrier(antlr.genericVisitor.parseIntegral(ctx.integerLiteral()).intValue());
}
/**
@@ -259,7 +269,7 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
*/
@Override
public GraphTraversal visitTraversalMethod_both(final GremlinParser.TraversalMethod_bothContext ctx) {
- return graphTraversal.both(antlr.genericVisitor.parseStringVarargs(ctx.stringLiteralVarargs()));
+ return graphTraversal.both(antlr.argumentVisitor.parseStringVarargs(ctx.stringLiteralVarargs()));
}
/**
@@ -267,7 +277,7 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
*/
@Override
public GraphTraversal visitTraversalMethod_bothE(final GremlinParser.TraversalMethod_bothEContext ctx) {
- return graphTraversal.bothE(antlr.genericVisitor.parseStringVarargs(ctx.stringLiteralVarargs()));
+ return graphTraversal.bothE(antlr.argumentVisitor.parseStringVarargs(ctx.stringLiteralVarargs()));
}
/**
@@ -332,7 +342,7 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
*/
@Override
public GraphTraversal visitTraversalMethod_by_String(final GremlinParser.TraversalMethod_by_StringContext ctx) {
- return graphTraversal.by(antlr.argumentVisitor.parseString(ctx.stringArgument()));
+ return graphTraversal.by(antlr.genericVisitor.parseString(ctx.stringLiteral()));
}
/**
@@ -340,7 +350,7 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
*/
@Override
public GraphTraversal visitTraversalMethod_by_String_Comparator(final GremlinParser.TraversalMethod_by_String_ComparatorContext ctx) {
- return graphTraversal.by(antlr.argumentVisitor.parseString(ctx.stringArgument()),
+ return graphTraversal.by(antlr.genericVisitor.parseString(ctx.stringLiteral()),
TraversalEnumParser.parseTraversalEnumFromContext(Order.class, ctx.getChild(4)));
}
@@ -375,10 +385,10 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
@Override
public GraphTraversal visitTraversalMethod_cap(final GremlinParser.TraversalMethod_capContext ctx) {
if (ctx.getChildCount() == 4) {
- return graphTraversal.cap(antlr.argumentVisitor.parseString(ctx.stringArgument()));
+ return graphTraversal.cap(antlr.genericVisitor.parseString(ctx.stringLiteral()));
} else {
- return graphTraversal.cap(antlr.argumentVisitor.parseString(ctx.stringArgument()),
- antlr.genericVisitor.parseStringVarargs(ctx.stringLiteralVarargs()));
+ return graphTraversal.cap(antlr.genericVisitor.parseString(ctx.stringLiteral()),
+ antlr.genericVisitor.parseStringVarargsLiterals(ctx.stringLiteralVarargsLiterals()));
}
}
@@ -523,7 +533,7 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
@Override
public GraphTraversal visitTraversalMethod_dedup_Scope_String(final GremlinParser.TraversalMethod_dedup_Scope_StringContext ctx) {
return graphTraversal.dedup(TraversalEnumParser.parseTraversalEnumFromContext(Scope.class, ctx.traversalScope()),
- antlr.genericVisitor.parseStringVarargs(ctx.stringLiteralVarargs()));
+ antlr.genericVisitor.parseStringVarargsLiterals(ctx.stringLiteralVarargsLiterals()));
}
/**
@@ -531,7 +541,7 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
*/
@Override
public GraphTraversal visitTraversalMethod_dedup_String(final GremlinParser.TraversalMethod_dedup_StringContext ctx) {
- return graphTraversal.dedup(antlr.genericVisitor.parseStringVarargs(ctx.stringLiteralVarargs()));
+ return graphTraversal.dedup(antlr.genericVisitor.parseStringVarargsLiterals(ctx.stringLiteralVarargsLiterals()));
}
/**
@@ -603,7 +613,7 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
*/
@Override
public Traversal visitTraversalMethod_fail_String(final GremlinParser.TraversalMethod_fail_StringContext ctx) {
- return this.graphTraversal.fail(antlr.argumentVisitor.parseString(ctx.stringArgument()));
+ return this.graphTraversal.fail(antlr.genericVisitor.parseString(ctx.stringLiteral()));
}
/**
@@ -689,7 +699,7 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
*/
@Override
public GraphTraversal visitTraversalMethod_groupCount_String(final GremlinParser.TraversalMethod_groupCount_StringContext ctx) {
- return graphTraversal.groupCount(antlr.argumentVisitor.parseString(ctx.stringArgument()));
+ return graphTraversal.groupCount(antlr.genericVisitor.parseString(ctx.stringLiteral()));
}
/**
@@ -705,7 +715,7 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
*/
@Override
public GraphTraversal visitTraversalMethod_group_String(final GremlinParser.TraversalMethod_group_StringContext ctx) {
- return graphTraversal.group(antlr.argumentVisitor.parseString(ctx.stringArgument()));
+ return graphTraversal.group(antlr.genericVisitor.parseString(ctx.stringLiteral()));
}
/**
@@ -739,10 +749,10 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
@Override
public GraphTraversal visitTraversalMethod_hasKey_String_String(final GremlinParser.TraversalMethod_hasKey_String_StringContext ctx) {
if (ctx.getChildCount() == 4) {
- return graphTraversal.hasKey(antlr.argumentVisitor.parseString(ctx.stringNullableArgument()));
+ return graphTraversal.hasKey(antlr.genericVisitor.parseString(ctx.stringNullableLiteral()));
} else {
- return graphTraversal.hasKey(antlr.argumentVisitor.parseString(ctx.stringNullableArgument()),
- antlr.genericVisitor.parseStringVarargs(ctx.stringLiteralVarargs()));
+ return graphTraversal.hasKey(antlr.genericVisitor.parseString(ctx.stringNullableLiteral()),
+ antlr.genericVisitor.parseStringVarargsLiterals(ctx.stringLiteralVarargsLiterals()));
}
}
@@ -771,7 +781,7 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
// if any are GValue then they all need to be GValue to call hasLabel
if (literalOrVar instanceof GValue || Arrays.stream(literalOrVars).anyMatch(lov -> lov instanceof GValue)) {
- literalOrVar = GValue.of(literalOrVar);
+ literalOrVar = ArgumentVisitor.asGValue(literalOrVar);
literalOrVars = GValue.ensureGValues(literalOrVars);
}
@@ -792,7 +802,7 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
*/
@Override
public GraphTraversal visitTraversalMethod_hasNot(final GremlinParser.TraversalMethod_hasNotContext ctx) {
- return graphTraversal.hasNot(antlr.argumentVisitor.parseString(ctx.stringNullableArgument()));
+ return graphTraversal.hasNot(antlr.genericVisitor.parseString(ctx.stringNullableLiteral()));
}
/**
@@ -817,7 +827,7 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
*/
@Override
public GraphTraversal visitTraversalMethod_has_String(final GremlinParser.TraversalMethod_has_StringContext ctx) {
- return graphTraversal.has(antlr.argumentVisitor.parseString(ctx.stringNullableArgument()));
+ return graphTraversal.has(antlr.genericVisitor.parseString(ctx.stringNullableLiteral()));
}
/**
@@ -825,7 +835,7 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
*/
@Override
public GraphTraversal visitTraversalMethod_has_String_Object(final GremlinParser.TraversalMethod_has_String_ObjectContext ctx) {
- return graphTraversal.has(antlr.argumentVisitor.parseString(ctx.stringNullableArgument()),
+ return graphTraversal.has(antlr.genericVisitor.parseString(ctx.stringNullableLiteral()),
antlr.argumentVisitor.visitGenericLiteralArgument(ctx.genericLiteralArgument()));
}
@@ -834,7 +844,7 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
*/
@Override
public GraphTraversal visitTraversalMethod_has_String_P(final GremlinParser.TraversalMethod_has_String_PContext ctx) {
- return graphTraversal.has(antlr.argumentVisitor.parseString(ctx.stringNullableArgument()),
+ return graphTraversal.has(antlr.genericVisitor.parseString(ctx.stringNullableLiteral()),
antlr.traversalPredicateVisitor.visitTraversalPredicate(ctx.traversalPredicate()));
}
@@ -843,14 +853,14 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
*/
@Override
public GraphTraversal visitTraversalMethod_has_String_String_Object(final GremlinParser.TraversalMethod_has_String_String_ObjectContext ctx) {
- final Object literalOrVar = antlr.argumentVisitor.visitStringNullableArgument(ctx.stringNullableArgument(0));
+ final Object literalOrVar = antlr.argumentVisitor.visitStringNullableArgument(ctx.stringNullableArgument());
if (GValue.valueInstanceOf(literalOrVar, GType.STRING)) {
return graphTraversal.has((GValue) literalOrVar,
- antlr.argumentVisitor.parseString(ctx.stringNullableArgument(1)),
+ antlr.genericVisitor.parseString(ctx.stringNullableLiteral()),
antlr.argumentVisitor.visitGenericLiteralArgument(ctx.genericLiteralArgument()));
} else {
return graphTraversal.has((String) literalOrVar,
- antlr.argumentVisitor.parseString(ctx.stringNullableArgument(1)),
+ antlr.genericVisitor.parseString(ctx.stringNullableLiteral()),
antlr.argumentVisitor.visitGenericLiteralArgument(ctx.genericLiteralArgument()));
}
}
@@ -860,9 +870,16 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
*/
@Override
public GraphTraversal visitTraversalMethod_has_String_String_P(final GremlinParser.TraversalMethod_has_String_String_PContext ctx) {
- return graphTraversal.has(antlr.argumentVisitor.parseString(ctx.stringNullableArgument(0)),
- antlr.argumentVisitor.parseString(ctx.stringNullableArgument(1)),
- antlr.traversalPredicateVisitor.visitTraversalPredicate(ctx.traversalPredicate()));
+ final Object literalOrVar = antlr.argumentVisitor.visitStringNullableArgument(ctx.stringNullableArgument());
+ if (GValue.valueInstanceOf(literalOrVar, GType.STRING)) {
+ return graphTraversal.has((GValue) literalOrVar,
+ antlr.genericVisitor.parseString(ctx.stringNullableLiteral()),
+ antlr.traversalPredicateVisitor.visitTraversalPredicate(ctx.traversalPredicate()));
+ } else {
+ return graphTraversal.has((String) literalOrVar,
+ antlr.genericVisitor.parseString(ctx.stringNullableLiteral()),
+ antlr.traversalPredicateVisitor.visitTraversalPredicate(ctx.traversalPredicate()));
+ }
}
/**
@@ -870,7 +887,7 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
*/
@Override
public GraphTraversal visitTraversalMethod_has_String_Traversal(final GremlinParser.TraversalMethod_has_String_TraversalContext ctx) {
- return graphTraversal.has(antlr.argumentVisitor.parseString(ctx.stringNullableArgument()),
+ return graphTraversal.has(antlr.genericVisitor.parseString(ctx.stringNullableLiteral()),
antlr.tvisitor.visitNestedTraversal(ctx.nestedTraversal()));
}
@@ -922,7 +939,7 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
*/
@Override
public GraphTraversal visitTraversalMethod_in(final GremlinParser.TraversalMethod_inContext ctx) {
- return graphTraversal.in(antlr.genericVisitor.parseStringVarargs(ctx.stringLiteralVarargs()));
+ return graphTraversal.in(antlr.argumentVisitor.parseStringVarargs(ctx.stringLiteralVarargs()));
}
/**
@@ -930,7 +947,7 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
*/
@Override
public GraphTraversal visitTraversalMethod_inE(final GremlinParser.TraversalMethod_inEContext ctx) {
- return graphTraversal.inE(antlr.genericVisitor.parseStringVarargs(ctx.stringLiteralVarargs()));
+ return graphTraversal.inE(antlr.argumentVisitor.parseStringVarargs(ctx.stringLiteralVarargs()));
}
/**
@@ -1004,7 +1021,7 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
@Override
public GraphTraversal visitTraversalMethod_limit_Scope_long(final GremlinParser.TraversalMethod_limit_Scope_longContext ctx) {
return graphTraversal.limit(TraversalEnumParser.parseTraversalEnumFromContext(Scope.class, ctx.traversalScope()),
- antlr.argumentVisitor.parseNumber(ctx.integerArgument()).longValue());
+ antlr.genericVisitor.parseIntegral(ctx.integerLiteral()).longValue());
}
/**
@@ -1012,7 +1029,7 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
*/
@Override
public GraphTraversal visitTraversalMethod_limit_long(final GremlinParser.TraversalMethod_limit_longContext ctx) {
- return graphTraversal.limit(antlr.argumentVisitor.parseNumber(ctx.integerArgument()).longValue());
+ return graphTraversal.limit(antlr.genericVisitor.parseIntegral(ctx.integerLiteral()).longValue());
}
/**
@@ -1030,12 +1047,12 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
@Override
public GraphTraversal visitTraversalMethod_loops_String(final GremlinParser.TraversalMethod_loops_StringContext ctx) {
- return graphTraversal.loops(antlr.argumentVisitor.parseString(ctx.stringArgument()));
+ return graphTraversal.loops(antlr.genericVisitor.parseString(ctx.stringLiteral()));
}
@Override
public GraphTraversal visitTraversalMethod_repeat_String_Traversal(final GremlinParser.TraversalMethod_repeat_String_TraversalContext ctx) {
- return graphTraversal.repeat((antlr.argumentVisitor.parseString(ctx.stringArgument())),
+ return graphTraversal.repeat((antlr.genericVisitor.parseString(ctx.stringLiteral())),
antlr.tvisitor.visitNestedTraversal(ctx.nestedTraversal()));
}
@@ -1059,7 +1076,7 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
if (ctx.withOptionKeys() != null) {
return graphTraversal.with((String) WithOptionsVisitor.instance().visitWithOptionKeys(ctx.withOptionKeys()));
} else {
- return graphTraversal.with(antlr.argumentVisitor.parseString(ctx.stringArgument()));
+ return graphTraversal.with(antlr.genericVisitor.parseString(ctx.stringLiteral()));
}
}
@@ -1069,7 +1086,7 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
if (ctx.withOptionKeys() != null) {
k = (String) WithOptionsVisitor.instance().visitWithOptionKeys(ctx.withOptionKeys());
} else {
- k = antlr.argumentVisitor.parseString(ctx.stringArgument());
+ k = antlr.genericVisitor.parseString(ctx.stringLiteral());
}
final Object o;
@@ -1078,7 +1095,7 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
} else if (ctx.ioOptionsValues() != null) {
o = WithOptionsVisitor.instance().visitIoOptionsValues(ctx.ioOptionsValues());
} else {
- o = antlr.argumentVisitor.parseObject(ctx.genericLiteralArgument());
+ o = antlr.argumentVisitor.visitGenericLiteralArgument(ctx.genericLiteralArgument());
}
return graphTraversal.with(k, o);
}
@@ -1288,7 +1305,7 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
*/
@Override
public GraphTraversal visitTraversalMethod_out(final GremlinParser.TraversalMethod_outContext ctx) {
- return graphTraversal.out(antlr.genericVisitor.parseStringVarargs(ctx.stringLiteralVarargs()));
+ return graphTraversal.out(antlr.argumentVisitor.parseStringVarargs(ctx.stringLiteralVarargs()));
}
/**
@@ -1296,7 +1313,7 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
*/
@Override
public GraphTraversal visitTraversalMethod_outE(final GremlinParser.TraversalMethod_outEContext ctx) {
- return graphTraversal.outE(antlr.genericVisitor.parseStringVarargs(ctx.stringLiteralVarargs()));
+ return graphTraversal.outE(antlr.argumentVisitor.parseStringVarargs(ctx.stringLiteralVarargs()));
}
/**
@@ -1369,7 +1386,7 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
*/
@Override
public GraphTraversal visitTraversalMethod_profile_String(final GremlinParser.TraversalMethod_profile_StringContext ctx) {
- return graphTraversal.profile(antlr.argumentVisitor.parseString(ctx.stringArgument()));
+ return graphTraversal.profile(antlr.genericVisitor.parseString(ctx.stringLiteral()));
}
/**
@@ -1378,10 +1395,10 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
@Override
public GraphTraversal visitTraversalMethod_project(final GremlinParser.TraversalMethod_projectContext ctx) {
if (ctx.getChildCount() == 4) {
- return graphTraversal.project(antlr.argumentVisitor.parseString(ctx.stringArgument()));
+ return graphTraversal.project(antlr.genericVisitor.parseString(ctx.stringLiteral()));
} else {
- return graphTraversal.project(antlr.argumentVisitor.parseString(ctx.stringArgument()),
- antlr.genericVisitor.parseStringVarargs(ctx.stringLiteralVarargs()));
+ return graphTraversal.project(antlr.genericVisitor.parseString(ctx.stringLiteral()),
+ antlr.genericVisitor.parseStringVarargsLiterals(ctx.stringLiteralVarargsLiterals()));
}
}
@@ -1390,7 +1407,7 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
*/
@Override
public GraphTraversal visitTraversalMethod_properties(final GremlinParser.TraversalMethod_propertiesContext ctx) {
- return graphTraversal.properties(antlr.genericVisitor.parseStringVarargs(ctx.stringLiteralVarargs()));
+ return graphTraversal.properties(antlr.genericVisitor.parseStringVarargsLiterals(ctx.stringLiteralVarargsLiterals()));
}
/**
@@ -1398,7 +1415,7 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
*/
@Override
public GraphTraversal visitTraversalMethod_elementMap(final GremlinParser.TraversalMethod_elementMapContext ctx) {
- return graphTraversal.elementMap(antlr.genericVisitor.parseStringVarargs(ctx.stringLiteralVarargs()));
+ return graphTraversal.elementMap(antlr.genericVisitor.parseStringVarargsLiterals(ctx.stringLiteralVarargsLiterals()));
}
/**
@@ -1406,7 +1423,7 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
*/
@Override
public GraphTraversal visitTraversalMethod_propertyMap(final GremlinParser.TraversalMethod_propertyMapContext ctx) {
- return graphTraversal.propertyMap(antlr.genericVisitor.parseStringVarargs(ctx.stringLiteralVarargs()));
+ return graphTraversal.propertyMap(antlr.genericVisitor.parseStringVarargsLiterals(ctx.stringLiteralVarargsLiterals()));
}
/**
@@ -1458,8 +1475,8 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
@Override
public GraphTraversal visitTraversalMethod_range_Scope_long_long(final GremlinParser.TraversalMethod_range_Scope_long_longContext ctx) {
return graphTraversal.range(TraversalEnumParser.parseTraversalEnumFromContext(Scope.class, ctx.traversalScope()),
- antlr.argumentVisitor.parseNumber(ctx.integerArgument(0)).longValue(),
- antlr.argumentVisitor.parseNumber(ctx.integerArgument(1)).longValue());
+ antlr.genericVisitor.parseIntegral(ctx.integerLiteral(0)).longValue(),
+ antlr.genericVisitor.parseIntegral(ctx.integerLiteral(1)).longValue());
}
/**
@@ -1467,8 +1484,8 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
*/
@Override
public GraphTraversal visitTraversalMethod_range_long_long(final GremlinParser.TraversalMethod_range_long_longContext ctx) {
- return graphTraversal.range(antlr.argumentVisitor.parseNumber(ctx.integerArgument(0)).longValue(),
- antlr.argumentVisitor.parseNumber(ctx.integerArgument(1)).longValue());
+ return graphTraversal.range(antlr.genericVisitor.parseIntegral(ctx.integerLiteral(0)).longValue(),
+ antlr.genericVisitor.parseIntegral(ctx.integerLiteral(1)).longValue());
}
/**
@@ -1493,7 +1510,7 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
@Override
public GraphTraversal visitTraversalMethod_sample_Scope_int(final GremlinParser.TraversalMethod_sample_Scope_intContext ctx) {
return graphTraversal.sample(TraversalEnumParser.parseTraversalEnumFromContext(Scope.class, ctx.traversalScope()),
- antlr.argumentVisitor.parseNumber(ctx.integerArgument()).intValue());
+ antlr.genericVisitor.parseIntegral(ctx.integerLiteral()).intValue());
}
/**
@@ -1501,7 +1518,7 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
*/
@Override
public GraphTraversal visitTraversalMethod_sample_int(final GremlinParser.TraversalMethod_sample_intContext ctx) {
- return graphTraversal.sample(antlr.argumentVisitor.parseNumber(ctx.integerArgument()).intValue());
+ return graphTraversal.sample(antlr.genericVisitor.parseIntegral(ctx.integerLiteral()).intValue());
}
/**
@@ -1518,7 +1535,7 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
@Override
public GraphTraversal visitTraversalMethod_select_Pop_String(final GremlinParser.TraversalMethod_select_Pop_StringContext ctx) {
return graphTraversal.select(TraversalEnumParser.parseTraversalEnumFromContext(Pop.class, ctx.traversalPop()),
- antlr.argumentVisitor.parseString(ctx.stringArgument()));
+ antlr.genericVisitor.parseString(ctx.stringLiteral()));
}
/**
@@ -1527,9 +1544,9 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
@Override
public GraphTraversal visitTraversalMethod_select_Pop_String_String_String(final GremlinParser.TraversalMethod_select_Pop_String_String_StringContext ctx) {
return graphTraversal.select(TraversalEnumParser.parseTraversalEnumFromContext(Pop.class, ctx.traversalPop()),
- antlr.argumentVisitor.parseString(ctx.stringArgument(0)),
- antlr.argumentVisitor.parseString(ctx.stringArgument(1)),
- antlr.genericVisitor.parseStringVarargs(ctx.stringLiteralVarargs()));
+ antlr.genericVisitor.parseString(ctx.stringLiteral(0)),
+ antlr.genericVisitor.parseString(ctx.stringLiteral(1)),
+ antlr.genericVisitor.parseStringVarargsLiterals(ctx.stringLiteralVarargsLiterals()));
}
@Override
@@ -1543,7 +1560,7 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
*/
@Override
public GraphTraversal visitTraversalMethod_select_String(final GremlinParser.TraversalMethod_select_StringContext ctx) {
- return graphTraversal.select(antlr.argumentVisitor.parseString(ctx.stringArgument()));
+ return graphTraversal.select(antlr.genericVisitor.parseString(ctx.stringLiteral()));
}
/**
@@ -1551,9 +1568,9 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
*/
@Override
public GraphTraversal visitTraversalMethod_select_String_String_String(final GremlinParser.TraversalMethod_select_String_String_StringContext ctx) {
- return graphTraversal.select(antlr.argumentVisitor.parseString(ctx.stringArgument(0)),
- antlr.argumentVisitor.parseString(ctx.stringArgument(1)),
- antlr.genericVisitor.parseStringVarargs(ctx.stringLiteralVarargs()));
+ return graphTraversal.select(antlr.genericVisitor.parseString(ctx.stringLiteral(0)),
+ antlr.genericVisitor.parseString(ctx.stringLiteral(1)),
+ antlr.genericVisitor.parseStringVarargsLiterals(ctx.stringLiteralVarargsLiterals()));
}
@Override
@@ -1583,7 +1600,7 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
@Override
public GraphTraversal visitTraversalMethod_skip_Scope_long(final GremlinParser.TraversalMethod_skip_Scope_longContext ctx) {
return graphTraversal.skip(TraversalEnumParser.parseTraversalEnumFromContext(Scope.class, ctx.traversalScope()),
- antlr.argumentVisitor.parseNumber(ctx.integerArgument()).longValue());
+ antlr.genericVisitor.parseIntegral(ctx.integerLiteral()).longValue());
}
/**
@@ -1591,7 +1608,7 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
*/
@Override
public GraphTraversal visitTraversalMethod_skip_long(final GremlinParser.TraversalMethod_skip_longContext ctx) {
- return graphTraversal.skip(antlr.argumentVisitor.parseNumber(ctx.integerArgument()).longValue());
+ return graphTraversal.skip(antlr.genericVisitor.parseIntegral(ctx.integerLiteral()).longValue());
}
/**
@@ -1599,7 +1616,7 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
*/
@Override
public GraphTraversal visitTraversalMethod_store(final GremlinParser.TraversalMethod_storeContext ctx) {
- return graphTraversal.store(antlr.argumentVisitor.parseString(ctx.stringArgument()));
+ return graphTraversal.store(antlr.genericVisitor.parseString(ctx.stringLiteral()));
}
/**
@@ -1607,7 +1624,7 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
*/
@Override
public GraphTraversal visitTraversalMethod_subgraph(final GremlinParser.TraversalMethod_subgraphContext ctx) {
- return graphTraversal.subgraph(antlr.argumentVisitor.parseString(ctx.stringArgument()));
+ return graphTraversal.subgraph(antlr.genericVisitor.parseString(ctx.stringLiteral()));
}
/**
@@ -1648,7 +1665,7 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
@Override
public GraphTraversal visitTraversalMethod_tail_Scope_long(final GremlinParser.TraversalMethod_tail_Scope_longContext ctx) {
return graphTraversal.tail(TraversalEnumParser.parseTraversalEnumFromContext(Scope.class, ctx.traversalScope()),
- antlr.argumentVisitor.parseNumber(ctx.integerArgument()).longValue());
+ antlr.genericVisitor.parseIntegral(ctx.integerLiteral()).longValue());
}
/**
@@ -1656,7 +1673,7 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
*/
@Override
public GraphTraversal visitTraversalMethod_tail_long(final GremlinParser.TraversalMethod_tail_longContext ctx) {
- return graphTraversal.tail(antlr.argumentVisitor.parseNumber(ctx.integerArgument()).longValue());
+ return graphTraversal.tail(antlr.genericVisitor.parseIntegral(ctx.integerLiteral()).longValue());
}
/**
@@ -1664,7 +1681,7 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
*/
@Override
public GraphTraversal visitTraversalMethod_timeLimit(final GremlinParser.TraversalMethod_timeLimitContext ctx) {
- return graphTraversal.timeLimit(antlr.argumentVisitor.parseNumber(ctx.integerArgument()).longValue());
+ return graphTraversal.timeLimit(antlr.genericVisitor.parseIntegral(ctx.integerLiteral()).longValue());
}
/**
@@ -1672,7 +1689,7 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
*/
@Override
public GraphTraversal visitTraversalMethod_times(final GremlinParser.TraversalMethod_timesContext ctx) {
- return graphTraversal.times(antlr.argumentVisitor.parseNumber(ctx.integerArgument()).intValue());
+ return graphTraversal.times(antlr.genericVisitor.parseIntegral(ctx.integerLiteral()).intValue());
}
/**
@@ -1681,7 +1698,7 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
@Override
public GraphTraversal visitTraversalMethod_toE(final GremlinParser.TraversalMethod_toEContext ctx) {
return graphTraversal.toE(TraversalEnumParser.parseTraversalEnumFromContext(Direction.class, ctx.traversalDirection()),
- antlr.genericVisitor.parseStringVarargs(ctx.stringLiteralVarargs()));
+ antlr.argumentVisitor.parseStringVarargs(ctx.stringLiteralVarargs()));
}
/**
@@ -1698,7 +1715,7 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
@Override
public GraphTraversal visitTraversalMethod_to_Direction_String(final GremlinParser.TraversalMethod_to_Direction_StringContext ctx) {
return graphTraversal.to(TraversalEnumParser.parseTraversalDirectionFromContext(ctx.traversalDirection()),
- antlr.genericVisitor.parseStringVarargs(ctx.stringLiteralVarargs()));
+ antlr.argumentVisitor.parseStringVarargs(ctx.stringLiteralVarargs()));
}
/**
@@ -1742,7 +1759,7 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
*/
@Override
public GraphTraversal visitTraversalMethod_tree_String(final GremlinParser.TraversalMethod_tree_StringContext ctx) {
- return graphTraversal.tree(antlr.argumentVisitor.parseString(ctx.stringArgument()));
+ return graphTraversal.tree(antlr.genericVisitor.parseString(ctx.stringLiteral()));
}
/**
@@ -1791,7 +1808,7 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
*/
@Override
public GraphTraversal visitTraversalMethod_valueMap_String(final GremlinParser.TraversalMethod_valueMap_StringContext ctx) {
- return graphTraversal.valueMap(antlr.genericVisitor.parseStringVarargs(ctx.stringLiteralVarargs()));
+ return graphTraversal.valueMap(antlr.genericVisitor.parseStringVarargsLiterals(ctx.stringLiteralVarargsLiterals()));
}
/**
@@ -1803,7 +1820,7 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
return graphTraversal.valueMap(antlr.genericVisitor.parseBoolean(ctx.booleanLiteral()));
} else {
return graphTraversal.valueMap(antlr.genericVisitor.parseBoolean(ctx.booleanLiteral()),
- antlr.genericVisitor.parseStringVarargs(ctx.stringLiteralVarargs()));
+ antlr.genericVisitor.parseStringVarargsLiterals(ctx.stringLiteralVarargsLiterals()));
}
}
@@ -1812,7 +1829,7 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
*/
@Override
public GraphTraversal visitTraversalMethod_values(final GremlinParser.TraversalMethod_valuesContext ctx) {
- return graphTraversal.values(antlr.genericVisitor.parseStringVarargs(ctx.stringLiteralVarargs()));
+ return graphTraversal.values(antlr.genericVisitor.parseStringVarargsLiterals(ctx.stringLiteralVarargsLiterals()));
}
/**
@@ -1828,7 +1845,7 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
*/
@Override
public GraphTraversal visitTraversalMethod_where_String_P(final GremlinParser.TraversalMethod_where_String_PContext ctx) {
- return graphTraversal.where(antlr.argumentVisitor.parseString(ctx.stringArgument()),
+ return graphTraversal.where(antlr.genericVisitor.parseString(ctx.stringLiteral()),
antlr.traversalPredicateVisitor.visitTraversalPredicate(ctx.traversalPredicate()));
}
@@ -1845,7 +1862,7 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
*/
@Override
public GraphTraversal visitTraversalMethod_math(final GremlinParser.TraversalMethod_mathContext ctx) {
- return graphTraversal.math(antlr.argumentVisitor.parseString(ctx.stringArgument()));
+ return graphTraversal.math(antlr.genericVisitor.parseString(ctx.stringLiteral()));
}
/**
@@ -1870,7 +1887,7 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
*/
@Override
public Traversal visitTraversalMethod_call_string(final GremlinParser.TraversalMethod_call_stringContext ctx) {
- return graphTraversal.call(antlr.argumentVisitor.parseString(ctx.stringArgument()));
+ return graphTraversal.call(antlr.genericVisitor.parseString(ctx.stringLiteral()));
}
/**
@@ -1880,9 +1897,9 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
public Traversal visitTraversalMethod_call_string_map(final GremlinParser.TraversalMethod_call_string_mapContext ctx) {
final Object literalOrVar = antlr.argumentVisitor.visitGenericLiteralMapArgument(ctx.genericLiteralMapArgument());
if (GValue.valueInstanceOf(literalOrVar, GType.MAP))
- return graphTraversal.call(antlr.argumentVisitor.parseString(ctx.stringArgument()), (GValue<Map>) literalOrVar);
+ return graphTraversal.call(antlr.genericVisitor.parseString(ctx.stringLiteral()), (GValue<Map>) literalOrVar);
else
- return graphTraversal.call(antlr.argumentVisitor.parseString(ctx.stringArgument()), (Map) literalOrVar);
+ return graphTraversal.call(antlr.genericVisitor.parseString(ctx.stringLiteral()), (Map) literalOrVar);
}
/**
@@ -1890,7 +1907,7 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
*/
@Override
public Traversal visitTraversalMethod_call_string_traversal(final GremlinParser.TraversalMethod_call_string_traversalContext ctx) {
- return graphTraversal.call(antlr.argumentVisitor.parseString(ctx.stringArgument()),
+ return graphTraversal.call(antlr.genericVisitor.parseString(ctx.stringLiteral()),
antlr.tvisitor.visitNestedTraversal(ctx.nestedTraversal()));
}
@@ -1901,9 +1918,9 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
public Traversal visitTraversalMethod_call_string_map_traversal(final GremlinParser.TraversalMethod_call_string_map_traversalContext ctx) {
final Object literalOrVar = antlr.argumentVisitor.visitGenericLiteralMapArgument(ctx.genericLiteralMapArgument());
if (GValue.valueInstanceOf(literalOrVar, GType.MAP))
- return graphTraversal.call(antlr.argumentVisitor.parseString(ctx.stringArgument()), (GValue<Map>) literalOrVar, antlr.tvisitor.visitNestedTraversal(ctx.nestedTraversal()));
+ return graphTraversal.call(antlr.genericVisitor.parseString(ctx.stringLiteral()), (GValue<Map>) literalOrVar, antlr.tvisitor.visitNestedTraversal(ctx.nestedTraversal()));
else
- return graphTraversal.call(antlr.argumentVisitor.parseString(ctx.stringArgument()), (Map) literalOrVar, antlr.tvisitor.visitNestedTraversal(ctx.nestedTraversal()));
+ return graphTraversal.call(antlr.genericVisitor.parseString(ctx.stringLiteral()), (Map) literalOrVar, antlr.tvisitor.visitNestedTraversal(ctx.nestedTraversal()));
}
/**
@@ -1923,7 +1940,7 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
*/
@Override
public GraphTraversal visitTraversalMethod_concat_String(final GremlinParser.TraversalMethod_concat_StringContext ctx) {
- return graphTraversal.concat(antlr.genericVisitor.parseStringVarargs(ctx.stringLiteralVarargs()));
+ return graphTraversal.concat(antlr.genericVisitor.parseStringVarargsLiterals(ctx.stringLiteralVarargsLiterals()));
}
/**
@@ -1931,7 +1948,7 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
*/
@Override
public GraphTraversal visitTraversalMethod_format_String(GremlinParser.TraversalMethod_format_StringContext ctx) {
- return graphTraversal.format(antlr.argumentVisitor.parseString(ctx.stringArgument()));
+ return graphTraversal.format(antlr.genericVisitor.parseString(ctx.stringLiteral()));
}
/**
@@ -2059,8 +2076,8 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
*/
@Override
public GraphTraversal visitTraversalMethod_replace_String_String(final GremlinParser.TraversalMethod_replace_String_StringContext ctx) {
- return graphTraversal.replace(antlr.argumentVisitor.parseString(ctx.stringNullableArgument(0)),
- antlr.argumentVisitor.parseString(ctx.stringNullableArgument(1)));
+ return graphTraversal.replace(antlr.genericVisitor.parseString(ctx.stringNullableLiteral(0)),
+ antlr.genericVisitor.parseString(ctx.stringNullableLiteral(1)));
}
/**
@@ -2069,8 +2086,8 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
@Override
public GraphTraversal visitTraversalMethod_replace_Scope_String_String(final GremlinParser.TraversalMethod_replace_Scope_String_StringContext ctx) {
return graphTraversal.replace(TraversalEnumParser.parseTraversalEnumFromContext(Scope.class, ctx.traversalScope()),
- antlr.argumentVisitor.parseString(ctx.stringNullableArgument(0)),
- antlr.argumentVisitor.parseString(ctx.stringNullableArgument(1)));
+ antlr.genericVisitor.parseString(ctx.stringNullableLiteral(0)),
+ antlr.genericVisitor.parseString(ctx.stringNullableLiteral(1)));
}
/**
@@ -2078,7 +2095,7 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
*/
@Override
public GraphTraversal visitTraversalMethod_split_String(final GremlinParser.TraversalMethod_split_StringContext ctx) {
- return graphTraversal.split(antlr.argumentVisitor.parseString(ctx.stringNullableArgument()));
+ return graphTraversal.split(antlr.genericVisitor.parseString(ctx.stringNullableLiteral()));
}
/**
@@ -2087,7 +2104,7 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
@Override
public GraphTraversal visitTraversalMethod_split_Scope_String(final GremlinParser.TraversalMethod_split_Scope_StringContext ctx) {
return graphTraversal.split(TraversalEnumParser.parseTraversalEnumFromContext(Scope.class, ctx.traversalScope()),
- antlr.argumentVisitor.parseString(ctx.stringNullableArgument()));
+ antlr.genericVisitor.parseString(ctx.stringNullableLiteral()));
}
/**
@@ -2095,7 +2112,7 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
*/
@Override
public GraphTraversal visitTraversalMethod_substring_int(final GremlinParser.TraversalMethod_substring_intContext ctx) {
- return graphTraversal.substring(antlr.argumentVisitor.parseNumber(ctx.integerArgument()).intValue());
+ return graphTraversal.substring(antlr.genericVisitor.parseIntegral(ctx.integerLiteral()).intValue());
}
/**
@@ -2104,7 +2121,7 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
@Override
public GraphTraversal visitTraversalMethod_substring_Scope_int(final GremlinParser.TraversalMethod_substring_Scope_intContext ctx) {
return graphTraversal.substring(TraversalEnumParser.parseTraversalEnumFromContext(Scope.class, ctx.traversalScope()),
- antlr.argumentVisitor.parseNumber(ctx.integerArgument()).intValue());
+ antlr.genericVisitor.parseIntegral(ctx.integerLiteral()).intValue());
}
/**
@@ -2112,8 +2129,8 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
*/
@Override
public GraphTraversal visitTraversalMethod_substring_int_int(final GremlinParser.TraversalMethod_substring_int_intContext ctx) {
- return graphTraversal.substring(antlr.argumentVisitor.parseNumber(ctx.integerArgument(0)).intValue(),
- antlr.argumentVisitor.parseNumber(ctx.integerArgument(1)).intValue());
+ return graphTraversal.substring(antlr.genericVisitor.parseIntegral(ctx.integerLiteral(0)).intValue(),
+ antlr.genericVisitor.parseIntegral(ctx.integerLiteral(1)).intValue());
}
/**
@@ -2122,8 +2139,8 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
@Override
public GraphTraversal visitTraversalMethod_substring_Scope_int_int(final GremlinParser.TraversalMethod_substring_Scope_int_intContext ctx) {
return graphTraversal.substring(TraversalEnumParser.parseTraversalEnumFromContext(Scope.class, ctx.traversalScope()),
- antlr.argumentVisitor.parseNumber(ctx.integerArgument(0)).intValue(),
- antlr.argumentVisitor.parseNumber(ctx.integerArgument(1)).intValue());
+ antlr.genericVisitor.parseIntegral(ctx.integerLiteral(0)).intValue(),
+ antlr.genericVisitor.parseIntegral(ctx.integerLiteral(1)).intValue());
}
/**
@@ -2140,7 +2157,7 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
@Override
public GraphTraversal visitTraversalMethod_dateAdd(final GremlinParser.TraversalMethod_dateAddContext ctx) {
return graphTraversal.dateAdd(TraversalEnumParser.parseTraversalEnumFromContext(DT.class, ctx.traversalDT()),
- antlr.argumentVisitor.parseNumber(ctx.integerArgument()).intValue());
+ antlr.genericVisitor.parseIntegral(ctx.integerLiteral()).intValue());
}
/**
@@ -2156,7 +2173,7 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
*/
@Override
public GraphTraversal visitTraversalMethod_dateDiff_Date(final GremlinParser.TraversalMethod_dateDiff_DateContext ctx) {
- return graphTraversal.dateDiff(antlr.argumentVisitor.parseDate(ctx.dateArgument()));
+ return graphTraversal.dateDiff(antlr.genericVisitor.parseDate(ctx.dateLiteral()));
}
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalSourceSelfMethodVisitor.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalSourceSelfMethodVisitor.java
index 34568da1f2..63c87aa6f9 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalSourceSelfMethodVisitor.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalSourceSelfMethodVisitor.java
@@ -89,10 +89,10 @@ public class TraversalSourceSelfMethodVisitor extends DefaultGremlinBaseVisitor<
public GraphTraversalSource visitTraversalSourceSelfMethod_withSideEffect(final GremlinParser.TraversalSourceSelfMethod_withSideEffectContext ctx) {
if (ctx.getChildCount() < 8) {
// with 4 children withSideEffect() was called without a reducer specified.
- return source.withSideEffect(antlr.argumentVisitor.parseString(ctx.stringArgument()),
+ return source.withSideEffect(antlr.genericVisitor.parseString(ctx.stringLiteral()),
antlr.argumentVisitor.visitGenericLiteralArgument(ctx.genericLiteralArgument()));
} else {
- return source.withSideEffect(antlr.argumentVisitor.parseString(ctx.stringArgument()),
+ return source.withSideEffect(antlr.genericVisitor.parseString(ctx.stringLiteral()),
antlr.argumentVisitor.visitGenericLiteralArgument(ctx.genericLiteralArgument()),
TraversalEnumParser.parseTraversalEnumFromContext(Operator.class, ctx.traversalBiFunction().traversalOperator()));
}
@@ -138,9 +138,9 @@ public class TraversalSourceSelfMethodVisitor extends DefaultGremlinBaseVisitor<
@Override
public GraphTraversalSource visitTraversalSourceSelfMethod_with(final GremlinParser.TraversalSourceSelfMethod_withContext ctx) {
if (ctx.getChildCount() == 4) {
- return source.with(antlr.argumentVisitor.parseString(ctx.stringArgument()));
+ return source.with(antlr.genericVisitor.parseString(ctx.stringLiteral()));
} else {
- return source.with(antlr.argumentVisitor.parseString(ctx.stringArgument()),
+ return source.with(antlr.genericVisitor.parseString(ctx.stringLiteral()),
antlr.argumentVisitor.visitGenericLiteralArgument(ctx.genericLiteralArgument()));
}
}
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalSourceSpawnMethodVisitor.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalSourceSpawnMethodVisitor.java
index 02fb654451..c65b283b0a 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalSourceSpawnMethodVisitor.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalSourceSpawnMethodVisitor.java
@@ -59,7 +59,12 @@ public class TraversalSourceSpawnMethodVisitor extends DefaultGremlinBaseVisitor
@Override
public GraphTraversal visitTraversalSourceSpawnMethod_addE(final GremlinParser.TraversalSourceSpawnMethod_addEContext ctx) {
if (ctx.stringArgument() != null) {
- return this.traversalSource.addE(antlr.argumentVisitor.parseString(ctx.stringArgument()));
+ final Object literalOrVar = antlr.argumentVisitor.visitStringArgument(ctx.stringArgument());
+ if (GValue.valueInstanceOf(literalOrVar, GType.STRING)) {
+ return this.traversalSource.addE((GValue<String>) literalOrVar);
+ } else {
+ return this.traversalSource.addE((String) literalOrVar);
+ }
} else if (ctx.nestedTraversal() != null) {
return this.traversalSource.addE(anonymousVisitor.visitNestedTraversal(ctx.nestedTraversal()));
} else {
@@ -73,7 +78,12 @@ public class TraversalSourceSpawnMethodVisitor extends DefaultGremlinBaseVisitor
@Override
public GraphTraversal visitTraversalSourceSpawnMethod_addV(final GremlinParser.TraversalSourceSpawnMethod_addVContext ctx) {
if (ctx.stringArgument() != null) {
- return this.traversalSource.addV(antlr.argumentVisitor.parseString(ctx.stringArgument()));
+ final Object literalOrVar = antlr.argumentVisitor.visitStringArgument(ctx.stringArgument());
+ if (GValue.valueInstanceOf(literalOrVar, GType.STRING)) {
+ return this.traversalSource.addV((GValue<String>) literalOrVar);
+ } else {
+ return this.traversalSource.addV((String) literalOrVar);
+ }
} else if (ctx.nestedTraversal() != null) {
return this.traversalSource.addV(anonymousVisitor.visitNestedTraversal(ctx.nestedTraversal()));
} else {
@@ -111,7 +121,7 @@ public class TraversalSourceSpawnMethodVisitor extends DefaultGremlinBaseVisitor
@Override
public GraphTraversal visitTraversalSourceSpawnMethod_io(final GremlinParser.TraversalSourceSpawnMethod_ioContext ctx) {
if (ctx.getChildCount() > 2) {
- this.graphTraversal = this.traversalSource.io(antlr.argumentVisitor.parseString(ctx.stringArgument()));
+ this.graphTraversal = this.traversalSource.io(antlr.genericVisitor.parseString(ctx.stringLiteral()));
}
return graphTraversal;
}
@@ -169,7 +179,7 @@ public class TraversalSourceSpawnMethodVisitor extends DefaultGremlinBaseVisitor
*/
@Override
public GraphTraversal visitTraversalSourceSpawnMethod_call_string(final GremlinParser.TraversalSourceSpawnMethod_call_stringContext ctx) {
- return this.traversalSource.call(antlr.argumentVisitor.parseString(ctx.stringArgument()));
+ return this.traversalSource.call(antlr.genericVisitor.parseString(ctx.stringLiteral()));
}
/**
@@ -179,9 +189,9 @@ public class TraversalSourceSpawnMethodVisitor extends DefaultGremlinBaseVisitor
public GraphTraversal visitTraversalSourceSpawnMethod_call_string_map(final GremlinParser.TraversalSourceSpawnMethod_call_string_mapContext ctx) {
final Object literalOrVar = antlr.argumentVisitor.visitGenericLiteralMapArgument(ctx.genericLiteralMapArgument());
if (GValue.valueInstanceOf(literalOrVar, GType.MAP))
- return this.traversalSource.call(antlr.argumentVisitor.parseString(ctx.stringArgument()), (GValue<Map>) literalOrVar);
+ return this.traversalSource.call(antlr.genericVisitor.parseString(ctx.stringLiteral()), (GValue<Map>) literalOrVar);
else
- return this.traversalSource.call(antlr.argumentVisitor.parseString(ctx.stringArgument()), (Map) literalOrVar);
+ return this.traversalSource.call(antlr.genericVisitor.parseString(ctx.stringLiteral()), (Map) literalOrVar);
}
/**
@@ -189,7 +199,7 @@ public class TraversalSourceSpawnMethodVisitor extends DefaultGremlinBaseVisitor
*/
@Override
public GraphTraversal visitTraversalSourceSpawnMethod_call_string_traversal(final GremlinParser.TraversalSourceSpawnMethod_call_string_traversalContext ctx) {
- return this.traversalSource.call(antlr.argumentVisitor.parseString(ctx.stringArgument()),
+ return this.traversalSource.call(antlr.genericVisitor.parseString(ctx.stringLiteral()),
anonymousVisitor.visitNestedTraversal(ctx.nestedTraversal()));
}
@@ -200,9 +210,9 @@ public class TraversalSourceSpawnMethodVisitor extends DefaultGremlinBaseVisitor
public GraphTraversal visitTraversalSourceSpawnMethod_call_string_map_traversal(final GremlinParser.TraversalSourceSpawnMethod_call_string_map_traversalContext ctx) {
final Object literalOrVar = antlr.argumentVisitor.visitGenericLiteralMapArgument(ctx.genericLiteralMapArgument());
if (GValue.valueInstanceOf(literalOrVar, GType.MAP))
- return this.traversalSource.call(antlr.argumentVisitor.parseString(ctx.stringArgument()), (GValue<Map>) literalOrVar, anonymousVisitor.visitNestedTraversal(ctx.nestedTraversal()));
+ return this.traversalSource.call(antlr.genericVisitor.parseString(ctx.stringLiteral()), (GValue<Map>) literalOrVar, anonymousVisitor.visitNestedTraversal(ctx.nestedTraversal()));
else
- return this.traversalSource.call(antlr.argumentVisitor.parseString(ctx.stringArgument()), (Map) literalOrVar, anonymousVisitor.visitNestedTraversal(ctx.nestedTraversal()));
+ return this.traversalSource.call(antlr.genericVisitor.parseString(ctx.stringLiteral()), (Map) literalOrVar, anonymousVisitor.visitNestedTraversal(ctx.nestedTraversal()));
}
/**
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/translator/DotNetTranslateVisitor.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/translator/DotNetTranslateVisitor.java
index 60ce2f8e30..886bcc365f 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/translator/DotNetTranslateVisitor.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/translator/DotNetTranslateVisitor.java
@@ -318,7 +318,7 @@ public class DotNetTranslateVisitor extends AbstractTranslateVisitor {
final String step = ctx.getChild(0).getText();
sb.append(convertToPascalCase(step));
sb.append("<object>").append("((string) ");
- visit(ctx.stringArgument());
+ visit(ctx.stringLiteral());
sb.append(")");
return null;
}
@@ -328,7 +328,7 @@ public class DotNetTranslateVisitor extends AbstractTranslateVisitor {
final String step = ctx.getChild(0).getText();
sb.append(convertToPascalCase(step));
sb.append("<object>").append("(");
- visit(ctx.stringArgument());
+ visit(ctx.stringLiteral());
sb.append(", ");
sb.append("(IDictionary<object, object>) ");
visit(ctx.genericLiteralMapArgument());
@@ -341,7 +341,7 @@ public class DotNetTranslateVisitor extends AbstractTranslateVisitor {
final String step = ctx.getChild(0).getText();
sb.append(convertToPascalCase(step));
sb.append("<object>").append("(");
- visit(ctx.stringArgument());
+ visit(ctx.stringLiteral());
sb.append(", ");
sb.append("(ITraversal) ");
visit(ctx.nestedTraversal());
@@ -354,7 +354,7 @@ public class DotNetTranslateVisitor extends AbstractTranslateVisitor {
final String step = ctx.getChild(0).getText();
sb.append(convertToPascalCase(step));
sb.append("<object>").append("(");
- visit(ctx.stringArgument());
+ visit(ctx.stringLiteral());
sb.append(", ");
sb.append("(IDictionary<object, object>) ");
visit(ctx.genericLiteralMapArgument());
@@ -429,7 +429,7 @@ public class DotNetTranslateVisitor extends AbstractTranslateVisitor {
final String step = ctx.getChild(0).getText();
sb.append(convertToPascalCase(step));
sb.append("<object>").append("((string) ");
- visit(ctx.stringArgument());
+ visit(ctx.stringLiteral());
sb.append(")");
return null;
}
@@ -439,7 +439,7 @@ public class DotNetTranslateVisitor extends AbstractTranslateVisitor {
final String step = ctx.getChild(0).getText();
sb.append(convertToPascalCase(step));
sb.append("<object>").append("(");
- visit(ctx.stringArgument());
+ visit(ctx.stringLiteral());
sb.append(", ");
sb.append("(IDictionary<object, object>) ");
visit(ctx.genericLiteralMapArgument());
@@ -452,7 +452,7 @@ public class DotNetTranslateVisitor extends AbstractTranslateVisitor {
final String step = ctx.getChild(0).getText();
sb.append(convertToPascalCase(step));
sb.append("<object>").append("(");
- visit(ctx.stringArgument());
+ visit(ctx.stringLiteral());
sb.append(", ");
sb.append("(ITraversal) ");
visit(ctx.nestedTraversal());
@@ -465,7 +465,7 @@ public class DotNetTranslateVisitor extends AbstractTranslateVisitor {
final String step = ctx.getChild(0).getText();
sb.append(convertToPascalCase(step));
sb.append("<object>").append("(");
- visit(ctx.stringArgument());
+ visit(ctx.stringLiteral());
sb.append(", ");
sb.append("(IDictionary<object, object>) ");
visit(ctx.genericLiteralMapArgument());
@@ -560,8 +560,8 @@ public class DotNetTranslateVisitor extends AbstractTranslateVisitor {
final String step = ctx.getChild(0).getText();
sb.append(convertToPascalCase(step));
sb.append("(");
- tryAppendCastToString(ctx.stringNullableArgument());
- visit(ctx.stringNullableArgument());
+ tryAppendCastToString(ctx.stringNullableLiteral());
+ visit(ctx.stringNullableLiteral());
sb.append(", ");
tryAppendCastToObject(ctx.genericLiteralArgument());
visit(ctx.genericLiteralArgument());
@@ -574,8 +574,8 @@ public class DotNetTranslateVisitor extends AbstractTranslateVisitor {
final String step = ctx.getChild(0).getText();
sb.append(convertToPascalCase(step));
sb.append("(");
- tryAppendCastToString(ctx.stringNullableArgument());
- visit(ctx.stringNullableArgument());
+ tryAppendCastToString(ctx.stringNullableLiteral());
+ visit(ctx.stringNullableLiteral());
sb.append(", ");
visit(ctx.traversalPredicate());
sb.append(")");
@@ -587,11 +587,11 @@ public class DotNetTranslateVisitor extends AbstractTranslateVisitor {
final String step = ctx.getChild(0).getText();
sb.append(convertToPascalCase(step));
sb.append("(");
- tryAppendCastToString(ctx.stringNullableArgument(0));
- visit(ctx.stringNullableArgument(0));
+ tryAppendCastToString(ctx.stringNullableArgument());
+ visit(ctx.stringNullableArgument());
sb.append(", ");
- tryAppendCastToString(ctx.stringNullableArgument(1));
- visit(ctx.stringNullableArgument(1));
+ tryAppendCastToString(ctx.stringNullableLiteral());
+ visit(ctx.stringNullableLiteral());
sb.append(", ");
tryAppendCastToObject(ctx.genericLiteralArgument());
visit(ctx.genericLiteralArgument());
@@ -604,11 +604,11 @@ public class DotNetTranslateVisitor extends AbstractTranslateVisitor {
final String step = ctx.getChild(0).getText();
sb.append(convertToPascalCase(step));
sb.append("(");
- tryAppendCastToString(ctx.stringNullableArgument(0));
- visit(ctx.stringNullableArgument(0));
+ tryAppendCastToString(ctx.stringNullableArgument());
+ visit(ctx.stringNullableArgument());
sb.append(", ");
- tryAppendCastToString(ctx.stringNullableArgument(1));
- visit(ctx.stringNullableArgument(1));
+ tryAppendCastToString(ctx.stringNullableLiteral());
+ visit(ctx.stringNullableLiteral());
sb.append(", ");
visit(ctx.traversalPredicate());
sb.append(")");
@@ -620,8 +620,8 @@ public class DotNetTranslateVisitor extends AbstractTranslateVisitor {
final String step = ctx.getChild(0).getText();
sb.append(convertToPascalCase(step));
sb.append("(");
- tryAppendCastToString(ctx.stringNullableArgument());
- visit(ctx.stringNullableArgument());
+ tryAppendCastToString(ctx.stringNullableLiteral());
+ visit(ctx.stringNullableLiteral());
sb.append(", ");
visit(ctx.nestedTraversal());
sb.append(")");
@@ -678,12 +678,12 @@ public class DotNetTranslateVisitor extends AbstractTranslateVisitor {
@Override
public Void visitTraversalMethod_hasKey_String_String(final GremlinParser.TraversalMethod_hasKey_String_StringContext ctx) {
// if there is only one argument then cast to string otherwise it's ambiguous with hasKey(P)
- if (ctx.stringLiteralVarargs() == null || ctx.stringLiteralVarargs().getChildCount() == 0) {
+ if (ctx.stringLiteralVarargsLiterals() == null || ctx.stringLiteralVarargsLiterals().getChildCount() == 0) {
final String step = ctx.getChild(0).getText();
sb.append(convertToPascalCase(step));
sb.append("(");
- tryAppendCastToString(ctx.stringNullableArgument());
- visit(ctx.stringNullableArgument());
+ tryAppendCastToString(ctx.stringNullableLiteral());
+ visit(ctx.stringNullableLiteral());
sb.append(")");
return null;
} else {
@@ -1202,6 +1202,12 @@ public class DotNetTranslateVisitor extends AbstractTranslateVisitor {
}
}
+ private void tryAppendCastToString(final GremlinParser.StringNullableLiteralContext ctx) {
+ if (ctx.NullLiteral() != null) {
+ sb.append("(string) ");
+ }
+ }
+
private void tryAppendCastToObject(final GremlinParser.GenericLiteralArgumentContext ctx) {
if (ctx.variable() != null || ctx.genericLiteral().nullLiteral() != null)
sb.append("(object) ");
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/translator/TranslateVisitor.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/translator/TranslateVisitor.java
index beb6040091..7d70c7bbb7 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/translator/TranslateVisitor.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/translator/TranslateVisitor.java
@@ -2149,6 +2149,11 @@ public class TranslateVisitor extends AbstractParseTreeVisitor<Void> implements
return visitChildren(ctx);
}
+ @Override
+ public Void visitStringLiteralVarargsLiterals(final GremlinParser.StringLiteralVarargsLiteralsContext ctx) {
+ return visitChildren(ctx);
+ }
+
@Override
public Void visitStringLiteralList(final GremlinParser.StringLiteralListContext ctx) {
return visitChildren(ctx);
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/GremlinLang.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/GremlinLang.java
index ced2489515..13f2c67c9f 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/GremlinLang.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/GremlinLang.java
@@ -22,11 +22,13 @@ package org.apache.tinkerpop.gremlin.process.traversal;
import org.apache.commons.configuration2.Configuration;
import org.apache.commons.text.StringEscapeUtils;
import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal;
+import org.apache.tinkerpop.gremlin.process.traversal.step.GValue;
import org.apache.tinkerpop.gremlin.process.traversal.strategy.TraversalStrategyProxy;
import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.OptionsStrategy;
import org.apache.tinkerpop.gremlin.process.traversal.util.ConnectiveP;
import org.apache.tinkerpop.gremlin.process.traversal.util.DefaultTraversal;
import org.apache.tinkerpop.gremlin.structure.Column;
+import org.apache.tinkerpop.gremlin.structure.Direction;
import org.apache.tinkerpop.gremlin.structure.T;
import org.apache.tinkerpop.gremlin.structure.Vertex;
import org.apache.tinkerpop.gremlin.util.NumberHelper;
@@ -168,12 +170,12 @@ public class GremlinLang implements Cloneable, Serializable {
return gremlinLang.getGremlin("__");
}
- if (arg instanceof Parameter) {
- final Parameter param = (Parameter) arg;
- String key = param.key;
+ if (arg instanceof GValue) {
+ final GValue gValue = (GValue) arg;
+ String key = gValue.getName();
if (key == null) {
- key = String.format("_%d", paramCount.getAndIncrement());
+ return argAsString(((GValue<?>) arg).get());
}
if (!SourceVersion.isIdentifier(key)) {
@@ -181,11 +183,11 @@ public class GremlinLang implements Cloneable, Serializable {
}
if (parameters.containsKey(key)) {
- if (!Objects.equals(parameters.get(key), param.value)) {
+ if (!Objects.equals(parameters.get(key), gValue.get())) {
throw new IllegalArgumentException(String.format("Parameter with name [%s] already defined.", key));
}
} else {
- parameters.put(key, param.value);
+ parameters.put(key, gValue.get());
}
return key;
}
@@ -470,33 +472,6 @@ public class GremlinLang implements Cloneable, Serializable {
}
}
- /**
- * Parameter to be used in Traversal.
- */
- public static class Parameter {
- private final String key;
- private final Object value;
-
- private Parameter(final String key, final Object value) {
- this.key = key;
- this.value = value;
- }
-
- public static Parameter var(final String key, final Object value) {
- if (key != null && key.startsWith("_")) {
- throw new IllegalArgumentException(String.format("Invalid parameter name [%s]. Should not start with _.", key));
- }
-
- return new Parameter(key, value);
- }
-
- public static Parameter value(final Object value) {
- return new Parameter(null, value);
- }
- }
-
- /////
-
private Object[] flattenArguments(final Object... arguments) {
if (arguments == null || arguments.length == 0)
return EMPTY_ARRAY;
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 ab5af2445b..624e3cfb2e 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
@@ -407,6 +407,18 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
return this.asAdmin().addStep(new GraphStep<>(this.asAdmin(), Edge.class, false, ids));
}
+ /**
+ * Map the {@link Vertex} to its adjacent vertices given a direction.
+ *
+ * @param direction the direction to traverse from the current vertex
+ * @return the traversal with an appended {@link VertexStep}.
+ * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#vertex-steps" target="_blank">Reference Documentation - Vertex Step</a>
+ * @since 3.0.0-incubating
+ */
+ public default GraphTraversal<S, Vertex> to(final Direction direction) {
+ return this.to(direction, new String[0]);
+ }
+
/**
* Map the {@link Vertex} to its adjacent vertices given a direction and edge labels.
*
@@ -431,10 +443,20 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
* @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#vertex-steps" target="_blank">Reference Documentation - Vertex Step</a>
* @since 4.0.0
*/
- public default GraphTraversal<S, Vertex> to(final Direction direction, final GValue<String> edgeLabel, final GValue<String>... edgeLabels) {
- this.asAdmin().getGremlinLang().addStep(GraphTraversal.Symbols.to, direction, edgeLabel, edgeLabels);
- final GValue<String>[] labels = CollectionUtil.addFirst(edgeLabels, edgeLabel, GValue.class);
- return this.asAdmin().addStep(new VertexStep<>(this.asAdmin(), Vertex.class, direction, labels));
+ public default GraphTraversal<S, Vertex> to(final Direction direction, final GValue<String>... edgeLabels) {
+ this.asAdmin().getGremlinLang().addStep(GraphTraversal.Symbols.to, direction, edgeLabels);
+ return this.asAdmin().addStep(new VertexStep<>(this.asAdmin(), Vertex.class, direction, edgeLabels));
+ }
+
+ /**
+ * Map the {@link Vertex} to its outgoing adjacent vertices.
+ *
+ * @return the traversal with an appended {@link VertexStep}.
+ * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#vertex-steps" target="_blank">Reference Documentation - Vertex Step</a>
+ * @since 3.0.0-incubating
+ */
+ public default GraphTraversal<S, Vertex> out() {
+ return this.out(new String[0]);
}
/**
@@ -459,12 +481,23 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
* @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#vertex-steps" target="_blank">Reference Documentation - Vertex Step</a>
* @since 3.7.3
*/
- public default GraphTraversal<S, Vertex> out(final GValue<String> label, final GValue<String>... edgeLabels) {
- final GValue<String>[] labels = CollectionUtil.addFirst(edgeLabels, label, GValue.class);
- this.asAdmin().getGremlinLang().addStep(GraphTraversal.Symbols.out, label, edgeLabels);
- return this.asAdmin().addStep(new VertexStep<>(this.asAdmin(), Vertex.class, Direction.OUT, labels));
+ public default GraphTraversal<S, Vertex> out(final GValue<String>... edgeLabels) {
+ this.asAdmin().getGremlinLang().addStep(GraphTraversal.Symbols.out, edgeLabels);
+ return this.asAdmin().addStep(new VertexStep<>(this.asAdmin(), Vertex.class, Direction.OUT, edgeLabels));
+ }
+
+ /**
+ * Map the {@link Vertex} to its incoming adjacent vertices.
+ *
+ * @return the traversal with an appended {@link VertexStep}.
+ * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#vertex-steps" target="_blank">Reference Documentation - Vertex Step</a>
+ * @since 3.0.0-incubating
+ */
+ public default GraphTraversal<S, Vertex> in() {
+ return this.in(new String[0]);
}
+
/**
* Map the {@link Vertex} to its incoming adjacent vertices given the edge labels.
*
@@ -487,10 +520,20 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
* @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#vertex-steps" target="_blank">Reference Documentation - Vertex Step</a>
* @since 4.0.0
*/
- public default GraphTraversal<S, Vertex> in(final GValue<String> label, final GValue<String>... edgeLabels) {
- final GValue<String>[] labels = CollectionUtil.addFirst(edgeLabels, label, GValue.class);
- this.asAdmin().getGremlinLang().addStep(GraphTraversal.Symbols.in, label, edgeLabels);
- return this.asAdmin().addStep(new VertexStep<>(this.asAdmin(), Vertex.class, Direction.IN, labels));
+ public default GraphTraversal<S, Vertex> in(final GValue<String>... edgeLabels) {
+ this.asAdmin().getGremlinLang().addStep(GraphTraversal.Symbols.in, edgeLabels);
+ return this.asAdmin().addStep(new VertexStep<>(this.asAdmin(), Vertex.class, Direction.IN, edgeLabels));
+ }
+
+ /**
+ * Map the {@link Vertex} to its adjacent vertices.
+ *
+ * @return the traversal with an appended {@link VertexStep}.
+ * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#vertex-steps" target="_blank">Reference Documentation - Vertex Step</a>
+ * @since 3.0.0-incubating
+ */
+ public default GraphTraversal<S, Vertex> both() {
+ return this.both(new String[0]);
}
/**
@@ -515,10 +558,21 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
* @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#vertex-steps" target="_blank">Reference Documentation - Vertex Step</a>
* @since 4.0.0
*/
- public default GraphTraversal<S, Vertex> both(final GValue<String> label, final GValue<String>... edgeLabels) {
- final GValue<String>[] labels = CollectionUtil.addFirst(edgeLabels, label, GValue.class);
- this.asAdmin().getGremlinLang().addStep(GraphTraversal.Symbols.both, label, edgeLabels);
- return this.asAdmin().addStep(new VertexStep<>(this.asAdmin(), Vertex.class, Direction.BOTH, labels));
+ public default GraphTraversal<S, Vertex> both(final GValue<String>... edgeLabels) {
+ this.asAdmin().getGremlinLang().addStep(GraphTraversal.Symbols.both, edgeLabels);
+ return this.asAdmin().addStep(new VertexStep<>(this.asAdmin(), Vertex.class, Direction.BOTH, edgeLabels));
+ }
+
+ /**
+ * Map the {@link Vertex} to its incident edges given the direction.
+ *
+ * @param direction the direction to traverse from the current vertex
+ * @return the traversal with an appended {@link VertexStep}.
+ * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#vertex-steps" target="_blank">Reference Documentation - Vertex Step</a>
+ * @since 3.0.0-incubating
+ */
+ public default GraphTraversal<S, Edge> toE(final Direction direction) {
+ return this.toE(direction, new String[0]);
}
/**
@@ -546,10 +600,20 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
* @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#vertex-steps" target="_blank">Reference Documentation - Vertex Step</a>
* @since 4.0.0
*/
- public default GraphTraversal<S, Edge> toE(final Direction direction, final GValue<String> edgeLabel, final GValue<String>... edgeLabels) {
- this.asAdmin().getGremlinLang().addStep(GraphTraversal.Symbols.toE, direction, edgeLabel, edgeLabels);
- final GValue<String>[] labels = CollectionUtil.addFirst(edgeLabels, edgeLabel, GValue.class);
- return this.asAdmin().addStep(new VertexStep<>(this.asAdmin(), Edge.class, direction, labels));
+ public default GraphTraversal<S, Edge> toE(final Direction direction, final GValue<String>... edgeLabels) {
+ this.asAdmin().getGremlinLang().addStep(GraphTraversal.Symbols.toE, direction, edgeLabels);
+ return this.asAdmin().addStep(new VertexStep<>(this.asAdmin(), Edge.class, direction, edgeLabels));
+ }
+
+ /**
+ * Map the {@link Vertex} to its outgoing incident edges.
+ *
+ * @return the traversal with an appended {@link VertexStep}.
+ * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#vertex-steps" target="_blank">Reference Documentation - Vertex Step</a>
+ * @since 3.0.0-incubating
+ */
+ public default GraphTraversal<S, Edge> outE() {
+ return this.outE(new String[0]);
}
/**
@@ -574,10 +638,20 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
* @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#vertex-steps" target="_blank">Reference Documentation - Vertex Step</a>
* @since 4.0.0
*/
- public default GraphTraversal<S, Edge> outE(final GValue<String> label, final GValue<String>... edgeLabels) {
- final GValue<String>[] labels = CollectionUtil.addFirst(edgeLabels, label, GValue.class);
- this.asAdmin().getGremlinLang().addStep(GraphTraversal.Symbols.outE, label, edgeLabels);
- return this.asAdmin().addStep(new VertexStep<>(this.asAdmin(), Edge.class, Direction.OUT, labels));
+ public default GraphTraversal<S, Edge> outE(final GValue<String>... edgeLabels) {
+ this.asAdmin().getGremlinLang().addStep(GraphTraversal.Symbols.outE, edgeLabels);
+ return this.asAdmin().addStep(new VertexStep<>(this.asAdmin(), Edge.class, Direction.OUT, edgeLabels));
+ }
+
+ /**
+ * Map the {@link Vertex} to its incoming incident edges.
+ *
+ * @return the traversal with an appended {@link VertexStep}.
+ * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#vertex-steps" target="_blank">Reference Documentation - Vertex Step</a>
+ * @since 3.0.0-incubating
+ */
+ public default GraphTraversal<S, Edge> inE() {
+ return this.inE(new String[0]);
}
/**
@@ -602,12 +676,21 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
* @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#vertex-steps" target="_blank">Reference Documentation - Vertex Step</a>
* @since 4.0.0
*/
- public default GraphTraversal<S, Edge> inE(final GValue<String> label, final GValue<String>... edgeLabels) {
- final GValue<String>[] labels = CollectionUtil.addFirst(edgeLabels, label, GValue.class);
- this.asAdmin().getGremlinLang().addStep(GraphTraversal.Symbols.inE, label, edgeLabels);
- return this.asAdmin().addStep(new VertexStep<>(this.asAdmin(), Edge.class, Direction.IN, labels));
+ public default GraphTraversal<S, Edge> inE(final GValue<String>... edgeLabels) {
+ this.asAdmin().getGremlinLang().addStep(GraphTraversal.Symbols.inE, edgeLabels);
+ return this.asAdmin().addStep(new VertexStep<>(this.asAdmin(), Edge.class, Direction.IN, edgeLabels));
}
+ /**
+ * Map the {@link Vertex} to its incident edges.
+ *
+ * @return the traversal with an appended {@link VertexStep}.
+ * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#vertex-steps" target="_blank">Reference Documentation - Vertex Step</a>
+ * @since 3.0.0-incubating
+ */
+ public default GraphTraversal<S, Edge> bothE() {
+ return this.bothE(new String[0]);
+ }
/**
* Map the {@link Vertex} to its incident edges given the edge labels.
@@ -631,10 +714,9 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
* @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#vertex-steps" target="_blank">Reference Documentation - Vertex Step</a>
* @since 4.0.0
*/
- public default GraphTraversal<S, Edge> bothE(final GValue<String> label, final GValue<String>... edgeLabels) {
- final GValue<String>[] labels = CollectionUtil.addFirst(edgeLabels, label, GValue.class);
- this.asAdmin().getGremlinLang().addStep(GraphTraversal.Symbols.bothE, label, edgeLabels);
- return this.asAdmin().addStep(new VertexStep<>(this.asAdmin(), Edge.class, Direction.BOTH, labels));
+ public default GraphTraversal<S, Edge> bothE(final GValue<String>... edgeLabels) {
+ this.asAdmin().getGremlinLang().addStep(GraphTraversal.Symbols.bothE, edgeLabels);
+ return this.asAdmin().addStep(new VertexStep<>(this.asAdmin(), Edge.class, Direction.BOTH, edgeLabels));
}
/**
@@ -1349,7 +1431,7 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
*/
public default GraphTraversal<S, Vertex> mergeV(final GValue<Map<Object, Object>> searchCreate) {
this.asAdmin().getGremlinLang().addStep(GraphTraversal.Symbols.mergeV, searchCreate);
- final MergeVertexStep<S> step = new MergeVertexStep(this.asAdmin(), false, null == searchCreate ? GValue.ofMap(null) : searchCreate);
+ final MergeVertexStep<S> step = new MergeVertexStep(this.asAdmin(), false, null == searchCreate ? GValue.ofMap(null, null) : searchCreate);
return this.asAdmin().addStep(step);
}
@@ -1404,7 +1486,7 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
public default GraphTraversal<S, Edge> mergeE(final GValue<Map<Object, Object>> searchCreate) {
// get a construction time exception if the Map is bad
this.asAdmin().getGremlinLang().addStep(GraphTraversal.Symbols.mergeE, searchCreate);
- final MergeEdgeStep<S> step = new MergeEdgeStep(this.asAdmin(), false, null == searchCreate ? GValue.ofMap(null) : searchCreate);
+ final MergeEdgeStep<S> step = new MergeEdgeStep(this.asAdmin(), false, null == searchCreate ? GValue.ofMap(null, null) : searchCreate);
return this.asAdmin().addStep(step);
}
@@ -2685,6 +2767,22 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
return TraversalHelper.addHasContainer(this.asAdmin(), new HasContainer(propertyKey, value instanceof P ? (P) value : P.eq(value)));
}
+ /**
+ * Filters vertices, edges and vertex properties based on their properties.
+ *
+ * @param label the label of the {@link Element}
+ * @param propertyKey the key of the property to filter on
+ * @param predicate the filter to apply to the key's value
+ * @return the traversal with an appended {@link HasStep}
+ * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#has-step" target="_blank">Reference Documentation - Has Step</a>
+ * @since 4.0.0
+ */
+ public default GraphTraversal<S, E> has(final GValue<String> label, final String propertyKey, final P<?> predicate) {
+ this.asAdmin().getGremlinLang().addStep(Symbols.has, label.get(), propertyKey, predicate);
+ TraversalHelper.addHasContainer(this.asAdmin(), new HasContainer(T.label.getAccessor(), P.eq(label)));
+ return TraversalHelper.addHasContainer(this.asAdmin(), new HasContainer(propertyKey, predicate));
+ }
+
/**
* Filters vertices, edges and vertex properties based on the non-existence of properties.
*
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversalSource.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversalSource.java
index 63e49e243f..968589b1db 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversalSource.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversalSource.java
@@ -346,6 +346,20 @@ public class GraphTraversalSource implements TraversalSource {
return traversal.addStep(new AddVertexStartStep(traversal, (String) null));
}
+ /**
+ * Spawns a {@link GraphTraversal} by adding a vertex with the specified label. If the {@code label} is
+ * {@code null} then it will default to {@link Vertex#DEFAULT_LABEL}.
+ *
+ * @since 4.0.0
+ */
+ public GraphTraversal<Vertex, Vertex> addV(final GValue<String> vertexLabel) {
+ if (null == vertexLabel) throw new IllegalArgumentException("vertexLabel cannot be null");
+ final GraphTraversalSource clone = this.clone();
+ clone.gremlinLang.addStep(GraphTraversal.Symbols.addV, vertexLabel);
+ final GraphTraversal.Admin<Vertex, Vertex> traversal = new DefaultGraphTraversal<>(clone);
+ return traversal.addStep(new AddVertexStartStep(traversal, vertexLabel));
+ }
+
/**
* Spawns a {@link GraphTraversal} by adding an edge with the specified label.
*
@@ -370,6 +384,18 @@ public class GraphTraversalSource implements TraversalSource {
return traversal.addStep(new AddEdgeStartStep(traversal, edgeLabelTraversal));
}
+ /**
+ * Spawns a {@link GraphTraversal} by adding an edge with the specified label.
+ *
+ * @since 4.0.0
+ */
+ public GraphTraversal<Edge, Edge> addE(final GValue<String> label) {
+ final GraphTraversalSource clone = this.clone();
+ clone.gremlinLang.addStep(GraphTraversal.Symbols.addE, label);
+ final GraphTraversal.Admin<Edge, Edge> traversal = new DefaultGraphTraversal<>(clone);
+ return traversal.addStep(new AddEdgeStartStep(traversal, label));
+ }
+
/**
* Spawns a {@link GraphTraversal} by doing a merge (i.e. upsert) style operation for an {@link Vertex} using a
* {@code Map} as an argument. The {@code Map} represents search criteria and will match each of the supplied
@@ -613,7 +639,7 @@ public class GraphTraversalSource implements TraversalSource {
*/
public <S> GraphTraversal<S, S> call(final String service, final GValue<Map> params, final Traversal<S, Map> childTraversal) {
final GraphTraversalSource clone = GraphTraversalSource.this.clone();
- clone.gremlinLang.addStep(GraphTraversal.Symbols.call, service, params);
+ clone.gremlinLang.addStep(GraphTraversal.Symbols.call, service, params, childTraversal);
final GraphTraversal.Admin<S, S> traversal = new DefaultGraphTraversal<>(clone);
return traversal.addStep(new CallStep<>(traversal, true, service, params, childTraversal.asAdmin()));
}
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 59fdf5f605..615a3a96f1 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
@@ -26,9 +26,12 @@ import org.apache.tinkerpop.gremlin.process.traversal.Scope;
import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
import org.apache.tinkerpop.gremlin.process.traversal.step.GValue;
+import org.apache.tinkerpop.gremlin.process.traversal.step.filter.HasStep;
import org.apache.tinkerpop.gremlin.process.traversal.step.map.FormatStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.HasContainer;
import org.apache.tinkerpop.gremlin.process.traversal.step.util.Tree;
import org.apache.tinkerpop.gremlin.process.traversal.traverser.util.TraverserSet;
+import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper;
import org.apache.tinkerpop.gremlin.structure.Column;
import org.apache.tinkerpop.gremlin.structure.Direction;
import org.apache.tinkerpop.gremlin.structure.Edge;
@@ -147,6 +150,13 @@ public class __ {
return __.<A>start().E(edgeIdsOrElements);
}
+ /**
+ * @see GraphTraversal#to(Direction)
+ */
+ public static GraphTraversal<Vertex, Vertex> to(final Direction direction) {
+ return __.<Vertex>start().to(direction);
+ }
+
/**
* @see GraphTraversal#to(Direction, String...)
*/
@@ -155,10 +165,17 @@ public class __ {
}
/**
- * @see GraphTraversal#to(Direction, GValue, GValue...)
+ * @see GraphTraversal#to(Direction, GValue...)
+ */
+ public static GraphTraversal<Vertex, Vertex> to(final Direction direction, final GValue<String>... edgeLabels) {
+ return __.<Vertex>start().to(direction, edgeLabels);
+ }
+
+ /**
+ * @see GraphTraversal#out()
*/
- public static GraphTraversal<Vertex, Vertex> to(final Direction direction, final GValue<String> edgeLabel, final GValue<String>... edgeLabels) {
- return __.<Vertex>start().to(direction, edgeLabel, edgeLabels);
+ public static GraphTraversal<Vertex, Vertex> out() {
+ return __.<Vertex>start().out();
}
/**
@@ -169,10 +186,17 @@ public class __ {
}
/**
- * @see GraphTraversal#out(GValue, GValue...)
+ * @see GraphTraversal#out(GValue...)
+ */
+ public static GraphTraversal<Vertex, Vertex> out(final GValue<String>... edgeLabels) {
+ return __.<Vertex>start().out(edgeLabels);
+ }
+
+ /**
+ * @see GraphTraversal#in()
*/
- public static GraphTraversal<Vertex, Vertex> out(final GValue<String> edgeLabel, final GValue<String>... edgeLabels) {
- return __.<Vertex>start().out(edgeLabel, edgeLabels);
+ public static GraphTraversal<Vertex, Vertex> in() {
+ return __.<Vertex>start().in();
}
/**
@@ -183,10 +207,17 @@ public class __ {
}
/**
- * @see GraphTraversal#in(String...)
+ * @see GraphTraversal#in(GValue...)
+ */
+ public static GraphTraversal<Vertex, Vertex> in(final GValue<String>... edgeLabels) {
+ return __.<Vertex>start().in(edgeLabels);
+ }
+
+ /**
+ * @see GraphTraversal#both()
*/
- public static GraphTraversal<Vertex, Vertex> in(final GValue<String> edgeLabel, final GValue<String>... edgeLabels) {
- return __.<Vertex>start().in(edgeLabel, edgeLabels);
+ public static GraphTraversal<Vertex, Vertex> both() {
+ return __.<Vertex>start().both();
}
/**
@@ -197,10 +228,17 @@ public class __ {
}
/**
- * @see GraphTraversal#both(GValue, GValue...)
+ * @see GraphTraversal#both(GValue...)
*/
- public static GraphTraversal<Vertex, Vertex> both(final GValue<String> edgeLabel, final GValue<String>... edgeLabels) {
- return __.<Vertex>start().both(edgeLabel, edgeLabels);
+ public static GraphTraversal<Vertex, Vertex> both(final GValue<String>... edgeLabels) {
+ return __.<Vertex>start().both(edgeLabels);
+ }
+
+ /**
+ * @see GraphTraversal#toE(Direction)
+ */
+ public static GraphTraversal<Vertex, Edge> toE(final Direction direction) {
+ return __.<Vertex>start().toE(direction);
}
/**
@@ -211,10 +249,17 @@ public class __ {
}
/**
- * @see GraphTraversal#toE(Direction, GValue, GValue...)
+ * @see GraphTraversal#toE(Direction, GValue...)
+ */
+ public static GraphTraversal<Vertex, Edge> toE(final Direction direction, final GValue<String>... edgeLabels) {
+ return __.<Vertex>start().toE(direction, edgeLabels);
+ }
+
+ /**
+ * @see GraphTraversal#outE()
*/
- public static GraphTraversal<Vertex, Edge> toE(final Direction direction, final GValue<String> edgeLabel, final GValue<String>... edgeLabels) {
- return __.<Vertex>start().toE(direction, edgeLabel, edgeLabels);
+ public static GraphTraversal<Vertex, Edge> outE() {
+ return __.<Vertex>start().outE();
}
/**
@@ -225,10 +270,17 @@ public class __ {
}
/**
- * @see GraphTraversal#outE(GValue, GValue...)
+ * @see GraphTraversal#outE(GValue...)
*/
- public static GraphTraversal<Vertex, Edge> outE(final GValue<String> edgeLabel, final GValue<String>... edgeLabels) {
- return __.<Vertex>start().outE(edgeLabel, edgeLabels);
+ public static GraphTraversal<Vertex, Edge> outE(final GValue<String>... edgeLabels) {
+ return __.<Vertex>start().outE(edgeLabels);
+ }
+
+ /**
+ * @see GraphTraversal#inE()
+ */
+ public static GraphTraversal<Vertex, Edge> inE() {
+ return __.<Vertex>start().inE();
}
/**
@@ -239,10 +291,17 @@ public class __ {
}
/**
- * @see GraphTraversal#inE(GValue, GValue...)
+ * @see GraphTraversal#inE(GValue...)
*/
- public static GraphTraversal<Vertex, Edge> inE(final GValue<String> edgeLabel, final GValue<String>... edgeLabels) {
- return __.<Vertex>start().inE(edgeLabel, edgeLabels);
+ public static GraphTraversal<Vertex, Edge> inE(final GValue<String>... edgeLabels) {
+ return __.<Vertex>start().inE(edgeLabels);
+ }
+
+ /**
+ * @see GraphTraversal#bothE()
+ */
+ public static GraphTraversal<Vertex, Edge> bothE() {
+ return __.<Vertex>start().bothE();
}
/**
@@ -253,10 +312,10 @@ public class __ {
}
/**
- * @see GraphTraversal#bothE(GValue, GValue...)
+ * @see GraphTraversal#bothE(GValue...)
*/
- public static GraphTraversal<Vertex, Edge> bothE(final GValue<String> edgeLabel, final GValue<String>... edgeLabels) {
- return __.<Vertex>start().bothE(edgeLabel, edgeLabels);
+ public static GraphTraversal<Vertex, Edge> bothE(final GValue<String>... edgeLabels) {
+ return __.<Vertex>start().bothE(edgeLabels);
}
/**
@@ -1076,6 +1135,14 @@ public class __ {
return __.<A>start().has(label, propertyKey, value);
}
+ /**
+ * @see GraphTraversal#has(GValue, String, P)
+ */
+ public static <A> GraphTraversal<A, A> has(final GValue<String> label, final String propertyKey, final P<?> predicate) {
+ return __.<A>start().has(label, propertyKey, predicate);
+ }
+
+
/**
* @see GraphTraversal#has(GValue, String, Object)
*/
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/lambda/ConstantTraversal.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/lambda/ConstantTraversal.java
index 3bac69ce48..8a662b396a 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/lambda/ConstantTraversal.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/lambda/ConstantTraversal.java
@@ -33,11 +33,11 @@ public final class ConstantTraversal<S, E> extends AbstractLambdaTraversal<S, E>
private final GValue<E> end;
public ConstantTraversal(final E end) {
- this.end = null == end ? GValue.of(null) : GValue.of(end);
+ this.end = null == end ? GValue.of(null, null) : GValue.of(null, end);
}
public ConstantTraversal(final GValue<E> end) {
- this.end = null == end ? GValue.of(null) : end;
+ this.end = null == end ? GValue.of(null, null) : end;
}
@Override
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/GValue.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/GValue.java
index 0608d94a19..b9f88684e3 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/GValue.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/GValue.java
@@ -52,6 +52,9 @@ public class GValue<V> implements Cloneable, Serializable {
}
private GValue(final String name, final GType type, final V value) {
+ if (name != null && name.startsWith("_")) {
+ throw new IllegalArgumentException(String.format("Invalid GValue name [%s]. Should not start with _.", name));
+ }
this.name = name;
this.type = type;
this.value = value;
@@ -120,7 +123,7 @@ public class GValue<V> implements Cloneable, Serializable {
*
* @param value the value of the variable
*/
- public static <V> GValue<V> of(final V value) {
+ static <V> GValue<V> of(final V value) {
if (value instanceof GValue) return (GValue) value;
return new GValue<>(GType.getType(value), value);
}
@@ -140,7 +143,7 @@ public class GValue<V> implements Cloneable, Serializable {
/**
* Create a new {@code GValue} for a string value.
*/
- public static GValue<String> ofString(final String value) {
+ static GValue<String> ofString(final String value) {
return new GValue<>(GType.STRING, value);
}
@@ -154,7 +157,7 @@ public class GValue<V> implements Cloneable, Serializable {
/**
* Create a new {@code GValue} for an integer value.
*/
- public static GValue<Integer> ofInteger(final Integer value) {
+ static GValue<Integer> ofInteger(final Integer value) {
return new GValue<>(GType.INTEGER, value);
}
@@ -168,7 +171,7 @@ public class GValue<V> implements Cloneable, Serializable {
/**
* Create a new {@code GValue} for a boolean value.
*/
- public static GValue<Boolean> ofBoolean(final Boolean value) {
+ static GValue<Boolean> ofBoolean(final Boolean value) {
return new GValue<>(GType.BOOLEAN, value);
}
@@ -182,7 +185,7 @@ public class GValue<V> implements Cloneable, Serializable {
/**
* Create a new {@code GValue} for a double value.
*/
- public static GValue<Double> ofDouble(final Double value) {
+ static GValue<Double> ofDouble(final Double value) {
return new GValue<>(GType.DOUBLE, value);
}
@@ -196,7 +199,7 @@ public class GValue<V> implements Cloneable, Serializable {
/**
* Create a new {@code GValue} for a BigInteger value.
*/
- public static GValue<BigInteger> ofBigInteger(final BigInteger value) {
+ static GValue<BigInteger> ofBigInteger(final BigInteger value) {
return new GValue<>(GType.BIG_INTEGER, value);
}
@@ -210,7 +213,7 @@ public class GValue<V> implements Cloneable, Serializable {
/**
* Create a new {@code GValue} for a BigDecimal value.
*/
- public static GValue<BigDecimal> ofBigDecimal(final BigDecimal value) {
+ static GValue<BigDecimal> ofBigDecimal(final BigDecimal value) {
return new GValue<>(GType.BIG_DECIMAL, value);
}
@@ -224,7 +227,7 @@ public class GValue<V> implements Cloneable, Serializable {
/**
* Create a new {@code GValue} for a long value.
*/
- public static GValue<Long> ofLong(final Long value) {
+ static GValue<Long> ofLong(final Long value) {
return new GValue<>(GType.LONG, value);
}
@@ -238,7 +241,7 @@ public class GValue<V> implements Cloneable, Serializable {
/**
* Create a new {@code GValue} for a map value.
*/
- public static GValue<Map> ofMap(final Map value) {
+ static GValue<Map> ofMap(final Map value) {
return new GValue<>(GType.MAP, value);
}
@@ -252,7 +255,7 @@ public class GValue<V> implements Cloneable, Serializable {
/**
* Create a new {@code GValue} for a list value.
*/
- public static <T> GValue<List<T>> ofList(final List<T> value) {
+ static <T> GValue<List<T>> ofList(final List<T> value) {
return new GValue<>(GType.LIST, value);
}
@@ -266,7 +269,7 @@ public class GValue<V> implements Cloneable, Serializable {
/**
* Create a new {@code GValue} for a set value.
*/
- public static GValue<Set> ofSet(final Set value) {
+ static GValue<Set> ofSet(final Set value) {
return new GValue<>(GType.SET, value);
}
@@ -280,7 +283,7 @@ public class GValue<V> implements Cloneable, Serializable {
/**
* Create a new {@code GValue} for a vertex value.
*/
- public static GValue<Vertex> ofVertex(final Vertex value) {
+ static GValue<Vertex> ofVertex(final Vertex value) {
return new GValue<>(GType.VERTEX, value);
}
@@ -294,7 +297,7 @@ public class GValue<V> implements Cloneable, Serializable {
/**
* Create a new {@code GValue} for an edge value.
*/
- public static GValue<Edge> ofEdge(final Edge value) {
+ static GValue<Edge> ofEdge(final Edge value) {
return new GValue<>(GType.EDGE, value);
}
@@ -308,7 +311,7 @@ public class GValue<V> implements Cloneable, Serializable {
/**
* Create a new {@code GValue} for a path value.
*/
- public static GValue<Path> ofPath(final Path value) {
+ static GValue<Path> ofPath(final Path value) {
return new GValue<>(GType.PATH, value);
}
@@ -322,7 +325,7 @@ public class GValue<V> implements Cloneable, Serializable {
/**
* Create a new {@code GValue} for a property value.
*/
- public static GValue<Property> ofProperty(final Property value) {
+ static GValue<Property> ofProperty(final Property value) {
return new GValue<>(GType.PROPERTY, value);
}
@@ -364,7 +367,7 @@ public class GValue<V> implements Cloneable, Serializable {
/**
* Checks the type of the object against the provided {@link GType}. If the object is a {@link GValue} then it
- * can directly check the type, otherwise it will test the given object's class itself using the mappign on the
+ * can directly check the type, otherwise it will test the given object's class itself using the mapping on the
* {@link GType}.
*/
public static boolean instanceOf(final Object o, final GType type) {
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/RepeatStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/RepeatStep.java
index 73414cf290..9e852bf388 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/RepeatStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/RepeatStep.java
@@ -179,9 +179,11 @@ public final class RepeatStep<S> extends ComputerAwareStep<S, S> implements Trav
@Override
public int hashCode() {
- int result = super.hashCode() ^ this.repeatTraversal.hashCode();
+ int result = super.hashCode();
result ^= Boolean.hashCode(this.untilFirst);
result ^= Boolean.hashCode(this.emitFirst) << 1;
+ if (this.repeatTraversal != null)
+ result ^= this.repeatTraversal.hashCode();
if (this.loopName != null)
result ^= this.loopName.hashCode();
if (this.untilTraversal != null)
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/CoinStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/CoinStep.java
index 5fd63ee3de..0efea0404f 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/CoinStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/CoinStep.java
@@ -41,12 +41,12 @@ public final class CoinStep<S> extends FilterStep<S> implements Seedable {
public CoinStep(final Traversal.Admin traversal, final double probability) {
super(traversal);
- this.probability = GValue.ofDouble(probability);
+ this.probability = GValue.ofDouble(null, probability);
}
public CoinStep(final Traversal.Admin traversal, final GValue<Double> probability) {
super(traversal);
- this.probability = null == probability ? GValue.ofDouble(null) : probability;
+ this.probability = null == probability ? GValue.ofDouble(null,null) : probability;
}
@Override
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AddEdgeStartStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AddEdgeStartStep.java
index 95907e9c7a..81f804f3e2 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AddEdgeStartStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AddEdgeStartStep.java
@@ -24,6 +24,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
import org.apache.tinkerpop.gremlin.process.traversal.TraverserGenerator;
import org.apache.tinkerpop.gremlin.process.traversal.step.FromToModulating;
+import org.apache.tinkerpop.gremlin.process.traversal.step.GValue;
import org.apache.tinkerpop.gremlin.process.traversal.step.Scoping;
import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent;
import org.apache.tinkerpop.gremlin.process.traversal.step.Writing;
@@ -68,6 +69,11 @@ public class AddEdgeStartStep extends AbstractStep<Edge, Edge>
this.parameters.set(this, T.label, edgeLabelTraversal);
}
+ public AddEdgeStartStep(final Traversal.Admin traversal, final GValue<String> edgeLabel) {
+ super(traversal);
+ this.parameters.set(this, T.label, edgeLabel.get());
+ }
+
@Override
public <S, E> List<Traversal.Admin<S, E>> getLocalChildren() {
return this.parameters.getTraversals();
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AddEdgeStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AddEdgeStep.java
index db3f72cfe7..258f8421ab 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AddEdgeStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AddEdgeStep.java
@@ -58,7 +58,7 @@ public class AddEdgeStep<S> extends ScalarMapStep<S, Edge>
public AddEdgeStep(final Traversal.Admin traversal, final String edgeLabel) {
super(traversal);
- this.parameters.set(this, T.label, edgeLabel);
+ this.parameters.set(this, T.label, GValue.of(null, edgeLabel));
}
public AddEdgeStep(final Traversal.Admin traversal, final GValue<String> edgeLabel) {
@@ -103,7 +103,10 @@ public class AddEdgeStep<S> extends ScalarMapStep<S, Edge>
@Override
protected Edge map(final Traverser.Admin<S> traverser) {
- final String edgeLabel = this.parameters.get(traverser, T.label, () -> Edge.DEFAULT_LABEL).get(0);
+ Object literalOrVar = this.parameters.get(traverser, T.label, () -> GValue.of(null, Edge.DEFAULT_LABEL)).get(0);
+ final GValue<String> edgeLabel = literalOrVar instanceof String ?
+ GValue.ofString(null, (String) literalOrVar) :
+ (GValue<String>) literalOrVar;
final Object theTo;
try {
@@ -143,7 +146,7 @@ public class AddEdgeStep<S> extends ScalarMapStep<S, Edge>
fromVertex = ((Attachable<Vertex>) fromVertex)
.attach(Attachable.Method.get(this.getTraversal().getGraph().orElse(EmptyGraph.instance())));
- final Edge edge = fromVertex.addEdge(edgeLabel, toVertex, this.parameters.getKeyValues(traverser, TO, FROM, T.label));
+ final Edge edge = fromVertex.addEdge(edgeLabel.get(), toVertex, this.parameters.getKeyValues(traverser, TO, FROM, T.label));
EventUtil.registerEdgeCreation(callbackRegistry, getTraversal(), edge);
return edge;
}
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AddVertexStartStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AddVertexStartStep.java
index fd52f445e8..d8dad9dbda 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AddVertexStartStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AddVertexStartStep.java
@@ -22,6 +22,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.Step;
import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
import org.apache.tinkerpop.gremlin.process.traversal.TraverserGenerator;
+import org.apache.tinkerpop.gremlin.process.traversal.step.GValue;
import org.apache.tinkerpop.gremlin.process.traversal.step.Scoping;
import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent;
import org.apache.tinkerpop.gremlin.process.traversal.step.Writing;
@@ -64,6 +65,12 @@ public class AddVertexStartStep extends AbstractStep<Vertex, Vertex>
userProvidedLabel = vertexLabelTraversal != null;
}
+ public AddVertexStartStep(final Traversal.Admin traversal, final GValue<String> label) {
+ super(traversal);
+ this.parameters.set(this, T.label, null == label ? Vertex.DEFAULT_LABEL : label);
+ userProvidedLabel = label != null;
+ }
+
public boolean hasUserProvidedLabel() {
return userProvidedLabel;
}
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/CallStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/CallStep.java
index 3dd99d1703..21c6058057 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/CallStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/CallStep.java
@@ -79,7 +79,7 @@ public final class CallStep<S, E> extends AbstractStep<S, E> implements Traversa
}
public CallStep(final Traversal.Admin traversal, final boolean isStart, final String service, final Map staticParams) {
- this(traversal, isStart, service, GValue.ofMap(staticParams));
+ this(traversal, isStart, service, GValue.ofMap(null, staticParams));
}
public CallStep(final Traversal.Admin traversal, final boolean isStart, final String service, final GValue<Map> staticParams) {
@@ -88,7 +88,7 @@ public final class CallStep<S, E> extends AbstractStep<S, E> implements Traversa
public CallStep(final Traversal.Admin traversal, final boolean isStart, final String service, final Map staticParams,
final Traversal.Admin<S, Map> mapTraversal) {
- this(traversal, isStart, service, GValue.ofMap(staticParams), mapTraversal);
+ this(traversal, isStart, service, GValue.ofMap(null, staticParams), mapTraversal);
}
public CallStep(final Traversal.Admin traversal, final boolean isStart, final String service, final GValue<Map> staticParams,
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/CombineStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/CombineStep.java
index 67c120c03a..4e6a6bd56b 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/CombineStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/CombineStep.java
@@ -46,7 +46,7 @@ public final class CombineStep<S, E> extends ScalarMapStep<S, List<?>> implement
if (values instanceof Traversal) {
valueTraversal = integrateChild(((Traversal<S, E>) values).asAdmin());
} else {
- parameterItems = values instanceof GValue ? (GValue<Object>) values : GValue.of(values);
+ parameterItems = values instanceof GValue ? (GValue<Object>) values : GValue.of(null, values);
}
}
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ConjoinStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ConjoinStep.java
index e6bb27a2e7..844a83ac2b 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ConjoinStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ConjoinStep.java
@@ -38,7 +38,7 @@ public final class ConjoinStep<S> extends ScalarMapStep<S, String> implements Li
private GValue<String> delimiter;
public ConjoinStep(final Traversal.Admin traversal, final String delimiter) {
- this(traversal, GValue.of(delimiter));
+ this(traversal, GValue.of(null, delimiter));
}
public ConjoinStep(final Traversal.Admin traversal, final GValue<String> delimiter) {
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ConstantStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ConstantStep.java
index 3646b599b2..1598e67ed0 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ConstantStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ConstantStep.java
@@ -33,12 +33,12 @@ public class ConstantStep<S, E> extends ScalarMapStep<S, E> {
private final GValue<E> constant;
public ConstantStep(final Traversal.Admin traversal, final E constant) {
- this(traversal, constant instanceof GValue ? (GValue) constant : GValue.of(constant));
+ this(traversal, constant instanceof GValue ? (GValue) constant : GValue.of(null, constant));
}
public ConstantStep(final Traversal.Admin traversal, final GValue<E> constant) {
super(traversal);
- this.constant = null == constant ? GValue.of(null) : constant;
+ this.constant = null == constant ? GValue.of(null, null) : constant;
}
public E getConstant() {
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/DifferenceStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/DifferenceStep.java
index 27922b984e..633c7b2f37 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/DifferenceStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/DifferenceStep.java
@@ -45,7 +45,7 @@ public final class DifferenceStep<S, E> extends ScalarMapStep<S, Set<?>> impleme
if (values instanceof Traversal) {
valueTraversal = integrateChild(((Traversal<S, E>) values).asAdmin());
} else {
- parameterItems = values instanceof GValue ? (GValue<Object>) values : GValue.of(values);
+ parameterItems = values instanceof GValue ? (GValue<Object>) values : GValue.of(null, values);
}
}
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/DisjunctStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/DisjunctStep.java
index c82eac3f64..de3336e900 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/DisjunctStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/DisjunctStep.java
@@ -44,7 +44,7 @@ public final class DisjunctStep<S, E> extends ScalarMapStep<S, Set<?>> implement
if (values instanceof Traversal) {
valueTraversal = integrateChild(((Traversal<S, E>) values).asAdmin());
} else {
- parameterItems = values instanceof GValue ? (GValue<Object>) values : GValue.of(values);
+ parameterItems = values instanceof GValue ? (GValue<Object>) values : GValue.of(null, values);
}
}
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/IntersectStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/IntersectStep.java
index 3c37db29e0..110e0527d2 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/IntersectStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/IntersectStep.java
@@ -45,7 +45,7 @@ public final class IntersectStep<S, E> extends ScalarMapStep<S, Set<?>> implemen
if (values instanceof Traversal) {
valueTraversal = integrateChild(((Traversal<S, E>) values).asAdmin());
} else {
- parameterItems = values instanceof GValue ? (GValue<Object>) values : GValue.of(values);
+ parameterItems = values instanceof GValue ? (GValue<Object>) values : GValue.of(null, values);
}
}
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MergeStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MergeStep.java
index 2f86240a42..7a169b4402 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MergeStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MergeStep.java
@@ -48,8 +48,10 @@ public final class MergeStep<S, E> extends ScalarMapStep<S, E> implements Traver
if (values instanceof Traversal) {
valueTraversal = integrateChild(((Traversal<S, E>) values).asAdmin());
+ } else if (values instanceof GValue){
+ parameterItems = (GValue<Object>) values;
} else {
- parameterItems = GValue.of(values);;
+ parameterItems = GValue.of(null, values);
}
}
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ProductStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ProductStep.java
index a07b204190..68373338f5 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ProductStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ProductStep.java
@@ -45,7 +45,7 @@ public final class ProductStep<S, E> extends ScalarMapStep<S, List<List<?>>> imp
if (values instanceof Traversal) {
valueTraversal = integrateChild(((Traversal<S, E>) values).asAdmin());
} else {
- parameterItems = values instanceof GValue ? (GValue<Object>) values : GValue.of(values);
+ parameterItems = values instanceof GValue ? (GValue<Object>) values : GValue.of(null, values);
}
}
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/DataType.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/DataType.java
index 90548c4cdd..5e7cddde8c 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/DataType.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/DataType.java
@@ -43,6 +43,7 @@ public enum DataType {
VERTEXPROPERTY(0X12),
DIRECTION(0X18),
T(0X20),
+ MERGE(0x2e),
TRAVERSER(0X21),
BIGDECIMAL(0X22),
BIGINTEGER(0X23),
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/TypeSerializerRegistry.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/TypeSerializerRegistry.java
index a5b9f79047..5eb09365e0 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/TypeSerializerRegistry.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/TypeSerializerRegistry.java
@@ -18,6 +18,7 @@
*/
package org.apache.tinkerpop.gremlin.structure.io.binary;
+import org.apache.tinkerpop.gremlin.process.traversal.Merge;
import org.apache.tinkerpop.gremlin.process.traversal.Path;
import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
import org.apache.tinkerpop.gremlin.process.traversal.step.util.BulkSet;
@@ -103,6 +104,7 @@ public class TypeSerializerRegistry {
new RegistryEntry<>(Vertex.class, new VertexSerializer()),
new RegistryEntry<>(Direction.class, EnumSerializer.DirectionSerializer),
new RegistryEntry<>(T.class, EnumSerializer.TSerializer),
+ new RegistryEntry<>(Merge.class, EnumSerializer.MergeSerializer),
new RegistryEntry<>(BigDecimal.class, new BigDecimalSerializer()),
new RegistryEntry<>(BigInteger.class, new BigIntegerSerializer()),
new RegistryEntry<>(Byte.class, SingleTypeSerializer.ByteSerializer),
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/EnumSerializer.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/EnumSerializer.java
index 394477dd4b..75ae33e9da 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/EnumSerializer.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/EnumSerializer.java
@@ -47,6 +47,7 @@ public class EnumSerializer<E extends Enum> extends SimpleTypeSerializer<E> {
public static final EnumSerializer<Direction> DirectionSerializer = new EnumSerializer<>(DataType.DIRECTION, Direction::valueOf);
public static final EnumSerializer<T> TSerializer = new EnumSerializer<>(DataType.T, T::valueOf);
+ public static final EnumSerializer<Merge> MergeSerializer = new EnumSerializer<>(DataType.MERGE, Merge::valueOf);
private final Function<String, E> readFunc;
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONModule.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONModule.java
index c18f3b05c5..cb60a0af8a 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONModule.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONModule.java
@@ -166,6 +166,7 @@ abstract class GraphSONModule extends TinkerPopJacksonModule {
put(Tree.class, "Tree");
Stream.of(
Direction.class,
+ Merge.class,
T.class).forEach(e -> put(e, e.getSimpleName()));
}});
@@ -202,6 +203,7 @@ abstract class GraphSONModule extends TinkerPopJacksonModule {
addSerializer(BulkSet.class, new TraversalSerializersV4.BulkSetJacksonSerializer());
Stream.of(
Direction.class,
+ Merge.class,
T.class).forEach(e -> addSerializer(e, new TraversalSerializersV4.EnumJacksonSerializer()));
/////////////////////// DESERIALIZERS ////////////////////////////
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/language/grammar/ArgumentVisitorTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/language/grammar/ArgumentVisitorTest.java
index 6a665787d3..ab5fbdcecb 100644
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/language/grammar/ArgumentVisitorTest.java
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/language/grammar/ArgumentVisitorTest.java
@@ -31,6 +31,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.SackFunctions;
import org.apache.tinkerpop.gremlin.process.traversal.Scope;
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.GValue;
import org.apache.tinkerpop.gremlin.structure.Column;
import org.apache.tinkerpop.gremlin.structure.Direction;
import org.apache.tinkerpop.gremlin.structure.T;
@@ -84,56 +85,67 @@ public class ArgumentVisitorTest {
public static Iterable<Object[]> generateTestParameters() {
return Arrays.asList(new Object[][]{
{Boolean.class, "x", new VariableResolverException("x"), createAntlr(VariableResolver.NoVariableResolver.instance())},
- {Boolean.class, "true", true, createAntlr(new VariableResolver.DirectVariableResolver(ElementHelper.asMap("x", true)))},
- {Boolean.class, "false", false, createAntlr(new VariableResolver.DirectVariableResolver(ElementHelper.asMap("x", true)))},
+ {Boolean.class, "true", true, createAntlr(new VariableResolver.DefaultVariableResolver(ElementHelper.asMap("x", true)))},
+ {Boolean.class, "false", false, createAntlr(new VariableResolver.DefaultVariableResolver(ElementHelper.asMap("x", true)))},
+ {Boolean.class, "x", GValue.of("x", true), createAntlr(new VariableResolver.DefaultVariableResolver(ElementHelper.asMap("x", true)))},
{Boolean.class, "x", true, createAntlr(new VariableResolver.DirectVariableResolver(ElementHelper.asMap("x", true)))},
{Integer.class, "x", new VariableResolverException("x"), createAntlr(VariableResolver.NoVariableResolver.instance())},
- {Integer.class, "0", 0, createAntlr(new VariableResolver.DirectVariableResolver(ElementHelper.asMap("x", 100)))},
- {Integer.class, "0i", 0, createAntlr(new VariableResolver.DirectVariableResolver(ElementHelper.asMap("x", 100)))},
- {Integer.class, "0L", 0L, createAntlr(new VariableResolver.DirectVariableResolver(ElementHelper.asMap("x", 100)))},
+ {Integer.class, "0", 0, createAntlr(new VariableResolver.DefaultVariableResolver(ElementHelper.asMap("x", 100)))},
+ {Integer.class, "0i", 0, createAntlr(new VariableResolver.DefaultVariableResolver(ElementHelper.asMap("x", 100)))},
+ {Integer.class, "0L", 0L, createAntlr(new VariableResolver.DefaultVariableResolver(ElementHelper.asMap("x", 100)))},
+ {Integer.class, "x", GValue.of("x", 0), createAntlr(new VariableResolver.DefaultVariableResolver(ElementHelper.asMap("x", 0)))},
+ {Integer.class, "x", GValue.of("x", 0L), createAntlr(new VariableResolver.DefaultVariableResolver(ElementHelper.asMap("x", 0L)))},
{Integer.class, "x", 0, createAntlr(new VariableResolver.DirectVariableResolver(ElementHelper.asMap("x", 0)))},
{Integer.class, "x", 0L, createAntlr(new VariableResolver.DirectVariableResolver(ElementHelper.asMap("x", 0L)))},
{Float.class, "x", new VariableResolverException("x"), createAntlr(VariableResolver.NoVariableResolver.instance())},
- {Float.class, "0.0d", 0.0, createAntlr(new VariableResolver.DirectVariableResolver(ElementHelper.asMap("x", 1000.0)))},
- {Float.class, "0d", 0.0, createAntlr(new VariableResolver.DirectVariableResolver(ElementHelper.asMap("x", 1000.0)))},
- {Float.class, "0F", 0.0F, createAntlr(new VariableResolver.DirectVariableResolver(ElementHelper.asMap("x", 1000.0F)))},
+ {Float.class, "0.0d", 0.0, createAntlr(new VariableResolver.DefaultVariableResolver(ElementHelper.asMap("x", 1000.0)))},
+ {Float.class, "0d", 0.0, createAntlr(new VariableResolver.DefaultVariableResolver(ElementHelper.asMap("x", 1000.0)))},
+ {Float.class, "0F", 0.0F, createAntlr(new VariableResolver.DefaultVariableResolver(ElementHelper.asMap("x", 1000.0F)))},
+ {Float.class, "x", GValue.of("x", 0.0), createAntlr(new VariableResolver.DefaultVariableResolver(ElementHelper.asMap("x", 0.0)))},
+ {Float.class, "x", GValue.of("x", 0.0F), createAntlr(new VariableResolver.DefaultVariableResolver(ElementHelper.asMap("x", 0.0F)))},
{Float.class, "x", 0.0, createAntlr(new VariableResolver.DirectVariableResolver(ElementHelper.asMap("x", 0.0)))},
{Float.class, "x", 0.0F, createAntlr(new VariableResolver.DirectVariableResolver(ElementHelper.asMap("x", 0.0F)))},
{String.class, "x", new VariableResolverException("x"), createAntlr(VariableResolver.NoVariableResolver.instance())},
- {String.class, "'test'", "test", createAntlr(new VariableResolver.DirectVariableResolver(ElementHelper.asMap("x", "nope")))},
+ {String.class, "'test'", "test", createAntlr(new VariableResolver.DefaultVariableResolver(ElementHelper.asMap("x", "nope")))},
+ {String.class, "x", GValue.of("x", "test"), createAntlr(new VariableResolver.DefaultVariableResolver(ElementHelper.asMap("x", "test")))},
+ {String.class, "x", GValue.of("x", "graphson"), createAntlr(new VariableResolver.DefaultVariableResolver(ElementHelper.asMap("x", IO.graphson)))},
{String.class, "x", "test", createAntlr(new VariableResolver.DirectVariableResolver(ElementHelper.asMap("x", "test")))},
{String.class, "x", "graphson", createAntlr(new VariableResolver.DirectVariableResolver(ElementHelper.asMap("x", IO.graphson)))},
{StringNullable.class, "x", new VariableResolverException("x"), createAntlr(VariableResolver.NoVariableResolver.instance())},
- {StringNullable.class, "null", null, createAntlr(new VariableResolver.DirectVariableResolver(ElementHelper.asMap("x", "nope")))},
+ {StringNullable.class, "null", null, createAntlr(new VariableResolver.DefaultVariableResolver(ElementHelper.asMap("x", "nope")))},
+ {StringNullable.class, "x", GValue.of("x", null), createAntlr(new VariableResolver.DefaultVariableResolver(nullMap))},
{StringNullable.class, "x", null, createAntlr(new VariableResolver.DirectVariableResolver(nullMap))},
{Object.class, "x", new VariableResolverException("x"), createAntlr(VariableResolver.NoVariableResolver.instance())},
- {Object.class, "'test'", "test", createAntlr(new VariableResolver.DirectVariableResolver(ElementHelper.asMap("x", "nope")))},
+ {Object.class, "'test'", "test", createAntlr(new VariableResolver.DefaultVariableResolver(ElementHelper.asMap("x", "nope")))},
+ {Object.class, "x", GValue.of("x", "test"), createAntlr(new VariableResolver.DefaultVariableResolver(ElementHelper.asMap("x", "test")))},
+ {Object.class, "x", GValue.of("x", now), createAntlr(new VariableResolver.DefaultVariableResolver(ElementHelper.asMap("x", now)))},
{Object.class, "x", "test", createAntlr(new VariableResolver.DirectVariableResolver(ElementHelper.asMap("x", "test")))},
{Object.class, "x", now, createAntlr(new VariableResolver.DirectVariableResolver(ElementHelper.asMap("x", now)))},
- {Object.class, "[1,2,3]", Arrays.asList(1, 2, 3), createAntlr(new VariableResolver.DirectVariableResolver(ElementHelper.asMap("x", now)))},
+ {Object.class, "[1,2,3]", Arrays.asList(1, 2, 3), createAntlr(new VariableResolver.DefaultVariableResolver(ElementHelper.asMap("x", now)))},
+ {Object.class, "x", GValue.of("x", P.eq(100)), createAntlr(new VariableResolver.DefaultVariableResolver(ElementHelper.asMap("x", P.eq(100))))},
{Object.class, "x", P.eq(100), createAntlr(new VariableResolver.DirectVariableResolver(ElementHelper.asMap("x", P.eq(100))))},
- {Direction.class, "Direction.OUT", Direction.OUT, createAntlr(new VariableResolver.DirectVariableResolver(ElementHelper.asMap("x", "nope")))},
- {Direction.class, "OUT", Direction.OUT, createAntlr(new VariableResolver.DirectVariableResolver(ElementHelper.asMap("x", "nope")))},
- {Vertex.class, "new Vertex(1i,'person')", new ReferenceVertex(1, "person"), createAntlr(new VariableResolver.DirectVariableResolver(ElementHelper.asMap("x", Direction.from)))},
- {Order.class, "Order.desc", Order.desc, createAntlr(new VariableResolver.DirectVariableResolver(ElementHelper.asMap("x", "nope")))},
- {Scope.class, "Scope.local", Scope.local, createAntlr(new VariableResolver.DirectVariableResolver(ElementHelper.asMap("x", "nope")))},
- {Scope.class, "local", Scope.local, createAntlr(new VariableResolver.DirectVariableResolver(ElementHelper.asMap("x", "nope")))},
- {T.class, "T.label", T.label, createAntlr(new VariableResolver.DirectVariableResolver(ElementHelper.asMap("x", "nope")))},
- {T.class, "label", T.label, createAntlr(new VariableResolver.DirectVariableResolver(ElementHelper.asMap("x", "nope")))},
- {VertexProperty.Cardinality.class, "Cardinality.list", VertexProperty.Cardinality.list, createAntlr(new VariableResolver.DirectVariableResolver(ElementHelper.asMap("x", "nope")))},
- {VertexProperty.Cardinality.class, "list", VertexProperty.Cardinality.list, createAntlr(new VariableResolver.DirectVariableResolver(ElementHelper.asMap("x", "nope")))},
- {DT.class, "DT.hour", DT.hour, createAntlr(new VariableResolver.DirectVariableResolver(ElementHelper.asMap("x", "nope")))},
- {DT.class, "hour", DT.hour, createAntlr(new VariableResolver.DirectVariableResolver(ElementHelper.asMap("x", "nope")))},
- {Merge.class, "Merge.onMatch", Merge.onMatch, createAntlr(new VariableResolver.DirectVariableResolver(ElementHelper.asMap("x", "nope")))},
- {Merge.class, "onMatch", Merge.onMatch, createAntlr(new VariableResolver.DirectVariableResolver(ElementHelper.asMap("x", "nope")))},
- {Pop.class, "Pop.last", Pop.last, createAntlr(new VariableResolver.DirectVariableResolver(ElementHelper.asMap("x", "nope")))},
- {Pop.class, "last", Pop.last, createAntlr(new VariableResolver.DirectVariableResolver(ElementHelper.asMap("x", "nope")))},
- {Operator.class, "Operator.sum", Operator.sum, createAntlr(new VariableResolver.DirectVariableResolver(ElementHelper.asMap("x", "nope")))},
- {Operator.class, "sum", Operator.sum, createAntlr(new VariableResolver.DirectVariableResolver(ElementHelper.asMap("x", "nope")))},
- {Column.class, "Column.keys", Column.keys, createAntlr(new VariableResolver.DirectVariableResolver(ElementHelper.asMap("x", "nope")))},
- {Column.class, "keys", Column.keys, createAntlr(new VariableResolver.DirectVariableResolver(ElementHelper.asMap("x", "nope")))},
- {SackFunctions.Barrier.class, "Barrier.normSack", SackFunctions.Barrier.normSack, createAntlr(new VariableResolver.DirectVariableResolver(ElementHelper.asMap("x", "nope")))},
- {SackFunctions.Barrier.class, "Barrier.normSack", SackFunctions.Barrier.normSack, createAntlr(new VariableResolver.DirectVariableResolver(ElementHelper.asMap("x", "nope")))},
+ {Direction.class, "Direction.OUT", Direction.OUT, createAntlr(new VariableResolver.DefaultVariableResolver(ElementHelper.asMap("x", "nope")))},
+ {Direction.class, "OUT", Direction.OUT, createAntlr(new VariableResolver.DefaultVariableResolver(ElementHelper.asMap("x", "nope")))},
+ {Vertex.class, "new Vertex(1i,'person')", new ReferenceVertex(1, "person"), createAntlr(new VariableResolver.DefaultVariableResolver(ElementHelper.asMap("x", Direction.from)))},
+ {Order.class, "Order.desc", Order.desc, createAntlr(new VariableResolver.DefaultVariableResolver(ElementHelper.asMap("x", "nope")))},
+ {Scope.class, "Scope.local", Scope.local, createAntlr(new VariableResolver.DefaultVariableResolver(ElementHelper.asMap("x", "nope")))},
+ {Scope.class, "local", Scope.local, createAntlr(new VariableResolver.DefaultVariableResolver(ElementHelper.asMap("x", "nope")))},
+ {T.class, "T.label", T.label, createAntlr(new VariableResolver.DefaultVariableResolver(ElementHelper.asMap("x", "nope")))},
+ {T.class, "label", T.label, createAntlr(new VariableResolver.DefaultVariableResolver(ElementHelper.asMap("x", "nope")))},
+ {VertexProperty.Cardinality.class, "Cardinality.list", VertexProperty.Cardinality.list, createAntlr(new VariableResolver.DefaultVariableResolver(ElementHelper.asMap("x", "nope")))},
+ {VertexProperty.Cardinality.class, "list", VertexProperty.Cardinality.list, createAntlr(new VariableResolver.DefaultVariableResolver(ElementHelper.asMap("x", "nope")))},
+ {DT.class, "DT.hour", DT.hour, createAntlr(new VariableResolver.DefaultVariableResolver(ElementHelper.asMap("x", "nope")))},
+ {DT.class, "hour", DT.hour, createAntlr(new VariableResolver.DefaultVariableResolver(ElementHelper.asMap("x", "nope")))},
+ {Merge.class, "Merge.onMatch", Merge.onMatch, createAntlr(new VariableResolver.DefaultVariableResolver(ElementHelper.asMap("x", "nope")))},
+ {Merge.class, "onMatch", Merge.onMatch, createAntlr(new VariableResolver.DefaultVariableResolver(ElementHelper.asMap("x", "nope")))},
+ {Pop.class, "Pop.last", Pop.last, createAntlr(new VariableResolver.DefaultVariableResolver(ElementHelper.asMap("x", "nope")))},
+ {Pop.class, "last", Pop.last, createAntlr(new VariableResolver.DefaultVariableResolver(ElementHelper.asMap("x", "nope")))},
+ {Operator.class, "Operator.sum", Operator.sum, createAntlr(new VariableResolver.DefaultVariableResolver(ElementHelper.asMap("x", "nope")))},
+ {Operator.class, "sum", Operator.sum, createAntlr(new VariableResolver.DefaultVariableResolver(ElementHelper.asMap("x", "nope")))},
+ {Column.class, "Column.keys", Column.keys, createAntlr(new VariableResolver.DefaultVariableResolver(ElementHelper.asMap("x", "nope")))},
+ {Column.class, "keys", Column.keys, createAntlr(new VariableResolver.DefaultVariableResolver(ElementHelper.asMap("x", "nope")))},
+ {SackFunctions.Barrier.class, "Barrier.normSack", SackFunctions.Barrier.normSack, createAntlr(new VariableResolver.DefaultVariableResolver(ElementHelper.asMap("x", "nope")))},
+ {SackFunctions.Barrier.class, "Barrier.normSack", SackFunctions.Barrier.normSack, createAntlr(new VariableResolver.DefaultVariableResolver(ElementHelper.asMap("x", "nope")))},
});
}
@@ -144,32 +156,32 @@ public class ArgumentVisitorTest {
if (clazz.equals(Boolean.class)) {
assertParsing(() -> {
final GremlinParser.BooleanArgumentContext ctx = parser.booleanArgument();
- return antlrToLanguage.argumentVisitor.parseBoolean(ctx);
+ return antlrToLanguage.argumentVisitor.visitBooleanArgument(ctx);
});
} else if (clazz.equals(Integer.class)) {
assertParsing(() -> {
final GremlinParser.IntegerArgumentContext ctx = parser.integerArgument();
- return antlrToLanguage.argumentVisitor.parseNumber(ctx);
+ return antlrToLanguage.argumentVisitor.visitIntegerArgument(ctx);
});
} else if (clazz.equals(Float.class)) {
assertParsing(() -> {
final GremlinParser.FloatArgumentContext ctx = parser.floatArgument();
- return antlrToLanguage.argumentVisitor.parseNumber(ctx);
+ return antlrToLanguage.argumentVisitor.visitFloatArgument(ctx);
});
} else if (clazz.equals(String.class)) {
assertParsing(() -> {
final GremlinParser.StringArgumentContext ctx = parser.stringArgument();
- return antlrToLanguage.argumentVisitor.parseString(ctx);
+ return antlrToLanguage.argumentVisitor.visitStringArgument(ctx);
});
} else if (clazz.equals(StringNullable.class)) {
assertParsing(() -> {
final GremlinParser.StringNullableArgumentContext ctx = parser.stringNullableArgument();
- return antlrToLanguage.argumentVisitor.parseString(ctx);
+ return antlrToLanguage.argumentVisitor.visitStringNullableArgument(ctx);
});
} else if (clazz.equals(Object.class)) {
assertParsing(() -> {
final GremlinParser.GenericLiteralArgumentContext ctx = parser.genericLiteralArgument();
- return antlrToLanguage.argumentVisitor.parseObject(ctx);
+ return antlrToLanguage.argumentVisitor.visitGenericLiteralArgument(ctx);
});
} else if (clazz.equals(List.class)) {
assertParsing(() -> {
@@ -181,7 +193,7 @@ public class ArgumentVisitorTest {
} else if (clazz.equals(Vertex.class)) {
assertParsing(() -> {
final GremlinParser.StructureVertexArgumentContext ctx = parser.structureVertexArgument();
- return antlrToLanguage.argumentVisitor.parseVertex(ctx);
+ return antlrToLanguage.argumentVisitor.visitStructureVertexArgument(ctx);
});
} else if (clazz.equals(Order.class)) {
assertParsing(() -> TraversalEnumParser.parseTraversalEnumFromContext(Order.class, parser.traversalOrder()));
@@ -225,4 +237,4 @@ public class ArgumentVisitorTest {
}
private static class StringNullable { }
-}
+}
\ No newline at end of file
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalMethodVisitorTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalMethodVisitorTest.java
index cc4f0c1fd9..a40ba6e6c6 100644
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalMethodVisitorTest.java
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalMethodVisitorTest.java
@@ -163,7 +163,7 @@ public class TraversalMethodVisitorTest {
@Test
public void shouldParseTraversalMethod_both_MultiString() throws Exception {
- compare(g.V().both(new String[]{"a", "b"}), eval("g.V().both('a', 'b')"));
+ compare(g.V().both("a", "b"), eval("g.V().both('a', 'b')"));
}
@Test
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/language/translator/GremlinTranslatorTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/language/translator/GremlinTranslatorTest.java
index 82e3461cc5..3858b265f2 100644
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/language/translator/GremlinTranslatorTest.java
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/language/translator/GremlinTranslatorTest.java
@@ -48,7 +48,7 @@ public class GremlinTranslatorTest {
public static Collection<Object[]> data() {
return Arrays.asList(new Object[][]{
{"g.V(l1)", Collections.singletonList("l1")},
- {"g.V().hasLabel('person').has(x, y).as('a').out('knows').as('b').select('a', 'b')", Arrays.asList("x", "y")},
+ {"g.V().hasLabel('person').has('key', y).as('a').out('knows').as('b').select('a', 'b')", Collections.singletonList("y")},
{"g.V(x).map(out(y).count())", Arrays.asList("x", "y")},
});
}
@@ -1063,11 +1063,11 @@ public class GremlinTranslatorTest {
"g.V().limit(1l)",
"g.V().limit(1)",
"g.V().limit(long(1))"},
- {"g.V().limit(x)",
- null,
+ {"g.V().limit(1)",
null,
- "g.V().Limit<object>(x)",
- "g.V().Limit(x)",
+ "g.V().limit(number0)",
+ "g.V().Limit<object>(1)",
+ "g.V().Limit(1)",
null,
null,
null,
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/remote/EmbeddedRemoteConnectionTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/remote/EmbeddedRemoteConnectionTest.java
index ad5a75c7a3..30df9bc0b2 100644
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/remote/EmbeddedRemoteConnectionTest.java
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/remote/EmbeddedRemoteConnectionTest.java
@@ -19,13 +19,12 @@
package org.apache.tinkerpop.gremlin.process.remote;
import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
+import org.apache.tinkerpop.gremlin.process.traversal.step.GValue;
import org.apache.tinkerpop.gremlin.structure.Graph;
import org.apache.tinkerpop.gremlin.structure.util.empty.EmptyGraph;
import org.junit.Test;
import static org.apache.tinkerpop.gremlin.process.traversal.AnonymousTraversalSource.traversal;
-import static org.apache.tinkerpop.gremlin.process.traversal.GremlinLang.Parameter.value;
-import static org.apache.tinkerpop.gremlin.process.traversal.GremlinLang.Parameter.var;
import static org.junit.Assert.assertEquals;
public class EmbeddedRemoteConnectionTest {
@@ -42,6 +41,6 @@ public class EmbeddedRemoteConnectionTest {
final Graph graph = EmptyGraph.instance();
final GraphTraversalSource g = graph.traversal();
final GraphTraversalSource simulatedRemoteG = traversal().with(new EmbeddedRemoteConnection(g));
- assertEquals(33, simulatedRemoteG.inject(value(11), var("x", 22)).sum().next());
+ assertEquals(33, simulatedRemoteG.inject(GValue.of(null, 11), GValue.of("x", 22)).sum().next());
}
}
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/GremlinLangTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/GremlinLangTest.java
index 47318fafc3..7911a95ed9 100644
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/GremlinLangTest.java
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/GremlinLangTest.java
@@ -18,9 +18,9 @@
*/
package org.apache.tinkerpop.gremlin.process.traversal;
-import org.apache.tinkerpop.gremlin.process.traversal.GremlinLang.Parameter;
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.GValue;
import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.SeedStrategy;
import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.SubgraphStrategy;
import org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.ReadOnlyStrategy;
@@ -120,8 +120,8 @@ public class GremlinLangTest {
"g.withStrategies(new SubgraphStrategy(checkAdjacentVertices:true,vertices:__.hasLabel(\"person\"))).V()",},
{g.withStrategies(SubgraphStrategy.build().vertices(__.has("name", P.within("josh", "lop", "ripple"))).create()).V(),
"g.withStrategies(new SubgraphStrategy(checkAdjacentVertices:true,vertices:__.has(\"name\",P.within([\"josh\",\"lop\",\"ripple\"])))).V()"},
- {g.inject(Parameter.var("x", "x")).V(Parameter.var("ids", new int[]{1, 2, 3})), "g.inject(x).V(ids)"},
- {newG().inject(Parameter.value("test1"), Parameter.value("test2")), "g.inject(_0,_1)"},
+ {g.inject(GValue.of("x", "x")).V(GValue.of("ids", new int[]{1, 2, 3})), "g.inject(x).V(ids)"},
+ {newG().inject(GValue.of(null, "test1"), GValue.of("xx2", "test2")), "g.inject(\"test1\",xx2)"},
{newG().inject(new HashSet<>(Arrays.asList(1, 2))), "g.inject({1,2})"},
});
}
@@ -130,35 +130,35 @@ public class GremlinLangTest {
@Test(expected = IllegalArgumentException.class)
public void shouldCheckParameterNameDontNeedEscaping() {
- g.V(GremlinLang.Parameter.var("\"", new int[]{1, 2, 3}));
+ g.V(GValue.of("\"", new int[]{1, 2, 3}));
}
@Test(expected = IllegalArgumentException.class)
public void shouldCheckParameterNameIsNotNumber() {
- g.V(GremlinLang.Parameter.var("1", new int[]{1, 2, 3}));
+ g.V(GValue.of("1", new int[]{1, 2, 3}));
}
@Test(expected = IllegalArgumentException.class)
public void shouldCheckParameterNameIsValidIdentifier() {
- g.V(GremlinLang.Parameter.var("1a", new int[]{1, 2, 3}));
+ g.V(GValue.of("1a", new int[]{1, 2, 3}));
}
@Test(expected = IllegalArgumentException.class)
public void shouldCheckParameterNameIsNotReserved() {
- g.V(GremlinLang.Parameter.var("_1", new int[]{1, 2, 3}));
+ g.V(GValue.of("_1", new int[]{1, 2, 3}));
}
@Test(expected = IllegalArgumentException.class)
public void shouldNowAllowParameterNameDuplicates() {
- final GremlinLang gremlin = g.inject(Parameter.var("ids", new int[]{1, 2})).V(Parameter.var("ids", new int[]{2, 3}))
+ final GremlinLang gremlin = g.inject(GValue.of("ids", new int[]{1, 2})).V(GValue.of("ids", new int[]{2, 3}))
.asAdmin().getGremlinLang();
}
@Test
public void shouldAllowToUseSameParameterTwice() {
final int[] value = new int[]{1, 2, 3};
- final Parameter p = Parameter.var("ids", value);
- final GremlinLang gremlin = g.inject(p).V(p).asAdmin().getGremlinLang();
+ final GValue<int[]> gValue = GValue.of("ids", value);
+ final GremlinLang gremlin = g.inject(gValue).V(gValue).asAdmin().getGremlinLang();
assertEquals("g.inject(ids).V(ids)", gremlin.getGremlin());
assertEquals(value, gremlin.getParameters().get("ids"));
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversalSourceTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversalSourceTest.java
index fb96db1f6f..cf1ab59b9b 100644
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversalSourceTest.java
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversalSourceTest.java
@@ -23,15 +23,13 @@ import org.apache.tinkerpop.gremlin.process.remote.RemoteConnection;
import org.apache.tinkerpop.gremlin.process.traversal.GremlinLang;
import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
import org.apache.tinkerpop.gremlin.process.traversal.Order;
+import org.apache.tinkerpop.gremlin.process.traversal.step.GValue;
import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.SubgraphStrategy;
import org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.ReadOnlyStrategy;
import org.apache.tinkerpop.gremlin.structure.T;
-import org.apache.tinkerpop.gremlin.structure.Graph;
import org.apache.tinkerpop.gremlin.structure.util.empty.EmptyGraph;
import org.apache.tinkerpop.gremlin.util.CollectionUtil;
import org.junit.Test;
-import org.mockito.invocation.InvocationOnMock;
-import org.mockito.stubbing.Answer;
import java.util.Arrays;
import java.util.HashMap;
@@ -40,18 +38,14 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static org.apache.tinkerpop.gremlin.process.traversal.AnonymousTraversalSource.traversal;
-import static org.apache.tinkerpop.gremlin.process.traversal.GremlinLang.Parameter.value;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.collection.IsIterableContainingInAnyOrder.containsInAnyOrder;
import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
-import static org.mockito.Answers.RETURNS_DEEP_STUBS;
-import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
/**
* @author Stephen Mallette (http://stephen.genoprime.com)
@@ -159,7 +153,7 @@ public class GraphTraversalSourceTest {
@Test
public void shouldContainReuseableGremlinLang() {
- final Pattern paramPatter = Pattern.compile("_\\d+");
+ final Pattern paramPatter = Pattern.compile("xx\\d+");
assertThat(g.getGremlinLang().getOptionsStrategies().isEmpty(), is(true));
g.with("a", "1").V();
assertThat(g.getGremlinLang().getOptionsStrategies().isEmpty(), is(true));
@@ -167,7 +161,7 @@ public class GraphTraversalSourceTest {
assertThat(g.getGremlinLang().getOptionsStrategies().isEmpty(), is(true));
assertThat(g.getGremlinLang().getParameters().isEmpty(), is(true));
- GremlinLang lang = g.V(value(11)).asAdmin().getGremlinLang();
+ GremlinLang lang = g.V(GValue.of("xx1", 11)).asAdmin().getGremlinLang();
assertThat(g.getGremlinLang().getParameters().isEmpty(), is(true));
assertThat(lang.getParameters().size(), is(1));
assertThat(lang.getParameters().values(), containsInAnyOrder(11));
@@ -175,7 +169,7 @@ public class GraphTraversalSourceTest {
paramMatcher.find();
assertThat(lang.getParameters().keySet(), containsInAnyOrder(paramMatcher.group()));
- lang = g.V(value(22)).asAdmin().getGremlinLang();
+ lang = g.V(GValue.of("xx2", 22)).asAdmin().getGremlinLang();
assertThat(g.getGremlinLang().getParameters().isEmpty(), is(true));
assertThat(lang.getParameters().size(), is(1));
assertThat(lang.getParameters().values(), containsInAnyOrder(22));
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/GValueTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/GValueTest.java
index 10bfafed29..0335d4a89c 100644
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/GValueTest.java
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/GValueTest.java
@@ -77,7 +77,7 @@ public class GValueTest {
@Test
public void shouldCreateGValueFromString() {
- final GValue<String> gValue = GValue.ofString("test");
+ final GValue<String> gValue = GValue.ofString(null, "test");
assertEquals("test", gValue.get());
assertEquals(GType.STRING, gValue.getType());
assertThat(gValue.isVariable(), is(false));
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/PartitionStrategyTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/PartitionStrategyTest.java
index b4d25f2626..fc811b9229 100644
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/PartitionStrategyTest.java
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/PartitionStrategyTest.java
@@ -23,6 +23,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.Step;
import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.DefaultGraphTraversal;
import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal;
+import org.apache.tinkerpop.gremlin.process.traversal.step.GValue;
import org.apache.tinkerpop.gremlin.process.traversal.step.filter.HasStep;
import org.apache.tinkerpop.gremlin.process.traversal.step.map.AddEdgeStep;
import org.apache.tinkerpop.gremlin.process.traversal.step.map.AddVertexStartStep;
@@ -117,7 +118,7 @@ public class PartitionStrategyTest {
final List<AddEdgeStep> addEdgeSteps = TraversalHelper.getStepsOfAssignableClass(AddEdgeStep.class, traversal.asAdmin());
assertEquals(1, addEdgeSteps.size());
addEdgeSteps.forEach(s -> {
- assertEquals(repr, "test", s.getParameters().get(T.label, () -> Edge.DEFAULT_LABEL).get(0));
+ assertEquals(repr, GValue.of(null, "test"), s.getParameters().get(T.label, () -> Edge.DEFAULT_LABEL).get(0));
assertEquals(repr, "a", s.getParameters().get("p", null).get(0));
});
} else if (TraversalHelper.hasStepOfAssignableClass(AddVertexStep.class, traversal.asAdmin())) {
diff --git a/gremlin-javascript/build/generate.groovy b/gremlin-javascript/build/generate.groovy
index feccd96688..8ab7e90f16 100644
--- a/gremlin-javascript/build/generate.groovy
+++ b/gremlin-javascript/build/generate.groovy
@@ -90,7 +90,7 @@ radishGremlinFile.withWriter('UTF-8') { Writer writer ->
writer.writeLine('const gremlins = {')
gremlins.each { k,v ->
// skipping lambdas until we decide for sure that they are out in 4.x
- if (v.any { it.contains('l1')} || v.any { it.contains('pred1')} || v.any { it.contains('Lambda')}) {
+ if (v.any { it.contains('l1')} || v.any { it.contains('pred1')} || v.any { it.contains('Lambda')} || v.any { it.contains('c1')}) {
writer.writeLine(" '${k}': [], // skipping as it contains a lambda")
} else if (staticTranslate.containsKey(k)) {
writer.writeLine(staticTranslate[k])
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/gremlin.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/gremlin.js
index 89e85ac91d..800d2fb85e 100644
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/gremlin.js
+++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/gremlin.js
@@ -168,7 +168,7 @@ const gremlins = {
g_V_out_asXxX_in_asXyX_selectXx_yX_byXnameX_fold_dedupXlocal_x_yX_unfold: [function({g}) { return g.V().out().as("x").in_().as("y").select("x", "y").by("name").fold().dedup(Scope.local, "x", "y").unfold() }],
g_V_both_dedup_name: [function({g}) { return g.V().both().dedup().values("name") }],
g_V_both_hasXlabel_softwareX_dedup_byXlangX_name: [function({g}) { return g.V().both().has(T.label, "software").dedup().by("lang").values("name") }],
- g_V_both_name_order_byXa_bX_dedup_value: [function({g, c1}) { return g.V().both().properties("name").order().by(c1).dedup().value() }],
+ 'g_V_both_name_order_byXa_bX_dedup_value': [], // skipping as it contains a lambda
g_V_both_both_name_dedup: [function({g}) { return g.V().both().both().values("name").dedup() }],
g_V_both_both_dedup: [function({g}) { return g.V().both().both().dedup() }],
g_V_both_both_dedup_byXlabelX: [function({g}) { return g.V().both().both().dedup().by(T.label) }],
@@ -212,6 +212,7 @@ const gremlins = {
g_VX1X_hasXnameX: [function({g, vid1}) { return g.V(vid1).has("name") }],
g_VX1X_hasXcircumferenceX: [function({g, vid1}) { return g.V(vid1).has("circumference") }],
g_VX1X_hasXname_markoX: [function({g, vid1}) { return g.V(vid1).has("name", "marko") }],
+ g_VX1X_hasXname_markovarX: [function({g, xx1, vid1}) { return g.V(vid1).has("name", xx1) }],
g_VX2X_hasXname_markoX: [function({g, vid1}) { return g.V(vid1).has("name", "marko") }],
g_V_hasXname_markoX: [function({g}) { return g.V().has("name", "marko") }],
g_V_hasXname_blahX: [function({g}) { return g.V().has("name", "blah") }],
@@ -310,8 +311,11 @@ const gremlins = {
g_V_properties_hasValueXnull_nullX: [function({g}) { return g.V().properties().hasValue(null, null) }],
g_V_properties_hasValueXnull_joshX_value: [function({g}) { return g.V().properties().hasValue(null, "josh").value() }],
g_V_valuesXageX_isX32X: [function({g}) { return g.V().values("age").is(32) }],
+ g_V_valuesXageX_isX32varX: [function({g, xx1}) { return g.V().values("age").is(xx1) }],
g_V_valuesXageX_isXlte_30X: [function({g}) { return g.V().values("age").is(P.lte(30)) }],
+ g_V_valuesXageX_isXlte_30varX: [function({g, xx1}) { return g.V().values("age").is(P.lte(xx1)) }],
g_V_valuesXageX_isXgte_29X_isXlt_34X: [function({g}) { return g.V().values("age").is(P.gte(29)).is(P.lt(34)) }],
+ g_V_valuesXageX_isXgte_29vaarX_isXlt_34varX: [function({g, xx1, xx2}) { return g.V().values("age").is(P.gte(xx1)).is(P.lt(xx2)) }],
g_V_whereXinXcreatedX_count_isX1XX_valuesXnameX: [function({g}) { return g.V().where(__.in_("created").count().is(1)).values("name") }],
g_V_whereXinXcreatedX_count_isXgte_2XX_valuesXnameX: [function({g}) { return g.V().where(__.in_("created").count().is(P.gte(2))).values("name") }],
g_V_valuesXageX_noneXgtX32XX: [function({g}) { return g.V().values("age").none(P.gt(32)) }],
@@ -379,7 +383,7 @@ const gremlins = {
g_V_hasXageX_asXaX_out_in_hasXageX_asXbX_selectXa_bX_whereXb_hasXname_markoXX: [function({g}) { return g.V().has("age").as("a").out().in_().has("age").as("b").select("a", "b").where(__.as("b").has("name", "marko")) }],
g_V_hasXageX_asXaX_out_in_hasXageX_asXbX_selectXa_bX_whereXa_outXknowsX_bX: [function({g}) { return g.V().has("age").as("a").out().in_().has("age").as("b").select("a", "b").where(__.as("a").out("knows").as("b")) }],
g_V_asXaX_outXcreatedX_whereXasXaX_name_isXjoshXX_inXcreatedX_name: [function({g}) { return g.V().as("a").out("created").where(__.as("a").values("name").is("josh")).in_("created").values("name") }],
- g_withSideEffectXa_josh_peterX_VX1X_outXcreatedX_inXcreatedX_name_whereXwithinXaXX: [function({g, xx1, vid1}) { return g.withSideEffect("a", xx1).V(vid1).out("created").in_("created").values("name").where(P.within("a")) }],
+ g_withSideEffectXa_josh_peterX_VX1X_outXcreatedX_inXcreatedX_name_whereXwithinXaXX: [function({g, vid1}) { return g.withSideEffect("a", ["josh", "peter"]).V(vid1).out("created").in_("created").values("name").where(P.within("a")) }],
g_VX1X_asXaX_outXcreatedX_inXcreatedX_asXbX_whereXa_neqXbXX_name: [function({g, vid1}) { return g.V(vid1).as("a").out("created").in_("created").as("b").where("a", P.neq("b")).values("name") }],
g_VX1X_asXaX_outXcreatedX_inXcreatedX_asXbX_whereXasXbX_outXcreatedX_hasXname_rippleXX_valuesXage_nameX: [function({g, vid1}) { return g.V(vid1).as("a").out("created").in_("created").as("b").where(__.as("b").out("created").has("name", "ripple")).values("age", "name") }],
g_VX1X_asXaX_outXcreatedX_inXcreatedX_whereXeqXaXX_name: [function({g, vid1}) { return g.V(vid1).as("a").out("created").in_("created").where(P.eq("a")).values("name") }],
@@ -584,11 +588,15 @@ const gremlins = {
g_V_hasXname_markoX_asXaX_outEXcreatedX_asXbX_inV_addEXselectXbX_labelX_toXaX: [function({g, v1}) { return g.addV("person").property("name", "marko").property("age", 29).as("marko").addV("person").property("name", "vadas").property("age", 27).as("vadas").addV("software").property("name", "lop").property("lang", "java").as("lop").addV("person").property("name", "josh").property("age", 32).as("josh").addV("software").property("name", "ripple").property("lang", "java").as("ripple").addV [...]
g_addEXV_outE_label_groupCount_orderXlocalX_byXvalues_descX_selectXkeysX_unfold_limitX1XX_fromXV_hasXname_vadasXX_toXV_hasXname_lopXX: [function({g, v2}) { return g.addV("person").property("name", "marko").property("age", 29).as("marko").addV("person").property("name", "vadas").property("age", 27).as("vadas").addV("software").property("name", "lop").property("lang", "java").as("lop").addV("person").property("name", "josh").property("age", 32).as("josh").addV("software").property("nam [...]
g_addEXknowsX_fromXaX_toXbX_propertyXweight_0_1X: [function({g, v6, xx1, v1}) { return g.addV("person").property("name", "marko").property("age", 29).as("marko").addV("person").property("name", "vadas").property("age", 27).as("vadas").addV("software").property("name", "lop").property("lang", "java").as("lop").addV("person").property("name", "josh").property("age", 32).as("josh").addV("software").property("name", "ripple").property("lang", "java").as("ripple").addV("person").property( [...]
+ g_addEXknowsvarX_fromXaX_toXbX_propertyXweight_0_1X: [function({g, xx1, v6, xx2, v1}) { return g.addV("person").property("name", "marko").property("age", 29).as("marko").addV("person").property("name", "vadas").property("age", 27).as("vadas").addV("software").property("name", "lop").property("lang", "java").as("lop").addV("person").property("name", "josh").property("age", 32).as("josh").addV("software").property("name", "ripple").property("lang", "java").as("ripple").addV("person").p [...]
g_VXaX_addEXknowsX_toXbX_propertyXweight_0_1X: [function({g, v6, xx1, v1}) { return g.addV("person").property("name", "marko").property("age", 29).as("marko").addV("person").property("name", "vadas").property("age", 27).as("vadas").addV("software").property("name", "lop").property("lang", "java").as("lop").addV("person").property("name", "josh").property("age", 32).as("josh").addV("software").property("name", "ripple").property("lang", "java").as("ripple").addV("person").property("na [...]
g_addEXknowsXpropertyXweight_nullXfromXV_hasXname_markoXX_toXV_hasXname_vadasXX: [function({g}) { return g.addV("person").property("name", "marko").property("age", 29).addV("person").property("name", "vadas").property("age", 27) }, function({g}) { return g.addE("knows").property("weight", null).from_(__.V().has("name", "marko")).to(__.V().has("name", "vadas")) }, function({g}) { return g.E().has("knows", "weight", null) }],
+ g_addEXknowsvarXpropertyXweight_nullXfromXV_hasXname_markoXX_toXV_hasXname_vadasXX: [function({g, xx1}) { return g.addV("person").property("name", "marko").property("age", 29).addV("person").property("name", "vadas").property("age", 27) }, function({g, xx1}) { return g.addE(xx1).property("weight", null).from_(__.V().has("name", "marko")).to(__.V().has("name", "vadas")) }, function({g, xx1}) { return g.E().has("knows", "weight", null) }],
g_VX1X_addVXanimalX_propertyXage_selectXaX_byXageXX_propertyXname_puppyX: [function({g, vid1}) { return g.addV("person").property("name", "marko").property("age", 29).as("marko").addV("person").property("name", "vadas").property("age", 27).as("vadas").addV("software").property("name", "lop").property("lang", "java").as("lop").addV("person").property("name", "josh").property("age", 32).as("josh").addV("software").property("name", "ripple").property("lang", "java").as("ripple").addV("p [...]
g_V_addVXanimalX_propertyXage_0X: [function({g}) { return g.addV("person").property("name", "marko").property("age", 29).as("marko").addV("person").property("name", "vadas").property("age", 27).as("vadas").addV("software").property("name", "lop").property("lang", "java").as("lop").addV("person").property("name", "josh").property("age", 32).as("josh").addV("software").property("name", "ripple").property("lang", "java").as("ripple").addV("person").property("name", "peter").property("ag [...]
+ g_V_addVXanimalvarX_propertyXage_0varX: [function({g, xx1, xx2}) { return g.addV("person").property("name", "marko").property("age", 29).as("marko").addV("person").property("name", "vadas").property("age", 27).as("vadas").addV("software").property("name", "lop").property("lang", "java").as("lop").addV("person").property("name", "josh").property("age", 32).as("josh").addV("software").property("name", "ripple").property("lang", "java").as("ripple").addV("person").property("name", "pete [...]
g_addVXpersonX_propertyXname_stephenX: [function({g}) { return g.addV("person").property("name", "marko").property("age", 29).as("marko").addV("person").property("name", "vadas").property("age", 27).as("vadas").addV("software").property("name", "lop").property("lang", "java").as("lop").addV("person").property("name", "josh").property("age", 32).as("josh").addV("software").property("name", "ripple").property("lang", "java").as("ripple").addV("person").property("name", "peter").propert [...]
+ g_addVXpersonvarX_propertyXname_stephenvarX: [function({g, xx1, xx2}) { return g.addV("person").property("name", "marko").property("age", 29).as("marko").addV("person").property("name", "vadas").property("age", 27).as("vadas").addV("software").property("name", "lop").property("lang", "java").as("lop").addV("person").property("name", "josh").property("age", 32).as("josh").addV("software").property("name", "ripple").property("lang", "java").as("ripple").addV("person").property("name", [...]
g_V_hasLabelXpersonX_propertyXname_nullX: [function({g}) { return g.addV("person").property("name", "marko").property("age", 29).as("marko").addV("person").property("name", "vadas").property("age", 27).as("vadas").addV("software").property("name", "lop").property("lang", "java").as("lop").addV("person").property("name", "josh").property("age", 32).as("josh").addV("software").property("name", "ripple").property("lang", "java").as("ripple").addV("person").property("name", "peter").prop [...]
g_addVXpersonX_propertyXsingle_name_stephenX_propertyXsingle_name_stephenmX: [function({g}) { return g.addV("person").property("name", "marko").property("age", 29).as("marko").addV("person").property("name", "vadas").property("age", 27).as("vadas").addV("software").property("name", "lop").property("lang", "java").as("lop").addV("person").property("name", "josh").property("age", 32).as("josh").addV("software").property("name", "ripple").property("lang", "java").as("ripple").addV("pers [...]
get_g_addVXpersonX_propertyXsingle_name_stephenX_propertyXsingle_name_stephenm_since_2010X: [function({g}) { return g.addV("person").property("name", "marko").property("age", 29).as("marko").addV("person").property("name", "vadas").property("age", 27).as("vadas").addV("software").property("name", "lop").property("lang", "java").as("lop").addV("person").property("name", "josh").property("age", 32).as("josh").addV("software").property("name", "ripple").property("lang", "java").as("ripp [...]
@@ -602,6 +610,9 @@ const gremlins = {
g_V_asXaX_hasXname_markoX_outXcreatedX_asXbX_addVXselectXaX_labelX_propertyXtest_selectXbX_labelX_valueMap_withXtokensX: [function({g}) { return g.addV("person").property("name", "marko").property("age", 29).as("marko").addV("person").property("name", "vadas").property("age", 27).as("vadas").addV("software").property("name", "lop").property("lang", "java").as("lop").addV("person").property("name", "josh").property("age", 32).as("josh").addV("software").property("name", "ripple").prop [...]
g_addVXV_hasXname_markoX_propertiesXnameX_keyX_label: [function({g}) { return g.addV("person").property("name", "marko").property("age", 29).as("marko").addV("person").property("name", "vadas").property("age", 27).as("vadas").addV("software").property("name", "lop").property("lang", "java").as("lop").addV("person").property("name", "josh").property("age", 32).as("josh").addV("software").property("name", "ripple").property("lang", "java").as("ripple").addV("person").property("name", " [...]
g_addV_propertyXlabel_personX: [function({g}) { return g.addV().property(T.label, "person") }, function({g}) { return g.V().hasLabel("person") }],
+ g_addV_propertyXlabel_personvarX: [function({g, xx1}) { return g.addV().property(T.label, xx1) }, function({g, xx1}) { return g.V().hasLabel("person") }],
+ g_addV_propertyXid_1X: [function({g}) { return g.addV().property(T.id, 1) }, function({g}) { return g.V().hasId("1") }],
+ g_addV_propertyXidvar_1varX: [function({g, xx1}) { return g.addV().property(T.id, xx1) }, function({g, xx1}) { return g.V().hasId("1") }],
g_addV_propertyXmapX: [function({g}) { return g.addV().property(new Map([["name", "foo"], ["age", 42]])) }, function({g}) { return g.V().has("name", "foo") }],
g_addV_propertyXsingle_mapX: [function({g}) { return g.addV().property(Cardinality.single, new Map([["name", "foo"], ["age", 42]])) }, function({g}) { return g.V().has("name", "foo") }],
g_V_hasXname_fooX_propertyXname_setXbarX_age_43X: [function({g}) { return g.addV().property(Cardinality.single, "name", "foo").property("age", 42) }, function({g}) { return g.V().has("name", "foo").property(new Map([["name", CardinalityValue.set("bar")], ["age", 43]])) }, function({g}) { return g.V().has("name", "foo") }, function({g}) { return g.V().has("name", "bar") }, function({g}) { return g.V().has("age", 43) }, function({g}) { return g.V().has("age", 42) }],
@@ -983,9 +994,11 @@ const gremlins = {
g_V_mergeEXlabel_selfX_optionXonMatch_emptyX: [function({g, xx1}) { return g.addV("person").property("name", "marko").property("age", 29).addE("self") }, function({g, xx1}) { return g.V().mergeE(xx1).option(Merge.onMatch, new Map([])) }, function({g, xx1}) { return g.E() }, function({g, xx1}) { return g.E().properties() }, function({g, xx1}) { return g.V() }],
g_V_mergeEXlabel_selfX_optionXonMatch_nullX: [function({g, xx1}) { return g.addV("person").property("name", "marko").property("age", 29).addE("self") }, function({g, xx1}) { return g.V().mergeE(xx1).option(Merge.onMatch, null) }, function({g, xx1}) { return g.E() }, function({g, xx1}) { return g.E().properties() }, function({g, xx1}) { return g.V() }],
g_V_mergeEXemptyX_optionXonCreate_nullX: [function({g, xx1}) { return g.addV("person").property("name", "marko").property("age", 29) }, function({g, xx1}) { return g.V().as("v").mergeE(xx1).option(Merge.onCreate, null).option(Merge.outV, __.select("v")).option(Merge.inV, __.select("v")) }, function({g, xx1}) { return g.E() }, function({g, xx1}) { return g.V() }],
+ g_V_mergeE_inlineXemptyX_optionXonCreate_nullX: [function({g}) { return g.addV("person").property("name", "marko").property("age", 29) }, function({g}) { return g.V().as("v").mergeE(new Map([[T.label, "self"], [Direction.OUT, Merge.outV], [Direction.IN, Merge.inV]])).option(Merge.onCreate, null).option(Merge.outV, __.select("v")).option(Merge.inV, __.select("v")) }, function({g}) { return g.E() }, function({g}) { return g.V() }],
g_mergeEXemptyX_exists: [function({g}) { return g.addV("person").property("name", "marko").property("age", 29).addE("self") }, function({g}) { return g.mergeE(new Map([])) }, function({g}) { return g.E() }, function({g}) { return g.V() }],
g_mergeEXemptyX: [function({g}) { return g.addV("person").property("name", "marko").property("age", 29) }, function({g}) { return g.mergeE(new Map([])) }],
g_V_mergeEXemptyX_two_exist: [function({g, xx1}) { return g.addV("person").property("name", "marko").property("age", 29).addV("person").property("name", "vadas").property("age", 27) }, function({g, xx1}) { return g.V().as("v").mergeE(xx1).option(Merge.outV, __.select("v")).option(Merge.inV, __.select("v")) }, function({g, xx1}) { return g.E() }, function({g, xx1}) { return g.V() }],
+ g_V_mergeE_inlineXemptyX_two_exist: [function({g}) { return g.addV("person").property("name", "marko").property("age", 29).addV("person").property("name", "vadas").property("age", 27) }, function({g}) { return g.V().as("v").mergeE(new Map([[T.label, "self"], [Direction.OUT, Merge.outV], [Direction.IN, Merge.inV]])).option(Merge.outV, __.select("v")).option(Merge.inV, __.select("v")) }, function({g}) { return g.E() }, function({g}) { return g.V() }],
g_mergeEXnullX: [function({g}) { return g.addV("person").property("name", "marko").property("age", 29) }, function({g}) { return g.mergeE(null) }],
g_V_mergeEXnullX: [function({g}) { return g.addV("person").property("name", "marko").property("age", 29) }, function({g}) { return g.V().mergeE(null) }],
g_mergeEXlabel_knows_out_marko_in_vadasX: [function({g, xx1}) { return g.addV("person").property("name", "marko").addV("person").property("name", "vadas") }, function({g, xx1}) { return g.mergeE(xx1) }, function({g, xx1}) { return g.V().has("person", "name", "marko").out("knows").has("person", "name", "vadas") }],
@@ -1009,7 +1022,9 @@ const gremlins = {
g_injectXlabel_knows_out_marko_in_vadas_label_self_out_vadas_in_vadasX: [function({g, xx1, xx2}) { return g.addV("person").property("name", "marko").addV("person").property("name", "vadas") }, function({g, xx1, xx2}) { return g.inject(xx1, xx2).mergeE() }, function({g, xx1, xx2}) { return g.V() }, function({g, xx1, xx2}) { return g.E() }, function({g, xx1, xx2}) { return g.V().has("person", "name", "marko").out("knows").has("person", "name", "vadas") }, function({g, xx1, xx2}) { retu [...]
g_withSideEffectXc_created_YX_withSideEffectXm_matchedX_mergeEXlabel_knows_out_marko_in_vadasX_optionXonCreate_selectXcXX_optionXonMatch_sideEffectXpropertiesXweightX_dropX_selectXmXX_exists: [function({g, xx1, xx3, xx2}) { return g.addV("person").property("name", "marko").as("a").addV("person").property("name", "vadas").as("b").addE("knows").property("weight", 1.0).from_("a").to("b") }, function({g, xx1, xx3, xx2}) { return g.withSideEffect("c", xx2).withSideEffect("m", xx3).mergeE( [...]
g_mergeE_with_outVinV_options_map: [function({g, xx1, xx3, xx2}) { return g.addV("person").property("name", "marko").addV("person").property("name", "vadas") }, function({g, xx1, xx3, xx2}) { return g.mergeE(xx1).option(Merge.outV, xx2).option(Merge.inV, xx3) }, function({g, xx1, xx3, xx2}) { return g.V() }, function({g, xx1, xx3, xx2}) { return g.V().has("name", "marko").out("knows").has("name", "vadas") }],
+ g_mergeE_inline_with_outVinV_options_map: [function({g, xx1, xx2}) { return g.addV("person").property("name", "marko").addV("person").property("name", "vadas") }, function({g, xx1, xx2}) { return g.mergeE(new Map([[Direction.OUT, Merge.outV], [Direction.IN, Merge.inV], [T.label, "knows"]])).option(Merge.outV, xx1).option(Merge.inV, xx2) }, function({g, xx1, xx2}) { return g.V() }, function({g, xx1, xx2}) { return g.V().has("name", "marko").out("knows").has("name", "vadas") }],
g_mergeE_with_outVinV_options_select: [function({g, xx1, vid2, vid1}) { return g.addV("person").property("name", "marko").addV("person").property("name", "vadas") }, function({g, xx1, vid2, vid1}) { return g.V(vid1).as("x").V(vid2).as("y").mergeE(xx1).option(Merge.outV, __.select("x")).option(Merge.inV, __.select("y")) }, function({g, xx1, vid2, vid1}) { return g.V() }, function({g, xx1, vid2, vid1}) { return g.V().has("name", "marko").out("knows").has("name", "vadas") }],
+ g_mergeE_inline_with_outVinV_options_select: [function({g, vid2, vid1}) { return g.addV("person").property("name", "marko").addV("person").property("name", "vadas") }, function({g, vid2, vid1}) { return g.V(vid1).as("x").V(vid2).as("y").mergeE(new Map([[Direction.OUT, Merge.outV], [Direction.IN, Merge.inV], [T.label, "knows"]])).option(Merge.outV, __.select("x")).option(Merge.inV, __.select("y")) }, function({g, vid2, vid1}) { return g.V() }, function({g, vid2, vid1}) { return g.V(). [...]
g_mergeE_with_eid_specified_and_inheritance_1: [function({g, xx1, xx2}) { return g.addV("person").property("name", "marko").addV("person").property("name", "vadas") }, function({g, xx1, xx2}) { return g.mergeE(xx1).option(Merge.onCreate, xx2) }, function({g, xx1, xx2}) { return g.V() }, function({g, xx1, xx2}) { return g.E() }, function({g, xx1, xx2}) { return g.E("201") }, function({g, xx1, xx2}) { return g.V().has("name", "marko").out("knows").has("name", "vadas") }],
g_mergeE_with_eid_specified_and_inheritance_2: [function({g, xx1, xx2}) { return g.addV("person").property("name", "marko").addV("person").property("name", "vadas") }, function({g, xx1, xx2}) { return g.mergeE(xx1).option(Merge.onCreate, xx2) }, function({g, xx1, xx2}) { return g.V() }, function({g, xx1, xx2}) { return g.E() }, function({g, xx1, xx2}) { return g.E("201") }, function({g, xx1, xx2}) { return g.V().has("name", "marko").out("knows").has("name", "vadas") }],
g_mergeE_outV_override_prohibited: [function({g, xx1, xx2}) { return g.addV("person").property("name", "marko").addV("person").property("name", "vadas") }, function({g, xx1, xx2}) { return g.mergeE(xx1).option(Merge.onCreate, xx2) }],
@@ -1104,7 +1119,7 @@ const gremlins = {
g_VX1X_valuesXageX_minXlocalX: [function({g, vid1}) { return g.V(vid1).values("age").min(Scope.local) }],
g_V_localXunionXvaluesXageX_outE_valuesXweightXX_foldX_minXlocalX: [function({g}) { return g.V().local(__.union(__.values("age"), __.outE().values("weight")).fold()).min(Scope.local) }],
g_V_name_order: [function({g}) { return g.V().values("name").order() }],
- g_V_name_order_byXa1_b1X_byXb2_a2X: [function({g, c1, c2}) { return g.V().values("name").order().by(c1).by(c2) }],
+ 'g_V_name_order_byXa1_b1X_byXb2_a2X': [], // skipping as it contains a lambda
g_V_order_byXname_ascX_name: [function({g}) { return g.V().order().by("name", Order.asc).values("name") }],
g_V_order_byXnameX_name: [function({g}) { return g.V().order().by("name").values("name") }],
g_V_outE_order_byXweight_descX_weight: [function({g}) { return g.V().outE().order().by("weight", Order.desc).values("weight") }],
@@ -1393,12 +1408,14 @@ const gremlins = {
g_VX1X_outE: [function({g, vid1}) { return g.V(vid1).outE() }],
g_VX2X_outE: [function({g, vid2}) { return g.V(vid2).inE() }],
g_VX4X_bothEXcreatedX: [function({g, vid4}) { return g.V(vid4).bothE("created") }],
+ g_VX4X_bothEXcreatedvarX: [function({g, xx1, vid4}) { return g.V(vid4).bothE(xx1) }],
g_VX4X_bothE: [function({g, vid4}) { return g.V(vid4).bothE() }],
g_V_out_outE_inV_inE_inV_both_name: [function({g}) { return g.V().out().outE().inV().inE().inV().both().values("name") }],
g_VX2X_inE: [function({g, vid2}) { return g.V(vid2).bothE() }],
g_VX1X_outXknowsX: [function({g, vid1}) { return g.V(vid1).out("knows") }],
g_VX1AsStringX_outXknowsX: [function({g, vid1}) { return g.V(vid1).out("knows") }],
g_VX1X_outXknows_createdX: [function({g, vid1}) { return g.V(vid1).out("knows", "created") }],
+ g_VX1X_outXknowsvar_createdvarX: [function({g, xx3, xx2, vid1}) { return g.V(vid1).out(xx2, xx3) }],
g_V_out_out: [function({g}) { return g.V().out().out() }],
g_VX1X_out_out_out: [function({g, vid1}) { return g.V(vid1).out().out().out() }],
g_VX1X_out_name: [function({g, vid1}) { return g.V(vid1).out().values("name") }],
@@ -1614,9 +1631,14 @@ const gremlins = {
g_VX1X_valuesXageX_inject: [function({g, xx1}) { return g.V(xx1).values("age").inject() }],
g_injectXnull_1_3_nullX_asXaX_selectXaX: [function({g}) { return g.inject(null, 1, 3, null).as("a").select("a") }],
g_injectX1_3X_injectX100_300X: [function({g}) { return g.inject(1, 3).inject(100, 300) }],
+ g_injectX1var_3varX_injectX100var_300varX: [function({g, xx1, xx3, xx2, xx4}) { return g.inject(xx1, xx2).inject(xx3, xx4) }],
g_injectX1_3_100_300X_list: [function({g}) { return g.inject([1, 3, 100, 300]) }],
+ g_injectX1_3_100_300X_listvar: [function({g, xx1}) { return g.inject(xx1) }],
g_injectX1_3_100_300X_set: [function({g}) { return g.inject(new Set([1, 3, 100, 300])) }],
+ g_injectX1_3_100_300X_setvar: [function({g, xx1}) { return g.inject(xx1) }],
g_injectX1_1X_set: [function({g}) { return g.inject(new Set([1, 1])) }],
+ g_injectX1_1X_setvar: [function({g, xx1}) { return g.inject(xx1) }],
+ g_injectX_set: [function({g, xx1}) { return g.inject(xx1) }],
g_io_readXkryoX: [function({g}) { return g.io("data/tinkerpop-modern.kryo").read() }, function({g}) { return g.V() }, function({g}) { return g.E() }],
g_io_read_withXreader_gryoX: [function({g}) { return g.io("data/tinkerpop-modern.kryo").with_(IO.reader, IO.gryo).read() }, function({g}) { return g.V() }, function({g}) { return g.E() }],
g_io_readXgraphsonX: [function({g}) { return g.io("data/tinkerpop-modern.json").read() }, function({g}) { return g.V() }, function({g}) { return g.E() }],
diff --git a/gremlin-language/src/main/antlr4/Gremlin.g4 b/gremlin-language/src/main/antlr4/Gremlin.g4
index 6394c55568..fcf0d3f0da 100644
--- a/gremlin-language/src/main/antlr4/Gremlin.g4
+++ b/gremlin-language/src/main/antlr4/Gremlin.g4
@@ -81,8 +81,8 @@ traversalSourceSelfMethod_withSack
;
traversalSourceSelfMethod_withSideEffect
- : 'withSideEffect' LPAREN stringArgument COMMA genericLiteralArgument RPAREN
- | 'withSideEffect' LPAREN stringArgument COMMA genericLiteralArgument COMMA traversalBiFunction RPAREN
+ : 'withSideEffect' LPAREN stringLiteral COMMA genericLiteralArgument RPAREN
+ | 'withSideEffect' LPAREN stringLiteral COMMA genericLiteralArgument COMMA traversalBiFunction RPAREN
;
traversalSourceSelfMethod_withStrategies
@@ -94,8 +94,8 @@ traversalSourceSelfMethod_withoutStrategies
;
traversalSourceSelfMethod_with
- : 'with' LPAREN stringArgument RPAREN
- | 'with' LPAREN stringArgument COMMA genericLiteralArgument RPAREN
+ : 'with' LPAREN stringLiteral RPAREN
+ | 'with' LPAREN stringLiteral COMMA genericLiteralArgument RPAREN
;
traversalSourceSpawnMethod
@@ -135,7 +135,7 @@ traversalSourceSpawnMethod_inject
;
traversalSourceSpawnMethod_io
- : 'io' LPAREN stringArgument RPAREN
+ : 'io' LPAREN stringLiteral RPAREN
;
traversalSourceSpawnMethod_mergeV
@@ -150,10 +150,10 @@ traversalSourceSpawnMethod_mergeE
traversalSourceSpawnMethod_call
: 'call' LPAREN RPAREN #traversalSourceSpawnMethod_call_empty
- | 'call' LPAREN stringArgument RPAREN #traversalSourceSpawnMethod_call_string
- | 'call' LPAREN stringArgument COMMA genericLiteralMapArgument RPAREN #traversalSourceSpawnMethod_call_string_map
- | 'call' LPAREN stringArgument COMMA nestedTraversal RPAREN #traversalSourceSpawnMethod_call_string_traversal
- | 'call' LPAREN stringArgument COMMA genericLiteralMapArgument COMMA nestedTraversal RPAREN #traversalSourceSpawnMethod_call_string_map_traversal
+ | 'call' LPAREN stringLiteral RPAREN #traversalSourceSpawnMethod_call_string
+ | 'call' LPAREN stringLiteral COMMA genericLiteralMapArgument RPAREN #traversalSourceSpawnMethod_call_string_map
+ | 'call' LPAREN stringLiteral COMMA nestedTraversal RPAREN #traversalSourceSpawnMethod_call_string_traversal
+ | 'call' LPAREN stringLiteral COMMA genericLiteralMapArgument COMMA nestedTraversal RPAREN #traversalSourceSpawnMethod_call_string_map_traversal
;
traversalSourceSpawnMethod_union
@@ -348,8 +348,8 @@ traversalMethod_mergeE
;
traversalMethod_aggregate
- : 'aggregate' LPAREN traversalScope COMMA stringArgument RPAREN #traversalMethod_aggregate_Scope_String
- | 'aggregate' LPAREN stringArgument RPAREN #traversalMethod_aggregate_String
+ : 'aggregate' LPAREN traversalScope COMMA stringLiteral RPAREN #traversalMethod_aggregate_Scope_String
+ | 'aggregate' LPAREN stringLiteral RPAREN #traversalMethod_aggregate_String
;
traversalMethod_all
@@ -365,13 +365,13 @@ traversalMethod_any
;
traversalMethod_as
- : 'as' LPAREN stringArgument (COMMA stringLiteralVarargs)? RPAREN
+ : 'as' LPAREN stringLiteral (COMMA stringLiteralVarargsLiterals)? RPAREN
;
traversalMethod_barrier
: 'barrier' LPAREN traversalSackMethod RPAREN #traversalMethod_barrier_Consumer
| 'barrier' LPAREN RPAREN #traversalMethod_barrier_Empty
- | 'barrier' LPAREN integerArgument RPAREN #traversalMethod_barrier_int
+ | 'barrier' LPAREN integerLiteral RPAREN #traversalMethod_barrier_int
;
traversalMethod_both
@@ -396,15 +396,15 @@ traversalMethod_by
| 'by' LPAREN traversalFunction RPAREN #traversalMethod_by_Function
| 'by' LPAREN traversalFunction COMMA traversalComparator RPAREN #traversalMethod_by_Function_Comparator
| 'by' LPAREN traversalOrder RPAREN #traversalMethod_by_Order
- | 'by' LPAREN stringArgument RPAREN #traversalMethod_by_String
- | 'by' LPAREN stringArgument COMMA traversalComparator RPAREN #traversalMethod_by_String_Comparator
+ | 'by' LPAREN stringLiteral RPAREN #traversalMethod_by_String
+ | 'by' LPAREN stringLiteral COMMA traversalComparator RPAREN #traversalMethod_by_String_Comparator
| 'by' LPAREN traversalToken RPAREN #traversalMethod_by_T
| 'by' LPAREN nestedTraversal RPAREN #traversalMethod_by_Traversal
| 'by' LPAREN nestedTraversal COMMA traversalComparator RPAREN #traversalMethod_by_Traversal_Comparator
;
traversalMethod_cap
- : 'cap' LPAREN stringArgument (COMMA stringLiteralVarargs)? RPAREN
+ : 'cap' LPAREN stringLiteral (COMMA stringLiteralVarargsLiterals)? RPAREN
;
traversalMethod_choose
@@ -446,8 +446,8 @@ traversalMethod_cyclicPath
;
traversalMethod_dedup
- : 'dedup' LPAREN traversalScope (COMMA stringLiteralVarargs)? RPAREN #traversalMethod_dedup_Scope_String
- | 'dedup' LPAREN stringLiteralVarargs RPAREN #traversalMethod_dedup_String
+ : 'dedup' LPAREN traversalScope (COMMA stringLiteralVarargsLiterals)? RPAREN #traversalMethod_dedup_Scope_String
+ | 'dedup' LPAREN stringLiteralVarargsLiterals RPAREN #traversalMethod_dedup_String
;
traversalMethod_difference
@@ -463,7 +463,7 @@ traversalMethod_drop
;
traversalMethod_elementMap
- : 'elementMap' LPAREN stringLiteralVarargs RPAREN
+ : 'elementMap' LPAREN stringLiteralVarargsLiterals RPAREN
;
traversalMethod_emit
@@ -494,21 +494,21 @@ traversalMethod_from
traversalMethod_group
: 'group' LPAREN RPAREN #traversalMethod_group_Empty
- | 'group' LPAREN stringArgument RPAREN #traversalMethod_group_String
+ | 'group' LPAREN stringLiteral RPAREN #traversalMethod_group_String
;
traversalMethod_groupCount
: 'groupCount' LPAREN RPAREN #traversalMethod_groupCount_Empty
- | 'groupCount' LPAREN stringArgument RPAREN #traversalMethod_groupCount_String
+ | 'groupCount' LPAREN stringLiteral RPAREN #traversalMethod_groupCount_String
;
traversalMethod_has
- : 'has' LPAREN stringNullableArgument RPAREN #traversalMethod_has_String
- | 'has' LPAREN stringNullableArgument COMMA genericLiteralArgument RPAREN #traversalMethod_has_String_Object
- | 'has' LPAREN stringNullableArgument COMMA traversalPredicate RPAREN #traversalMethod_has_String_P
- | 'has' LPAREN stringNullableArgument COMMA stringNullableArgument COMMA genericLiteralArgument RPAREN #traversalMethod_has_String_String_Object
- | 'has' LPAREN stringNullableArgument COMMA stringNullableArgument COMMA traversalPredicate RPAREN #traversalMethod_has_String_String_P
- | 'has' LPAREN stringNullableArgument COMMA nestedTraversal RPAREN #traversalMethod_has_String_Traversal
+ : 'has' LPAREN stringNullableLiteral RPAREN #traversalMethod_has_String
+ | 'has' LPAREN stringNullableLiteral COMMA genericLiteralArgument RPAREN #traversalMethod_has_String_Object
+ | 'has' LPAREN stringNullableLiteral COMMA traversalPredicate RPAREN #traversalMethod_has_String_P
+ | 'has' LPAREN stringNullableArgument COMMA stringNullableLiteral COMMA genericLiteralArgument RPAREN #traversalMethod_has_String_String_Object
+ | 'has' LPAREN stringNullableArgument COMMA stringNullableLiteral COMMA traversalPredicate RPAREN #traversalMethod_has_String_String_P
+ | 'has' LPAREN stringNullableLiteral COMMA nestedTraversal RPAREN #traversalMethod_has_String_Traversal
| 'has' LPAREN traversalToken COMMA genericLiteralArgument RPAREN #traversalMethod_has_T_Object
| 'has' LPAREN traversalToken COMMA traversalPredicate RPAREN #traversalMethod_has_T_P
| 'has' LPAREN traversalToken COMMA nestedTraversal RPAREN #traversalMethod_has_T_Traversal
@@ -521,7 +521,7 @@ traversalMethod_hasId
traversalMethod_hasKey
: 'hasKey' LPAREN traversalPredicate RPAREN #traversalMethod_hasKey_P
- | 'hasKey' LPAREN stringNullableArgument (COMMA stringLiteralVarargs)? RPAREN #traversalMethod_hasKey_String_String
+ | 'hasKey' LPAREN stringNullableLiteral (COMMA stringLiteralVarargsLiterals)? RPAREN #traversalMethod_hasKey_String_String
;
traversalMethod_hasLabel
@@ -530,7 +530,7 @@ traversalMethod_hasLabel
;
traversalMethod_hasNot
- : 'hasNot' LPAREN stringNullableArgument RPAREN
+ : 'hasNot' LPAREN stringNullableLiteral RPAREN
;
traversalMethod_hasValue
@@ -588,8 +588,8 @@ traversalMethod_label
;
traversalMethod_limit
- : 'limit' LPAREN traversalScope COMMA integerArgument RPAREN #traversalMethod_limit_Scope_long
- | 'limit' LPAREN integerArgument RPAREN #traversalMethod_limit_long
+ : 'limit' LPAREN traversalScope COMMA integerLiteral RPAREN #traversalMethod_limit_Scope_long
+ | 'limit' LPAREN integerLiteral RPAREN #traversalMethod_limit_long
;
traversalMethod_local
@@ -598,7 +598,7 @@ traversalMethod_local
traversalMethod_loops
: 'loops' LPAREN RPAREN #traversalMethod_loops_Empty
- | 'loops' LPAREN stringArgument RPAREN #traversalMethod_loops_String
+ | 'loops' LPAREN stringLiteral RPAREN #traversalMethod_loops_String
;
traversalMethod_map
@@ -610,7 +610,7 @@ traversalMethod_match
;
traversalMethod_math
- : 'math' LPAREN stringArgument RPAREN
+ : 'math' LPAREN stringLiteral RPAREN
;
traversalMethod_max
@@ -697,15 +697,15 @@ traversalMethod_product
traversalMethod_profile
: 'profile' LPAREN RPAREN #traversalMethod_profile_Empty
- | 'profile' LPAREN stringArgument RPAREN #traversalMethod_profile_String
+ | 'profile' LPAREN stringLiteral RPAREN #traversalMethod_profile_String
;
traversalMethod_project
- : 'project' LPAREN stringArgument (COMMA stringLiteralVarargs)? RPAREN
+ : 'project' LPAREN stringLiteral (COMMA stringLiteralVarargsLiterals)? RPAREN
;
traversalMethod_properties
- : 'properties' LPAREN stringLiteralVarargs RPAREN
+ : 'properties' LPAREN stringLiteralVarargsLiterals RPAREN
;
traversalMethod_property
@@ -716,12 +716,12 @@ traversalMethod_property
;
traversalMethod_propertyMap
- : 'propertyMap' LPAREN stringLiteralVarargs RPAREN
+ : 'propertyMap' LPAREN stringLiteralVarargsLiterals RPAREN
;
traversalMethod_range
- : 'range' LPAREN traversalScope COMMA integerArgument COMMA integerArgument RPAREN #traversalMethod_range_Scope_long_long
- | 'range' LPAREN integerArgument COMMA integerArgument RPAREN #traversalMethod_range_long_long
+ : 'range' LPAREN traversalScope COMMA integerLiteral COMMA integerLiteral RPAREN #traversalMethod_range_Scope_long_long
+ | 'range' LPAREN integerLiteral COMMA integerLiteral RPAREN #traversalMethod_range_long_long
;
traversalMethod_read
@@ -729,7 +729,7 @@ traversalMethod_read
;
traversalMethod_repeat
- : 'repeat' LPAREN stringArgument COMMA nestedTraversal RPAREN #traversalMethod_repeat_String_Traversal
+ : 'repeat' LPAREN stringLiteral COMMA nestedTraversal RPAREN #traversalMethod_repeat_String_Traversal
| 'repeat' LPAREN nestedTraversal RPAREN #traversalMethod_repeat_Traversal
;
@@ -743,17 +743,17 @@ traversalMethod_sack
;
traversalMethod_sample
- : 'sample' LPAREN traversalScope COMMA integerArgument RPAREN #traversalMethod_sample_Scope_int
- | 'sample' LPAREN integerArgument RPAREN #traversalMethod_sample_int
+ : 'sample' LPAREN traversalScope COMMA integerLiteral RPAREN #traversalMethod_sample_Scope_int
+ | 'sample' LPAREN integerLiteral RPAREN #traversalMethod_sample_int
;
traversalMethod_select
: 'select' LPAREN traversalColumn RPAREN #traversalMethod_select_Column
- | 'select' LPAREN traversalPop COMMA stringArgument RPAREN #traversalMethod_select_Pop_String
- | 'select' LPAREN traversalPop COMMA stringArgument COMMA stringArgument (COMMA stringLiteralVarargs)? RPAREN #traversalMethod_select_Pop_String_String_String
+ | 'select' LPAREN traversalPop COMMA stringLiteral RPAREN #traversalMethod_select_Pop_String
+ | 'select' LPAREN traversalPop COMMA stringLiteral COMMA stringLiteral (COMMA stringLiteralVarargsLiterals)? RPAREN #traversalMethod_select_Pop_String_String_String
| 'select' LPAREN traversalPop COMMA nestedTraversal RPAREN #traversalMethod_select_Pop_Traversal
- | 'select' LPAREN stringArgument RPAREN #traversalMethod_select_String
- | 'select' LPAREN stringArgument COMMA stringArgument (COMMA stringLiteralVarargs)? RPAREN #traversalMethod_select_String_String_String
+ | 'select' LPAREN stringLiteral RPAREN #traversalMethod_select_String
+ | 'select' LPAREN stringLiteral COMMA stringLiteral (COMMA stringLiteralVarargsLiterals)? RPAREN #traversalMethod_select_String_String_String
| 'select' LPAREN nestedTraversal RPAREN #traversalMethod_select_Traversal
;
@@ -770,16 +770,16 @@ traversalMethod_simplePath
;
traversalMethod_skip
- : 'skip' LPAREN traversalScope COMMA integerArgument RPAREN #traversalMethod_skip_Scope_long
- | 'skip' LPAREN integerArgument RPAREN #traversalMethod_skip_long
+ : 'skip' LPAREN traversalScope COMMA integerLiteral RPAREN #traversalMethod_skip_Scope_long
+ | 'skip' LPAREN integerLiteral RPAREN #traversalMethod_skip_long
;
traversalMethod_store
- : 'store' LPAREN stringArgument RPAREN
+ : 'store' LPAREN stringLiteral RPAREN
;
traversalMethod_subgraph
- : 'subgraph' LPAREN stringArgument RPAREN
+ : 'subgraph' LPAREN stringLiteral RPAREN
;
traversalMethod_sum
@@ -790,21 +790,21 @@ traversalMethod_sum
traversalMethod_tail
: 'tail' LPAREN RPAREN #traversalMethod_tail_Empty
| 'tail' LPAREN traversalScope RPAREN #traversalMethod_tail_Scope
- | 'tail' LPAREN traversalScope COMMA integerArgument RPAREN #traversalMethod_tail_Scope_long
- | 'tail' LPAREN integerArgument RPAREN #traversalMethod_tail_long
+ | 'tail' LPAREN traversalScope COMMA integerLiteral RPAREN #traversalMethod_tail_Scope_long
+ | 'tail' LPAREN integerLiteral RPAREN #traversalMethod_tail_long
;
traversalMethod_fail
: 'fail' LPAREN RPAREN #traversalMethod_fail_Empty
- | 'fail' LPAREN stringArgument RPAREN #traversalMethod_fail_String
+ | 'fail' LPAREN stringLiteral RPAREN #traversalMethod_fail_String
;
traversalMethod_timeLimit
- : 'timeLimit' LPAREN integerArgument RPAREN
+ : 'timeLimit' LPAREN integerLiteral RPAREN
;
traversalMethod_times
- : 'times' LPAREN integerArgument RPAREN
+ : 'times' LPAREN integerLiteral RPAREN
;
traversalMethod_to
@@ -824,7 +824,7 @@ traversalMethod_toV
traversalMethod_tree
: 'tree' LPAREN RPAREN #traversalMethod_tree_Empty
- | 'tree' LPAREN stringArgument RPAREN #traversalMethod_tree_String
+ | 'tree' LPAREN stringLiteral RPAREN #traversalMethod_tree_String
;
traversalMethod_unfold
@@ -845,23 +845,23 @@ traversalMethod_value
;
traversalMethod_valueMap
- : 'valueMap' LPAREN stringLiteralVarargs RPAREN #traversalMethod_valueMap_String
- | 'valueMap' LPAREN booleanLiteral (COMMA stringLiteralVarargs)? RPAREN #traversalMethod_valueMap_boolean_String
+ : 'valueMap' LPAREN stringLiteralVarargsLiterals RPAREN #traversalMethod_valueMap_String
+ | 'valueMap' LPAREN booleanLiteral (COMMA stringLiteralVarargsLiterals)? RPAREN #traversalMethod_valueMap_boolean_String
;
traversalMethod_values
- : 'values' LPAREN stringLiteralVarargs RPAREN
+ : 'values' LPAREN stringLiteralVarargsLiterals RPAREN
;
traversalMethod_where
: 'where' LPAREN traversalPredicate RPAREN #traversalMethod_where_P
- | 'where' LPAREN stringArgument COMMA traversalPredicate RPAREN #traversalMethod_where_String_P
+ | 'where' LPAREN stringLiteral COMMA traversalPredicate RPAREN #traversalMethod_where_String_P
| 'where' LPAREN nestedTraversal RPAREN #traversalMethod_where_Traversal
;
traversalMethod_with
- : 'with' LPAREN (withOptionKeys | stringArgument) RPAREN #traversalMethod_with_String
- | 'with' LPAREN (withOptionKeys | stringArgument) COMMA (withOptionsValues | ioOptionsValues | genericLiteralArgument) RPAREN #traversalMethod_with_String_Object
+ : 'with' LPAREN (withOptionKeys | stringLiteral) RPAREN #traversalMethod_with_String
+ | 'with' LPAREN (withOptionKeys | stringLiteral) COMMA (withOptionsValues | ioOptionsValues | genericLiteralArgument) RPAREN #traversalMethod_with_String_Object
;
traversalMethod_write
@@ -873,15 +873,15 @@ traversalMethod_element
;
traversalMethod_call
- : 'call' LPAREN stringArgument RPAREN #traversalMethod_call_string
- | 'call' LPAREN stringArgument COMMA genericLiteralMapArgument RPAREN #traversalMethod_call_string_map
- | 'call' LPAREN stringArgument COMMA nestedTraversal RPAREN #traversalMethod_call_string_traversal
- | 'call' LPAREN stringArgument COMMA genericLiteralMapArgument COMMA nestedTraversal RPAREN #traversalMethod_call_string_map_traversal
+ : 'call' LPAREN stringLiteral RPAREN #traversalMethod_call_string
+ | 'call' LPAREN stringLiteral COMMA genericLiteralMapArgument RPAREN #traversalMethod_call_string_map
+ | 'call' LPAREN stringLiteral COMMA nestedTraversal RPAREN #traversalMethod_call_string_traversal
+ | 'call' LPAREN stringLiteral COMMA genericLiteralMapArgument COMMA nestedTraversal RPAREN #traversalMethod_call_string_map_traversal
;
traversalMethod_concat
: 'concat' LPAREN nestedTraversal (COMMA nestedTraversalList)? RPAREN #traversalMethod_concat_Traversal_Traversal
- | 'concat' LPAREN stringLiteralVarargs RPAREN #traversalMethod_concat_String
+ | 'concat' LPAREN stringLiteralVarargsLiterals RPAREN #traversalMethod_concat_String
;
traversalMethod_asString
@@ -890,7 +890,7 @@ traversalMethod_asString
;
traversalMethod_format
- : 'format' LPAREN stringArgument RPAREN #traversalMethod_format_String
+ : 'format' LPAREN stringLiteral RPAREN #traversalMethod_format_String
;
traversalMethod_toUpper
@@ -924,20 +924,20 @@ traversalMethod_rTrim
;
traversalMethod_replace
- : 'replace' LPAREN stringNullableArgument COMMA stringNullableArgument RPAREN #traversalMethod_replace_String_String
- | 'replace' LPAREN traversalScope COMMA stringNullableArgument COMMA stringNullableArgument RPAREN #traversalMethod_replace_Scope_String_String
+ : 'replace' LPAREN stringNullableLiteral COMMA stringNullableLiteral RPAREN #traversalMethod_replace_String_String
+ | 'replace' LPAREN traversalScope COMMA stringNullableLiteral COMMA stringNullableLiteral RPAREN #traversalMethod_replace_Scope_String_String
;
traversalMethod_split
- : 'split' LPAREN stringNullableArgument RPAREN #traversalMethod_split_String
- | 'split' LPAREN traversalScope COMMA stringNullableArgument RPAREN #traversalMethod_split_Scope_String
+ : 'split' LPAREN stringNullableLiteral RPAREN #traversalMethod_split_String
+ | 'split' LPAREN traversalScope COMMA stringNullableLiteral RPAREN #traversalMethod_split_Scope_String
;
traversalMethod_substring
- : 'substring' LPAREN integerArgument RPAREN #traversalMethod_substring_int
- | 'substring' LPAREN traversalScope COMMA integerArgument RPAREN #traversalMethod_substring_Scope_int
- | 'substring' LPAREN integerArgument COMMA integerArgument RPAREN #traversalMethod_substring_int_int
- | 'substring' LPAREN traversalScope COMMA integerArgument COMMA integerArgument RPAREN #traversalMethod_substring_Scope_int_int
+ : 'substring' LPAREN integerLiteral RPAREN #traversalMethod_substring_int
+ | 'substring' LPAREN traversalScope COMMA integerLiteral RPAREN #traversalMethod_substring_Scope_int
+ | 'substring' LPAREN integerLiteral COMMA integerLiteral RPAREN #traversalMethod_substring_int_int
+ | 'substring' LPAREN traversalScope COMMA integerLiteral COMMA integerLiteral RPAREN #traversalMethod_substring_Scope_int_int
;
traversalMethod_asDate
@@ -945,12 +945,12 @@ traversalMethod_asDate
;
traversalMethod_dateAdd
- : 'dateAdd' LPAREN traversalDT COMMA integerArgument RPAREN
+ : 'dateAdd' LPAREN traversalDT COMMA integerLiteral RPAREN
;
traversalMethod_dateDiff
: 'dateDiff' LPAREN nestedTraversal RPAREN #traversalMethod_dateDiff_Traversal
- | 'dateDiff' LPAREN dateArgument RPAREN #traversalMethod_dateDiff_Date
+ | 'dateDiff' LPAREN dateLiteral RPAREN #traversalMethod_dateDiff_Date
;
/*********************************************
@@ -1551,6 +1551,10 @@ stringLiteralVarargs
: (stringNullableArgument (COMMA stringNullableArgument)*)?
;
+stringLiteralVarargsLiterals
+ : (stringNullableLiteral (COMMA stringNullableLiteral)*)?
+ ;
+
stringLiteralList
: stringLiteralExpr?
| LBRACK stringLiteralExpr? RBRACK
diff --git a/gremlin-language/src/test/java/org/apache/tinkerpop/gremlin/language/grammar/ReferenceGrammarTest.java b/gremlin-language/src/test/java/org/apache/tinkerpop/gremlin/language/grammar/ReferenceGrammarTest.java
index d74ac439ca..35afdeb768 100644
--- a/gremlin-language/src/test/java/org/apache/tinkerpop/gremlin/language/grammar/ReferenceGrammarTest.java
+++ b/gremlin-language/src/test/java/org/apache/tinkerpop/gremlin/language/grammar/ReferenceGrammarTest.java
@@ -69,6 +69,12 @@ public class ReferenceGrammarTest extends AbstractGrammarTest {
final String listItems = Stream.of(items).map(String::trim).map(x -> String.format("\"%s\"", x)).collect(Collectors.joining(","));
return String.format("[%s]", listItems);
}));
+ add(Pair.with(Pattern.compile("s\\[\\]"), (k,v) -> "{}"));
+ add(Pair.with(Pattern.compile("s\\[(.*)\\]"), (k,v) -> {
+ final String[] items = v.split(",");
+ final String setItems = Stream.of(items).map(String::trim).map(x -> String.format("\"%s\"", x)).collect(Collectors.joining(","));
+ return String.format("{%s}", setItems);
+ }));
add(Pair.with(Pattern.compile("v\\[(.+)\\]"), (k,v) -> "\"1\""));
add(Pair.with(Pattern.compile("v(\\d)"), (k,v) -> String.format("new Vertex(%s, \"vertex\")", v)));
add(Pair.with(Pattern.compile("e\\[(.+)\\]"), (k,v) -> "\"1\""));
diff --git a/gremlin-python/docker-compose.yml b/gremlin-python/docker-compose.yml
index 7a981e4fc4..85cec1d59d 100644
--- a/gremlin-python/docker-compose.yml
+++ b/gremlin-python/docker-compose.yml
@@ -63,8 +63,10 @@ services:
&& python3 ./setup.py build
&& python3 ./setup.py test
&& python3 ./setup.py install
- && radish -f dots -e -t -b ./radish ./gremlin-test --user-data='serializer=application/vnd.graphbinary-v4.0' --user-data='bulking=true'
+ && radish -f dots -e -t -b ./radish ./gremlin-test --user-data='serializer=application/vnd.graphbinary-v4.0' --user-data='bulked=true'
+ && radish -f dots -e -t -b ./radish ./gremlin-test --user-data='serializer=application/vnd.graphbinary-v4.0' --user-data='parameterize=true'
&& radish -f dots -e -t -b ./radish ./gremlin-test --user-data='serializer=application/vnd.graphbinary-v4.0'
+ && radish -f dots -e -t -b ./radish ./gremlin-test --user-data='serializer=application/vnd.gremlin-v4.0+json' --user-data='parameterize=true'
&& radish -f dots -e -t -b ./radish ./gremlin-test --user-data='serializer=application/vnd.gremlin-v4.0+json';
EXIT_CODE=$$?; chown -R `stat -c "%u:%g" .` .; exit $$EXIT_CODE"
depends_on:
diff --git a/gremlin-python/src/main/python/gremlin_python/process/traversal.py b/gremlin-python/src/main/python/gremlin_python/process/traversal.py
index bed20abc0b..08ad525252 100644
--- a/gremlin-python/src/main/python/gremlin_python/process/traversal.py
+++ b/gremlin-python/src/main/python/gremlin_python/process/traversal.py
@@ -23,7 +23,7 @@ import threading
import warnings
from aenum import Enum
-from gremlin_python.structure.graph import Vertex
+from gremlin_python.structure.graph import Vertex, Edge, Path, Property
from .. import statics
from ..statics import long, SingleByte, short, bigint, BigDecimal
@@ -853,10 +853,8 @@ class GremlinLang(object):
self.parameters.update(gremlin_lang.parameters)
return gremlin_lang.get_gremlin('__')
- if isinstance(arg, Parameter):
- key = arg.key
- if key is None:
- key = f'_{self.param_count.get_and_increment()}'
+ if isinstance(arg, GValue):
+ key = arg.get_name()
if not key.isidentifier():
raise Exception(f'invalid parameter name {key}.')
@@ -1085,20 +1083,23 @@ class GremlinLang(object):
# return Bytecode._create_graph_op("tx", "rollback")
-class Parameter:
- def __init__(self, key, value):
- self.key = key
+class GValue:
+ def __init__(self, name, value):
+ if name is None:
+ raise Exception("The parameter name cannot be None.")
+ if name.startswith('_'):
+ raise Exception(f'invalid GValue name {name}. Should not start with _.')
+ self.name = name
self.value = value
- @staticmethod
- def var(key, value):
- if key is not None and key.startswith('_'):
- raise Exception(f'invalid parameter name {key}. Should not start with _.')
- return Parameter(key, value)
+ def get_name(self):
+ return self.name
- @staticmethod
- def value(value):
- return Parameter(None, value)
+ def is_null(self):
+ return self.value is None
+
+ def get(self):
+ return self.value
class CardinalityValue(GremlinLang):
diff --git a/gremlin-python/src/main/python/gremlin_python/structure/io/graphbinaryV4.py b/gremlin-python/src/main/python/gremlin_python/structure/io/graphbinaryV4.py
index 7f646b0cbb..7e7eeb81bd 100644
--- a/gremlin-python/src/main/python/gremlin_python/structure/io/graphbinaryV4.py
+++ b/gremlin-python/src/main/python/gremlin_python/structure/io/graphbinaryV4.py
@@ -27,7 +27,7 @@ from datetime import datetime, timedelta, timezone
from struct import pack, unpack
from aenum import Enum
-from gremlin_python.process.traversal import Direction, T
+from gremlin_python.process.traversal import Direction, T, Merge
from gremlin_python.statics import FloatType, BigDecimal, ShortType, IntType, LongType, BigIntType, \
DictType, SetType, SingleByte, SingleChar
from gremlin_python.structure.graph import Graph, Edge, Property, Vertex, VertexProperty, Path
@@ -62,6 +62,7 @@ class DataType(Enum):
vertexproperty = 0x12
direction = 0x18
t = 0x20
+ merge = 0x2e
bigdecimal = 0x22
biginteger = 0x23
byte = 0x24
@@ -740,6 +741,11 @@ class TIO(_EnumIO):
python_type = T
+class MergeIO(_EnumIO):
+ graphbinary_type = DataType.merge
+ python_type = Merge
+
+
class ByteIO(_GraphBinaryTypeIO):
python_type = SingleByte
graphbinary_type = DataType.byte
diff --git a/gremlin-python/src/main/python/gremlin_python/structure/io/graphsonV4.py b/gremlin-python/src/main/python/gremlin_python/structure/io/graphsonV4.py
index 87183d420f..438c5d44f1 100644
--- a/gremlin-python/src/main/python/gremlin_python/structure/io/graphsonV4.py
+++ b/gremlin-python/src/main/python/gremlin_python/structure/io/graphsonV4.py
@@ -577,3 +577,12 @@ class DirectionIO(_GraphSONTypeIO):
@classmethod
def objectify(cls, d, reader):
return Direction[d]
+
+
+class EnumSerializer(_GraphSONTypeIO):
+ python_type = Enum
+
+ @classmethod
+ def dictify(cls, enum, _):
+ return GraphSONUtil.typed_value(SymbolUtil.to_camel_case(type(enum).__name__),
+ SymbolUtil.to_camel_case(str(enum.name)))
diff --git a/gremlin-python/src/main/python/radish/feature_steps.py b/gremlin-python/src/main/python/radish/feature_steps.py
index ccb600f2ef..cb622f7c06 100644
--- a/gremlin-python/src/main/python/radish/feature_steps.py
+++ b/gremlin-python/src/main/python/radish/feature_steps.py
@@ -25,7 +25,7 @@ from gremlin_python.structure.graph import Path, Vertex
from gremlin_python.process.anonymous_traversal import traversal
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, WithOptions, Merge
+ Pick, Operator, IO, WithOptions, Merge, GValue
from radish import given, when, then, world
from hamcrest import *
@@ -127,9 +127,16 @@ def translate_traversal(step):
if step.context.ignore:
return
- p = step.context.traversal_params if hasattr(step.context, "traversal_params") else {}
- localg = step.context.g.with_('language', 'gremlin-lang')
+ p = {}
+ if hasattr(step.context, "traversal_params"):
+ # user flag "parameterize", when set to 'true' will use GValue to parameterize parameters instead of flattening them out into string
+ if world.config.user_data.get("parameterize"):
+ for k, v in step.context.traversal_params.items():
+ p[k] = GValue(k, v)
+ else:
+ p = step.context.traversal_params
+ localg = step.context.g.with_('language', 'gremlin-lang')
tagset = [tag.name for tag in step.all_tags]
if "GraphComputerOnly" in tagset:
localg = step.context.g.with_('language', 'gremlin-lang').with_computer()
diff --git a/gremlin-python/src/main/python/radish/gremlin.py b/gremlin-python/src/main/python/radish/gremlin.py
index d082e9e3a3..a2db50be54 100644
--- a/gremlin-python/src/main/python/radish/gremlin.py
+++ b/gremlin-python/src/main/python/radish/gremlin.py
@@ -194,6 +194,7 @@ world.gremlins = {
'g_VX1X_hasXnameX': [(lambda g, vid1=None:g.V(vid1).has('name'))],
'g_VX1X_hasXcircumferenceX': [(lambda g, vid1=None:g.V(vid1).has('circumference'))],
'g_VX1X_hasXname_markoX': [(lambda g, vid1=None:g.V(vid1).has('name', 'marko'))],
+ 'g_VX1X_hasXname_markovarX': [(lambda g, xx1=None,vid1=None:g.V(vid1).has('name', xx1))],
'g_VX2X_hasXname_markoX': [(lambda g, vid1=None:g.V(vid1).has('name', 'marko'))],
'g_V_hasXname_markoX': [(lambda g:g.V().has('name', 'marko'))],
'g_V_hasXname_blahX': [(lambda g:g.V().has('name', 'blah'))],
@@ -292,8 +293,11 @@ world.gremlins = {
'g_V_properties_hasValueXnull_nullX': [(lambda g:g.V().properties().has_value(None, None))],
'g_V_properties_hasValueXnull_joshX_value': [(lambda g:g.V().properties().has_value(None, 'josh').value())],
'g_V_valuesXageX_isX32X': [(lambda g:g.V().values('age').is_(32))],
+ 'g_V_valuesXageX_isX32varX': [(lambda g, xx1=None:g.V().values('age').is_(xx1))],
'g_V_valuesXageX_isXlte_30X': [(lambda g:g.V().values('age').is_(P.lte(30)))],
+ 'g_V_valuesXageX_isXlte_30varX': [(lambda g, xx1=None:g.V().values('age').is_(P.lte(xx1)))],
'g_V_valuesXageX_isXgte_29X_isXlt_34X': [(lambda g:g.V().values('age').is_(P.gte(29)).is_(P.lt(34)))],
+ 'g_V_valuesXageX_isXgte_29vaarX_isXlt_34varX': [(lambda g, xx1=None,xx2=None:g.V().values('age').is_(P.gte(xx1)).is_(P.lt(xx2)))],
'g_V_whereXinXcreatedX_count_isX1XX_valuesXnameX': [(lambda g:g.V().where(__.in_('created').count().is_(1)).values('name'))],
'g_V_whereXinXcreatedX_count_isXgte_2XX_valuesXnameX': [(lambda g:g.V().where(__.in_('created').count().is_(P.gte(2))).values('name'))],
'g_V_valuesXageX_noneXgtX32XX': [(lambda g:g.V().values('age').none(P.gt(32)))],
@@ -361,7 +365,7 @@ world.gremlins = {
'g_V_hasXageX_asXaX_out_in_hasXageX_asXbX_selectXa_bX_whereXb_hasXname_markoXX': [(lambda g:g.V().has('age').as_('a').out().in_().has('age').as_('b').select('a', 'b').where(__.as_('b').has('name', 'marko')))],
'g_V_hasXageX_asXaX_out_in_hasXageX_asXbX_selectXa_bX_whereXa_outXknowsX_bX': [(lambda g:g.V().has('age').as_('a').out().in_().has('age').as_('b').select('a', 'b').where(__.as_('a').out('knows').as_('b')))],
'g_V_asXaX_outXcreatedX_whereXasXaX_name_isXjoshXX_inXcreatedX_name': [(lambda g:g.V().as_('a').out('created').where(__.as_('a').values('name').is_('josh')).in_('created').values('name'))],
- 'g_withSideEffectXa_josh_peterX_VX1X_outXcreatedX_inXcreatedX_name_whereXwithinXaXX': [(lambda g, xx1=None,vid1=None:g.with_side_effect('a', xx1).V(vid1).out('created').in_('created').values('name').where(P.within('a')))],
+ 'g_withSideEffectXa_josh_peterX_VX1X_outXcreatedX_inXcreatedX_name_whereXwithinXaXX': [(lambda g, vid1=None:g.with_side_effect('a', ['josh', 'peter']).V(vid1).out('created').in_('created').values('name').where(P.within('a')))],
'g_VX1X_asXaX_outXcreatedX_inXcreatedX_asXbX_whereXa_neqXbXX_name': [(lambda g, vid1=None:g.V(vid1).as_('a').out('created').in_('created').as_('b').where('a', P.neq('b')).values('name'))],
'g_VX1X_asXaX_outXcreatedX_inXcreatedX_asXbX_whereXasXbX_outXcreatedX_hasXname_rippleXX_valuesXage_nameX': [(lambda g, vid1=None:g.V(vid1).as_('a').out('created').in_('created').as_('b').where(__.as_('b').out('created').has('name', 'ripple')).values('age', 'name'))],
'g_VX1X_asXaX_outXcreatedX_inXcreatedX_whereXeqXaXX_name': [(lambda g, vid1=None:g.V(vid1).as_('a').out('created').in_('created').where(P.eq('a')).values('name'))],
@@ -566,11 +570,15 @@ world.gremlins = {
'g_V_hasXname_markoX_asXaX_outEXcreatedX_asXbX_inV_addEXselectXbX_labelX_toXaX': [(lambda g, v1=None:g.add_v('person').property('name', 'marko').property('age', 29).as_('marko').add_v('person').property('name', 'vadas').property('age', 27).as_('vadas').add_v('software').property('name', 'lop').property('lang', 'java').as_('lop').add_v('person').property('name', 'josh').property('age', 32).as_('josh').add_v('software').property('name', 'ripple').property('lang', 'java').as_('ripple'). [...]
'g_addEXV_outE_label_groupCount_orderXlocalX_byXvalues_descX_selectXkeysX_unfold_limitX1XX_fromXV_hasXname_vadasXX_toXV_hasXname_lopXX': [(lambda g, v2=None:g.add_v('person').property('name', 'marko').property('age', 29).as_('marko').add_v('person').property('name', 'vadas').property('age', 27).as_('vadas').add_v('software').property('name', 'lop').property('lang', 'java').as_('lop').add_v('person').property('name', 'josh').property('age', 32).as_('josh').add_v('software').property(' [...]
'g_addEXknowsX_fromXaX_toXbX_propertyXweight_0_1X': [(lambda g, v6=None,xx1=None,v1=None:g.add_v('person').property('name', 'marko').property('age', 29).as_('marko').add_v('person').property('name', 'vadas').property('age', 27).as_('vadas').add_v('software').property('name', 'lop').property('lang', 'java').as_('lop').add_v('person').property('name', 'josh').property('age', 32).as_('josh').add_v('software').property('name', 'ripple').property('lang', 'java').as_('ripple').add_v('perso [...]
+ 'g_addEXknowsvarX_fromXaX_toXbX_propertyXweight_0_1X': [(lambda g, xx1=None,v6=None,xx2=None,v1=None:g.add_v('person').property('name', 'marko').property('age', 29).as_('marko').add_v('person').property('name', 'vadas').property('age', 27).as_('vadas').add_v('software').property('name', 'lop').property('lang', 'java').as_('lop').add_v('person').property('name', 'josh').property('age', 32).as_('josh').add_v('software').property('name', 'ripple').property('lang', 'java').as_('ripple'). [...]
'g_VXaX_addEXknowsX_toXbX_propertyXweight_0_1X': [(lambda g, v6=None,xx1=None,v1=None:g.add_v('person').property('name', 'marko').property('age', 29).as_('marko').add_v('person').property('name', 'vadas').property('age', 27).as_('vadas').add_v('software').property('name', 'lop').property('lang', 'java').as_('lop').add_v('person').property('name', 'josh').property('age', 32).as_('josh').add_v('software').property('name', 'ripple').property('lang', 'java').as_('ripple').add_v('person') [...]
'g_addEXknowsXpropertyXweight_nullXfromXV_hasXname_markoXX_toXV_hasXname_vadasXX': [(lambda g:g.add_v('person').property('name', 'marko').property('age', 29).add_v('person').property('name', 'vadas').property('age', 27)), (lambda g:g.add_e('knows').property('weight', None).from_(__.V().has('name', 'marko')).to(__.V().has('name', 'vadas'))), (lambda g:g.E().has('knows', 'weight', None))],
+ 'g_addEXknowsvarXpropertyXweight_nullXfromXV_hasXname_markoXX_toXV_hasXname_vadasXX': [(lambda g, xx1=None:g.add_v('person').property('name', 'marko').property('age', 29).add_v('person').property('name', 'vadas').property('age', 27)), (lambda g, xx1=None:g.add_e(xx1).property('weight', None).from_(__.V().has('name', 'marko')).to(__.V().has('name', 'vadas'))), (lambda g, xx1=None:g.E().has('knows', 'weight', None))],
'g_VX1X_addVXanimalX_propertyXage_selectXaX_byXageXX_propertyXname_puppyX': [(lambda g, vid1=None:g.add_v('person').property('name', 'marko').property('age', 29).as_('marko').add_v('person').property('name', 'vadas').property('age', 27).as_('vadas').add_v('software').property('name', 'lop').property('lang', 'java').as_('lop').add_v('person').property('name', 'josh').property('age', 32).as_('josh').add_v('software').property('name', 'ripple').property('lang', 'java').as_('ripple').add [...]
'g_V_addVXanimalX_propertyXage_0X': [(lambda g:g.add_v('person').property('name', 'marko').property('age', 29).as_('marko').add_v('person').property('name', 'vadas').property('age', 27).as_('vadas').add_v('software').property('name', 'lop').property('lang', 'java').as_('lop').add_v('person').property('name', 'josh').property('age', 32).as_('josh').add_v('software').property('name', 'ripple').property('lang', 'java').as_('ripple').add_v('person').property('name', 'peter').property('ag [...]
+ 'g_V_addVXanimalvarX_propertyXage_0varX': [(lambda g, xx1=None,xx2=None:g.add_v('person').property('name', 'marko').property('age', 29).as_('marko').add_v('person').property('name', 'vadas').property('age', 27).as_('vadas').add_v('software').property('name', 'lop').property('lang', 'java').as_('lop').add_v('person').property('name', 'josh').property('age', 32).as_('josh').add_v('software').property('name', 'ripple').property('lang', 'java').as_('ripple').add_v('person').property('nam [...]
'g_addVXpersonX_propertyXname_stephenX': [(lambda g:g.add_v('person').property('name', 'marko').property('age', 29).as_('marko').add_v('person').property('name', 'vadas').property('age', 27).as_('vadas').add_v('software').property('name', 'lop').property('lang', 'java').as_('lop').add_v('person').property('name', 'josh').property('age', 32).as_('josh').add_v('software').property('name', 'ripple').property('lang', 'java').as_('ripple').add_v('person').property('name', 'peter').propert [...]
+ 'g_addVXpersonvarX_propertyXname_stephenvarX': [(lambda g, xx1=None,xx2=None:g.add_v('person').property('name', 'marko').property('age', 29).as_('marko').add_v('person').property('name', 'vadas').property('age', 27).as_('vadas').add_v('software').property('name', 'lop').property('lang', 'java').as_('lop').add_v('person').property('name', 'josh').property('age', 32).as_('josh').add_v('software').property('name', 'ripple').property('lang', 'java').as_('ripple').add_v('person').property [...]
'g_V_hasLabelXpersonX_propertyXname_nullX': [(lambda g:g.add_v('person').property('name', 'marko').property('age', 29).as_('marko').add_v('person').property('name', 'vadas').property('age', 27).as_('vadas').add_v('software').property('name', 'lop').property('lang', 'java').as_('lop').add_v('person').property('name', 'josh').property('age', 32).as_('josh').add_v('software').property('name', 'ripple').property('lang', 'java').as_('ripple').add_v('person').property('name', 'peter').prop [...]
'g_addVXpersonX_propertyXsingle_name_stephenX_propertyXsingle_name_stephenmX': [(lambda g:g.add_v('person').property('name', 'marko').property('age', 29).as_('marko').add_v('person').property('name', 'vadas').property('age', 27).as_('vadas').add_v('software').property('name', 'lop').property('lang', 'java').as_('lop').add_v('person').property('name', 'josh').property('age', 32).as_('josh').add_v('software').property('name', 'ripple').property('lang', 'java').as_('ripple').add_v('pers [...]
'get_g_addVXpersonX_propertyXsingle_name_stephenX_propertyXsingle_name_stephenm_since_2010X': [(lambda g:g.add_v('person').property('name', 'marko').property('age', 29).as_('marko').add_v('person').property('name', 'vadas').property('age', 27).as_('vadas').add_v('software').property('name', 'lop').property('lang', 'java').as_('lop').add_v('person').property('name', 'josh').property('age', 32).as_('josh').add_v('software').property('name', 'ripple').property('lang', 'java').as_('rippl [...]
@@ -584,6 +592,9 @@ world.gremlins = {
'g_V_asXaX_hasXname_markoX_outXcreatedX_asXbX_addVXselectXaX_labelX_propertyXtest_selectXbX_labelX_valueMap_withXtokensX': [(lambda g:g.add_v('person').property('name', 'marko').property('age', 29).as_('marko').add_v('person').property('name', 'vadas').property('age', 27).as_('vadas').add_v('software').property('name', 'lop').property('lang', 'java').as_('lop').add_v('person').property('name', 'josh').property('age', 32).as_('josh').add_v('software').property('name', 'ripple').proper [...]
'g_addVXV_hasXname_markoX_propertiesXnameX_keyX_label': [(lambda g:g.add_v('person').property('name', 'marko').property('age', 29).as_('marko').add_v('person').property('name', 'vadas').property('age', 27).as_('vadas').add_v('software').property('name', 'lop').property('lang', 'java').as_('lop').add_v('person').property('name', 'josh').property('age', 32).as_('josh').add_v('software').property('name', 'ripple').property('lang', 'java').as_('ripple').add_v('person').property('name', ' [...]
'g_addV_propertyXlabel_personX': [(lambda g:g.add_v().property(T.label, 'person')), (lambda g:g.V().has_label('person'))],
+ 'g_addV_propertyXlabel_personvarX': [(lambda g, xx1=None:g.add_v().property(T.label, xx1)), (lambda g, xx1=None:g.V().has_label('person'))],
+ 'g_addV_propertyXid_1X': [(lambda g:g.add_v().property(T.id_, 1)), (lambda g:g.V().has_id('1'))],
+ 'g_addV_propertyXidvar_1varX': [(lambda g, xx1=None:g.add_v().property(T.id_, xx1)), (lambda g, xx1=None:g.V().has_id('1'))],
'g_addV_propertyXmapX': [(lambda g:g.add_v().property({ 'name': 'foo', 'age': 42 })), (lambda g:g.V().has('name', 'foo'))],
'g_addV_propertyXsingle_mapX': [(lambda g:g.add_v().property(Cardinality.single, { 'name': 'foo', 'age': 42 })), (lambda g:g.V().has('name', 'foo'))],
'g_V_hasXname_fooX_propertyXname_setXbarX_age_43X': [(lambda g:g.add_v().property(Cardinality.single, 'name', 'foo').property('age', 42)), (lambda g:g.V().has('name', 'foo').property({ 'name': CardinalityValue.set_('bar'), 'age': 43 })), (lambda g:g.V().has('name', 'foo')), (lambda g:g.V().has('name', 'bar')), (lambda g:g.V().has('age', 43)), (lambda g:g.V().has('age', 42))],
@@ -965,9 +976,11 @@ world.gremlins = {
'g_V_mergeEXlabel_selfX_optionXonMatch_emptyX': [(lambda g, xx1=None:g.add_v('person').property('name', 'marko').property('age', 29).add_e('self')), (lambda g, xx1=None:g.V().merge_e(xx1).option(Merge.on_match, { })), (lambda g, xx1=None:g.E()), (lambda g, xx1=None:g.E().properties()), (lambda g, xx1=None:g.V())],
'g_V_mergeEXlabel_selfX_optionXonMatch_nullX': [(lambda g, xx1=None:g.add_v('person').property('name', 'marko').property('age', 29).add_e('self')), (lambda g, xx1=None:g.V().merge_e(xx1).option(Merge.on_match, None)), (lambda g, xx1=None:g.E()), (lambda g, xx1=None:g.E().properties()), (lambda g, xx1=None:g.V())],
'g_V_mergeEXemptyX_optionXonCreate_nullX': [(lambda g, xx1=None:g.add_v('person').property('name', 'marko').property('age', 29)), (lambda g, xx1=None:g.V().as_('v').merge_e(xx1).option(Merge.on_create, None).option(Merge.out_v, __.select('v')).option(Merge.in_v, __.select('v'))), (lambda g, xx1=None:g.E()), (lambda g, xx1=None:g.V())],
+ 'g_V_mergeE_inlineXemptyX_optionXonCreate_nullX': [(lambda g:g.add_v('person').property('name', 'marko').property('age', 29)), (lambda g:g.V().as_('v').merge_e({ T.label: 'self', Direction.OUT: Merge.out_v, Direction.IN: Merge.in_v }).option(Merge.on_create, None).option(Merge.out_v, __.select('v')).option(Merge.in_v, __.select('v'))), (lambda g:g.E()), (lambda g:g.V())],
'g_mergeEXemptyX_exists': [(lambda g:g.add_v('person').property('name', 'marko').property('age', 29).add_e('self')), (lambda g:g.merge_e({ })), (lambda g:g.E()), (lambda g:g.V())],
'g_mergeEXemptyX': [(lambda g:g.add_v('person').property('name', 'marko').property('age', 29)), (lambda g:g.merge_e({ }))],
'g_V_mergeEXemptyX_two_exist': [(lambda g, xx1=None:g.add_v('person').property('name', 'marko').property('age', 29).add_v('person').property('name', 'vadas').property('age', 27)), (lambda g, xx1=None:g.V().as_('v').merge_e(xx1).option(Merge.out_v, __.select('v')).option(Merge.in_v, __.select('v'))), (lambda g, xx1=None:g.E()), (lambda g, xx1=None:g.V())],
+ 'g_V_mergeE_inlineXemptyX_two_exist': [(lambda g:g.add_v('person').property('name', 'marko').property('age', 29).add_v('person').property('name', 'vadas').property('age', 27)), (lambda g:g.V().as_('v').merge_e({ T.label: 'self', Direction.OUT: Merge.out_v, Direction.IN: Merge.in_v }).option(Merge.out_v, __.select('v')).option(Merge.in_v, __.select('v'))), (lambda g:g.E()), (lambda g:g.V())],
'g_mergeEXnullX': [(lambda g:g.add_v('person').property('name', 'marko').property('age', 29)), (lambda g:g.merge_e(None))],
'g_V_mergeEXnullX': [(lambda g:g.add_v('person').property('name', 'marko').property('age', 29)), (lambda g:g.V().merge_e(None))],
'g_mergeEXlabel_knows_out_marko_in_vadasX': [(lambda g, xx1=None:g.add_v('person').property('name', 'marko').add_v('person').property('name', 'vadas')), (lambda g, xx1=None:g.merge_e(xx1)), (lambda g, xx1=None:g.V().has('person', 'name', 'marko').out('knows').has('person', 'name', 'vadas'))],
@@ -991,7 +1004,9 @@ world.gremlins = {
'g_injectXlabel_knows_out_marko_in_vadas_label_self_out_vadas_in_vadasX': [(lambda g, xx1=None,xx2=None:g.add_v('person').property('name', 'marko').add_v('person').property('name', 'vadas')), (lambda g, xx1=None,xx2=None:g.inject(xx1, xx2).merge_e()), (lambda g, xx1=None,xx2=None:g.V()), (lambda g, xx1=None,xx2=None:g.E()), (lambda g, xx1=None,xx2=None:g.V().has('person', 'name', 'marko').out('knows').has('person', 'name', 'vadas')), (lambda g, xx1=None,xx2=None:g.V().has('person', ' [...]
'g_withSideEffectXc_created_YX_withSideEffectXm_matchedX_mergeEXlabel_knows_out_marko_in_vadasX_optionXonCreate_selectXcXX_optionXonMatch_sideEffectXpropertiesXweightX_dropX_selectXmXX_exists': [(lambda g, xx1=None,xx3=None,xx2=None:g.add_v('person').property('name', 'marko').as_('a').add_v('person').property('name', 'vadas').as_('b').add_e('knows').property('weight', 1.0).from_('a').to('b')), (lambda g, xx1=None,xx3=None,xx2=None:g.with_side_effect('c', xx2).with_side_effect('m', xx [...]
'g_mergeE_with_outVinV_options_map': [(lambda g, xx1=None,xx3=None,xx2=None:g.add_v('person').property('name', 'marko').add_v('person').property('name', 'vadas')), (lambda g, xx1=None,xx3=None,xx2=None:g.merge_e(xx1).option(Merge.out_v, xx2).option(Merge.in_v, xx3)), (lambda g, xx1=None,xx3=None,xx2=None:g.V()), (lambda g, xx1=None,xx3=None,xx2=None:g.V().has('name', 'marko').out('knows').has('name', 'vadas'))],
+ 'g_mergeE_inline_with_outVinV_options_map': [(lambda g, xx1=None,xx2=None:g.add_v('person').property('name', 'marko').add_v('person').property('name', 'vadas')), (lambda g, xx1=None,xx2=None:g.merge_e({ Direction.OUT: Merge.out_v, Direction.IN: Merge.in_v, T.label: 'knows' }).option(Merge.out_v, xx1).option(Merge.in_v, xx2)), (lambda g, xx1=None,xx2=None:g.V()), (lambda g, xx1=None,xx2=None:g.V().has('name', 'marko').out('knows').has('name', 'vadas'))],
'g_mergeE_with_outVinV_options_select': [(lambda g, xx1=None,vid2=None,vid1=None:g.add_v('person').property('name', 'marko').add_v('person').property('name', 'vadas')), (lambda g, xx1=None,vid2=None,vid1=None:g.V(vid1).as_('x').V(vid2).as_('y').merge_e(xx1).option(Merge.out_v, __.select('x')).option(Merge.in_v, __.select('y'))), (lambda g, xx1=None,vid2=None,vid1=None:g.V()), (lambda g, xx1=None,vid2=None,vid1=None:g.V().has('name', 'marko').out('knows').has('name', 'vadas'))],
+ 'g_mergeE_inline_with_outVinV_options_select': [(lambda g, vid2=None,vid1=None:g.add_v('person').property('name', 'marko').add_v('person').property('name', 'vadas')), (lambda g, vid2=None,vid1=None:g.V(vid1).as_('x').V(vid2).as_('y').merge_e({ Direction.OUT: Merge.out_v, Direction.IN: Merge.in_v, T.label: 'knows' }).option(Merge.out_v, __.select('x')).option(Merge.in_v, __.select('y'))), (lambda g, vid2=None,vid1=None:g.V()), (lambda g, vid2=None,vid1=None:g.V().has('name', 'marko'). [...]
'g_mergeE_with_eid_specified_and_inheritance_1': [(lambda g, xx1=None,xx2=None:g.add_v('person').property('name', 'marko').add_v('person').property('name', 'vadas')), (lambda g, xx1=None,xx2=None:g.merge_e(xx1).option(Merge.on_create, xx2)), (lambda g, xx1=None,xx2=None:g.V()), (lambda g, xx1=None,xx2=None:g.E()), (lambda g, xx1=None,xx2=None:g.E('201')), (lambda g, xx1=None,xx2=None:g.V().has('name', 'marko').out('knows').has('name', 'vadas'))],
'g_mergeE_with_eid_specified_and_inheritance_2': [(lambda g, xx1=None,xx2=None:g.add_v('person').property('name', 'marko').add_v('person').property('name', 'vadas')), (lambda g, xx1=None,xx2=None:g.merge_e(xx1).option(Merge.on_create, xx2)), (lambda g, xx1=None,xx2=None:g.V()), (lambda g, xx1=None,xx2=None:g.E()), (lambda g, xx1=None,xx2=None:g.E('201')), (lambda g, xx1=None,xx2=None:g.V().has('name', 'marko').out('knows').has('name', 'vadas'))],
'g_mergeE_outV_override_prohibited': [(lambda g, xx1=None,xx2=None:g.add_v('person').property('name', 'marko').add_v('person').property('name', 'vadas')), (lambda g, xx1=None,xx2=None:g.merge_e(xx1).option(Merge.on_create, xx2))],
@@ -1375,12 +1390,14 @@ world.gremlins = {
'g_VX1X_outE': [(lambda g, vid1=None:g.V(vid1).out_e())],
'g_VX2X_outE': [(lambda g, vid2=None:g.V(vid2).in_e())],
'g_VX4X_bothEXcreatedX': [(lambda g, vid4=None:g.V(vid4).both_e('created'))],
+ 'g_VX4X_bothEXcreatedvarX': [(lambda g, xx1=None,vid4=None:g.V(vid4).both_e(xx1))],
'g_VX4X_bothE': [(lambda g, vid4=None:g.V(vid4).both_e())],
'g_V_out_outE_inV_inE_inV_both_name': [(lambda g:g.V().out().out_e().in_v().in_e().in_v().both().values('name'))],
'g_VX2X_inE': [(lambda g, vid2=None:g.V(vid2).both_e())],
'g_VX1X_outXknowsX': [(lambda g, vid1=None:g.V(vid1).out('knows'))],
'g_VX1AsStringX_outXknowsX': [(lambda g, vid1=None:g.V(vid1).out('knows'))],
'g_VX1X_outXknows_createdX': [(lambda g, vid1=None:g.V(vid1).out('knows', 'created'))],
+ 'g_VX1X_outXknowsvar_createdvarX': [(lambda g, xx3=None,xx2=None,vid1=None:g.V(vid1).out(xx2, xx3))],
'g_V_out_out': [(lambda g:g.V().out().out())],
'g_VX1X_out_out_out': [(lambda g, vid1=None:g.V(vid1).out().out().out())],
'g_VX1X_out_name': [(lambda g, vid1=None:g.V(vid1).out().values('name'))],
@@ -1596,9 +1613,14 @@ world.gremlins = {
'g_VX1X_valuesXageX_inject': [(lambda g, xx1=None:g.V(xx1).values('age').inject())],
'g_injectXnull_1_3_nullX_asXaX_selectXaX': [(lambda g:g.inject(None, 1, 3, None).as_('a').select('a'))],
'g_injectX1_3X_injectX100_300X': [(lambda g:g.inject(1, 3).inject(100, 300))],
+ 'g_injectX1var_3varX_injectX100var_300varX': [(lambda g, xx1=None,xx3=None,xx2=None,xx4=None:g.inject(xx1, xx2).inject(xx3, xx4))],
'g_injectX1_3_100_300X_list': [(lambda g:g.inject([1, 3, 100, 300]))],
+ 'g_injectX1_3_100_300X_listvar': [(lambda g, xx1=None:g.inject(xx1))],
'g_injectX1_3_100_300X_set': [(lambda g:g.inject({1, 3, 100, 300}))],
+ 'g_injectX1_3_100_300X_setvar': [(lambda g, xx1=None:g.inject(xx1))],
'g_injectX1_1X_set': [(lambda g:g.inject({1, 1}))],
+ 'g_injectX1_1X_setvar': [(lambda g, xx1=None:g.inject(xx1))],
+ 'g_injectX_set': [(lambda g, xx1=None:g.inject(xx1))],
'g_io_readXkryoX': [(lambda g:g.io('data/tinkerpop-modern.kryo').read()), (lambda g:g.V()), (lambda g:g.E())],
'g_io_read_withXreader_gryoX': [(lambda g:g.io('data/tinkerpop-modern.kryo').with_(IO.reader, IO.gryo).read()), (lambda g:g.V()), (lambda g:g.E())],
'g_io_readXgraphsonX': [(lambda g:g.io('data/tinkerpop-modern.json').read()), (lambda g:g.V()), (lambda g:g.E())],
diff --git a/gremlin-python/src/main/python/tests/driver/test_client.py b/gremlin-python/src/main/python/tests/driver/test_client.py
index 462d40288a..c04bf9d26d 100644
--- a/gremlin-python/src/main/python/tests/driver/test_client.py
+++ b/gremlin-python/src/main/python/tests/driver/test_client.py
@@ -27,7 +27,7 @@ from gremlin_python.driver.protocol import GremlinServerError
from gremlin_python.driver.request import RequestMessage
from gremlin_python.driver.serializer import GraphBinarySerializersV4
from gremlin_python.process.graph_traversal import __, GraphTraversalSource
-from gremlin_python.process.traversal import TraversalStrategies, Parameter
+from gremlin_python.process.traversal import TraversalStrategies, GValue
from gremlin_python.process.strategies import OptionsStrategy
from gremlin_python.structure.graph import Graph, Vertex
from gremlin_python.driver.aiohttp.transport import AiohttpHTTPTransport
@@ -264,8 +264,8 @@ def test_client_gremlin_lang_options(client):
def test_client_gremlin_lang_request_options_with_binding(client):
g = GraphTraversalSource(Graph(), TraversalStrategies())
# Note that bindings for constructed traversals is done via Parameter only
- t = g.with_('language', 'gremlin-lang').V(Parameter.var('x', [1, 2, 3])).count()
- request_opts = {'language': 'gremlin-lang', 'params': {'x': [1, 2, 3]}}
+ t = g.with_('language', 'gremlin-lang').V(GValue('x', [1, 2, 3])).count()
+ request_opts = DriverRemoteConnection.extract_request_options(t.gremlin_lang)
message = create_basic_request_message(t)
result_set = client.submit(message, request_options=request_opts)
assert result_set.all().result()[0] == 3
diff --git a/gremlin-python/src/main/python/tests/driver/test_driver_remote_connection.py b/gremlin-python/src/main/python/tests/driver/test_driver_remote_connection.py
index 1d4db05c44..0567a7c538 100644
--- a/gremlin-python/src/main/python/tests/driver/test_driver_remote_connection.py
+++ b/gremlin-python/src/main/python/tests/driver/test_driver_remote_connection.py
@@ -21,7 +21,7 @@ import os
from gremlin_python import statics
from gremlin_python.driver.driver_remote_connection import DriverRemoteConnection
from gremlin_python.statics import long
-from gremlin_python.process.traversal import TraversalStrategy, P, Order, T, DT, Parameter, Cardinality
+from gremlin_python.process.traversal import TraversalStrategy, P, Order, T, DT, GValue, Cardinality
from gremlin_python.process.graph_traversal import __
from gremlin_python.process.anonymous_traversal import traversal
from gremlin_python.structure.graph import Vertex
@@ -116,7 +116,7 @@ class TestDriverRemoteConnection(object):
g = traversal().with_(remote_connection)
t = g.with_("evaluationTimeout",
1000).with_("batchSize", 100).with_("userAgent",
- "test").V(Parameter.var('ids', [1, 2, 3])).count()
+ "test").V(GValue('ids', [1, 2, 3])).count()
assert remote_connection.extract_request_options(t.gremlin_lang) == {'batchSize': 100,
'evaluationTimeout': 1000,
'userAgent': 'test',
diff --git a/gremlin-python/src/main/python/tests/process/test_gremlin_lang.py b/gremlin-python/src/main/python/tests/process/test_gremlin_lang.py
index 0ff3ce69b5..e4c60c8bc8 100644
--- a/gremlin-python/src/main/python/tests/process/test_gremlin_lang.py
+++ b/gremlin-python/src/main/python/tests/process/test_gremlin_lang.py
@@ -21,7 +21,7 @@ Unit tests for the GremlinLang Class. Modified from deprecated Groovy Translator
"""
from gremlin_python.process.strategies import ReadOnlyStrategy, SubgraphStrategy, OptionsStrategy, PartitionStrategy
from gremlin_python.process.traversal import within, eq, T, Order, Scope, Column, Operator, P, Pop, Cardinality, \
- between, inside, WithOptions, ShortestPath, starting_with, ending_with, containing, gt, lte, Parameter
+ between, inside, WithOptions, ShortestPath, starting_with, ending_with, containing, gt, lte, GValue
from gremlin_python.statics import SingleByte, short, long, bigint, BigDecimal
from gremlin_python.structure.graph import Graph, Vertex, Edge, VertexProperty
from gremlin_python.process.anonymous_traversal import traversal
@@ -473,45 +473,52 @@ class TestGremlinLang(object):
gremlin_lang = tests[t][0].gremlin_lang.get_gremlin()
assert gremlin_lang == tests[t][1]
- def test_parameters_name_dont_need_escaping(self):
+ def test_gvalue_name_cannot_be_null(self):
g = traversal().with_(None)
try:
- g.V(Parameter.var('\"', [1, 2, 3]))
+ g.V(GValue(None, [1, 2, 3]))
+ except Exception as ex:
+ assert str(ex) == 'The parameter name cannot be None.'
+
+ def test_gvalue_name_dont_need_escaping(self):
+ g = traversal().with_(None)
+ try:
+ g.V(GValue('\"', [1, 2, 3]))
except Exception as ex:
assert str(ex) == 'invalid parameter name ".'
- def test_parameters_is_not_number(self):
+ def test_gvalue_is_not_number(self):
g = traversal().with_(None)
try:
- g.V(Parameter.var('1', [1, 2, 3]))
+ g.V(GValue('1', [1, 2, 3]))
except Exception as ex:
assert str(ex) == 'invalid parameter name 1.'
- def test_parameters_is_valid_identifier(self):
+ def test_gvalue_is_valid_identifier(self):
g = traversal().with_(None)
try:
- g.V(Parameter.var('1a', [1, 2, 3]))
+ g.V(GValue('1a', [1, 2, 3]))
except Exception as ex:
assert str(ex) == 'invalid parameter name 1a.'
- def test_parameters_is_not_reserved(self):
+ def test_gvalue_is_not_reserved(self):
g = traversal().with_(None)
try:
- g.V(Parameter.var('_1', [1, 2, 3]))
+ g.V(GValue('_1', [1, 2, 3]))
except Exception as ex:
- assert str(ex) == 'invalid parameter name _1. Should not start with _.'
+ assert str(ex) == 'invalid GValue name _1. Should not start with _.'
- def test_parameters_is_not_duplicate(self):
+ def test_gvalue_is_not_duplicate(self):
g = traversal().with_(None)
try:
- g.inject(Parameter.var('ids', [1, 2])).V(Parameter.var('ids', [2, 3]))
+ g.inject(GValue('ids', [1, 2])).V(GValue('ids', [2, 3]))
except Exception as ex:
assert str(ex) == 'parameter with name ids already exists.'
- def test_parameters_allow_parameter_reuse(self):
+ def test_gvalue_allow_parameter_reuse(self):
g = traversal().with_(None)
val = [1, 2, 3]
- p = Parameter.var('ids', val)
+ p = GValue('ids', val)
gremlin = g.inject(p).V(p).gremlin_lang
assert 'g.inject(ids).V(ids)' == gremlin.get_gremlin()
assert val == gremlin.get_parameters().get('ids')
diff --git a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/GraphBinaryLangRemoteFeatureTest.java b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/GraphBinaryLangRemoteFeatureTest.java
index d02ad5cc5f..205db5884a 100644
--- a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/GraphBinaryLangRemoteFeatureTest.java
+++ b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/GraphBinaryLangRemoteFeatureTest.java
@@ -34,6 +34,7 @@ import org.junit.runner.RunWith;
glue = { "org.apache.tinkerpop.gremlin.features" },
objectFactory = GraphBinaryLangRemoteFeatureTest.RemoteGuiceFactory.class,
features = { "classpath:/org/apache/tinkerpop/gremlin/test/features" },
+// name= {"g_addEXknowsX_fromXaX_toXbX_propertyXweight_0_1X"},
plugin = {"progress", "junit:target/cucumber.xml"})
public class GraphBinaryLangRemoteFeatureTest extends AbstractFeatureTest {
public static class RemoteGuiceFactory extends AbstractGuiceFactory {
diff --git a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/RemoteWorld.java b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/RemoteWorld.java
index 668bc57ca1..6ec1bafe9f 100644
--- a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/RemoteWorld.java
+++ b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/RemoteWorld.java
@@ -167,6 +167,11 @@ public abstract class RemoteWorld implements World {
final GraphTraversalSource g = super.getGraphTraversalSource(graphData);
return g.with("language", "gremlin-lang");
}
+
+ @Override
+ public boolean useParametersLiterally() {
+ return false;
+ }
}
public static class GraphBinaryLangBulkedRemoteWorld extends RemoteWorld {
@@ -187,6 +192,11 @@ public abstract class RemoteWorld implements World {
final GraphTraversalSource g = super.getGraphTraversalSource(graphData);
return g.with("language", "groovy-test");
}
+
+ @Override
+ public boolean useParametersLiterally() {
+ return false;
+ }
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -211,6 +221,11 @@ public abstract class RemoteWorld implements World {
final GraphTraversalSource g = super.getGraphTraversalSource(graphData);
return g.with("language", "gremlin-lang");
}
+
+ @Override
+ public boolean useParametersLiterally() {
+ return false;
+ }
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/HttpDriverIntegrateTest.java b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/HttpDriverIntegrateTest.java
index 87a1ed5476..cff1068097 100644
--- a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/HttpDriverIntegrateTest.java
+++ b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/HttpDriverIntegrateTest.java
@@ -88,9 +88,8 @@ public class HttpDriverIntegrateTest extends AbstractGremlinServerIntegrationTes
final Cluster cluster = TestClientFactory.build().create();
final Client client = cluster.connect();
try {
- final RequestOptions ro = RequestOptions.build().language("gremlin-lang").
- addParameter("x", "Good bye, world!").create();
- client.submit("g.inject(1).fail(x)", ro).all().get();
+ final RequestOptions ro = RequestOptions.build().language("gremlin-lang").create();
+ client.submit("g.inject(1).fail('Good bye, world!')", ro).all().get();
fail("should throw exception");
} catch (Exception ex) {
final Throwable inner = ExceptionHelper.getRootCause(ex);
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/features/StepDefinition.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/features/StepDefinition.java
index a282f69759..ae19a1c613 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/features/StepDefinition.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/features/StepDefinition.java
@@ -122,6 +122,12 @@ public final class StepDefinition {
final String listItems = Stream.of(items).map(String::trim).map(x -> convertToString(x)).collect(Collectors.joining(","));
return String.format("[%s]", listItems);
}));
+ add(Pair.with(Pattern.compile("s\\[\\]"), s -> "{}"));
+ add(Pair.with(Pattern.compile("s\\[(.*)\\]"), s -> {
+ final String[] items = s.split(",");
+ final String setItems = Stream.of(items).map(String::trim).map(x -> convertToString(x)).collect(Collectors.joining(","));
+ return String.format("{%s}", setItems);
+ }));
add(Pair.with(Pattern.compile("d\\[(NaN)\\]"), s -> "NaN"));
add(Pair.with(Pattern.compile("d\\[(Infinity)\\]"), s -> "Infinity"));
add(Pair.with(Pattern.compile("d\\[(-Infinity)\\]"), s -> "-Infinity"));
@@ -161,12 +167,6 @@ public final class StepDefinition {
add(Pair.with(Pattern.compile("p\\[(.*)\\]"), s -> {
throw new AssumptionViolatedException("This test uses a Path as a parameter which is not supported by gremlin-language");
}));
- add(Pair.with(Pattern.compile("s\\[\\]"), s -> {
- throw new AssumptionViolatedException("This test uses a empty Set as a parameter which is not supported by gremlin-language");
- }));
- add(Pair.with(Pattern.compile("s\\[(.*)\\]"), s -> {
- throw new AssumptionViolatedException("This test uses a Set as a parameter which is not supported by gremlin-language");
- }));
add(Pair.with(Pattern.compile("(null)"), s -> "null"));
add(Pair.with(Pattern.compile("(true)"), s -> "true"));
add(Pair.with(Pattern.compile("(false)"), s -> "false"));
diff --git a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/filter/Has.feature b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/filter/Has.feature
index 8a1db09a05..42059bccdb 100644
--- a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/filter/Has.feature
+++ b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/filter/Has.feature
@@ -64,6 +64,19 @@ Feature: Step - has()
| result |
| v[marko] |
+ Scenario: g_VX1X_hasXname_markovarX
+ Given the modern graph
+ And using the parameter vid1 defined as "v[marko].id"
+ And using the parameter xx1 defined as "marko"
+ And the traversal of
+ """
+ g.V(vid1).has("name", xx1)
+ """
+ When iterated to list
+ Then the result should be unordered
+ | result |
+ | v[marko] |
+
Scenario: g_VX2X_hasXname_markoX
Given the modern graph
And using the parameter vid1 defined as "v[vadas].id"
diff --git a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/filter/HasId.feature b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/filter/HasId.feature
index cc85a5c4fe..2cb6992510 100644
--- a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/filter/HasId.feature
+++ b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/filter/HasId.feature
@@ -155,6 +155,7 @@ Feature: Step - hasId()
| v[josh] |
| v[josh] |
| v[peter] |
+
Scenario: g_VX1X_out_hasIdX2X
Given the modern graph
And using the parameter vid1 defined as "v[marko].id"
diff --git a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/filter/Is.feature b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/filter/Is.feature
index a1ca6ffd7b..600dc91778 100644
--- a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/filter/Is.feature
+++ b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/filter/Is.feature
@@ -29,6 +29,18 @@ Feature: Step - is()
| result |
| d[32].i |
+ Scenario: g_V_valuesXageX_isX32varX
+ Given the modern graph
+ And using the parameter xx1 defined as "d[32].i"
+ And the traversal of
+ """
+ g.V().values("age").is(xx1)
+ """
+ When iterated to list
+ Then the result should be unordered
+ | result |
+ | d[32].i |
+
Scenario: g_V_valuesXageX_isXlte_30X
Given the modern graph
And the traversal of
@@ -41,6 +53,19 @@ Feature: Step - is()
| d[27].i |
| d[29].i |
+ Scenario: g_V_valuesXageX_isXlte_30varX
+ Given the modern graph
+ And using the parameter xx1 defined as "d[30].i"
+ And the traversal of
+ """
+ g.V().values("age").is(P.lte(xx1))
+ """
+ When iterated to list
+ Then the result should be unordered
+ | result |
+ | d[27].i |
+ | d[29].i |
+
Scenario: g_V_valuesXageX_isXgte_29X_isXlt_34X
Given the modern graph
And the traversal of
@@ -53,6 +78,20 @@ Feature: Step - is()
| d[29].i |
| d[32].i |
+ Scenario: g_V_valuesXageX_isXgte_29vaarX_isXlt_34varX
+ Given the modern graph
+ And using the parameter xx1 defined as "d[29].i"
+ And using the parameter xx2 defined as "d[34].i"
+ And the traversal of
+ """
+ g.V().values("age").is(P.gte(xx1)).is(P.lt(xx2))
+ """
+ When iterated to list
+ Then the result should be unordered
+ | result |
+ | d[29].i |
+ | d[32].i |
+
Scenario: g_V_whereXinXcreatedX_count_isX1XX_valuesXnameX
Given the modern graph
And the traversal of
diff --git a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/filter/Where.feature b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/filter/Where.feature
index 160951b4bd..1d2287a5e2 100644
--- a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/filter/Where.feature
+++ b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/filter/Where.feature
@@ -92,11 +92,10 @@ Feature: Step - where()
Scenario: g_withSideEffectXa_josh_peterX_VX1X_outXcreatedX_inXcreatedX_name_whereXwithinXaXX
Given the modern graph
- And using the parameter xx1 defined as "l[josh,peter]"
And using the parameter vid1 defined as "v[marko].id"
And the traversal of
"""
- g.withSideEffect("a", xx1).V(vid1).out("created").in("created").values("name").where(P.within("a"))
+ g.withSideEffect("a", ["josh","peter"]).V(vid1).out("created").in("created").values("name").where(P.within("a"))
"""
When iterated to list
Then the result should be unordered
diff --git a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/AddEdge.feature b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/AddEdge.feature
index 6261baa347..b2cd709619 100644
--- a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/AddEdge.feature
+++ b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/AddEdge.feature
@@ -387,6 +387,37 @@ Feature: Step - addE()
And the graph should return 3 for count of "g.V(v1).outE(\"knows\")"
And the graph should return 1 for count of "g.V(v1).out(\"knows\").has(\"name\",\"peter\")"
+ Scenario: g_addEXknowsvarX_fromXaX_toXbX_propertyXweight_0_1X
+ Given the empty graph
+ And the graph initializer of
+ """
+ g.addV("person").property("name", "marko").property("age", 29).as("marko").
+ addV("person").property("name", "vadas").property("age", 27).as("vadas").
+ addV("software").property("name", "lop").property("lang", "java").as("lop").
+ addV("person").property("name","josh").property("age", 32).as("josh").
+ addV("software").property("name", "ripple").property("lang", "java").as("ripple").
+ addV("person").property("name", "peter").property("age", 35).as('peter').
+ addE("knows").from("marko").to("vadas").property("weight", 0.5d).
+ addE("knows").from("marko").to("josh").property("weight", 1.0d).
+ addE("created").from("marko").to("lop").property("weight", 0.4d).
+ addE("created").from("josh").to("ripple").property("weight", 1.0d).
+ addE("created").from("josh").to("lop").property("weight", 0.4d).
+ addE("created").from("peter").to("lop").property("weight", 0.2d)
+ """
+ And using the parameter v1 defined as "v[marko]"
+ And using the parameter v6 defined as "v[peter]"
+ And using the parameter xx1 defined as "knows"
+ And using the parameter xx2 defined as "d[0.1].d"
+ And the traversal of
+ """
+ g.addE(xx1).from(v1).to(v6).property("weight", xx2)
+ """
+ When iterated to list
+ Then the result should have a count of 1
+ And the graph should return 7 for count of "g.E()"
+ And the graph should return 3 for count of "g.V(v1).outE(\"knows\")"
+ And the graph should return 1 for count of "g.V(v1).out(\"knows\").has(\"name\",\"peter\")"
+
Scenario: g_VXaX_addEXknowsX_toXbX_propertyXweight_0_1X
Given the empty graph
And the graph initializer of
@@ -431,4 +462,21 @@ Feature: Step - addE()
"""
When iterated to list
Then the result should have a count of 1
+ And the graph should return 1 for count of "g.E().has(\"knows\",\"weight\",null)"
+
+ @AllowNullPropertyValues
+ Scenario: g_addEXknowsvarXpropertyXweight_nullXfromXV_hasXname_markoXX_toXV_hasXname_vadasXX
+ Given the empty graph
+ And the graph initializer of
+ """
+ g.addV("person").property("name", "marko").property("age", 29).
+ addV("person").property("name", "vadas").property("age", 27)
+ """
+ And using the parameter xx1 defined as "knows"
+ And the traversal of
+ """
+ g.addE(xx1).property("weight", null).from(V().has("name","marko")).to(V().has("name","vadas"))
+ """
+ When iterated to list
+ Then the result should have a count of 1
And the graph should return 1 for count of "g.E().has(\"knows\",\"weight\",null)"
\ No newline at end of file
diff --git a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/AddVertex.feature b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/AddVertex.feature
index 004794b4a0..ee8e7c4552 100644
--- a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/AddVertex.feature
+++ b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/AddVertex.feature
@@ -69,6 +69,33 @@ Feature: Step - addV()
Then the result should have a count of 6
And the graph should return 6 for count of "g.V().has(\"animal\",\"age\",0)"
+ Scenario: g_V_addVXanimalvarX_propertyXage_0varX
+ Given the empty graph
+ And the graph initializer of
+ """
+ g.addV("person").property("name", "marko").property("age", 29).as("marko").
+ addV("person").property("name", "vadas").property("age", 27).as("vadas").
+ addV("software").property("name", "lop").property("lang", "java").as("lop").
+ addV("person").property("name","josh").property("age", 32).as("josh").
+ addV("software").property("name", "ripple").property("lang", "java").as("ripple").
+ addV("person").property("name", "peter").property("age", 35).as('peter').
+ addE("knows").from("marko").to("vadas").property("weight", 0.5d).
+ addE("knows").from("marko").to("josh").property("weight", 1.0d).
+ addE("created").from("marko").to("lop").property("weight", 0.4d).
+ addE("created").from("josh").to("ripple").property("weight", 1.0d).
+ addE("created").from("josh").to("lop").property("weight", 0.4d).
+ addE("created").from("peter").to("lop").property("weight", 0.2d)
+ """
+ And using the parameter xx1 defined as "animal"
+ And using the parameter xx2 defined as "d[0].i"
+ And the traversal of
+ """
+ g.V().addV(xx1).property("age", xx2)
+ """
+ When iterated to list
+ Then the result should have a count of 6
+ And the graph should return 6 for count of "g.V().has(\"animal\",\"age\",0)"
+
Scenario: g_addVXpersonX_propertyXname_stephenX
Given the empty graph
And the graph initializer of
@@ -94,6 +121,33 @@ Feature: Step - addV()
Then the result should have a count of 1
And the graph should return 1 for count of "g.V().has(\"person\",\"name\",\"stephen\")"
+ Scenario: g_addVXpersonvarX_propertyXname_stephenvarX
+ Given the empty graph
+ And the graph initializer of
+ """
+ g.addV("person").property("name", "marko").property("age", 29).as("marko").
+ addV("person").property("name", "vadas").property("age", 27).as("vadas").
+ addV("software").property("name", "lop").property("lang", "java").as("lop").
+ addV("person").property("name","josh").property("age", 32).as("josh").
+ addV("software").property("name", "ripple").property("lang", "java").as("ripple").
+ addV("person").property("name", "peter").property("age", 35).as('peter').
+ addE("knows").from("marko").to("vadas").property("weight", 0.5d).
+ addE("knows").from("marko").to("josh").property("weight", 1.0d).
+ addE("created").from("marko").to("lop").property("weight", 0.4d).
+ addE("created").from("josh").to("ripple").property("weight", 1.0d).
+ addE("created").from("josh").to("lop").property("weight", 0.4d).
+ addE("created").from("peter").to("lop").property("weight", 0.2d)
+ """
+ And using the parameter xx1 defined as "person"
+ And using the parameter xx2 defined as "stephen"
+ And the traversal of
+ """
+ g.addV(xx1).property("name", xx2)
+ """
+ When iterated to list
+ Then the result should have a count of 1
+ And the graph should return 1 for count of "g.V().has(\"person\",\"name\",\"stephen\")"
+
Scenario: g_V_hasLabelXpersonX_propertyXname_nullX
Given the empty graph
And the graph initializer of
@@ -428,6 +482,40 @@ Feature: Step - addV()
Then the result should have a count of 1
And the graph should return 1 for count of "g.V().hasLabel(\"person\")"
+ Scenario: g_addV_propertyXlabel_personvarX
+ Given the empty graph
+ And using the parameter xx1 defined as "person"
+ And the traversal of
+ """
+ g.addV().property(T.label, xx1)
+ """
+ When iterated to list
+ Then the result should have a count of 1
+ And the graph should return 1 for count of "g.V().hasLabel(\"person\")"
+
+ @UserSuppliedVertexIds
+ Scenario: g_addV_propertyXid_1X
+ Given the empty graph
+ And the traversal of
+ """
+ g.addV().property(T.id, 1)
+ """
+ When iterated to list
+ Then the result should have a count of 1
+ And the graph should return 1 for count of "g.V().hasId(\"1\")"
+
+ @UserSuppliedVertexIds
+ Scenario: g_addV_propertyXidvar_1varX
+ Given the empty graph
+ And using the parameter xx1 defined as "1"
+ And the traversal of
+ """
+ g.addV().property(T.id, xx1)
+ """
+ When iterated to list
+ Then the result should have a count of 1
+ And the graph should return 1 for count of "g.V().hasId(\"1\")"
+
Scenario: g_addV_propertyXmapX
Given the empty graph
And the traversal of
diff --git a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/Call.feature b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/Call.feature
index 0c44d7e952..d5f9366c40 100644
--- a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/Call.feature
+++ b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/Call.feature
@@ -87,6 +87,7 @@ Feature: Step - call()
| result |
| tinker.search |
+# The parameterized xx1 map will fail, but just passing in the map will pass, need to check
Scenario: g_callXlist_map_traversalX
Given the empty graph
And using the parameter xx1 defined as "m[{\"x\": \"y\"}]"
diff --git a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/MergeEdge.feature b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/MergeEdge.feature
index ae252145b5..5c085da304 100644
--- a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/MergeEdge.feature
+++ b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/MergeEdge.feature
@@ -179,6 +179,22 @@ Feature: Step - mergeE()
And the graph should return 1 for count of "g.E()"
And the graph should return 1 for count of "g.V()"
+ @GremlinLangScriptOnly
+ Scenario: g_V_mergeE_inlineXemptyX_optionXonCreate_nullX
+ Given the empty graph
+ And the graph initializer of
+ """
+ g.addV("person").property("name", "marko").property("age", 29)
+ """
+ And the traversal of
+ """
+ g.V().as("v").mergeE([T.label:"self",OUT:Merge.outV,IN:Merge.inV]).option(Merge.onCreate,null).option(Merge.outV,select("v")).option(Merge.inV,select("v"))
+ """
+ When iterated to list
+ Then the result should have a count of 1
+ And the graph should return 1 for count of "g.E()"
+ And the graph should return 1 for count of "g.V()"
+
Scenario: g_mergeEXemptyX_exists
Given the empty graph
And the graph initializer of
@@ -225,6 +241,23 @@ Feature: Step - mergeE()
And the graph should return 2 for count of "g.E()"
And the graph should return 2 for count of "g.V()"
+ Scenario: g_V_mergeE_inlineXemptyX_two_exist
+ Given the empty graph
+ And the graph initializer of
+ """
+ g.addV("person").property("name", "marko").property("age", 29).
+ addV("person").property("name", "vadas").property("age", 27)
+ """
+ And the traversal of
+ """
+ g.V().as("v").mergeE([T.label:"self",OUT:Merge.outV,IN:Merge.inV]).option(Merge.outV,select("v")).option(Merge.inV,select("v"))
+ """
+ When iterated to list
+ Then the result should have a count of 2
+ And the graph should return 2 for count of "g.E()"
+ And the graph should return 2 for count of "g.V()"
+
+ @GremlinLangScriptOnly
Scenario: g_mergeEXnullX
Given the empty graph
And the graph initializer of
@@ -656,6 +689,24 @@ Feature: Step - mergeE()
And the graph should return 2 for count of "g.V()"
And the graph should return 1 for count of "g.V().has(\"name\",\"marko\").out(\"knows\").has(\"name\",\"vadas\")"
+ Scenario: g_mergeE_inline_with_outVinV_options_map
+ Given the empty graph
+ And the graph initializer of
+ """
+ g.addV("person").property("name", "marko").
+ addV("person").property("name", "vadas")
+ """
+ And using the parameter xx1 defined as "m[{\"t[id]\": \"v[marko].id\"}]"
+ And using the parameter xx2 defined as "m[{\"t[id]\": \"v[vadas].id\"}]"
+ And the traversal of
+ """
+ g.mergeE([OUT:Merge.outV,IN:Merge.inV,T.label:"knows"]).option(outV, xx1).option(inV, xx2)
+ """
+ When iterated to list
+ Then the result should have a count of 1
+ And the graph should return 2 for count of "g.V()"
+ And the graph should return 1 for count of "g.V().has(\"name\",\"marko\").out(\"knows\").has(\"name\",\"vadas\")"
+
Scenario: g_mergeE_with_outVinV_options_select
Given the empty graph
And the graph initializer of
@@ -675,6 +726,24 @@ Feature: Step - mergeE()
And the graph should return 2 for count of "g.V()"
And the graph should return 1 for count of "g.V().has(\"name\",\"marko\").out(\"knows\").has(\"name\",\"vadas\")"
+ Scenario: g_mergeE_inline_with_outVinV_options_select
+ Given the empty graph
+ And the graph initializer of
+ """
+ g.addV("person").property("name", "marko").
+ addV("person").property("name", "vadas")
+ """
+ And using the parameter vid1 defined as "v[marko].id"
+ And using the parameter vid2 defined as "v[vadas].id"
+ And the traversal of
+ """
+ g.V(vid1).as("x").V(vid2).as("y").mergeE([OUT:Merge.outV,IN:Merge.inV,T.label:"knows"]).option(outV, select("x")).option(inV, select("y"))
+ """
+ When iterated to list
+ Then the result should have a count of 1
+ And the graph should return 2 for count of "g.V()"
+ And the graph should return 1 for count of "g.V().has(\"name\",\"marko\").out(\"knows\").has(\"name\",\"vadas\")"
+
# onCreate inherits from merge and can specify an eid
@UserSuppliedEdgeIds
Scenario: g_mergeE_with_eid_specified_and_inheritance_1
diff --git a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/Vertex.feature b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/Vertex.feature
index 3f8912211b..1fc2854c84 100644
--- a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/Vertex.feature
+++ b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/Vertex.feature
@@ -186,6 +186,20 @@ Feature: Step - V(), out(), in(), both(), inE(), outE(), bothE()
| e[josh-created->lop] |
| e[josh-created->ripple] |
+ Scenario: g_VX4X_bothEXcreatedvarX
+ Given the modern graph
+ And using the parameter vid4 defined as "v[josh].id"
+ And using the parameter xx1 defined as "created"
+ And the traversal of
+ """
+ g.V(vid4).bothE(xx1)
+ """
+ When iterated to list
+ Then the result should be unordered
+ | result |
+ | e[josh-created->lop] |
+ | e[josh-created->ripple] |
+
Scenario: g_VX4X_bothE
Given the modern graph
And using the parameter vid4 defined as "v[josh].id"
@@ -272,6 +286,22 @@ Feature: Step - V(), out(), in(), both(), inE(), outE(), bothE()
| v[josh] |
| v[lop] |
+ Scenario: g_VX1X_outXknowsvar_createdvarX
+ Given the modern graph
+ And using the parameter vid1 defined as "v[marko].id"
+ And using the parameter xx2 defined as "knows"
+ And using the parameter xx3 defined as "created"
+ And the traversal of
+ """
+ g.V(vid1).out(xx2,xx3)
+ """
+ When iterated to list
+ Then the result should be unordered
+ | result |
+ | v[vadas] |
+ | v[josh] |
+ | v[lop] |
+
Scenario: g_V_out_out
Given the modern graph
And the traversal of
diff --git a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/sideEffect/Inject.feature b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/sideEffect/Inject.feature
index 762f9cff5d..678705d19b 100644
--- a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/sideEffect/Inject.feature
+++ b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/sideEffect/Inject.feature
@@ -219,6 +219,25 @@ Feature: Step - inject()
| d[1].i |
| d[3].i |
+ @GraphComputerVerificationInjectionNotSupported
+ Scenario: g_injectX1var_3varX_injectX100var_300varX
+ Given the modern graph
+ And using the parameter xx1 defined as "d[1].i"
+ And using the parameter xx2 defined as "d[3].i"
+ And using the parameter xx3 defined as "d[100].i"
+ And using the parameter xx4 defined as "d[300].i"
+ And the traversal of
+ """
+ g.inject(xx1, xx2).inject(xx3, xx4)
+ """
+ When iterated to list
+ Then the result should be unordered
+ | result |
+ | d[100].i |
+ | d[300].i |
+ | d[1].i |
+ | d[3].i |
+
@GraphComputerVerificationInjectionNotSupported
Scenario: g_injectX1_3_100_300X_list
Given the modern graph
@@ -231,7 +250,20 @@ Feature: Step - inject()
| result |
| l[d[1].i,d[3].i,d[100].i,d[300].i] |
- @GraphComputerVerificationInjectionNotSupported
+ @GraphComputerVerificationInjectionNotSupported @GremlinLangScriptOnly
+ Scenario: g_injectX1_3_100_300X_listvar
+ Given the modern graph
+ And using the parameter xx1 defined as "l[d[1].i,d[3].i,d[100].i,d[300].i]"
+ And the traversal of
+ """
+ g.inject(xx1)
+ """
+ When iterated to list
+ Then the result should be unordered
+ | result |
+ | l[d[1].i,d[3].i,d[100].i,d[300].i] |
+
+ @GraphComputerVerificationInjectionNotSupported @GremlinLangScriptOnly
Scenario: g_injectX1_3_100_300X_set
Given the modern graph
And the traversal of
@@ -243,7 +275,20 @@ Feature: Step - inject()
| result |
| s[d[100].i,d[300].i,d[1].i,d[3].i] |
- @GraphComputerVerificationInjectionNotSupported
+ @GraphComputerVerificationInjectionNotSupported @GremlinLangScriptOnly
+ Scenario: g_injectX1_3_100_300X_setvar
+ Given the modern graph
+ And using the parameter xx1 defined as "s[d[100].i,d[300].i,d[1].i,d[3].i]"
+ And the traversal of
+ """
+ g.inject(xx1)
+ """
+ When iterated to list
+ Then the result should be unordered
+ | result |
+ | s[d[100].i,d[300].i,d[1].i,d[3].i] |
+
+ @GraphComputerVerificationInjectionNotSupported @GremlinLangScriptOnly
Scenario: g_injectX1_1X_set
Given the modern graph
And the traversal of
@@ -253,4 +298,30 @@ Feature: Step - inject()
When iterated to list
Then the result should be unordered
| result |
- | s[d[1].i] |
\ No newline at end of file
+ | s[d[1].i] |
+
+ @GraphComputerVerificationInjectionNotSupported @GremlinLangScriptOnly
+ Scenario: g_injectX1_1X_setvar
+ Given the modern graph
+ And using the parameter xx1 defined as "s[d[1].i,d[1].i]"
+ And the traversal of
+ """
+ g.inject(xx1)
+ """
+ When iterated to list
+ Then the result should be unordered
+ | result |
+ | s[d[1].i] |
+
+ @GraphComputerVerificationInjectionNotSupported @GremlinLangScriptOnly
+ Scenario: g_injectX_set
+ Given the modern graph
+ And using the parameter xx1 defined as "s[]"
+ And the traversal of
+ """
+ g.inject(xx1)
+ """
+ When iterated to list
+ Then the result should be unordered
+ | result |
+ | s[] |
\ No newline at end of file
diff --git a/gremlin-tools/gremlin-benchmark/src/main/java/org/apache/tinkerpop/gremlin/process/TraversalConstructionBenchmark.java b/gremlin-tools/gremlin-benchmark/src/main/java/org/apache/tinkerpop/gremlin/process/TraversalConstructionBenchmark.java
index 6f59f774ba..14b638de54 100644
--- a/gremlin-tools/gremlin-benchmark/src/main/java/org/apache/tinkerpop/gremlin/process/TraversalConstructionBenchmark.java
+++ b/gremlin-tools/gremlin-benchmark/src/main/java/org/apache/tinkerpop/gremlin/process/TraversalConstructionBenchmark.java
@@ -19,9 +19,9 @@
package org.apache.tinkerpop.gremlin.process;
import org.apache.tinkerpop.benchmark.util.AbstractGraphBenchmark;
-import org.apache.tinkerpop.gremlin.process.traversal.GremlinLang;
import org.apache.tinkerpop.gremlin.process.traversal.P;
import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal;
+import org.apache.tinkerpop.gremlin.process.traversal.step.GValue;
import org.openjdk.jmh.annotations.Benchmark;
import java.util.HashMap;
@@ -72,8 +72,8 @@ public class TraversalConstructionBenchmark extends AbstractGraphBenchmark {
}
@Benchmark
- public GraphTraversal constructMediumWithBindings() throws Exception {
- return g.V().has("person","name", GremlinLang.Parameter.var("x","marko")).
+ public GraphTraversal constructMediumWithBindings() {
+ return g.V().has("person","name", GValue.of("x","marko")).
project("user","knows","created").
by(project("name","age").by("name").by("age")).
by(out("knows").project("name","age").by("name").by("age")).
diff --git a/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/TinkerGraphFeatureTest.java b/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/TinkerGraphFeatureTest.java
index 8f03a7e991..6df6140206 100644
--- a/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/TinkerGraphFeatureTest.java
+++ b/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/TinkerGraphFeatureTest.java
@@ -34,6 +34,7 @@ import org.junit.runner.RunWith;
glue = { "org.apache.tinkerpop.gremlin.features" },
objectFactory = TinkerGraphFeatureTest.TinkerGraphGuiceFactory.class,
features = { "classpath:/org/apache/tinkerpop/gremlin/test/features" },
+// name= {"g_VX1X_outXknowsvar_createdvarX"},
plugin = {"progress", "junit:target/cucumber.xml"})
public class TinkerGraphFeatureTest {
(tinkerpop) 01/05: TINKERPOP-2959 Allow parameters to work for primitives
Posted by co...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
colegreer pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/tinkerpop.git
commit 8ebcc28f3cb1925c8af72c58baa1d15dd6cbfcc1
Author: Stephen Mallette <st...@amazon.com>
AuthorDate: Fri Jul 12 10:48:20 2024 -0400
TINKERPOP-2959 Allow parameters to work for primitives
---
.../gremlin/jsr223/GremlinLangScriptEngine.java | 17 +-
.../gremlin/jsr223/VariableResolverCustomizer.java | 40 ++
.../gremlin/jsr223/VariableResolverPlugin.java | 95 +++
.../grammar/DefaultGremlinBaseVisitor.java | 16 +-
.../language/grammar/GenericLiteralVisitor.java | 14 +
.../language/grammar/TraversalMethodVisitor.java | 191 ++++--
.../grammar/TraversalSourceSpawnMethodVisitor.java | 29 +-
.../gremlin/language/grammar/VariableResolver.java | 37 +-
.../translator/DotNetTranslateVisitor.java | 62 +-
.../translator/GroovyTranslateVisitor.java | 31 +-
.../language/translator/TranslateVisitor.java | 6 +-
.../tinkerpop/gremlin/process/traversal/P.java | 14 +-
.../gremlin/process/traversal/SackFunctions.java | 5 +-
.../traversal/dsl/graph/GraphTraversal.java | 547 ++++++++++++++++--
.../traversal/dsl/graph/GraphTraversalSource.java | 61 ++
.../gremlin/process/traversal/dsl/graph/__.java | 177 ++++++
.../traversal/lambda/ConstantTraversal.java | 15 +-
.../gremlin/process/traversal/step/GType.java | 103 ++++
.../gremlin/process/traversal/step/GValue.java | 443 ++++++++++++++
.../process/traversal/step/filter/CoinStep.java | 24 +-
.../process/traversal/step/map/AddEdgeStep.java | 15 +-
.../process/traversal/step/map/AddVertexStep.java | 5 +
.../process/traversal/step/map/CallStep.java | 36 +-
.../process/traversal/step/map/CombineStep.java | 15 +-
.../process/traversal/step/map/ConjoinStep.java | 19 +-
.../process/traversal/step/map/ConstantStep.java | 18 +-
.../process/traversal/step/map/DifferenceStep.java | 20 +-
.../process/traversal/step/map/DisjunctStep.java | 14 +-
.../process/traversal/step/map/GraphStep.java | 87 ++-
.../process/traversal/step/map/IntersectStep.java | 15 +-
.../process/traversal/step/map/MergeEdgeStep.java | 5 +
.../traversal/step/map/MergeElementStep.java | 14 +-
.../process/traversal/step/map/MergeStep.java | 23 +-
.../traversal/step/map/MergeVertexStep.java | 5 +
.../process/traversal/step/map/ProductStep.java | 19 +-
.../process/traversal/step/map/VertexStep.java | 27 +-
.../traversal/step/sideEffect/InjectStep.java | 23 +-
.../process/traversal/step/util/AbstractStep.java | 2 +-
.../process/traversal/step/util/HasContainer.java | 6 +-
.../process/traversal/step/util/Parameters.java | 21 +-
.../strategy/decoration/ElementIdStrategy.java | 7 +-
.../strategy/decoration/SideEffectStrategy.java | 7 +-
.../strategy/decoration/SubgraphStrategy.java | 2 +-
.../optimization/AdjacentToIncidentStrategy.java | 2 +-
.../optimization/IncidentToAdjacentStrategy.java | 2 +-
.../optimization/InlineFilterStrategy.java | 19 +-
.../process/traversal/util/ListFunction.java | 16 +-
.../gremlin/structure/VertexProperty.java | 3 -
.../gremlin/structure/io/gryo/GryoVersion.java | 12 +-
.../tinkerpop/gremlin/util/CollectionUtil.java | 44 +-
.../gremlin/jsr223/VariableResolverPluginTest.java | 117 ++++
.../language/grammar/ArgumentVisitorTest.java | 92 ++-
.../language/grammar/GremlinQueryParserTest.java | 8 +-
.../language/translator/GremlinTranslatorTest.java | 58 +-
.../gremlin/process/traversal/step/GTypeTest.java | 77 +++
.../gremlin/process/traversal/step/GValueTest.java | 641 +++++++++++++++++++++
.../traversal/step/map/ConjoinStepTest.java | 2 +-
.../traversal/step/util/ParametersTest.java | 11 +
.../tinkerpop/gremlin/util/CollectionUtilTest.java | 110 ++++
.../Gherkin/CommonSteps.cs | 7 -
.../Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs | 61 +-
gremlin-go/driver/cucumber/cucumberSteps_test.go | 15 +-
gremlin-go/driver/cucumber/gremlin.go | 15 +-
.../test/cucumber/feature-steps.js | 4 -
.../gremlin-javascript/test/cucumber/gremlin.js | 54 +-
gremlin-language/src/main/antlr4/Gremlin.g4 | 4 +-
.../src/main/python/radish/feature_steps.py | 11 -
gremlin-python/src/main/python/radish/gremlin.py | 54 +-
.../tinkerpop/gremlin/features/StepDefinition.java | 55 +-
.../apache/tinkerpop/gremlin/features/World.java | 9 +
.../gremlin/test/features/filter/Has.feature | 24 +
.../gremlin/test/features/filter/HasId.feature | 13 +-
.../gremlin/test/features/filter/HasLabel.feature | 28 +
.../gremlin/test/features/map/Conjoin.feature | 14 +-
.../gremlin/test/features/map/Edge.feature | 261 ++++++++-
.../gremlin/test/features/map/Vertex.feature | 248 +-------
.../traversal/step/sideEffect/Neo4jGraphStep.java | 4 +-
.../process/traversal/strategy/SparqlStrategy.java | 1 -
.../traversal/step/sideEffect/TinkerGraphStep.java | 14 +-
.../tinkerpop/gremlin/tinkergraph/TinkerWorld.java | 5 +
.../tinkergraph/structure/TinkerGraphPlayTest.java | 33 +-
81 files changed, 3773 insertions(+), 707 deletions(-)
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/GremlinLangScriptEngine.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/GremlinLangScriptEngine.java
index 440c27ad56..5528b280b1 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/GremlinLangScriptEngine.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/GremlinLangScriptEngine.java
@@ -31,7 +31,11 @@ import javax.script.ScriptException;
import javax.script.SimpleBindings;
import java.io.IOException;
import java.io.Reader;
+import java.util.Arrays;
+import java.util.List;
import java.util.Map;
+import java.util.Optional;
+import java.util.function.Function;
/**
* A {@link GremlinScriptEngine} implementation that evaluates Gremlin scripts using {@code gremlin-language}. As it
@@ -50,6 +54,8 @@ import java.util.Map;
public class GremlinLangScriptEngine extends AbstractScriptEngine implements GremlinScriptEngine {
private volatile GremlinScriptEngineFactory factory;
+ private final Function<Map<String, Object>, VariableResolver> variableResolverMaker;
+
/**
* Creates a new instance using no {@link Customizer}.
*/
@@ -58,6 +64,15 @@ public class GremlinLangScriptEngine extends AbstractScriptEngine implements Gre
}
public GremlinLangScriptEngine(final Customizer... customizers) {
+ final List<Customizer> listOfCustomizers = Arrays.asList(customizers);
+
+ // this ScriptEngine really only supports the VariableResolverCustomizer to configure the VariableResolver
+ // and can't configure it more than once. first one wins
+ final Optional<Customizer> opt = listOfCustomizers.stream().filter(c -> c instanceof VariableResolverCustomizer).findFirst();
+ variableResolverMaker = opt.isPresent() ?
+ ((VariableResolverCustomizer) opt.get()).getVariableResolverMaker() :
+ VariableResolver.DirectVariableResolver::new;
+
}
@Override
@@ -84,7 +99,7 @@ public class GremlinLangScriptEngine extends AbstractScriptEngine implements Gre
final Map<String, Object> m = context.getBindings(ScriptContext.ENGINE_SCOPE);
final GremlinAntlrToJava antlr = new GremlinAntlrToJava((GraphTraversalSource) o,
- new VariableResolver.DefaultVariableResolver(m));
+ variableResolverMaker.apply(m));
try {
return GremlinQueryParser.parse(script, antlr);
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/VariableResolverCustomizer.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/VariableResolverCustomizer.java
new file mode 100644
index 0000000000..1be1f3d448
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/VariableResolverCustomizer.java
@@ -0,0 +1,40 @@
+/*
+ * 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.jsr223;
+
+import org.apache.tinkerpop.gremlin.language.grammar.VariableResolver;
+
+import java.util.Map;
+import java.util.function.Function;
+
+/**
+ * Supplies a {@link VariableResolver} implementation to the {@link GremlinLangScriptEngine}. This {@link Customizer}
+ * is not relevant to any other {@link GremlinScriptEngine} implementation.
+ */
+public class VariableResolverCustomizer implements Customizer {
+ private final Function<Map<String,Object>, VariableResolver> variableResolverMaker;
+
+ public VariableResolverCustomizer(final Function<Map<String, Object>, VariableResolver> variableResolverMaker) {
+ this.variableResolverMaker = variableResolverMaker;
+ }
+
+ public Function<Map<String, Object>, VariableResolver> getVariableResolverMaker() {
+ return variableResolverMaker;
+ }
+}
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/VariableResolverPlugin.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/VariableResolverPlugin.java
new file mode 100644
index 0000000000..587f9666a1
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/VariableResolverPlugin.java
@@ -0,0 +1,95 @@
+/*
+ * 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.jsr223;
+
+import org.apache.tinkerpop.gremlin.language.grammar.VariableResolver;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.function.Function;
+
+/**
+ * A plugin that allows for the configuration of a {@link VariableResolver} implementation to be used by the
+ * {@link GremlinLangScriptEngine}. By default, it will use the {@link VariableResolver.DirectVariableResolver} which
+ * directly resolves variable name to a value from the binding in the script engine context. This is the most common
+ * usage relevant for most users and providers. Other options are reserved for more advanced use cases.
+ */
+public class VariableResolverPlugin extends AbstractGremlinPlugin {
+ private static final String NAME = "tinkerpop.variableResolver";
+
+ public static final Map<String, Function<Map<String, Object>, VariableResolver>> VARIABLE_RESOLVERS =
+ new HashMap<String, Function<Map<String, Object>, VariableResolver>>() {{
+ put(VariableResolver.DirectVariableResolver.class.getSimpleName(), VariableResolver.DirectVariableResolver::new);
+ put(VariableResolver.DefaultVariableResolver.class.getSimpleName(), VariableResolver.DefaultVariableResolver::new);
+ put(VariableResolver.NoVariableResolver.class.getSimpleName(), m -> VariableResolver.NoVariableResolver.instance());
+ put(VariableResolver.NullVariableResolver.class.getSimpleName(), m -> VariableResolver.NullVariableResolver.instance());
+ }};
+
+ private VariableResolverPlugin(final VariableResolverPlugin.Builder builder) {
+ super(NAME, new VariableResolverCustomizer(builder.variableResolverMaker));
+ }
+
+ /**
+ * Builds a set of static bindings.
+ */
+ public static VariableResolverPlugin.Builder build() {
+ return new VariableResolverPlugin.Builder();
+ }
+
+ public static final class Builder {
+
+ Function<Map<String,Object>, VariableResolver> variableResolverMaker = VariableResolver.DirectVariableResolver::new;
+
+ private Builder() {}
+
+ /**
+ * Sets the type of {@link VariableResolver} to use by specifying a simple class name associated with the
+ * inner classes in that interface or a fully qualified class name. The assumption is that implementations
+ * will allow a constructor that takes a {@code Map} which contains the bindings from the script engine context.
+ * Implementations are can then decide how to resolve variables in the script based on that {@code Map} or some
+ * other mechanism.
+ */
+ public VariableResolverPlugin.Builder resolver(final String resolverName) {
+ if (VARIABLE_RESOLVERS.containsKey(resolverName)) {
+ this.variableResolverMaker = VARIABLE_RESOLVERS.get(resolverName);
+ } else {
+ try {
+ // Assuming resolverName is a fully qualified class name if it's not in the simple name map
+ final Class<?> clazz = Class.forName(resolverName);
+ if (VariableResolver.class.isAssignableFrom(clazz)) {
+ this.variableResolverMaker = map -> {
+ try {
+ return (VariableResolver) clazz.getConstructor(Map.class).newInstance(map);
+ } catch (Exception e) {
+ throw new RuntimeException("Error instantiating VariableResolver", e);
+ }
+ };
+ }
+ } catch (ClassNotFoundException e) {
+ throw new RuntimeException("VariableResolver class not found: " + resolverName, e);
+ }
+ }
+ return this;
+ }
+
+ public VariableResolverPlugin create() {
+ return new VariableResolverPlugin(this);
+ }
+ }
+}
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/DefaultGremlinBaseVisitor.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/DefaultGremlinBaseVisitor.java
index 2cade8cac7..c7a255cd34 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/DefaultGremlinBaseVisitor.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/DefaultGremlinBaseVisitor.java
@@ -414,11 +414,11 @@ public class DefaultGremlinBaseVisitor<T> extends AbstractParseTreeVisitor<T> im
/**
* {@inheritDoc}
*/
- @Override public T visitTraversalMethod_from_Traversal(final GremlinParser.TraversalMethod_from_TraversalContext ctx) { notImplemented(ctx); return null; }
+ @Override public T visitTraversalMethod_from_Vertex(final GremlinParser.TraversalMethod_from_VertexContext ctx) { notImplemented(ctx); return null; }
/**
* {@inheritDoc}
*/
- @Override public T visitTraversalMethod_from_Vertex(final GremlinParser.TraversalMethod_from_VertexContext ctx) { notImplemented(ctx); return null; }
+ @Override public T visitTraversalMethod_from_Traversal(final GremlinParser.TraversalMethod_from_TraversalContext ctx) { notImplemented(ctx); return null; }
/**
* {@inheritDoc}
*/
@@ -631,6 +631,10 @@ public class DefaultGremlinBaseVisitor<T> extends AbstractParseTreeVisitor<T> im
* {@inheritDoc}
*/
@Override public T visitTraversalMethod_option_Traversal(final GremlinParser.TraversalMethod_option_TraversalContext ctx) { notImplemented(ctx); return null; }
+ /**
+ * {@inheritDoc}
+ */
+ @Override public T visitTraversalMethod_option_Merge_Traversal(final GremlinParser.TraversalMethod_option_Merge_TraversalContext ctx) { notImplemented(ctx); return null; }
/**
* {@inheritDoc}
*/
@@ -854,11 +858,11 @@ public class DefaultGremlinBaseVisitor<T> extends AbstractParseTreeVisitor<T> im
/**
* {@inheritDoc}
*/
- @Override public T visitTraversalMethod_to_Traversal(final GremlinParser.TraversalMethod_to_TraversalContext ctx) { notImplemented(ctx); return null; }
+ @Override public T visitTraversalMethod_to_Vertex(final GremlinParser.TraversalMethod_to_VertexContext ctx) { notImplemented(ctx); return null; }
/**
* {@inheritDoc}
*/
- @Override public T visitTraversalMethod_to_Vertex(final GremlinParser.TraversalMethod_to_VertexContext ctx) { notImplemented(ctx); return null; }
+ @Override public T visitTraversalMethod_to_Traversal(final GremlinParser.TraversalMethod_to_TraversalContext ctx) { notImplemented(ctx); return null; }
/**
* {@inheritDoc}
*/
@@ -1395,10 +1399,6 @@ public class DefaultGremlinBaseVisitor<T> extends AbstractParseTreeVisitor<T> im
* {@inheritDoc}
*/
@Override public T visitTraversalMethod_option_Merge_Map(final GremlinParser.TraversalMethod_option_Merge_MapContext ctx) { notImplemented(ctx); return null; }
- /**
- * {@inheritDoc}
- */
- @Override public T visitTraversalMethod_option_Merge_Traversal(final GremlinParser.TraversalMethod_option_Merge_TraversalContext ctx) { notImplemented(ctx); return null; }
/**
* {@inheritDoc}
*/
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/GenericLiteralVisitor.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/GenericLiteralVisitor.java
index ced6c832d1..fb124ec910 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/GenericLiteralVisitor.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/GenericLiteralVisitor.java
@@ -658,4 +658,18 @@ public class GenericLiteralVisitor extends DefaultGremlinBaseVisitor<Object> {
else
return StringEscapeUtils.unescapeJava(stripQuotes(ctx.getText()));
}
+
+ @Override
+ public Object[] visitStringLiteralVarargs(final GremlinParser.StringLiteralVarargsContext ctx) {
+ if (ctx == null) {
+ return new Object[0];
+ }
+ return ctx.children
+ .stream()
+ .filter(Objects::nonNull)
+ .filter(p -> p instanceof GremlinParser.StringNullableArgumentContext)
+ .map(p -> (GremlinParser.StringNullableArgumentContext) p)
+ .map(antlr.argumentVisitor::visitStringNullableArgument)
+ .toArray(Object[]::new);
+ }
}
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalMethodVisitor.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalMethodVisitor.java
index c4437d9f75..1d107e6a88 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalMethodVisitor.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalMethodVisitor.java
@@ -27,16 +27,18 @@ import org.apache.tinkerpop.gremlin.process.traversal.SackFunctions;
import org.apache.tinkerpop.gremlin.process.traversal.Scope;
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.step.GType;
+import org.apache.tinkerpop.gremlin.process.traversal.step.GValue;
+import org.apache.tinkerpop.gremlin.structure.Vertex;
import org.apache.tinkerpop.gremlin.structure.Column;
import org.apache.tinkerpop.gremlin.structure.Direction;
import org.apache.tinkerpop.gremlin.structure.T;
import org.apache.tinkerpop.gremlin.structure.VertexProperty.Cardinality;
+import java.util.Arrays;
import java.util.Map;
import java.util.function.BiFunction;
-import static org.apache.tinkerpop.gremlin.process.traversal.SackFunctions.Barrier.normSack;
-
/**
* Specific case of TraversalRootVisitor where all TraversalMethods returns
* a GraphTraversal object.
@@ -45,11 +47,11 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
/**
* This object is used to append the traversal methods.
*/
- private final GraphTraversal graphTraversal;
+ private final GraphTraversal.Admin graphTraversal;
public TraversalMethodVisitor(final GremlinAntlrToJava antlr, final GraphTraversal graphTraversal) {
super(antlr, graphTraversal);
- this.graphTraversal = graphTraversal;
+ this.graphTraversal = graphTraversal.asAdmin();
}
/**
@@ -97,7 +99,11 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
*/
@Override
public GraphTraversal visitTraversalMethod_mergeV_Map(final GremlinParser.TraversalMethod_mergeV_MapContext ctx) {
- return this.graphTraversal.mergeV(antlr.argumentVisitor.parseMap(ctx.genericLiteralMapNullableArgument()));
+ final Object literalOrVar = antlr.argumentVisitor.visitGenericLiteralMapNullableArgument(ctx.genericLiteralMapNullableArgument());
+ if (GValue.valueInstanceOf(literalOrVar, GType.MAP))
+ return graphTraversal.mergeV((GValue<Map<Object, Object>>) literalOrVar);
+ else
+ return graphTraversal.mergeV((Map) literalOrVar);
}
/**
@@ -129,7 +135,11 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
*/
@Override
public GraphTraversal visitTraversalMethod_mergeE_Map(final GremlinParser.TraversalMethod_mergeE_MapContext ctx) {
- return this.graphTraversal.mergeE(antlr.argumentVisitor.parseMap(ctx.genericLiteralMapNullableArgument()));
+ final Object literalOrVar = antlr.argumentVisitor.visitGenericLiteralMapNullableArgument(ctx.genericLiteralMapNullableArgument());
+ if (GValue.valueInstanceOf(literalOrVar, GType.MAP))
+ return graphTraversal.mergeE((GValue<Map<Object, Object>>) literalOrVar);
+ else
+ return graphTraversal.mergeE((Map) literalOrVar);
}
/**
@@ -440,7 +450,11 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
*/
@Override
public GraphTraversal visitTraversalMethod_combine_Object(final GremlinParser.TraversalMethod_combine_ObjectContext ctx) {
- return graphTraversal.combine(antlr.argumentVisitor.visitGenericLiteralArgument(ctx.genericLiteralArgument()));
+ final Object literalOrVar = antlr.argumentVisitor.visitGenericLiteralArgument(ctx.genericLiteralArgument());
+ if (literalOrVar instanceof GValue && ((GValue) literalOrVar).getType().isCollection())
+ return graphTraversal.combine((GValue<Object>) literalOrVar);
+ else
+ return graphTraversal.combine(literalOrVar);
}
/**
@@ -448,7 +462,12 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
*/
@Override
public GraphTraversal visitTraversalMethod_coin(final GremlinParser.TraversalMethod_coinContext ctx) {
- return graphTraversal.coin(((Number) antlr.argumentVisitor.visitFloatArgument(ctx.floatArgument())).doubleValue());
+ final Object literalOrVar = antlr.argumentVisitor.visitFloatArgument(ctx.floatArgument());
+ if (GValue.valueInstanceOfNumeric(literalOrVar))
+ return graphTraversal.coin((GValue<Double>) literalOrVar);
+ else
+ return graphTraversal.coin(((Number) literalOrVar).doubleValue());
+
}
/**
@@ -456,7 +475,13 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
*/
@Override
public GraphTraversal visitTraversalMethod_conjoin_String(final GremlinParser.TraversalMethod_conjoin_StringContext ctx) {
- return graphTraversal.conjoin(antlr.argumentVisitor.parseString(ctx.stringArgument()));
+ final Object literalOrVar = antlr.argumentVisitor.visitStringArgument(ctx.stringArgument());
+ if (literalOrVar instanceof String)
+ return graphTraversal.conjoin((String) literalOrVar);
+ else if (literalOrVar instanceof GValue && ((GValue) literalOrVar).getType() == GType.STRING)
+ return graphTraversal.conjoin((GValue<String>) literalOrVar);
+ else
+ throw new IllegalArgumentException("conjoin argument must be a string");
}
/**
@@ -514,7 +539,11 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
*/
@Override
public GraphTraversal visitTraversalMethod_difference_Object(final GremlinParser.TraversalMethod_difference_ObjectContext ctx) {
- return graphTraversal.difference(antlr.argumentVisitor.visitGenericLiteralArgument(ctx.genericLiteralArgument()));
+ final Object literalOrVar = antlr.argumentVisitor.visitGenericLiteralArgument(ctx.genericLiteralArgument());
+ if (literalOrVar instanceof GValue && ((GValue) literalOrVar).getType().isCollection())
+ return graphTraversal.difference((GValue<Object>) literalOrVar);
+ else
+ return graphTraversal.difference(literalOrVar);
}
/**
@@ -522,7 +551,11 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
*/
@Override
public GraphTraversal visitTraversalMethod_disjunct_Object(final GremlinParser.TraversalMethod_disjunct_ObjectContext ctx) {
- return graphTraversal.disjunct(antlr.argumentVisitor.visitGenericLiteralArgument(ctx.genericLiteralArgument()));
+ final Object literalOrVar = antlr.argumentVisitor.visitGenericLiteralArgument(ctx.genericLiteralArgument());
+ if (literalOrVar instanceof GValue && ((GValue) literalOrVar).getType().isCollection())
+ return graphTraversal.disjunct((GValue<Object>) literalOrVar);
+ else
+ return graphTraversal.disjunct(literalOrVar);
}
/**
@@ -619,8 +652,20 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
* {@inheritDoc}
*/
@Override
- public GraphTraversal visitTraversalMethod_from_String(final GremlinParser.TraversalMethod_from_StringContext ctx) {
- return graphTraversal.from(antlr.argumentVisitor.parseString(ctx.stringArgument()));
+ public Traversal visitTraversalMethod_from_String(final GremlinParser.TraversalMethod_from_StringContext ctx) {
+ return graphTraversal.from(antlr.genericVisitor.parseString(ctx.stringLiteral()));
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Traversal visitTraversalMethod_from_Vertex(final GremlinParser.TraversalMethod_from_VertexContext ctx) {
+ final Object literalOrVar = antlr.argumentVisitor.visitStructureVertexArgument(ctx.structureVertexArgument());
+ if (GValue.valueInstanceOf(literalOrVar, GType.VERTEX))
+ return graphTraversal.from((GValue<Vertex>) literalOrVar);
+ else
+ return graphTraversal.from((Vertex) literalOrVar);
}
/**
@@ -715,10 +760,30 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
@Override
public GraphTraversal visitTraversalMethod_hasLabel_String_String(final GremlinParser.TraversalMethod_hasLabel_String_StringContext ctx) {
if (ctx.getChildCount() == 4) {
- return graphTraversal.hasLabel(antlr.argumentVisitor.parseString(ctx.stringNullableArgument()));
+ final Object literalOrVar = antlr.argumentVisitor.visitStringNullableArgument(ctx.stringNullableArgument());
+ if (GValue.valueInstanceOf(literalOrVar, GType.STRING))
+ return graphTraversal.hasLabel((GValue) literalOrVar);
+ else
+ return graphTraversal.hasLabel((String) literalOrVar);
} else {
- return graphTraversal.hasLabel(antlr.argumentVisitor.parseString(ctx.stringNullableArgument()),
- antlr.genericVisitor.parseStringVarargs(ctx.stringLiteralVarargs()));
+ Object literalOrVar = antlr.argumentVisitor.visitStringNullableArgument(ctx.stringNullableArgument());
+ Object[] literalOrVars = antlr.genericVisitor.visitStringLiteralVarargs(ctx.stringLiteralVarargs());
+
+ // if any are GValue then they all need to be GValue to call hasLabel
+ if (literalOrVar instanceof GValue || Arrays.stream(literalOrVars).anyMatch(lov -> lov instanceof GValue)) {
+ literalOrVar = GValue.of(literalOrVar);
+ literalOrVars = GValue.ensureGValues(literalOrVars);
+ }
+
+ // since we normalized above to gvalue or literal we can just test the first arg for gvalue-ness
+ if (GValue.valueInstanceOf(literalOrVar, GType.STRING)) {
+ final GValue[] gvalueLiteralOrVars = literalOrVars == null ? null : Arrays.stream(literalOrVars).map(o -> (GValue) o).toArray(GValue[]::new);
+ return graphTraversal.hasLabel((GValue) literalOrVar, (GValue[]) gvalueLiteralOrVars);
+ } else {
+ // convert object array to string array
+ final String[] stringLiteralOrVars = literalOrVars == null ? null : Arrays.stream(literalOrVars).map(o -> (String) o).toArray(String[]::new);
+ return graphTraversal.hasLabel((String) literalOrVar, stringLiteralOrVars);
+ }
}
}
@@ -778,9 +843,16 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
*/
@Override
public GraphTraversal visitTraversalMethod_has_String_String_Object(final GremlinParser.TraversalMethod_has_String_String_ObjectContext ctx) {
- return graphTraversal.has(antlr.argumentVisitor.parseString(ctx.stringNullableArgument(0)),
- antlr.argumentVisitor.parseString(ctx.stringNullableArgument(1)),
- antlr.argumentVisitor.visitGenericLiteralArgument(ctx.genericLiteralArgument()));
+ final Object literalOrVar = antlr.argumentVisitor.visitStringNullableArgument(ctx.stringNullableArgument(0));
+ if (GValue.valueInstanceOf(literalOrVar, GType.STRING)) {
+ return graphTraversal.has((GValue) literalOrVar,
+ antlr.argumentVisitor.parseString(ctx.stringNullableArgument(1)),
+ antlr.argumentVisitor.visitGenericLiteralArgument(ctx.genericLiteralArgument()));
+ } else {
+ return graphTraversal.has((String) literalOrVar,
+ antlr.argumentVisitor.parseString(ctx.stringNullableArgument(1)),
+ antlr.argumentVisitor.visitGenericLiteralArgument(ctx.genericLiteralArgument()));
+ }
}
/**
@@ -866,7 +938,11 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
*/
@Override
public GraphTraversal visitTraversalMethod_intersect_Object(final GremlinParser.TraversalMethod_intersect_ObjectContext ctx) {
- return graphTraversal.intersect(antlr.argumentVisitor.visitGenericLiteralArgument(ctx.genericLiteralArgument()));
+ final Object literalOrVar = antlr.argumentVisitor.visitGenericLiteralArgument(ctx.genericLiteralArgument());
+ if (literalOrVar instanceof GValue && ((GValue) literalOrVar).getType().isCollection())
+ return graphTraversal.intersect((GValue<Object>) literalOrVar);
+ else
+ return graphTraversal.intersect(literalOrVar);
}
/**
@@ -1066,7 +1142,11 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
*/
@Override
public GraphTraversal visitTraversalMethod_merge_Object(final GremlinParser.TraversalMethod_merge_ObjectContext ctx) {
- return graphTraversal.merge(antlr.argumentVisitor.visitGenericLiteralArgument(ctx.genericLiteralArgument()));
+ final Object literalOrVar = antlr.argumentVisitor.visitGenericLiteralArgument(ctx.genericLiteralArgument());
+ if (literalOrVar instanceof GValue && ((GValue) literalOrVar).getType().isCollection())
+ return graphTraversal.merge((GValue<Object>) literalOrVar);
+ else
+ return graphTraversal.merge(literalOrVar);
}
/**
@@ -1106,8 +1186,11 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
*/
@Override
public GraphTraversal visitTraversalMethod_option_Object_Traversal(final GremlinParser.TraversalMethod_option_Object_TraversalContext ctx) {
- return graphTraversal.option(antlr.argumentVisitor.visitGenericLiteralArgument(ctx.genericLiteralArgument()),
- antlr.tvisitor.visitNestedTraversal(ctx.nestedTraversal()));
+ final Object literalOrVar = antlr.argumentVisitor.visitGenericLiteralArgument(ctx.genericLiteralArgument());
+ if (literalOrVar instanceof GValue)
+ return graphTraversal.option((GValue) literalOrVar, antlr.tvisitor.visitNestedTraversal(ctx.nestedTraversal()));
+ else
+ return graphTraversal.option(literalOrVar, antlr.tvisitor.visitNestedTraversal(ctx.nestedTraversal()));
}
/**
@@ -1123,8 +1206,11 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
*/
@Override
public GraphTraversal visitTraversalMethod_option_Merge_Map(final GremlinParser.TraversalMethod_option_Merge_MapContext ctx) {
- return graphTraversal.option(TraversalEnumParser.parseTraversalEnumFromContext(Merge.class, ctx.traversalMerge()),
- (Map) antlr.argumentVisitor.visitGenericLiteralMapNullableArgument(ctx.genericLiteralMapNullableArgument()));
+ final Object literalOrVar = antlr.argumentVisitor.visitGenericLiteralMapNullableArgument(ctx.genericLiteralMapNullableArgument());
+ if (GValue.valueInstanceOf(literalOrVar, GType.MAP))
+ return graphTraversal.option(TraversalEnumParser.parseTraversalEnumFromContext(Merge.class, ctx.traversalMerge()), (GValue<Map>) literalOrVar);
+ else
+ return graphTraversal.option(TraversalEnumParser.parseTraversalEnumFromContext(Merge.class, ctx.traversalMerge()), (Map) literalOrVar);
}
/**
@@ -1263,7 +1349,11 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
*/
@Override
public GraphTraversal visitTraversalMethod_product_Object(final GremlinParser.TraversalMethod_product_ObjectContext ctx) {
- return graphTraversal.product(antlr.argumentVisitor.visitGenericLiteralArgument(ctx.genericLiteralArgument()));
+ final Object literalOrVar = antlr.argumentVisitor.visitGenericLiteralArgument(ctx.genericLiteralArgument());
+ if (literalOrVar instanceof GValue && ((GValue) literalOrVar).getType().isCollection())
+ return graphTraversal.product((GValue<Object>) literalOrVar);
+ else
+ return graphTraversal.product(literalOrVar);
}
/**
@@ -1607,7 +1697,7 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
*/
@Override
public GraphTraversal visitTraversalMethod_to_Direction_String(final GremlinParser.TraversalMethod_to_Direction_StringContext ctx) {
- return graphTraversal.to(TraversalEnumParser.parseTraversalEnumFromContext(Direction.class, ctx.traversalDirection()),
+ return graphTraversal.to(TraversalEnumParser.parseTraversalDirectionFromContext(ctx.traversalDirection()),
antlr.genericVisitor.parseStringVarargs(ctx.stringLiteralVarargs()));
}
@@ -1615,8 +1705,20 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
* {@inheritDoc}
*/
@Override
- public GraphTraversal visitTraversalMethod_to_String(final GremlinParser.TraversalMethod_to_StringContext ctx) {
- return graphTraversal.to(antlr.argumentVisitor.parseString(ctx.stringArgument()));
+ public Traversal visitTraversalMethod_to_String(final GremlinParser.TraversalMethod_to_StringContext ctx) {
+ return graphTraversal.to(antlr.genericVisitor.parseString(ctx.stringLiteral()));
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Traversal visitTraversalMethod_to_Vertex(final GremlinParser.TraversalMethod_to_VertexContext ctx) {
+ final Object literalOrVar = antlr.argumentVisitor.visitStructureVertexArgument(ctx.structureVertexArgument());
+ if (GValue.valueInstanceOf(literalOrVar, GType.VERTEX))
+ return graphTraversal.to((GValue<Vertex>) literalOrVar);
+ else
+ return graphTraversal.to((Vertex) literalOrVar);
}
/**
@@ -1755,22 +1857,6 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
antlr.tvisitor.visitNestedTraversal(ctx.nestedTraversal()));
}
- /**
- * {@inheritDoc}
- */
- @Override
- public Traversal visitTraversalMethod_from_Vertex(final GremlinParser.TraversalMethod_from_VertexContext ctx) {
- return graphTraversal.from(antlr.argumentVisitor.parseVertex(ctx.structureVertexArgument()));
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public Traversal visitTraversalMethod_to_Vertex(final GremlinParser.TraversalMethod_to_VertexContext ctx) {
- return graphTraversal.to(antlr.argumentVisitor.parseVertex(ctx.structureVertexArgument()));
- }
-
/**
* {@inheritDoc}
*/
@@ -1792,8 +1878,11 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
*/
@Override
public Traversal visitTraversalMethod_call_string_map(final GremlinParser.TraversalMethod_call_string_mapContext ctx) {
- return graphTraversal.call(antlr.argumentVisitor.parseString(ctx.stringArgument()),
- antlr.argumentVisitor.parseMap(ctx.genericLiteralMapArgument()));
+ final Object literalOrVar = antlr.argumentVisitor.visitGenericLiteralMapArgument(ctx.genericLiteralMapArgument());
+ if (GValue.valueInstanceOf(literalOrVar, GType.MAP))
+ return graphTraversal.call(antlr.argumentVisitor.parseString(ctx.stringArgument()), (GValue<Map>) literalOrVar);
+ else
+ return graphTraversal.call(antlr.argumentVisitor.parseString(ctx.stringArgument()), (Map) literalOrVar);
}
/**
@@ -1810,9 +1899,11 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
*/
@Override
public Traversal visitTraversalMethod_call_string_map_traversal(final GremlinParser.TraversalMethod_call_string_map_traversalContext ctx) {
- return graphTraversal.call(antlr.argumentVisitor.parseString(ctx.stringArgument()),
- antlr.argumentVisitor.parseMap(ctx.genericLiteralMapArgument()),
- antlr.tvisitor.visitNestedTraversal(ctx.nestedTraversal()));
+ final Object literalOrVar = antlr.argumentVisitor.visitGenericLiteralMapArgument(ctx.genericLiteralMapArgument());
+ if (GValue.valueInstanceOf(literalOrVar, GType.MAP))
+ return graphTraversal.call(antlr.argumentVisitor.parseString(ctx.stringArgument()), (GValue<Map>) literalOrVar, antlr.tvisitor.visitNestedTraversal(ctx.nestedTraversal()));
+ else
+ return graphTraversal.call(antlr.argumentVisitor.parseString(ctx.stringArgument()), (Map) literalOrVar, antlr.tvisitor.visitNestedTraversal(ctx.nestedTraversal()));
}
/**
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalSourceSpawnMethodVisitor.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalSourceSpawnMethodVisitor.java
index 2227635f80..02fb654451 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalSourceSpawnMethodVisitor.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalSourceSpawnMethodVisitor.java
@@ -21,6 +21,8 @@ package org.apache.tinkerpop.gremlin.language.grammar;
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.step.GValue;
+import org.apache.tinkerpop.gremlin.process.traversal.step.GType;
import java.util.Map;
@@ -119,7 +121,11 @@ public class TraversalSourceSpawnMethodVisitor extends DefaultGremlinBaseVisitor
*/
@Override
public GraphTraversal visitTraversalSourceSpawnMethod_mergeV_Map(final GremlinParser.TraversalSourceSpawnMethod_mergeV_MapContext ctx) {
- return this.traversalSource.mergeV(antlr.argumentVisitor.parseMap(ctx.genericLiteralMapNullableArgument()));
+ final Object literalOrVar = antlr.argumentVisitor.visitGenericLiteralMapNullableArgument(ctx.genericLiteralMapNullableArgument());
+ if (GValue.valueInstanceOf(literalOrVar, GType.MAP))
+ return this.traversalSource.mergeV((GValue) literalOrVar);
+ else
+ return this.traversalSource.mergeV((Map) literalOrVar);
}
/**
@@ -143,7 +149,11 @@ public class TraversalSourceSpawnMethodVisitor extends DefaultGremlinBaseVisitor
*/
@Override
public GraphTraversal visitTraversalSourceSpawnMethod_mergeE_Map(final GremlinParser.TraversalSourceSpawnMethod_mergeE_MapContext ctx) {
- return this.traversalSource.mergeE(antlr.argumentVisitor.parseMap(ctx.genericLiteralMapNullableArgument()));
+ final Object literalOrVar = antlr.argumentVisitor.visitGenericLiteralMapNullableArgument(ctx.genericLiteralMapNullableArgument());
+ if (GValue.valueInstanceOf(literalOrVar, GType.MAP))
+ return this.traversalSource.mergeE((GValue) literalOrVar);
+ else
+ return this.traversalSource.mergeE((Map) literalOrVar);
}
/**
@@ -167,8 +177,11 @@ public class TraversalSourceSpawnMethodVisitor extends DefaultGremlinBaseVisitor
*/
@Override
public GraphTraversal visitTraversalSourceSpawnMethod_call_string_map(final GremlinParser.TraversalSourceSpawnMethod_call_string_mapContext ctx) {
- return this.traversalSource.call(antlr.argumentVisitor.parseString(ctx.stringArgument()),
- antlr.argumentVisitor.parseMap(ctx.genericLiteralMapArgument()));
+ final Object literalOrVar = antlr.argumentVisitor.visitGenericLiteralMapArgument(ctx.genericLiteralMapArgument());
+ if (GValue.valueInstanceOf(literalOrVar, GType.MAP))
+ return this.traversalSource.call(antlr.argumentVisitor.parseString(ctx.stringArgument()), (GValue<Map>) literalOrVar);
+ else
+ return this.traversalSource.call(antlr.argumentVisitor.parseString(ctx.stringArgument()), (Map) literalOrVar);
}
/**
@@ -185,9 +198,11 @@ public class TraversalSourceSpawnMethodVisitor extends DefaultGremlinBaseVisitor
*/
@Override
public GraphTraversal visitTraversalSourceSpawnMethod_call_string_map_traversal(final GremlinParser.TraversalSourceSpawnMethod_call_string_map_traversalContext ctx) {
- return this.traversalSource.call(antlr.argumentVisitor.parseString(ctx.stringArgument()),
- antlr.argumentVisitor.parseMap(ctx.genericLiteralMapArgument()),
- anonymousVisitor.visitNestedTraversal(ctx.nestedTraversal()));
+ final Object literalOrVar = antlr.argumentVisitor.visitGenericLiteralMapArgument(ctx.genericLiteralMapArgument());
+ if (GValue.valueInstanceOf(literalOrVar, GType.MAP))
+ return this.traversalSource.call(antlr.argumentVisitor.parseString(ctx.stringArgument()), (GValue<Map>) literalOrVar, anonymousVisitor.visitNestedTraversal(ctx.nestedTraversal()));
+ else
+ return this.traversalSource.call(antlr.argumentVisitor.parseString(ctx.stringArgument()), (Map) literalOrVar, anonymousVisitor.visitNestedTraversal(ctx.nestedTraversal()));
}
/**
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/VariableResolver.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/VariableResolver.java
index a97bd4b646..e017808faf 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/VariableResolver.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/VariableResolver.java
@@ -18,24 +18,25 @@
*/
package org.apache.tinkerpop.gremlin.language.grammar;
+import org.apache.tinkerpop.gremlin.process.traversal.step.GValue;
import java.util.Map;
import java.util.function.BiFunction;
/**
* Resolves parameters in Gremlin to objects.
*/
-public interface VariableResolver extends BiFunction<String, GremlinParser.VariableContext, Object> {
+public interface VariableResolver<T> extends BiFunction<String, GremlinParser.VariableContext, T> {
/**
* This function resolves a variable name and the given parsers context to an object.
*/
@Override
- Object apply(final String varName, final GremlinParser.VariableContext variableContext);
+ T apply(final String varName, final GremlinParser.VariableContext variableContext);
/**
* This {@link VariableResolver} implementation throws exceptions for all variable names.
*/
- class NoVariableResolver implements VariableResolver {
+ class NoVariableResolver implements VariableResolver<Object> {
private static NoVariableResolver instance = new NoVariableResolver();
public static VariableResolver instance() {
@@ -48,12 +49,35 @@ public interface VariableResolver extends BiFunction<String, GremlinParser.Varia
}
}
+ /**
+ * Allows for a provided variable set in the form of a {@code Map}, where the keys are variable names and the
+ * values are the parameter values to be injected into the traversal in their place. The value is provided to a
+ * {@link GValue} object along with the variable name for further reference.
+ */
+ class DefaultVariableResolver implements VariableResolver<GValue<?>> {
+
+ private final Map<String, Object> variables;
+
+ public DefaultVariableResolver(final Map<String, Object> variables) {
+ this.variables = variables;
+ }
+
+ @Override
+ public GValue<?> apply(final String s, final GremlinParser.VariableContext variableContext) {
+ if (!variables.containsKey(s)) {
+ throw new VariableResolverException(String.format("No variable found for %s", s));
+ }
+
+ return GValue.of(s, variables.get(s));
+ }
+ }
+
/**
* This {@link VariableResolver} simply provides a {@code null} value for all variable names. It's typical use
* is for when you really don't intend to execute the traversal and just want to get an instance of one when
* bindings are being used as with {@link NoOpTerminalVisitor}.
*/
- class NullVariableResolver implements VariableResolver {
+ class NullVariableResolver implements VariableResolver<Object> {
private static NullVariableResolver instance = new NullVariableResolver();
public static VariableResolver instance() {
@@ -70,11 +94,11 @@ public interface VariableResolver extends BiFunction<String, GremlinParser.Varia
* Allows for a provided variable set in the form of a {@code Map}, where the keys are variable names and the
* values are the parameter values to be injected into the traversal in their place.
*/
- class DefaultVariableResolver implements VariableResolver {
+ class DirectVariableResolver implements VariableResolver<Object> {
private final Map<String, Object> variables;
- public DefaultVariableResolver(final Map<String, Object> variables) {
+ public DirectVariableResolver(final Map<String, Object> variables) {
this.variables = variables;
}
@@ -87,4 +111,5 @@ public interface VariableResolver extends BiFunction<String, GremlinParser.Varia
return variables.get(s);
}
}
+
}
\ No newline at end of file
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/translator/DotNetTranslateVisitor.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/translator/DotNetTranslateVisitor.java
index 21c4d20ea4..60ce2f8e30 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/translator/DotNetTranslateVisitor.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/translator/DotNetTranslateVisitor.java
@@ -739,10 +739,36 @@ public class DotNetTranslateVisitor extends AbstractTranslateVisitor {
sb.append(")");
return null;
} else {
- return super.visitTraversalMethod_hasLabel_String_String(ctx);
+ final String step = ctx.getChild(0).getText();
+ sb.append(convertToPascalCase(step));
+ sb.append("(");
+ tryAppendCastToString(ctx.stringNullableArgument());
+ visit(ctx.stringNullableArgument());
+
+ // more arguments to come
+ if (!ctx.stringLiteralVarargs().isEmpty()) sb.append(", ");
+ visit(ctx.stringLiteralVarargs());
+
+ sb.append(")");
+ return null;
}
}
+ @Override
+ public Void visitStringLiteralVarargs(final GremlinParser.StringLiteralVarargsContext ctx) {
+ for (int ix = 0; ix < ctx.getChildCount(); ix++) {
+ final ParseTree pt = ctx.getChild(ix);
+ if (pt instanceof GremlinParser.StringNullableArgumentContext) {
+ GremlinParser.StringNullableArgumentContext sna = (GremlinParser.StringNullableArgumentContext) pt;
+ tryAppendCastToString(sna);
+ visit(sna);
+ } else {
+ visit(pt);
+ }
+ };
+ return null;
+ }
+
@Override
public Void visitTraversalMethod_index(final GremlinParser.TraversalMethod_indexContext ctx) {
return handleGenerics(ctx);
@@ -870,9 +896,24 @@ public class DotNetTranslateVisitor extends AbstractTranslateVisitor {
return null;
}
+ @Override
+ public Void visitTraversalMethod_option_Object_Traversal(final GremlinParser.TraversalMethod_option_Object_TraversalContext ctx) {
+ if (ctx.genericLiteralArgument().genericLiteral() != null && ctx.genericLiteralArgument().genericLiteral().traversalMerge() != null) {
+ visit(ctx.getChild(0));
+ sb.append("(");
+ visit(ctx.genericLiteralArgument());
+ sb.append(", ");
+ sb.append("(ITraversal) ");
+ visit(ctx.nestedTraversal());
+ sb.append(")");
+ return null;
+ } else {
+ return super.visitTraversalMethod_option_Object_Traversal(ctx);
+ }
+ }
+
@Override
public Void visitTraversalMethod_option_Merge_Traversal(final GremlinParser.TraversalMethod_option_Merge_TraversalContext ctx) {
- // call is ambiguous without an explicit cast
visit(ctx.getChild(0));
sb.append("(");
visit(ctx.traversalMerge());
@@ -923,6 +964,17 @@ public class DotNetTranslateVisitor extends AbstractTranslateVisitor {
}
}
+ @Override
+ public Void visitTraversalMethod_conjoin_String(final GremlinParser.TraversalMethod_conjoin_StringContext ctx) {
+ final String step = ctx.getChild(0).getText();
+ sb.append(convertToPascalCase(step));
+ sb.append("(");
+ tryAppendCastToString(ctx.stringArgument());
+ visit(ctx.stringArgument());
+ sb.append(")");
+ return null;
+ }
+
@Override
public Void visitTraversalMethod_propertyMap(final GremlinParser.TraversalMethod_propertyMapContext ctx) {
return handleGenerics(ctx);
@@ -1138,6 +1190,12 @@ public class DotNetTranslateVisitor extends AbstractTranslateVisitor {
}
}
+ private void tryAppendCastToString(final GremlinParser.StringArgumentContext ctx) {
+ if (ctx.variable() != null || ctx.stringLiteral() != null) {
+ sb.append("(string) ");
+ }
+ }
+
private void tryAppendCastToString(final GremlinParser.StringNullableArgumentContext ctx) {
if (ctx.variable() != null || ctx.stringNullableLiteral().NullLiteral() != null) {
sb.append("(string) ");
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/translator/GroovyTranslateVisitor.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/translator/GroovyTranslateVisitor.java
index 3c87b6249a..20a6b6434e 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/translator/GroovyTranslateVisitor.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/translator/GroovyTranslateVisitor.java
@@ -186,8 +186,35 @@ public class GroovyTranslateVisitor extends TranslateVisitor {
return handleInject(ctx);
}
- /*
- * very special handling for inject with second `null` argument like g.inject(1, null)
+ @Override
+ public Void visitTraversalMethod_hasLabel_String_String(final GremlinParser.TraversalMethod_hasLabel_String_StringContext ctx) {
+ // special handling for resolving ambiguous invocations of the hasLabel() step. coerces to the string form
+ if (ctx.getChildCount() > 4 && ctx.getChild(2).getText().equals("null")) {
+ final GremlinParser.StringLiteralVarargsContext varArgs = (GremlinParser.StringLiteralVarargsContext) ctx.getChild(4);
+ sb.append(ctx.getChild(0).getText());
+ sb.append("((String) null, ");
+
+ for (int i = 0; i < varArgs.getChildCount(); i += 2) {
+ if (varArgs.getChild(i).getText().equals("null")) {
+ sb.append("(String) null");
+ } else {
+ visit(varArgs.getChild(i));
+ }
+
+ if (i < varArgs.getChildCount() - 1) {
+ sb.append(", ");
+ }
+ }
+
+ sb.append(")");
+ return null;
+ }
+
+ return visitChildren(ctx);
+ }
+
+ /**
+ * Special handling for inject with second `null` argument like g.inject(1, null)
* inject() ends up being ambiguous with groovy's jdk extension of inject(Object initialValue, Closure closure)
*/
private Void handleInject(final ParserRuleContext ctx) {
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/translator/TranslateVisitor.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/translator/TranslateVisitor.java
index 2712262678..beb6040091 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/translator/TranslateVisitor.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/translator/TranslateVisitor.java
@@ -903,17 +903,17 @@ public class TranslateVisitor extends AbstractParseTreeVisitor<Void> implements
}
@Override
- public Void visitTraversalMethod_option_Merge_Traversal(final GremlinParser.TraversalMethod_option_Merge_TraversalContext ctx) {
+ public Void visitTraversalMethod_option_Object_Traversal(final GremlinParser.TraversalMethod_option_Object_TraversalContext ctx) {
return visitChildren(ctx);
}
@Override
- public Void visitTraversalMethod_option_Object_Traversal(final GremlinParser.TraversalMethod_option_Object_TraversalContext ctx) {
+ public Void visitTraversalMethod_option_Traversal(final GremlinParser.TraversalMethod_option_TraversalContext ctx) {
return visitChildren(ctx);
}
@Override
- public Void visitTraversalMethod_option_Traversal(final GremlinParser.TraversalMethod_option_TraversalContext ctx) {
+ public Void visitTraversalMethod_option_Merge_Traversal(final GremlinParser.TraversalMethod_option_Merge_TraversalContext ctx) {
return visitChildren(ctx);
}
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/P.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/P.java
index 917a13891d..a878bbb839 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/P.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/P.java
@@ -18,13 +18,16 @@
*/
package org.apache.tinkerpop.gremlin.process.traversal;
+import org.apache.tinkerpop.gremlin.process.traversal.step.GValue;
import org.apache.tinkerpop.gremlin.process.traversal.util.AndP;
import org.apache.tinkerpop.gremlin.process.traversal.util.OrP;
import java.io.Serializable;
import java.util.Arrays;
import java.util.Collection;
+import java.util.List;
import java.util.function.Predicate;
+import java.util.stream.Collectors;
/**
* Predefined {@code Predicate} values that can be used to define filters to {@code has()} and {@code where()}.
@@ -74,7 +77,16 @@ public class P<V> implements Predicate<V>, Serializable, Cloneable {
@Override
public boolean test(final V testValue) {
- return this.biPredicate.test(testValue, this.value);
+ if (this.value instanceof GValue) {
+ return this.biPredicate.test(testValue, ((GValue<V>) this.value).get());
+ } else {
+ // this might be a bunch of GValue that need to be resolved. zomg
+ if (this.value instanceof List) {
+ return this.biPredicate.test(testValue, (V) ((List) this.value).stream().map(GValue::valueOf).collect(Collectors.toList()));
+ } else {
+ return this.biPredicate.test(testValue, this.value);
+ }
+ }
}
@Override
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/SackFunctions.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/SackFunctions.java
index 4752bf0b32..3985efe699 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/SackFunctions.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/SackFunctions.java
@@ -19,6 +19,7 @@
package org.apache.tinkerpop.gremlin.process.traversal;
+import org.apache.tinkerpop.gremlin.process.traversal.step.GValue;
import org.apache.tinkerpop.gremlin.process.traversal.traverser.util.TraverserSet;
import java.util.function.Consumer;
@@ -42,10 +43,10 @@ public final class SackFunctions {
public void accept(final TraverserSet<Object> traverserSet) {
Number total = 0.0;
for (final Traverser.Admin<Object> traverser : traverserSet) {
- total = add(total, mul(traverser.sack(), traverser.bulk()));
+ total = add(total, mul(GValue.numberOf(traverser.sack()), traverser.bulk()));
}
for (final Traverser.Admin<Object> traverser : traverserSet) {
- traverser.sack(div(mul(traverser.sack(), traverser.bulk()), total));
+ traverser.sack(div(mul(GValue.numberOf(traverser.sack()), traverser.bulk()), total));
}
}
}
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 9d5b500376..ab5af2445b 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
@@ -25,6 +25,7 @@ import org.apache.tinkerpop.gremlin.process.computer.traversal.step.map.PageRank
import org.apache.tinkerpop.gremlin.process.computer.traversal.step.map.PeerPressureVertexProgramStep;
import org.apache.tinkerpop.gremlin.process.computer.traversal.step.map.ProgramVertexProgramStep;
import org.apache.tinkerpop.gremlin.process.computer.traversal.step.map.ShortestPathVertexProgramStep;
+import org.apache.tinkerpop.gremlin.process.traversal.Contains;
import org.apache.tinkerpop.gremlin.process.traversal.DT;
import org.apache.tinkerpop.gremlin.process.traversal.Failure;
import org.apache.tinkerpop.gremlin.process.traversal.Merge;
@@ -47,6 +48,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.lambda.TrueTraversal;
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.FromToModulating;
+import org.apache.tinkerpop.gremlin.process.traversal.step.GValue;
import org.apache.tinkerpop.gremlin.process.traversal.step.Mutating;
import org.apache.tinkerpop.gremlin.process.traversal.step.ReadWriting;
import org.apache.tinkerpop.gremlin.process.traversal.step.TimesModulating;
@@ -203,8 +205,10 @@ import org.apache.tinkerpop.gremlin.structure.PropertyType;
import org.apache.tinkerpop.gremlin.structure.T;
import org.apache.tinkerpop.gremlin.structure.Vertex;
import org.apache.tinkerpop.gremlin.structure.VertexProperty;
+import org.apache.tinkerpop.gremlin.util.CollectionUtil;
import org.apache.tinkerpop.gremlin.util.function.ConstantSupplier;
+import java.lang.reflect.Array;
import java.time.OffsetDateTime;
import java.util.ArrayList;
import java.util.Arrays;
@@ -230,6 +234,11 @@ import static org.apache.tinkerpop.gremlin.structure.VertexProperty.Cardinality.
*/
public interface GraphTraversal<S, E> extends Traversal<S, E> {
+ /**
+ * Exposes administrative methods that are either internal to TinkerPop or for users with advanced needs. This
+ * separation helps keep the Gremlin API more concise. Any {@code GraphTraversal} can get an instance of its
+ * administrative form by way of {@link GraphTraversal#asAdmin()}.
+ */
public interface Admin<S, E> extends Traversal.Admin<S, E>, GraphTraversal<S, E> {
@Override
@@ -356,6 +365,18 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
return this.asAdmin().addStep(new ConstantStep<E, E2>(this.asAdmin(), e));
}
+ /**
+ * Map any object to a fixed <code>E</code> value. For internal use for parameterization features.
+ *
+ * @return the traversal with an appended {@link ConstantStep}.
+ * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#constant-step" target="_blank">Reference Documentation - Constant Step</a>
+ * @since 4.0.0
+ */
+ public default <E2> GraphTraversal<S, E2> constant(final GValue<E2> e) {
+ this.asAdmin().getGremlinLang().addStep(GraphTraversal.Symbols.constant, e);
+ return this.asAdmin().addStep(new ConstantStep<E, E2>(this.asAdmin(), e));
+ }
+
/**
* A {@code V} step is usually used to start a traversal but it may also be used mid-traversal.
*
@@ -400,6 +421,22 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
return this.asAdmin().addStep(new VertexStep<>(this.asAdmin(), Vertex.class, direction, edgeLabels));
}
+ /**
+ * Map the {@link Vertex} to its adjacent vertices given a direction and edge labels. The arguments for the
+ * labels must be either a {@code String} or a {@link GValue<String>}. For internal use for parameterization.
+ *
+ * @param direction the direction to traverse from the current vertex
+ * @param edgeLabels the edge labels to traverse
+ * @return the traversal with an appended {@link VertexStep}.
+ * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#vertex-steps" target="_blank">Reference Documentation - Vertex Step</a>
+ * @since 4.0.0
+ */
+ public default GraphTraversal<S, Vertex> to(final Direction direction, final GValue<String> edgeLabel, final GValue<String>... edgeLabels) {
+ this.asAdmin().getGremlinLang().addStep(GraphTraversal.Symbols.to, direction, edgeLabel, edgeLabels);
+ final GValue<String>[] labels = CollectionUtil.addFirst(edgeLabels, edgeLabel, GValue.class);
+ return this.asAdmin().addStep(new VertexStep<>(this.asAdmin(), Vertex.class, direction, labels));
+ }
+
/**
* Map the {@link Vertex} to its outgoing adjacent vertices given the edge labels.
*
@@ -413,6 +450,21 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
return this.asAdmin().addStep(new VertexStep<>(this.asAdmin(), Vertex.class, Direction.OUT, edgeLabels));
}
+ /**
+ * Map the {@link Vertex} to its outgoing adjacent vertices given the edge labels. The arguments for the
+ * labels must be either a {@code String} or a {@link GValue<String>}. For internal use for parameterization.
+ *
+ * @param edgeLabels the edge labels to traverse
+ * @return the traversal with an appended {@link VertexStep}.
+ * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#vertex-steps" target="_blank">Reference Documentation - Vertex Step</a>
+ * @since 3.7.3
+ */
+ public default GraphTraversal<S, Vertex> out(final GValue<String> label, final GValue<String>... edgeLabels) {
+ final GValue<String>[] labels = CollectionUtil.addFirst(edgeLabels, label, GValue.class);
+ this.asAdmin().getGremlinLang().addStep(GraphTraversal.Symbols.out, label, edgeLabels);
+ return this.asAdmin().addStep(new VertexStep<>(this.asAdmin(), Vertex.class, Direction.OUT, labels));
+ }
+
/**
* Map the {@link Vertex} to its incoming adjacent vertices given the edge labels.
*
@@ -426,6 +478,21 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
return this.asAdmin().addStep(new VertexStep<>(this.asAdmin(), Vertex.class, Direction.IN, edgeLabels));
}
+ /**
+ * Map the {@link Vertex} to its incoming adjacent vertices given the edge labels. The arguments for the
+ * labels must be either a {@code String} or a {@link GValue<String>}. For internal use for parameterization.
+ *
+ * @param edgeLabels the edge labels to traverse
+ * @return the traversal with an appended {@link VertexStep}.
+ * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#vertex-steps" target="_blank">Reference Documentation - Vertex Step</a>
+ * @since 4.0.0
+ */
+ public default GraphTraversal<S, Vertex> in(final GValue<String> label, final GValue<String>... edgeLabels) {
+ final GValue<String>[] labels = CollectionUtil.addFirst(edgeLabels, label, GValue.class);
+ this.asAdmin().getGremlinLang().addStep(GraphTraversal.Symbols.in, label, edgeLabels);
+ return this.asAdmin().addStep(new VertexStep<>(this.asAdmin(), Vertex.class, Direction.IN, labels));
+ }
+
/**
* Map the {@link Vertex} to its adjacent vertices given the edge labels.
*
@@ -439,6 +506,21 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
return this.asAdmin().addStep(new VertexStep<>(this.asAdmin(), Vertex.class, Direction.BOTH, edgeLabels));
}
+ /**
+ * Map the {@link Vertex} to its adjacent vertices given the edge labels. The arguments for the labels must be
+ * either a {@code String} or a {@link GValue<String>}. For internal use for parameterization.
+ *
+ * @param edgeLabels the edge labels to traverse
+ * @return the traversal with an appended {@link VertexStep}.
+ * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#vertex-steps" target="_blank">Reference Documentation - Vertex Step</a>
+ * @since 4.0.0
+ */
+ public default GraphTraversal<S, Vertex> both(final GValue<String> label, final GValue<String>... edgeLabels) {
+ final GValue<String>[] labels = CollectionUtil.addFirst(edgeLabels, label, GValue.class);
+ this.asAdmin().getGremlinLang().addStep(GraphTraversal.Symbols.both, label, edgeLabels);
+ return this.asAdmin().addStep(new VertexStep<>(this.asAdmin(), Vertex.class, Direction.BOTH, labels));
+ }
+
/**
* Map the {@link Vertex} to its incident edges given the direction and edge labels.
*
@@ -453,6 +535,23 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
return this.asAdmin().addStep(new VertexStep<>(this.asAdmin(), Edge.class, direction, edgeLabels));
}
+
+ /**
+ * Map the {@link Vertex} to its incident edges given the direction and edge labels. The arguments for the
+ * labels must be either a {@code String} or a {@link GValue<String>}. For internal use for parameterization.
+ *
+ * @param direction the direction to traverse from the current vertex
+ * @param edgeLabels the edge labels to traverse
+ * @return the traversal with an appended {@link VertexStep}.
+ * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#vertex-steps" target="_blank">Reference Documentation - Vertex Step</a>
+ * @since 4.0.0
+ */
+ public default GraphTraversal<S, Edge> toE(final Direction direction, final GValue<String> edgeLabel, final GValue<String>... edgeLabels) {
+ this.asAdmin().getGremlinLang().addStep(GraphTraversal.Symbols.toE, direction, edgeLabel, edgeLabels);
+ final GValue<String>[] labels = CollectionUtil.addFirst(edgeLabels, edgeLabel, GValue.class);
+ return this.asAdmin().addStep(new VertexStep<>(this.asAdmin(), Edge.class, direction, labels));
+ }
+
/**
* Map the {@link Vertex} to its outgoing incident edges given the edge labels.
*
@@ -466,6 +565,21 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
return this.asAdmin().addStep(new VertexStep<>(this.asAdmin(), Edge.class, Direction.OUT, edgeLabels));
}
+ /**
+ * Map the {@link Vertex} to its outgoing incident edges given the edge labels. The arguments for the labels
+ * must be either a {@code String} or a {@link GValue<String>}. For internal use for parameterization.
+ *
+ * @param edgeLabels the edge labels to traverse
+ * @return the traversal with an appended {@link VertexStep}.
+ * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#vertex-steps" target="_blank">Reference Documentation - Vertex Step</a>
+ * @since 4.0.0
+ */
+ public default GraphTraversal<S, Edge> outE(final GValue<String> label, final GValue<String>... edgeLabels) {
+ final GValue<String>[] labels = CollectionUtil.addFirst(edgeLabels, label, GValue.class);
+ this.asAdmin().getGremlinLang().addStep(GraphTraversal.Symbols.outE, label, edgeLabels);
+ return this.asAdmin().addStep(new VertexStep<>(this.asAdmin(), Edge.class, Direction.OUT, labels));
+ }
+
/**
* Map the {@link Vertex} to its incoming incident edges given the edge labels.
*
@@ -479,6 +593,22 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
return this.asAdmin().addStep(new VertexStep<>(this.asAdmin(), Edge.class, Direction.IN, edgeLabels));
}
+ /**
+ * Map the {@link Vertex} to its incoming incident edges given the edge labels. The arguments for the labels
+ * must be either a {@code String} or a {@link GValue<String>}. For internal use for parameterization.
+ *
+ * @param edgeLabels the edge labels to traverse
+ * @return the traversal with an appended {@link VertexStep}.
+ * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#vertex-steps" target="_blank">Reference Documentation - Vertex Step</a>
+ * @since 4.0.0
+ */
+ public default GraphTraversal<S, Edge> inE(final GValue<String> label, final GValue<String>... edgeLabels) {
+ final GValue<String>[] labels = CollectionUtil.addFirst(edgeLabels, label, GValue.class);
+ this.asAdmin().getGremlinLang().addStep(GraphTraversal.Symbols.inE, label, edgeLabels);
+ return this.asAdmin().addStep(new VertexStep<>(this.asAdmin(), Edge.class, Direction.IN, labels));
+ }
+
+
/**
* Map the {@link Vertex} to its incident edges given the edge labels.
*
@@ -492,6 +622,21 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
return this.asAdmin().addStep(new VertexStep<>(this.asAdmin(), Edge.class, Direction.BOTH, edgeLabels));
}
+ /**
+ * Map the {@link Vertex} to its incident edges given the edge labels. The arguments for the labels must be
+ * either a {@code String} or a {@link GValue<String>}. For internal use for parameterization.
+ *
+ * @param edgeLabels the edge labels to traverse
+ * @return the traversal with an appended {@link VertexStep}.
+ * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#vertex-steps" target="_blank">Reference Documentation - Vertex Step</a>
+ * @since 4.0.0
+ */
+ public default GraphTraversal<S, Edge> bothE(final GValue<String> label, final GValue<String>... edgeLabels) {
+ final GValue<String>[] labels = CollectionUtil.addFirst(edgeLabels, label, GValue.class);
+ this.asAdmin().getGremlinLang().addStep(GraphTraversal.Symbols.bothE, label, edgeLabels);
+ return this.asAdmin().addStep(new VertexStep<>(this.asAdmin(), Edge.class, Direction.BOTH, labels));
+ }
+
/**
* Map the {@link Edge} to its incident vertices given the direction.
*
@@ -1121,6 +1266,20 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
return this.asAdmin().addStep(new AddVertexStep<>(this.asAdmin(), vertexLabelTraversal.asAdmin()));
}
+ /**
+ * Adds a {@link Vertex}.
+ *
+ * @param vertexLabel the label of the {@link Vertex} to add
+ * @return the traversal with the {@link AddVertexStep} added
+ * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#addvertex-step" target="_blank">Reference Documentation - AddVertex Step</a>
+ * @since 4.0.0
+ */
+ public default GraphTraversal<S, Vertex> addV(final GValue<String> vertexLabel) {
+ if (null == vertexLabel || null == vertexLabel.get()) throw new IllegalArgumentException("vertexLabel cannot be null");
+ this.asAdmin().getGremlinLang().addStep(GraphTraversal.Symbols.addV, vertexLabel);
+ return this.asAdmin().addStep(new AddVertexStep<>(this.asAdmin(), vertexLabel));
+ }
+
/**
* Adds a {@link Vertex} with a default vertex label.
*
@@ -1179,6 +1338,21 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
return this.asAdmin().addStep(step);
}
+ /**
+ * Performs a merge (i.e. upsert) style operation for an {@link Vertex} using a {@code Map} as an argument.
+ * The {@code Map} represents search criteria and will match each of the supplied key/value pairs where the keys
+ * may be {@code String} property values or a value of {@link T}. If a match is not made it will use that search
+ * criteria to create the new {@link Vertex}.
+ *
+ * @param searchCreate This {@code Map} can have a key of {@link T} or a {@code String}.
+ * @since 4.0.0
+ */
+ public default GraphTraversal<S, Vertex> mergeV(final GValue<Map<Object, Object>> searchCreate) {
+ this.asAdmin().getGremlinLang().addStep(GraphTraversal.Symbols.mergeV, searchCreate);
+ final MergeVertexStep<S> step = new MergeVertexStep(this.asAdmin(), false, null == searchCreate ? GValue.ofMap(null) : searchCreate);
+ return this.asAdmin().addStep(step);
+ }
+
/**
* Spawns a {@link GraphTraversal} by doing a merge (i.e. upsert) style operation for an {@link Edge} using an
* incoming {@code Map} as an argument.
@@ -1220,6 +1394,20 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
return this.asAdmin().addStep(step);
}
+ /**
+ * Spawns a {@link GraphTraversal} by doing a merge (i.e. upsert) style operation for an {@link Edge} using a
+ * {@code Map} as an argument.
+ *
+ * @param searchCreate This {@code Map} can have a key of {@link T} {@link Direction} or a {@code String}.
+ * @since 4.0.0
+ */
+ public default GraphTraversal<S, Edge> mergeE(final GValue<Map<Object, Object>> searchCreate) {
+ // get a construction time exception if the Map is bad
+ this.asAdmin().getGremlinLang().addStep(GraphTraversal.Symbols.mergeE, searchCreate);
+ final MergeEdgeStep<S> step = new MergeEdgeStep(this.asAdmin(), false, null == searchCreate ? GValue.ofMap(null) : searchCreate);
+ return this.asAdmin().addStep(step);
+ }
+
/**
* Adds an {@link Edge} with the specified edge label.
*
@@ -1246,21 +1434,35 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
}
/**
- * Provide {@code to()}-modulation to respective steps.
+ * Adds an {@link Edge} with the specified edge label.
*
- * @param toStepLabel the step label to modulate to.
- * @return the traversal with the modified {@link FromToModulating} step.
- * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#to-step" target="_blank">Reference Documentation - To Step</a>
+ * @param edgeLabel the label of the newly added edge
+ * @return the traversal with the {@link AddEdgeStep} added
+ * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#addedge-step" target="_blank">Reference Documentation - AddEdge Step</a>
+ * @since 4.0.0
+ */
+ public default GraphTraversal<S, Edge> addE(final GValue<String> edgeLabel) {
+ this.asAdmin().getGremlinLang().addStep(GraphTraversal.Symbols.addE, edgeLabel);
+ return this.asAdmin().addStep(new AddEdgeStep<>(this.asAdmin(), edgeLabel));
+ }
+
+ /**
+ * When used as a modifier to {@link #addE(String)} this method specifies the traversal to use for selecting the
+ * outgoing vertex of the newly added {@link Edge}.
+ *
+ * @param fromVertex the traversal for selecting the outgoing vertex
+ * @return the traversal with the modified {@link AddEdgeStep}
+ * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#addedge-step" target="_blank">Reference Documentation - From Step</a>
* @since 3.1.0-incubating
*/
- public default GraphTraversal<S, E> to(final String toStepLabel) {
+ public default GraphTraversal<S, E> from(final Traversal<?, Vertex> fromVertex) {
final Step<?,?> prev = this.asAdmin().getEndStep();
if (!(prev instanceof FromToModulating))
throw new IllegalArgumentException(String.format(
- "The to() step cannot follow %s", prev.getClass().getSimpleName()));
+ "The from() step cannot follow %s", prev.getClass().getSimpleName()));
- this.asAdmin().getGremlinLang().addStep(Symbols.to, toStepLabel);
- ((FromToModulating) prev).addTo(toStepLabel);
+ this.asAdmin().getGremlinLang().addStep(Symbols.from, fromVertex);
+ ((FromToModulating) prev).addFrom(fromVertex.asAdmin());
return this;
}
@@ -1285,21 +1487,21 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
/**
* When used as a modifier to {@link #addE(String)} this method specifies the traversal to use for selecting the
- * incoming vertex of the newly added {@link Edge}.
+ * outgoing vertex of the newly added {@link Edge}.
*
- * @param toVertex the traversal for selecting the incoming vertex
+ * @param fromVertex the vertex for selecting the outgoing vertex
* @return the traversal with the modified {@link AddEdgeStep}
* @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#addedge-step" target="_blank">Reference Documentation - From Step</a>
- * @since 3.1.0-incubating
+ * @since 4.0.0
*/
- public default GraphTraversal<S, E> to(final Traversal<?, Vertex> toVertex) {
+ public default GraphTraversal<S, E> from(final GValue<Vertex> fromVertex) {
final Step<?,?> prev = this.asAdmin().getEndStep();
if (!(prev instanceof FromToModulating))
throw new IllegalArgumentException(String.format(
- "The to() step cannot follow %s", prev.getClass().getSimpleName()));
+ "The from() step cannot follow %s", prev.getClass().getSimpleName()));
- this.asAdmin().getGremlinLang().addStep(Symbols.to, toVertex);
- ((FromToModulating) prev).addTo(toVertex.asAdmin());
+ this.asAdmin().getGremlinLang().addStep(GraphTraversal.Symbols.from, fromVertex);
+ ((FromToModulating) prev).addFrom(__.constant(fromVertex).asAdmin());
return this;
}
@@ -1307,19 +1509,38 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
* When used as a modifier to {@link #addE(String)} this method specifies the traversal to use for selecting the
* outgoing vertex of the newly added {@link Edge}.
*
- * @param fromVertex the traversal for selecting the outgoing vertex
+ * @param fromVertex the vertex for selecting the outgoing vertex
* @return the traversal with the modified {@link AddEdgeStep}
* @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#addedge-step" target="_blank">Reference Documentation - From Step</a>
- * @since 3.1.0-incubating
+ * @since 3.3.0
*/
- public default GraphTraversal<S, E> from(final Traversal<?, Vertex> fromVertex) {
+ public default GraphTraversal<S, E> from(final Vertex fromVertex) {
final Step<?,?> prev = this.asAdmin().getEndStep();
if (!(prev instanceof FromToModulating))
throw new IllegalArgumentException(String.format(
"The from() step cannot follow %s", prev.getClass().getSimpleName()));
this.asAdmin().getGremlinLang().addStep(Symbols.from, fromVertex);
- ((FromToModulating) prev).addFrom(fromVertex.asAdmin());
+ ((FromToModulating) prev).addFrom(__.constant(fromVertex).asAdmin());
+ return this;
+ }
+
+ /**
+ * Provide {@code to()}-modulation to respective steps.
+ *
+ * @param toStepLabel the step label to modulate to.
+ * @return the traversal with the modified {@link FromToModulating} step.
+ * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#to-step" target="_blank">Reference Documentation - To Step</a>
+ * @since 3.1.0-incubating
+ */
+ public default GraphTraversal<S, E> to(final String toStepLabel) {
+ final Step<?,?> prev = this.asAdmin().getEndStep();
+ if (!(prev instanceof FromToModulating))
+ throw new IllegalArgumentException(String.format(
+ "The to() step cannot follow %s", prev.getClass().getSimpleName()));
+
+ this.asAdmin().getGremlinLang().addStep(Symbols.to, toStepLabel);
+ ((FromToModulating) prev).addTo(toStepLabel);
return this;
}
@@ -1330,36 +1551,56 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
* @param toVertex the vertex for selecting the incoming vertex
* @return the traversal with the modified {@link AddEdgeStep}
* @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#addedge-step" target="_blank">Reference Documentation - From Step</a>
- * @since 3.3.0
+ * @since 4.0.0
*/
- public default GraphTraversal<S, E> to(final Vertex toVertex) {
+ public default GraphTraversal<S, E> to(final GValue<Vertex> toVertex) {
final Step<?,?> prev = this.asAdmin().getEndStep();
if (!(prev instanceof FromToModulating))
throw new IllegalArgumentException(String.format(
"The to() step cannot follow %s", prev.getClass().getSimpleName()));
- this.asAdmin().getGremlinLang().addStep(Symbols.to, toVertex);
+ this.asAdmin().getGremlinLang().addStep(GraphTraversal.Symbols.to, toVertex);
((FromToModulating) prev).addTo(__.constant(toVertex).asAdmin());
return this;
}
/**
* When used as a modifier to {@link #addE(String)} this method specifies the traversal to use for selecting the
- * outgoing vertex of the newly added {@link Edge}.
+ * incoming vertex of the newly added {@link Edge}.
*
- * @param fromVertex the vertex for selecting the outgoing vertex
+ * @param toVertex the traversal for selecting the incoming vertex
+ * @return the traversal with the modified {@link AddEdgeStep}
+ * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#addedge-step" target="_blank">Reference Documentation - From Step</a>
+ * @since 3.1.0-incubating
+ */
+ public default GraphTraversal<S, E> to(final Traversal<?, Vertex> toVertex) {
+ final Step<?,?> prev = this.asAdmin().getEndStep();
+ if (!(prev instanceof FromToModulating))
+ throw new IllegalArgumentException(String.format(
+ "The to() step cannot follow %s", prev.getClass().getSimpleName()));
+
+ this.asAdmin().getGremlinLang().addStep(Symbols.to, toVertex);
+ ((FromToModulating) prev).addTo(toVertex.asAdmin());
+ return this;
+ }
+
+ /**
+ * When used as a modifier to {@link #addE(String)} this method specifies the traversal to use for selecting the
+ * incoming vertex of the newly added {@link Edge}.
+ *
+ * @param toVertex the vertex for selecting the incoming vertex
* @return the traversal with the modified {@link AddEdgeStep}
* @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#addedge-step" target="_blank">Reference Documentation - From Step</a>
* @since 3.3.0
*/
- public default GraphTraversal<S, E> from(final Vertex fromVertex) {
+ public default GraphTraversal<S, E> to(final Vertex toVertex) {
final Step<?,?> prev = this.asAdmin().getEndStep();
if (!(prev instanceof FromToModulating))
throw new IllegalArgumentException(String.format(
- "The from() step cannot follow %s", prev.getClass().getSimpleName()));
+ "The to() step cannot follow %s", prev.getClass().getSimpleName()));
- this.asAdmin().getGremlinLang().addStep(Symbols.from, fromVertex);
- ((FromToModulating) prev).addFrom(__.constant(fromVertex).asAdmin());
+ this.asAdmin().getGremlinLang().addStep(Symbols.to, toVertex);
+ ((FromToModulating) prev).addTo(__.constant(toVertex).asAdmin());
return this;
}
@@ -1416,6 +1657,21 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
return this.asAdmin().addStep(call);
}
+ /**
+ * Perform the specified service call with the specified static parameters.
+ *
+ * @param service the name of the service call
+ * @param params static parameter map (no nested traversals)
+ * @return the traversal with an appended {@link CallStep}.
+ * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#call-step" target="_blank">Reference Documentation - Call Step</a>
+ * @since 4.0.0
+ */
+ default <E> GraphTraversal<S, E> call(final String service, final GValue<Map> params) {
+ this.asAdmin().getGremlinLang().addStep(GraphTraversal.Symbols.call, service, params);
+ final CallStep<S,E> call = new CallStep<>(this.asAdmin(), false, service, params);
+ return this.asAdmin().addStep(call);
+ }
+
/**
* Perform the specified service call with dynamic parameters produced by the specified child traversal.
*
@@ -1451,6 +1707,25 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
return this.asAdmin().addStep(step);
}
+ /**
+ * Perform the specified service call with both static and dynamic parameters produced by the specified child
+ * traversal. These parameters will be merged at execution time per the provider implementation. Reference
+ * implementation merges dynamic into static (dynamic will overwrite static).
+ *
+ * @param service the name of the service call
+ * @param params static parameter map (no nested traversals)
+ * @param childTraversal a traversal that will produce a Map of parameters for the service call when invoked.
+ * @return the traversal with an appended {@link CallStep}.
+ * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#call-step" target="_blank">Reference Documentation - Call Step</a>
+ * @since 4.0.0
+ */
+ default <E> GraphTraversal<S, E> call(final String service, final GValue<Map> params, final Traversal<?, Map<?,?>> childTraversal) {
+ this.asAdmin().getGremlinLang().addStep(GraphTraversal.Symbols.call, service, params, childTraversal);
+ final CallStep<S,E> step = null == childTraversal ? new CallStep(this.asAdmin(), false, service, params) :
+ new CallStep(this.asAdmin(), false, service, params, childTraversal.asAdmin());
+ return this.asAdmin().addStep(step);
+ }
+
/**
* Concatenate values of an arbitrary number of string traversals to the incoming traverser.
*
@@ -1900,6 +2175,18 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
return this.asAdmin().addStep(new DifferenceStep<>(this.asAdmin(), values));
}
+ /**
+ * Calculates the difference between the list traverser and list argument.
+ *
+ * @return the traversal with an appended {@link DifferenceStep}.
+ * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#difference-step" target="_blank">Reference Documentation - Difference Step</a>
+ * @since 4.0.0
+ */
+ public default GraphTraversal<S, Set<?>> difference(final GValue<Object> values) {
+ this.asAdmin().getGremlinLang().addStep(GraphTraversal.Symbols.difference, values);
+ return this.asAdmin().addStep(new DifferenceStep<>(this.asAdmin(), values));
+ }
+
/**
* Calculates the disjunction between the list traverser and list argument.
*
@@ -1912,6 +2199,18 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
return this.asAdmin().addStep(new DisjunctStep<>(this.asAdmin(), values));
}
+ /**
+ * Calculates the disjunction between the list traverser and list argument.
+ *
+ * @return the traversal with an appended {@link DisjunctStep}.
+ * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#disjunct-step" target="_blank">Reference Documentation - Disjunct Step</a>
+ * @since 4.0.0
+ */
+ public default GraphTraversal<S, Set<?>> disjunct(final GValue<Object> values) {
+ this.asAdmin().getGremlinLang().addStep(GraphTraversal.Symbols.disjunct, values);
+ return this.asAdmin().addStep(new DisjunctStep<>(this.asAdmin(), values));
+ }
+
/**
* Calculates the intersection between the list traverser and list argument.
*
@@ -1924,6 +2223,18 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
return this.asAdmin().addStep(new IntersectStep<>(this.asAdmin(), values));
}
+ /**
+ * Calculates the intersection between the list traverser and list argument.
+ *
+ * @return the traversal with an appended {@link IntersectStep}.
+ * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#intersect-step" target="_blank">Reference Documentation - Intersect Step</a>
+ * @since 4.0.0
+ */
+ public default GraphTraversal<S, Set<?>> intersect(final GValue<Object> values) {
+ this.asAdmin().getGremlinLang().addStep(GraphTraversal.Symbols.intersect, values);
+ return this.asAdmin().addStep(new IntersectStep<>(this.asAdmin(), values));
+ }
+
/**
* Joins together the elements of the incoming list traverser together with the provided delimiter.
*
@@ -1936,6 +2247,18 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
return this.asAdmin().addStep(new ConjoinStep<>(this.asAdmin(), delimiter));
}
+ /**
+ * Joins together the elements of the incoming list traverser together with the provided delimiter.
+ *
+ * @return the traversal with an appended {@link ConjoinStep}.
+ * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#conjoin-step" target="_blank">Reference Documentation - Conjoin Step</a>
+ * @since 4.0.0
+ */
+ public default GraphTraversal<S, String> conjoin(final GValue<String> delimiter) {
+ this.asAdmin().getGremlinLang().addStep(GraphTraversal.Symbols.conjoin, delimiter);
+ return this.asAdmin().addStep(new ConjoinStep<>(this.asAdmin(), delimiter));
+ }
+
/**
* Merges the list traverser and list argument. Also known as union.
*
@@ -1948,6 +2271,18 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
return this.asAdmin().addStep(new MergeStep<>(this.asAdmin(), values));
}
+ /**
+ * Merges the list traverser and list argument. Also known as union.
+ *
+ * @return the traversal with an appended {@link MergeStep}.
+ * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#merge-step" target="_blank">Reference Documentation - Merge Step</a>
+ * @since 4.0.0
+ */
+ public default <E2> GraphTraversal<S, E2> merge(final GValue<Object> values) {
+ this.asAdmin().getGremlinLang().addStep(GraphTraversal.Symbols.merge, values);
+ return this.asAdmin().addStep(new MergeStep<>(this.asAdmin(), values));
+ }
+
/**
* Combines the list traverser and list argument. Also known as concatenation or append.
*
@@ -1960,6 +2295,18 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
return this.asAdmin().addStep(new CombineStep<>(this.asAdmin(), values));
}
+ /**
+ * Combines the list traverser and list argument. Also known as concatenation or append.
+ *
+ * @return the traversal with an appended {@link CombineStep}.
+ * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#combine-step" target="_blank">Reference Documentation - Combine Step</a>
+ * @since 4.0.0
+ */
+ public default GraphTraversal<S, List<?>> combine(final GValue<Object> values) {
+ this.asAdmin().getGremlinLang().addStep(GraphTraversal.Symbols.combine, values);
+ return this.asAdmin().addStep(new CombineStep<>(this.asAdmin(), values));
+ }
+
/**
* Calculates the cartesian product between the list traverser and list argument.
*
@@ -1972,6 +2319,18 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
return this.asAdmin().addStep(new ProductStep<>(this.asAdmin(), values));
}
+ /**
+ * Calculates the cartesian product between the list traverser and list argument.
+ *
+ * @return the traversal with an appended {@link ProductStep}.
+ * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#product-step" target="_blank">Reference Documentation - Product Step</a>
+ * @since 4.0.0
+ */
+ public default GraphTraversal<S, List<List<?>>> product(final GValue<Object> values) {
+ this.asAdmin().getGremlinLang().addStep(GraphTraversal.Symbols.product, values);
+ return this.asAdmin().addStep(new ProductStep<>(this.asAdmin(), values));
+ }
+
///////////////////// FILTER STEPS /////////////////////
/**
@@ -2310,6 +2669,22 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
return this.asAdmin().addStep(new TraversalFilterStep(this.asAdmin(), __.values(propertyKey)));
}
+ /**
+ * Filters vertices, edges and vertex properties based on their properties.
+ *
+ * @param label the label of the {@link Element}
+ * @param propertyKey the key of the property to filter on
+ * @param value the value to compare the accessor value to for equality
+ * @return the traversal with an appended {@link HasStep}
+ * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#has-step" target="_blank">Reference Documentation - Has Step</a>
+ * @since 4.0.0
+ */
+ public default GraphTraversal<S, E> has(final GValue<String> label, final String propertyKey, final Object value) {
+ this.asAdmin().getGremlinLang().addStep(GraphTraversal.Symbols.has, label.get(), propertyKey, value);
+ TraversalHelper.addHasContainer(this.asAdmin(), new HasContainer(T.label.getAccessor(), P.eq(label)));
+ return TraversalHelper.addHasContainer(this.asAdmin(), new HasContainer(propertyKey, value instanceof P ? (P) value : P.eq(value)));
+ }
+
/**
* Filters vertices, edges and vertex properties based on the non-existence of properties.
*
@@ -2337,11 +2712,7 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
// groovy evaluation seems to do strange things with varargs given hasLabel(null, null). odd someone would
// do this but the failure is ugly if not handled.
- final int otherLabelsLength = null == otherLabels ? 0 : otherLabels.length;
- final String[] labels = new String[otherLabelsLength + 1];
- labels[0] = label;
- if (otherLabelsLength > 0)
- System.arraycopy(otherLabels, 0, labels, 1, otherLabelsLength);
+ final String[] labels = CollectionUtil.addFirst(otherLabels, label, String.class);
return TraversalHelper.addHasContainer(this.asAdmin(), new HasContainer(T.label.getAccessor(), labels.length == 1 ? P.eq(labels[0]) : P.within(labels)));
}
@@ -2364,6 +2735,24 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
}
}
+ /**
+ * Filters vertices, edges and vertex properties based on their label.
+ *
+ * @param label the label of the {@link Element}
+ * @param otherLabels additional labels of the {@link Element}
+ * @return the traversal with an appended {@link HasStep}
+ * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#has-step" target="_blank">Reference Documentation - Has Step</a>
+ * @since 4.0.0
+ */
+ public default GraphTraversal<S, E> hasLabel(final GValue<String> label, final GValue<String>... otherLabels) {
+ this.asAdmin().getGremlinLang().addStep(GraphTraversal.Symbols.hasLabel, label, otherLabels);
+
+ // groovy evaluation seems to do strange things with varargs given hasLabel(null, null). odd someone would
+ // do this but the failure is ugly if not handled.
+ final Object[] labels = CollectionUtil.addFirst(otherLabels, label, GValue.class);
+ return TraversalHelper.addHasContainer(this.asAdmin(), new HasContainer(T.label.getAccessor(), labels.length == 1 ? P.eq(labels[0]) : P.within(labels)));
+ }
+
/**
* Filters vertices, edges and vertex properties based on their identifier.
*
@@ -2376,10 +2765,15 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
public default GraphTraversal<S, E> hasId(final Object id, final Object... otherIds) {
if (id instanceof P) {
return this.hasId((P) id);
- }
- else {
+ } else {
this.asAdmin().getGremlinLang().addStep(Symbols.hasId, id, otherIds);
+ // the logic for dealing with hasId([]) is sketchy historically, just trying to maintain what we were
+ // originally testing prior to GValue.
+ if (id instanceof GValue && ((GValue) id).getType().isCollection()) {
+ return TraversalHelper.addHasContainer(this.asAdmin(), new HasContainer(T.id.getAccessor(), new P(Contains.within, id)));
+ }
+
//using ArrayList given P.within() turns all arguments into lists
final List<Object> ids = new ArrayList<>();
if (id instanceof Object[]) {
@@ -2388,8 +2782,9 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
// as ids are unrolled when it's in array, they should also be unrolled when it's a list.
// this also aligns with behavior of hasId() when it's pushed down to g.V() (TINKERPOP-2863)
ids.addAll((Collection<?>) id);
- } else
+ } else {
ids.add(id);
+ }
// unrolling ids from lists works cleaner with Collection too, as otherwise they will need to
// be turned into array first
@@ -2575,6 +2970,19 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
return this.asAdmin().addStep(new CoinStep<>(this.asAdmin(), probability));
}
+ /**
+ * Filter the <code>E</code> object given a biased coin toss. For internal use for parameterization features.
+ *
+ * @param probability the probability that the object will pass through the filter
+ * @return the traversal with an appended {@link CoinStep}.
+ * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#coin-step" target="_blank">Reference Documentation - Coin Step</a>
+ * @since 4.0.0
+ */
+ public default GraphTraversal<S, E> coin(final GValue<Double> probability) {
+ this.asAdmin().getGremlinLang().addStep(GraphTraversal.Symbols.coin, probability);
+ return this.asAdmin().addStep(new CoinStep<>(this.asAdmin(), probability));
+ }
+
/**
* Filter the objects in the traversal by the number of them to pass through the stream. Those before the value
* of {@code low} do not pass through and those that exceed the value of {@code high} will end the iteration.
@@ -3970,6 +4378,73 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
return this;
}
+ /**
+ * This is a step modulator to a {@link TraversalOptionParent} like {@code choose()} or {@code mergeV()} where the
+ * provided argument associated to the {@code token} is applied according to the semantics of the step. Please see
+ * the documentation of such steps to understand the usage context.
+ *
+ * @param token the token that would trigger this option which may be a {@link Pick}, {@link Merge},
+ * a {@link Traversal}, {@link Predicate}, or object depending on the step being modulated.
+ * @param traversalOption the option as a traversal
+ * @return the traversal with the modulated step
+ * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#choose-step" target="_blank">Reference Documentation - Choose Step</a>
+ * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#mergev-step" target="_blank">Reference Documentation - MergeV Step</a>
+ * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#mergee-step" target="_blank">Reference Documentation - MergeE Step</a>
+ * @since 3.0.0-incubating
+ */
+ public default <M, E2> GraphTraversal<S, E> option(final GValue<M> token, final Traversal<?, E2> traversalOption) {
+ this.asAdmin().getGremlinLang().addStep(GraphTraversal.Symbols.option, token, traversalOption);
+
+ // handle null similar to how option() with Map handles it, otherwise we get a NPE if this one gets used
+ final Traversal.Admin<E,E2> t = null == traversalOption ?
+ new ConstantTraversal<>(null) : (Traversal.Admin<E, E2>) traversalOption.asAdmin();
+ ((TraversalOptionParent<M, E, E2>) this.asAdmin().getEndStep()).addChildOption(token.get(), t);
+ return this;
+ }
+
+ /**
+ * This is a step modulator to a {@link TraversalOptionParent} like {@code choose()} or {@code mergeV()} where the
+ * provided argument associated to the {@code token} is applied according to the semantics of the step. Please see
+ * the documentation of such steps to understand the usage context.
+ *
+ * @param m Provides a {@code Map} as the option which is the same as doing {@code constant(m)}.
+ * @return the traversal with the modulated step
+ * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#mergev-step" target="_blank">Reference Documentation - MergeV Step</a>
+ * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#mergee-step" target="_blank">Reference Documentation - MergeE Step</a>
+ * @since 3.7.3
+ */
+ public default <M, E2> GraphTraversal<S, E> option(final M token, final GValue<Map<Object, Object>> m) {
+ this.asAdmin().getGremlinLang().addStep(GraphTraversal.Symbols.option, token, m);
+ ((TraversalOptionParent<M, E, E2>) this.asAdmin().getEndStep()).addChildOption(token, (Traversal.Admin<E, E2>) new ConstantTraversal<>(m).asAdmin());
+ return this;
+ }
+
+ /**
+ * This is a step modulator to a {@link TraversalOptionParent} like {@code choose()} or {@code mergeV()} where the
+ * provided argument associated to the {@code token} is applied according to the semantics of the step. Please see
+ * the documentation of such steps to understand the usage context.
+ *
+ * @param m Provides a {@code Map} as the option which is the same as doing {@code constant(m)}.
+ * @return the traversal with the modulated step
+ * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#mergev-step" target="_blank">Reference Documentation - MergeV Step</a>
+ * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#mergee-step" target="_blank">Reference Documentation - MergeE Step</a>
+ * @since 3.7.3
+ */
+ public default <M, E2> GraphTraversal<S, E> option(final Merge merge, final GValue<Map<Object, Object>> m, final VertexProperty.Cardinality cardinality) {
+ this.asAdmin().getGremlinLang().addStep(GraphTraversal.Symbols.option, merge, m, cardinality);
+
+ final Map<Object, Object> map = m.get();
+
+ // do explicit cardinality for every single pair in the map
+ for (Object k : map.keySet()) {
+ final Object o = map.get(k);
+ if (!(o instanceof CardinalityValueTraversal))
+ map.put(k, new CardinalityValueTraversal(cardinality, o));
+ }
+ ((TraversalOptionParent<M, E, E2>) this.asAdmin().getEndStep()).addChildOption((M) merge, (Traversal.Admin<E, E2>) new ConstantTraversal<>(m).asAdmin());
+ return this;
+ }
+
////
///////////////////// IO STEPS /////////////////////
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversalSource.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversalSource.java
index a28089247f..63e49e243f 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversalSource.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversalSource.java
@@ -27,6 +27,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
import org.apache.tinkerpop.gremlin.process.traversal.TraversalSource;
import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategies;
import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.step.GValue;
import org.apache.tinkerpop.gremlin.process.traversal.step.branch.UnionStep;
import org.apache.tinkerpop.gremlin.process.traversal.step.map.AddEdgeStartStep;
import org.apache.tinkerpop.gremlin.process.traversal.step.map.AddVertexStartStep;
@@ -406,6 +407,22 @@ public class GraphTraversalSource implements TraversalSource {
return traversal.addStep(step);
}
+ /**
+ * Spawns a {@link GraphTraversal} by doing a merge (i.e. upsert) style operation for an {@link Vertex} using a
+ * {@code Map} as an argument. The {@code Map} represents search criteria and will match each of the supplied
+ * key/value pairs where the keys may be {@code String} property values or a value of {@link T}. If a match is not
+ * made it will use that search criteria to create the new {@link Vertex}.
+ *
+ * @param searchCreate This {@code Map} can have a key of {@link T} or a {@code String}.
+ * @since 4.0.0
+ */
+ public GraphTraversal<Vertex, Vertex> mergeV(final GValue<Map<Object, Object>> searchCreate) {
+ final GraphTraversalSource clone = GraphTraversalSource.this.clone();
+ clone.gremlinLang.addStep(GraphTraversal.Symbols.mergeV, searchCreate);
+ final GraphTraversal.Admin<Vertex, Vertex> traversal = new DefaultGraphTraversal<>(clone);
+ return traversal.addStep(new MergeVertexStep(traversal, true, searchCreate));
+ }
+
/**
* Spawns a {@link GraphTraversal} by doing a merge (i.e. upsert) style operation for an {@link Edge} using a
* {@code Map} as an argument.
@@ -438,6 +455,20 @@ public class GraphTraversalSource implements TraversalSource {
return traversal.addStep(step);
}
+ /**
+ * Spawns a {@link GraphTraversal} by doing a merge (i.e. upsert) style operation for an {@link Edge} using a
+ * {@code Map} as an argument.
+ *
+ * @param searchCreate This {@code Map} can have a key of {@link T} {@link Direction} or a {@code String}.
+ * @since 4.0.0
+ */
+ public GraphTraversal<Edge, Edge> mergeE(final GValue<Map<?, Object>> searchCreate) {
+ final GraphTraversalSource clone = GraphTraversalSource.this.clone();
+ clone.gremlinLang.addStep(GraphTraversal.Symbols.mergeE, searchCreate);
+ final GraphTraversal.Admin<Edge, Edge> traversal = new DefaultGraphTraversal<>(clone);
+ return traversal.addStep(new MergeEdgeStep(traversal, true, searchCreate));
+ }
+
/**
* Spawns a {@link GraphTraversal} starting it with arbitrary values.
*/
@@ -557,6 +588,36 @@ public class GraphTraversalSource implements TraversalSource {
return traversal.addStep(step);
}
+ /**
+ * Spawns a {@link GraphTraversal} starting with values produced by the specified service call with the specified
+ * static parameters.
+ *
+ * @param service the name of the service call
+ * @param params static parameter map (no nested traversals)
+ * @since 4.0.0
+ */
+ public <S> GraphTraversal<S, S> call(final String service, final GValue<Map> params) {
+ final GraphTraversalSource clone = GraphTraversalSource.this.clone();
+ clone.gremlinLang.addStep(GraphTraversal.Symbols.call, service, params);
+ final GraphTraversal.Admin<S, S> traversal = new DefaultGraphTraversal<>(clone);
+ return traversal.addStep(new CallStep<>(traversal, true, service, params));
+ }
+
+ /**
+ * Spawns a {@link GraphTraversal} starting with values produced by the specified service call with the specified
+ * static parameters.
+ *
+ * @param service the name of the service call
+ * @param params static parameter map (no nested traversals)
+ * @since 4.0.0
+ */
+ public <S> GraphTraversal<S, S> call(final String service, final GValue<Map> params, final Traversal<S, Map> childTraversal) {
+ final GraphTraversalSource clone = GraphTraversalSource.this.clone();
+ clone.gremlinLang.addStep(GraphTraversal.Symbols.call, service, params);
+ final GraphTraversal.Admin<S, S> traversal = new DefaultGraphTraversal<>(clone);
+ return traversal.addStep(new CallStep<>(traversal, true, service, params, childTraversal.asAdmin()));
+ }
+
/**
* Merges the results of an arbitrary number of traversals.
*
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 57776db82e..59fdf5f605 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
@@ -25,6 +25,8 @@ import org.apache.tinkerpop.gremlin.process.traversal.Pop;
import org.apache.tinkerpop.gremlin.process.traversal.Scope;
import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
+import org.apache.tinkerpop.gremlin.process.traversal.step.GValue;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.FormatStep;
import org.apache.tinkerpop.gremlin.process.traversal.step.util.Tree;
import org.apache.tinkerpop.gremlin.process.traversal.traverser.util.TraverserSet;
import org.apache.tinkerpop.gremlin.structure.Column;
@@ -110,6 +112,13 @@ public class __ {
return __.<A>start().constant(a);
}
+ /**
+ * @see GraphTraversal#constant(GValue)
+ */
+ public static <A> GraphTraversal<A, A> constant(final GValue<A> a) {
+ return __.<A>start().constant(a);
+ }
+
/**
* @see GraphTraversal#label()
*/
@@ -145,6 +154,13 @@ public class __ {
return __.<Vertex>start().to(direction, edgeLabels);
}
+ /**
+ * @see GraphTraversal#to(Direction, GValue, GValue...)
+ */
+ public static GraphTraversal<Vertex, Vertex> to(final Direction direction, final GValue<String> edgeLabel, final GValue<String>... edgeLabels) {
+ return __.<Vertex>start().to(direction, edgeLabel, edgeLabels);
+ }
+
/**
* @see GraphTraversal#out(String...)
*/
@@ -152,6 +168,13 @@ public class __ {
return __.<Vertex>start().out(edgeLabels);
}
+ /**
+ * @see GraphTraversal#out(GValue, GValue...)
+ */
+ public static GraphTraversal<Vertex, Vertex> out(final GValue<String> edgeLabel, final GValue<String>... edgeLabels) {
+ return __.<Vertex>start().out(edgeLabel, edgeLabels);
+ }
+
/**
* @see GraphTraversal#in(String...)
*/
@@ -159,6 +182,13 @@ public class __ {
return __.<Vertex>start().in(edgeLabels);
}
+ /**
+ * @see GraphTraversal#in(String...)
+ */
+ public static GraphTraversal<Vertex, Vertex> in(final GValue<String> edgeLabel, final GValue<String>... edgeLabels) {
+ return __.<Vertex>start().in(edgeLabel, edgeLabels);
+ }
+
/**
* @see GraphTraversal#both(String...)
*/
@@ -166,6 +196,13 @@ public class __ {
return __.<Vertex>start().both(edgeLabels);
}
+ /**
+ * @see GraphTraversal#both(GValue, GValue...)
+ */
+ public static GraphTraversal<Vertex, Vertex> both(final GValue<String> edgeLabel, final GValue<String>... edgeLabels) {
+ return __.<Vertex>start().both(edgeLabel, edgeLabels);
+ }
+
/**
* @see GraphTraversal#toE(Direction, String...)
*/
@@ -173,6 +210,13 @@ public class __ {
return __.<Vertex>start().toE(direction, edgeLabels);
}
+ /**
+ * @see GraphTraversal#toE(Direction, GValue, GValue...)
+ */
+ public static GraphTraversal<Vertex, Edge> toE(final Direction direction, final GValue<String> edgeLabel, final GValue<String>... edgeLabels) {
+ return __.<Vertex>start().toE(direction, edgeLabel, edgeLabels);
+ }
+
/**
* @see GraphTraversal#outE(String...)
*/
@@ -180,6 +224,13 @@ public class __ {
return __.<Vertex>start().outE(edgeLabels);
}
+ /**
+ * @see GraphTraversal#outE(GValue, GValue...)
+ */
+ public static GraphTraversal<Vertex, Edge> outE(final GValue<String> edgeLabel, final GValue<String>... edgeLabels) {
+ return __.<Vertex>start().outE(edgeLabel, edgeLabels);
+ }
+
/**
* @see GraphTraversal#inE(String...)
*/
@@ -187,6 +238,13 @@ public class __ {
return __.<Vertex>start().inE(edgeLabels);
}
+ /**
+ * @see GraphTraversal#inE(GValue, GValue...)
+ */
+ public static GraphTraversal<Vertex, Edge> inE(final GValue<String> edgeLabel, final GValue<String>... edgeLabels) {
+ return __.<Vertex>start().inE(edgeLabel, edgeLabels);
+ }
+
/**
* @see GraphTraversal#bothE(String...)
*/
@@ -194,6 +252,13 @@ public class __ {
return __.<Vertex>start().bothE(edgeLabels);
}
+ /**
+ * @see GraphTraversal#bothE(GValue, GValue...)
+ */
+ public static GraphTraversal<Vertex, Edge> bothE(final GValue<String> edgeLabel, final GValue<String>... edgeLabels) {
+ return __.<Vertex>start().bothE(edgeLabel, edgeLabels);
+ }
+
/**
* @see GraphTraversal#toV(Direction)
*/
@@ -512,6 +577,13 @@ public class __ {
return __.<A>start().addV(vertexLabel);
}
+ /**
+ * @see GraphTraversal#addV(GValue)
+ */
+ public static <A> GraphTraversal<A, Vertex> addV(final GValue<String> vertexLabel) {
+ return __.<A>start().addV(vertexLabel);
+ }
+
/**
* @see GraphTraversal#addV(org.apache.tinkerpop.gremlin.process.traversal.Traversal)
*/
@@ -540,6 +612,13 @@ public class __ {
return __.<A>start().mergeV(searchCreate);
}
+ /**
+ * @see GraphTraversal#mergeV(GValue)
+ */
+ public static <A> GraphTraversal<A, Vertex> mergeV(final GValue<Map<Object, Object>> searchCreate) {
+ return __.<A>start().mergeV(searchCreate);
+ }
+
/**
* @see GraphTraversal#mergeV(Traversal)
*/
@@ -554,6 +633,13 @@ public class __ {
return __.<A>start().addE(edgeLabel);
}
+ /**
+ * @see GraphTraversal#addE(GValue)
+ */
+ public static <A> GraphTraversal<A, Edge> addE(final GValue<String> edgeLabel) {
+ return __.<A>start().addE(edgeLabel);
+ }
+
/**
* @see GraphTraversal#addE(Traversal)
*/
@@ -575,6 +661,13 @@ public class __ {
return __.<A>start().mergeE(searchCreate);
}
+ /**
+ * @see GraphTraversal#mergeE(GValue)
+ */
+ public static <A> GraphTraversal<A, Edge> mergeE(final GValue<Map<Object, Object>> searchCreate) {
+ return __.<A>start().mergeE(searchCreate);
+ }
+
/**
* @see GraphTraversal#mergeE(Traversal)
*/
@@ -806,6 +899,13 @@ public class __ {
return __.<A>start().difference(values);
}
+ /**
+ * @see GraphTraversal#difference(GValue)
+ */
+ public static <A> GraphTraversal<A, Set<?>> difference(final GValue<Object> values) {
+ return __.<A>start().difference(values);
+ }
+
/**
* @see GraphTraversal#disjunct(Object)
*/
@@ -813,6 +913,13 @@ public class __ {
return __.<A>start().disjunct(values);
}
+ /**
+ * @see GraphTraversal#disjunct(GValue)
+ */
+ public static <A> GraphTraversal<A, Set<?>> disjunct(final GValue<Object> values) {
+ return __.<A>start().disjunct(values);
+ }
+
/**
* @see GraphTraversal#intersect(Object)
*/
@@ -820,6 +927,13 @@ public class __ {
return __.<A>start().intersect(values);
}
+ /**
+ * @see GraphTraversal#intersect(GValue)
+ */
+ public static <A> GraphTraversal<A, Set<?>> intersect(final GValue<Object> values) {
+ return __.<A>start().intersect(values);
+ }
+
/**
* @see GraphTraversal#conjoin(String)
*/
@@ -827,6 +941,13 @@ public class __ {
return __.<A>start().conjoin(values);
}
+ /**
+ * @see GraphTraversal#conjoin(GValue)
+ */
+ public static <A> GraphTraversal<A, String> conjoin(final GValue<String> values) {
+ return __.<A>start().conjoin(values);
+ }
+
/**
* @see GraphTraversal#merge(Object)
*/
@@ -834,6 +955,13 @@ public class __ {
return __.<A>start().merge(values);
}
+ /**
+ * @see GraphTraversal#merge(GValue)
+ */
+ public static <A, B> GraphTraversal<A, B> merge(final GValue<Object> values) {
+ return __.<A>start().merge(values);
+ }
+
/**
* @see GraphTraversal#combine(Object)
*/
@@ -841,6 +969,13 @@ public class __ {
return __.<A>start().combine(values);
}
+ /**
+ * @see GraphTraversal#combine(GValue)
+ */
+ public static <A> GraphTraversal<A, List<?>> combine(final GValue<Object> values) {
+ return __.<A>start().combine(values);
+ }
+
/**
* @see GraphTraversal#product(Object)
*/
@@ -848,6 +983,13 @@ public class __ {
return __.<A>start().product(values);
}
+ /**
+ * @see GraphTraversal#product(GValue)
+ */
+ public static <A> GraphTraversal<A, List<List<?>>> product(final GValue<Object> values) {
+ return __.<A>start().product(values);
+ }
+
///////////////////// FILTER STEPS /////////////////////
/**
@@ -934,6 +1076,13 @@ public class __ {
return __.<A>start().has(label, propertyKey, value);
}
+ /**
+ * @see GraphTraversal#has(GValue, String, Object)
+ */
+ public static <A> GraphTraversal<A, A> has(final GValue<String> label, final String propertyKey, final Object value) {
+ return __.<A>start().has(label, propertyKey, value);
+ }
+
/**
* @see GraphTraversal#has(String, String, P)
*/
@@ -976,6 +1125,13 @@ public class __ {
return __.<A>start().hasLabel(label, otherLabels);
}
+ /**
+ * @see GraphTraversal#hasLabel(GValue, GValue...)
+ */
+ public static <A> GraphTraversal<A, A> hasLabel(final GValue<String> label, GValue<String>... otherLabels) {
+ return __.<A>start().hasLabel(label, otherLabels);
+ }
+
/**
* @see GraphTraversal#hasLabel(P)
*/
@@ -1074,6 +1230,13 @@ public class __ {
return __.<A>start().coin(probability);
}
+ /**
+ * @see GraphTraversal#coin(GValue)
+ */
+ public static <A> GraphTraversal<A, A> coin(final GValue<Double> probability) {
+ return __.<A>start().coin(probability);
+ }
+
/**
* @see GraphTraversal#range(long, long)
*/
@@ -1517,6 +1680,13 @@ public class __ {
return __.<A>start().call(service, params);
}
+ /**
+ * @see GraphTraversal#call(String, GValue)
+ */
+ public static <A, B> GraphTraversal<A, B> call(final String service, final GValue<Map> params) {
+ return __.<A>start().call(service, params);
+ }
+
/**
* @see GraphTraversal#call(String, Traversal)
*/
@@ -1530,4 +1700,11 @@ public class __ {
public static <A, B> GraphTraversal<A, B> call(final String service, final Map params, final Traversal<?, Map<?,?>> childTraversal) {
return __.<A>start().call(service, params, childTraversal);
}
+
+ /**
+ * @see GraphTraversal#call(String, GValue, Traversal)
+ */
+ public static <A, B> GraphTraversal<A, B> call(final String service, final GValue<Map> params, final Traversal<?, Map<?,?>> childTraversal) {
+ return __.<A>start().call(service, params, childTraversal);
+ }
}
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/lambda/ConstantTraversal.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/lambda/ConstantTraversal.java
index b22d88e66c..3bac69ce48 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/lambda/ConstantTraversal.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/lambda/ConstantTraversal.java
@@ -19,6 +19,7 @@
package org.apache.tinkerpop.gremlin.process.traversal.lambda;
import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
+import org.apache.tinkerpop.gremlin.process.traversal.step.GValue;
import java.util.Objects;
@@ -29,15 +30,23 @@ import java.util.Objects;
*/
public final class ConstantTraversal<S, E> extends AbstractLambdaTraversal<S, E> {
- private final E end;
+ private final GValue<E> end;
public ConstantTraversal(final E end) {
- this.end = end;
+ this.end = null == end ? GValue.of(null) : GValue.of(end);
+ }
+
+ public ConstantTraversal(final GValue<E> end) {
+ this.end = null == end ? GValue.of(null) : end;
}
@Override
public E next() {
- return this.end;
+ return this.end.get();
+ }
+
+ public GValue<E> getEnd() {
+ return end;
}
@Override
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/GType.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/GType.java
new file mode 100644
index 0000000000..4c8777d290
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/GType.java
@@ -0,0 +1,103 @@
+/*
+ * 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;
+
+import org.apache.tinkerpop.gremlin.process.traversal.Path;
+import org.apache.tinkerpop.gremlin.structure.Edge;
+import org.apache.tinkerpop.gremlin.structure.Property;
+import org.apache.tinkerpop.gremlin.structure.Vertex;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * An enum that describes types that are used in the Gremlin language.
+ */
+public enum GType {
+ BIG_DECIMAL(BigDecimal.class),
+ BIG_INTEGER(BigInteger.class),
+ BOOLEAN(Boolean.class),
+ DOUBLE(Double.class),
+ EDGE(Edge.class),
+ INTEGER(Integer.class),
+ LIST(List.class),
+ LONG(Long.class),
+ MAP(Map.class),
+ PATH(Path.class),
+ PROPERTY(Property.class),
+ SET(Set.class),
+ STRING(String.class),
+ UNKNOWN(null),
+ VERTEX(Vertex.class);
+
+ private Class<?> javaType;
+
+ GType(final Class<?> javaType) {
+ this.javaType = javaType;
+ }
+
+ public Class<?> getJavaType() {
+ return this.javaType;
+ }
+
+ /**
+ * Returns {@code true} if the type is a number.
+ */
+ public boolean isNumeric() {
+ return this == INTEGER || this == DOUBLE || this == LONG || this == BIG_INTEGER || this == BIG_DECIMAL;
+ }
+
+ /**
+ * Returns {@code true} if the type is a collection.v
+ */
+ public boolean isCollection() {
+ return this == LIST || this == SET;
+ }
+
+ /**
+ * Returns {@code true} if the type is an element.
+ */
+ public boolean isElement() {
+ return this == VERTEX || this == EDGE;
+ }
+
+ /**
+ * Convert an object to a matching {@link GType} and if not matched return {@link GType#UNKNOWN}.
+ */
+ public static GType getType(final Object object) {
+ if (object instanceof String) return STRING;
+ else if (object instanceof Integer) return INTEGER;
+ else if (object instanceof Boolean) return BOOLEAN;
+ else if (object instanceof Double) return DOUBLE;
+ else if (object instanceof Long) return LONG;
+ else if (object instanceof Map) return MAP;
+ else if (object instanceof List) return LIST;
+ else if (object instanceof Set) return SET;
+ else if (object instanceof Vertex) return VERTEX;
+ else if (object instanceof Edge) return EDGE;
+ else if (object instanceof Path) return PATH;
+ else if (object instanceof Property) return PROPERTY;
+ else if (object instanceof BigInteger) return BIG_INTEGER;
+ else if (object instanceof BigDecimal) return BIG_DECIMAL;
+ else return UNKNOWN;
+ }
+}
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/GValue.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/GValue.java
new file mode 100644
index 0000000000..0608d94a19
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/GValue.java
@@ -0,0 +1,443 @@
+/*
+ * 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;
+
+import org.apache.tinkerpop.gremlin.process.traversal.Path;
+import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
+import org.apache.tinkerpop.gremlin.structure.Edge;
+import org.apache.tinkerpop.gremlin.structure.Element;
+import org.apache.tinkerpop.gremlin.structure.Property;
+import org.apache.tinkerpop.gremlin.structure.Vertex;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+import java.util.stream.Stream;
+
+/**
+ * A {@code GValue} is a variable or literal value that is used in a {@link Traversal}. It is composed of a key-value
+ * pair where the key is the name given to the variable and the value is the object that the variable resolved to. If
+ * the name is not given, the value was provided literally in the traversal. The value of the variable can be any
+ * object. The {@code GValue} also includes the {@link GType} that describes the type it contains.
+ */
+public class GValue<V> implements Cloneable, Serializable {
+ private final String name;
+ private final GType type;
+
+ private final V value;
+
+ private GValue(final GType type, final V value) {
+ this(null, type, value);
+ }
+
+ private GValue(final String name, final GType type, final V value) {
+ this.name = name;
+ this.type = type;
+ this.value = value;
+ }
+
+ /**
+ * Determines if the value held by this object was defined as a variable or a literal value. Literal values simply
+ * have no name.
+ */
+ public boolean isVariable() {
+ return this.name != null;
+ }
+
+ /**
+ * Gets the name of the variable if it was defined as such and returns empty if the value was a literal.
+ */
+ public String getName() {
+ return this.name;
+ }
+
+ /**
+ * Gets the type of the value. The explicit type could be determined with {@code instanceof} on the value, but this
+ * might be helpful for cases where the value was constructed with a {@code null} value which might just return as
+ * {@code Object}.
+ */
+ public GType getType() {
+ return this.type;
+ }
+
+ /**
+ * Determines if the value held is of a {@code null} value.
+ */
+ public boolean isNull() {
+ return this.value == null;
+ }
+
+ /**
+ * Gets the value.
+ */
+ public V get() {
+ return this.value;
+ }
+
+ @Override
+ public String toString() {
+ return isVariable() ?
+ String.format("%s&%s", name, value) : Objects.toString(value);
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ final GValue<?> gValue = (GValue<?>) o;
+ return Objects.equals(name, gValue.name) && type == gValue.type && Objects.equals(value, gValue.value);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(name, type, value);
+ }
+
+ /**
+ * Create a new {@code Var} from a particular value but without the specified name. If the argument provide is
+ * already a {@code GValue} then it is returned as-is.
+ *
+ * @param value the value of the variable
+ */
+ public static <V> GValue<V> of(final V value) {
+ if (value instanceof GValue) return (GValue) value;
+ return new GValue<>(GType.getType(value), value);
+ }
+
+ /**
+ * Create a new {@code Var} with the specified name and value.. If the argument provide is already a
+ * {@code GValue} then it is returned as-is.
+ *
+ * @param name the name of the variable
+ * @param value the value of the variable
+ */
+ public static <V> GValue<V> of(final String name, final V value) {
+ if (value instanceof GValue) throw new IllegalArgumentException("value cannot be a GValue");
+ return new GValue<>(name, GType.getType(value), value);
+ }
+
+ /**
+ * Create a new {@code GValue} for a string value.
+ */
+ public static GValue<String> ofString(final String value) {
+ return new GValue<>(GType.STRING, value);
+ }
+
+ /**
+ * Create a new {@code GValue} for a string value with a specified name.
+ */
+ public static GValue<String> ofString(final String name, final String value) {
+ return new GValue<>(name, GType.STRING, value);
+ }
+
+ /**
+ * Create a new {@code GValue} for an integer value.
+ */
+ public static GValue<Integer> ofInteger(final Integer value) {
+ return new GValue<>(GType.INTEGER, value);
+ }
+
+ /**
+ * Create a new {@code GValue} for an integer value with a specified name.
+ */
+ public static GValue<Integer> ofInteger(final String name, final Integer value) {
+ return new GValue<>(name, GType.INTEGER, value);
+ }
+
+ /**
+ * Create a new {@code GValue} for a boolean value.
+ */
+ public static GValue<Boolean> ofBoolean(final Boolean value) {
+ return new GValue<>(GType.BOOLEAN, value);
+ }
+
+ /**
+ * Create a new {@code GValue} for a boolean value with a specified name.
+ */
+ public static GValue<Boolean> ofBoolean(final String name, final Boolean value) {
+ return new GValue<>(name, GType.BOOLEAN, value);
+ }
+
+ /**
+ * Create a new {@code GValue} for a double value.
+ */
+ public static GValue<Double> ofDouble(final Double value) {
+ return new GValue<>(GType.DOUBLE, value);
+ }
+
+ /**
+ * Create a new {@code GValue} for a double value with a specified name.
+ */
+ public static GValue<Double> ofDouble(final String name, final Double value) {
+ return new GValue<>(name, GType.DOUBLE, value);
+ }
+
+ /**
+ * Create a new {@code GValue} for a BigInteger value.
+ */
+ public static GValue<BigInteger> ofBigInteger(final BigInteger value) {
+ return new GValue<>(GType.BIG_INTEGER, value);
+ }
+
+ /**
+ * Create a new {@code GValue} for a BigInteger value with a specified name.
+ */
+ public static GValue<BigInteger> ofBigInteger(final String name, final BigInteger value) {
+ return new GValue<>(name, GType.BIG_INTEGER, value);
+ }
+
+ /**
+ * Create a new {@code GValue} for a BigDecimal value.
+ */
+ public static GValue<BigDecimal> ofBigDecimal(final BigDecimal value) {
+ return new GValue<>(GType.BIG_DECIMAL, value);
+ }
+
+ /**
+ * Create a new {@code GValue} for a BigDecimal value with a specified name.
+ */
+ public static GValue<BigDecimal> ofBigDecimal(final String name, final BigDecimal value) {
+ return new GValue<>(name, GType.BIG_DECIMAL, value);
+ }
+
+ /**
+ * Create a new {@code GValue} for a long value.
+ */
+ public static GValue<Long> ofLong(final Long value) {
+ return new GValue<>(GType.LONG, value);
+ }
+
+ /**
+ * Create a new {@code GValue} for a long value with a specified name.
+ */
+ public static GValue<Long> ofLong(final String name, final Long value) {
+ return new GValue<>(name, GType.LONG, value);
+ }
+
+ /**
+ * Create a new {@code GValue} for a map value.
+ */
+ public static GValue<Map> ofMap(final Map value) {
+ return new GValue<>(GType.MAP, value);
+ }
+
+ /**
+ * Create a new {@code GValue} for a map value with a specified name.
+ */
+ public static GValue<Map> ofMap(final String name, final Map value) {
+ return new GValue<>(name, GType.MAP, value);
+ }
+
+ /**
+ * Create a new {@code GValue} for a list value.
+ */
+ public static <T> GValue<List<T>> ofList(final List<T> value) {
+ return new GValue<>(GType.LIST, value);
+ }
+
+ /**
+ * Create a new {@code GValue} for a list value with a specified name.
+ */
+ public static <T> GValue<List<T>> ofList(final String name, final List<T> value) {
+ return new GValue<>(name, GType.LIST, value);
+ }
+
+ /**
+ * Create a new {@code GValue} for a set value.
+ */
+ public static GValue<Set> ofSet(final Set value) {
+ return new GValue<>(GType.SET, value);
+ }
+
+ /**
+ * Create a new {@code GValue} for a set value with a specified name.
+ */
+ public static GValue<Set> ofSet(final String name, final Set value) {
+ return new GValue<>(name, GType.SET, value);
+ }
+
+ /**
+ * Create a new {@code GValue} for a vertex value.
+ */
+ public static GValue<Vertex> ofVertex(final Vertex value) {
+ return new GValue<>(GType.VERTEX, value);
+ }
+
+ /**
+ * Create a new {@code GValue} for a vertex value with a specified name.
+ */
+ public static GValue<Vertex> ofVertex(final String name, final Vertex value) {
+ return new GValue<>(name, GType.VERTEX, value);
+ }
+
+ /**
+ * Create a new {@code GValue} for an edge value.
+ */
+ public static GValue<Edge> ofEdge(final Edge value) {
+ return new GValue<>(GType.EDGE, value);
+ }
+
+ /**
+ * Create a new {@code GValue} for an edge value with a specified name.
+ */
+ public static GValue<Edge> ofEdge(final String name, final Edge value) {
+ return new GValue<>(name, GType.EDGE, value);
+ }
+
+ /**
+ * Create a new {@code GValue} for a path value.
+ */
+ public static GValue<Path> ofPath(final Path value) {
+ return new GValue<>(GType.PATH, value);
+ }
+
+ /**
+ * Create a new {@code GValue} for a path value with a specified name.
+ */
+ public static GValue<Path> ofPath(final String name, final Path value) {
+ return new GValue<>(name, GType.PATH, value);
+ }
+
+ /**
+ * Create a new {@code GValue} for a property value.
+ */
+ public static GValue<Property> ofProperty(final Property value) {
+ return new GValue<>(GType.PROPERTY, value);
+ }
+
+ /**
+ * Create a new {@code GValue} for a property value with a specified name.
+ */
+ public static GValue<Property> ofProperty(final String name, final Property value) {
+ return new GValue<>(name, GType.PROPERTY, value);
+ }
+
+ /**
+ * If the object is a {@code GValue} then get its value, otherwise return the object as-is.
+ */
+ public static <T> T getFrom(final Object o) {
+ return o instanceof GValue ? ((GValue<T>) o).get() : (T) o;
+ }
+
+ /**
+ * Tests if the object is a {@link GValue} and if so, checks the type of the value against the provided
+ * {@link GType}.
+ */
+ public static boolean valueInstanceOf(final Object o, final GType type) {
+ return o instanceof GValue && ((GValue) o).getType() == type;
+ }
+
+ /**
+ * Tests if the object is a {@link GValue} and if so, checks if the type of the value is a collection.
+ */
+ public static boolean valueInstanceOfCollection(final Object o) {
+ return o instanceof GValue && ((GValue) o).getType().isCollection();
+ }
+
+ /**
+ * Tests if the object is a {@link GValue} and if so, checks if the type of the value is a numeric.
+ */
+ public static boolean valueInstanceOfNumeric(final Object o) {
+ return o instanceof GValue && ((GValue) o).getType().isNumeric();
+ }
+
+ /**
+ * Checks the type of the object against the provided {@link GType}. If the object is a {@link GValue} then it
+ * can directly check the type, otherwise it will test the given object's class itself using the mappign on the
+ * {@link GType}.
+ */
+ public static boolean instanceOf(final Object o, final GType type) {
+ if (null == o)
+ return false;
+ else if (o instanceof GValue)
+ return ((GValue) o).getType() == type;
+ else
+ return type.getJavaType().isAssignableFrom(o.getClass());
+ }
+
+ /**
+ * Returns {@code true} if the object is a collection or a {@link GValue} that contains a {@link Collection}.
+ */
+ public static boolean instanceOfCollection(final Object o) {
+ return o instanceof Collection || (o instanceof GValue && ((GValue) o).getType().isCollection());
+ }
+
+ /**
+ * Returns {@code true} if the object is an element or a {@link GValue} that contains an {@link Element}.
+ */
+ public static boolean instanceOfElement(final Object o) {
+ return o instanceof Element || (o instanceof GValue && ((GValue) o).getType().isElement());
+ }
+
+ /**
+ * Returns {@code true} if the object is a number or a {@link GValue} that contains a number.
+ */
+ public static boolean instanceOfNumber(final Object o) {
+ return o instanceof Number || (o instanceof GValue && ((GValue) o).getType().isNumeric());
+ }
+
+ /**
+ * The elements in object array argument are examined to see if they are {@link GValue} objects. If they are, they
+ * are preserved as is. If they are not then they are wrapped in a {@link GValue} object.
+ */
+ public static <T> GValue<T>[] ensureGValues(final Object[] args) {
+ return Stream.of(args).map(GValue::of).toArray(GValue[]::new);
+ }
+
+ /**
+ * Converts {@link GValue} objects argument array to their values to prevent them from leaking to the Graph API.
+ * Providers extending from this step should use this method to get actual values to prevent any {@link GValue}
+ * objects from leaking to the Graph API.
+ */
+ public static Object[] resolveToValues(final GValue<?>[] gvalues) {
+ final Object[] values = new Object[gvalues.length];
+ for (int i = 0; i < gvalues.length; i++) {
+ values[i] = gvalues[i].get();
+ }
+ return values;
+ }
+
+ /**
+ * Takes an argument that is either a {@code GValue} or an object and if the former, returns the child object and
+ * if the latter returns the object itself.
+ */
+ public static Object valueOf(final Object either) {
+ if (either instanceof GValue)
+ return ((GValue<?>) either).get();
+ else
+ return either;
+ }
+
+ /**
+ * Takes an argument that is either a {@code GValue} or an object and returns its {@code Number} form, otherwise
+ * throws an exception.
+ */
+ public static Number numberOf(final Object either) {
+ final Object o = valueOf(either);
+ if (o instanceof Number)
+ return (Number) o;
+ else
+ throw new IllegalStateException("Argument is not a number");
+ }
+}
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/CoinStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/CoinStep.java
index e4a44abe93..5fd63ee3de 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/CoinStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/CoinStep.java
@@ -21,6 +21,7 @@ package org.apache.tinkerpop.gremlin.process.traversal.step.filter;
import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
import org.apache.tinkerpop.gremlin.process.traversal.step.Seedable;
+import org.apache.tinkerpop.gremlin.process.traversal.step.GValue;
import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
@@ -29,16 +30,23 @@ import java.util.Random;
import java.util.Set;
/**
+ * A filter step that will randomly allow traversers to pass through the step based on a probability value.
+ *
* @author Marko A. Rodriguez (http://markorodriguez.com)
*/
public final class CoinStep<S> extends FilterStep<S> implements Seedable {
private final Random random = new Random();
- private final double probability;
+ private final GValue<Double> probability;
public CoinStep(final Traversal.Admin traversal, final double probability) {
super(traversal);
- this.probability = probability;
+ this.probability = GValue.ofDouble(probability);
+ }
+
+ public CoinStep(final Traversal.Admin traversal, final GValue<Double> probability) {
+ super(traversal);
+ this.probability = null == probability ? GValue.ofDouble(null) : probability;
}
@Override
@@ -47,7 +55,11 @@ public final class CoinStep<S> extends FilterStep<S> implements Seedable {
}
public double getProbability() {
- return this.probability;
+ return probability.get();
+ }
+
+ public GValue<Double> getProbabilityGValue() {
+ return probability;
}
@Override
@@ -55,11 +67,11 @@ public final class CoinStep<S> extends FilterStep<S> implements Seedable {
long newBulk = 0l;
if (traverser.bulk() < 100) {
for (int i = 0; i < traverser.bulk(); i++) {
- if (this.probability >= random.nextDouble())
+ if (this.probability.get() >= random.nextDouble())
newBulk++;
}
} else {
- newBulk = Math.round(this.probability * traverser.bulk());
+ newBulk = Math.round(this.probability.get() * traverser.bulk());
}
if (0 == newBulk) return false;
traverser.setBulk(newBulk);
@@ -73,7 +85,7 @@ public final class CoinStep<S> extends FilterStep<S> implements Seedable {
@Override
public int hashCode() {
- return super.hashCode() ^ Double.hashCode(this.probability);
+ return super.hashCode() ^ Double.hashCode(this.probability.get());
}
@Override
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AddEdgeStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AddEdgeStep.java
index f5f7280764..db3f72cfe7 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AddEdgeStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AddEdgeStep.java
@@ -21,6 +21,8 @@ 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.FromToModulating;
+import org.apache.tinkerpop.gremlin.process.traversal.step.GType;
+import org.apache.tinkerpop.gremlin.process.traversal.step.GValue;
import org.apache.tinkerpop.gremlin.process.traversal.step.Scoping;
import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent;
import org.apache.tinkerpop.gremlin.process.traversal.step.Writing;
@@ -59,6 +61,11 @@ public class AddEdgeStep<S> extends ScalarMapStep<S, Edge>
this.parameters.set(this, T.label, edgeLabel);
}
+ public AddEdgeStep(final Traversal.Admin traversal, final GValue<String> edgeLabel) {
+ super(traversal);
+ this.parameters.set(this, T.label, edgeLabel);
+ }
+
public AddEdgeStep(final Traversal.Admin traversal, final Traversal.Admin<S,String> edgeLabelTraversal) {
super(traversal);
this.parameters.set(this, T.label, edgeLabelTraversal);
@@ -107,7 +114,7 @@ public class AddEdgeStep<S> extends ScalarMapStep<S, Edge>
edgeLabel, e.getMessage()));
}
- if (!(theTo instanceof Vertex))
+ if (!GValue.instanceOf(theTo, GType.VERTEX))
throw new IllegalStateException(String.format(
"The value given to addE(%s).to() must resolve to a Vertex but %s was specified instead", edgeLabel,
null == theTo ? "null" : theTo.getClass().getSimpleName()));
@@ -121,13 +128,13 @@ public class AddEdgeStep<S> extends ScalarMapStep<S, Edge>
edgeLabel, e.getMessage()));
}
- if (!(theFrom instanceof Vertex))
+ if (!GValue.instanceOf(theFrom, GType.VERTEX))
throw new IllegalStateException(String.format(
"The value given to addE(%s).to() must resolve to a Vertex but %s was specified instead", edgeLabel,
null == theFrom ? "null" : theFrom.getClass().getSimpleName()));
- Vertex toVertex = (Vertex) theTo;
- Vertex fromVertex = (Vertex) theFrom;
+ Vertex toVertex = GValue.getFrom(theTo);
+ Vertex fromVertex = GValue.getFrom(theFrom);
if (toVertex instanceof Attachable)
toVertex = ((Attachable<Vertex>) toVertex)
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AddVertexStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AddVertexStep.java
index 0dfb55c2a1..cfde7d84fc 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AddVertexStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AddVertexStep.java
@@ -20,6 +20,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.Traverser;
+import org.apache.tinkerpop.gremlin.process.traversal.step.GValue;
import org.apache.tinkerpop.gremlin.process.traversal.step.Scoping;
import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent;
import org.apache.tinkerpop.gremlin.process.traversal.step.Writing;
@@ -52,6 +53,10 @@ public class AddVertexStep<S> extends ScalarMapStep<S, Vertex>
this.parameters.set(this, T.label, null == label ? Vertex.DEFAULT_LABEL : label);
userProvidedLabel = label != null;
}
+ public AddVertexStep(final Traversal.Admin traversal, final GValue<String> label) {
+ super(traversal);
+ this.parameters.set(this, T.label, null == label ? Vertex.DEFAULT_LABEL : label);
+ }
public AddVertexStep(final Traversal.Admin traversal, final Traversal.Admin<S,String> vertexLabelTraversal) {
super(traversal);
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/CallStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/CallStep.java
index 2435be373c..3dd99d1703 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/CallStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/CallStep.java
@@ -22,6 +22,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.Step;
import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
import org.apache.tinkerpop.gremlin.process.traversal.step.Configuring;
+import org.apache.tinkerpop.gremlin.process.traversal.step.GValue;
import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent;
import org.apache.tinkerpop.gremlin.process.traversal.step.util.AbstractStep;
import org.apache.tinkerpop.gremlin.process.traversal.step.util.Parameters;
@@ -62,7 +63,7 @@ public final class CallStep<S, E> extends AbstractStep<S, E> implements Traversa
private ServiceCallContext ctx;
private String serviceName;
private Service<S, E> service;
- private Map staticParams;
+ private GValue<Map> staticParams;
private Traversal.Admin<S,Map> mapTraversal;
private Parameters parameters;
@@ -74,20 +75,29 @@ public final class CallStep<S, E> extends AbstractStep<S, E> implements Traversa
}
public CallStep(final Traversal.Admin traversal, final boolean isStart, final String service) {
- this(traversal, isStart, service, null);
+ this(traversal, isStart, service, (Map) null);
}
public CallStep(final Traversal.Admin traversal, final boolean isStart, final String service, final Map staticParams) {
+ this(traversal, isStart, service, GValue.ofMap(staticParams));
+ }
+
+ public CallStep(final Traversal.Admin traversal, final boolean isStart, final String service, final GValue<Map> staticParams) {
this(traversal, isStart, service, staticParams, null);
}
public CallStep(final Traversal.Admin traversal, final boolean isStart, final String service, final Map staticParams,
final Traversal.Admin<S, Map> mapTraversal) {
+ this(traversal, isStart, service, GValue.ofMap(staticParams), mapTraversal);
+ }
+
+ public CallStep(final Traversal.Admin traversal, final boolean isStart, final String service, final GValue<Map> staticParams,
+ final Traversal.Admin<S, Map> mapTraversal) {
super(traversal);
this.isStart = isStart;
this.serviceName = service;
- this.staticParams = staticParams == null ? new LinkedHashMap() : staticParams;
+ this.staticParams = staticParams == null || staticParams.isNull() ? GValue.ofMap(staticParams.getName(), new LinkedHashMap()) : staticParams;
this.mapTraversal = mapTraversal == null ? null : integrateChild(mapTraversal);
this.parameters = new Parameters();
this.ctx = new ServiceCallContext(traversal, this);
@@ -95,13 +105,17 @@ public final class CallStep<S, E> extends AbstractStep<S, E> implements Traversa
protected Service<S, E> service() {
// throws exception for unrecognized service
- return service != null ? service : (service = getServiceRegistry().get(serviceName, isStart, staticParams));
+ return service != null ? service : (service = getServiceRegistry().get(serviceName, isStart, staticParams.get()));
}
public String getServiceName() {
return serviceName;
}
+ public GValue<Map> getStaticParams() {
+ return staticParams;
+ }
+
@Override
protected Traverser.Admin<E> processNextStart() {
if (isStart && first) {
@@ -199,7 +213,7 @@ public final class CallStep<S, E> extends AbstractStep<S, E> implements Traversa
public Map getMergedParams() {
if (mapTraversal == null && parameters.isEmpty()) {
// static params only
- return Collections.unmodifiableMap(this.staticParams);
+ return Collections.unmodifiableMap(this.staticParams.get());
}
return getMergedParams(new DummyTraverser(this.traversal.getTraverserGenerator()));
@@ -208,11 +222,11 @@ public final class CallStep<S, E> extends AbstractStep<S, E> implements Traversa
protected Map getMergedParams(final Traverser.Admin<S> traverser) {
if (mapTraversal == null && parameters.isEmpty()) {
// static params only
- return Collections.unmodifiableMap(this.staticParams);
+ return Collections.unmodifiableMap(this.staticParams.get());
}
// merge dynamic with static params
- final Map params = new LinkedHashMap(this.staticParams);
+ final Map params = new LinkedHashMap(this.staticParams.get());
if (mapTraversal != null) params.putAll(TraversalUtil.apply(traverser, mapTraversal));
final Object[] kvs = this.parameters.getKeyValues(traverser);
for (int i = 0; i < kvs.length; i += 2) {
@@ -225,7 +239,7 @@ public final class CallStep<S, E> extends AbstractStep<S, E> implements Traversa
protected Map getMergedParams(final TraverserSet<S> traverserSet) {
if (mapTraversal == null && parameters.isEmpty()) {
// static params only
- return Collections.unmodifiableMap(this.staticParams);
+ return Collections.unmodifiableMap(this.staticParams.get());
}
/*
@@ -302,7 +316,7 @@ public final class CallStep<S, E> extends AbstractStep<S, E> implements Traversa
public String toString() {
final ArrayList args = new ArrayList();
args.add(serviceName);
- if (!staticParams.isEmpty())
+ if (!staticParams.get().isEmpty())
args.add(staticParams);
if (mapTraversal != null)
args.add(mapTraversal);
@@ -314,8 +328,8 @@ public final class CallStep<S, E> extends AbstractStep<S, E> implements Traversa
@Override
public int hashCode() {
int hashCode = super.hashCode() ^ Objects.hashCode(this.serviceName);
- if (!staticParams.isEmpty())
- hashCode ^= staticParams.hashCode();
+ if (!staticParams.get().isEmpty())
+ hashCode ^= staticParams.get().hashCode();
if (mapTraversal != null)
hashCode ^= mapTraversal.hashCode();
if (!parameters.isEmpty())
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/CombineStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/CombineStep.java
index ccf601acab..67c120c03a 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/CombineStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/CombineStep.java
@@ -20,6 +20,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.Traverser;
+import org.apache.tinkerpop.gremlin.process.traversal.step.GValue;
import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent;
import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
import org.apache.tinkerpop.gremlin.process.traversal.util.ListFunction;
@@ -37,7 +38,7 @@ import java.util.Set;
*/
public final class CombineStep<S, E> extends ScalarMapStep<S, List<?>> implements TraversalParent, ListFunction {
private Traversal.Admin<S, E> valueTraversal;
- private Object parameterItems;
+ private GValue<Object> parameterItems;
public CombineStep(final Traversal.Admin traversal, final Object values) {
super(traversal);
@@ -45,7 +46,7 @@ public final class CombineStep<S, E> extends ScalarMapStep<S, List<?>> implement
if (values instanceof Traversal) {
valueTraversal = integrateChild(((Traversal<S, E>) values).asAdmin());
} else {
- parameterItems = values;
+ parameterItems = values instanceof GValue ? (GValue<Object>) values : GValue.of(values);
}
}
@@ -53,9 +54,9 @@ public final class CombineStep<S, E> extends ScalarMapStep<S, List<?>> implement
public String getStepName() { return "combine"; }
@Override
- protected List<?> map(Traverser.Admin<S> traverser) {
+ protected List<?> map(final Traverser.Admin<S> traverser) {
final Collection listA = convertTraverserToCollection(traverser);
- final Collection listB = (null != valueTraversal) ? convertTraversalToCollection(traverser, valueTraversal) : convertArgumentToCollection(parameterItems);
+ final Collection listB = (null != valueTraversal) ? convertTraversalToCollection(traverser, valueTraversal) : convertArgumentToCollection(parameterItems.get());
final List combined = new ArrayList(listA);
combined.addAll(listB);
@@ -68,7 +69,11 @@ public final class CombineStep<S, E> extends ScalarMapStep<S, List<?>> implement
return (null == valueTraversal) ? Collections.emptyList() : Collections.singletonList(valueTraversal);
}
- public Object getParameterItems() {
+ public Object getParameter() {
+ return parameterItems.get();
+ }
+
+ public GValue<Object> getParameterItems() {
return parameterItems;
}
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ConjoinStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ConjoinStep.java
index ce6818b473..e6bb27a2e7 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ConjoinStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ConjoinStep.java
@@ -20,6 +20,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.Traverser;
+import org.apache.tinkerpop.gremlin.process.traversal.step.GValue;
import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
import org.apache.tinkerpop.gremlin.process.traversal.util.ListFunction;
@@ -34,11 +35,15 @@ import java.util.Set;
* A map step that returns the result of joining every element in the traverser using the delimiter argument.
*/
public final class ConjoinStep<S> extends ScalarMapStep<S, String> implements ListFunction {
- private String delimiter;
+ private GValue<String> delimiter;
public ConjoinStep(final Traversal.Admin traversal, final String delimiter) {
+ this(traversal, GValue.of(delimiter));
+ }
+
+ public ConjoinStep(final Traversal.Admin traversal, final GValue<String> delimiter) {
super(traversal);
- if (null == delimiter) { throw new IllegalArgumentException("Input delimiter to conjoin step can't be null."); }
+ if (null == delimiter || null == delimiter.get()) { throw new IllegalArgumentException("Input delimiter to conjoin step can't be null."); }
this.delimiter = delimiter;
}
@@ -46,7 +51,7 @@ public final class ConjoinStep<S> extends ScalarMapStep<S, String> implements Li
public String getStepName() { return "conjoin"; }
@Override
- protected String map(Traverser.Admin<S> traverser) {
+ protected String map(final Traverser.Admin<S> traverser) {
final Collection elements = convertTraverserToCollection(traverser);
if (elements.isEmpty()) { return ""; }
@@ -54,12 +59,12 @@ public final class ConjoinStep<S> extends ScalarMapStep<S, String> implements Li
for (Object elem : elements) {
if (elem != null) {
- joinResult.append(String.valueOf(elem)).append(delimiter);
+ joinResult.append(elem).append(delimiter.get());
}
}
if (joinResult.length() != 0) {
- joinResult.delete(joinResult.length() - delimiter.length(), joinResult.length());
+ joinResult.delete(joinResult.length() - delimiter.get().length(), joinResult.length());
return joinResult.toString();
} else {
return null;
@@ -67,6 +72,10 @@ public final class ConjoinStep<S> extends ScalarMapStep<S, String> implements Li
}
public String getDelimiter() {
+ return this.delimiter.get();
+ }
+
+ public GValue<String> getDelimiterGValue() {
return this.delimiter;
}
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ConstantStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ConstantStep.java
index 9434cc3b47..3646b599b2 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ConstantStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ConstantStep.java
@@ -20,6 +20,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.Traverser;
+import org.apache.tinkerpop.gremlin.process.traversal.step.GValue;
import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
@@ -29,29 +30,36 @@ import java.util.Set;
public class ConstantStep<S, E> extends ScalarMapStep<S, E> {
- private final E constant;
+ private final GValue<E> constant;
public ConstantStep(final Traversal.Admin traversal, final E constant) {
+ this(traversal, constant instanceof GValue ? (GValue) constant : GValue.of(constant));
+ }
+
+ public ConstantStep(final Traversal.Admin traversal, final GValue<E> constant) {
super(traversal);
- this.constant = constant;
+ this.constant = null == constant ? GValue.of(null) : constant;
}
public E getConstant() {
+ return this.constant.get();
+ }
+ public GValue<E> getConstantGValue() {
return this.constant;
}
@Override
protected E map(final Traverser.Admin<S> traverser) {
- return this.constant;
+ return this.constant.get();
}
@Override
public String toString() {
- return StringFactory.stepString(this, this.constant);
+ return StringFactory.stepString(this, this.constant.get());
}
@Override
public int hashCode() {
- return super.hashCode() ^ Objects.hashCode(this.constant);
+ return super.hashCode() ^ Objects.hashCode(this.constant.get());
}
}
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/DifferenceStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/DifferenceStep.java
index 1317f931c4..27922b984e 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/DifferenceStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/DifferenceStep.java
@@ -20,6 +20,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.Traverser;
+import org.apache.tinkerpop.gremlin.process.traversal.step.GValue;
import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent;
import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
import org.apache.tinkerpop.gremlin.process.traversal.util.ListFunction;
@@ -36,24 +37,37 @@ import java.util.Set;
*/
public final class DifferenceStep<S, E> extends ScalarMapStep<S, Set<?>> implements TraversalParent, ListFunction {
private Traversal.Admin<S, E> valueTraversal;
- private Object parameterItems;
+ private GValue<Object> parameterItems;
+
public DifferenceStep(final Traversal.Admin traversal, final Object values) {
super(traversal);
if (values instanceof Traversal) {
valueTraversal = integrateChild(((Traversal<S, E>) values).asAdmin());
} else {
- parameterItems = values;
+ parameterItems = values instanceof GValue ? (GValue<Object>) values : GValue.of(values);
}
}
+ public Traversal.Admin<S,E> getValueTraversal() {
+ return this.valueTraversal;
+ }
+
+ public Object getParameterItems() {
+ return parameterItems;
+ }
+
+ public GValue<Object> getParameterItemsGValue() {
+ return parameterItems;
+ }
+
@Override
public String getStepName() { return "difference"; }
@Override
protected Set<?> map(Traverser.Admin<S> traverser) {
final Collection setA = convertTraverserToCollection(traverser);
- final Collection setB = (null != valueTraversal) ? convertTraversalToCollection(traverser, valueTraversal) : convertArgumentToCollection(parameterItems);
+ final Collection setB = (null != valueTraversal) ? convertTraversalToCollection(traverser, valueTraversal) : convertArgumentToCollection(parameterItems.get());
final Set differenceSet = new HashSet();
for (Object element : setA) {
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/DisjunctStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/DisjunctStep.java
index 60eebf0457..c82eac3f64 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/DisjunctStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/DisjunctStep.java
@@ -20,6 +20,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.Traverser;
+import org.apache.tinkerpop.gremlin.process.traversal.step.GValue;
import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent;
import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
import org.apache.tinkerpop.gremlin.process.traversal.util.ListFunction;
@@ -35,14 +36,15 @@ import java.util.Set;
*/
public final class DisjunctStep<S, E> extends ScalarMapStep<S, Set<?>> implements TraversalParent, ListFunction {
private Traversal.Admin<S, E> valueTraversal;
- private Object parameterItems;
+ private GValue<Object> parameterItems;
+
public DisjunctStep(final Traversal.Admin traversal, final Object values) {
super(traversal);
if (values instanceof Traversal) {
valueTraversal = integrateChild(((Traversal<S, E>) values).asAdmin());
} else {
- parameterItems = values;
+ parameterItems = values instanceof GValue ? (GValue<Object>) values : GValue.of(values);
}
}
@@ -51,7 +53,11 @@ public final class DisjunctStep<S, E> extends ScalarMapStep<S, Set<?>> implement
}
public Object getParameterItems() {
- return this.parameterItems;
+ return parameterItems;
+ }
+
+ public GValue<Object> getParameterItemsGValue() {
+ return parameterItems;
}
@Override
@@ -60,7 +66,7 @@ public final class DisjunctStep<S, E> extends ScalarMapStep<S, Set<?>> implement
@Override
protected Set<?> map(Traverser.Admin<S> traverser) {
final Set setA = convertTraverserToSet(traverser);
- final Set setB = (null != valueTraversal) ? convertTraversalToSet(traverser, this.valueTraversal) : convertArgumentToSet(parameterItems);
+ final Set setB = (null != valueTraversal) ? convertTraversalToSet(traverser, this.valueTraversal) : convertArgumentToSet(parameterItems.get());
final Set disjunctSet = new HashSet();
if (setA.size() == 0) {
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/GraphStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/GraphStep.java
index 3b1720ff9a..c009588864 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/GraphStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/GraphStep.java
@@ -25,6 +25,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.Step;
import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
import org.apache.tinkerpop.gremlin.process.traversal.step.Configuring;
+import org.apache.tinkerpop.gremlin.process.traversal.step.GValue;
import org.apache.tinkerpop.gremlin.process.traversal.step.GraphComputing;
import org.apache.tinkerpop.gremlin.process.traversal.step.util.AbstractStep;
import org.apache.tinkerpop.gremlin.process.traversal.step.util.HasContainer;
@@ -42,7 +43,9 @@ import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
+import java.util.List;
import java.util.Objects;
+import java.util.Optional;
import java.util.function.Supplier;
/**
@@ -53,7 +56,8 @@ public class GraphStep<S, E extends Element> extends AbstractStep<S, E> implemen
protected Parameters parameters = new Parameters();
protected final Class<E> returnClass;
- protected Object[] ids;
+ protected GValue<?>[] ids;
+ protected boolean legacyLogicForPassingNoIds = false;
protected transient Supplier<Iterator<E>> iteratorSupplier;
protected boolean isStart;
protected boolean done = false;
@@ -64,11 +68,40 @@ public class GraphStep<S, E extends Element> extends AbstractStep<S, E> implemen
public GraphStep(final Traversal.Admin traversal, final Class<E> returnClass, final boolean isStart, final Object... ids) {
super(traversal);
this.returnClass = returnClass;
- this.ids = (ids != null && ids.length == 1 && ids[0] instanceof Collection) ? ((Collection) ids[0]).toArray(new Object[((Collection) ids[0]).size()]) : ids;
+
+ // if ids is a single collection like g.V(['a','b','c']), then unroll it into an array of ids
+ this.ids = GValue.ensureGValues(tryUnrollSingleCollectionArgument(ids));
+
this.isStart = isStart;
+
this.iteratorSupplier = () -> (Iterator<E>) (Vertex.class.isAssignableFrom(this.returnClass) ?
- this.getTraversal().getGraph().get().vertices(this.ids) :
- this.getTraversal().getGraph().get().edges(this.ids));
+ this.getTraversal().getGraph().get().vertices(GValue.resolveToValues(this.ids)) :
+ this.getTraversal().getGraph().get().edges(GValue.resolveToValues(this.ids)));
+ }
+
+ /**
+ * Unrolls a single collection argument into an array of ids. This is useful for steps like
+ * {@code g.V(['a','b','c'])}.
+ */
+ protected static Object[] tryUnrollSingleCollectionArgument(final Object[] ids) {
+ final Object[] tempIds;
+ if (ids != null && ids.length == 1) {
+ final Optional<Collection> opt;
+ if (ids[0] instanceof GValue && ((GValue<?>) ids[0]).getType().isCollection())
+ opt = Optional.of((Collection) ((GValue) ids[0]).get());
+ else if (ids[0] instanceof Collection)
+ opt = Optional.of((Collection) ids[0]);
+ else
+ opt = Optional.empty();
+
+ if (opt.isPresent()) {
+ tempIds = opt.get().toArray(new Object[opt.get().size()]);
+ } else
+ tempIds = ids;
+ } else {
+ tempIds = ids;
+ }
+ return tempIds;
}
public String toString() {
@@ -109,24 +142,39 @@ public class GraphStep<S, E extends Element> extends AbstractStep<S, E> implemen
this.iteratorSupplier = iteratorSupplier;
}
- public Object[] getIds() {
+ /**
+ * Get the ids associated with this step. If there are {@link GValue} objects present they will be returned
+ * alongside literal ids. Prefer {@link #getIdsAsValues()} if you prefer to work with literal ids only.
+ */
+ public GValue[] getIds() {
return this.ids;
}
+ /**
+ * Gets the ids associated with this step as literal values rather than {@link GValue} objects.
+ */
+ public Object[] getIdsAsValues() {
+ if (legacyLogicForPassingNoIds) return null;
+ return GValue.resolveToValues(this.ids);
+ }
+
public void addIds(final Object... newIds) {
- if ((this.ids == null || this.ids.length == 0) &&
- newIds.length == 1 &&
- newIds[0] instanceof Collection && ((Collection) newIds[0]).isEmpty())
- this.ids = null;
- else
- this.ids = ArrayUtils.addAll(this.ids,
- (newIds.length == 1 && newIds[0] instanceof Collection) ?
- ((Collection) newIds[0]).toArray(new Object[((Collection) newIds[0]).size()]) :
- newIds);
+ // there is some logic that has been around for a long time that used to set ids to null. it only happened here
+ // in this method and only occurred when the ids were already null or empty and the newIds were length 1 and
+ // an instance of List and that list was empty. so basically it would trigger for something like g.V().hasId([])
+ // which in turn would trigger an empty iterator in TinkerGraphStep and zero results. trying to maintain that
+ // logic now with GValue in the mix is tough because the context of what the meaning is gets lost by the time
+ // you get to calling getResolvedIds(). using a flag to try to maintain that legacy logic, but ultimately, all
+ // this needs to be rethought.
+ this.legacyLogicForPassingNoIds = newIds.length == 1 && ((newIds[0] instanceof List && ((List) newIds[0]).isEmpty()) ||
+ (newIds[0] instanceof GValue && ((GValue) newIds[0]).getType().isCollection() && ((List) ((GValue) newIds[0]).get()).isEmpty()));
+
+ final GValue[] gvalues = GValue.ensureGValues(tryUnrollSingleCollectionArgument(newIds));
+ this.ids = ArrayUtils.addAll(this.ids, gvalues);
}
public void clearIds() {
- this.ids = new Object[0];
+ this.ids = new GValue[0];
}
@Override
@@ -137,9 +185,12 @@ public class GraphStep<S, E extends Element> extends AbstractStep<S, E> implemen
public void convertElementsToIds() {
if (null != this.ids) {
- for (int i = 0; i < this.ids.length; i++) { // if this is going to OLAP, convert to ids so you don't serialize elements
- if (this.ids[i] instanceof Element)
- this.ids[i] = ((Element) this.ids[i]).id();
+ // if this is going to OLAP, convert to ids so you don't serialize elements
+ for (int i = 0; i < this.ids.length; i++) {
+ final GValue<?> current = this.ids[i];
+ if (current.getType().isElement()) {
+ this.ids[i] = GValue.of(current.getName(), ((Element) current.get()).id());
+ }
}
}
}
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/IntersectStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/IntersectStep.java
index 651dec7502..3c37db29e0 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/IntersectStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/IntersectStep.java
@@ -20,6 +20,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.Traverser;
+import org.apache.tinkerpop.gremlin.process.traversal.step.GValue;
import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent;
import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
import org.apache.tinkerpop.gremlin.process.traversal.util.ListFunction;
@@ -36,7 +37,7 @@ import java.util.Set;
*/
public final class IntersectStep<S, E> extends ScalarMapStep<S, Set<?>> implements TraversalParent, ListFunction {
private Traversal.Admin<S, E> valueTraversal;
- private Object parameterItems;
+ private GValue<Object> parameterItems;
public IntersectStep(final Traversal.Admin traversal, final Object values) {
super(traversal);
@@ -44,7 +45,7 @@ public final class IntersectStep<S, E> extends ScalarMapStep<S, Set<?>> implemen
if (values instanceof Traversal) {
valueTraversal = integrateChild(((Traversal<S, E>) values).asAdmin());
} else {
- parameterItems = values;
+ parameterItems = values instanceof GValue ? (GValue<Object>) values : GValue.of(values);
}
}
@@ -53,16 +54,20 @@ public final class IntersectStep<S, E> extends ScalarMapStep<S, Set<?>> implemen
}
public Object getParameterItems() {
- return this.parameterItems;
+ return parameterItems;
+ }
+
+ public GValue<Object> getParameterItemsGValue() {
+ return parameterItems;
}
@Override
public String getStepName() { return "intersect"; }
@Override
- protected Set<?> map(Traverser.Admin<S> traverser) {
+ protected Set<?> map(final Traverser.Admin<S> traverser) {
final Set setA = convertTraverserToSet(traverser);
- final Collection setB = (null != valueTraversal) ? convertTraversalToCollection(traverser, this.valueTraversal) : convertArgumentToCollection(parameterItems);
+ final Collection setB = (null != valueTraversal) ? convertTraversalToCollection(traverser, this.valueTraversal) : convertArgumentToCollection(parameterItems.get());
final Set intersection = new HashSet();
for (Object element : setB) {
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MergeEdgeStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MergeEdgeStep.java
index bb22d218e5..5beb203a24 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MergeEdgeStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MergeEdgeStep.java
@@ -34,6 +34,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal;
import org.apache.tinkerpop.gremlin.process.traversal.lambda.ConstantTraversal;
+import org.apache.tinkerpop.gremlin.process.traversal.step.GValue;
import org.apache.tinkerpop.gremlin.process.traversal.step.util.event.EventUtil;
import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalUtil;
import org.apache.tinkerpop.gremlin.structure.Direction;
@@ -71,6 +72,10 @@ public class MergeEdgeStep<S> extends MergeElementStep<S, Edge, Object> {
super(traversal, isStart, merge);
}
+ public MergeEdgeStep(final Traversal.Admin traversal, final boolean isStart, final GValue<Map> merge) {
+ super(traversal, isStart, merge);
+ }
+
public MergeEdgeStep(final Traversal.Admin traversal, final boolean isStart, final Traversal.Admin<S,Map> mergeTraversal) {
super(traversal, isStart, mergeTraversal);
}
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MergeElementStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MergeElementStep.java
index 44e954fb31..6835387c5e 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MergeElementStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MergeElementStep.java
@@ -35,6 +35,8 @@ import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal;
import org.apache.tinkerpop.gremlin.process.traversal.lambda.ConstantTraversal;
import org.apache.tinkerpop.gremlin.process.traversal.lambda.IdentityTraversal;
import org.apache.tinkerpop.gremlin.process.traversal.step.Deleting;
+import org.apache.tinkerpop.gremlin.process.traversal.step.GType;
+import org.apache.tinkerpop.gremlin.process.traversal.step.GValue;
import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalOptionParent;
import org.apache.tinkerpop.gremlin.process.traversal.step.Writing;
import org.apache.tinkerpop.gremlin.process.traversal.step.util.Parameters;
@@ -80,6 +82,11 @@ public abstract class MergeElementStep<S, E, C> extends FlatMapStep<S, E>
validate(mergeMap, false);
}
+ public MergeElementStep(final Traversal.Admin traversal, final boolean isStart, final GValue<Map> mergeMap) {
+ this(traversal, isStart, new ConstantTraversal<>(mergeMap));
+ validate(mergeMap.get(), false);
+ }
+
public MergeElementStep(final Traversal.Admin traversal, final boolean isStart,
final Traversal.Admin mergeTraversal) {
super(traversal);
@@ -279,7 +286,7 @@ public abstract class MergeElementStep<S, E, C> extends FlatMapStep<S, E>
op, allowedTokens, k));
}
if (k == T.label) {
- if (!(v instanceof String)) {
+ if (!(GValue.instanceOf(v, GType.STRING))) {
throw new IllegalArgumentException(String.format(
"%s() and option(onCreate) args expect T.label value to be of String - found: %s", op,
v.getClass().getSimpleName()));
@@ -318,7 +325,8 @@ public abstract class MergeElementStep<S, E, C> extends FlatMapStep<S, E>
* null Map == empty Map
*/
protected Map materializeMap(final Traverser.Admin<S> traverser, Traversal.Admin<S, ?> mapTraversal) {
- Map map = (Map) TraversalUtil.apply(traverser, mapTraversal);
+ final Object o = TraversalUtil.apply(traverser, mapTraversal);
+ Map map = GValue.getFrom(o);
// PartitionStrategy uses parameters as a mechanism for setting the partition key. trying to be as specific
// as possible here wrt parameters usage to avoid misuse
@@ -360,7 +368,7 @@ public abstract class MergeElementStep<S, E, C> extends FlatMapStep<S, E>
return id != null ? graph.traversal().V(id) : graph.traversal().V();
}
- protected GraphTraversal searchVerticesLabelConstraint(GraphTraversal t, final String label) {
+ protected GraphTraversal searchVerticesLabelConstraint(final GraphTraversal t, final String label) {
return label != null ? t.hasLabel(label) : t;
}
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MergeStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MergeStep.java
index d11fdf0894..2f86240a42 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MergeStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MergeStep.java
@@ -20,6 +20,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.Traverser;
+import org.apache.tinkerpop.gremlin.process.traversal.step.GValue;
import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent;
import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
import org.apache.tinkerpop.gremlin.process.traversal.util.ListFunction;
@@ -40,7 +41,7 @@ import java.util.Set;
*/
public final class MergeStep<S, E> extends ScalarMapStep<S, E> implements TraversalParent, ListFunction {
private Traversal.Admin<S, E> valueTraversal;
- private Object parameterItems;
+ private GValue<Object> parameterItems;
public MergeStep(final Traversal.Admin traversal, final Object values) {
super(traversal);
@@ -48,10 +49,22 @@ public final class MergeStep<S, E> extends ScalarMapStep<S, E> implements Traver
if (values instanceof Traversal) {
valueTraversal = integrateChild(((Traversal<S, E>) values).asAdmin());
} else {
- parameterItems = values;
+ parameterItems = GValue.of(values);;
}
}
+ public Traversal.Admin<S, E> getValueTraversal() {
+ return valueTraversal;
+ }
+
+ public Object getParameterItems() {
+ return parameterItems;
+ }
+
+ public GValue<Object> getParameterItemsGValue() {
+ return parameterItems;
+ }
+
@Override
public String getStepName() { return "merge"; }
@@ -61,7 +74,7 @@ public final class MergeStep<S, E> extends ScalarMapStep<S, E> implements Traver
final Map mapA = (incoming instanceof Map) ? (Map) incoming : null;
if (mapA != null) {
- final Object mapB = (valueTraversal != null) ? TraversalUtil.apply(traverser, valueTraversal) : parameterItems;
+ final Object mapB = (valueTraversal != null) ? TraversalUtil.apply(traverser, valueTraversal) : parameterItems.get();
if (!(mapB instanceof Map)) {
throw new IllegalArgumentException(
String.format(
@@ -76,13 +89,13 @@ public final class MergeStep<S, E> extends ScalarMapStep<S, E> implements Traver
} else {
final Collection listA = convertTraverserToCollection(traverser);
- if (parameterItems instanceof Map) {
+ if (parameterItems != null && parameterItems.get() instanceof Map) {
throw new IllegalArgumentException(getStepName() + " step type mismatch: expected argument to be Iterable but got Map");
}
final Collection listB =
(null != valueTraversal)
? convertTraversalToCollection(traverser, valueTraversal)
- : convertArgumentToCollection(parameterItems);
+ : convertArgumentToCollection(parameterItems.get());
final Set elements = new HashSet();
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MergeVertexStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MergeVertexStep.java
index 9aab3790ac..e15ff745bc 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MergeVertexStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MergeVertexStep.java
@@ -30,6 +30,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
import org.apache.tinkerpop.gremlin.process.traversal.lambda.CardinalityValueTraversal;
import org.apache.tinkerpop.gremlin.process.traversal.lambda.ConstantTraversal;
+import org.apache.tinkerpop.gremlin.process.traversal.step.GValue;
import org.apache.tinkerpop.gremlin.process.traversal.step.util.event.EventUtil;
import org.apache.tinkerpop.gremlin.structure.Graph;
import org.apache.tinkerpop.gremlin.structure.T;
@@ -60,6 +61,10 @@ public class MergeVertexStep<S> extends MergeElementStep<S, Vertex, Map> {
super(traversal, isStart, merge);
}
+ public MergeVertexStep(final Traversal.Admin traversal, final boolean isStart, final GValue<Map> merge) {
+ super(traversal, isStart, merge);
+ }
+
public MergeVertexStep(final Traversal.Admin traversal, final boolean isStart, final Traversal.Admin<S,Map> mergeTraversal) {
super(traversal, isStart, mergeTraversal);
}
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ProductStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ProductStep.java
index b14c02ba92..a07b204190 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ProductStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ProductStep.java
@@ -20,6 +20,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.Traverser;
+import org.apache.tinkerpop.gremlin.process.traversal.step.GValue;
import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent;
import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
import org.apache.tinkerpop.gremlin.process.traversal.util.ListFunction;
@@ -36,7 +37,7 @@ import java.util.Set;
*/
public final class ProductStep<S, E> extends ScalarMapStep<S, List<List<?>>> implements TraversalParent, ListFunction {
private Traversal.Admin<S, E> valueTraversal;
- private Object parameterItems;
+ private GValue<Object> parameterItems;
public ProductStep(final Traversal.Admin traversal, final Object values) {
super(traversal);
@@ -44,17 +45,29 @@ public final class ProductStep<S, E> extends ScalarMapStep<S, List<List<?>>> imp
if (values instanceof Traversal) {
valueTraversal = integrateChild(((Traversal<S, E>) values).asAdmin());
} else {
- parameterItems = values;
+ parameterItems = values instanceof GValue ? (GValue<Object>) values : GValue.of(values);
}
}
+ public Traversal.Admin<S,E> getValueTraversal() {
+ return this.valueTraversal;
+ }
+
+ public Object getParameterItems() {
+ return parameterItems;
+ }
+
+ public GValue<Object> getParameterItemsGValue() {
+ return parameterItems;
+ }
+
@Override
public String getStepName() { return "product"; }
@Override
protected List<List<?>> map(Traverser.Admin<S> traverser) {
final Collection listA = convertTraverserToCollection(traverser);
- final Collection listB = (null != valueTraversal) ? convertTraversalToCollection(traverser, valueTraversal) : convertArgumentToCollection(parameterItems);
+ final Collection listB = (null != valueTraversal) ? convertTraversalToCollection(traverser, valueTraversal) : convertArgumentToCollection(parameterItems.get());
final List elements = new ArrayList();
for (Object elementInA : listA) {
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/VertexStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/VertexStep.java
index bd429f049c..b6230e0538 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/VertexStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/VertexStep.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.Traverser;
import org.apache.tinkerpop.gremlin.process.traversal.step.Configuring;
+import org.apache.tinkerpop.gremlin.process.traversal.step.GValue;
import org.apache.tinkerpop.gremlin.process.traversal.step.util.Parameters;
import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
import org.apache.tinkerpop.gremlin.structure.Direction;
@@ -39,20 +40,31 @@ import java.util.Set;
import java.util.stream.Collectors;
/**
+ * Handles the logic of traversing to adjacent vertices or edges given a direction and edge labels for steps like,
+ * {@code out}, {@code in}, {@code both}, {@code outE}, {@code inE}, and {@code bothE}.
+ *
* @author Marko A. Rodriguez (http://markorodriguez.com)
*/
public class VertexStep<E extends Element> extends FlatMapStep<Vertex, E> implements AutoCloseable, Configuring {
protected Parameters parameters = new Parameters();
private final String[] edgeLabels;
+ private final GValue<String>[] edgeLabelsGValue;
private Direction direction;
private final Class<E> returnClass;
public VertexStep(final Traversal.Admin traversal, final Class<E> returnClass, final Direction direction, final String... edgeLabels) {
+ this(traversal, returnClass, direction, GValue.ensureGValues(edgeLabels));
+ }
+
+ public VertexStep(final Traversal.Admin traversal, final Class<E> returnClass, final Direction direction, final GValue<String>... edgeLabels) {
super(traversal);
this.direction = direction;
- this.edgeLabels = edgeLabels;
this.returnClass = returnClass;
+ this.edgeLabelsGValue = edgeLabels;
+
+ // convert the GValue<String> to a String[] for the edgeLabels field to cache the values
+ this.edgeLabels = Arrays.stream(this.edgeLabelsGValue).map(GValue::get).toArray(String[]::new);
}
@Override
@@ -67,6 +79,9 @@ public class VertexStep<E extends Element> extends FlatMapStep<Vertex, E> implem
@Override
protected Iterator<E> flatMap(final Traverser.Admin<Vertex> traverser) {
+ // not passing GValue to graphs at this point. if a graph wants to support GValue, it should implement
+ // its own step to do so. in this way, we keep things backwards compatible and don't force folks to have
+ // deal with this until they are ready.
return Vertex.class.isAssignableFrom(this.returnClass) ?
(Iterator<E>) traverser.get().vertices(this.direction, this.edgeLabels) :
(Iterator<E>) traverser.get().edges(this.direction, this.edgeLabels);
@@ -80,6 +95,10 @@ public class VertexStep<E extends Element> extends FlatMapStep<Vertex, E> implem
return this.edgeLabels;
}
+ public GValue<String>[] getEdgeLabelsGValue() {
+ return this.edgeLabelsGValue;
+ }
+
public Class<E> getReturnClass() {
return this.returnClass;
}
@@ -88,10 +107,16 @@ public class VertexStep<E extends Element> extends FlatMapStep<Vertex, E> implem
this.direction = this.direction.opposite();
}
+ /**
+ * Determines if the step returns vertices.
+ */
public boolean returnsVertex() {
return this.returnClass.equals(Vertex.class);
}
+ /**
+ * Determines if the step returns edges.
+ */
public boolean returnsEdge() {
return this.returnClass.equals(Edge.class);
}
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/InjectStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/InjectStep.java
index 0502f18541..fa27d5af92 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/InjectStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/InjectStep.java
@@ -19,6 +19,7 @@
package org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect;
import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
+import org.apache.tinkerpop.gremlin.process.traversal.step.GValue;
import org.apache.tinkerpop.gremlin.util.iterator.ArrayIterator;
/**
@@ -26,29 +27,39 @@ import org.apache.tinkerpop.gremlin.util.iterator.ArrayIterator;
*/
public final class InjectStep<S> extends StartStep<S> {
- private final S[] injections;
+ private final GValue<S>[] injections;
@SafeVarargs
public InjectStep(final Traversal.Admin traversal, final S... injections) {
super(traversal);
- this.injections = injections;
- this.start = new ArrayIterator<>(this.injections);
+ this.injections = GValue.ensureGValues(injections);
+ this.start = new ArrayIterator<>(GValue.resolveToValues(this.injections));
}
@Override
public InjectStep<S> clone() {
final InjectStep<S> clone = (InjectStep<S>) super.clone();
- clone.start = new ArrayIterator<>(clone.injections);
+ clone.start = new ArrayIterator<>(GValue.resolveToValues(clone.injections));
return clone;
}
@Override
public void reset() {
super.reset();
- this.start = new ArrayIterator<>(this.injections);
+ this.start = new ArrayIterator<>(GValue.resolveToValues(this.injections));
}
- public S[] getInjections() {
+ /**
+ * Get the injections of the step.
+ */
+ public GValue<S>[] getInjectionsGValue() {
return this.injections;
}
+
+ /**
+ * Gets the injections of the step but unwraps the {@link GValue}.
+ */
+ public S[] getInjections() {
+ return (S[]) GValue.resolveToValues(this.injections);
+ }
}
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/AbstractStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/AbstractStep.java
index d4545ead5c..f0af790c73 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/AbstractStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/AbstractStep.java
@@ -27,6 +27,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.util.EmptyTraversal;
import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalInterruptedException;
import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
+import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashSet;
@@ -228,5 +229,4 @@ public abstract class AbstractStep<S, E> implements Step<S, E> {
}
return traverser;
}
-
}
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/HasContainer.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/HasContainer.java
index c20c68fde0..35689f8367 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/HasContainer.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/HasContainer.java
@@ -19,10 +19,12 @@
package org.apache.tinkerpop.gremlin.process.traversal.step.util;
import org.apache.tinkerpop.gremlin.process.traversal.P;
+import org.apache.tinkerpop.gremlin.process.traversal.step.GType;
import org.apache.tinkerpop.gremlin.structure.Element;
import org.apache.tinkerpop.gremlin.structure.Property;
import org.apache.tinkerpop.gremlin.structure.T;
import org.apache.tinkerpop.gremlin.structure.util.CloseableIterator;
+import org.apache.tinkerpop.gremlin.process.traversal.step.GValue;
import java.io.Serializable;
import java.util.Collection;
@@ -154,11 +156,11 @@ public class HasContainer implements Serializable, Cloneable, Predicate<Element>
if (predicateValue instanceof Collection) {
final Collection collection = (Collection) predicateValue;
if (!collection.isEmpty()) {
- return ((Collection) predicateValue).stream().allMatch(c -> null == c || c instanceof String);
+ return ((Collection) predicateValue).stream().allMatch(c -> null == c || GValue.instanceOf(c, GType.STRING));
}
}
- return predicateValue instanceof String;
+ return GValue.instanceOf(predicateValue, GType.STRING);
}
return false;
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/Parameters.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/Parameters.java
index d1654a344e..9b4a926c74 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/Parameters.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/Parameters.java
@@ -22,6 +22,7 @@ package org.apache.tinkerpop.gremlin.process.traversal.step.util;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
+import org.apache.tinkerpop.gremlin.process.traversal.step.GValue;
import org.apache.tinkerpop.gremlin.process.traversal.step.Scoping;
import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent;
import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalUtil;
@@ -165,7 +166,7 @@ public class Parameters implements Cloneable, Serializable {
/**
* Gets the array of keys/values of the parameters while resolving parameter values that contain
- * {@link Traversal} instances.
+ * {@link Traversal} or {@link GValue} instances.
*/
public <S> Object[] getKeyValues(final Traverser.Admin<S> traverser, final Object... exceptKeys) {
if (this.parameters.isEmpty()) return EMPTY_ARRAY;
@@ -173,14 +174,28 @@ public class Parameters implements Cloneable, Serializable {
for (final Map.Entry<Object, List<Object>> entry : this.parameters.entrySet()) {
if (!ArrayUtils.contains(exceptKeys, entry.getKey())) {
for (final Object value : entry.getValue()) {
- keyValues.add(entry.getKey() instanceof Traversal.Admin ? TraversalUtil.apply(traverser, (Traversal.Admin<S, ?>) entry.getKey()) : entry.getKey());
- keyValues.add(value instanceof Traversal.Admin ? TraversalUtil.apply(traverser, (Traversal.Admin<S, ?>) value) : value);
+ keyValues.add(resolve(entry.getKey(), traverser));
+ keyValues.add(resolve(value, traverser));
}
}
}
return keyValues.toArray(new Object[keyValues.size()]);
}
+ /**
+ * Takes an object and tests if it is a {@link GValue} or a {@link Traversal} and if so, resolves it to its value
+ * otherwise it just returns itself.
+ */
+ private static <S> Object resolve(final Object object, final Traverser.Admin<S> traverser) {
+ if (object instanceof Traversal.Admin) {
+ return TraversalUtil.apply(traverser, (Traversal.Admin<S, ?>) object);
+ } else if (object instanceof GValue) {
+ return ((GValue) object).get();
+ } else {
+ return object;
+ }
+ }
+
/**
* Gets an immutable set of the parameters without evaluating them in the context of a {@link Traverser} as
* is done in {@link #getKeyValues(Traverser.Admin, Object...)}.
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/ElementIdStrategy.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/ElementIdStrategy.java
index 67c08254a8..e47b782185 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/ElementIdStrategy.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/ElementIdStrategy.java
@@ -94,11 +94,12 @@ public final class ElementIdStrategy extends AbstractTraversalStrategy<Traversal
// note that it is then only necessary to replace the step if the id is a non-element. other tests
// in the suite validate that items in getIds() is uniform so it is ok to just test the first item
// in the list.
- if (graphStep.getIds().length > 0 && !(graphStep.getIds()[0] instanceof Element)) {
+ final Object[] ids = graphStep.getIdsAsValues();
+ if (ids.length > 0 && !(ids[0] instanceof Element)) {
if (graphStep instanceof HasContainerHolder)
- ((HasContainerHolder) graphStep).addHasContainer(new HasContainer(this.idPropertyKey, P.within(Arrays.asList(graphStep.getIds()))));
+ ((HasContainerHolder) graphStep).addHasContainer(new HasContainer(this.idPropertyKey, P.within(Arrays.asList(ids))));
else
- TraversalHelper.insertAfterStep(new HasStep(traversal, new HasContainer(this.idPropertyKey, P.within(Arrays.asList(graphStep.getIds())))), graphStep, traversal);
+ TraversalHelper.insertAfterStep(new HasStep(traversal, new HasContainer(this.idPropertyKey, P.within(Arrays.asList(ids)))), graphStep, traversal);
graphStep.clearIds();
}
}
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/SideEffectStrategy.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/SideEffectStrategy.java
index ce794b8b6a..9b309dba3f 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/SideEffectStrategy.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/SideEffectStrategy.java
@@ -22,6 +22,7 @@ package org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration;
import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategies;
import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.step.GValue;
import org.apache.tinkerpop.gremlin.process.traversal.step.util.EmptyStep;
import org.apache.tinkerpop.gremlin.process.traversal.strategy.AbstractTraversalStrategy;
import org.apache.tinkerpop.gremlin.util.function.ConstantSupplier;
@@ -60,7 +61,11 @@ public final class SideEffectStrategy extends AbstractTraversalStrategy<Traversa
strategy = cloneStrategy;
traversalStrategies.addStrategies(strategy);
}
- strategy.sideEffects.add(new Triplet<>(key, value instanceof Supplier ? (Supplier) value : new ConstantSupplier<>(value), reducer));
+
+ // don't want the GValue to leak beyond strategy application or else the Supplier will start producing it
+ // during execution
+ final ConstantSupplier initialValue = value instanceof GValue ? new ConstantSupplier<>(((GValue) value).get()) : new ConstantSupplier<>(value);
+ strategy.sideEffects.add(new Triplet<>(key, value instanceof Supplier ? (Supplier) value : initialValue, reducer));
}
public boolean contains(final String sideEffectKey) {
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/SubgraphStrategy.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/SubgraphStrategy.java
index 6a876e8514..b012d66d84 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/SubgraphStrategy.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/SubgraphStrategy.java
@@ -193,7 +193,7 @@ public final class SubgraphStrategy extends AbstractTraversalStrategy<TraversalS
continue;
if (edgeCriterion != null) {
- final VertexStep<Edge> someEStep = new VertexStep<>(traversal, Edge.class, step.getDirection(), step.getEdgeLabels());
+ final VertexStep<Edge> someEStep = new VertexStep<>(traversal, Edge.class, step.getDirection(), step.getEdgeLabelsGValue());
final Step<Edge, Vertex> someVStep = step.getDirection() == Direction.BOTH ?
new EdgeOtherVertexStep(traversal) :
new EdgeVertexStep(traversal, step.getDirection().opposite());
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/AdjacentToIncidentStrategy.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/AdjacentToIncidentStrategy.java
index d8e538ab37..b33d527c2c 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/AdjacentToIncidentStrategy.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/AdjacentToIncidentStrategy.java
@@ -118,7 +118,7 @@ public final class AdjacentToIncidentStrategy extends AbstractTraversalStrategy<
final Step newStep;
if (step instanceof VertexStep) {
final VertexStep vs = (VertexStep) step;
- newStep = new VertexStep<>(traversal, Edge.class, vs.getDirection(), vs.getEdgeLabels());
+ newStep = new VertexStep<>(traversal, Edge.class, vs.getDirection(), vs.getEdgeLabelsGValue());
} else if (step instanceof PropertiesStep) {
final PropertiesStep ps = (PropertiesStep) step;
newStep = new PropertiesStep(traversal, PropertyType.PROPERTY, ps.getPropertyKeys());
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/IncidentToAdjacentStrategy.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/IncidentToAdjacentStrategy.java
index 75d55adcd0..813b60b955 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/IncidentToAdjacentStrategy.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/IncidentToAdjacentStrategy.java
@@ -110,7 +110,7 @@ public final class IncidentToAdjacentStrategy extends AbstractTraversalStrategy<
* @param step2 the vertex-emitting step to replace
*/
private static void optimizeSteps(final Traversal.Admin traversal, final VertexStep step1, final Step step2) {
- final Step newStep = new VertexStep(traversal, Vertex.class, step1.getDirection(), step1.getEdgeLabels());
+ final Step newStep = new VertexStep(traversal, Vertex.class, step1.getDirection(), step1.getEdgeLabelsGValue());
for (final String label : (Iterable<String>) step2.getLabels()) {
newStep.addLabel(label);
}
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/InlineFilterStrategy.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/InlineFilterStrategy.java
index d2713218c5..e8b154fef6 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/InlineFilterStrategy.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/InlineFilterStrategy.java
@@ -26,6 +26,8 @@ import org.apache.tinkerpop.gremlin.process.traversal.P;
import org.apache.tinkerpop.gremlin.process.traversal.Step;
import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.step.GType;
+import org.apache.tinkerpop.gremlin.process.traversal.step.GValue;
import org.apache.tinkerpop.gremlin.process.traversal.step.LambdaHolder;
import org.apache.tinkerpop.gremlin.process.traversal.step.filter.AndStep;
import org.apache.tinkerpop.gremlin.process.traversal.step.filter.DedupGlobalStep;
@@ -124,26 +126,25 @@ public final class InlineFilterStrategy extends AbstractTraversalStrategy<Traver
&& ((VertexStep) step.getPreviousStep()).returnsEdge()
&& 0 == ((VertexStep) step.getPreviousStep()).getEdgeLabels().length) {
final VertexStep<Edge> previousStep = (VertexStep<Edge>) step.getPreviousStep();
- final List<String> edgeLabels = new ArrayList<>();
+ final List<Object> edgeLabels = new ArrayList<>();
for (final HasContainer hasContainer : new ArrayList<>(step.getHasContainers())) {
if (hasContainer.getKey().equals(T.label.getAccessor())) {
- if (hasContainer.getBiPredicate() == Compare.eq &&
- hasContainer.getValue() instanceof String &&
+ if (hasContainer.getBiPredicate() == Compare.eq && GValue.instanceOf(hasContainer.getValue(), GType.STRING) &&
edgeLabels.isEmpty()) {
- edgeLabels.add((String) hasContainer.getValue());
+ edgeLabels.add(hasContainer.getValue());
step.removeHasContainer(hasContainer);
} else if (hasContainer.getBiPredicate() == Contains.within &&
hasContainer.getValue() instanceof Collection &&
((Collection) hasContainer.getValue()).containsAll(edgeLabels)) {
- edgeLabels.addAll((Collection<String>) hasContainer.getValue());
+ edgeLabels.addAll((Collection) hasContainer.getValue());
step.removeHasContainer(hasContainer);
} else if (hasContainer.getPredicate() instanceof OrP && edgeLabels.isEmpty()) {
boolean removeContainer = true;
final List<P<?>> orps = ((OrP) hasContainer.getPredicate()).getPredicates();
- final List<String> newEdges = new ArrayList<>();
+ final List<Object> newEdges = new ArrayList<>();
for (int i = 0; i < orps.size(); i++) {
- if (orps.get(i).getBiPredicate() == Compare.eq && orps.get(i).getValue() instanceof String)
- newEdges.add((String) orps.get(i).getValue());
+ if (orps.get(i).getBiPredicate() == Compare.eq && GValue.instanceOf(orps.get(i).getValue(), GType.STRING))
+ newEdges.add(orps.get(i).getValue());
else {
removeContainer = false;
break;
@@ -157,7 +158,7 @@ public final class InlineFilterStrategy extends AbstractTraversalStrategy<Traver
}
}
if (!edgeLabels.isEmpty()) {
- final VertexStep<Edge> newVertexStep = new VertexStep<>(traversal, Edge.class, previousStep.getDirection(), edgeLabels.toArray(new String[edgeLabels.size()]));
+ final VertexStep<Edge> newVertexStep = new VertexStep<>(traversal, Edge.class, previousStep.getDirection(), GValue.ensureGValues(edgeLabels.toArray()));
TraversalHelper.replaceStep(previousStep, newVertexStep, traversal);
TraversalHelper.copyLabels(previousStep, newVertexStep, false);
if (step.getHasContainers().isEmpty()) {
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/ListFunction.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/ListFunction.java
index ab693b9e29..5bf91c41e8 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/ListFunction.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/ListFunction.java
@@ -39,7 +39,7 @@ public interface ListFunction {
* @param iterable an Iterable or array.
* @return The iterable type as a Collection or null if argument isn't iterable.
*/
- public static Collection asCollection(Object iterable) {
+ public static Collection asCollection(final Object iterable) {
if (iterable instanceof Collection) {
return (Collection) iterable;
} else if ((iterable != null && iterable.getClass().isArray()) || iterable instanceof Iterable) {
@@ -56,7 +56,7 @@ public interface ListFunction {
* @param iterable an Iterable or array.
* @return The iterable type as a Collection or null if argument isn't iterable.
*/
- public static Set asSet(Object iterable) {
+ public static Set asSet(final Object iterable) {
if (iterable instanceof Iterable || iterable != null && iterable.getClass().isArray()) {
return IteratorUtils.asSet(iterable);
} else {
@@ -71,7 +71,7 @@ public interface ListFunction {
*/
public String getStepName();
- public default Collection convertArgumentToCollection(Object arg) {
+ public default Collection convertArgumentToCollection(final Object arg) {
if (null == arg) {
throw new IllegalArgumentException(
String.format("Argument provided for %s step can't be null.", getStepName()));
@@ -90,7 +90,7 @@ public interface ListFunction {
return incoming;
}
- public default <S> Collection convertTraverserToCollection(Traverser.Admin<S> traverser) {
+ public default <S> Collection convertTraverserToCollection(final Traverser.Admin<S> traverser) {
final S items = traverser.get();
if (null == items) {
@@ -111,7 +111,7 @@ public interface ListFunction {
return incoming;
}
- public default <S, E> Collection convertTraversalToCollection(Traverser.Admin<S> traverser, final Traversal.Admin<S, E> traversal) {
+ public default <S, E> Collection convertTraversalToCollection(final Traverser.Admin<S> traverser, final Traversal.Admin<S, E> traversal) {
final Object array = TraversalUtil.apply(traverser, traversal);
if (null == array) {
@@ -134,7 +134,7 @@ public interface ListFunction {
return input;
}
- public default Set convertArgumentToSet(Object arg) {
+ public default Set convertArgumentToSet(final Object arg) {
if (null == arg) {
throw new IllegalArgumentException(
String.format("Argument provided for %s step can't be null.", getStepName()));
@@ -153,7 +153,7 @@ public interface ListFunction {
return incoming;
}
- public default <S> Set convertTraverserToSet(Traverser.Admin<S> traverser) {
+ public default <S> Set convertTraverserToSet(final Traverser.Admin<S> traverser) {
final S items = traverser.get();
if (null == items) {
@@ -174,7 +174,7 @@ public interface ListFunction {
return incoming;
}
- public default <S, E> Set convertTraversalToSet(Traverser.Admin<S> traverser, final Traversal.Admin<S, E> traversal) {
+ public default <S, E> Set convertTraversalToSet(final Traverser.Admin<S> traverser, final Traversal.Admin<S, E> traversal) {
final Object array = TraversalUtil.apply(traverser, traversal);
if (null == array) {
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/VertexProperty.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/VertexProperty.java
index af7a18a1d9..962140adb5 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/VertexProperty.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/VertexProperty.java
@@ -18,9 +18,6 @@
*/
package org.apache.tinkerpop.gremlin.structure;
-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.__;
import org.apache.tinkerpop.gremlin.process.traversal.lambda.CardinalityValueTraversal;
import org.apache.tinkerpop.gremlin.structure.util.empty.EmptyVertexProperty;
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoVersion.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoVersion.java
index b06509a4b0..7fa37b5acb 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoVersion.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoVersion.java
@@ -38,6 +38,8 @@ import org.apache.tinkerpop.gremlin.process.traversal.SackFunctions;
import org.apache.tinkerpop.gremlin.process.traversal.Scope;
import org.apache.tinkerpop.gremlin.process.traversal.Text;
import org.apache.tinkerpop.gremlin.process.traversal.TextP;
+import org.apache.tinkerpop.gremlin.process.traversal.step.GType;
+import org.apache.tinkerpop.gremlin.process.traversal.step.GValue;
import org.apache.tinkerpop.gremlin.process.traversal.step.filter.RangeGlobalStep;
import org.apache.tinkerpop.gremlin.process.traversal.step.map.FoldStep;
import org.apache.tinkerpop.gremlin.process.traversal.step.map.GroupCountStep;
@@ -325,7 +327,7 @@ public enum GryoVersion {
add(GryoTypeReg.of(P.class, 124, new GryoSerializersV3.PSerializer()));
add(GryoTypeReg.of(TextP.class, 186, new GryoSerializersV3.TextPSerializer()));
- add(GryoTypeReg.of(Text.RegexPredicate.class, 197)); // ***LAST ID***
+ add(GryoTypeReg.of(Text.RegexPredicate.class, 197));
add(GryoTypeReg.of(Lambda.class, 125, new GryoSerializersV3.LambdaSerializer()));
add(GryoTypeReg.of(Order.class, 127));
add(GryoTypeReg.of(Scope.class, 128));
@@ -422,6 +424,9 @@ public enum GryoVersion {
add(GryoTypeReg.of(Stack.class, 181));
add(GryoTypeReg.of(ReferenceMap.class, 182));
+ add(GryoTypeReg.of(GValue.class, 199, new JavaSerializer()));
+ add(GryoTypeReg.of(GType.class, 200, new JavaSerializer())); // ***LAST ID***
+
// placeholder serializers for classes that don't live here in core. this will allow them to be used if
// present or ignored if the class isn't available. either way the registration numbers are held as
// placeholders so that the format stays stable
@@ -538,7 +543,7 @@ public enum GryoVersion {
add(GryoTypeReg.of(Pop.class, 133));
add(GryoTypeReg.of(SackFunctions.Barrier.class, 135));
add(GryoTypeReg.of(Pick.class, 137));
- add(GryoTypeReg.of(DT.class, 198)); // ***LAST ID***
+ add(GryoTypeReg.of(DT.class, 198));
add(GryoTypeReg.of(Merge.class, 196));
add(GryoTypeReg.of(HashSetSupplier.class, 136, new UtilSerializers.HashSetSupplierSerializer()));
add(GryoTypeReg.of(MultiComparator.class, 165));
@@ -629,6 +634,9 @@ public enum GryoVersion {
add(GryoTypeReg.of(LabelledCounter.class, 180));
add(GryoTypeReg.of(Stack.class, 181));
add(GryoTypeReg.of(ReferenceMap.class, 182));
+
+ add(GryoTypeReg.of(GValue.class, 199, new JavaSerializer()));
+ add(GryoTypeReg.of(GType.class, 200, new JavaSerializer())); // ***LAST ID***
}};
}
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/CollectionUtil.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/CollectionUtil.java
index 1242d16af7..27d41d8e18 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/CollectionUtil.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/CollectionUtil.java
@@ -19,6 +19,9 @@
package org.apache.tinkerpop.gremlin.util;
+import org.apache.commons.lang3.ArrayUtils;
+
+import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@@ -29,22 +32,36 @@ import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
+/**
+ * Utility class for working with collections and arrays.
+ */
public final class CollectionUtil {
- private CollectionUtil() {
- }
+ private CollectionUtil() { }
+ /**
+ * Converts varargs to a {@code List}.
+ */
public static <E> List<E> asList(final E... elements) {
return new ArrayList<>(Arrays.asList(elements));
}
+ /**
+ * Converts varargs to a {@code Set}.
+ */
public static <E> LinkedHashSet<E> asSet(final E... elements) {
return asSet(Arrays.asList(elements));
}
+ /**
+ * Converts {@code Collection} to a {@code Set}.
+ */
public static <E> LinkedHashSet<E> asSet(final Collection<E> elements) {
return new LinkedHashSet<>(elements);
}
+ /**
+ * Converts varargs to a {@code Map} where the elements are key/value pairs.
+ */
public static <K,V> LinkedHashMap<K,V> asMap(final Object... elements) {
final LinkedHashMap<K,V> map = new LinkedHashMap<>();
for (int i = 0; i < elements.length; i+=2) {
@@ -55,6 +72,11 @@ public final class CollectionUtil {
return map;
}
+ /**
+ * Clones a given {@code ConcurrentHashMap} by creating a new map and copying all entries from the original map.
+ * If the value of an entry is a {@code Set} or an {@code ArrayList}, a deep copy of the value is created.
+ * Otherwise, the value is copied as is.
+ */
public static <K,V> ConcurrentHashMap<K,V> clone(final ConcurrentHashMap<K,V> map) {
final ConcurrentHashMap<K, V> result = new ConcurrentHashMap<>(map.size());
@@ -74,4 +96,22 @@ public final class CollectionUtil {
return result;
}
+
+ /**
+ * Adds the element argument to the start of the supplied array argument, but if the array is null then return the
+ * element as a new array with just that item in it.
+ */
+ public static <T> T[] addFirst(final T[] array, final T element, final Class<T> clazz) {
+ if (null == array && null == element) {
+ final T[] singleElementArray = (T[]) Array.newInstance(clazz, 1);
+ singleElementArray[0] = null;
+ return singleElementArray;
+ } else if (null == array) {
+ final T[] singleElementArray = (T[]) Array.newInstance(clazz, 1);
+ singleElementArray[0] = element;
+ return singleElementArray;
+ } else {
+ return ArrayUtils.addFirst(array, element);
+ }
+ }
}
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/jsr223/VariableResolverPluginTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/jsr223/VariableResolverPluginTest.java
new file mode 100644
index 0000000000..0d3dc5fd96
--- /dev/null
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/jsr223/VariableResolverPluginTest.java
@@ -0,0 +1,117 @@
+/*
+ * 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.jsr223;
+
+import org.apache.tinkerpop.gremlin.language.grammar.GremlinParser;
+import org.apache.tinkerpop.gremlin.language.grammar.VariableResolver;
+import org.junit.Test;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.core.IsInstanceOf.instanceOf;
+import static org.hamcrest.CoreMatchers.containsString;
+import static org.junit.Assert.fail;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class VariableResolverPluginTest {
+
+ @Test
+ public void shouldProduceNullVariableResolver() {
+ final Map<String, Object> bindings = new HashMap<>();
+ final VariableResolverPlugin plugin = VariableResolverPlugin.build().
+ resolver(VariableResolver.NullVariableResolver.class.getSimpleName()).create();
+ final VariableResolver resolver = ((VariableResolverCustomizer) plugin.getCustomizers().
+ get()[0]).getVariableResolverMaker().apply(bindings);
+ assertThat(resolver, instanceOf(VariableResolver.NullVariableResolver.class));
+ }
+
+ @Test
+ public void shouldProduceNoVariableResolver() {
+ final Map<String, Object> bindings = new HashMap<>();
+ final VariableResolverPlugin plugin = VariableResolverPlugin.build().
+ resolver(VariableResolver.NoVariableResolver.class.getSimpleName()).create();
+ final VariableResolver resolver = ((VariableResolverCustomizer) plugin.getCustomizers().
+ get()[0]).getVariableResolverMaker().apply(bindings);
+ assertThat(resolver, instanceOf(VariableResolver.NoVariableResolver.class));
+ }
+
+ @Test
+ public void shouldProduceDefaultVariableResolver() {
+ final Map<String, Object> bindings = new HashMap<>();
+ final VariableResolverPlugin plugin = VariableResolverPlugin.build().
+ resolver(VariableResolver.DefaultVariableResolver.class.getSimpleName()).create();
+ final VariableResolver resolver = ((VariableResolverCustomizer) plugin.getCustomizers().
+ get()[0]).getVariableResolverMaker().apply(bindings);
+ assertThat(resolver, instanceOf(VariableResolver.DefaultVariableResolver.class));
+ }
+
+ @Test
+ public void shouldProduceDirectVariableResolver() {
+ final Map<String, Object> bindings = new HashMap<>();
+ final VariableResolverPlugin plugin = VariableResolverPlugin.build().
+ resolver(VariableResolver.DirectVariableResolver.class.getSimpleName()).create();
+ final VariableResolver resolver = ((VariableResolverCustomizer) plugin.getCustomizers().
+ get()[0]).getVariableResolverMaker().apply(bindings);
+ assertThat(resolver, instanceOf(VariableResolver.DirectVariableResolver.class));
+ }
+
+ @Test
+ public void shouldProduceDefaultedVariableResolverWhenNoSpecified() {
+ final Map<String, Object> bindings = new HashMap<>();
+ final VariableResolverPlugin plugin = VariableResolverPlugin.build().create();
+ final VariableResolver resolver = ((VariableResolverCustomizer) plugin.getCustomizers().
+ get()[0]).getVariableResolverMaker().apply(bindings);
+ assertThat(resolver, instanceOf(VariableResolver.DirectVariableResolver.class));
+ }
+
+ @Test
+ public void shouldProduceCustomVariableResolverForFullyQualifiedClassName() {
+ final Map<String, Object> bindings = new HashMap<>();
+ final VariableResolverPlugin plugin = VariableResolverPlugin.build().
+ resolver(CustomVariableResolver.class.getName()).create();
+ final VariableResolver resolver = ((VariableResolverCustomizer) plugin.getCustomizers().
+ get()[0]).getVariableResolverMaker().apply(bindings);
+ assertThat(resolver, instanceOf(CustomVariableResolver.class));
+ }
+
+ @Test
+ public void shouldProduceExceptionVariableResolverIfResolverNotFound() {
+ try {
+ final VariableResolverPlugin plugin = VariableResolverPlugin.build().
+ resolver("NotAResolver").create();
+ fail("The resolver does not exist and should have failed");
+ } catch (Exception re) {
+ assertThat(re.getMessage(), containsString("VariableResolver class not found: NotAResolver"));
+ }
+ }
+
+ /**
+ * Custom test implementation of {@link VariableResolver} that is not part of the standard set of implementations.
+ * This class does nothing.
+ */
+ public static class CustomVariableResolver implements VariableResolver<Object> {
+ public CustomVariableResolver(final Map<String, Object> m) {
+ }
+
+ @Override
+ public Object apply(final String varName, final GremlinParser.VariableContext variableContext) {
+ return null;
+ }
+ }
+}
\ No newline at end of file
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/language/grammar/ArgumentVisitorTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/language/grammar/ArgumentVisitorTest.java
index 4dd0af45c6..6a665787d3 100644
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/language/grammar/ArgumentVisitorTest.java
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/language/grammar/ArgumentVisitorTest.java
@@ -84,58 +84,56 @@ public class ArgumentVisitorTest {
public static Iterable<Object[]> generateTestParameters() {
return Arrays.asList(new Object[][]{
{Boolean.class, "x", new VariableResolverException("x"), createAntlr(VariableResolver.NoVariableResolver.instance())},
- {Boolean.class, "true", true, createAntlr(new VariableResolver.DefaultVariableResolver(ElementHelper.asMap("x", true)))},
- {Boolean.class, "false", false, createAntlr(new VariableResolver.DefaultVariableResolver(ElementHelper.asMap("x", true)))},
- {Boolean.class, "x", true, createAntlr(new VariableResolver.DefaultVariableResolver(ElementHelper.asMap("x", true)))},
+ {Boolean.class, "true", true, createAntlr(new VariableResolver.DirectVariableResolver(ElementHelper.asMap("x", true)))},
+ {Boolean.class, "false", false, createAntlr(new VariableResolver.DirectVariableResolver(ElementHelper.asMap("x", true)))},
+ {Boolean.class, "x", true, createAntlr(new VariableResolver.DirectVariableResolver(ElementHelper.asMap("x", true)))},
{Integer.class, "x", new VariableResolverException("x"), createAntlr(VariableResolver.NoVariableResolver.instance())},
- {Integer.class, "0", 0, createAntlr(new VariableResolver.DefaultVariableResolver(ElementHelper.asMap("x", 100)))},
- {Integer.class, "0i", 0, createAntlr(new VariableResolver.DefaultVariableResolver(ElementHelper.asMap("x", 100)))},
- {Integer.class, "0L", 0L, createAntlr(new VariableResolver.DefaultVariableResolver(ElementHelper.asMap("x", 100)))},
- {Integer.class, "x", 0, createAntlr(new VariableResolver.DefaultVariableResolver(ElementHelper.asMap("x", 0)))},
- {Integer.class, "x", 0L, createAntlr(new VariableResolver.DefaultVariableResolver(ElementHelper.asMap("x", 0L)))},
+ {Integer.class, "0", 0, createAntlr(new VariableResolver.DirectVariableResolver(ElementHelper.asMap("x", 100)))},
+ {Integer.class, "0i", 0, createAntlr(new VariableResolver.DirectVariableResolver(ElementHelper.asMap("x", 100)))},
+ {Integer.class, "0L", 0L, createAntlr(new VariableResolver.DirectVariableResolver(ElementHelper.asMap("x", 100)))},
+ {Integer.class, "x", 0, createAntlr(new VariableResolver.DirectVariableResolver(ElementHelper.asMap("x", 0)))},
+ {Integer.class, "x", 0L, createAntlr(new VariableResolver.DirectVariableResolver(ElementHelper.asMap("x", 0L)))},
{Float.class, "x", new VariableResolverException("x"), createAntlr(VariableResolver.NoVariableResolver.instance())},
- {Float.class, "0.0d", 0.0, createAntlr(new VariableResolver.DefaultVariableResolver(ElementHelper.asMap("x", 1000.0)))},
- {Float.class, "0d", 0.0, createAntlr(new VariableResolver.DefaultVariableResolver(ElementHelper.asMap("x", 1000.0)))},
- {Float.class, "0F", 0.0F, createAntlr(new VariableResolver.DefaultVariableResolver(ElementHelper.asMap("x", 1000.0F)))},
- {Float.class, "x", 0.0, createAntlr(new VariableResolver.DefaultVariableResolver(ElementHelper.asMap("x", 0.0)))},
- {Float.class, "x", 0.0F, createAntlr(new VariableResolver.DefaultVariableResolver(ElementHelper.asMap("x", 0.0F)))},
+ {Float.class, "0.0d", 0.0, createAntlr(new VariableResolver.DirectVariableResolver(ElementHelper.asMap("x", 1000.0)))},
+ {Float.class, "0d", 0.0, createAntlr(new VariableResolver.DirectVariableResolver(ElementHelper.asMap("x", 1000.0)))},
+ {Float.class, "0F", 0.0F, createAntlr(new VariableResolver.DirectVariableResolver(ElementHelper.asMap("x", 1000.0F)))},
+ {Float.class, "x", 0.0, createAntlr(new VariableResolver.DirectVariableResolver(ElementHelper.asMap("x", 0.0)))},
+ {Float.class, "x", 0.0F, createAntlr(new VariableResolver.DirectVariableResolver(ElementHelper.asMap("x", 0.0F)))},
{String.class, "x", new VariableResolverException("x"), createAntlr(VariableResolver.NoVariableResolver.instance())},
- {String.class, "'test'", "test", createAntlr(new VariableResolver.DefaultVariableResolver(ElementHelper.asMap("x", "nope")))},
- {String.class, "x", "test", createAntlr(new VariableResolver.DefaultVariableResolver(ElementHelper.asMap("x", "test")))},
- {String.class, "x", "graphson", createAntlr(new VariableResolver.DefaultVariableResolver(ElementHelper.asMap("x", IO.graphson)))},
+ {String.class, "'test'", "test", createAntlr(new VariableResolver.DirectVariableResolver(ElementHelper.asMap("x", "nope")))},
+ {String.class, "x", "test", createAntlr(new VariableResolver.DirectVariableResolver(ElementHelper.asMap("x", "test")))},
+ {String.class, "x", "graphson", createAntlr(new VariableResolver.DirectVariableResolver(ElementHelper.asMap("x", IO.graphson)))},
{StringNullable.class, "x", new VariableResolverException("x"), createAntlr(VariableResolver.NoVariableResolver.instance())},
- {StringNullable.class, "null", null, createAntlr(new VariableResolver.DefaultVariableResolver(ElementHelper.asMap("x", "nope")))},
- {StringNullable.class, "x", null, createAntlr(new VariableResolver.DefaultVariableResolver(nullMap))},
+ {StringNullable.class, "null", null, createAntlr(new VariableResolver.DirectVariableResolver(ElementHelper.asMap("x", "nope")))},
+ {StringNullable.class, "x", null, createAntlr(new VariableResolver.DirectVariableResolver(nullMap))},
{Object.class, "x", new VariableResolverException("x"), createAntlr(VariableResolver.NoVariableResolver.instance())},
- {Object.class, "'test'", "test", createAntlr(new VariableResolver.DefaultVariableResolver(ElementHelper.asMap("x", "nope")))},
- {Object.class, "x", "test", createAntlr(new VariableResolver.DefaultVariableResolver(ElementHelper.asMap("x", "test")))},
- {Object.class, "x", now, createAntlr(new VariableResolver.DefaultVariableResolver(ElementHelper.asMap("x", now)))},
- {Object.class, "[1,2,3]", Arrays.asList(1, 2, 3), createAntlr(new VariableResolver.DefaultVariableResolver(ElementHelper.asMap("x", now)))},
- {Object.class, "x", P.eq(100), createAntlr(new VariableResolver.DefaultVariableResolver(ElementHelper.asMap("x", P.eq(100))))},
- {Direction.class, "Direction.OUT", Direction.OUT, createAntlr(new VariableResolver.DefaultVariableResolver(ElementHelper.asMap("x", "nope")))},
- {Direction.class, "OUT", Direction.OUT, createAntlr(new VariableResolver.DefaultVariableResolver(ElementHelper.asMap("x", "nope")))},
- {Vertex.class, "x", new VariableResolverException("x"), createAntlr(VariableResolver.NoVariableResolver.instance())},
- {Vertex.class, "new Vertex(1i,'person')", new ReferenceVertex(1, "person"), createAntlr(new VariableResolver.DefaultVariableResolver(ElementHelper.asMap("x", Direction.from)))},
- {Vertex.class, "x", new ReferenceVertex(1, "person"), createAntlr(new VariableResolver.DefaultVariableResolver(ElementHelper.asMap("x", new ReferenceVertex(1, "person"))))},
- {Order.class, "Order.desc", Order.desc, createAntlr(new VariableResolver.DefaultVariableResolver(ElementHelper.asMap("x", "nope")))},
- {Scope.class, "Scope.local", Scope.local, createAntlr(new VariableResolver.DefaultVariableResolver(ElementHelper.asMap("x", "nope")))},
- {Scope.class, "local", Scope.local, createAntlr(new VariableResolver.DefaultVariableResolver(ElementHelper.asMap("x", "nope")))},
- {T.class, "T.label", T.label, createAntlr(new VariableResolver.DefaultVariableResolver(ElementHelper.asMap("x", "nope")))},
- {T.class, "label", T.label, createAntlr(new VariableResolver.DefaultVariableResolver(ElementHelper.asMap("x", "nope")))},
- {VertexProperty.Cardinality.class, "Cardinality.list", VertexProperty.Cardinality.list, createAntlr(new VariableResolver.DefaultVariableResolver(ElementHelper.asMap("x", "nope")))},
- {VertexProperty.Cardinality.class, "list", VertexProperty.Cardinality.list, createAntlr(new VariableResolver.DefaultVariableResolver(ElementHelper.asMap("x", "nope")))},
- {DT.class, "DT.hour", DT.hour, createAntlr(new VariableResolver.DefaultVariableResolver(ElementHelper.asMap("x", "nope")))},
- {DT.class, "hour", DT.hour, createAntlr(new VariableResolver.DefaultVariableResolver(ElementHelper.asMap("x", "nope")))},
- {Merge.class, "Merge.onMatch", Merge.onMatch, createAntlr(new VariableResolver.DefaultVariableResolver(ElementHelper.asMap("x", "nope")))},
- {Merge.class, "onMatch", Merge.onMatch, createAntlr(new VariableResolver.DefaultVariableResolver(ElementHelper.asMap("x", "nope")))},
- {Pop.class, "Pop.last", Pop.last, createAntlr(new VariableResolver.DefaultVariableResolver(ElementHelper.asMap("x", "nope")))},
- {Pop.class, "last", Pop.last, createAntlr(new VariableResolver.DefaultVariableResolver(ElementHelper.asMap("x", "nope")))},
- {Operator.class, "Operator.sum", Operator.sum, createAntlr(new VariableResolver.DefaultVariableResolver(ElementHelper.asMap("x", "nope")))},
- {Operator.class, "sum", Operator.sum, createAntlr(new VariableResolver.DefaultVariableResolver(ElementHelper.asMap("x", "nope")))},
- {Column.class, "Column.keys", Column.keys, createAntlr(new VariableResolver.DefaultVariableResolver(ElementHelper.asMap("x", "nope")))},
- {Column.class, "keys", Column.keys, createAntlr(new VariableResolver.DefaultVariableResolver(ElementHelper.asMap("x", "nope")))},
- {SackFunctions.Barrier.class, "Barrier.normSack", SackFunctions.Barrier.normSack, createAntlr(new VariableResolver.DefaultVariableResolver(ElementHelper.asMap("x", "nope")))},
- {SackFunctions.Barrier.class, "Barrier.normSack", SackFunctions.Barrier.normSack, createAntlr(new VariableResolver.DefaultVariableResolver(ElementHelper.asMap("x", "nope")))},
+ {Object.class, "'test'", "test", createAntlr(new VariableResolver.DirectVariableResolver(ElementHelper.asMap("x", "nope")))},
+ {Object.class, "x", "test", createAntlr(new VariableResolver.DirectVariableResolver(ElementHelper.asMap("x", "test")))},
+ {Object.class, "x", now, createAntlr(new VariableResolver.DirectVariableResolver(ElementHelper.asMap("x", now)))},
+ {Object.class, "[1,2,3]", Arrays.asList(1, 2, 3), createAntlr(new VariableResolver.DirectVariableResolver(ElementHelper.asMap("x", now)))},
+ {Object.class, "x", P.eq(100), createAntlr(new VariableResolver.DirectVariableResolver(ElementHelper.asMap("x", P.eq(100))))},
+ {Direction.class, "Direction.OUT", Direction.OUT, createAntlr(new VariableResolver.DirectVariableResolver(ElementHelper.asMap("x", "nope")))},
+ {Direction.class, "OUT", Direction.OUT, createAntlr(new VariableResolver.DirectVariableResolver(ElementHelper.asMap("x", "nope")))},
+ {Vertex.class, "new Vertex(1i,'person')", new ReferenceVertex(1, "person"), createAntlr(new VariableResolver.DirectVariableResolver(ElementHelper.asMap("x", Direction.from)))},
+ {Order.class, "Order.desc", Order.desc, createAntlr(new VariableResolver.DirectVariableResolver(ElementHelper.asMap("x", "nope")))},
+ {Scope.class, "Scope.local", Scope.local, createAntlr(new VariableResolver.DirectVariableResolver(ElementHelper.asMap("x", "nope")))},
+ {Scope.class, "local", Scope.local, createAntlr(new VariableResolver.DirectVariableResolver(ElementHelper.asMap("x", "nope")))},
+ {T.class, "T.label", T.label, createAntlr(new VariableResolver.DirectVariableResolver(ElementHelper.asMap("x", "nope")))},
+ {T.class, "label", T.label, createAntlr(new VariableResolver.DirectVariableResolver(ElementHelper.asMap("x", "nope")))},
+ {VertexProperty.Cardinality.class, "Cardinality.list", VertexProperty.Cardinality.list, createAntlr(new VariableResolver.DirectVariableResolver(ElementHelper.asMap("x", "nope")))},
+ {VertexProperty.Cardinality.class, "list", VertexProperty.Cardinality.list, createAntlr(new VariableResolver.DirectVariableResolver(ElementHelper.asMap("x", "nope")))},
+ {DT.class, "DT.hour", DT.hour, createAntlr(new VariableResolver.DirectVariableResolver(ElementHelper.asMap("x", "nope")))},
+ {DT.class, "hour", DT.hour, createAntlr(new VariableResolver.DirectVariableResolver(ElementHelper.asMap("x", "nope")))},
+ {Merge.class, "Merge.onMatch", Merge.onMatch, createAntlr(new VariableResolver.DirectVariableResolver(ElementHelper.asMap("x", "nope")))},
+ {Merge.class, "onMatch", Merge.onMatch, createAntlr(new VariableResolver.DirectVariableResolver(ElementHelper.asMap("x", "nope")))},
+ {Pop.class, "Pop.last", Pop.last, createAntlr(new VariableResolver.DirectVariableResolver(ElementHelper.asMap("x", "nope")))},
+ {Pop.class, "last", Pop.last, createAntlr(new VariableResolver.DirectVariableResolver(ElementHelper.asMap("x", "nope")))},
+ {Operator.class, "Operator.sum", Operator.sum, createAntlr(new VariableResolver.DirectVariableResolver(ElementHelper.asMap("x", "nope")))},
+ {Operator.class, "sum", Operator.sum, createAntlr(new VariableResolver.DirectVariableResolver(ElementHelper.asMap("x", "nope")))},
+ {Column.class, "Column.keys", Column.keys, createAntlr(new VariableResolver.DirectVariableResolver(ElementHelper.asMap("x", "nope")))},
+ {Column.class, "keys", Column.keys, createAntlr(new VariableResolver.DirectVariableResolver(ElementHelper.asMap("x", "nope")))},
+ {SackFunctions.Barrier.class, "Barrier.normSack", SackFunctions.Barrier.normSack, createAntlr(new VariableResolver.DirectVariableResolver(ElementHelper.asMap("x", "nope")))},
+ {SackFunctions.Barrier.class, "Barrier.normSack", SackFunctions.Barrier.normSack, createAntlr(new VariableResolver.DirectVariableResolver(ElementHelper.asMap("x", "nope")))},
});
}
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/language/grammar/GremlinQueryParserTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/language/grammar/GremlinQueryParserTest.java
index 4e7168a7f5..a286e2e5fd 100644
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/language/grammar/GremlinQueryParserTest.java
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/language/grammar/GremlinQueryParserTest.java
@@ -41,7 +41,7 @@ public class GremlinQueryParserTest {
public void shouldParseVariables() {
final GremlinAntlrToJava gremlinAntlrToJava = new GremlinAntlrToJava("g",
EmptyGraph.instance(), __::start, g,
- new VariableResolver.DefaultVariableResolver(ElementHelper.asMap("z", 50)));
+ new VariableResolver.DirectVariableResolver(ElementHelper.asMap("z", 50)));
final GraphTraversal<?, ?> t = (GraphTraversal<?, ?>) GremlinQueryParser.parse("g.V().has('name',gt(z))", gremlinAntlrToJava);
assertEquals(g.V().has("name", P.gt(50)).asAdmin().getGremlinLang(),
@@ -52,7 +52,7 @@ public class GremlinQueryParserTest {
public void shouldParseVariablesInVarargs() {
final GremlinAntlrToJava gremlinAntlrToJava = new GremlinAntlrToJava("g",
EmptyGraph.instance(), __::start, g,
- new VariableResolver.DefaultVariableResolver(ElementHelper.asMap("x", 100,
+ new VariableResolver.DirectVariableResolver(ElementHelper.asMap("x", 100,
"y", 200,
"z", 50)));
@@ -73,7 +73,7 @@ public class GremlinQueryParserTest {
public void shouldNotParseVariablesInList() {
final GremlinAntlrToJava gremlinAntlrToJava = new GremlinAntlrToJava("g",
EmptyGraph.instance(), __::start, g,
- new VariableResolver.DefaultVariableResolver(ElementHelper.asMap("x", 100,
+ new VariableResolver.DirectVariableResolver(ElementHelper.asMap("x", 100,
"y", 200,
"z", 50)));
GremlinQueryParser.parse("g.V([x, y, 300]).has('name',gt(z))", gremlinAntlrToJava);
@@ -83,7 +83,7 @@ public class GremlinQueryParserTest {
public void shouldNotParseVariablesWhichAreTraversalBased() {
final GremlinAntlrToJava gremlinAntlrToJava = new GremlinAntlrToJava("g",
EmptyGraph.instance(), __::start, g,
- new VariableResolver.DefaultVariableResolver(ElementHelper.asMap("x", 100,
+ new VariableResolver.DirectVariableResolver(ElementHelper.asMap("x", 100,
"y", 200,
"z", __.out())));
GremlinQueryParser.parse("g.V([x, y, 300]).where(z)", gremlinAntlrToJava);
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/language/translator/GremlinTranslatorTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/language/translator/GremlinTranslatorTest.java
index 90022b34d5..82e3461cc5 100644
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/language/translator/GremlinTranslatorTest.java
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/language/translator/GremlinTranslatorTest.java
@@ -703,6 +703,33 @@ public class GremlinTranslatorTest {
null,
null,
"g.V().has_label(None)"},
+ {"g.V().hasLabel(null, null)",
+ null,
+ "g.V().hasLabel(string0, string0)",
+ "g.V().HasLabel((string) null, (string) null)",
+ "g.V().HasLabel(nil, nil)",
+ "g.V().hasLabel((String) null, (String) null)",
+ null,
+ null,
+ "g.V().has_label(None, None)"},
+ {"g.V().hasLabel(null, null, null)",
+ null,
+ "g.V().hasLabel(string0, string0, string0)",
+ "g.V().HasLabel((string) null, (string) null, (string) null)",
+ "g.V().HasLabel(nil, nil, nil)",
+ "g.V().hasLabel((String) null, (String) null, (String) null)",
+ null,
+ null,
+ "g.V().has_label(None, None, None)"},
+ {"g.V().hasLabel(\"person\", null)",
+ null,
+ "g.V().hasLabel(string0, string1)",
+ "g.V().HasLabel(\"person\", (string) null)",
+ "g.V().HasLabel(\"person\", nil)",
+ "g.V().hasLabel(\"person\", null)",
+ null,
+ null,
+ "g.V().has_label('person', None)"},
{"g.V().hasLabel('person')",
null,
"g.V().hasLabel(string0)",
@@ -724,9 +751,9 @@ public class GremlinTranslatorTest {
{"g.V().hasLabel(null, 'software', 'class')",
null,
"g.V().hasLabel(string0, string1, string2)",
- "g.V().HasLabel(null, \"software\", \"class\")",
+ "g.V().HasLabel((string) null, \"software\", \"class\")",
"g.V().HasLabel(nil, \"software\", \"class\")",
- "g.V().hasLabel(null, 'software', 'class')",
+ "g.V().hasLabel((String) null, 'software', 'class')",
"g.V().hasLabel(null, \"software\", \"class\")",
"g.V().hasLabel(null, \"software\", \"class\")",
"g.V().has_label(None, 'software', 'class')"},
@@ -1045,6 +1072,24 @@ public class GremlinTranslatorTest {
null,
null,
null},
+ {"g.V().hasLabel(x, y)",
+ null,
+ null,
+ "g.V().HasLabel((string) x, (string) y)",
+ "g.V().HasLabel(x, y)",
+ null,
+ null,
+ null,
+ "g.V().has_label(x, y)"},
+ {"g.V().conjoin(x)",
+ null,
+ null,
+ "g.V().Conjoin((string) x)",
+ "g.V().Conjoin(x)",
+ null,
+ null,
+ null,
+ null},
{"g.mergeV([name:\"alice\", T.label:\"person\"]).option(Merge.onCreate, [age:Cardinality.single(81)])",
null,
"g.mergeV(map0).option(Merge.onCreate, map1)",
@@ -1063,6 +1108,15 @@ public class GremlinTranslatorTest {
"g.mergeV(new LinkedHashMap<Object, Object>() {{ put(\"name\", \"alice\"); put(T.label, \"person\"); }}).option(Merge.onCreate, new LinkedHashMap<Object, Object>() {{ put(\"age\", Cardinality.single(81)); }})",
"g.mergeV(new Map([[\"name\", \"alice\"], [T.label, \"person\"]])).option(Merge.onCreate, new Map([[\"age\", CardinalityValue.single(81)]]))",
"g.merge_v({ 'name': 'alice', T.label: 'person' }).option(Merge.on_create, { 'age': CardinalityValue.single(81) })"},
+ {"g.V().branch(__.label().is(\"person\").count()).option(xx1, __.values(\"age\")).option(xx2, __.values(\"lang\")).option(xx2, __.values(\"name\")).option(Pick.any, __.label())",
+ null,
+ "g.V().branch(__.label().is(string0).count()).option(xx1, __.values(string1)).option(xx2, __.values(string2)).option(xx2, __.values(string3)).option(Pick.any, __.label())",
+ "g.V().Branch<object>(__.Label().Is(\"person\").Count()).Option(xx1, __.Values<object>(\"age\")).Option(xx2, __.Values<object>(\"lang\")).Option(xx2, __.Values<object>(\"name\")).Option(Pick.Any, __.Label())",
+ "g.V().Branch(gremlingo.T__.Label().Is(\"person\").Count()).Option(xx1, gremlingo.T__.Values(\"age\")).Option(xx2, gremlingo.T__.Values(\"lang\")).Option(xx2, gremlingo.T__.Values(\"name\")).Option(gremlingo.Pick.Any, gremlingo.T__.Label())",
+ null,
+ null,
+ null,
+ "g.V().branch(__.label().is_('person').count()).option(xx1, __.values('age')).option(xx2, __.values('lang')).option(xx2, __.values('name')).option(Pick.any_, __.label())"},
{"g.V().toList()",
null,
null,
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/GTypeTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/GTypeTest.java
new file mode 100644
index 0000000000..9596445860
--- /dev/null
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/GTypeTest.java
@@ -0,0 +1,77 @@
+/*
+ * 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;
+
+import org.apache.tinkerpop.gremlin.process.traversal.Path;
+import org.apache.tinkerpop.gremlin.structure.Edge;
+import org.apache.tinkerpop.gremlin.structure.Property;
+import org.apache.tinkerpop.gremlin.structure.Vertex;
+import org.junit.Test;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.Collections;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
+
+public class GTypeTest {
+
+ @Test
+ public void shouldReturnTrueForNumericTypes() {
+ assertThat(GType.INTEGER.isNumeric(), is(true));
+ assertThat(GType.DOUBLE.isNumeric(), is(true));
+ assertThat(GType.LONG.isNumeric(), is(true));
+ assertThat(GType.BIG_INTEGER.isNumeric(), is(true));
+ assertThat(GType.BIG_DECIMAL.isNumeric(), is(true));
+ }
+
+ @Test
+ public void shouldReturnFalseForNonNumericTypes() {
+ assertThat(GType.STRING.isNumeric(), is(false));
+ assertThat(GType.BOOLEAN.isNumeric(), is(false));
+ assertThat(GType.EDGE.isNumeric(), is(false));
+ assertThat(GType.VERTEX.isNumeric(), is(false));
+ }
+
+ @Test
+ public void shouldReturnCorrectGType() {
+ assertEquals(GType.STRING, GType.getType("test"));
+ assertEquals(GType.INTEGER, GType.getType(123));
+ assertEquals(GType.BOOLEAN, GType.getType(true));
+ assertEquals(GType.DOUBLE, GType.getType(123.45));
+ assertEquals(GType.LONG, GType.getType(123L));
+ assertEquals(GType.MAP, GType.getType(Collections.emptyMap()));
+ assertEquals(GType.LIST, GType.getType(Collections.emptyList()));
+ assertEquals(GType.SET, GType.getType(Collections.emptySet()));
+ assertEquals(GType.VERTEX, GType.getType(mock(Vertex.class)));
+ assertEquals(GType.EDGE, GType.getType(mock(Edge.class)));
+ assertEquals(GType.PATH, GType.getType(mock(Path.class)));
+ assertEquals(GType.PROPERTY, GType.getType(mock(Property.class)));
+ assertEquals(GType.BIG_INTEGER, GType.getType(BigInteger.ONE));
+ assertEquals(GType.BIG_DECIMAL, GType.getType(BigDecimal.ONE));
+ }
+
+ @Test
+ public void shouldReturnUnknownForUnmatchedTypes() {
+ assertEquals(GType.UNKNOWN, GType.getType(new Object()));
+ }
+}
\ No newline at end of file
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/GValueTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/GValueTest.java
new file mode 100644
index 0000000000..10bfafed29
--- /dev/null
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/GValueTest.java
@@ -0,0 +1,641 @@
+/*
+ * 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;
+
+import org.apache.tinkerpop.gremlin.process.traversal.Path;
+import org.apache.tinkerpop.gremlin.structure.Edge;
+import org.apache.tinkerpop.gremlin.structure.Property;
+import org.apache.tinkerpop.gremlin.structure.Vertex;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
+import static org.mockito.Mockito.mock;
+
+public class GValueTest {
+
+ @Test
+ public void shouldReturnAnExistingGValue() {
+ final GValue<Integer> gValue = GValue.of(123);
+ final Object returnedGValue = GValue.of(gValue);
+ assertEquals(gValue, returnedGValue);
+ assertSame(gValue, returnedGValue);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void shouldReturnAnExistInTypedGValue() {
+ final Object gValue = GValue.of("x", 123);
+ GValue.of("x", gValue);
+ }
+
+ @Test
+ public void shouldCreateGValueFromValue() {
+ final GValue<Integer> gValue = GValue.of(123);
+ assertEquals(123, gValue.get().intValue());
+ assertEquals(GType.INTEGER, gValue.getType());
+ assertThat(gValue.isVariable(), is(false));
+ }
+
+ @Test
+ public void shouldCreateGValueFromNameAndValue() {
+ final GValue<Integer> gValue = GValue.of("varName", 123);
+ assertEquals(123, gValue.get().intValue());
+ assertEquals(GType.INTEGER, gValue.getType());
+ assertEquals("varName", gValue.getName());
+ assertThat(gValue.isVariable(), is(true));
+ }
+
+ @Test
+ public void shouldCreateGValueFromString() {
+ final GValue<String> gValue = GValue.ofString("test");
+ assertEquals("test", gValue.get());
+ assertEquals(GType.STRING, gValue.getType());
+ assertThat(gValue.isVariable(), is(false));
+ }
+
+ @Test
+ public void shouldCreateGValueFromStringWithName() {
+ final GValue<String> gValue = GValue.ofString("varName", "test");
+ assertEquals("test", gValue.get());
+ assertEquals(GType.STRING, gValue.getType());
+ assertEquals("varName", gValue.getName());
+ assertThat(gValue.isVariable(), is(true));
+ }
+
+ @Test
+ public void shouldCreateGValueFromInteger() {
+ final GValue<Integer> gValue = GValue.ofInteger(123);
+ assertEquals(123, gValue.get().intValue());
+ assertEquals(GType.INTEGER, gValue.getType());
+ assertThat(gValue.isVariable(), is(false));
+ }
+
+ @Test
+ public void shouldCreateGValueFromIntegerWithName() {
+ final GValue<Integer> gValue = GValue.ofInteger("varName", 123);
+ assertEquals(123, gValue.get().intValue());
+ assertEquals(GType.INTEGER, gValue.getType());
+ assertEquals("varName", gValue.getName());
+ assertThat(gValue.isVariable(), is(true));
+ }
+
+ @Test
+ public void shouldCreateGValueFromBoolean() {
+ final GValue<Boolean> gValue = GValue.ofBoolean(true);
+ assertEquals(true, gValue.get());
+ assertEquals(GType.BOOLEAN, gValue.getType());
+ assertThat(gValue.isVariable(), is(false));
+ }
+
+ @Test
+ public void shouldCreateGValueFromBooleanWithName() {
+ final GValue<Boolean> gValue = GValue.ofBoolean("varName", true);
+ assertEquals(true, gValue.get());
+ assertEquals(GType.BOOLEAN, gValue.getType());
+ assertEquals("varName", gValue.getName());
+ assertThat(gValue.isVariable(), is(true));
+ }
+
+ @Test
+ public void shouldCreateGValueFromDouble() {
+ final GValue<Double> gValue = GValue.ofDouble(123.45);
+ assertEquals(123.45, gValue.get(), 0.0);
+ assertEquals(GType.DOUBLE, gValue.getType());
+ assertThat(gValue.isVariable(), is(false));
+ }
+
+ @Test
+ public void shouldCreateGValueFromDoubleWithName() {
+ final GValue<Double> gValue = GValue.ofDouble("varName", 123.45);
+ assertEquals(123.45, gValue.get(), 0.0);
+ assertEquals(GType.DOUBLE, gValue.getType());
+ assertEquals("varName", gValue.getName());
+ assertThat(gValue.isVariable(), is(true));
+ }
+
+ @Test
+ public void shouldCreateGValueFromBigInteger() {
+ final GValue<BigInteger> gValue = GValue.ofBigInteger(BigInteger.ONE);
+ assertEquals(BigInteger.ONE, gValue.get());
+ assertEquals(GType.BIG_INTEGER, gValue.getType());
+ assertThat(gValue.isVariable(), is(false));
+ }
+
+ @Test
+ public void shouldCreateGValueFromBigIntegerWithName() {
+ final GValue<BigInteger> gValue = GValue.ofBigInteger("varName", BigInteger.ONE);
+ assertEquals(BigInteger.ONE, gValue.get());
+ assertEquals(GType.BIG_INTEGER, gValue.getType());
+ assertEquals("varName", gValue.getName());
+ assertThat(gValue.isVariable(), is(true));
+ }
+
+ @Test
+ public void shouldCreateGValueFromBigDecimal() {
+ final GValue<BigDecimal> gValue = GValue.ofBigDecimal(BigDecimal.ONE);
+ assertEquals(BigDecimal.ONE, gValue.get());
+ assertEquals(GType.BIG_DECIMAL, gValue.getType());
+ assertThat(gValue.isVariable(), is(false));
+ }
+
+ @Test
+ public void shouldCreateGValueFromBigDecimalWithName() {
+ final GValue<BigDecimal> gValue = GValue.ofBigDecimal("varName", BigDecimal.ONE);
+ assertEquals(BigDecimal.ONE, gValue.get());
+ assertEquals(GType.BIG_DECIMAL, gValue.getType());
+ assertEquals("varName", gValue.getName());
+ assertThat(gValue.isVariable(), is(true));
+ }
+
+ @Test
+ public void shouldCreateGValueFromLong() {
+ final GValue<Long> gValue = GValue.ofLong(123L);
+ assertEquals(123L, gValue.get().longValue());
+ assertEquals(GType.LONG, gValue.getType());
+ assertThat(gValue.isVariable(), is(false));
+ }
+
+ @Test
+ public void shouldCreateGValueFromLongWithName() {
+ final GValue<Long> gValue = GValue.ofLong("varName", 123L);
+ assertEquals(123L, gValue.get().longValue());
+ assertEquals(GType.LONG, gValue.getType());
+ assertEquals("varName", gValue.getName());
+ assertThat(gValue.isVariable(), is(true));
+ }
+
+ @Test
+ public void shouldCreateGValueFromMap() {
+ final Map<String, String> map = new HashMap<String,String>() {{
+ put("key", "value");
+ }};
+ final GValue<Map> gValue = GValue.ofMap(map);
+ assertEquals(map, gValue.get());
+ assertEquals(GType.MAP, gValue.getType());
+ assertThat(gValue.isVariable(), is(false));
+ }
+
+ @Test
+ public void shouldCreateGValueFromMapWithName() {
+ final Map<String, String> map = new HashMap<String,String>() {{
+ put("key", "value");
+ }};
+ final GValue<Map> gValue = GValue.ofMap("varName", map);
+ assertEquals(map, gValue.get());
+ assertEquals(GType.MAP, gValue.getType());
+ assertEquals("varName", gValue.getName());
+ assertThat(gValue.isVariable(), is(true));
+ }
+
+ @Test
+ public void shouldCreateGValueFromList() {
+ final List<String> list = Arrays.asList("value1", "value2");
+ final GValue<List<String>> gValue = GValue.ofList(list);
+ assertEquals(list, gValue.get());
+ assertEquals(GType.LIST, gValue.getType());
+ assertThat(gValue.isVariable(), is(false));
+ }
+
+ @Test
+ public void shouldCreateGValueFromListWithName() {
+ final List<String> list = Arrays.asList("value1", "value2");
+ final GValue<List<String>> gValue = GValue.ofList("varName", list);
+ assertEquals(list, gValue.get());
+ assertEquals(GType.LIST, gValue.getType());
+ assertEquals("varName", gValue.getName());
+ assertThat(gValue.isVariable(), is(true));
+ }
+
+ @Test
+ public void shouldCreateGValueFromSet() {
+ final Set<String> set = new HashSet<>(Arrays.asList("value1", "value2"));
+ final GValue<Set> gValue = GValue.ofSet(set);
+ assertEquals(set, gValue.get());
+ assertEquals(GType.SET, gValue.getType());
+ assertThat(gValue.isVariable(), is(false));
+ }
+
+ @Test
+ public void shouldCreateGValueFromSetWithName() {
+ final Set<String> set = new HashSet<>(Arrays.asList("value1", "value2"));
+ final GValue<Set> gValue = GValue.ofSet("varName", set);
+ assertEquals(set, gValue.get());
+ assertEquals(GType.SET, gValue.getType());
+ assertEquals("varName", gValue.getName());
+ assertThat(gValue.isVariable(), is(true));
+ }
+
+ @Test
+ public void shouldCreateGValueFromVertex() {
+ final Vertex vertex = mock(Vertex.class);
+ final GValue<Vertex> gValue = GValue.ofVertex(vertex);
+ assertEquals(vertex, gValue.get());
+ assertEquals(GType.VERTEX, gValue.getType());
+ assertThat(gValue.isVariable(), is(false));
+ }
+
+ @Test
+ public void shouldCreateGValueFromVertexWithName() {
+ final Vertex vertex = mock(Vertex.class);
+ final GValue<Vertex> gValue = GValue.ofVertex("varName", vertex);
+ assertEquals(vertex, gValue.get());
+ assertEquals(GType.VERTEX, gValue.getType());
+ assertEquals("varName", gValue.getName());
+ assertThat(gValue.isVariable(), is(true));
+ }
+
+ @Test
+ public void shouldCreateGValueFromEdge() {
+ final Edge edge = mock(Edge.class);
+ final GValue<Edge> gValue = GValue.ofEdge(edge);
+ assertEquals(edge, gValue.get());
+ assertEquals(GType.EDGE, gValue.getType());
+ assertThat(gValue.isVariable(), is(false));
+ }
+
+ @Test
+ public void shouldCreateGValueFromEdgeWithName() {
+ final Edge edge = mock(Edge.class);
+ final GValue<Edge> gValue = GValue.ofEdge("varName", edge);
+ assertEquals(edge, gValue.get());
+ assertEquals(GType.EDGE, gValue.getType());
+ assertEquals("varName", gValue.getName());
+ assertThat(gValue.isVariable(), is(true));
+ }
+
+ @Test
+ public void shouldCreateGValueFromPath() {
+ final Path path = mock(Path.class);
+ final GValue<Path> gValue = GValue.ofPath(path);
+ assertEquals(path, gValue.get());
+ assertEquals(GType.PATH, gValue.getType());
+ assertThat(gValue.isVariable(), is(false));
+ }
+
+ @Test
+ public void shouldCreateGValueFromPathWithName() {
+ final Path path = mock(Path.class);
+ final GValue<Path> gValue = GValue.ofPath("varName", path);
+ assertEquals(path, gValue.get());
+ assertEquals(GType.PATH, gValue.getType());
+ assertEquals("varName", gValue.getName());
+ assertThat(gValue.isVariable(), is(true));
+ }
+
+ @Test
+ public void shouldCreateGValueFromProperty() {
+ final Property property = mock(Property.class);
+ final GValue<Property> gValue = GValue.ofProperty(property);
+ assertEquals(property, gValue.get());
+ assertEquals(GType.PROPERTY, gValue.getType());
+ assertThat(gValue.isVariable(), is(false));
+ }
+
+ @Test
+ public void shouldCreateGValueFromPropertyWithName() {
+ final Property property = mock(Property.class);
+ final GValue<Property> gValue = GValue.ofProperty("varName", property);
+ assertEquals(property, gValue.get());
+ assertEquals(GType.PROPERTY, gValue.getType());
+ assertEquals("varName", gValue.getName());
+ assertThat(gValue.isVariable(), is(true));
+ }
+
+ @Test
+ public void shouldBeAnInstanceOf() {
+ assertThat(GValue.instanceOf(GValue.of("string"), GType.STRING), is(true));
+ assertThat(GValue.instanceOf(GValue.ofInteger(1), GType.INTEGER), is(true));
+ assertThat(GValue.instanceOf("string", GType.STRING), is(true));
+ assertThat(GValue.instanceOf(1, GType.INTEGER), is(true));
+ }
+
+ @Test
+ public void shouldNotBeAnInstanceOf() {
+ assertThat(GValue.instanceOf(GValue.of("string"), GType.INTEGER), is(false));
+ assertThat(GValue.instanceOf(GValue.ofInteger(1), GType.STRING), is(false));
+ assertThat(GValue.instanceOf("string", GType.INTEGER), is(false));
+ assertThat(GValue.instanceOf(1, GType.STRING), is(false));
+ }
+
+ @Test
+ public void shouldBeAnInstanceOfCollection() {
+ assertThat(GValue.instanceOfCollection(GValue.of(Arrays.asList("string"))), is(true));
+ assertThat(GValue.instanceOfCollection(GValue.ofSet(new HashSet(Arrays.asList("string")))), is(true));
+ assertThat(GValue.instanceOfCollection(Arrays.asList("string")), is(true));
+ assertThat(GValue.instanceOfCollection(new HashSet(Arrays.asList("string"))), is(true));
+ }
+
+ @Test
+ public void shouldNotBeAnInstanceOfCollection() {
+ assertThat(GValue.instanceOfCollection(GValue.of(new HashMap())), is(false));
+ assertThat(GValue.instanceOfCollection(GValue.ofInteger(1)), is(false));
+ assertThat(GValue.instanceOfCollection(new HashMap()), is(false));
+ assertThat(GValue.instanceOfCollection(1), is(false));
+ }
+
+ @Test
+ public void shouldBeAnInstanceOfNumber() {
+ assertThat(GValue.instanceOfNumber(GValue.of(1)), is(true));
+ assertThat(GValue.instanceOfNumber(GValue.of(1L)), is(true));
+ assertThat(GValue.instanceOfNumber(GValue.of(1D)), is(true));
+ assertThat(GValue.instanceOfNumber(GValue.of(BigInteger.valueOf((1L)))), is(true));
+ assertThat(GValue.instanceOfNumber(GValue.of(BigDecimal.valueOf((1.0)))), is(true));
+ assertThat(GValue.instanceOfNumber(GValue.ofInteger(1)), is(true));
+ assertThat(GValue.instanceOfNumber(GValue.ofLong(1L)), is(true));
+ assertThat(GValue.instanceOfNumber(GValue.ofDouble(1D)), is(true));
+ assertThat(GValue.instanceOfNumber(GValue.ofBigInteger(BigInteger.valueOf((1L)))), is(true));
+ assertThat(GValue.instanceOfNumber(GValue.ofBigDecimal(BigDecimal.valueOf((1.0)))), is(true));
+ }
+
+ @Test
+ public void shouldNotBeAnInstanceOfNumber() {
+ assertThat(GValue.instanceOfNumber(GValue.of("string")), is(false));
+ assertThat(GValue.instanceOfNumber(GValue.of(Arrays.asList("string"))), is(false));
+ }
+
+ @Test
+ public void shouldBeAnInstanceOfElement() {
+ assertThat(GValue.instanceOfElement(GValue.ofVertex(mock(Vertex.class))), is(true));
+ assertThat(GValue.instanceOfElement(GValue.ofEdge(mock(Edge.class))), is(true));
+ }
+
+ @Test
+ public void shouldNotBeAnInstanceOfElement() {
+ assertThat(GValue.instanceOfElement(GValue.of("string")), is(false));
+ assertThat(GValue.instanceOfElement(GValue.of(Arrays.asList("string"))), is(false));
+ }
+
+ @Test
+ public void shouldHaveForMatchingType() {
+ final GValue<Integer> gValue = GValue.of(123);
+ assertThat(GValue.valueInstanceOf(gValue, GType.INTEGER), is(true));
+ }
+
+ @Test
+ public void valueInstanceOfShouldReturnFalseForNonMatchingType() {
+ final GValue<Integer> gValue = GValue.of(123);
+ assertThat(GValue.valueInstanceOf(gValue, GType.STRING), is(false));
+ }
+
+ @Test
+ public void valueInstanceOfShouldReturnFalseForNonGValueObject() {
+ String nonGValue = "test";
+ assertThat(GValue.valueInstanceOf(nonGValue, GType.STRING), is(false));
+ }
+
+ @Test
+ public void valueInstanceOfShouldReturnFalseForNullObject() {
+ assertThat(GValue.valueInstanceOf(null, GType.STRING), is(false));
+ }
+
+ @Test
+ public void getShouldReturnGValueValue() {
+ final GValue<Integer> gValue = GValue.of(123);
+ assertThat(GValue.getFrom(gValue), is(123));
+ }
+
+ @Test
+ public void getShouldReturnObjectAsIs() {
+ final String value = "test";
+ assertThat(GValue.getFrom(value), is(value));
+ }
+
+ @Test
+ public void getShouldReturnNullForNullInput() {
+ assertThat(GValue.getFrom(null), is((Object) null));
+ }
+
+ @Test
+ public void valueInstanceOfCollectionShouldReturnTrueForGValueWithCollectionType() {
+ final GValue<List<String>> gValue = GValue.ofList(Arrays.asList("value1", "value2"));
+ assertThat(GValue.valueInstanceOfCollection(gValue), is(true));
+ }
+
+ @Test
+ public void valueInstanceOfCollectionShouldReturnFalseForGValueWithNonCollectionType() {
+ final GValue<Integer> gValue = GValue.of(123);
+ assertThat(GValue.valueInstanceOfCollection(gValue), is(false));
+ }
+
+ @Test
+ public void valueInstanceOfCollectionShouldReturnFalseForNonGValueObject() {
+ assertThat(GValue.valueInstanceOfCollection("test"), is(false));
+ }
+
+ @Test
+ public void valueInstanceOfCollectionShouldReturnFalseForNullObject() {
+ assertThat(GValue.valueInstanceOfCollection(null), is(false));
+ }
+
+ @Test
+ public void valueInstanceOfNumericShouldReturnTrueForGValueWithNumericType() {
+ final GValue<Integer> gValue = GValue.of(123);
+ assertThat(GValue.valueInstanceOfNumeric(gValue), is(true));
+ }
+
+ @Test
+ public void valueInstanceOfNumericShouldReturnFalseForGValueWithNonNumericType() {
+ assertThat(GValue.valueInstanceOfNumeric("test"), is(false));
+ }
+
+ @Test
+ public void valueInstanceOfNumericShouldReturnFalseForNonGValueObject() {
+ assertThat(GValue.valueInstanceOfNumeric("test"), is(false));
+ }
+
+ @Test
+ public void valueInstanceOfNumericShouldReturnFalseForNullObject() {
+ assertThat(GValue.valueInstanceOfNumeric(null), is(false));
+ }
+
+ @Test
+ public void shouldConvertObjectArrayToGValues() {
+ final Object[] input = {1, "string", true};
+ final GValue<?>[] expected = {GValue.of(1), GValue.of("string"), GValue.of(true)};
+ final GValue<?>[] result = GValue.ensureGValues(input);
+ assertArrayEquals(expected, result);
+ }
+
+ @Test
+ public void shouldPreserveExistingGValuesInArray() {
+ final GValue<Integer> gValue = GValue.of(123);
+ final Object[] input = {gValue, "string"};
+ final GValue<?>[] expected = {gValue, GValue.of("string")};
+ final GValue<?>[] result = GValue.ensureGValues(input);
+ assertArrayEquals(expected, result);
+ }
+
+ @Test
+ public void shouldHandleEmptyArray() {
+ final Object[] input = {};
+ final GValue<?>[] expected = {};
+ final GValue<?>[] result = GValue.ensureGValues(input);
+ assertArrayEquals(expected, result);
+ }
+
+ @Test
+ public void shouldHandleArrayWithNullValues() {
+ final Object[] input = {null, "string"};
+ final GValue<?>[] expected = {GValue.of(null), GValue.of("string")};
+ final GValue<?>[] result = GValue.ensureGValues(input);
+ assertArrayEquals(expected, result);
+ }
+
+ @Test
+ public void shouldResolveGValuesToValues() {
+ final GValue<?>[] input = {GValue.of(1), GValue.of("string"), GValue.of(true)};
+ final Object[] expected = {1, "string", true};
+ final Object[] result = GValue.resolveToValues(input);
+ assertArrayEquals(expected, result);
+ }
+
+ @Test
+ public void shouldHandleEmptyGValuesArray() {
+ final GValue<?>[] input = {};
+ final Object[] expected = {};
+ final Object[] result = GValue.resolveToValues(input);
+ assertArrayEquals(expected, result);
+ }
+
+ @Test
+ public void shouldHandleGValuesArrayWithNullValues() {
+ final GValue<?>[] input = {GValue.of(null), GValue.of("string")};
+ final Object[] expected = {null, "string"};
+ final Object[] result = GValue.resolveToValues(input);
+ assertArrayEquals(expected, result);
+ }
+
+ @Test
+ public void shouldHandleMixedTypeGValuesArray() {
+ final GValue<?>[] input = {GValue.of(1), GValue.of("string"), GValue.of(true), GValue.of(123.45)};
+ final Object[] expected = {1, "string", true, 123.45};
+ final Object[] result = GValue.resolveToValues(input);
+ assertArrayEquals(expected, result);
+ }
+
+ @Test
+ public void equalsShouldReturnTrueForSameObject() {
+ final GValue<Integer> gValue = GValue.of(123);
+ assertEquals(true, gValue.equals(gValue));
+ }
+
+ @Test
+ public void equalsShouldReturnFalseForNull() {
+ final GValue<Integer> gValue = GValue.of(123);
+ assertEquals(false, gValue.equals(null));
+ }
+
+ @Test
+ public void equalsShouldReturnFalseForDifferentClass() {
+ final GValue<Integer> gValue = GValue.of(123);
+ assertEquals(false, gValue.equals("string"));
+ }
+
+ @Test
+ public void equalsShouldReturnTrueForEqualGValues() {
+ final GValue<Integer> gValue1 = GValue.of(123);
+ final GValue<Integer> gValue2 = GValue.of(123);
+ assertEquals(true, gValue1.equals(gValue2));
+ }
+
+ @Test
+ public void equalsShouldReturnFalseForDifferentNames() {
+ final GValue<Integer> gValue1 = GValue.of("name1", 123);
+ final GValue<Integer> gValue2 = GValue.of("name2", 123);
+ assertEquals(false, gValue1.equals(gValue2));
+ }
+
+ @Test
+ public void equalsShouldReturnFalseForDifferentTypes() {
+ final GValue<Integer> gValue1 = GValue.of(123);
+ final GValue<String> gValue2 = GValue.of("123");
+ assertEquals(false, gValue1.equals(gValue2));
+ }
+
+ @Test
+ public void equalsShouldReturnFalseForDifferentValues() {
+ final GValue<Integer> gValue1 = GValue.of(123);
+ final GValue<Integer> gValue2 = GValue.of(456);
+ assertEquals(false, gValue1.equals(gValue2));
+ }
+
+ @Test
+ public void valueOfShouldReturnGValueValue() {
+ final GValue<Integer> gValue = GValue.of(123);
+ assertEquals(123, GValue.valueOf(gValue));
+ }
+
+ @Test
+ public void valueOfShouldReturnObjectAsIs() {
+ final String value = "test";
+ assertEquals("test", GValue.valueOf(value));
+ }
+
+ @Test
+ public void valueOfShouldReturnNullForNullInput() {
+ assertNull(GValue.valueOf(null));
+ assertNull(null);
+ }
+
+ @Test
+ public void numberOfShouldReturnGValueValue() {
+ final GValue<Integer> gValue = GValue.ofInteger(1234);
+ assertEquals(1234, GValue.numberOf(gValue));
+ }
+
+ @Test
+ public void numberOfShouldReturnObjectAsIs() {
+ assertEquals(1234, GValue.numberOf(1234));
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void numberOfShouldThrowBecauseGValueNotNumberType() {
+ assertEquals(1234, GValue.numberOf("1234"));
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void numberOfShouldThrowBecauseObjectNotNumberType() {
+ final GValue<String> gValue = GValue.of("1234");
+ GValue.numberOf(gValue);
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void numberOfShouldThrowBecauseNullIntegerGType() {
+ GValue.numberOf(GValue.of(null, GType.INTEGER));
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void numberOfShouldThrowBecauseNullObject() {
+ GValue.numberOf(null);
+ }
+}
\ No newline at end of file
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ConjoinStepTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ConjoinStepTest.java
index a84c691182..35d9fe29f9 100644
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ConjoinStepTest.java
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ConjoinStepTest.java
@@ -41,7 +41,7 @@ public class ConjoinStepTest extends StepTest {
@Test
public void testReturnTypes() {
try {
- __.__(Collections.emptyList()).conjoin(null).next();
+ __.__(Collections.emptyList()).conjoin((String) null).next();
fail();
} catch (Exception e) {
assertTrue(e.getMessage().contains("Input delimiter to conjoin step can't be null"));
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/ParametersTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/ParametersTest.java
index 0983540dcb..f509926359 100644
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/ParametersTest.java
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/ParametersTest.java
@@ -21,6 +21,7 @@ package org.apache.tinkerpop.gremlin.process.traversal.step.util;
import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
+import org.apache.tinkerpop.gremlin.process.traversal.step.GValue;
import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent;
import org.junit.Test;
@@ -356,4 +357,14 @@ public class ParametersTest {
verify(mock).integrateChild(__.outE("knows").asAdmin());
}
+
+ @Test
+ public void shouldGetKeyValuesAndResolveGValues() {
+ final Parameters parameters = new Parameters();
+ parameters.set(null, "a", "axe", "b", GValue.of("B", "bat"), "c", GValue.of("C", "cat"));
+
+ final Object[] params = parameters.getKeyValues(mock(Traverser.Admin.class));
+ assertEquals(6, params.length);
+ assertThat(Arrays.equals(new Object[] {"a", "axe", "b", "bat", "c", "cat"}, params), is(true));
+ }
}
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/util/CollectionUtilTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/util/CollectionUtilTest.java
index 73bd39b415..7b938c1a22 100644
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/util/CollectionUtilTest.java
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/util/CollectionUtilTest.java
@@ -22,10 +22,20 @@ import org.apache.tinkerpop.gremlin.AssertHelper;
import org.junit.Test;
import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;
public class CollectionUtilTest {
@@ -70,4 +80,104 @@ public class CollectionUtilTest {
final ConcurrentHashMap<?, ?> cloned = CollectionUtil.clone(source);
assertTrue(source.equals(cloned));
}
+
+ @Test
+ public void shouldCloneEmptyConcurrentHashMap() {
+ final ConcurrentHashMap<String, String> source = new ConcurrentHashMap<>();
+ final ConcurrentHashMap<?, ?> cloned = CollectionUtil.clone(source);
+ assertTrue(source.equals(cloned));
+ }
+
+ @Test
+ public void shouldCloneConcurrentHashMapWithMixedTypes() {
+ final ConcurrentHashMap<String, Object> source = new ConcurrentHashMap<>();
+ source.put("key1", "value1");
+ source.put("key2", new ArrayList<>(Arrays.asList("a", "b")));
+ source.put("key3", new HashSet<>(Arrays.asList("x", "y")));
+
+ final ConcurrentHashMap<?, ?> cloned = CollectionUtil.clone(source);
+ assertTrue(source.equals(cloned));
+ }
+
+ @Test
+ public void shouldAddFirstWhenBothArgumentsNull() {
+ String[] result = CollectionUtil.addFirst(null, null, String.class);
+ assertArrayEquals(new String[]{null}, result);
+ }
+
+ @Test
+ public void shouldAddFirstWhenArrayNull() {
+ String[] result = CollectionUtil.addFirst(null, "element", String.class);
+ assertArrayEquals(new String[]{"element"}, result);
+ }
+
+ @Test
+ public void shoulAddFirstWhenNeitherArgumentNull() {
+ Integer[] array = {1, 2, 3};
+ Integer[] result = CollectionUtil.addFirst(array, 0, Integer.class);
+ assertArrayEquals(new Integer[]{0, 1, 2, 3}, result);
+ }
+
+ @Test
+ public void shouldAddFirstWhenEmptyArray() {
+ String[] array = {};
+ String[] result = CollectionUtil.addFirst(array, "element", String.class);
+ assertArrayEquals(new String[]{"element"}, result);
+ }
+
+ @Test
+ public void shouldAddFirstWhenIntegers() {
+ Integer[] array = {1, 2, 3};
+ Integer[] result = CollectionUtil.addFirst(array, 0, Integer.class);
+ assertArrayEquals(new Integer[]{0, 1, 2, 3}, result);
+ }
+
+ @Test
+ public void shouldConvertVarargsToList() {
+ List<String> result = CollectionUtil.asList("a", "b", "c");
+ assertEquals(Arrays.asList("a", "b", "c"), result);
+ }
+
+ @Test
+ public void shouldConvertEmptyVarargsToList() {
+ List<String> result = CollectionUtil.asList();
+ assertEquals(Collections.emptyList(), result);
+ }
+
+ @Test
+ public void shouldConvertVarargsToSet() {
+ Set<String> result = CollectionUtil.asSet("a", "b", "c");
+ assertEquals(new LinkedHashSet<>(Arrays.asList("a", "b", "c")), result);
+ }
+
+ @Test
+ public void shouldConvertEmptyVarargsToSet() {
+ Set<String> result = CollectionUtil.asSet();
+ assertEquals(new LinkedHashSet<>(), result);
+ }
+
+ @Test
+ public void shouldConvertCollectionToSet() {
+ Collection<String> collection = Arrays.asList("a", "b", "c");
+ Set<String> result = CollectionUtil.asSet(collection);
+ assertEquals(new LinkedHashSet<>(collection), result);
+ }
+
+ @Test
+ public void shouldConvertVarargsToMap() {
+ Map<String, String> result = CollectionUtil.asMap("key1", "value1", "key2", "value2");
+ Map<String, String> expected = new LinkedHashMap<>();
+ expected.put("key1", "value1");
+ expected.put("key2", "value2");
+ assertEquals(expected, result);
+ }
+
+ @Test
+ public void shouldConvertVarargsToMapWithOddNumberOfElements() {
+ Map<String, String> result = CollectionUtil.asMap("key1", "value1", "key2");
+ Map<String, String> expected = new LinkedHashMap<>();
+ expected.put("key1", "value1");
+ expected.put("key2", null);
+ assertEquals(expected, result);
+ }
}
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/CommonSteps.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/CommonSteps.cs
index 98f8b0b5b4..98d49d8df7 100644
--- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/CommonSteps.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/CommonSteps.cs
@@ -115,13 +115,6 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
_parameters.Add(name, parsedValue);
}
- [Given("using the parameter (\\w+) of P.(\\w+)\\(\"(.*)\"\\)")]
- public void UsingParameterP(string name, string pval, string value)
- {
- var parsedValue = ParseValue(value.Replace("\\\"", "\""), _graphName!);
- _parameters.Add(name, new P(pval, parsedValue));
- }
-
[Given("the traversal of")]
public void TranslateTraversal(string traversalText)
{
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs
index e72e7aa112..b324e8be68 100644
--- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs
@@ -63,17 +63,17 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
new Dictionary<string, List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>>>
{
{"g_V_branchXlabel_eq_person__a_bX_optionXa__ageX_optionXb__langX_optionXb__nameX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>>()}, // skipping as it contains a lambda
- {"g_V_branchXlabel_isXpersonX_countX_optionX1__ageX_optionX0__langX_optionX0__nameX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Branch<object>(__.Label().Is("person").Count()).Option(p["xx1"], (ITraversal) __.Values<object>("age")).Option(p["xx2"], (ITraversal) __.Values<object>("lang")).Option(p["xx2"], (ITraversal) __.Values<object>("name"))}},
- {"g_V_branchXlabel_isXpersonX_countX_optionX1__ageX_optionX0__langX_optionX0__nameX_optionXany__labelX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Branch<object>(__.Label().Is("person").Count()).Option(p["xx1"], (ITraversal) __.Values<object>("age")).Option(p["xx2"], (ITraversal) __.Values<object>("lang")).Option(p["xx2"], (ITraversal) __.Values<object>("name")).Option(Pick.Any, __.Label())}},
+ {"g_V_branchXlabel_isXpersonX_countX_optionX1__ageX_optionX0__langX_optionX0__nameX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Branch<object>(__.Label().Is("person").Count()).Option(p["xx1"], __.Values<object>("age")).Option(p["xx2"], __.Values<object>("lang")).Option(p["xx2"], __.Values<object>("name"))}},
+ {"g_V_branchXlabel_isXpersonX_countX_optionX1__ageX_optionX0__langX_optionX0__nameX_optionXany__labelX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Branch<object>(__.Label().Is("person").Count()).Option(p["xx1"], __.Values<object>("age")).Option(p["xx2"], __.Values<object>("lang")).Option(p["xx2"], __.Values<object>("name")).Option(Pick.Any, __.Label())}},
{"g_V_branchXageX_optionXltX30X__youngX_optionXgtX30X__oldX_optionXnone__on_the_edgeX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().HasLabel("person").Branch<object>(__.Values<object>("age")).Option(P.Lt(30), __.Constant<object>("young")).Option(P.Gt(30), __.Constant<object>("old")).Option(Pick.None, __.Constant<object>("on the edge"))}},
{"g_V_branchXidentityX_optionXhasLabelXsoftwareX__inXcreatedX_name_order_foldX_optionXhasXname_vadasX__ageX_optionXneqX123X__bothE_countX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Branch<object>(__.Identity()).Option(__.HasLabel("software"), __.In("created").Values<object>("name").Order().Fold()).Option(__.Has("name", "vadas"), __.Values<object>("age")).Option(P.Neq(123), __.BothE().Count())}},
- {"g_V_chooseXout_countX_optionX2L_nameX_optionX3L_ageX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Choose<object>(__.Out().Count()).Option(p["xx1"], (ITraversal) __.Values<object>("name")).Option(p["xx2"], (ITraversal) __.Values<object>("age"))}},
+ {"g_V_chooseXout_countX_optionX2L_nameX_optionX3L_ageX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Choose<object>(__.Out().Count()).Option(p["xx1"], __.Values<object>("name")).Option(p["xx2"], __.Values<object>("age"))}},
{"g_V_chooseXlabel_eqXpersonX__outXknowsX__inXcreatedXX_name", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>>()}, // skipping as it contains a lambda
{"g_V_chooseXhasLabelXpersonX_and_outXcreatedX__outXknowsX__identityX_name", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Choose<object>(__.HasLabel("person").And().Out("created"), __.Out("knows"), __.Identity()).Values<object>("name")}},
{"g_V_chooseXlabelX_optionXblah__outXknowsXX_optionXbleep__outXcreatedXX_optionXnone__identityX_name", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Choose<object>(__.Label()).Option("blah", __.Out("knows")).Option("bleep", __.Out("created")).Option(Pick.None, __.Identity()).Values<object>("name")}},
{"g_V_chooseXoutXknowsX_count_isXgtX0XX__outXknowsXX_name", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Choose<object>(__.Out("knows").Count().Is(P.Gt(0)), __.Out("knows")).Values<object>("name")}},
{"g_V_hasLabelXpersonX_asXp1X_chooseXoutEXknowsX__outXknowsXX_asXp2X_selectXp1_p2X_byXnameX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().HasLabel("person").As("p1").Choose<object>(__.OutE("knows"), __.Out("knows")).As("p2").Select<object>("p1", "p2").By("name")}},
- {"g_V_hasLabelXpersonX_chooseXageX__optionX27L__constantXyoungXX_optionXnone__constantXoldXX_groupCount", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().HasLabel("person").Choose<object>(__.Values<object>("age")).Option(p["xx1"], (ITraversal) __.Constant<object>("young")).Option(Pick.None, __.Constant<object>("old")).GroupCount<object>()}},
+ {"g_V_hasLabelXpersonX_chooseXageX__optionX27L__constantXyoungXX_optionXnone__constantXoldXX_groupCount", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().HasLabel("person").Choose<object>(__.Values<object>("age")).Option(p["xx1"], __.Constant<object>("young")).Option(Pick.None, __.Constant<object>("old")).GroupCount<object>()}},
{"g_injectX1X_chooseXisX1X__constantX10Xfold__foldX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject<object>(p["xx2"]).Choose<object>(__.Is(p["xx2"]), __.Constant<object>(p["xx1"]).Fold(), __.Fold<object>())}},
{"g_injectX2X_chooseXisX1X__constantX10Xfold__foldX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject<object>(p["xx3"]).Choose<object>(__.Is(p["xx2"]), __.Constant<object>(p["xx1"]).Fold(), __.Fold<object>())}},
{"g_V_localXpropertiesXlocationX_order_byXvalueX_limitX2XX_value", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Local<object>(__.Properties<object>("location").Order().By(T.Value, Order.Asc).Range<object>(0, 2)).Value<object>()}},
@@ -234,6 +234,8 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
{"g_VX1X_out_hasXid_2X", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V((Vertex) p["v2"]).Has("age", P.Gt(30))}},
{"g_V_hasXblahX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Has("blah")}},
{"g_V_hasXperson_name_markoX_age", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Has("person", "name", "marko").Values<object>("age")}},
+ {"g_V_hasXperson_name_markovarX_age", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Has("person", "name", (object) p["xx1"]).Values<object>("age")}},
+ {"g_V_hasXpersonvar_name_markoX_age", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Has((string) p["xx1"], "name", "marko").Values<object>("age")}},
{"g_VX1X_outE_hasXweight_inside_0_06X_inV", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V(p["vid1"]).OutE().Has("weight", P.Inside(0.0, 0.6)).InV()}},
{"g_EX11X_outV_outE_hasXid_10X", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.E(p["eid11"]).OutV().OutE().Has(T.Id, (object) p["eid10"])}},
{"g_EX11X_outV_outE_hasXid_10AsStringX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.E(p["eid11"]).OutV().OutE().Has(T.Id, (object) p["eid10"])}},
@@ -269,9 +271,9 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
{"g_V_hasXlabel_isXpersonXX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Has(T.Label, __.Is("person"))}},
{"g_V_hasXname_nullX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Has("name", (object) null)}},
{"g_V_hasIdXemptyX_count", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().HasId(p["xx1"]).Count()}},
- {"g_V_hasIdXwithinXemptyXX_count", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().HasId(p["xx1"]).Count()}},
- {"g_V_hasIdXwithoutXemptyXX_count", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().HasId(p["xx1"]).Count()}},
- {"g_V_notXhasIdXwithinXemptyXXX_count", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Not(__.HasId(p["xx1"])).Count()}},
+ {"g_V_hasIdXwithinXemptyXX_count", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().HasId(P.Within(new List<object> { })).Count()}},
+ {"g_V_hasIdXwithoutXemptyXX_count", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().HasId(P.Without(new List<object> { })).Count()}},
+ {"g_V_notXhasIdXwithinXemptyXXX_count", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Not(__.HasId(P.Within(new List<object> { }))).Count()}},
{"g_V_hasIdXnullX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().HasId(null)}},
{"g_V_hasIdXeqXnullXX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().HasId(P.Eq(null))}},
{"g_V_hasIdX2_nullX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().HasId(p["vid2"], null)}},
@@ -279,7 +281,7 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
{"g_V_hasIdX1AsString_2AsString_nullX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().HasId(p["vid1"], p["vid2"], null)}},
{"g_V_hasIdXnull_2X", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().HasId(null, p["vid2"])}},
{"g_V_hasIdX1X_hasIdX2X", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().HasId(p["vid1"]).HasId(p["vid2"])}},
- {"g_V_in_hasIdXneqX1XX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().In().HasId(p["xx1"])}},
+ {"g_V_in_hasIdXneqX1XX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().In().HasId(P.Neq(p["xx1"]))}},
{"g_VX1X_out_hasIdX2X", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V(p["vid1"]).Out().HasId(p["vid2"])}},
{"g_VX1X_out_hasXid_2_3X", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V(p["vid1"]).Out().HasId(p["vid2"], p["vid3"])}},
{"g_VX1X_out_hasXid_2AsString_3AsStringX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V(p["vid1"]).Out().HasId(p["vid2"], p["vid3"])}},
@@ -292,21 +294,23 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
{"g_V_bothE_properties_dedup_hasKeyXweightX_value", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().BothE().Properties<object>().Dedup().HasKey("weight").Value<object>()}},
{"g_V_bothE_properties_dedup_hasKeyXweightX_hasValueXltX0d3XX_value", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().BothE().Properties<object>().Dedup().HasKey("weight").HasValue(P.Lt(0.3)).Value<object>(), (g,p) =>g.V().BothE().Properties<object>().Dedup().HasKey("weight").HasValue(P.Lt(0.3)).Value<object>()}},
{"g_V_properties_hasKeyXnullX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Properties<object>().HasKey((string) null)}},
- {"g_V_properties_hasKeyXnull_nullX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Properties<object>().HasKey(null, null)}},
+ {"g_V_properties_hasKeyXnull_nullX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Properties<object>().HasKey(null, (string) null)}},
{"g_V_properties_hasKeyXnull_ageX_value", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Properties<object>().HasKey(null, "age").Value<object>()}},
{"g_E_properties_hasKeyXnullX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.E().Properties<object>().HasKey((string) null)}},
- {"g_E_properties_hasKeyXnull_nullX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.E().Properties<object>().HasKey(null, null)}},
+ {"g_E_properties_hasKeyXnull_nullX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.E().Properties<object>().HasKey(null, (string) null)}},
{"g_E_properties_hasKeyXnull_weightX_value", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.E().Properties<object>().HasKey(null, "weight").Value<object>()}},
{"g_EX7X_hasLabelXknowsX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.E(p["eid7"]).HasLabel("knows")}},
{"g_E_hasLabelXknowsX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.E().HasLabel("knows")}},
{"g_E_hasLabelXuses_traversesX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.E().HasLabel("uses", "traverses")}},
{"g_V_hasLabelXperson_software_blahX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().HasLabel("person", "software", "blah")}},
{"g_V_hasLabelXpersonX_hasLabelXsoftwareX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().HasLabel("person").HasLabel("software")}},
+ {"g_V_hasLabelXpersonvarX_hasLabelXsoftwareX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().HasLabel((string) p["xx1"]).HasLabel("software")}},
+ {"g_V_hasLabelXpersonvar_softwarevarX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().HasLabel((string) p["xx1"], (string) p["xx2"])}},
{"g_V_hasLabelXpersonX_hasXage_notXlteX10X_andXnotXbetweenX11_20XXXX_andXltX29X_orXeqX35XXXX_name", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().HasLabel("person").Has("age", P.Not(P.Lte(10).And(P.Not(P.Between(11, 20)))).And(P.Lt(29).Or(P.Eq(35)))).Values<object>("name")}},
{"g_V_hasLabelXnullX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().HasLabel((string) null)}},
{"g_V_hasXlabel_nullX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Has(T.Label, (object) null)}},
- {"g_V_hasLabelXnull_nullX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().HasLabel(null, null)}},
- {"g_V_hasLabelXnull_personX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().HasLabel(null, "person")}},
+ {"g_V_hasLabelXnull_nullX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().HasLabel((string) null, (string) null)}},
+ {"g_V_hasLabelXnull_personX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().HasLabel((string) null, "person")}},
{"g_E_hasLabelXnullX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.E().HasLabel((string) null)}},
{"g_E_hasXlabel_nullX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.E().Has(T.Label, (object) null)}},
{"g_V_properties_hasLabelXnullX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Properties<object>().HasLabel((string) null)}},
@@ -695,7 +699,7 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
{"g_injectXaX_concat_Xinject_List_b_cX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject<object>("a").Concat(__.Inject(p["xx1"]))}},
{"g_injectXListXa_bXcX_concat_XdX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject<object>(p["xx1"], "c").Concat("d")}},
{"g_injectXnullX_concat_XinjectX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject<object>(null).Concat()}},
- {"g_injectXnull_aX_concat_Xnull_bX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject<object>(null, "a").Concat(null, "b")}},
+ {"g_injectXnull_aX_concat_Xnull_bX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject<object>(null, "a").Concat((string) null, "b")}},
{"g_injectXhello_hiX_concat_XV_valuesXnameXX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject<object>("hello", "hi").Concat(__.V().Order().By(T.Id).Values<object>("name"))}},
{"g_V_hasLabel_value_concat_X_X_concat_XpersonX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().HasLabel("person").Values<object>("name").Concat(" ").Concat("person")}},
{"g_hasLabelXpersonX_valuesXnameX_asXaX_constantXMrX_concatXselectXaX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().HasLabel("person").Values<object>("name").As("a").Constant<object>("Mr.").Concat(__.Select<object>("a"))}},
@@ -703,17 +707,18 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
{"g_VX1X_outE_asXaX_VX1X_valuesXnamesX_concatXselectXaX_labelX_concatXselectXaX_inV_valuesXnameXX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V(p["vid1"]).OutE().As("a").V(p["vid1"]).Values<object>("name").Concat(__.Select<object>("a").Label()).Concat(__.Select<object>("a").InV().Values<object>("name"))}},
{"g_VX1X_outE_asXaX_VX1X_valuesXnamesX_concatXselectXaX_label_selectXaX_inV_valuesXnameXX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V(p["vid1"]).OutE().As("a").V(p["vid1"]).Values<object>("name").Concat(__.Select<object>("a").Label(), __.Select<object>("a").InV().Values<object>("name"))}},
{"g_addVXconstantXprefix_X_concatXVX1X_labelX_label", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.AddV("person").Property("name", "marko").Property("age", 29).As("marko").AddV("person").Property("name", "vadas").Property("age", 27).As("vadas").AddV("software").Property("name", "lop").Property("lang", "java").As("lop").AddV("person").Property("name", "josh").Property("age", 32).As("josh").AddV("software").Property("name", "ripple [...]
- {"g_injectXnullX_conjoinX1X", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject<object>(null).Conjoin("1")}},
- {"g_V_valuesXnameX_conjoinX1X", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Values<object>("name").Conjoin("1")}},
- {"g_V_valuesXnonexistantX_fold_conjoinX_X", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Values<object>("nonexistant").Fold().Conjoin(";")}},
- {"g_V_valuesXnameX_order_fold_conjoinX_X", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Values<object>("name").Order().Fold().Conjoin("_")}},
- {"g_V_valuesXageX_order_fold_conjoinX_X", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Values<object>("age").Order().Fold().Conjoin(";")}},
- {"g_V_out_path_byXvaluesXnameX_toUpperX_conjoinXMARKOX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Out().Path().By(__.Values<object>("name").ToUpper()).Conjoin("MARKO")}},
- {"g_injectXmarkoX_conjoinX_X", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject<object>(p["xx1"]).Conjoin("-")}},
- {"g_V_valueMapXlocationX_selectXvaluesX_unfold_orderXlocalX_conjoinX1X", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().ValueMap<object, object>("location").Select<object>(Column.Values).Unfold<object>().Order(Scope.Local).Conjoin("1")}},
- {"g_V_out_out_path_byXnameX_conjoinXX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Out().Out().Path().By("name").Conjoin("")}},
- {"g_injectXa_null_bX_conjoinXxyzX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject<object>(p["xx1"]).Conjoin("xyz")}},
- {"g_injectX3_threeX_conjoinX_X", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject<object>(p["xx1"]).Conjoin(";")}},
+ {"g_injectXnullX_conjoinX1X", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject<object>(null).Conjoin((string) "1")}},
+ {"g_V_valuesXnameX_conjoinX1X", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Values<object>("name").Conjoin((string) "1")}},
+ {"g_V_valuesXnonexistantX_fold_conjoinX_X", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Values<object>("nonexistant").Fold().Conjoin((string) ";")}},
+ {"g_V_valuesXnameX_order_fold_conjoinX_X", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Values<object>("name").Order().Fold().Conjoin((string) "_")}},
+ {"g_V_valuesXageX_order_fold_conjoinXsemicolonX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Values<object>("age").Order().Fold().Conjoin((string) ";")}},
+ {"g_V_valuesXageX_order_fold_conjoinXslashX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Values<object>("age").Order().Fold().Conjoin((string) p["xx1"])}},
+ {"g_V_out_path_byXvaluesXnameX_toUpperX_conjoinXMARKOX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Out().Path().By(__.Values<object>("name").ToUpper()).Conjoin((string) "MARKO")}},
+ {"g_injectXmarkoX_conjoinX_X", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject<object>(p["xx1"]).Conjoin((string) "-")}},
+ {"g_V_valueMapXlocationX_selectXvaluesX_unfold_orderXlocalX_conjoinX1X", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().ValueMap<object, object>("location").Select<object>(Column.Values).Unfold<object>().Order(Scope.Local).Conjoin((string) "1")}},
+ {"g_V_out_out_path_byXnameX_conjoinXX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Out().Out().Path().By("name").Conjoin((string) "")}},
+ {"g_injectXa_null_bX_conjoinXxyzX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject<object>(p["xx1"]).Conjoin((string) "xyz")}},
+ {"g_injectX3_threeX_conjoinX_X", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject<object>(p["xx1"]).Conjoin((string) ";")}},
{"g_V_connectedComponent_hasXcomponentX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().ConnectedComponent().Has("gremlin.connectedComponentVertexProgram.component")}},
{"g_V_dedup_connectedComponent_hasXcomponentX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Dedup().ConnectedComponent().Has("gremlin.connectedComponentVertexProgram.component")}},
{"g_V_hasLabelXsoftwareX_connectedComponent_project_byXnameX_byXcomponentX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().HasLabel("software").ConnectedComponent().Project<object>("name", "component").By("name").By("gremlin.connectedComponentVertexProgram.component")}},
@@ -797,7 +802,7 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
{"g_V_elementMap", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().ElementMap<object>()}},
{"g_V_elementMapXname_ageX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().ElementMap<object>("name", "age")}},
{"g_EX11X_elementMap", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.E(p["eid11"]).ElementMap<object>()}},
- {"g_V_elementMapXname_age_nullX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().ElementMap<object>("name", "age", null)}},
+ {"g_V_elementMapXname_age_nullX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().ElementMap<object>("name", "age", (string) null)}},
{"g_V_asXaX_flatMapXselectXaXX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().As("a").FlatMap<object>(__.Select<object>("a"))}},
{"g_V_fold", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Fold()}},
{"g_V_fold_unfold", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Fold().Unfold<object>()}},
@@ -1169,8 +1174,8 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
{"g_V_hasXageX_propertiesXnameX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Has("age").Properties<object>("name").Value<object>()}},
{"g_V_hasXageX_propertiesXname_ageX_value", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Has("age").Properties<object>("name", "age").Value<object>()}},
{"g_V_hasXageX_propertiesXage_nameX_value", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Has("age").Properties<object>("age", "name").Value<object>()}},
- {"g_V_propertiesXname_age_nullX_value", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Properties<object>("name", "age", null).Value<object>()}},
- {"g_V_valuesXname_age_nullX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Values<object>("name", "age", null)}},
+ {"g_V_propertiesXname_age_nullX_value", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Properties<object>("name", "age", (string) null).Value<object>()}},
+ {"g_V_valuesXname_age_nullX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Values<object>("name", "age", (string) null)}},
{"g_injectX__feature___test__nullX_rTrim", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject<object>("feature ", "one test ", null, "", " ", " abc", "abc ", " abc ", "  ").RTrim()}},
{"g_injectX__feature___test__nullX_rTrimXlocalX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject<object>(new List<object> { " feature ", " one test ", null, "", " ", " abc", "abc ", " abc ", "  " }).RTrim<object>(Scope.Local)}},
{"g_injectX__feature__X_rTrim", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject<object>(" feature ").RTrim()}},
@@ -1356,7 +1361,7 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
{"g_V_hasLabelXpersonX_filterXoutEXcreatedXX_valueMapXtrueX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().HasLabel("person").Filter(__.OutE("created")).ValueMap<object, object>(true)}},
{"g_V_hasLabelXpersonX_filterXoutEXcreatedXX_valueMap_withXtokensX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().HasLabel("person").Filter(__.OutE("created")).ValueMap<object, object>().With(WithOptions.Tokens)}},
{"g_VX1X_valueMapXname_locationX_byXunfoldX_by", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V(p["vid1"]).ValueMap<object, object>("name", "location").By(__.Unfold<object>()).By()}},
- {"g_V_valueMapXname_age_nullX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().ValueMap<object, object>("name", "age", null)}},
+ {"g_V_valueMapXname_age_nullX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().ValueMap<object, object>("name", "age", (string) null)}},
{"g_V_valueMapXname_ageX_byXisXxXXbyXunfoldX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().ValueMap<object, object>("name", "age").By(__.Is("x")).By(__.Unfold<object>())}},
{"g_VXnullX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V(null)}},
{"g_VXlistXnullXX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V(p["xx1"])}},
diff --git a/gremlin-go/driver/cucumber/cucumberSteps_test.go b/gremlin-go/driver/cucumber/cucumberSteps_test.go
index fd49c7d8b4..38fbdb6207 100644
--- a/gremlin-go/driver/cucumber/cucumberSteps_test.go
+++ b/gremlin-go/driver/cucumber/cucumberSteps_test.go
@@ -47,7 +47,7 @@ var parsers map[*regexp.Regexp]func(string, string) interface{}
func init() {
parsers = map[*regexp.Regexp]func(string, string) interface{}{
- regexp.MustCompile(`^str\[(.*)]$`): func(stringVal, graphName string) interface{} { return stringVal }, //returns the string value as is
+ regexp.MustCompile(`^str\[(.*)]$`): func(stringVal, graphName string) interface{} { return stringVal }, //returns the string value as is
regexp.MustCompile(`^dt\[(.*)]$`): toDateTime,
regexp.MustCompile(`^d\[(.*)]\.[bslfdmn]$`): toNumeric,
regexp.MustCompile(`^d\[(.*)]\.[i]$`): toInt32,
@@ -821,18 +821,6 @@ func (tg *tinkerPopGraph) usingTheParameterDefined(name string, params string) e
return nil
}
-func (tg *tinkerPopGraph) usingTheParameterOfP(paramName, pVal, stringVal string) error {
- predicate := reflect.ValueOf(gremlingo.P).MethodByName(strings.Title(pVal)).Interface().(func(...interface{}) gremlingo.Predicate)
- values := parseValue(stringVal, tg.graphName)
- switch reflect.TypeOf(values).Kind() {
- case reflect.Array, reflect.Slice:
- tg.parameters[paramName] = predicate(values.([]interface{})...)
- default:
- tg.parameters[paramName] = predicate(values)
- }
- return nil
-}
-
func (tg *tinkerPopGraph) theTraversalWillRaiseAnError() error {
if _, ok := tg.error[true]; ok {
return nil
@@ -912,7 +900,6 @@ func InitializeScenario(ctx *godog.ScenarioContext) {
ctx.Step(`^the result should have a count of (\d+)$`, tg.theResultShouldHaveACountOf)
ctx.Step(`^the traversal of$`, tg.theTraversalOf)
ctx.Step(`^using the parameter (.+) defined as "(.+)"$`, tg.usingTheParameterDefined)
- ctx.Step(`^using the parameter (.+) of P\.(.+)\("(.+)"\)$`, tg.usingTheParameterOfP)
ctx.Step(`^the traversal will raise an error$`, tg.theTraversalWillRaiseAnError)
ctx.Step(`^the traversal will raise an error with message (\w+) text of "(.+)"$`, tg.theTraversalWillRaiseAnErrorWithMessageContainingTextOf)
}
diff --git a/gremlin-go/driver/cucumber/gremlin.go b/gremlin-go/driver/cucumber/gremlin.go
index 591bdd0c7c..667ae6d1f3 100644
--- a/gremlin-go/driver/cucumber/gremlin.go
+++ b/gremlin-go/driver/cucumber/gremlin.go
@@ -204,6 +204,8 @@ var translationMap = map[string][]func(g *gremlingo.GraphTraversalSource, p map[
"g_VX1X_out_hasXid_2X": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V(p["v2"]).Has("age", gremlingo.P.Gt(30))}},
"g_V_hasXblahX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Has("blah")}},
"g_V_hasXperson_name_markoX_age": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Has("person", "name", "marko").Values("age")}},
+ "g_V_hasXperson_name_markovarX_age": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Has("person", "name", p["xx1"]).Values("age")}},
+ "g_V_hasXpersonvar_name_markoX_age": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Has(p["xx1"], "name", "marko").Values("age")}},
"g_VX1X_outE_hasXweight_inside_0_06X_inV": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V(p["vid1"]).OutE().Has("weight", gremlingo.P.Inside(0.0, 0.6)).InV()}},
"g_EX11X_outV_outE_hasXid_10X": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.E(p["eid11"]).OutV().OutE().Has(gremlingo.T.Id, p["eid10"])}},
"g_EX11X_outV_outE_hasXid_10AsStringX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.E(p["eid11"]).OutV().OutE().Has(gremlingo.T.Id, p["eid10"])}},
@@ -239,9 +241,9 @@ var translationMap = map[string][]func(g *gremlingo.GraphTraversalSource, p map[
"g_V_hasXlabel_isXpersonXX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Has(gremlingo.T.Label, gremlingo.T__.Is("person"))}},
"g_V_hasXname_nullX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Has("name", nil)}},
"g_V_hasIdXemptyX_count": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().HasId(p["xx1"]).Count()}},
- "g_V_hasIdXwithinXemptyXX_count": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().HasId(p["xx1"]).Count()}},
- "g_V_hasIdXwithoutXemptyXX_count": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().HasId(p["xx1"]).Count()}},
- "g_V_notXhasIdXwithinXemptyXXX_count": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Not(gremlingo.T__.HasId(p["xx1"])).Count()}},
+ "g_V_hasIdXwithinXemptyXX_count": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().HasId(gremlingo.P.Within([]interface{}{})).Count()}},
+ "g_V_hasIdXwithoutXemptyXX_count": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().HasId(gremlingo.P.Without([]interface{}{})).Count()}},
+ "g_V_notXhasIdXwithinXemptyXXX_count": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Not(gremlingo.T__.HasId(gremlingo.P.Within([]interface{}{}))).Count()}},
"g_V_hasIdXnullX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().HasId(nil)}},
"g_V_hasIdXeqXnullXX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().HasId(gremlingo.P.Eq(nil))}},
"g_V_hasIdX2_nullX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().HasId(p["vid2"], nil)}},
@@ -249,7 +251,7 @@ var translationMap = map[string][]func(g *gremlingo.GraphTraversalSource, p map[
"g_V_hasIdX1AsString_2AsString_nullX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().HasId(p["vid1"], p["vid2"], nil)}},
"g_V_hasIdXnull_2X": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().HasId(nil, p["vid2"])}},
"g_V_hasIdX1X_hasIdX2X": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().HasId(p["vid1"]).HasId(p["vid2"])}},
- "g_V_in_hasIdXneqX1XX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().In().HasId(p["xx1"])}},
+ "g_V_in_hasIdXneqX1XX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().In().HasId(gremlingo.P.Neq(p["xx1"]))}},
"g_VX1X_out_hasIdX2X": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V(p["vid1"]).Out().HasId(p["vid2"])}},
"g_VX1X_out_hasXid_2_3X": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V(p["vid1"]).Out().HasId(p["vid2"], p["vid3"])}},
"g_VX1X_out_hasXid_2AsString_3AsStringX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V(p["vid1"]).Out().HasId(p["vid2"], p["vid3"])}},
@@ -272,6 +274,8 @@ var translationMap = map[string][]func(g *gremlingo.GraphTraversalSource, p map[
"g_E_hasLabelXuses_traversesX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.E().HasLabel("uses", "traverses")}},
"g_V_hasLabelXperson_software_blahX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().HasLabel("person", "software", "blah")}},
"g_V_hasLabelXpersonX_hasLabelXsoftwareX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().HasLabel("person").HasLabel("software")}},
+ "g_V_hasLabelXpersonvarX_hasLabelXsoftwareX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().HasLabel(p["xx1"]).HasLabel("software")}},
+ "g_V_hasLabelXpersonvar_softwarevarX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().HasLabel(p["xx1"], p["xx2"])}},
"g_V_hasLabelXpersonX_hasXage_notXlteX10X_andXnotXbetweenX11_20XXXX_andXltX29X_orXeqX35XXXX_name": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().HasLabel("person").Has("age", gremlingo.P.Not(gremlingo.P.Lte(10).And(gremlingo.P.Not(gremlingo.P.Between(11, 20)))).And(gremlingo.P.Lt(29).Or(gremlingo.P.Eq(35)))).Values("name")}},
"g_V_hasLabelXnullX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().HasLabel(nil)}},
"g_V_hasXlabel_nullX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Has(gremlingo.T.Label, nil)}},
@@ -677,7 +681,8 @@ var translationMap = map[string][]func(g *gremlingo.GraphTraversalSource, p map[
"g_V_valuesXnameX_conjoinX1X": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Values("name").Conjoin("1")}},
"g_V_valuesXnonexistantX_fold_conjoinX_X": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Values("nonexistant").Fold().Conjoin(";")}},
"g_V_valuesXnameX_order_fold_conjoinX_X": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Values("name").Order().Fold().Conjoin("_")}},
- "g_V_valuesXageX_order_fold_conjoinX_X": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Values("age").Order().Fold().Conjoin(";")}},
+ "g_V_valuesXageX_order_fold_conjoinXsemicolonX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Values("age").Order().Fold().Conjoin(";")}},
+ "g_V_valuesXageX_order_fold_conjoinXslashX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Values("age").Order().Fold().Conjoin(p["xx1"])}},
"g_V_out_path_byXvaluesXnameX_toUpperX_conjoinXMARKOX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Out().Path().By(gremlingo.T__.Values("name").ToUpper()).Conjoin("MARKO")}},
"g_injectXmarkoX_conjoinX_X": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.Inject(p["xx1"]).Conjoin("-")}},
"g_V_valueMapXlocationX_selectXvaluesX_unfold_orderXlocalX_conjoinX1X": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().ValueMap("location").Select(gremlingo.Column.Values).Unfold().Order(gremlingo.Scope.Local).Conjoin("1")}},
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 e590415406..bad8161e70 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
@@ -117,10 +117,6 @@ Given('the traversal of', function (traversalText) {
this.traversal = gremlin[this.scenario].shift()(p);
});
-Given(/^using the parameter (.+) of P\.(.+)\("(.+)"\)$/, function (paramName, pval, stringValue) {
- this.parameters[paramName] = new P(pval, parseValue.call(this, stringValue))
-});
-
Given(/^using the parameter (.+) defined as "(.+)"$/, function (paramName, stringValue) {
// Remove escaped chars
stringValue = stringValue.replace(/\\"/g, '"');
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/gremlin.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/gremlin.js
index 5251007c64..89e85ac91d 100644
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/gremlin.js
+++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/gremlin.js
@@ -225,6 +225,8 @@ const gremlins = {
g_VX1X_out_hasXid_2X: [function({g, v2}) { return g.V(v2).has("age", P.gt(30)) }],
g_V_hasXblahX: [function({g}) { return g.V().has("blah") }],
g_V_hasXperson_name_markoX_age: [function({g}) { return g.V().has("person", "name", "marko").values("age") }],
+ g_V_hasXperson_name_markovarX_age: [function({g, xx1}) { return g.V().has("person", "name", xx1).values("age") }],
+ g_V_hasXpersonvar_name_markoX_age: [function({g, xx1}) { return g.V().has(xx1, "name", "marko").values("age") }],
g_VX1X_outE_hasXweight_inside_0_06X_inV: [function({g, vid1}) { return g.V(vid1).outE().has("weight", P.inside(0.0, 0.6)).inV() }],
g_EX11X_outV_outE_hasXid_10X: [function({g, eid11, eid10}) { return g.E(eid11).outV().outE().has(T.id, eid10) }],
g_EX11X_outV_outE_hasXid_10AsStringX: [function({g, eid11, eid10}) { return g.E(eid11).outV().outE().has(T.id, eid10) }],
@@ -260,9 +262,9 @@ const gremlins = {
g_V_hasXlabel_isXpersonXX: [function({g}) { return g.V().has(T.label, __.is("person")) }],
g_V_hasXname_nullX: [function({g}) { return g.V().has("name", null) }],
g_V_hasIdXemptyX_count: [function({g, xx1}) { return g.V().hasId(xx1).count() }],
- g_V_hasIdXwithinXemptyXX_count: [function({g, xx1}) { return g.V().hasId(xx1).count() }],
- g_V_hasIdXwithoutXemptyXX_count: [function({g, xx1}) { return g.V().hasId(xx1).count() }],
- g_V_notXhasIdXwithinXemptyXXX_count: [function({g, xx1}) { return g.V().not(__.hasId(xx1)).count() }],
+ g_V_hasIdXwithinXemptyXX_count: [function({g}) { return g.V().hasId(P.within([])).count() }],
+ g_V_hasIdXwithoutXemptyXX_count: [function({g}) { return g.V().hasId(P.without([])).count() }],
+ g_V_notXhasIdXwithinXemptyXXX_count: [function({g}) { return g.V().not(__.hasId(P.within([]))).count() }],
g_V_hasIdXnullX: [function({g}) { return g.V().hasId(null) }],
g_V_hasIdXeqXnullXX: [function({g}) { return g.V().hasId(P.eq(null)) }],
g_V_hasIdX2_nullX: [function({g, vid2}) { return g.V().hasId(vid2, null) }],
@@ -270,7 +272,7 @@ const gremlins = {
g_V_hasIdX1AsString_2AsString_nullX: [function({g, vid2, vid1}) { return g.V().hasId(vid1, vid2, null) }],
g_V_hasIdXnull_2X: [function({g, vid2}) { return g.V().hasId(null, vid2) }],
g_V_hasIdX1X_hasIdX2X: [function({g, vid2, vid1}) { return g.V().hasId(vid1).hasId(vid2) }],
- g_V_in_hasIdXneqX1XX: [function({g, xx1}) { return g.V().in_().hasId(xx1) }],
+ g_V_in_hasIdXneqX1XX: [function({g, xx1}) { return g.V().in_().hasId(P.neq(xx1)) }],
g_VX1X_out_hasIdX2X: [function({g, vid2, vid1}) { return g.V(vid1).out().hasId(vid2) }],
g_VX1X_out_hasXid_2_3X: [function({g, vid3, vid2, vid1}) { return g.V(vid1).out().hasId(vid2, vid3) }],
g_VX1X_out_hasXid_2AsString_3AsStringX: [function({g, vid3, vid2, vid1}) { return g.V(vid1).out().hasId(vid2, vid3) }],
@@ -293,6 +295,8 @@ const gremlins = {
g_E_hasLabelXuses_traversesX: [function({g}) { return g.E().hasLabel("uses", "traverses") }],
g_V_hasLabelXperson_software_blahX: [function({g}) { return g.V().hasLabel("person", "software", "blah") }],
g_V_hasLabelXpersonX_hasLabelXsoftwareX: [function({g}) { return g.V().hasLabel("person").hasLabel("software") }],
+ g_V_hasLabelXpersonvarX_hasLabelXsoftwareX: [function({g, xx1}) { return g.V().hasLabel(xx1).hasLabel("software") }],
+ g_V_hasLabelXpersonvar_softwarevarX: [function({g, xx1, xx2}) { return g.V().hasLabel(xx1, xx2) }],
g_V_hasLabelXpersonX_hasXage_notXlteX10X_andXnotXbetweenX11_20XXXX_andXltX29X_orXeqX35XXXX_name: [function({g}) { return g.V().hasLabel("person").has("age", P.not(P.lte(10).and(P.not(P.between(11, 20)))).and(P.lt(29).or(P.eq(35)))).values("name") }],
g_V_hasLabelXnullX: [function({g}) { return g.V().hasLabel(null) }],
g_V_hasXlabel_nullX: [function({g}) { return g.V().has(T.label, null) }],
@@ -694,7 +698,8 @@ const gremlins = {
g_V_valuesXnameX_conjoinX1X: [function({g}) { return g.V().values("name").conjoin("1") }],
g_V_valuesXnonexistantX_fold_conjoinX_X: [function({g}) { return g.V().values("nonexistant").fold().conjoin(";") }],
g_V_valuesXnameX_order_fold_conjoinX_X: [function({g}) { return g.V().values("name").order().fold().conjoin("_") }],
- g_V_valuesXageX_order_fold_conjoinX_X: [function({g}) { return g.V().values("age").order().fold().conjoin(";") }],
+ g_V_valuesXageX_order_fold_conjoinXsemicolonX: [function({g}) { return g.V().values("age").order().fold().conjoin(";") }],
+ g_V_valuesXageX_order_fold_conjoinXslashX: [function({g, xx1}) { return g.V().values("age").order().fold().conjoin(xx1) }],
g_V_out_path_byXvaluesXnameX_toUpperX_conjoinXMARKOX: [function({g}) { return g.V().out().path().by(__.values("name").toUpper()).conjoin("MARKO") }],
g_injectXmarkoX_conjoinX_X: [function({g, xx1}) { return g.inject(xx1).conjoin("-") }],
g_V_valueMapXlocationX_selectXvaluesX_unfold_orderXlocalX_conjoinX1X: [function({g}) { return g.V().valueMap("location").select(Column.values).unfold().order(Scope.local).conjoin("1") }],
@@ -768,12 +773,32 @@ const gremlins = {
g_injectXa_null_bX_disjunctXa_cX: [function({g, xx1, xx2}) { return g.inject(xx1).disjunct(xx2) }],
g_injectXa_null_bX_disjunctXa_null_cX: [function({g, xx1, xx2}) { return g.inject(xx1).disjunct(xx2) }],
g_injectX3_threeX_disjunctXfive_three_7X: [function({g, xx1, xx2}) { return g.inject(xx1).disjunct(xx2) }],
+ g_E: [function({g}) { return g.E() }],
+ g_EX11X: [function({g, eid11}) { return g.E(eid11) }],
+ g_EX11AsStringX: [function({g, eid11}) { return g.E(eid11) }],
+ g_EXe11X: [function({g, e11}) { return g.E(e11) }],
+ g_EXe7_e11X: [function({g, e7, e11}) { return g.E(e7, e11) }],
+ g_EXlistXe7_e11XX: [function({g, xx1}) { return g.E(xx1) }],
+ g_EXnullX: [function({g}) { return g.E(null) }],
+ g_EXlistXnullXX: [function({g, xx1}) { return g.E(xx1) }],
+ g_EX11_nullX: [function({g, eid11}) { return g.E(eid11, null) }],
g_V_EX11X: [function({g, eid11}) { return g.V().E(eid11) }],
g_EX11X_E: [function({g, eid11}) { return g.E(eid11).E() }],
g_V_EXnullX: [function({g}) { return g.V().E(null) }],
g_V_EXlistXnullXX: [function({g, xx1}) { return g.V().E(xx1) }],
g_injectX1X_EX11_nullX: [function({g, eid11}) { return g.inject(1).E(eid11, null) }],
g_injectX1X_coalesceXEX_hasLabelXtestsX_addEXtestsX_from_V_hasXnameX_XjoshXX_toXV_hasXnameX_XvadasXXX: [function({g}) { return g.addV("person").property("name", "josh").addV("person").property("name", "vadas") }, function({g}) { return g.inject(1).coalesce(__.E().hasLabel("tests"), __.addE("tests").from_(__.V().has("name", "josh")).to(__.V().has("name", "vadas"))) }, function({g}) { return g.E().hasLabel("tests") }],
+ g_VX1X_outE_inV: [function({g, vid1}) { return g.V(vid1).outE().inV() }],
+ g_VX2X_inE_outV: [function({g, vid2}) { return g.V(vid2).inE().outV() }],
+ g_V_outE_hasXweight_1X_outV: [function({g}) { return g.V().outE().has("weight", 1.0).outV() }],
+ g_VX1X_outE_otherV: [function({g, vid1}) { return g.V(vid1).outE().otherV() }],
+ g_VX4X_bothE_otherV: [function({g, vid4}) { return g.V(vid4).bothE().otherV() }],
+ g_VX4X_bothE_hasXweight_lt_1X_otherV: [function({g, vid4}) { return g.V(vid4).bothE().has("weight", P.lt(1.0)).otherV() }],
+ get_g_VX1X_outE_otherV: [function({g, vid1}) { return g.V(vid1).outE().otherV() }],
+ g_VX1X_outEXknowsX_inV: [function({g, vid1}) { return g.V(vid1).outE("knows").inV() }],
+ g_VX1X_outEXknows_createdX_inV: [function({g, vid1}) { return g.V(vid1).outE("knows", "created").inV() }],
+ g_VX1X_outEXknowsX_bothV: [function({g, vid1}) { return g.V(vid1).outE("knows").bothV() }],
+ g_VX1X_outEXknowsX_bothV_name: [function({g, vid1}) { return g.V(vid1).outE("knows").bothV().values("name") }],
g_VX1X_properties_element: [function({g, v2}) { return g.V(v2).properties().element().limit(1) }],
g_V_properties_element: [function({g}) { return g.V().properties().element() }],
g_V_propertiesXageX_element: [function({g}) { return g.V().properties("age").element() }],
@@ -1365,34 +1390,15 @@ const gremlins = {
g_VX1X_out: [function({g, vid1}) { return g.V(vid1).out() }],
g_VX2X_in: [function({g, vid2}) { return g.V(vid2).in_() }],
g_VX4X_both: [function({g, vid4}) { return g.V(vid4).both() }],
- g_E: [function({g}) { return g.E() }],
- g_EX11X: [function({g, eid11}) { return g.E(eid11) }],
- g_EX11AsStringX: [function({g, eid11}) { return g.E(eid11) }],
- g_EXe11X: [function({g, e11}) { return g.E(e11) }],
- g_EXe7_e11X: [function({g, e7, e11}) { return g.E(e7, e11) }],
- g_EXlistXe7_e11XX: [function({g, xx1}) { return g.E(xx1) }],
- g_EXnullX: [function({g}) { return g.E(null) }],
- g_EXlistXnullXX: [function({g, xx1}) { return g.E(xx1) }],
- g_EX11_nullX: [function({g, eid11}) { return g.E(eid11, null) }],
g_VX1X_outE: [function({g, vid1}) { return g.V(vid1).outE() }],
g_VX2X_outE: [function({g, vid2}) { return g.V(vid2).inE() }],
g_VX4X_bothEXcreatedX: [function({g, vid4}) { return g.V(vid4).bothE("created") }],
g_VX4X_bothE: [function({g, vid4}) { return g.V(vid4).bothE() }],
- g_VX1X_outE_inV: [function({g, vid1}) { return g.V(vid1).both() }],
- g_VX2X_inE_outV: [function({g, vid2}) { return g.V(vid2).inE().outV() }],
- g_V_outE_hasXweight_1X_outV: [function({g}) { return g.V().outE().has("weight", 1.0).outV() }],
g_V_out_outE_inV_inE_inV_both_name: [function({g}) { return g.V().out().outE().inV().inE().inV().both().values("name") }],
- g_VX1X_outEXknowsX_bothV_name: [function({g, vid1}) { return g.V(vid1).outE("knows").bothV().values("name") }],
- g_VX1X_outE_otherV: [function({g, vid1}) { return g.V(vid1).outE().otherV() }],
- g_VX4X_bothE_otherV: [function({g, vid4}) { return g.V(vid4).bothE().otherV() }],
- g_VX4X_bothE_hasXweight_lt_1X_otherV: [function({g, vid4}) { return g.V(vid4).bothE().has("weight", P.lt(1.0)).otherV() }],
g_VX2X_inE: [function({g, vid2}) { return g.V(vid2).bothE() }],
- get_g_VX1X_outE_otherV: [function({g, vid1}) { return g.V(vid1).outE().otherV() }],
g_VX1X_outXknowsX: [function({g, vid1}) { return g.V(vid1).out("knows") }],
g_VX1AsStringX_outXknowsX: [function({g, vid1}) { return g.V(vid1).out("knows") }],
g_VX1X_outXknows_createdX: [function({g, vid1}) { return g.V(vid1).out("knows", "created") }],
- g_VX1X_outEXknowsX_inV: [function({g, vid1}) { return g.V(vid1).outE("knows").inV() }],
- g_VX1X_outEXknows_createdX_inV: [function({g, vid1}) { return g.V(vid1).outE("knows", "created").inV() }],
g_V_out_out: [function({g}) { return g.V().out().out() }],
g_VX1X_out_out_out: [function({g, vid1}) { return g.V(vid1).out().out().out() }],
g_VX1X_out_name: [function({g, vid1}) { return g.V(vid1).out().values("name") }],
diff --git a/gremlin-language/src/main/antlr4/Gremlin.g4 b/gremlin-language/src/main/antlr4/Gremlin.g4
index cda26269ac..6394c55568 100644
--- a/gremlin-language/src/main/antlr4/Gremlin.g4
+++ b/gremlin-language/src/main/antlr4/Gremlin.g4
@@ -487,7 +487,7 @@ traversalMethod_fold
;
traversalMethod_from
- : 'from' LPAREN stringArgument RPAREN #traversalMethod_from_String
+ : 'from' LPAREN stringLiteral RPAREN #traversalMethod_from_String
| 'from' LPAREN structureVertexArgument RPAREN #traversalMethod_from_Vertex
| 'from' LPAREN nestedTraversal RPAREN #traversalMethod_from_Traversal
;
@@ -809,7 +809,7 @@ traversalMethod_times
traversalMethod_to
: 'to' LPAREN traversalDirection (COMMA stringLiteralVarargs)? RPAREN #traversalMethod_to_Direction_String
- | 'to' LPAREN stringArgument RPAREN #traversalMethod_to_String
+ | 'to' LPAREN stringLiteral RPAREN #traversalMethod_to_String
| 'to' LPAREN structureVertexArgument RPAREN #traversalMethod_to_Vertex
| 'to' LPAREN nestedTraversal RPAREN #traversalMethod_to_Traversal
;
diff --git a/gremlin-python/src/main/python/radish/feature_steps.py b/gremlin-python/src/main/python/radish/feature_steps.py
index 6d3f03b935..ccb600f2ef 100644
--- a/gremlin-python/src/main/python/radish/feature_steps.py
+++ b/gremlin-python/src/main/python/radish/feature_steps.py
@@ -109,17 +109,6 @@ def unsupported_scenario(step):
return
-@given("using the parameter {param_name:w} of P.{p_val:w}({param:QuotedString})")
-def add_p_parameter(step, param_name, p_val, param):
- if (step.context.ignore):
- return
-
- if not hasattr(step.context, "traversal_params"):
- step.context.traversal_params = {}
-
- step.context.traversal_params[param_name] = getattr(P, p_val)(_convert(param.replace('\\"', '"'), step.context))
-
-
@given("using the parameter {param_name:w} defined as {param:QuotedString}")
def add_parameter(step, param_name, param):
if (step.context.ignore):
diff --git a/gremlin-python/src/main/python/radish/gremlin.py b/gremlin-python/src/main/python/radish/gremlin.py
index bba1156256..d082e9e3a3 100644
--- a/gremlin-python/src/main/python/radish/gremlin.py
+++ b/gremlin-python/src/main/python/radish/gremlin.py
@@ -207,6 +207,8 @@ world.gremlins = {
'g_VX1X_out_hasXid_2X': [(lambda g, v2=None:g.V(v2).has('age', P.gt(30)))],
'g_V_hasXblahX': [(lambda g:g.V().has('blah'))],
'g_V_hasXperson_name_markoX_age': [(lambda g:g.V().has('person', 'name', 'marko').values('age'))],
+ 'g_V_hasXperson_name_markovarX_age': [(lambda g, xx1=None:g.V().has('person', 'name', xx1).values('age'))],
+ 'g_V_hasXpersonvar_name_markoX_age': [(lambda g, xx1=None:g.V().has(xx1, 'name', 'marko').values('age'))],
'g_VX1X_outE_hasXweight_inside_0_06X_inV': [(lambda g, vid1=None:g.V(vid1).out_e().has('weight', P.inside(0.0, 0.6)).in_v())],
'g_EX11X_outV_outE_hasXid_10X': [(lambda g, eid11=None,eid10=None:g.E(eid11).out_v().out_e().has(T.id_, eid10))],
'g_EX11X_outV_outE_hasXid_10AsStringX': [(lambda g, eid11=None,eid10=None:g.E(eid11).out_v().out_e().has(T.id_, eid10))],
@@ -242,9 +244,9 @@ world.gremlins = {
'g_V_hasXlabel_isXpersonXX': [(lambda g:g.V().has(T.label, __.is_('person')))],
'g_V_hasXname_nullX': [(lambda g:g.V().has('name', None))],
'g_V_hasIdXemptyX_count': [(lambda g, xx1=None:g.V().has_id(xx1).count())],
- 'g_V_hasIdXwithinXemptyXX_count': [(lambda g, xx1=None:g.V().has_id(xx1).count())],
- 'g_V_hasIdXwithoutXemptyXX_count': [(lambda g, xx1=None:g.V().has_id(xx1).count())],
- 'g_V_notXhasIdXwithinXemptyXXX_count': [(lambda g, xx1=None:g.V().not_(__.has_id(xx1)).count())],
+ 'g_V_hasIdXwithinXemptyXX_count': [(lambda g:g.V().has_id(P.within([])).count())],
+ 'g_V_hasIdXwithoutXemptyXX_count': [(lambda g:g.V().has_id(P.without([])).count())],
+ 'g_V_notXhasIdXwithinXemptyXXX_count': [(lambda g:g.V().not_(__.has_id(P.within([]))).count())],
'g_V_hasIdXnullX': [(lambda g:g.V().has_id(None))],
'g_V_hasIdXeqXnullXX': [(lambda g:g.V().has_id(P.eq(None)))],
'g_V_hasIdX2_nullX': [(lambda g, vid2=None:g.V().has_id(vid2, None))],
@@ -252,7 +254,7 @@ world.gremlins = {
'g_V_hasIdX1AsString_2AsString_nullX': [(lambda g, vid2=None,vid1=None:g.V().has_id(vid1, vid2, None))],
'g_V_hasIdXnull_2X': [(lambda g, vid2=None:g.V().has_id(None, vid2))],
'g_V_hasIdX1X_hasIdX2X': [(lambda g, vid2=None,vid1=None:g.V().has_id(vid1).has_id(vid2))],
- 'g_V_in_hasIdXneqX1XX': [(lambda g, xx1=None:g.V().in_().has_id(xx1))],
+ 'g_V_in_hasIdXneqX1XX': [(lambda g, xx1=None:g.V().in_().has_id(P.neq(xx1)))],
'g_VX1X_out_hasIdX2X': [(lambda g, vid2=None,vid1=None:g.V(vid1).out().has_id(vid2))],
'g_VX1X_out_hasXid_2_3X': [(lambda g, vid3=None,vid2=None,vid1=None:g.V(vid1).out().has_id(vid2, vid3))],
'g_VX1X_out_hasXid_2AsString_3AsStringX': [(lambda g, vid3=None,vid2=None,vid1=None:g.V(vid1).out().has_id(vid2, vid3))],
@@ -275,6 +277,8 @@ world.gremlins = {
'g_E_hasLabelXuses_traversesX': [(lambda g:g.E().has_label('uses', 'traverses'))],
'g_V_hasLabelXperson_software_blahX': [(lambda g:g.V().has_label('person', 'software', 'blah'))],
'g_V_hasLabelXpersonX_hasLabelXsoftwareX': [(lambda g:g.V().has_label('person').has_label('software'))],
+ 'g_V_hasLabelXpersonvarX_hasLabelXsoftwareX': [(lambda g, xx1=None:g.V().has_label(xx1).has_label('software'))],
+ 'g_V_hasLabelXpersonvar_softwarevarX': [(lambda g, xx1=None,xx2=None:g.V().has_label(xx1, xx2))],
'g_V_hasLabelXpersonX_hasXage_notXlteX10X_andXnotXbetweenX11_20XXXX_andXltX29X_orXeqX35XXXX_name': [(lambda g:g.V().has_label('person').has('age', P.not_(P.lte(10).and_(P.not_(P.between(11, 20)))).and_(P.lt(29).or_(P.eq(35)))).values('name'))],
'g_V_hasLabelXnullX': [(lambda g:g.V().has_label(None))],
'g_V_hasXlabel_nullX': [(lambda g:g.V().has(T.label, None))],
@@ -676,7 +680,8 @@ world.gremlins = {
'g_V_valuesXnameX_conjoinX1X': [(lambda g:g.V().values('name').conjoin('1'))],
'g_V_valuesXnonexistantX_fold_conjoinX_X': [(lambda g:g.V().values('nonexistant').fold().conjoin(';'))],
'g_V_valuesXnameX_order_fold_conjoinX_X': [(lambda g:g.V().values('name').order().fold().conjoin('_'))],
- 'g_V_valuesXageX_order_fold_conjoinX_X': [(lambda g:g.V().values('age').order().fold().conjoin(';'))],
+ 'g_V_valuesXageX_order_fold_conjoinXsemicolonX': [(lambda g:g.V().values('age').order().fold().conjoin(';'))],
+ 'g_V_valuesXageX_order_fold_conjoinXslashX': [(lambda g, xx1=None:g.V().values('age').order().fold().conjoin(xx1))],
'g_V_out_path_byXvaluesXnameX_toUpperX_conjoinXMARKOX': [(lambda g:g.V().out().path().by(__.values('name').to_upper()).conjoin('MARKO'))],
'g_injectXmarkoX_conjoinX_X': [(lambda g, xx1=None:g.inject(xx1).conjoin('-'))],
'g_V_valueMapXlocationX_selectXvaluesX_unfold_orderXlocalX_conjoinX1X': [(lambda g:g.V().value_map('location').select(Column.values).unfold().order(Scope.local).conjoin('1'))],
@@ -750,12 +755,32 @@ world.gremlins = {
'g_injectXa_null_bX_disjunctXa_cX': [(lambda g, xx1=None,xx2=None:g.inject(xx1).disjunct(xx2))],
'g_injectXa_null_bX_disjunctXa_null_cX': [(lambda g, xx1=None,xx2=None:g.inject(xx1).disjunct(xx2))],
'g_injectX3_threeX_disjunctXfive_three_7X': [(lambda g, xx1=None,xx2=None:g.inject(xx1).disjunct(xx2))],
+ 'g_E': [(lambda g:g.E())],
+ 'g_EX11X': [(lambda g, eid11=None:g.E(eid11))],
+ 'g_EX11AsStringX': [(lambda g, eid11=None:g.E(eid11))],
+ 'g_EXe11X': [(lambda g, e11=None:g.E(e11))],
+ 'g_EXe7_e11X': [(lambda g, e7=None,e11=None:g.E(e7, e11))],
+ 'g_EXlistXe7_e11XX': [(lambda g, xx1=None:g.E(xx1))],
+ 'g_EXnullX': [(lambda g:g.E(None))],
+ 'g_EXlistXnullXX': [(lambda g, xx1=None:g.E(xx1))],
+ 'g_EX11_nullX': [(lambda g, eid11=None:g.E(eid11, None))],
'g_V_EX11X': [(lambda g, eid11=None:g.V().E(eid11))],
'g_EX11X_E': [(lambda g, eid11=None:g.E(eid11).E())],
'g_V_EXnullX': [(lambda g:g.V().E(None))],
'g_V_EXlistXnullXX': [(lambda g, xx1=None:g.V().E(xx1))],
'g_injectX1X_EX11_nullX': [(lambda g, eid11=None:g.inject(1).E(eid11, None))],
'g_injectX1X_coalesceXEX_hasLabelXtestsX_addEXtestsX_from_V_hasXnameX_XjoshXX_toXV_hasXnameX_XvadasXXX': [(lambda g:g.add_v('person').property('name', 'josh').add_v('person').property('name', 'vadas')), (lambda g:g.inject(1).coalesce(__.E().has_label('tests'), __.add_e('tests').from_(__.V().has('name', 'josh')).to(__.V().has('name', 'vadas')))), (lambda g:g.E().has_label('tests'))],
+ 'g_VX1X_outE_inV': [(lambda g, vid1=None:g.V(vid1).out_e().in_v())],
+ 'g_VX2X_inE_outV': [(lambda g, vid2=None:g.V(vid2).in_e().out_v())],
+ 'g_V_outE_hasXweight_1X_outV': [(lambda g:g.V().out_e().has('weight', 1.0).out_v())],
+ 'g_VX1X_outE_otherV': [(lambda g, vid1=None:g.V(vid1).out_e().other_v())],
+ 'g_VX4X_bothE_otherV': [(lambda g, vid4=None:g.V(vid4).both_e().other_v())],
+ 'g_VX4X_bothE_hasXweight_lt_1X_otherV': [(lambda g, vid4=None:g.V(vid4).both_e().has('weight', P.lt(1.0)).other_v())],
+ 'get_g_VX1X_outE_otherV': [(lambda g, vid1=None:g.V(vid1).out_e().other_v())],
+ 'g_VX1X_outEXknowsX_inV': [(lambda g, vid1=None:g.V(vid1).out_e('knows').in_v())],
+ 'g_VX1X_outEXknows_createdX_inV': [(lambda g, vid1=None:g.V(vid1).out_e('knows', 'created').in_v())],
+ 'g_VX1X_outEXknowsX_bothV': [(lambda g, vid1=None:g.V(vid1).out_e('knows').both_v())],
+ 'g_VX1X_outEXknowsX_bothV_name': [(lambda g, vid1=None:g.V(vid1).out_e('knows').both_v().values('name'))],
'g_VX1X_properties_element': [(lambda g, v2=None:g.V(v2).properties().element().limit(1))],
'g_V_properties_element': [(lambda g:g.V().properties().element())],
'g_V_propertiesXageX_element': [(lambda g:g.V().properties('age').element())],
@@ -1347,34 +1372,15 @@ world.gremlins = {
'g_VX1X_out': [(lambda g, vid1=None:g.V(vid1).out())],
'g_VX2X_in': [(lambda g, vid2=None:g.V(vid2).in_())],
'g_VX4X_both': [(lambda g, vid4=None:g.V(vid4).both())],
- 'g_E': [(lambda g:g.E())],
- 'g_EX11X': [(lambda g, eid11=None:g.E(eid11))],
- 'g_EX11AsStringX': [(lambda g, eid11=None:g.E(eid11))],
- 'g_EXe11X': [(lambda g, e11=None:g.E(e11))],
- 'g_EXe7_e11X': [(lambda g, e7=None,e11=None:g.E(e7, e11))],
- 'g_EXlistXe7_e11XX': [(lambda g, xx1=None:g.E(xx1))],
- 'g_EXnullX': [(lambda g:g.E(None))],
- 'g_EXlistXnullXX': [(lambda g, xx1=None:g.E(xx1))],
- 'g_EX11_nullX': [(lambda g, eid11=None:g.E(eid11, None))],
'g_VX1X_outE': [(lambda g, vid1=None:g.V(vid1).out_e())],
'g_VX2X_outE': [(lambda g, vid2=None:g.V(vid2).in_e())],
'g_VX4X_bothEXcreatedX': [(lambda g, vid4=None:g.V(vid4).both_e('created'))],
'g_VX4X_bothE': [(lambda g, vid4=None:g.V(vid4).both_e())],
- 'g_VX1X_outE_inV': [(lambda g, vid1=None:g.V(vid1).both())],
- 'g_VX2X_inE_outV': [(lambda g, vid2=None:g.V(vid2).in_e().out_v())],
- 'g_V_outE_hasXweight_1X_outV': [(lambda g:g.V().out_e().has('weight', 1.0).out_v())],
'g_V_out_outE_inV_inE_inV_both_name': [(lambda g:g.V().out().out_e().in_v().in_e().in_v().both().values('name'))],
- 'g_VX1X_outEXknowsX_bothV_name': [(lambda g, vid1=None:g.V(vid1).out_e('knows').both_v().values('name'))],
- 'g_VX1X_outE_otherV': [(lambda g, vid1=None:g.V(vid1).out_e().other_v())],
- 'g_VX4X_bothE_otherV': [(lambda g, vid4=None:g.V(vid4).both_e().other_v())],
- 'g_VX4X_bothE_hasXweight_lt_1X_otherV': [(lambda g, vid4=None:g.V(vid4).both_e().has('weight', P.lt(1.0)).other_v())],
'g_VX2X_inE': [(lambda g, vid2=None:g.V(vid2).both_e())],
- 'get_g_VX1X_outE_otherV': [(lambda g, vid1=None:g.V(vid1).out_e().other_v())],
'g_VX1X_outXknowsX': [(lambda g, vid1=None:g.V(vid1).out('knows'))],
'g_VX1AsStringX_outXknowsX': [(lambda g, vid1=None:g.V(vid1).out('knows'))],
'g_VX1X_outXknows_createdX': [(lambda g, vid1=None:g.V(vid1).out('knows', 'created'))],
- 'g_VX1X_outEXknowsX_inV': [(lambda g, vid1=None:g.V(vid1).out_e('knows').in_v())],
- 'g_VX1X_outEXknows_createdX_inV': [(lambda g, vid1=None:g.V(vid1).out_e('knows', 'created').in_v())],
'g_V_out_out': [(lambda g:g.V().out().out())],
'g_VX1X_out_out_out': [(lambda g, vid1=None:g.V(vid1).out().out().out())],
'g_VX1X_out_name': [(lambda g, vid1=None:g.V(vid1).out().values('name'))],
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/features/StepDefinition.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/features/StepDefinition.java
index 4bcb90f110..a282f69759 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/features/StepDefinition.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/features/StepDefinition.java
@@ -32,6 +32,7 @@ import org.antlr.v4.runtime.CommonTokenStream;
import org.apache.tinkerpop.gremlin.language.grammar.GremlinAntlrToJava;
import org.apache.tinkerpop.gremlin.language.grammar.GremlinLexer;
import org.apache.tinkerpop.gremlin.language.grammar.GremlinParser;
+import org.apache.tinkerpop.gremlin.language.grammar.VariableResolver;
import org.apache.tinkerpop.gremlin.language.translator.GremlinTranslator;
import org.apache.tinkerpop.gremlin.language.translator.Translator;
import org.apache.tinkerpop.gremlin.process.traversal.Merge;
@@ -62,6 +63,7 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
@@ -92,7 +94,7 @@ public final class StepDefinition {
private World world;
private GraphTraversalSource g;
- private final Map<String, String> stringParameters = new HashMap<>();
+ private final Map<String, Object> stringParameters = new HashMap<>();
private Traversal traversal;
private Object result;
private Throwable error;
@@ -182,13 +184,13 @@ public final class StepDefinition {
}
}));
- add(Pair.with(Pattern.compile("l\\[\\]"), s -> Collections.emptyList()));
+ add(Pair.with(Pattern.compile("l\\[\\]"), s -> new ArrayList<>()));
add(Pair.with(Pattern.compile("l\\[(.*)\\]"), s -> {
final String[] items = s.split(",");
return Stream.of(items).map(String::trim).map(x -> convertToObject(x)).collect(Collectors.toList());
}));
- add(Pair.with(Pattern.compile("s\\[\\]"), s -> Collections.emptySet()));
+ add(Pair.with(Pattern.compile("s\\[\\]"), s -> new HashSet<>()));
add(Pair.with(Pattern.compile("s\\[(.*)\\]"), s -> {
final String[] items = s.split(",");
return Stream.of(items).map(String::trim).map(x -> convertToObject(x)).collect(Collectors.toSet());
@@ -234,7 +236,7 @@ public final class StepDefinition {
add(Pair.with(Pattern.compile("e\\[(.+)\\]"), s -> getEdge(g, s)));
add(Pair.with(Pattern.compile("t\\[(.*)\\]"), T::valueOf));
- add(Pair.with(Pattern.compile("D\\[(.*)\\]"), Direction::valueOf));
+ add(Pair.with(Pattern.compile("D\\[(.*)\\]"), StepDefinition::getDirection));
add(Pair.with(Pattern.compile("M\\[(.*)\\]"), Merge::valueOf));
add(Pair.with(Pattern.compile("c\\[(.*)\\]"), s -> {
@@ -285,19 +287,26 @@ public final class StepDefinition {
@Given("using the parameter {word} defined as {string}")
public void usingTheParameterXDefinedAsX(final String key, final String value) {
- stringParameters.put(key, convertToString(value));
- }
-
- @Given("using the parameter {word} of P.{word}\\({string})")
- public void usingTheParameterXOfPX(final String key, final String pval, final String string) {
- stringParameters.put(key, String.format("P.%s(%s)", pval, convertToString(string)));
+ // when parameters are used literally, they are converted to string representations that can be recognized by
+ // the grammar and parsed inline. when they are used as variables, they are converted to objects that can be
+ // applied to the script as variables.
+ if (world.useParametersLiterally())
+ stringParameters.put(key, convertToString(value));
+ else
+ stringParameters.put(key, convertToObject(value));
}
@Given("the traversal of")
public void theTraversalOf(final String docString) {
try {
- final String gremlin = tryUpdateDataFilePath(docString);
- traversal = parseGremlin(applyParameters(gremlin));
+ final String rawGremlin = tryUpdateDataFilePath(docString);
+
+ // when parameters are used literally, they are converted to string representations that can be recognized by
+ // the grammar and parsed inline. when they are used as variables, they are converted to objects that can be
+ // applied to the script as variables.
+ final String gremlin = world.useParametersLiterally() ? applyParameters(rawGremlin) : rawGremlin;
+
+ traversal = parseGremlin(gremlin);
} catch (Exception ex) {
ex.printStackTrace();
error = ex;
@@ -375,10 +384,11 @@ public final class StepDefinition {
}
@Then("the graph should return {int} for count of {string}")
- public void theGraphShouldReturnForCountOf(final Integer count, final String gremlin) {
+ public void theGraphShouldReturnForCountOf(final Integer count, final String rawGremlin) {
assertThatNoErrorWasThrown();
- assertEquals(count.longValue(), ((GraphTraversal) parseGremlin(applyParameters(gremlin))).count().next());
+ final String gremlin = world.useParametersLiterally() ? applyParameters(rawGremlin) : rawGremlin;
+ assertEquals(count.longValue(), ((GraphTraversal) parseGremlin(gremlin)).count().next());
}
@Then("the result should be empty")
@@ -450,7 +460,14 @@ public final class StepDefinition {
final GremlinLexer lexer = new GremlinLexer(CharStreams.fromString(normalizedGremlin));
final GremlinParser parser = new GremlinParser(new CommonTokenStream(lexer));
final GremlinParser.QueryContext ctx = parser.query();
- return (Traversal) new GremlinAntlrToJava(g).visitQuery(ctx);
+
+ // when parameters are used literally, they are converted to string representations that can be recognized by
+ // the grammar and parsed inline. when they are used as variables, they are converted to objects that can be
+ // applied to the script as variables.
+ if (world.useParametersLiterally())
+ return (Traversal) new GremlinAntlrToJava(g).visitQuery(ctx);
+ else
+ return (Traversal) new GremlinAntlrToJava(g, new VariableResolver.DefaultVariableResolver(this.stringParameters)).visitQuery(ctx);
}
private List<Object> translateResultsToActual() {
@@ -574,7 +591,7 @@ public final class StepDefinition {
final List<String> paramNames = new ArrayList<>(stringParameters.keySet());
paramNames.sort((a,b) -> b.length() - a.length());
for (String k : paramNames) {
- replaced = replaced.replace(k, stringParameters.get(k));
+ replaced = replaced.replace(k, stringParameters.get(k).toString());
}
return replaced;
}
@@ -587,6 +604,12 @@ public final class StepDefinition {
return docString.replace(relPath, escapeJava(absPath));
}
+ private static Direction getDirection(final String direction) {
+ if (direction.equals("from")) return Direction.OUT;
+ if (direction.equals("to")) return Direction.IN;
+ return Direction.valueOf(direction);
+ }
+
/**
* TinkerPop version of Hamcrest's {code containsInAnyOrder} that can use our custom assertions for {@link Path}.
*/
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/features/World.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/features/World.java
index 52a977e614..726f72631a 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/features/World.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/features/World.java
@@ -82,6 +82,15 @@ public interface World {
return id.toString();
}
+ /**
+ * Determines if the test should use parameters literally or treat them as variables to be applied to the script.
+ * By default, they are treated literally.
+ */
+ public default boolean useParametersLiterally() {
+ return true;
+ }
+
+
/**
* Allows for some flexibility in error message assertion, where the provider can handle assertions themselves.
* Providers should use standard assertion logic as they would with tests. Note that if this method is called, then
diff --git a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/filter/Has.feature b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/filter/Has.feature
index c10757748d..8a1db09a05 100644
--- a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/filter/Has.feature
+++ b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/filter/Has.feature
@@ -206,6 +206,30 @@ Feature: Step - has()
| result |
| d[29].i |
+ Scenario: g_V_hasXperson_name_markovarX_age
+ Given the modern graph
+ And using the parameter xx1 defined as "marko"
+ And the traversal of
+ """
+ g.V().has("person", "name", xx1).values("age")
+ """
+ When iterated to list
+ Then the result should be unordered
+ | result |
+ | d[29].i |
+
+ Scenario: g_V_hasXpersonvar_name_markoX_age
+ Given the modern graph
+ And using the parameter xx1 defined as "person"
+ And the traversal of
+ """
+ g.V().has(xx1, "name", "marko").values("age")
+ """
+ When iterated to list
+ Then the result should be unordered
+ | result |
+ | d[29].i |
+
Scenario: g_VX1X_outE_hasXweight_inside_0_06X_inV
Given the modern graph
And using the parameter vid1 defined as "v[marko].id"
diff --git a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/filter/HasId.feature b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/filter/HasId.feature
index 8c20b41b72..cc85a5c4fe 100644
--- a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/filter/HasId.feature
+++ b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/filter/HasId.feature
@@ -32,10 +32,9 @@ Feature: Step - hasId()
Scenario: g_V_hasIdXwithinXemptyXX_count
Given the modern graph
- And using the parameter xx1 of P.within("l[]")
And the traversal of
"""
- g.V().hasId(xx1).count()
+ g.V().hasId(P.within([])).count()
"""
When iterated to list
Then the result should be unordered
@@ -44,10 +43,9 @@ Feature: Step - hasId()
Scenario: g_V_hasIdXwithoutXemptyXX_count
Given the modern graph
- And using the parameter xx1 of P.without("l[]")
And the traversal of
"""
- g.V().hasId(xx1).count()
+ g.V().hasId(P.without([])).count()
"""
When iterated to list
Then the result should be unordered
@@ -56,10 +54,9 @@ Feature: Step - hasId()
Scenario: g_V_notXhasIdXwithinXemptyXXX_count
Given the modern graph
- And using the parameter xx1 of P.within("l[]")
And the traversal of
"""
- g.V().not(__.hasId(xx1)).count()
+ g.V().not(__.hasId(P.within([]))).count()
"""
When iterated to list
Then the result should be unordered
@@ -147,10 +144,10 @@ Feature: Step - hasId()
Scenario: g_V_in_hasIdXneqX1XX
Given the modern graph
- And using the parameter xx1 of P.neq("v[marko].id")
+ And using the parameter xx1 defined as "v[marko].id"
And the traversal of
"""
- g.V().in().hasId(xx1)
+ g.V().in().hasId(P.neq(xx1))
"""
When iterated to list
Then the result should be unordered
diff --git a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/filter/HasLabel.feature b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/filter/HasLabel.feature
index 470019f36d..2da655e7e6 100644
--- a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/filter/HasLabel.feature
+++ b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/filter/HasLabel.feature
@@ -87,6 +87,34 @@ Feature: Step - hasLabel()
When iterated to list
Then the result should be empty
+ Scenario: g_V_hasLabelXpersonvarX_hasLabelXsoftwareX
+ Given the modern graph
+ And using the parameter xx1 defined as "person"
+ And the traversal of
+ """
+ g.V().hasLabel(xx1).hasLabel("software")
+ """
+ When iterated to list
+ Then the result should be empty
+
+ Scenario: g_V_hasLabelXpersonvar_softwarevarX
+ Given the modern graph
+ And using the parameter xx1 defined as "person"
+ And using the parameter xx2 defined as "software"
+ And the traversal of
+ """
+ g.V().hasLabel(xx1,xx2)
+ """
+ When iterated to list
+ Then the result should be unordered
+ | result |
+ | v[marko] |
+ | v[vadas] |
+ | v[josh] |
+ | v[peter] |
+ | v[lop] |
+ | v[ripple] |
+
Scenario: g_V_hasLabelXpersonX_hasXage_notXlteX10X_andXnotXbetweenX11_20XXXX_andXltX29X_orXeqX35XXXX_name
Given the modern graph
And the traversal of
diff --git a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/Conjoin.feature b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/Conjoin.feature
index 9d9d54547e..8f05f14f0d 100644
--- a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/Conjoin.feature
+++ b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/Conjoin.feature
@@ -59,7 +59,7 @@ Feature: Step - conjoin()
| result |
| josh_lop_marko_peter_ripple_vadas |
- Scenario: g_V_valuesXageX_order_fold_conjoinX_X
+ Scenario: g_V_valuesXageX_order_fold_conjoinXsemicolonX
Given the modern graph
And the traversal of
"""
@@ -70,6 +70,18 @@ Feature: Step - conjoin()
| result |
| 27;29;32;35 |
+ Scenario: g_V_valuesXageX_order_fold_conjoinXslashX
+ Given the modern graph
+ And using the parameter xx1 defined as "/"
+ And the traversal of
+ """
+ g.V().values("age").order().fold().conjoin(xx1)
+ """
+ When iterated to list
+ Then the result should be unordered
+ | result |
+ | 27/29/32/35 |
+
@GraphComputerVerificationReferenceOnly
Scenario: g_V_out_path_byXvaluesXnameX_toUpperX_conjoinXMARKOX
Given the modern graph
diff --git a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/Edge.feature b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/Edge.feature
index f3d92320d2..7d75a251af 100644
--- a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/Edge.feature
+++ b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/Edge.feature
@@ -16,7 +16,117 @@
# under the License.
@StepClassMap @StepE
-Feature: Step - E()
+Feature: Step - E(), inV(), outV(), bothV(), otherV()
+
+ Scenario: g_E
+ Given the modern graph
+ And the traversal of
+ """
+ g.E()
+ """
+ When iterated to list
+ Then the result should be unordered
+ | result |
+ | e[marko-created->lop] |
+ | e[marko-knows->josh] |
+ | e[marko-knows->vadas] |
+ | e[peter-created->lop] |
+ | e[josh-created->lop] |
+ | e[josh-created->ripple] |
+
+ Scenario: g_EX11X
+ Given the modern graph
+ And using the parameter eid11 defined as "e[josh-created->lop].id"
+ And the traversal of
+ """
+ g.E(eid11)
+ """
+ When iterated to list
+ Then the result should be unordered
+ | result |
+ | e[josh-created->lop] |
+
+ Scenario: g_EX11AsStringX
+ Given the modern graph
+ And using the parameter eid11 defined as "e[josh-created->lop].sid"
+ And the traversal of
+ """
+ g.E(eid11)
+ """
+ When iterated to list
+ Then the result should be unordered
+ | result |
+ | e[josh-created->lop] |
+
+ Scenario: g_EXe11X
+ Given the modern graph
+ And using the parameter e11 defined as "e[josh-created->lop]"
+ And the traversal of
+ """
+ g.E(e11)
+ """
+ When iterated to list
+ Then the result should be unordered
+ | result |
+ | e[josh-created->lop] |
+
+ Scenario: g_EXe7_e11X
+ Given the modern graph
+ And using the parameter e7 defined as "e[marko-knows->vadas]"
+ And using the parameter e11 defined as "e[josh-created->lop]"
+ And the traversal of
+ """
+ g.E(e7,e11)
+ """
+ When iterated to list
+ Then the result should be unordered
+ | result |
+ | e[marko-knows->vadas] |
+ | e[josh-created->lop] |
+
+ Scenario: g_EXlistXe7_e11XX
+ Given the modern graph
+ And using the parameter xx1 defined as "l[e[marko-knows->vadas],e[josh-created->lop]]"
+ And the traversal of
+ """
+ g.E(xx1)
+ """
+ When iterated to list
+ Then the result should be unordered
+ | result |
+ | e[marko-knows->vadas] |
+ | e[josh-created->lop] |
+
+ Scenario: g_EXnullX
+ Given the modern graph
+ And the traversal of
+ """
+ g.E(null)
+ """
+ When iterated to list
+ Then the result should be empty
+
+ Scenario: g_EXlistXnullXX
+ Given the modern graph
+ And using the parameter xx1 defined as "l[null]"
+ And the traversal of
+ """
+ g.E(xx1)
+ """
+ When iterated to list
+ Then the result should be empty
+
+ Scenario: g_EX11_nullX
+ Given the modern graph
+ And using the parameter eid11 defined as "e[josh-created->lop].id"
+ And the traversal of
+ """
+ g.E(eid11,null)
+ """
+ When iterated to list
+ Then the result should be unordered
+ | result |
+ | e[josh-created->lop] |
Scenario: g_V_EX11X
Given the modern graph
@@ -97,3 +207,152 @@ Feature: Step - E()
When iterated to list
Then the result should have a count of 1
And the graph should return 1 for count of "g.E().hasLabel(\"tests\")"
+
+ Scenario: g_VX1X_outE_inV
+ Given the modern graph
+ And using the parameter vid1 defined as "v[marko].id"
+ And the traversal of
+ """
+ g.V(vid1).outE().inV()
+ """
+ When iterated to list
+ Then the result should be unordered
+ | result |
+ | v[vadas] |
+ | v[josh] |
+ | v[lop] |
+
+ Scenario: g_VX2X_inE_outV
+ Given the modern graph
+ And using the parameter vid2 defined as "v[vadas].id"
+ And the traversal of
+ """
+ g.V(vid2).inE().outV()
+ """
+ When iterated to list
+ Then the result should be unordered
+ | result |
+ | v[marko] |
+
+ Scenario: g_V_outE_hasXweight_1X_outV
+ Given the modern graph
+ And the traversal of
+ """
+ g.V().outE().has("weight",1.0).outV()
+ """
+ When iterated to list
+ Then the result should be unordered
+ | result |
+ | v[marko] |
+ | v[josh] |
+
+ Scenario: g_VX1X_outE_otherV
+ Given the modern graph
+ And using the parameter vid1 defined as "v[marko].id"
+ And the traversal of
+ """
+ g.V(vid1).outE().otherV()
+ """
+ When iterated to list
+ Then the result should be unordered
+ | result |
+ | v[vadas] |
+ | v[josh] |
+ | v[lop] |
+
+ Scenario: g_VX4X_bothE_otherV
+ Given the modern graph
+ And using the parameter vid4 defined as "v[josh].id"
+ And the traversal of
+ """
+ g.V(vid4).bothE().otherV()
+ """
+ When iterated to list
+ Then the result should be unordered
+ | result |
+ | v[marko] |
+ | v[ripple] |
+ | v[lop] |
+
+ Scenario: g_VX4X_bothE_hasXweight_lt_1X_otherV
+ Given the modern graph
+ And using the parameter vid4 defined as "v[josh].id"
+ And the traversal of
+ """
+ g.V(vid4).bothE().has("weight", P.lt(1.0)).otherV()
+ """
+ When iterated to list
+ Then the result should be unordered
+ | result |
+ | v[lop] |
+
+ Scenario: get_g_VX1X_outE_otherV
+ Given the modern graph
+ And using the parameter vid1 defined as "v[marko].id"
+ And the traversal of
+ """
+ g.V(vid1).outE().otherV()
+ """
+ When iterated to list
+ Then the result should be unordered
+ | result |
+ | v[vadas] |
+ | v[josh] |
+ | v[lop] |
+
+ Scenario: g_VX1X_outEXknowsX_inV
+ Given the modern graph
+ And using the parameter vid1 defined as "v[marko].id"
+ And the traversal of
+ """
+ g.V(vid1).outE("knows").inV()
+ """
+ When iterated to list
+ Then the result should be unordered
+ | result |
+ | v[vadas] |
+ | v[josh] |
+
+ Scenario: g_VX1X_outEXknows_createdX_inV
+ Given the modern graph
+ And using the parameter vid1 defined as "v[marko].id"
+ And the traversal of
+ """
+ g.V(vid1).outE("knows","created").inV()
+ """
+ When iterated to list
+ Then the result should be unordered
+ | result |
+ | v[vadas] |
+ | v[josh] |
+ | v[lop] |
+
+ Scenario: g_VX1X_outEXknowsX_bothV
+ Given the modern graph
+ And using the parameter vid1 defined as "v[marko].id"
+ And the traversal of
+ """
+ g.V(vid1).outE("knows").bothV()
+ """
+ When iterated to list
+ Then the result should be unordered
+ | result |
+ | v[marko] |
+ | v[marko] |
+ | v[josh] |
+ | v[vadas] |
+
+ Scenario: g_VX1X_outEXknowsX_bothV_name
+ Given the modern graph
+ And using the parameter vid1 defined as "v[marko].id"
+ And the traversal of
+ """
+ g.V(vid1).outE("knows").bothV().values("name")
+ """
+ When iterated to list
+ Then the result should be unordered
+ | result |
+ | marko |
+ | marko |
+ | josh |
+ | vadas |
\ No newline at end of file
diff --git a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/Vertex.feature b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/Vertex.feature
index f0b3c95a93..3f8912211b 100644
--- a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/Vertex.feature
+++ b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/Vertex.feature
@@ -16,7 +16,7 @@
# under the License.
@StepClassMap @StepVertex
-Feature: Step - V(), E(), out(), in(), both(), inE(), outE(), bothE()
+Feature: Step - V(), out(), in(), both(), inE(), outE(), bothE()
Scenario: g_VXnullX
Given the modern graph
@@ -147,116 +147,6 @@ Feature: Step - V(), E(), out(), in(), both(), inE(), outE(), bothE()
| v[lop] |
| v[ripple] |
- Scenario: g_E
- Given the modern graph
- And the traversal of
- """
- g.E()
- """
- When iterated to list
- Then the result should be unordered
- | result |
- | e[marko-created->lop] |
- | e[marko-knows->josh] |
- | e[marko-knows->vadas] |
- | e[peter-created->lop] |
- | e[josh-created->lop] |
- | e[josh-created->ripple] |
-
- Scenario: g_EX11X
- Given the modern graph
- And using the parameter eid11 defined as "e[josh-created->lop].id"
- And the traversal of
- """
- g.E(eid11)
- """
- When iterated to list
- Then the result should be unordered
- | result |
- | e[josh-created->lop] |
-
- Scenario: g_EX11AsStringX
- Given the modern graph
- And using the parameter eid11 defined as "e[josh-created->lop].sid"
- And the traversal of
- """
- g.E(eid11)
- """
- When iterated to list
- Then the result should be unordered
- | result |
- | e[josh-created->lop] |
-
- Scenario: g_EXe11X
- Given the modern graph
- And using the parameter e11 defined as "e[josh-created->lop]"
- And the traversal of
- """
- g.E(e11)
- """
- When iterated to list
- Then the result should be unordered
- | result |
- | e[josh-created->lop] |
-
- Scenario: g_EXe7_e11X
- Given the modern graph
- And using the parameter e7 defined as "e[marko-knows->vadas]"
- And using the parameter e11 defined as "e[josh-created->lop]"
- And the traversal of
- """
- g.E(e7,e11)
- """
- When iterated to list
- Then the result should be unordered
- | result |
- | e[marko-knows->vadas] |
- | e[josh-created->lop] |
-
- Scenario: g_EXlistXe7_e11XX
- Given the modern graph
- And using the parameter xx1 defined as "l[e[marko-knows->vadas],e[josh-created->lop]]"
- And the traversal of
- """
- g.E(xx1)
- """
- When iterated to list
- Then the result should be unordered
- | result |
- | e[marko-knows->vadas] |
- | e[josh-created->lop] |
-
- Scenario: g_EXnullX
- Given the modern graph
- And the traversal of
- """
- g.E(null)
- """
- When iterated to list
- Then the result should be empty
-
- Scenario: g_EXlistXnullXX
- Given the modern graph
- And using the parameter xx1 defined as "l[null]"
- And the traversal of
- """
- g.E(xx1)
- """
- When iterated to list
- Then the result should be empty
-
- Scenario: g_EX11_nullX
- Given the modern graph
- And using the parameter eid11 defined as "e[josh-created->lop].id"
- And the traversal of
- """
- g.E(eid11,null)
- """
- When iterated to list
- Then the result should be unordered
- | result |
- | e[josh-created->lop] |
-
Scenario: g_VX1X_outE
Given the modern graph
And using the parameter vid1 defined as "v[marko].id"
@@ -310,44 +200,6 @@ Feature: Step - V(), E(), out(), in(), both(), inE(), outE(), bothE()
| e[josh-created->ripple] |
| e[marko-knows->josh] |
- Scenario: g_VX1X_outE_inV
- Given the modern graph
- And using the parameter vid1 defined as "v[marko].id"
- And the traversal of
- """
- g.V(vid1).both()
- """
- When iterated to list
- Then the result should be unordered
- | result |
- | v[vadas] |
- | v[josh] |
- | v[lop] |
-
- Scenario: g_VX2X_inE_outV
- Given the modern graph
- And using the parameter vid2 defined as "v[vadas].id"
- And the traversal of
- """
- g.V(vid2).inE().outV()
- """
- When iterated to list
- Then the result should be unordered
- | result |
- | v[marko] |
-
- Scenario: g_V_outE_hasXweight_1X_outV
- Given the modern graph
- And the traversal of
- """
- g.V().outE().has("weight",1.0).outV()
- """
- When iterated to list
- Then the result should be unordered
- | result |
- | v[marko] |
- | v[josh] |
-
Scenario: g_V_out_outE_inV_inE_inV_both_name
Given the modern graph
And the traversal of
@@ -368,61 +220,6 @@ Feature: Step - V(), E(), out(), in(), both(), inE(), outE(), bothE()
| peter |
| peter |
- Scenario: g_VX1X_outEXknowsX_bothV_name
- Given the modern graph
- And using the parameter vid1 defined as "v[marko].id"
- And the traversal of
- """
- g.V(vid1).outE("knows").bothV().values("name")
- """
- When iterated to list
- Then the result should be unordered
- | result |
- | marko |
- | marko |
- | josh |
- | vadas |
-
- Scenario: g_VX1X_outE_otherV
- Given the modern graph
- And using the parameter vid1 defined as "v[marko].id"
- And the traversal of
- """
- g.V(vid1).outE().otherV()
- """
- When iterated to list
- Then the result should be unordered
- | result |
- | v[vadas] |
- | v[josh] |
- | v[lop] |
-
- Scenario: g_VX4X_bothE_otherV
- Given the modern graph
- And using the parameter vid4 defined as "v[josh].id"
- And the traversal of
- """
- g.V(vid4).bothE().otherV()
- """
- When iterated to list
- Then the result should be unordered
- | result |
- | v[marko] |
- | v[ripple] |
- | v[lop] |
-
- Scenario: g_VX4X_bothE_hasXweight_lt_1X_otherV
- Given the modern graph
- And using the parameter vid4 defined as "v[josh].id"
- And the traversal of
- """
- g.V(vid4).bothE().has("weight", P.lt(1.0)).otherV()
- """
- When iterated to list
- Then the result should be unordered
- | result |
- | v[lop] |
-
Scenario: g_VX2X_inE
Given the modern graph
And using the parameter vid2 defined as "v[vadas].id"
@@ -435,20 +232,6 @@ Feature: Step - V(), E(), out(), in(), both(), inE(), outE(), bothE()
| result |
| e[marko-knows->vadas] |
- Scenario: get_g_VX1X_outE_otherV
- Given the modern graph
- And using the parameter vid1 defined as "v[marko].id"
- And the traversal of
- """
- g.V(vid1).outE().otherV()
- """
- When iterated to list
- Then the result should be unordered
- | result |
- | v[vadas] |
- | v[josh] |
- | v[lop] |
-
Scenario: g_VX1X_outXknowsX
Given the modern graph
And using the parameter vid1 defined as "v[marko].id"
@@ -489,33 +272,6 @@ Feature: Step - V(), E(), out(), in(), both(), inE(), outE(), bothE()
| v[josh] |
| v[lop] |
- Scenario: g_VX1X_outEXknowsX_inV
- Given the modern graph
- And using the parameter vid1 defined as "v[marko].id"
- And the traversal of
- """
- g.V(vid1).outE("knows").inV()
- """
- When iterated to list
- Then the result should be unordered
- | result |
- | v[vadas] |
- | v[josh] |
-
- Scenario: g_VX1X_outEXknows_createdX_inV
- Given the modern graph
- And using the parameter vid1 defined as "v[marko].id"
- And the traversal of
- """
- g.V(vid1).outE("knows","created").inV()
- """
- When iterated to list
- Then the result should be unordered
- | result |
- | v[vadas] |
- | v[josh] |
- | v[lop] |
-
Scenario: g_V_out_out
Given the modern graph
And the traversal of
@@ -565,8 +321,6 @@ Feature: Step - V(), E(), out(), in(), both(), inE(), outE(), bothE()
| v[vadas] |
| v[josh] |
-
-
# the point here is to test g.V() where an id is not present. to do this with the gherkin structure
# the test establishes the modern graph, does a drop() of "lop" and then tries to query the 4 vertices
# and we assert the count of 3
diff --git a/neo4j-gremlin/src/main/java/org/apache/tinkerpop/gremlin/neo4j/process/traversal/step/sideEffect/Neo4jGraphStep.java b/neo4j-gremlin/src/main/java/org/apache/tinkerpop/gremlin/neo4j/process/traversal/step/sideEffect/Neo4jGraphStep.java
index 7ab286543c..90d7327cc7 100644
--- a/neo4j-gremlin/src/main/java/org/apache/tinkerpop/gremlin/neo4j/process/traversal/step/sideEffect/Neo4jGraphStep.java
+++ b/neo4j-gremlin/src/main/java/org/apache/tinkerpop/gremlin/neo4j/process/traversal/step/sideEffect/Neo4jGraphStep.java
@@ -66,7 +66,7 @@ public final class Neo4jGraphStep<S, E extends Element> extends GraphStep<S, E>
private Iterator<? extends Edge> edges() {
if (null == this.ids)
return Collections.emptyIterator();
- return IteratorUtils.filter(this.getTraversal().getGraph().get().edges(this.ids), edge -> HasContainer.testAll(edge, this.hasContainers));
+ return IteratorUtils.filter(this.getTraversal().getGraph().get().edges(this.getIdsAsValues()), edge -> HasContainer.testAll(edge, this.hasContainers));
}
private Iterator<? extends Vertex> vertices() {
@@ -76,7 +76,7 @@ public final class Neo4jGraphStep<S, E extends Element> extends GraphStep<S, E>
// ids are present, filter on them first
if (ids.length > 0)
- return IteratorUtils.filter(graph.vertices(ids), vertex -> HasContainer.testAll(vertex, hasContainers));
+ return IteratorUtils.filter(graph.vertices(this.getIdsAsValues()), vertex -> HasContainer.testAll(vertex, hasContainers));
////// do index lookups //////
graph.tx().readWrite();
// get a label being search on
diff --git a/sparql-gremlin/src/main/java/org/apache/tinkerpop/gremlin/sparql/process/traversal/strategy/SparqlStrategy.java b/sparql-gremlin/src/main/java/org/apache/tinkerpop/gremlin/sparql/process/traversal/strategy/SparqlStrategy.java
index a4a95cc1c1..5f791b41d5 100644
--- a/sparql-gremlin/src/main/java/org/apache/tinkerpop/gremlin/sparql/process/traversal/strategy/SparqlStrategy.java
+++ b/sparql-gremlin/src/main/java/org/apache/tinkerpop/gremlin/sparql/process/traversal/strategy/SparqlStrategy.java
@@ -23,7 +23,6 @@ import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategy;
import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.InjectStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.util.EmptyStep;
import org.apache.tinkerpop.gremlin.process.traversal.strategy.AbstractTraversalStrategy;
import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper;
import org.apache.tinkerpop.gremlin.sparql.SparqlToGremlinCompiler;
diff --git a/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/process/traversal/step/sideEffect/TinkerGraphStep.java b/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/process/traversal/step/sideEffect/TinkerGraphStep.java
index 6a3e965629..5a3d59e80b 100644
--- a/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/process/traversal/step/sideEffect/TinkerGraphStep.java
+++ b/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/process/traversal/step/sideEffect/TinkerGraphStep.java
@@ -71,11 +71,12 @@ public final class TinkerGraphStep<S, E extends Element> extends GraphStep<S, E>
final AbstractTinkerGraph graph = (AbstractTinkerGraph) this.getTraversal().getGraph().get();
final HasContainer indexedContainer = getIndexKey(Edge.class);
Iterator<Edge> iterator;
+ final Object[] resolvedIds = this.getIdsAsValues();
// ids are present, filter on them first
- if (null == this.ids)
+ if (null == resolvedIds)
iterator = Collections.emptyIterator();
- else if (this.ids.length > 0)
- iterator = this.iteratorList(graph.edges(this.ids));
+ else if (resolvedIds.length > 0)
+ iterator = this.iteratorList(graph.edges(resolvedIds));
else
iterator = null == indexedContainer ?
this.iteratorList(graph.edges()) :
@@ -93,11 +94,12 @@ public final class TinkerGraphStep<S, E extends Element> extends GraphStep<S, E>
final AbstractTinkerGraph graph = (AbstractTinkerGraph) this.getTraversal().getGraph().get();
final HasContainer indexedContainer = getIndexKey(Vertex.class);
Iterator<? extends Vertex> iterator;
+ final Object[] resolvedIds = this.getIdsAsValues();
// ids are present, filter on them first
- if (null == this.ids)
+ if (null == resolvedIds)
iterator = Collections.emptyIterator();
- else if (this.ids.length > 0)
- iterator = this.iteratorList(graph.vertices(this.ids));
+ else if (resolvedIds.length > 0)
+ iterator = this.iteratorList(graph.vertices(resolvedIds));
else
iterator = (null == indexedContainer ?
this.iteratorList(graph.vertices()) :
diff --git a/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/TinkerWorld.java b/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/TinkerWorld.java
index 329a07fbae..52fd414164 100644
--- a/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/TinkerWorld.java
+++ b/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/TinkerWorld.java
@@ -109,6 +109,11 @@ public abstract class TinkerWorld implements World {
public AbstractTinkerGraph open(final Configuration configuration) {
return TinkerGraph.open(configuration);
}
+
+ @Override
+ public boolean useParametersLiterally() {
+ return false;
+ }
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
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 80111709f5..e1d908045b 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
@@ -18,8 +18,12 @@
*/
package org.apache.tinkerpop.gremlin.tinkergraph.structure;
+import org.apache.tinkerpop.gremlin.jsr223.GremlinLangScriptEngine;
+import org.apache.tinkerpop.gremlin.jsr223.VariableResolverCustomizer;
+import org.apache.tinkerpop.gremlin.language.grammar.VariableResolver;
import org.apache.tinkerpop.gremlin.process.computer.Computer;
import org.apache.tinkerpop.gremlin.process.traversal.P;
+import org.apache.tinkerpop.gremlin.process.traversal.Scope;
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;
@@ -38,6 +42,7 @@ import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import javax.script.Bindings;
import java.util.Arrays;
import java.util.List;
import java.util.function.BiFunction;
@@ -270,17 +275,25 @@ public class TinkerGraphPlayTest {
}
@Test
- @Ignore
- public void testBugs() {
+ public void testBugs() throws Exception {
final GraphTraversalSource g = TinkerFactory.createModern().traversal();
- Object o1 = g.V().map(__.V(1));
- System.out.println(g.V().as("a").both().as("b").dedup("a", "b").by(T.label).select("a", "b").explain());
- System.out.println(g.V().as("a").both().as("b").dedup("a", "b").by(T.label).select("a", "b").toList());
-
- Traversal<?,?> t =
- g.V("3").
- union(__.repeat(out().simplePath()).times(2).count(),
- __.repeat(in().simplePath()).times(2).count());
+ final GremlinLangScriptEngine se = new GremlinLangScriptEngine(
+ new VariableResolverCustomizer(VariableResolver.DefaultVariableResolver::new));
+
+ final Bindings b = se.createBindings();
+ b.put("g", g);
+ System.out.println(((GraphTraversal) se.eval("g.V().coin(0.5).count()", b)).toList());
+
+ b.clear();
+ b.put("g", g);
+ b.put("x", 0.5d);
+ System.out.println(((GraphTraversal) se.eval("g.V().coin(x).count()", b)).toList());
+
+ b.clear();
+ b.put("g", g);
+ b.put("x", "josh");
+ b.put("y", 32);
+ System.out.println(((GraphTraversal) se.eval("g.V().has('name', x).has('age', y).count()", b)).toList());
}
@Test