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 2026/07/06 20:39:30 UTC
(tinkerpop) branch multi-label-toy-graph updated (228b0c602e -> 5abaae710c)
This is an automated email from the ASF dual-hosted git repository.
Cole-Greer pushed a change to branch multi-label-toy-graph
in repository https://gitbox.apache.org/repos/asf/tinkerpop.git
discard 228b0c602e Add an example zoo graph
add 6a3c91ed07 Reconstruct source-spawned multi-label addV as a single step
add 99f496a86e Preserve GValue variables through multi-label addV and simplify the addV API
add 687878f5e2 Add label-traversal semantics, addV traversal-varargs, and multi-label test coverage
add dfc1827a41 Address multi-label documentation review comments
add 561723f234 Fold LabelsDropVerificationStrategy into StandardVerificationStrategy
add d6c57e2b27 cleanup gherkin tags docs
add 131098648a Fix gremlin-core compilation for addLabel(Traversal) type inference
add f1e678b261 Test multi-label single-label-default rendering via one-of assertion
add 102938e5d7 Align addLabel()/dropLabel() traversal-varargs with addV() semantics
add b88f22ec8f Simplify addV/addLabel/dropLabel grammar visitors
add 43e0336980 Fix multi-label addV codegen in GremlinDslProcessor
add 9ea3df147c Use literal-only grammar for addLabel()/dropLabel() strings
add 2958a30e72 Unify multi-label representation in addV step hierarchy
new 6b78279218 Add an example zoo graph
new ad751d50d3 Fix multi-label rendering gaps in ElementMapStep and ComputerGraph
new 5abaae710c Wire up the zoo graph and convert read-only multi-label scenarios
This update added new revisions after undoing existing revisions.
That is to say, some revisions that were in the old version of the
branch are not in the new version. This situation occurs
when a user --force pushes a change and generates a repository
containing something like this:
* -- * -- B -- O -- O -- O (228b0c602e)
\
N -- N -- N refs/heads/multi-label-toy-graph (5abaae710c)
You should already have received notification emails for all of the O
revisions, and so the following emails describe only the N revisions
from the common base, B.
Any revisions marked "omit" are not gone; other references still
refer to them. Any revisions marked "discard" are gone forever.
The 3 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:
CHANGELOG.asciidoc | 2 +-
.../gremlin-server/gremlin-server-integration.yaml | 4 +
docs/src/dev/developer/for-committers.asciidoc | 20 +-
docs/src/dev/provider/gremlin-semantics.asciidoc | 99 +-
.../reference/implementations-tinkergraph.asciidoc | 16 +-
docs/src/reference/the-graph.asciidoc | 11 +
docs/src/reference/the-traversal.asciidoc | 32 +-
.../gremlin/process/traversal/dsl/GremlinDsl.java | 2 +-
.../process/traversal/dsl/GremlinDslProcessor.java | 46 +-
.../traversal/dsl/GremlinDslProcessorTest.java | 32 +
.../traversal/dsl/AddVMultiLabelDslTraversal.java | 70 ++
.../gremlin/language/grammar/ArgumentVisitor.java | 25 +
.../grammar/DefaultGremlinBaseVisitor.java | 25 +-
.../language/grammar/GenericLiteralVisitor.java | 14 +
.../language/grammar/TraversalMethodVisitor.java | 88 +-
.../grammar/TraversalSourceSpawnMethodVisitor.java | 59 +-
.../translator/DotNetTranslateVisitor.java | 58 +-
.../process/computer/util/ComputerGraph.java | 5 +
.../process/traversal/TraversalStrategies.java | 3 -
.../traversal/dsl/graph/GraphTraversal.java | 146 +--
.../traversal/dsl/graph/GraphTraversalSource.java | 117 ++-
.../gremlin/process/traversal/dsl/graph/__.java | 38 +-
.../map/AbstractAddElementStepPlaceholder.java | 148 ++-
.../step/map/AbstractAddVertexStepPlaceholder.java | 10 +-
.../traversal/step/map/AddElementStepContract.java | 17 +
.../traversal/step/map/AddVertexStartStep.java | 168 +++-
.../step/map/AddVertexStartStepPlaceholder.java | 28 +-
.../process/traversal/step/map/AddVertexStep.java | 170 +++-
.../step/map/AddVertexStepPlaceholder.java | 27 +-
.../process/traversal/step/map/ElementMapStep.java | 14 +-
.../traversal/step/map/PropertyMapStep.java | 5 +-
.../traversal/step/sideEffect/AddLabelStep.java | 54 +-
.../traversal/step/sideEffect/DropLabelsStep.java | 46 +-
.../LabelsDropVerificationStrategy.java | 66 --
.../verification/StandardVerificationStrategy.java | 19 +
.../process/traversal/util/TraversalHelper.java | 27 +
.../process/traversal/util/TraversalUtil.java | 51 +
.../grammar/TraversalMethodVisitorTest.java | 98 ++
.../language/grammar/TraversalRootVisitorTest.java | 29 +
.../gremlin/process/traversal/GremlinLangTest.java | 4 +
.../dsl/graph/GraphTraversalSourceTest.java | 2 +-
.../traversal/step/map/AddVertexStepTest.java | 107 +-
.../LabelsDropVerificationStrategyTest.java | 85 --
.../StandardVerificationStrategyTest.java | 15 +-
.../Process/Traversal/GraphTraversal.cs | 77 +-
.../Process/Traversal/GraphTraversalSource.cs | 47 +-
.../src/Gremlin.Net/Process/Traversal/__.cs | 26 +-
.../Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs | 33 +
.../Gherkin/ScenarioData.cs | 2 +-
gremlin-go/driver/cucumber/cucumberWorld.go | 15 +-
gremlin-go/driver/cucumber/gremlin.go | 33 +
.../language/translator/DotNetTranslateVisitor.ts | 13 +-
.../gremlin-javascript/test/cucumber/gremlin.js | 43 +-
.../gremlin-javascript/test/cucumber/world.js | 2 +-
gremlin-language/src/main/antlr4/Gremlin.g4 | 28 +-
.../src/main/python/tests/feature/gremlin.py | 33 +
.../src/main/python/tests/feature/terrain.py | 4 +-
.../server/util/TinkerFactoryDataLoader.java | 5 +-
.../gremlin/driver/remote/RemoteWorld.java | 3 +
.../server/util/CheckedGraphManagerTest.java | 2 +-
.../server/util/DefaultGraphManagerTest.java | 13 +-
.../gremlin/server/gremlin-server-integration.yaml | 4 +
.../apache/tinkerpop/gremlin/LoadGraphWith.java | 20 +-
.../gremlin/language/translator/translations.json | 1033 +++++++++++++++++---
.../gremlin/test/features/map/AddVertex.feature | 44 +
.../gremlin/test/features/map/ElementMap.feature | 154 ++-
.../gremlin/test/features/map/Labels.feature | 80 +-
.../gremlin/test/features/map/ValueMap.feature | 80 +-
.../test/features/sideEffect/AddLabel.feature | 74 +-
.../test/features/sideEffect/DropLabel.feature | 84 +-
.../tinkerpop/gremlin/tinkergraph/TinkerWorld.java | 33 +
.../sideEffect/LabelTraversalSemanticsTest.java | 289 ++++++
72 files changed, 3514 insertions(+), 862 deletions(-)
create mode 100644 gremlin-annotations/src/test/resources/org/apache/tinkerpop/gremlin/process/traversal/dsl/AddVMultiLabelDslTraversal.java
delete mode 100644 gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/verification/LabelsDropVerificationStrategy.java
delete mode 100644 gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/verification/LabelsDropVerificationStrategyTest.java
create mode 100644 tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/process/traversal/step/sideEffect/LabelTraversalSemanticsTest.java
(tinkerpop) 01/03: Add an example zoo graph
Posted by co...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
Cole-Greer pushed a commit to branch multi-label-toy-graph
in repository https://gitbox.apache.org/repos/asf/tinkerpop.git
commit 6b782792189947a63a4dffc7228b1a80a1dfdd49
Author: Yang Xia <xi...@gmail.com>
AuthorDate: Sat Jun 27 12:07:41 2026 -0700
Add an example zoo graph
---
.../tinkergraph/structure/TinkerFactory.java | 186 +++++++++++++++++++++
1 file changed, 186 insertions(+)
diff --git a/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerFactory.java b/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerFactory.java
index fc6105e9f8..15b1c99322 100644
--- a/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerFactory.java
+++ b/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerFactory.java
@@ -21,6 +21,7 @@ package org.apache.tinkerpop.gremlin.tinkergraph.structure;
import org.apache.commons.configuration2.BaseConfiguration;
import org.apache.commons.configuration2.Configuration;
import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
+import org.apache.tinkerpop.gremlin.structure.LabelCardinality;
import org.apache.tinkerpop.gremlin.structure.T;
import org.apache.tinkerpop.gremlin.structure.Vertex;
import org.apache.tinkerpop.gremlin.structure.VertexProperty;
@@ -252,6 +253,191 @@ public final class TinkerFactory {
}
}
+ /**
+ * Create "the zoo" graph — a TinkerPop 4.x toy graph showcasing multi-label vertex support
+ * and diverse property types. Contains 13 vertices, 20 edges with animals classified across
+ * taxonomy, behavior, and conservation axes.
+ */
+ public static TinkerGraph createTheZoo() {
+ final Configuration conf = getConfigurationWithCurrentNumberManager();
+ conf.setProperty(AbstractTinkerGraph.GREMLIN_TINKERGRAPH_VERTEX_LABEL_CARDINALITY, LabelCardinality.ZERO_OR_MORE.name());
+ final TinkerGraph g = TinkerGraph.open(conf);
+ generateTheZoo(g);
+ return g;
+ }
+
+ /**
+ * Generate the graph in {@link #createTheZoo()} into an existing graph. The graph must support
+ * multi-label vertices (LabelCardinality of ONE_OR_MORE or ZERO_OR_MORE).
+ */
+ public static void generateTheZoo(final AbstractTinkerGraph g) {
+ // Animals
+ final Vertex tux = g.addVertex(T.id, 1, T.label, "animal");
+ tux.addLabel("bird", "aquatic", "endangered");
+ tux.property("name", "tux");
+ tux.property("species", "african penguin");
+ tux.property("weight", 3.7d);
+ tux.property("age", 5);
+ tux.property("captiveBorn", true);
+ tux.property(VertexProperty.Cardinality.list, "diet", "fish");
+ tux.property(VertexProperty.Cardinality.list, "diet", "krill");
+ tux.property(VertexProperty.Cardinality.list, "diet", "squid");
+
+ final Vertex atlas = g.addVertex(T.id, 2, T.label, "animal");
+ atlas.addLabel("reptile", "aquatic", "endangered");
+ atlas.property("name", "atlas");
+ atlas.property("species", "green sea turtle");
+ atlas.property("weight", 180.5d);
+ atlas.property("age", 30);
+ atlas.property("captiveBorn", false);
+ atlas.property(VertexProperty.Cardinality.list, "diet", "seagrass");
+ atlas.property(VertexProperty.Cardinality.list, "diet", "algae");
+
+ final Vertex ripple = g.addVertex(T.id, 3, T.label, "animal");
+ ripple.addLabel("mammal", "aquatic");
+ ripple.property("name", "ripple");
+ ripple.property("species", "bottlenose dolphin");
+ ripple.property("weight", 220.0d);
+ ripple.property("age", 12);
+ ripple.property("captiveBorn", true);
+ ripple.property(VertexProperty.Cardinality.list, "diet", "fish");
+ ripple.property(VertexProperty.Cardinality.list, "diet", "squid");
+
+ final Vertex monty = g.addVertex(T.id, 4, T.label, "animal");
+ monty.addLabel("reptile", "nocturnal");
+ monty.property("name", "monty");
+ monty.property("species", "ball python");
+ monty.property("weight", 1.8d);
+ monty.property("age", 8);
+ monty.property("captiveBorn", true);
+ monty.property("venomous", false);
+ monty.property(VertexProperty.Cardinality.list, "diet", "mice");
+ monty.property(VertexProperty.Cardinality.list, "diet", "rats");
+
+ final Vertex echo = g.addVertex(T.id, 5, T.label, "animal");
+ echo.addLabel("mammal", "flying", "nocturnal");
+ echo.property("name", "echo");
+ echo.property("species", "fruit bat");
+ echo.property("weight", 0.3d);
+ echo.property("age", 3);
+ echo.property("captiveBorn", true);
+ echo.property(VertexProperty.Cardinality.list, "diet", "fruit");
+ echo.property(VertexProperty.Cardinality.list, "diet", "nectar");
+
+ final Vertex blaze = g.addVertex(T.id, 6, T.label, "animal");
+ blaze.addLabel("mammal", "endangered", "nocturnal");
+ blaze.property("name", "blaze");
+ blaze.property("species", "red panda");
+ blaze.property("weight", 5.4d);
+ blaze.property("age", 4);
+ blaze.property("captiveBorn", false);
+ blaze.property(VertexProperty.Cardinality.list, "diet", "bamboo");
+ blaze.property(VertexProperty.Cardinality.list, "diet", "fruit");
+ blaze.property(VertexProperty.Cardinality.list, "diet", "insects");
+
+ final Vertex titan = g.addVertex(T.id, 7, T.label, "animal");
+ titan.addLabel("mammal", "endangered");
+ titan.property("name", "titan");
+ titan.property("species", "african elephant");
+ titan.property("weight", 4000.0d);
+ titan.property("age", 15);
+ titan.property("captiveBorn", false);
+ titan.property(VertexProperty.Cardinality.list, "diet", "grass");
+ titan.property(VertexProperty.Cardinality.list, "diet", "leaves");
+ titan.property(VertexProperty.Cardinality.list, "diet", "bark");
+
+ final Vertex bitsy = g.addVertex(T.id, 8, T.label, "animal");
+ bitsy.addLabel("mammal", "nocturnal");
+ bitsy.property("name", "bitsy");
+ bitsy.property("species", "harvest mouse");
+ bitsy.property("weight", 0.006d);
+ bitsy.property("age", 1);
+ bitsy.property("captiveBorn", true);
+ bitsy.property(VertexProperty.Cardinality.list, "diet", "seeds");
+ bitsy.property(VertexProperty.Cardinality.list, "diet", "insects");
+
+ final Vertex splash = g.addVertex(T.id, 9, T.label, "animal");
+ splash.addLabel("mammal", "aquatic", "nocturnal", "endangered");
+ splash.property("name", "splash");
+ splash.property("species", "fishing cat");
+ splash.property("weight", 8.2d);
+ splash.property("age", 2);
+ splash.property("captiveBorn", false);
+ splash.property(VertexProperty.Cardinality.list, "diet", "fish");
+ splash.property(VertexProperty.Cardinality.list, "diet", "frogs");
+ splash.property(VertexProperty.Cardinality.list, "diet", "crustaceans");
+
+ final Vertex tinker = g.addVertex(T.id, 10, T.label, "animal");
+ tinker.addLabel("mammal", "nocturnal", "endangered");
+ tinker.property("name", "tinker");
+ tinker.property("species", "bengal tiger");
+ tinker.property("weight", 220.0d);
+ tinker.property("age", 5);
+ tinker.property("captiveBorn", false);
+ tinker.property(VertexProperty.Cardinality.list, "diet", "deer");
+ tinker.property(VertexProperty.Cardinality.list, "diet", "boar");
+ tinker.property(VertexProperty.Cardinality.list, "diet", "snakes");
+
+ // Habitats
+ final Vertex lagoon = g.addVertex(T.id, 11, T.label, "habitat");
+ lagoon.addLabel("aquatic");
+ lagoon.property("name", "lagoon");
+ lagoon.property("biome", "marine");
+ lagoon.property("capacity", 8);
+ lagoon.property("openAir", true);
+
+ final Vertex canopy = g.addVertex(T.id, 12, T.label, "habitat");
+ canopy.property("name", "canopy");
+ canopy.property("biome", "tropical");
+ canopy.property("capacity", 8);
+ canopy.property("openAir", false);
+
+ // People
+ final Vertex drGremlin = g.addVertex(T.id, 13, T.label, "person");
+ drGremlin.addLabel("veterinarian", "keeper");
+ drGremlin.property("name", "dr_gremlin");
+ drGremlin.property("since", 2015);
+ drGremlin.property(VertexProperty.Cardinality.list, "specialties", "conservation");
+ drGremlin.property(VertexProperty.Cardinality.list, "specialties", "surgery");
+ drGremlin.property(VertexProperty.Cardinality.list, "specialties", "nutrition");
+
+ // Edges: livesIn
+ tux.addEdge("livesIn", lagoon, T.id, 14, "since", 2020);
+ atlas.addEdge("livesIn", lagoon, T.id, 15, "since", 2018);
+ ripple.addEdge("livesIn", lagoon, T.id, 16, "since", 2019);
+ splash.addEdge("livesIn", lagoon, T.id, 17, "since", 2023);
+ monty.addEdge("livesIn", canopy, T.id, 18, "since", 2021);
+ echo.addEdge("livesIn", canopy, T.id, 19, "since", 2022);
+ blaze.addEdge("livesIn", canopy, T.id, 20, "since", 2023);
+ bitsy.addEdge("livesIn", canopy, T.id, 21, "since", 2024);
+ tinker.addEdge("livesIn", canopy, T.id, 22, "since", 2020);
+ titan.addEdge("livesIn", canopy, T.id, 23, "since", 2019);
+
+ // Edges: careFor
+ drGremlin.addEdge("careFor", atlas, T.id, 24, "specialty", "conservation");
+ drGremlin.addEdge("careFor", blaze, T.id, 25, "specialty", "conservation");
+ drGremlin.addEdge("careFor", splash, T.id, 26, "specialty", "conservation");
+ drGremlin.addEdge("careFor", tinker, T.id, 27, "specialty", "conservation");
+
+ // Edges: friendsWith
+ tux.addEdge("friendsWith", atlas, T.id, 28, "since", 2020);
+ ripple.addEdge("friendsWith", tux, T.id, 29, "since", 2020);
+ titan.addEdge("friendsWith", blaze, T.id, 30, "since", 2022);
+
+ // Edges: eats (food chain: tinker → monty → bitsy)
+ tinker.addEdge("eats", monty, T.id, 31);
+ monty.addEdge("eats", bitsy, T.id, 32);
+
+ // Edges: avoids
+ echo.addEdge("avoids", bitsy, T.id, 33);
+
+ g.variables().set("name", "the-zoo");
+ g.variables().set("creator", "tinkerpop");
+ g.variables().set("comment",
+ "this graph showcases multi-label vertex support and diverse " +
+ "property types introduced in tinkerpop 4.x");
+ }
+
private static TinkerGraph getTinkerGraphWithCurrentNumberManager() {
return TinkerGraph.open(getConfigurationWithCurrentNumberManager());
}
(tinkerpop) 03/03: Wire up the zoo graph and convert read-only multi-label scenarios
Posted by co...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
Cole-Greer pushed a commit to branch multi-label-toy-graph
in repository https://gitbox.apache.org/repos/asf/tinkerpop.git
commit 5abaae710c1f9342dc7428aafc3dc76f362d6b38
Author: Cole Greer <co...@colegreer.ca>
AuthorDate: Mon Jul 6 13:08:05 2026 -0700
Wire up the zoo graph and convert read-only multi-label scenarios
Adds ZOO to the GraphData enum and wires it into every test harness that
already supports the other named toy graphs: TinkerWorld (embedded,
transaction, and shuffle graph variants), RemoteWorld/TinkerFactoryDataLoader
for server-backed tests, both gremlin-server-integration.yaml configs, and
the Python, JavaScript, Go, and .NET GLV Gherkin runners. The zoo graph uses
tinkergraph-multilabel.properties since it requires ZERO_OR_MORE vertex
label cardinality. Updated the two graph-manager tests whose assertions
hardcoded the total configured graph count, which shifted by one with the
new entry.
Converts scenarios in ElementMap.feature, ValueMap.feature, and
Labels.feature from a bespoke empty-graph-plus-initializer fixture to the
zoo graph wherever the traversal under test is read-only and the zoo's
pre-populated multi-label vertices/edges (tux, lagoon, canopy, atlas, etc.)
can express the same shape deterministically. Scenarios that mutate the
graph, need a vertex with zero or exactly-one label, or depend on a
provider's implicit default label-rendering mode (which is a per-World
configuration switch independent of graph data) remain on the empty graph.
Assisted-by: Claude Code:claude-sonnet-5
---
.../gremlin-server/gremlin-server-integration.yaml | 4 +
.../Gherkin/ScenarioData.cs | 2 +-
gremlin-go/driver/cucumber/cucumberWorld.go | 2 +-
.../gremlin-javascript/test/cucumber/gremlin.js | 16 +-
.../gremlin-javascript/test/cucumber/world.js | 2 +-
.../src/main/python/tests/feature/terrain.py | 4 +-
.../server/util/TinkerFactoryDataLoader.java | 5 +-
.../gremlin/driver/remote/RemoteWorld.java | 3 +
.../server/util/CheckedGraphManagerTest.java | 2 +-
.../server/util/DefaultGraphManagerTest.java | 13 +-
.../gremlin/server/gremlin-server-integration.yaml | 4 +
.../apache/tinkerpop/gremlin/LoadGraphWith.java | 20 +-
.../gremlin/language/translator/translations.json | 256 +++++++--------------
.../gremlin/test/features/map/ElementMap.feature | 36 ++-
.../gremlin/test/features/map/Labels.feature | 32 +--
.../gremlin/test/features/map/ValueMap.feature | 24 +-
.../tinkerpop/gremlin/tinkergraph/TinkerWorld.java | 17 ++
17 files changed, 186 insertions(+), 256 deletions(-)
diff --git a/docker/gremlin-server/gremlin-server-integration.yaml b/docker/gremlin-server/gremlin-server-integration.yaml
index a730970f85..4f2f226b42 100644
--- a/docker/gremlin-server/gremlin-server-integration.yaml
+++ b/docker/gremlin-server/gremlin-server-integration.yaml
@@ -44,6 +44,9 @@ graphs: {
sink: {
configuration: conf/tinkergraph-service.properties,
traversalSources: [{name: gsink}]},
+ zoo: {
+ configuration: conf/tinkergraph-multilabel.properties,
+ traversalSources: [{name: gzoo}]},
tx: {
configuration: conf/tinkertransactiongraph-service.properties,
traversalSources: [{name: gtx}]}}
@@ -53,6 +56,7 @@ lifecycleHooks:
- { className: org.apache.tinkerpop.gremlin.server.util.TinkerFactoryDataLoader, config: {graph: crew, dataset: crew}}
- { className: org.apache.tinkerpop.gremlin.server.util.TinkerFactoryDataLoader, config: {graph: grateful, dataset: grateful}}
- { className: org.apache.tinkerpop.gremlin.server.util.TinkerFactoryDataLoader, config: {graph: sink, dataset: sink}}
+ - { className: org.apache.tinkerpop.gremlin.server.util.TinkerFactoryDataLoader, config: {graph: zoo, dataset: zoo}}
scriptEngines: {
gremlin-lang : {},
gremlin-groovy: {
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/ScenarioData.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/ScenarioData.cs
index b337594415..5cf427fe92 100644
--- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/ScenarioData.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/ScenarioData.cs
@@ -39,7 +39,7 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
{
internal class ScenarioData : IDisposable
{
- private static readonly string[] GraphNames = {"modern", "classic", "crew", "grateful", "sink"};
+ private static readonly string[] GraphNames = {"modern", "classic", "crew", "grateful", "sink", "zoo"};
private static readonly IDictionary<string, Vertex> EmptyVertices =
new ReadOnlyDictionary<string, Vertex>(new Dictionary<string, Vertex>());
diff --git a/gremlin-go/driver/cucumber/cucumberWorld.go b/gremlin-go/driver/cucumber/cucumberWorld.go
index 9e9b8e0b79..d26e4d9c19 100644
--- a/gremlin-go/driver/cucumber/cucumberWorld.go
+++ b/gremlin-go/driver/cucumber/cucumberWorld.go
@@ -87,7 +87,7 @@ func NewCucumberWorld() *CucumberWorld {
}
}
-var graphNames = []string{"modern", "classic", "crew", "grateful", "sink", "empty", "multilabel"}
+var graphNames = []string{"modern", "classic", "crew", "grateful", "sink", "zoo", "empty", "multilabel"}
func (t *CucumberWorld) getDataGraphFromMap(name string) *DataGraph {
if val, ok := t.graphDataMap[name]; ok {
diff --git a/gremlin-js/gremlin-javascript/test/cucumber/gremlin.js b/gremlin-js/gremlin-javascript/test/cucumber/gremlin.js
index 448d09a2fa..0d3dc0fba2 100644
--- a/gremlin-js/gremlin-javascript/test/cucumber/gremlin.js
+++ b/gremlin-js/gremlin-javascript/test/cucumber/gremlin.js
@@ -1209,15 +1209,15 @@ const gremlins = {
g_V_elementMapXname_age_nullX: [function({g}) { return g.with_("singlelabel").V().elementMap("name", "age", null) }],
g_withXmultilabelX_VXmarkoX_elementMap: [function({g}) { return g.with_("multilabel").V().has("name", "marko").elementMap() }],
g_V_elementMap_single_label_default: [function({g}) { return g.addV("person").addLabel("employee").property("name", "marko") }, function({g}) { return g.V().elementMap() }],
- g_withXmultilabelX_V_elementMap_multilabel: [function({g}) { return g.addV("person").addLabel("employee").property("name", "marko") }, function({g}) { return g.with_("multilabel").V().elementMap() }],
+ g_withXmultilabelX_V_elementMap_multilabel: [function({g}) { return g.with_("multilabel").V().has("name", "tux").elementMap("name", "species") }],
g_V_elementMap_multi_label_default: [function({g}) { return g.addV("person").addLabel("employee").property("name", "marko") }, function({g}) { return g.V().elementMap() }],
- g_withXsinglelabelX_V_elementMap_multi_label_default: [function({g}) { return g.addV("person").addLabel("employee").property("name", "marko") }, function({g}) { return g.with_("singlelabel").V().elementMap() }],
+ g_withXsinglelabelX_V_elementMap_multi_label_default: [function({g}) { return g.with_("singlelabel").V().has("name", "lagoon").elementMap("name", "biome") }],
g_V_elementMap_single_label_vertex_multi_label_default: [function({g}) { return g.addV("person").property("name", "marko") }, function({g}) { return g.V().elementMap() }],
g_withXsinglelabelX_V_elementMap_zero_label_vertex: [function({g}) { return g.addV().property("name", "nobody") }, function({g}) { return g.with_("singlelabel").V().elementMap() }],
g_withXmultilabelX_V_elementMap_zero_label_vertex: [function({g}) { return g.addV().property("name", "nobody") }, function({g}) { return g.with_("multilabel").V().elementMap() }],
g_V_elementMap_zero_label_vertex_multi_label_default: [function({g}) { return g.addV().property("name", "nobody") }, function({g}) { return g.V().elementMap() }],
g_V_elementMap_zero_label_vertex_single_label_default: [function({g}) { return g.addV().property("name", "nobody") }, function({g}) { return g.V().elementMap() }],
- g_withXmultilabelX_E_elementMap: [function({g}) { return g.addV("person").property("name", "marko").as("a").addV("person").property("name", "josh").as("b").addE("knows").from_("a").to("b").property("weight", 0.5) }, function({g}) { return g.with_("multilabel").E().elementMap() }],
+ g_withXmultilabelX_E_elementMap: [function({g}) { return g.with_("multilabel").E().has("since", 2018).hasLabel("livesIn").elementMap() }],
g_E_elementMap_multi_label_default: [function({g}) { return g.addV("person").property("name", "marko").as("a").addV("person").property("name", "josh").as("b").addE("knows").from_("a").to("b").property("weight", 0.5) }, function({g}) { return g.E().elementMap() }],
g_E_elementMap_single_label_default: [function({g}) { return g.addV("person").property("name", "marko").as("a").addV("person").property("name", "josh").as("b").addE("knows").from_("a").to("b").property("weight", 0.5) }, function({g}) { return g.E().elementMap() }],
g_withXsinglelabelX_E_elementMap: [function({g}) { return g.addV("person").property("name", "marko").as("a").addV("person").property("name", "josh").as("b").addE("knows").from_("a").to("b").property("weight", 0.5) }, function({g}) { return g.with_("singlelabel").E().elementMap() }],
@@ -1272,15 +1272,15 @@ const gremlins = {
g_V_valuesXnameX_lTrim: [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").proper [...]
g_V_valuesXnameX_order_fold_lTrimXlocalX: [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_V_hasLabelXpersonX_labels: [function({g}) { return g.V().hasLabel("person").labels() }],
- g_V_labels_multilabel: [function({g}) { return g.addV("a", "b") }, function({g}) { return g.V().labels() }],
+ g_V_labels_multilabel: [function({g}) { return g.V().has("name", "tux").labels() }],
g_addVXa_bX_labels_count: [function({g}) { return g.addV("a", "b") }, function({g}) { return g.V().labels().count() }],
g_addV_labels: [function({g}) { return g.addV() }, function({g}) { return g.V().labels() }],
g_E_labels: [function({g}) { return g.E().hasLabel("knows").labels() }],
g_V_hasLabelXpersonX_labels_single_label_graph: [function({g}) { return g.V().hasLabel("person").labels() }],
g_V_labels_single_label_graph: [function({g}) { return g.V().labels() }],
g_E_labels_single_label_graph: [function({g}) { return g.E().hasLabel("knows").labels() }],
- g_V_label_deprecated_multilabel: [function({g}) { return g.addV("a", "b").property("name", "test") }, function({g}) { return g.V().label().count() }],
- g_V_label_deprecated_multilabel_value_is_one_of_labels: [function({g}) { return g.addV("a", "b").property("name", "test") }, function({g}) { return g.V().filter(__.label().is(P.within("a", "b"))) }],
+ g_V_label_deprecated_multilabel: [function({g}) { return g.V().has("name", "tux").label().count() }],
+ g_V_label_deprecated_multilabel_value_is_one_of_labels: [function({g}) { return g.V().has("name", "tux").filter(__.label().is(P.within("animal", "bird", "aquatic", "endangered"))) }],
g_injectXfeature_test_nullX_length: [function({g}) { return g.inject("feature", "test", null).length() }],
g_injectXfeature_test_nullX_lengthXlocalX: [function({g}) { return g.inject("feature", "test", null).length(Scope.local) }],
g_injectXListXa_bXX_length: [function({g}) { return g.inject(["a", "b"]).length() }],
@@ -1860,9 +1860,9 @@ const gremlins = {
g_V_valueMapXname_ageX_byXisXxXXbyXunfoldX: [function({g}) { return g.V().valueMap("name", "age").by(__.is("x")).by(__.unfold()) }],
g_withXmultilabelX_VXmarkoX_valueMap_withXtokensX: [function({g}) { return g.with_("multilabel").V().has("name", "marko").valueMap().with_(WithOptions.tokens) }],
g_V_valueMap_withXtokensX_single_label_default: [function({g}) { return g.addV("person").addLabel("employee").property("name", "marko") }, function({g}) { return g.V().valueMap().with_(WithOptions.tokens) }],
- g_withXmultilabelX_V_valueMap_withXtokensX_multilabel: [function({g}) { return g.addV("person").addLabel("employee").property("name", "marko") }, function({g}) { return g.with_("multilabel").V().valueMap().with_(WithOptions.tokens) }],
+ g_withXmultilabelX_V_valueMap_withXtokensX_multilabel: [function({g}) { return g.with_("multilabel").V().has("name", "tux").valueMap("name", "species").with_(WithOptions.tokens) }],
g_V_valueMap_withXtokensX_multi_label_default: [function({g}) { return g.addV("person").addLabel("employee").property("name", "marko") }, function({g}) { return g.V().valueMap().with_(WithOptions.tokens) }],
- g_withXsinglelabelX_V_valueMap_withXtokensX_multi_label_default: [function({g}) { return g.addV("person").addLabel("employee").property("name", "marko") }, function({g}) { return g.with_("singlelabel").V().valueMap().with_(WithOptions.tokens) }],
+ g_withXsinglelabelX_V_valueMap_withXtokensX_multi_label_default: [function({g}) { return g.with_("singlelabel").V().has("name", "lagoon").valueMap("name", "biome").with_(WithOptions.tokens) }],
g_withXsinglelabelX_V_valueMapXtrueX_zero_label_vertex: [function({g}) { return g.addV().property("name", "nobody") }, function({g}) { return g.with_("singlelabel").V().valueMap(true) }],
g_withXmultilabelX_V_valueMapXtrueX_zero_label_vertex: [function({g}) { return g.addV().property("name", "nobody") }, function({g}) { return g.with_("multilabel").V().valueMap(true) }],
g_V_valueMapXtrueX_zero_label_vertex_multi_label_default: [function({g}) { return g.addV().property("name", "nobody") }, function({g}) { return g.V().valueMap(true) }],
diff --git a/gremlin-js/gremlin-javascript/test/cucumber/world.js b/gremlin-js/gremlin-javascript/test/cucumber/world.js
index 04d1125579..be25215efe 100644
--- a/gremlin-js/gremlin-javascript/test/cucumber/world.js
+++ b/gremlin-js/gremlin-javascript/test/cucumber/world.js
@@ -84,7 +84,7 @@ setWorldConstructor(TinkerPopWorld);
BeforeAll(function () {
// load all traversals
- const promises = ['modern', 'classic', 'crew', 'grateful', 'sink', 'empty', 'multilabel'].map(graphName => {
+ const promises = ['modern', 'classic', 'crew', 'grateful', 'sink', 'zoo', 'empty', 'multilabel'].map(graphName => {
let connection = null;
if (graphName === 'empty') {
connection = getConnection('ggraph');
diff --git a/gremlin-python/src/main/python/tests/feature/terrain.py b/gremlin-python/src/main/python/tests/feature/terrain.py
index 55489c7807..a5035879ea 100644
--- a/gremlin-python/src/main/python/tests/feature/terrain.py
+++ b/gremlin-python/src/main/python/tests/feature/terrain.py
@@ -42,7 +42,7 @@ def prepare_static_traversal_source(features, marker):
# as the various traversal sources for testing do not change their data, there is no need to re-create remotes
# and client side lookup data over and over. it can be created once for all tests and be reused.
cache = {}
- for graph_name in (("modern", "gmodern"), ("classic", "gclassic"), ("crew", "gcrew"), ("grateful", "ggrateful"), ("sink", "gsink")):
+ for graph_name in (("modern", "gmodern"), ("classic", "gclassic"), ("crew", "gcrew"), ("grateful", "ggrateful"), ("sink", "gsink"), ("zoo", "gzoo")):
cache[graph_name[0]] = {}
remote = __create_remote(graph_name[1])
cache[graph_name[0]]["remote_conn"] = __create_remote(graph_name[1])
@@ -62,7 +62,7 @@ def prepare_static_traversal_source(features, marker):
scenario.context.lookup_e = {}
scenario.context.lookup_vp = {}
- for graph_name in ("modern", "classic", "crew", "grateful", "sink"):
+ for graph_name in ("modern", "classic", "crew", "grateful", "sink", "zoo"):
scenario.context.remote_conn[graph_name] = cache[graph_name]["remote_conn"]
scenario.context.lookup_v[graph_name] = cache[graph_name]["lookup_v"]
scenario.context.lookup_e[graph_name] = cache[graph_name]["lookup_e"]
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/util/TinkerFactoryDataLoader.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/util/TinkerFactoryDataLoader.java
index a211d81426..3e01a887f4 100644
--- a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/util/TinkerFactoryDataLoader.java
+++ b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/util/TinkerFactoryDataLoader.java
@@ -31,7 +31,7 @@ import java.util.Map;
* <p>Configuration parameters (via {@code config} in YAML):
* <ul>
* <li>{@code graph} — name of the graph (as defined in {@code graphs:} config) to load data into</li>
- * <li>{@code dataset} — which dataset to load: modern, classic, crew, grateful, sink, airroutes</li>
+ * <li>{@code dataset} — which dataset to load: modern, classic, crew, grateful, sink, airroutes, zoo</li>
* </ul>
*
* <p>Example YAML usage:
@@ -88,6 +88,9 @@ public class TinkerFactoryDataLoader implements LifeCycleHook {
case "airroutes":
TinkerFactory.generateAirRoutes(tinkerGraph);
break;
+ case "zoo":
+ TinkerFactory.generateTheZoo(tinkerGraph);
+ break;
default:
c.getLogger().warn("TinkerFactoryDataLoader unknown dataset [{}]", dataset);
return;
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 8a19b4f3b7..972a753a5d 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
@@ -92,6 +92,9 @@ public abstract class RemoteWorld implements World {
case GRATEFUL:
remoteTraversalSource = "ggrateful";
break;
+ case ZOO:
+ remoteTraversalSource = "gzoo";
+ break;
default:
throw new UnsupportedOperationException("GraphData not supported: " + graphData.name());
}
diff --git a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/util/CheckedGraphManagerTest.java b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/util/CheckedGraphManagerTest.java
index 490ead1423..f440a3bd5a 100644
--- a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/util/CheckedGraphManagerTest.java
+++ b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/util/CheckedGraphManagerTest.java
@@ -66,7 +66,7 @@ public class CheckedGraphManagerTest {
public void justAGraphFails() {
settings.graphs.put("invalid", "conf/invalidPath");
final GraphManager manager = new CheckedGraphManager(settings);
- assertThat(manager.getGraphNames(), hasSize(8));
+ assertThat(manager.getGraphNames(), hasSize(9));
}
/**
diff --git a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/util/DefaultGraphManagerTest.java b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/util/DefaultGraphManagerTest.java
index 87af675779..b401b12e79 100644
--- a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/util/DefaultGraphManagerTest.java
+++ b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/util/DefaultGraphManagerTest.java
@@ -48,7 +48,7 @@ public class DefaultGraphManagerTest {
final Set<String> graphNames = graphManager.getGraphNames();
assertNotNull(graphNames);
- assertEquals(8, graphNames.size());
+ assertEquals(9, graphNames.size());
assertThat(graphNames.contains("graph"), is(true));
assertThat(graphNames.contains("classic"), is(true));
@@ -56,6 +56,7 @@ public class DefaultGraphManagerTest {
assertThat(graphNames.contains("crew"), is(true));
assertThat(graphNames.contains("sink"), is(true));
assertThat(graphNames.contains("grateful"), is(true));
+ assertThat(graphNames.contains("zoo"), is(true));
assertThat(graphNames.contains("tx"), is(true));
assertThat(graphManager.getGraph("graph"), instanceOf(TinkerGraph.class));
assertThat(graphManager.getGraph("tx"), instanceOf(TinkerTransactionGraph.class));
@@ -68,13 +69,14 @@ public class DefaultGraphManagerTest {
final Bindings bindings = graphManager.getAsBindings();
assertNotNull(bindings);
- assertEquals(8, bindings.size());
+ assertEquals(9, bindings.size());
assertThat(bindings.containsKey("graph"), is(true));
assertThat(bindings.containsKey("classic"), is(true));
assertThat(bindings.containsKey("modern"), is(true));
assertThat(bindings.containsKey("crew"), is(true));
assertThat(bindings.containsKey("sink"), is(true));
assertThat(bindings.containsKey("grateful"), is(true));
+ assertThat(bindings.containsKey("zoo"), is(true));
assertThat(bindings.containsKey("tx"), is(true));
assertThat(bindings.get("graph"), instanceOf(TinkerGraph.class));
assertThat(bindings.get("tx"), instanceOf(TinkerTransactionGraph.class));
@@ -99,7 +101,7 @@ public class DefaultGraphManagerTest {
final Set<String> graphNames = graphManager.getGraphNames();
assertNotNull(graphNames);
- assertEquals(9, graphNames.size());
+ assertEquals(10, graphNames.size());
assertThat(graphNames.contains("newGraph"), is(true));
assertThat(graphNames.contains("graph"), is(true));
assertThat(graphNames.contains("classic"), is(true));
@@ -107,6 +109,7 @@ public class DefaultGraphManagerTest {
assertThat(graphNames.contains("crew"), is(true));
assertThat(graphNames.contains("sink"), is(true));
assertThat(graphNames.contains("grateful"), is(true));
+ assertThat(graphNames.contains("zoo"), is(true));
assertThat(graphNames.contains("tx"), is(true));
assertThat(graphManager.getGraph("newGraph"), instanceOf(TinkerGraph.class));
assertThat(graphManager.getGraph("tx"), instanceOf(TinkerTransactionGraph.class));
@@ -120,14 +123,14 @@ public class DefaultGraphManagerTest {
graphManager.putGraph("newGraph", graph);
final Set<String> graphNames = graphManager.getGraphNames();
assertNotNull(graphNames);
- assertEquals(9, graphNames.size());
+ assertEquals(10, graphNames.size());
assertThat(graphNames.contains("newGraph"), is(true));
assertThat(graphManager.getGraph("newGraph"), instanceOf(TinkerGraph.class));
graphManager.removeGraph("newGraph");
final Set<String> graphNames2 = graphManager.getGraphNames();
- assertEquals(8, graphNames2.size());
+ assertEquals(9, graphNames2.size());
assertThat(graphNames2.contains("newGraph"), is(false));
}
diff --git a/gremlin-server/src/test/resources/org/apache/tinkerpop/gremlin/server/gremlin-server-integration.yaml b/gremlin-server/src/test/resources/org/apache/tinkerpop/gremlin/server/gremlin-server-integration.yaml
index 5e9a753eed..6e21e6a037 100644
--- a/gremlin-server/src/test/resources/org/apache/tinkerpop/gremlin/server/gremlin-server-integration.yaml
+++ b/gremlin-server/src/test/resources/org/apache/tinkerpop/gremlin/server/gremlin-server-integration.yaml
@@ -53,6 +53,9 @@ graphs: {
sink: {
configuration: conf/tinkergraph-empty.properties,
traversalSources: [{name: gsink}]},
+ zoo: {
+ configuration: conf/tinkergraph-multilabel.properties,
+ traversalSources: [{name: gzoo}]},
tx: {
configuration: conf/tinkertransactiongraph-empty.properties,
traversalSources: [{name: gtx}]}}
@@ -62,6 +65,7 @@ lifecycleHooks:
- { className: org.apache.tinkerpop.gremlin.server.util.TinkerFactoryDataLoader, config: {graph: crew, dataset: crew}}
- { className: org.apache.tinkerpop.gremlin.server.util.TinkerFactoryDataLoader, config: {graph: grateful, dataset: grateful}}
- { className: org.apache.tinkerpop.gremlin.server.util.TinkerFactoryDataLoader, config: {graph: sink, dataset: sink}}
+ - { className: org.apache.tinkerpop.gremlin.server.util.TinkerFactoryDataLoader, config: {graph: zoo, dataset: zoo}}
scriptEngines: {
gremlin-lang : {},
groovy-test: {},
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/LoadGraphWith.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/LoadGraphWith.java
index b11de7411b..5418dff87a 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/LoadGraphWith.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/LoadGraphWith.java
@@ -94,7 +94,13 @@ public @interface LoadGraphWith {
* Loads the air-routes graph, a real-world dataset of ~3,500 airports and ~50,000 routes suitable for
* benchmarking and integration testing of traversals that benefit from larger, denser graphs.
*/
- AIR_ROUTES;
+ AIR_ROUTES,
+
+ /**
+ * Loads "The Zoo" TinkerPop4 toy graph which showcases multi-label vertices and a variety of property
+ * types. Requires a graph configured with {@code LabelCardinality.ZERO_OR_MORE} (or {@code ONE_OR_MORE}).
+ */
+ ZOO;
private static final List<FeatureRequirement> featuresRequiredByClassic = new ArrayList<FeatureRequirement>() {{
add(FeatureRequirement.Factory.create(FEATURE_STRING_VALUES, VertexPropertyFeatures.class));
@@ -132,6 +138,14 @@ public @interface LoadGraphWith {
add(FeatureRequirement.Factory.create(FEATURE_INTEGER_VALUES, EdgePropertyFeatures.class));
}};
+ private static final List<FeatureRequirement> featuresRequiredByZoo = new ArrayList<FeatureRequirement>() {{
+ add(FeatureRequirement.Factory.create(FEATURE_STRING_VALUES, VertexPropertyFeatures.class));
+ add(FeatureRequirement.Factory.create(FEATURE_INTEGER_VALUES, VertexPropertyFeatures.class));
+ add(FeatureRequirement.Factory.create(FEATURE_DOUBLE_VALUES, VertexPropertyFeatures.class));
+ add(FeatureRequirement.Factory.create(FEATURE_BOOLEAN_VALUES, VertexPropertyFeatures.class));
+ add(FeatureRequirement.Factory.create(FEATURE_MULTI_PROPERTIES, Graph.Features.VertexFeatures.class));
+ }};
+
public String location() {
switch (this) {
case CLASSIC:
@@ -146,6 +160,8 @@ public @interface LoadGraphWith {
return RESOURCE_PATH_PREFIX + "tinkerpop-sink-v3.kryo";
case AIR_ROUTES:
return RESOURCE_PATH_PREFIX + "air-routes-v3.kryo";
+ case ZOO:
+ return RESOURCE_PATH_PREFIX + "tinkerpop-zoo-v3.kryo";
}
throw new RuntimeException("No file for this GraphData type");
@@ -165,6 +181,8 @@ public @interface LoadGraphWith {
return featuresRequiredBySink;
case AIR_ROUTES:
return featuresRequiredByAirRoutes;
+ case ZOO:
+ return featuresRequiredByZoo;
}
throw new RuntimeException("No features for this GraphData type");
diff --git a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/language/translator/translations.json b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/language/translator/translations.json
index b02dd7f067..3731a49316 100644
--- a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/language/translator/translations.json
+++ b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/language/translator/translations.json
@@ -23710,28 +23710,16 @@
"scenario": "g_withXmultilabelX_V_elementMap_multilabel",
"traversals": [
{
- "original": "g.addV(\"person\").addLabel(\"employee\").property(\"name\", \"marko\")",
- "language": "g.addV(\"person\").addLabel(\"employee\").property(\"name\", \"marko\")",
- "canonical": "g.addV(\"person\").addLabel(\"employee\").property(\"name\", \"marko\")",
- "anonymized": "g.addV(string0).addLabel(string1).property(string2, string3)",
- "dotnet": "g.AddV((string) \"person\").AddLabel(\"employee\").Property(\"name\", \"marko\")",
- "go": "g.AddV(\"person\").AddLabel(\"employee\").Property(\"name\", \"marko\")",
- "groovy": "g.addV(\"person\").addLabel(\"employee\").property(\"name\", \"marko\")",
- "java": "g.addV(\"person\").addLabel(\"employee\").property(\"name\", \"marko\")",
- "javascript": "g.addV(\"person\").addLabel(\"employee\").property(\"name\", \"marko\")",
- "python": "g.add_v('person').add_label('employee').property('name', 'marko')"
- },
- {
- "original": "g.with(\"multilabel\").V().elementMap()",
- "language": "g.with(\"multilabel\").V().elementMap()",
- "canonical": "g.with(\"multilabel\").V().elementMap()",
- "anonymized": "g.with(string0).V().elementMap()",
- "dotnet": "g.With(\"multilabel\").V().ElementMap<object>()",
- "go": "g.With(\"multilabel\").V().ElementMap()",
- "groovy": "g.with(\"multilabel\").V().elementMap()",
- "java": "g.with(\"multilabel\").V().elementMap()",
- "javascript": "g.with_(\"multilabel\").V().elementMap()",
- "python": "g.with_('multilabel').V().element_map()"
+ "original": "g.with(\"multilabel\").V().has(\"name\", \"tux\").elementMap(\"name\", \"species\")",
+ "language": "g.with(\"multilabel\").V().has(\"name\", \"tux\").elementMap(\"name\", \"species\")",
+ "canonical": "g.with(\"multilabel\").V().has(\"name\", \"tux\").elementMap(\"name\", \"species\")",
+ "anonymized": "g.with(string0).V().has(string1, string2).elementMap(string1, string3)",
+ "dotnet": "g.With(\"multilabel\").V().Has(\"name\", \"tux\").ElementMap<object>(\"name\", \"species\")",
+ "go": "g.With(\"multilabel\").V().Has(\"name\", \"tux\").ElementMap(\"name\", \"species\")",
+ "groovy": "g.with(\"multilabel\").V().has(\"name\", \"tux\").elementMap(\"name\", \"species\")",
+ "java": "g.with(\"multilabel\").V().has(\"name\", \"tux\").elementMap(\"name\", \"species\")",
+ "javascript": "g.with_(\"multilabel\").V().has(\"name\", \"tux\").elementMap(\"name\", \"species\")",
+ "python": "g.with_('multilabel').V().has('name', 'tux').element_map('name', 'species')"
}
]
},
@@ -23768,28 +23756,16 @@
"scenario": "g_withXsinglelabelX_V_elementMap_multi_label_default",
"traversals": [
{
- "original": "g.addV(\"person\").addLabel(\"employee\").property(\"name\", \"marko\")",
- "language": "g.addV(\"person\").addLabel(\"employee\").property(\"name\", \"marko\")",
- "canonical": "g.addV(\"person\").addLabel(\"employee\").property(\"name\", \"marko\")",
- "anonymized": "g.addV(string0).addLabel(string1).property(string2, string3)",
- "dotnet": "g.AddV((string) \"person\").AddLabel(\"employee\").Property(\"name\", \"marko\")",
- "go": "g.AddV(\"person\").AddLabel(\"employee\").Property(\"name\", \"marko\")",
- "groovy": "g.addV(\"person\").addLabel(\"employee\").property(\"name\", \"marko\")",
- "java": "g.addV(\"person\").addLabel(\"employee\").property(\"name\", \"marko\")",
- "javascript": "g.addV(\"person\").addLabel(\"employee\").property(\"name\", \"marko\")",
- "python": "g.add_v('person').add_label('employee').property('name', 'marko')"
- },
- {
- "original": "g.with(\"singlelabel\").V().elementMap()",
- "language": "g.with(\"singlelabel\").V().elementMap()",
- "canonical": "g.with(\"singlelabel\").V().elementMap()",
- "anonymized": "g.with(string0).V().elementMap()",
- "dotnet": "g.With(\"singlelabel\").V().ElementMap<object>()",
- "go": "g.With(\"singlelabel\").V().ElementMap()",
- "groovy": "g.with(\"singlelabel\").V().elementMap()",
- "java": "g.with(\"singlelabel\").V().elementMap()",
- "javascript": "g.with_(\"singlelabel\").V().elementMap()",
- "python": "g.with_('singlelabel').V().element_map()"
+ "original": "g.with(\"singlelabel\").V().has(\"name\", \"lagoon\").elementMap(\"name\", \"biome\")",
+ "language": "g.with(\"singlelabel\").V().has(\"name\", \"lagoon\").elementMap(\"name\", \"biome\")",
+ "canonical": "g.with(\"singlelabel\").V().has(\"name\", \"lagoon\").elementMap(\"name\", \"biome\")",
+ "anonymized": "g.with(string0).V().has(string1, string2).elementMap(string1, string3)",
+ "dotnet": "g.With(\"singlelabel\").V().Has(\"name\", \"lagoon\").ElementMap<object>(\"name\", \"biome\")",
+ "go": "g.With(\"singlelabel\").V().Has(\"name\", \"lagoon\").ElementMap(\"name\", \"biome\")",
+ "groovy": "g.with(\"singlelabel\").V().has(\"name\", \"lagoon\").elementMap(\"name\", \"biome\")",
+ "java": "g.with(\"singlelabel\").V().has(\"name\", \"lagoon\").elementMap(\"name\", \"biome\")",
+ "javascript": "g.with_(\"singlelabel\").V().has(\"name\", \"lagoon\").elementMap(\"name\", \"biome\")",
+ "python": "g.with_('singlelabel').V().has('name', 'lagoon').element_map('name', 'biome')"
}
]
},
@@ -23942,28 +23918,16 @@
"scenario": "g_withXmultilabelX_E_elementMap",
"traversals": [
{
- "original": "g.addV(\"person\").property(\"name\", \"marko\").as(\"a\").addV(\"person\").property(\"name\", \"josh\").as(\"b\").addE(\"knows\").from(\"a\").to(\"b\").property(\"weight\", 0.5)",
- "language": "g.addV(\"person\").property(\"name\", \"marko\").as(\"a\").addV(\"person\").property(\"name\", \"josh\").as(\"b\").addE(\"knows\").from(\"a\").to(\"b\").property(\"weight\", 0.5)",
- "canonical": "g.addV(\"person\").property(\"name\", \"marko\").as(\"a\").addV(\"person\").property(\"name\", \"josh\").as(\"b\").addE(\"knows\").from(\"a\").to(\"b\").property(\"weight\", 0.5)",
- "anonymized": "g.addV(string0).property(string1, string2).as(string3).addV(string0).property(string1, string4).as(string5).addE(string6).from(string3).to(string5).property(string7, number0)",
- "dotnet": "g.AddV((string) \"person\").Property(\"name\", \"marko\").As(\"a\").AddV((string) \"person\").Property(\"name\", \"josh\").As(\"b\").AddE((string) \"knows\").From(\"a\").To(\"b\").Property(\"weight\", 0.5)",
- "go": "g.AddV(\"person\").Property(\"name\", \"marko\").As(\"a\").AddV(\"person\").Property(\"name\", \"josh\").As(\"b\").AddE(\"knows\").From(\"a\").To(\"b\").Property(\"weight\", 0.5)",
- "groovy": "g.addV(\"person\").property(\"name\", \"marko\").as(\"a\").addV(\"person\").property(\"name\", \"josh\").as(\"b\").addE(\"knows\").from(\"a\").to(\"b\").property(\"weight\", 0.5)",
- "java": "g.addV(\"person\").property(\"name\", \"marko\").as(\"a\").addV(\"person\").property(\"name\", \"josh\").as(\"b\").addE(\"knows\").from(\"a\").to(\"b\").property(\"weight\", 0.5)",
- "javascript": "g.addV(\"person\").property(\"name\", \"marko\").as(\"a\").addV(\"person\").property(\"name\", \"josh\").as(\"b\").addE(\"knows\").from_(\"a\").to(\"b\").property(\"weight\", 0.5)",
- "python": "g.add_v('person').property('name', 'marko').as_('a').add_v('person').property('name', 'josh').as_('b').add_e('knows').from_('a').to('b').property('weight', 0.5)"
- },
- {
- "original": "g.with(\"multilabel\").E().elementMap()",
- "language": "g.with(\"multilabel\").E().elementMap()",
- "canonical": "g.with(\"multilabel\").E().elementMap()",
- "anonymized": "g.with(string0).E().elementMap()",
- "dotnet": "g.With(\"multilabel\").E().ElementMap<object>()",
- "go": "g.With(\"multilabel\").E().ElementMap()",
- "groovy": "g.with(\"multilabel\").E().elementMap()",
- "java": "g.with(\"multilabel\").E().elementMap()",
- "javascript": "g.with_(\"multilabel\").E().elementMap()",
- "python": "g.with_('multilabel').E().element_map()"
+ "original": "g.with(\"multilabel\").E().has(\"since\", 2018).hasLabel(\"livesIn\").elementMap()",
+ "language": "g.with(\"multilabel\").E().has(\"since\", 2018).hasLabel(\"livesIn\").elementMap()",
+ "canonical": "g.with(\"multilabel\").E().has(\"since\", 2018).hasLabel(\"livesIn\").elementMap()",
+ "anonymized": "g.with(string0).E().has(string1, number0).hasLabel(string2).elementMap()",
+ "dotnet": "g.With(\"multilabel\").E().Has(\"since\", 2018).HasLabel(\"livesIn\").ElementMap<object>()",
+ "go": "g.With(\"multilabel\").E().Has(\"since\", 2018).HasLabel(\"livesIn\").ElementMap()",
+ "groovy": "g.with(\"multilabel\").E().has(\"since\", 2018).hasLabel(\"livesIn\").elementMap()",
+ "java": "g.with(\"multilabel\").E().has(\"since\", 2018).hasLabel(\"livesIn\").elementMap()",
+ "javascript": "g.with_(\"multilabel\").E().has(\"since\", 2018).hasLabel(\"livesIn\").elementMap()",
+ "python": "g.with_('multilabel').E().has('since', 2018).has_label('livesIn').element_map()"
}
]
},
@@ -24949,28 +24913,16 @@
"scenario": "g_V_labels_multilabel",
"traversals": [
{
- "original": "g.addV(\"a\", \"b\")",
- "language": "g.addV(\"a\", \"b\")",
- "canonical": "g.addV(\"a\", \"b\")",
- "anonymized": "g.addV(string0, string1)",
- "dotnet": "g.AddV((string) \"a\", (string) \"b\")",
- "go": "g.AddV(\"a\", \"b\")",
- "groovy": "g.addV(\"a\", \"b\")",
- "java": "g.addV(\"a\", \"b\")",
- "javascript": "g.addV(\"a\", \"b\")",
- "python": "g.add_v('a', 'b')"
- },
- {
- "original": "g.V().labels()",
- "language": "g.V().labels()",
- "canonical": "g.V().labels()",
- "anonymized": "g.V().labels()",
- "dotnet": "g.V().Labels()",
- "go": "g.V().Labels()",
- "groovy": "g.V().labels()",
- "java": "g.V().labels()",
- "javascript": "g.V().labels()",
- "python": "g.V().labels()"
+ "original": "g.V().has(\"name\", \"tux\").labels()",
+ "language": "g.V().has(\"name\", \"tux\").labels()",
+ "canonical": "g.V().has(\"name\", \"tux\").labels()",
+ "anonymized": "g.V().has(string0, string1).labels()",
+ "dotnet": "g.V().Has(\"name\", \"tux\").Labels()",
+ "go": "g.V().Has(\"name\", \"tux\").Labels()",
+ "groovy": "g.V().has(\"name\", \"tux\").labels()",
+ "java": "g.V().has(\"name\", \"tux\").labels()",
+ "javascript": "g.V().has(\"name\", \"tux\").labels()",
+ "python": "g.V().has('name', 'tux').labels()"
}
]
},
@@ -25104,28 +25056,16 @@
"scenario": "g_V_label_deprecated_multilabel",
"traversals": [
{
- "original": "g.addV(\"a\", \"b\").property(\"name\", \"test\")",
- "language": "g.addV(\"a\", \"b\").property(\"name\", \"test\")",
- "canonical": "g.addV(\"a\", \"b\").property(\"name\", \"test\")",
- "anonymized": "g.addV(string0, string1).property(string2, string3)",
- "dotnet": "g.AddV((string) \"a\", (string) \"b\").Property(\"name\", \"test\")",
- "go": "g.AddV(\"a\", \"b\").Property(\"name\", \"test\")",
- "groovy": "g.addV(\"a\", \"b\").property(\"name\", \"test\")",
- "java": "g.addV(\"a\", \"b\").property(\"name\", \"test\")",
- "javascript": "g.addV(\"a\", \"b\").property(\"name\", \"test\")",
- "python": "g.add_v('a', 'b').property('name', 'test')"
- },
- {
- "original": "g.V().label().count()",
- "language": "g.V().label().count()",
- "canonical": "g.V().label().count()",
- "anonymized": "g.V().label().count()",
- "dotnet": "g.V().Label().Count()",
- "go": "g.V().Label().Count()",
- "groovy": "g.V().label().count()",
- "java": "g.V().label().count()",
- "javascript": "g.V().label().count()",
- "python": "g.V().label().count()"
+ "original": "g.V().has(\"name\", \"tux\").label().count()",
+ "language": "g.V().has(\"name\", \"tux\").label().count()",
+ "canonical": "g.V().has(\"name\", \"tux\").label().count()",
+ "anonymized": "g.V().has(string0, string1).label().count()",
+ "dotnet": "g.V().Has(\"name\", \"tux\").Label().Count()",
+ "go": "g.V().Has(\"name\", \"tux\").Label().Count()",
+ "groovy": "g.V().has(\"name\", \"tux\").label().count()",
+ "java": "g.V().has(\"name\", \"tux\").label().count()",
+ "javascript": "g.V().has(\"name\", \"tux\").label().count()",
+ "python": "g.V().has('name', 'tux').label().count()"
}
]
},
@@ -25133,28 +25073,16 @@
"scenario": "g_V_label_deprecated_multilabel_value_is_one_of_labels",
"traversals": [
{
- "original": "g.addV(\"a\", \"b\").property(\"name\", \"test\")",
- "language": "g.addV(\"a\", \"b\").property(\"name\", \"test\")",
- "canonical": "g.addV(\"a\", \"b\").property(\"name\", \"test\")",
- "anonymized": "g.addV(string0, string1).property(string2, string3)",
- "dotnet": "g.AddV((string) \"a\", (string) \"b\").Property(\"name\", \"test\")",
- "go": "g.AddV(\"a\", \"b\").Property(\"name\", \"test\")",
- "groovy": "g.addV(\"a\", \"b\").property(\"name\", \"test\")",
- "java": "g.addV(\"a\", \"b\").property(\"name\", \"test\")",
- "javascript": "g.addV(\"a\", \"b\").property(\"name\", \"test\")",
- "python": "g.add_v('a', 'b').property('name', 'test')"
- },
- {
- "original": "g.V().filter(__.label().is(P.within(\"a\", \"b\")))",
- "language": "g.V().filter(__.label().is(P.within(\"a\", \"b\")))",
- "canonical": "g.V().filter(__.label().is(P.within(\"a\", \"b\")))",
- "anonymized": "g.V().filter(__.label().is(P.within(string0, string1)))",
- "dotnet": "g.V().Filter(__.Label().Is(P.Within(\"a\", \"b\")))",
- "go": "g.V().Filter(gremlingo.T__.Label().Is(gremlingo.P.Within(\"a\", \"b\")))",
- "groovy": "g.V().filter(__.label().is(P.within(\"a\", \"b\")))",
- "java": "g.V().filter(__.label().is(P.within(\"a\", \"b\")))",
- "javascript": "g.V().filter(__.label().is(P.within(\"a\", \"b\")))",
- "python": "g.V().filter_(__.label().is_(P.within('a', 'b')))"
+ "original": "g.V().has(\"name\", \"tux\").filter(__.label().is(P.within(\"animal\", \"bird\", \"aquatic\", \"endangered\")))",
+ "language": "g.V().has(\"name\", \"tux\").filter(__.label().is(P.within(\"animal\", \"bird\", \"aquatic\", \"endangered\")))",
+ "canonical": "g.V().has(\"name\", \"tux\").filter(__.label().is(P.within(\"animal\", \"bird\", \"aquatic\", \"endangered\")))",
+ "anonymized": "g.V().has(string0, string1).filter(__.label().is(P.within(string2, string3, string4, string5)))",
+ "dotnet": "g.V().Has(\"name\", \"tux\").Filter(__.Label().Is(P.Within(\"animal\", \"bird\", \"aquatic\", \"endangered\")))",
+ "go": "g.V().Has(\"name\", \"tux\").Filter(gremlingo.T__.Label().Is(gremlingo.P.Within(\"animal\", \"bird\", \"aquatic\", \"endangered\")))",
+ "groovy": "g.V().has(\"name\", \"tux\").filter(__.label().is(P.within(\"animal\", \"bird\", \"aquatic\", \"endangered\")))",
+ "java": "g.V().has(\"name\", \"tux\").filter(__.label().is(P.within(\"animal\", \"bird\", \"aquatic\", \"endangered\")))",
+ "javascript": "g.V().has(\"name\", \"tux\").filter(__.label().is(P.within(\"animal\", \"bird\", \"aquatic\", \"endangered\")))",
+ "python": "g.V().has('name', 'tux').filter_(__.label().is_(P.within('animal', 'bird', 'aquatic', 'endangered')))"
}
]
},
@@ -39253,28 +39181,16 @@
"scenario": "g_withXmultilabelX_V_valueMap_withXtokensX_multilabel",
"traversals": [
{
- "original": "g.addV(\"person\").addLabel(\"employee\").property(\"name\", \"marko\")",
- "language": "g.addV(\"person\").addLabel(\"employee\").property(\"name\", \"marko\")",
- "canonical": "g.addV(\"person\").addLabel(\"employee\").property(\"name\", \"marko\")",
- "anonymized": "g.addV(string0).addLabel(string1).property(string2, string3)",
- "dotnet": "g.AddV((string) \"person\").AddLabel(\"employee\").Property(\"name\", \"marko\")",
- "go": "g.AddV(\"person\").AddLabel(\"employee\").Property(\"name\", \"marko\")",
- "groovy": "g.addV(\"person\").addLabel(\"employee\").property(\"name\", \"marko\")",
- "java": "g.addV(\"person\").addLabel(\"employee\").property(\"name\", \"marko\")",
- "javascript": "g.addV(\"person\").addLabel(\"employee\").property(\"name\", \"marko\")",
- "python": "g.add_v('person').add_label('employee').property('name', 'marko')"
- },
- {
- "original": "g.with(\"multilabel\").V().valueMap().with(WithOptions.tokens)",
- "language": "g.with(\"multilabel\").V().valueMap().with(WithOptions.tokens)",
- "canonical": "g.with(\"multilabel\").V().valueMap().with(WithOptions.tokens)",
- "anonymized": "g.with(string0).V().valueMap().with(WithOptions.tokens)",
- "dotnet": "g.With(\"multilabel\").V().ValueMap<object, object>().With(WithOptions.Tokens)",
- "go": "g.With(\"multilabel\").V().ValueMap().With(gremlingo.WithOptions.Tokens)",
- "groovy": "g.with(\"multilabel\").V().valueMap().with(WithOptions.tokens)",
- "java": "g.with(\"multilabel\").V().valueMap().with(WithOptions.tokens)",
- "javascript": "g.with_(\"multilabel\").V().valueMap().with_(WithOptions.tokens)",
- "python": "g.with_('multilabel').V().value_map().with_(WithOptions.tokens)"
+ "original": "g.with(\"multilabel\").V().has(\"name\", \"tux\").valueMap(\"name\", \"species\").with(WithOptions.tokens)",
+ "language": "g.with(\"multilabel\").V().has(\"name\", \"tux\").valueMap(\"name\", \"species\").with(WithOptions.tokens)",
+ "canonical": "g.with(\"multilabel\").V().has(\"name\", \"tux\").valueMap(\"name\", \"species\").with(WithOptions.tokens)",
+ "anonymized": "g.with(string0).V().has(string1, string2).valueMap(string1, string3).with(WithOptions.tokens)",
+ "dotnet": "g.With(\"multilabel\").V().Has(\"name\", \"tux\").ValueMap<object, object>(\"name\", \"species\").With(WithOptions.Tokens)",
+ "go": "g.With(\"multilabel\").V().Has(\"name\", \"tux\").ValueMap(\"name\", \"species\").With(gremlingo.WithOptions.Tokens)",
+ "groovy": "g.with(\"multilabel\").V().has(\"name\", \"tux\").valueMap(\"name\", \"species\").with(WithOptions.tokens)",
+ "java": "g.with(\"multilabel\").V().has(\"name\", \"tux\").valueMap(\"name\", \"species\").with(WithOptions.tokens)",
+ "javascript": "g.with_(\"multilabel\").V().has(\"name\", \"tux\").valueMap(\"name\", \"species\").with_(WithOptions.tokens)",
+ "python": "g.with_('multilabel').V().has('name', 'tux').value_map('name', 'species').with_(WithOptions.tokens)"
}
]
},
@@ -39311,28 +39227,16 @@
"scenario": "g_withXsinglelabelX_V_valueMap_withXtokensX_multi_label_default",
"traversals": [
{
- "original": "g.addV(\"person\").addLabel(\"employee\").property(\"name\", \"marko\")",
- "language": "g.addV(\"person\").addLabel(\"employee\").property(\"name\", \"marko\")",
- "canonical": "g.addV(\"person\").addLabel(\"employee\").property(\"name\", \"marko\")",
- "anonymized": "g.addV(string0).addLabel(string1).property(string2, string3)",
- "dotnet": "g.AddV((string) \"person\").AddLabel(\"employee\").Property(\"name\", \"marko\")",
- "go": "g.AddV(\"person\").AddLabel(\"employee\").Property(\"name\", \"marko\")",
- "groovy": "g.addV(\"person\").addLabel(\"employee\").property(\"name\", \"marko\")",
- "java": "g.addV(\"person\").addLabel(\"employee\").property(\"name\", \"marko\")",
- "javascript": "g.addV(\"person\").addLabel(\"employee\").property(\"name\", \"marko\")",
- "python": "g.add_v('person').add_label('employee').property('name', 'marko')"
- },
- {
- "original": "g.with(\"singlelabel\").V().valueMap().with(WithOptions.tokens)",
- "language": "g.with(\"singlelabel\").V().valueMap().with(WithOptions.tokens)",
- "canonical": "g.with(\"singlelabel\").V().valueMap().with(WithOptions.tokens)",
- "anonymized": "g.with(string0).V().valueMap().with(WithOptions.tokens)",
- "dotnet": "g.With(\"singlelabel\").V().ValueMap<object, object>().With(WithOptions.Tokens)",
- "go": "g.With(\"singlelabel\").V().ValueMap().With(gremlingo.WithOptions.Tokens)",
- "groovy": "g.with(\"singlelabel\").V().valueMap().with(WithOptions.tokens)",
- "java": "g.with(\"singlelabel\").V().valueMap().with(WithOptions.tokens)",
- "javascript": "g.with_(\"singlelabel\").V().valueMap().with_(WithOptions.tokens)",
- "python": "g.with_('singlelabel').V().value_map().with_(WithOptions.tokens)"
+ "original": "g.with(\"singlelabel\").V().has(\"name\", \"lagoon\").valueMap(\"name\", \"biome\").with(WithOptions.tokens)",
+ "language": "g.with(\"singlelabel\").V().has(\"name\", \"lagoon\").valueMap(\"name\", \"biome\").with(WithOptions.tokens)",
+ "canonical": "g.with(\"singlelabel\").V().has(\"name\", \"lagoon\").valueMap(\"name\", \"biome\").with(WithOptions.tokens)",
+ "anonymized": "g.with(string0).V().has(string1, string2).valueMap(string1, string3).with(WithOptions.tokens)",
+ "dotnet": "g.With(\"singlelabel\").V().Has(\"name\", \"lagoon\").ValueMap<object, object>(\"name\", \"biome\").With(WithOptions.Tokens)",
+ "go": "g.With(\"singlelabel\").V().Has(\"name\", \"lagoon\").ValueMap(\"name\", \"biome\").With(gremlingo.WithOptions.Tokens)",
+ "groovy": "g.with(\"singlelabel\").V().has(\"name\", \"lagoon\").valueMap(\"name\", \"biome\").with(WithOptions.tokens)",
+ "java": "g.with(\"singlelabel\").V().has(\"name\", \"lagoon\").valueMap(\"name\", \"biome\").with(WithOptions.tokens)",
+ "javascript": "g.with_(\"singlelabel\").V().has(\"name\", \"lagoon\").valueMap(\"name\", \"biome\").with_(WithOptions.tokens)",
+ "python": "g.with_('singlelabel').V().has('name', 'lagoon').value_map('name', 'biome').with_(WithOptions.tokens)"
}
]
},
diff --git a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/ElementMap.feature b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/ElementMap.feature
index 4cc80f1529..409fba71b1 100644
--- a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/ElementMap.feature
+++ b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/ElementMap.feature
@@ -110,19 +110,15 @@ Feature: Step - elementMap()
@MultiLabel
Scenario: g_withXmultilabelX_V_elementMap_multilabel
- Given the empty graph
- And the graph initializer of
- """
- g.addV("person").addLabel("employee").property("name", "marko")
- """
+ Given the zoo graph
And the traversal of
"""
- g.with("multilabel").V().elementMap()
+ g.with("multilabel").V().has("name", "tux").elementMap("name", "species")
"""
When iterated to list
Then the result should be unordered
| result |
- | m[{"t[id]": "v[marko].id", "t[label]": "s[person,employee]", "name": "marko"}] |
+ | m[{"t[id]": "v[tux].id", "t[label]": "s[animal,bird,aquatic,endangered]", "name": "tux", "species": "african penguin"}] |
@MultiLabel @MultiLabelDefault
Scenario: g_V_elementMap_multi_label_default
@@ -142,19 +138,17 @@ Feature: Step - elementMap()
@MultiLabel @MultiLabelDefault
Scenario: g_withXsinglelabelX_V_elementMap_multi_label_default
- Given the empty graph
- And the graph initializer of
- """
- g.addV("person").addLabel("employee").property("name", "marko")
- """
+ Given the zoo graph
And the traversal of
"""
- g.with("singlelabel").V().elementMap()
+ g.with("singlelabel").V().has("name", "lagoon").elementMap("name", "biome")
"""
When iterated to list
- Then the result should be unordered
+ Then the result should have a count of 1
+ And the result should be of
| result |
- | m[{"t[id]": "v[marko].id", "t[label]": "person", "name": "marko"}] |
+ | m[{"t[id]": "v[lagoon].id", "t[label]": "habitat", "name": "lagoon", "biome": "marine"}] |
+ | m[{"t[id]": "v[lagoon].id", "t[label]": "aquatic", "name": "lagoon", "biome": "marine"}] |
@MultiLabel @MultiLabelDefault
Scenario: g_V_elementMap_single_label_vertex_multi_label_default
@@ -236,21 +230,17 @@ Feature: Step - elementMap()
| result |
| m[{"t[id]": "v[nobody].id", "name": "nobody"}] |
- @MultiLabel
+ @GraphComputerVerificationReferenceOnly @MultiLabel
Scenario: g_withXmultilabelX_E_elementMap
- Given the empty graph
- And the graph initializer of
- """
- g.addV("person").property("name", "marko").as("a").addV("person").property("name", "josh").as("b").addE("knows").from("a").to("b").property("weight", 0.5)
- """
+ Given the zoo graph
And the traversal of
"""
- g.with("multilabel").E().elementMap()
+ g.with("multilabel").E().has("since", 2018).hasLabel("livesIn").elementMap()
"""
When iterated to list
Then the result should be unordered
| result |
- | m[{"t[id]": "e[marko-knows->josh].id", "t[label]": "s[knows]", "weight": "d[0.5].d", "D[OUT]": "m[{\\"t[id]\\": \\"v[marko].id\\", \\"t[label]\\": \\"s[person]\\"}]", "D[IN]": "m[{\\"t[id]\\": \\"v[josh].id\\", \\"t[label]\\": \\"s[person]\\"}]"}] |
+ | m[{"t[id]": "e[atlas-livesIn->lagoon].id", "t[label]": "s[livesIn]", "since": 2018, "D[OUT]": "m[{\\"t[id]\\": \\"v[atlas].id\\", \\"t[label]\\": \\"s[animal,reptile,aquatic,endangered]\\"}]", "D[IN]": "m[{\\"t[id]\\": \\"v[lagoon].id\\", \\"t[label]\\": \\"s[habitat,aquatic]\\"}]"}] |
@GraphComputerVerificationReferenceOnly @MultiLabel @MultiLabelDefault
Scenario: g_E_elementMap_multi_label_default
diff --git a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/Labels.feature b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/Labels.feature
index aeb21a3404..7598afa791 100644
--- a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/Labels.feature
+++ b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/Labels.feature
@@ -35,20 +35,18 @@ Feature: Step - labels()
@MultiLabel
Scenario: g_V_labels_multilabel
- Given the empty graph
- And the graph initializer of
- """
- g.addV("a", "b")
- """
+ Given the zoo graph
And the traversal of
"""
- g.V().labels()
+ g.V().has("name", "tux").labels()
"""
When iterated to list
Then the result should be unordered
| result |
- | a |
- | b |
+ | animal |
+ | bird |
+ | aquatic |
+ | endangered |
@MultiLabel
Scenario: g_addVXa_bX_labels_count
@@ -137,14 +135,10 @@ Feature: Step - labels()
@MultiLabel
Scenario: g_V_label_deprecated_multilabel
- Given the empty graph
- And the graph initializer of
- """
- g.addV("a", "b").property("name", "test")
- """
+ Given the zoo graph
And the traversal of
"""
- g.V().label().count()
+ g.V().has("name", "tux").label().count()
"""
When iterated to list
Then the result should be unordered
@@ -153,14 +147,10 @@ Feature: Step - labels()
@MultiLabel
Scenario: g_V_label_deprecated_multilabel_value_is_one_of_labels
- Given the empty graph
- And the graph initializer of
- """
- g.addV("a", "b").property("name", "test")
- """
+ Given the zoo graph
And the traversal of
"""
- g.V().filter(__.label().is(P.within("a", "b")))
+ g.V().has("name", "tux").filter(__.label().is(P.within("animal", "bird", "aquatic", "endangered")))
"""
When iterated to list
- Then the result should have a count of 1
\ No newline at end of file
+ Then the result should have a count of 1
diff --git a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/ValueMap.feature b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/ValueMap.feature
index 351254804e..698dc1d808 100644
--- a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/ValueMap.feature
+++ b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/ValueMap.feature
@@ -252,19 +252,15 @@ Feature: Step - valueMap()
@MultiLabel
Scenario: g_withXmultilabelX_V_valueMap_withXtokensX_multilabel
- Given the empty graph
- And the graph initializer of
- """
- g.addV("person").addLabel("employee").property("name", "marko")
- """
+ Given the zoo graph
And the traversal of
"""
- g.with("multilabel").V().valueMap().with(WithOptions.tokens)
+ g.with("multilabel").V().has("name", "tux").valueMap("name", "species").with(WithOptions.tokens)
"""
When iterated to list
Then the result should be unordered
| result |
- | m[{"t[id]": "v[marko].id", "t[label]": "s[person,employee]", "name": ["marko"]}] |
+ | m[{"t[id]": "v[tux].id", "t[label]": "s[animal,bird,aquatic,endangered]", "name": ["tux"], "species": ["african penguin"]}] |
@MultiLabel @MultiLabelDefault
Scenario: g_V_valueMap_withXtokensX_multi_label_default
@@ -284,19 +280,17 @@ Feature: Step - valueMap()
@MultiLabel @MultiLabelDefault
Scenario: g_withXsinglelabelX_V_valueMap_withXtokensX_multi_label_default
- Given the empty graph
- And the graph initializer of
- """
- g.addV("person").addLabel("employee").property("name", "marko")
- """
+ Given the zoo graph
And the traversal of
"""
- g.with("singlelabel").V().valueMap().with(WithOptions.tokens)
+ g.with("singlelabel").V().has("name", "lagoon").valueMap("name", "biome").with(WithOptions.tokens)
"""
When iterated to list
- Then the result should be unordered
+ Then the result should have a count of 1
+ And the result should be of
| result |
- | m[{"t[id]": "v[marko].id", "t[label]": "person", "name": ["marko"]}] |
+ | m[{"t[id]": "v[lagoon].id", "t[label]": "habitat", "name": ["lagoon"], "biome": ["marine"]}] |
+ | m[{"t[id]": "v[lagoon].id", "t[label]": "aquatic", "name": ["lagoon"], "biome": ["marine"]}] |
@MultiLabel
Scenario: g_withXsinglelabelX_V_valueMapXtrueX_zero_label_vertex
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 66d941bdcd..9a6cedf882 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
@@ -87,6 +87,7 @@ public abstract class TinkerWorld implements World {
private static final AbstractTinkerGraph crew = registerTestServices(TinkerFactory.createTheCrew());
private static final AbstractTinkerGraph sink = registerTestServices(TinkerFactory.createKitchenSink());
private static final AbstractTinkerGraph grateful = registerTestServices(TinkerFactory.createGratefulDead());
+ private static final AbstractTinkerGraph zoo = registerTestServices(TinkerFactory.createTheZoo());
@Override
public GraphTraversalSource getGraphTraversalSource(final LoadGraphWith.GraphData graphData) {
@@ -102,6 +103,8 @@ public abstract class TinkerWorld implements World {
return sink.traversal();
else if (graphData == LoadGraphWith.GraphData.GRATEFUL)
return grateful.traversal();
+ else if (graphData == LoadGraphWith.GraphData.ZOO)
+ return zoo.traversal();
else
throw new UnsupportedOperationException("GraphData not supported: " + graphData.name());
}
@@ -149,6 +152,7 @@ public abstract class TinkerWorld implements World {
private static final AbstractTinkerGraph crew;
private static final AbstractTinkerGraph sink;
private static final AbstractTinkerGraph grateful;
+ private static final AbstractTinkerGraph zoo;
static {
modern = TinkerTransactionGraph.open(getNumberIdManagerConfiguration());
@@ -175,6 +179,11 @@ public abstract class TinkerWorld implements World {
TinkerFactory.generateGratefulDead(grateful);
grateful.tx().commit();
registerTestServices(grateful);
+
+ zoo = TinkerTransactionGraph.open(getNumberIdManagerConfiguration());
+ TinkerFactory.generateTheZoo(zoo);
+ zoo.tx().commit();
+ registerTestServices(zoo);
}
@Override
@@ -191,6 +200,8 @@ public abstract class TinkerWorld implements World {
return sink.traversal();
else if (graphData == LoadGraphWith.GraphData.GRATEFUL)
return grateful.traversal();
+ else if (graphData == LoadGraphWith.GraphData.ZOO)
+ return zoo.traversal();
else
throw new UnsupportedOperationException("GraphData not supported: " + graphData.name());
}
@@ -229,6 +240,7 @@ public abstract class TinkerWorld implements World {
private static final TinkerGraph crew;
private static final TinkerGraph sink;
private static final TinkerGraph grateful;
+ private static final TinkerGraph zoo;
static {
modern = TinkerShuffleGraph.open();
@@ -246,6 +258,9 @@ public abstract class TinkerWorld implements World {
grateful = TinkerShuffleGraph.open();
TinkerFactory.generateGratefulDead(grateful);
registerTestServices(grateful);
+ zoo = TinkerShuffleGraph.open(getNumberIdManagerConfiguration());
+ TinkerFactory.generateTheZoo(zoo);
+ registerTestServices(zoo);
}
@Override
@@ -262,6 +277,8 @@ public abstract class TinkerWorld implements World {
return sink.traversal();
else if (graphData == LoadGraphWith.GraphData.GRATEFUL)
return grateful.traversal();
+ else if (graphData == LoadGraphWith.GraphData.ZOO)
+ return zoo.traversal();
else
throw new UnsupportedOperationException("GraphData not supported: " + graphData.name());
}
(tinkerpop) 02/03: Fix multi-label rendering gaps in ElementMapStep and ComputerGraph
Posted by co...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
Cole-Greer pushed a commit to branch multi-label-toy-graph
in repository https://gitbox.apache.org/repos/asf/tinkerpop.git
commit ad751d50d39ed44684fd55eb2b6c532ac73cefd1
Author: Cole Greer <co...@colegreer.ca>
AuthorDate: Mon Jul 6 12:59:57 2026 -0700
Fix multi-label rendering gaps in ElementMapStep and ComputerGraph
- ComputerElement.labels() previously inherited Element's default
implementation (Collections.singleton(label())) instead of delegating
to the wrapped element, silently losing multi-label data and returning
a nondeterministic single label under GraphComputer/OLAP execution.
- ElementMapStep.getVertexStructure() always rendered adjacent vertex
labels via the deprecated, nondeterministic label() regardless of
with("multilabel") mode, ignoring the same multilabel option that the
top-level element already respected. Corrected two scenarios in
ElementMap.feature whose expected values assumed the old behavior.
- gremlin-javascript's DotNetTranslateVisitor never unwrapped the
StringArgumentVarargsContext node introduced for multi-label addV(),
so generated .NET translations were missing the (string) cast that
the Java translator already applies; also fixed a labeled-alternative
method name mismatch that left visitTraversalSourceSpawnMethod_addV
as dead code (never dispatched by the ANTLR visitor).
Assisted-by: Claude Code:claude-sonnet-5
---
.../gremlin/process/computer/util/ComputerGraph.java | 5 +++++
.../gremlin/process/traversal/step/map/ElementMapStep.java | 9 ++++++++-
.../lib/language/translator/DotNetTranslateVisitor.ts | 13 ++++++++++++-
.../tinkerpop/gremlin/test/features/map/ElementMap.feature | 4 ++--
4 files changed, 27 insertions(+), 4 deletions(-)
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/util/ComputerGraph.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/util/ComputerGraph.java
index 5634cbbc09..1a302adaea 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/util/ComputerGraph.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/util/ComputerGraph.java
@@ -135,6 +135,11 @@ public final class ComputerGraph implements Graph {
return this.element.label();
}
+ @Override
+ public Set<String> labels() {
+ return this.element.labels();
+ }
+
@Override
public Graph graph() {
return ComputerGraph.this;
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ElementMapStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ElementMapStep.java
index a9566032e5..9eb0e05a21 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ElementMapStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ElementMapStep.java
@@ -97,7 +97,14 @@ public class ElementMapStep<K,E> extends ScalarMapStep<Element, Map<K, E>> imple
m.put(T.id, v.id());
// can't add label if doing GraphComputer stuff as there is no access to the label of the adjacent vertex
- if (!onGraphComputer) m.put(T.label, v.label());
+ if (!onGraphComputer) {
+ if (isMultilabelEnabled()) {
+ m.put(T.label, v.labels());
+ } else {
+ final String label = v.label();
+ if (!label.isEmpty()) m.put(T.label, label);
+ }
+ }
return m;
}
diff --git a/gremlin-js/gremlin-javascript/lib/language/translator/DotNetTranslateVisitor.ts b/gremlin-js/gremlin-javascript/lib/language/translator/DotNetTranslateVisitor.ts
index 8955acc5f4..fc22d85a01 100644
--- a/gremlin-js/gremlin-javascript/lib/language/translator/DotNetTranslateVisitor.ts
+++ b/gremlin-js/gremlin-javascript/lib/language/translator/DotNetTranslateVisitor.ts
@@ -359,6 +359,14 @@ export default class DotNetTranslateVisitor extends TranslateVisitor {
if (ctx?.variable() != null || ctx?.stringLiteral() != null) this.sb.push('(string) ');
}
+ private visitStringArgumentVarargsWithCast(ctx: any): void {
+ for (let ix = 0; ix < ctx.getChildCount(); ix++) {
+ const child = ctx.getChild(ix);
+ if (child.constructor?.name === 'StringArgumentContext') this.tryAppendCastToString_StringArg(child);
+ this.visit(child);
+ }
+ }
+
private tryAppendCastToString_StringNullableLit(ctx: any): void {
if (ctx?.K_NULL != null && ctx.K_NULL() != null) this.sb.push('(string) ');
}
@@ -421,11 +429,12 @@ export default class DotNetTranslateVisitor extends TranslateVisitor {
this.sb.push(')');
}
- visitTraversalSourceSpawnMethod_addV(ctx: any): void {
+ visitTraversalSourceSpawnMethod_addV_String(ctx: any): void {
this.sb.push(capitalize(ctx.getChild(0).getText()));
for (let ix = 1; ix < ctx.getChildCount(); ix++) {
const child = ctx.getChild(ix);
if (child.constructor?.name === 'StringArgumentContext') this.tryAppendCastToString_StringArg(child);
+ else if (child.constructor?.name === 'StringArgumentVarargsContext') { this.visitStringArgumentVarargsWithCast(child); continue; }
this.visit(child);
}
}
@@ -610,6 +619,7 @@ export default class DotNetTranslateVisitor extends TranslateVisitor {
for (let ix = 1; ix < ctx.getChildCount(); ix++) {
const child = ctx.getChild(ix);
if (child.constructor?.name === 'StringArgumentContext') this.tryAppendCastToString_StringArg(child);
+ else if (child.constructor?.name === 'StringArgumentVarargsContext') { this.visitStringArgumentVarargsWithCast(child); continue; }
this.visit(child);
}
}
@@ -619,6 +629,7 @@ export default class DotNetTranslateVisitor extends TranslateVisitor {
for (let ix = 1; ix < ctx.getChildCount(); ix++) {
const child = ctx.getChild(ix);
if (child.constructor?.name === 'StringArgumentContext') this.tryAppendCastToString_StringArg(child);
+ else if (child.constructor?.name === 'StringArgumentVarargsContext') { this.visitStringArgumentVarargsWithCast(child); continue; }
this.visit(child);
}
}
diff --git a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/ElementMap.feature b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/ElementMap.feature
index e5a746bf80..4cc80f1529 100644
--- a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/ElementMap.feature
+++ b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/ElementMap.feature
@@ -250,7 +250,7 @@ Feature: Step - elementMap()
When iterated to list
Then the result should be unordered
| result |
- | m[{"t[id]": "e[marko-knows->josh].id", "t[label]": "s[knows]", "weight": "d[0.5].d", "D[OUT]": "m[{\\"t[id]\\": \\"v[marko].id\\", \\"t[label]\\": \\"person\\"}]", "D[IN]": "m[{\\"t[id]\\": \\"v[josh].id\\", \\"t[label]\\": \\"person\\"}]"}] |
+ | m[{"t[id]": "e[marko-knows->josh].id", "t[label]": "s[knows]", "weight": "d[0.5].d", "D[OUT]": "m[{\\"t[id]\\": \\"v[marko].id\\", \\"t[label]\\": \\"s[person]\\"}]", "D[IN]": "m[{\\"t[id]\\": \\"v[josh].id\\", \\"t[label]\\": \\"s[person]\\"}]"}] |
@GraphComputerVerificationReferenceOnly @MultiLabel @MultiLabelDefault
Scenario: g_E_elementMap_multi_label_default
@@ -266,7 +266,7 @@ Feature: Step - elementMap()
When iterated to list
Then the result should be unordered
| result |
- | m[{"t[id]": "e[marko-knows->josh].id", "t[label]": "s[knows]", "weight": "d[0.5].d", "D[OUT]": "m[{\\"t[id]\\": \\"v[marko].id\\", \\"t[label]\\": \\"person\\"}]", "D[IN]": "m[{\\"t[id]\\": \\"v[josh].id\\", \\"t[label]\\": \\"person\\"}]"}] |
+ | m[{"t[id]": "e[marko-knows->josh].id", "t[label]": "s[knows]", "weight": "d[0.5].d", "D[OUT]": "m[{\\"t[id]\\": \\"v[marko].id\\", \\"t[label]\\": \\"s[person]\\"}]", "D[IN]": "m[{\\"t[id]\\": \\"v[josh].id\\", \\"t[label]\\": \\"s[person]\\"}]"}] |
@GraphComputerVerificationReferenceOnly @MultiLabel @SingleLabelDefault
Scenario: g_E_elementMap_single_label_default