You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tinkerpop.apache.org by "Cole-Greer (via GitHub)" <gi...@apache.org> on 2025/09/17 22:54:07 UTC
[PR] Fix TraversalParent implementations for Placeholder steps [tinkerpop]
Cole-Greer opened a new pull request, #3209:
URL: https://github.com/apache/tinkerpop/pull/3209
The TraversalParent methods were not consistently implemented in the new placeholder steps. This commit adds proper implementations in all TraversalParent placeholder steps, and introduces TraversalParentTest.
TraversalParentTest takes traversals with TraversalParents and verifies that getGlobalChildren() and getLocalChildren() are producing the expected children, and that those children have correctly set their parents. These checks are done before and after strategy application. This is primarily intended for placeholder steps to ensure that TraversalParent remains correctly implemented in both placeholder and concrete steps, however it is also useful to verify against interference from strategies.
The new tests identified an existing deficiency DateDiffStep which was also addressed.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@tinkerpop.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Fix TraversalParent implementations for Placeholder steps [tinkerpop]
Posted by "Cole-Greer (via GitHub)" <gi...@apache.org>.
Cole-Greer commented on code in PR #3209:
URL: https://github.com/apache/tinkerpop/pull/3209#discussion_r2373550949
##########
gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AbstractMergeElementStepPlaceholder.java:
##########
Review Comment:
In the context of mergeV/E, we currently never call `integrateChild` for the `properties`, and we we also never return any of the properties from `getLocalChildren`. The mergeV/E steps do not really consider the properties to be child traversals. The properties really only exist in mergeV/E to support `PartitionStrategy`, and it's arguably not the right way to do this. PartitionStrategy only ever stores String values in the properties too so there really should never be a Traversal here in practice.
The proper solution here is to introduce a dedicated interface such as `Partitioning` to support `PartitionStrategy`, and then get properties out of mergeV/E. I consider this out of scope for this PR, and for the meantime I'm happy with the current state here where although Traversal's may theoretically be possible in properties, they are not considered child traversals of this step.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@tinkerpop.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Fix TraversalParent implementations for Placeholder steps [tinkerpop]
Posted by "Cole-Greer (via GitHub)" <gi...@apache.org>.
Cole-Greer merged PR #3209:
URL: https://github.com/apache/tinkerpop/pull/3209
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@tinkerpop.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Fix TraversalParent implementations for Placeholder steps [tinkerpop]
Posted by "andreachild (via GitHub)" <gi...@apache.org>.
andreachild commented on code in PR #3209:
URL: https://github.com/apache/tinkerpop/pull/3209#discussion_r2377010041
##########
gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/TraversalParentTest.java:
##########
@@ -0,0 +1,1028 @@
+/*
+ * 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 java.time.OffsetDateTime;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.commons.configuration2.MapConfiguration;
+import org.apache.tinkerpop.gremlin.process.traversal.Operator;
+import org.apache.tinkerpop.gremlin.process.traversal.Pick;
+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.GraphTraversalSource;
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
+import org.apache.tinkerpop.gremlin.process.traversal.lambda.AbstractLambdaTraversal;
+import org.apache.tinkerpop.gremlin.process.traversal.lambda.ConstantTraversal;
+import org.apache.tinkerpop.gremlin.process.traversal.Merge;
+import org.apache.tinkerpop.gremlin.process.traversal.Scope;
+import org.apache.tinkerpop.gremlin.process.traversal.P;
+import org.apache.tinkerpop.gremlin.process.traversal.lambda.LoopTraversal;
+import org.apache.tinkerpop.gremlin.process.traversal.lambda.PredicateTraversal;
+import org.apache.tinkerpop.gremlin.process.traversal.lambda.TrueTraversal;
+import org.apache.tinkerpop.gremlin.process.traversal.lambda.ValueTraversal;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.AddEdgeStepContract;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.AddVertexStepContract;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.CallStepContract;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.MergeStepContract;
+import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.AddPropertyStepContract;
+import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.AggregateGlobalStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.AggregateLocalStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.filter.AndStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.filter.OrStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.branch.BranchStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.branch.ChooseStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.CoalesceStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.CombineStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.ConcatStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.DateDiffStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.filter.DedupGlobalStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.DifferenceStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.DisjunctStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.FormatStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.GroupCountStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.GroupCountSideEffectStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.GroupStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.IntersectStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.branch.LocalStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.MatchStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.MathStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.MergeStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.filter.NotStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.branch.OptionalStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.OrderGlobalStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.OrderLocalStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.filter.PathFilterStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.PathStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.ProductStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.ProjectStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.PropertyMapStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.branch.RepeatStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.SackValueStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.filter.SampleGlobalStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.SelectOneStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.SelectStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.TraversalSelectStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.filter.TraversalFilterStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.TraversalFlatMapStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.TraversalMapStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.TraversalSideEffectStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.TreeStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.TreeSideEffectStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.branch.UnionStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.filter.WherePredicateStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.filter.WhereTraversalStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.ComputerAwareStep;
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.GValueReductionStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper;
+import org.apache.tinkerpop.gremlin.structure.T;
+import org.apache.tinkerpop.gremlin.structure.service.Service;
+import org.apache.tinkerpop.gremlin.structure.service.ServiceRegistry;
+
+import org.apache.tinkerpop.gremlin.structure.util.GraphFactoryTest;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import static org.apache.tinkerpop.gremlin.process.traversal.AnonymousTraversalSource.traversal;
+import static org.hamcrest.Matchers.containsInAnyOrder;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+
+@RunWith(Parameterized.class)
+public class TraversalParentTest {
+
+ private static ServiceRegistry mockedRegistry= mock(ServiceRegistry.class);
+ private static Service<?, ?> mockedService = mock(Service.class);
+ private static GraphTraversalSource g = traversal().with(GraphFactoryTest.MockGraph.open(new MapConfiguration(Map.of("service-registry", mockedRegistry))));
+
+ @BeforeClass
+ public static void setupClass() {
+ when(mockedRegistry.get(any(), anyBoolean(), any())).thenReturn(mockedService);
+ when(mockedService.getRequirements()).thenReturn(Set.of());
+ }
+
+ @Parameterized.Parameter(value = 0)
+ public Class stepClass;
+
+ @Parameterized.Parameter(value = 1)
+ public Traversal.Admin traversal;
+
+ @Parameterized.Parameter(value = 2)
+ public List<Traversal.Admin<?,?>> expectedGlobalChildren;
+
+ @Parameterized.Parameter(value = 3)
+ public List<Traversal.Admin<?,?>> expectedLocalChildren;
+
+ /**
+ * Overrides expectedGlobalChildren for assertions following strategy execution. If left null, expectedGlobalChildren is used instead.
+ */
+ @Parameterized.Parameter(value = 4)
+ public List<Traversal.Admin<?,?>> postStrategyExpectedGlobalChildren;
+
+ /**
+ * Overrides expectedLocalChildren for assertions following strategy execution. If left null, expectedLocalChildren is used instead.
+ */
+ @Parameterized.Parameter(value = 5)
+ public List<Traversal.Admin<?,?>> postStrategyExpectedLocalChildren;
+
+ @Parameterized.Parameters(name = "{0}")
+ public static Iterable<Object[]> data() {
+ return Arrays.asList(new Object[][]{
+ {AddVertexStepContract.class,
+ g.addV("label").property("name", __.constant("cole")),
+ List.of(),
+ List.of(__.constant("cole"), new ConstantTraversal<>("label")),
+ null, null
+ },
+ {AddVertexStepContract.class,
+ g.addV(__.constant("label")).property("name", __.constant("cole")),
+ List.of(),
+ List.of(__.constant("cole"), __.constant("label")),
+ null, null
+ },
+ {AddVertexStepContract.class,
+ g.addV().property("name", __.constant("cole")).property(T.label, __.constant("label")).property(T.id, __.constant(1)),
+ List.of(),
+ List.of(__.constant("cole"), __.constant("label"), __.constant(1)),
+ null, null
+ },
+ {AddVertexStepContract.class,
+ g.addV(GValue.of("l", "label")).property("name", GValue.of("name", "cole")),
+ List.of(),
+ List.of(new ConstantTraversal<>("label")), // Property is not stored as a child traversal in this case
+ null, null
+ },
+ {AddVertexStepContract.class,
+ g.addV("label").property(__.constant("name"), __.constant("cole")),
+ List.of(),
+ List.of(__.constant("name"), __.constant("cole"), new ConstantTraversal<>("label")),
+ null, null
+ },
+ {AddVertexStepContract.class,
+ g.inject(1).addV("label").property("name", __.constant("cole")),
+ List.of(),
+ List.of(__.constant("cole"), new ConstantTraversal<>("label")),
+ null, null
+ },
+ {AddVertexStepContract.class,
+ g.inject(1).addV(__.constant("label")).property("name", __.constant("cole")),
+ List.of(),
+ List.of(__.constant("cole"), __.constant("label")),
+ null, null
+ },
+ {AddVertexStepContract.class,
+ g.inject(1).addV(GValue.of("l", "label")).property("name", GValue.of("name", "cole")),
+ List.of(),
+ List.of(new ConstantTraversal<>("label")), // Property is not stored as a child traversal in this case
+ null, null
+ },
+ {AddVertexStepContract.class,
+ g.inject(1).addV("label").property(__.constant("name"), __.constant("cole")),
+ List.of(),
+ List.of(__.constant("name"), __.constant("cole"), new ConstantTraversal<>("label")),
+ null, null
+ },
+ {AddEdgeStepContract.class,
+ g.addE("label").from(1).to(2).property("name", __.constant("cole")),
+ List.of(),
+ List.of(__.constant("cole"), new ConstantTraversal<>("label"), __.constant(1), __.constant(2)),
+ null, null
+ },
+ {AddEdgeStepContract.class,
+ g.addE("label").from(__.V(1)).to(__.V(2))
+ .property("name", __.constant("cole"))
+ .property(T.id, __.constant(5)),
+ List.of(),
+ List.of(__.constant("cole"), new ConstantTraversal<>("label"), __.V(1), __.V(2), __.constant(5)),
+ null, null
+ },
+ {AddEdgeStepContract.class,
+ g.addE("label").from(__.V(1)).to(__.V(2)).property("name", __.constant("cole")),
+ List.of(),
+ List.of(__.constant("cole"), new ConstantTraversal<>("label"), __.V(1), __.V(2)),
+ null, null
+ },
+ {AddEdgeStepContract.class,
+ g.addE(GValue.of("l", "label")).from(GValue.of("from", 1)).to(GValue.of("to", 2)).property("name", GValue.of("name", "cole")),
+ List.of(),
+ List.of(new ConstantTraversal<>("label"), new ConstantTraversal(1), new ConstantTraversal(2)),
+ null, null
+ },
+ {AddEdgeStepContract.class,
+ g.addE("label").from(1).to(2).property(__.constant("name"), __.constant("cole")),
+ List.of(),
+ List.of(__.constant("name"), __.constant("cole"), new ConstantTraversal<>("label"), __.constant(1), __.constant(2)),
+ null, null
+ },
+ {AddEdgeStepContract.class,
+ g.inject(1).addE("label").from(1).to(2).property("name", __.constant("cole")),
+ List.of(),
+ List.of(__.constant("cole"), new ConstantTraversal<>("label"), __.constant(1), __.constant(2)),
+ null, null
+ },
+ {AddEdgeStepContract.class,
+ g.inject(1).addE("label").from(__.V(1)).to(__.V(2)).property("name", __.constant("cole")),
+ List.of(),
+ List.of(__.constant("cole"), new ConstantTraversal<>("label"), __.V(1), __.V(2)),
+ null, null
+ },
+ {AddEdgeStepContract.class,
+ g.inject(1).addE(GValue.of("l", "label")).from(GValue.of("from", 1)).to(GValue.of("to", 2)).property("name", GValue.of("name", "cole")),
+ List.of(),
+ List.of(new ConstantTraversal<>("label"), new ConstantTraversal(1), new ConstantTraversal(2)),
+ null, null
+ },
+ {AddEdgeStepContract.class,
+ g.inject(1).addE("label").from(1).to(2).property(__.constant("name"), __.constant("cole")),
+ List.of(),
+ List.of(__.constant("name"), __.constant("cole"), new ConstantTraversal<>("label"), __.constant(1), __.constant(2)),
+ null, null
+ },
+ {CallStepContract.class,
+ g.call("service"),
+ List.of(),
+ List.of(),
+ null, null
+ },
+ {CallStepContract.class,
+ g.call("service").with("key", __.constant("value")),
+ List.of(),
+ List.of(__.constant("value")),
+ null, null
+ },
+ {CallStepContract.class,
+ g.call("service", __.constant(Map.of("key", "value"))),
+ List.of(),
+ List.of(__.constant(Map.of("key", "value"))),
+ null, null
+ },
+ {CallStepContract.class,
+ g.call("service", __.constant(Map.of("key", "value"))).with("key", __.constant("value")),
+ List.of(),
+ List.of(__.constant(Map.of("key", "value")), __.constant("value")),
+ null, null
+ },
+ {AddPropertyStepContract.class,
+ g.inject(1).property("key", "value"),
+ List.of(),
+ List.of(new ConstantTraversal<>("value")), // constant Value's are internally boxed in Traversals
+ null, null
+ },
+ {AddPropertyStepContract.class,
+ g.inject(1).property("key", __.constant("value")),
+ List.of(),
+ List.of(__.constant("value")),
+ null, null
+ },
+ {AddPropertyStepContract.class,
+ g.inject(1).property(__.constant("key"), __.constant("value")),
+ List.of(),
+ List.of(__.constant("key"), __.constant("value")),
+ null, null
+ },
+ {AddPropertyStepContract.class,
+ g.addV().property("name", "value", "metaKey", "metaValue"),
+ List.of(),
+ List.of(new ConstantTraversal<>("value")), // constant Value's are internally boxed in Traversals
+ null, null
+ },
+ {AddPropertyStepContract.class,
+ g.addV().property("name", __.constant("value"), "metaKey", __.constant("metaValue")),
+ List.of(),
+ List.of(__.constant("value"), __.constant("metaValue")),
+ null, null
+ },
+ {AddPropertyStepContract.class,
+ g.addV().property(__.constant("name"), __.constant("value"), __.constant("metaKey"), __.constant("metaValue")),
+ List.of(),
+ List.of(__.constant("name"), __.constant("value"), __.constant("metaKey"), __.constant("metaValue")),
+ null, null
+ },
+ {AddPropertyStepContract.class,
+ g.addV().property("name", "value", "metaKey1", "metaValue1", "metaKey2", "metaValue2"),
+ List.of(),
+ List.of(new ConstantTraversal<>("value")), // constant Value's are internally boxed in Traversals
+ null, null
+ },
+ {MergeStepContract.class,
+ g.mergeV(Map.of("name", "marko")),
+ List.of(),
+ List.of(new ConstantTraversal<>(Map.of("name", "marko"))), // constant MergeMap's are internally boxed in Traversals
+ null, null
+ },
+ {MergeStepContract.class,
+ g.mergeV(__.constant(Map.of("name", "marko"))),
+ List.of(),
+ List.of(__.constant(Map.of("name", "marko"))),
+ null, null
+ },
+ {MergeStepContract.class,
+ g.mergeV(Map.of("name", "marko")).option(Merge.onCreate, __.constant(Map.of("age", 29))),
+ List.of(),
+ List.of(new ConstantTraversal<>(Map.of("name", "marko")), __.constant(Map.of("age", 29))), // constant MergeMap's are internally boxed in Traversals
+ null, null
+ },
+ {MergeStepContract.class,
+ g.mergeV(__.constant(Map.of("name", "marko"))).option(Merge.onCreate, __.constant(Map.of("age", 29))).option(Merge.onMatch, __.constant(Map.of("updated", true))),
+ List.of(),
+ List.of(__.constant(Map.of("name", "marko")), __.constant(Map.of("age", 29)), __.constant(Map.of("updated", true))),
+ null, null
+ },
+ {MergeStepContract.class,
+ g.mergeE(Map.of(T.label, "knows")),
+ List.of(),
+ List.of(new ConstantTraversal<>(Map.of(T.label, "knows"))), // constant MergeMap's are internally boxed in Traversals
+ null, null
+ },
+ {MergeStepContract.class,
+ g.mergeE(__.constant(Map.of(T.label, "knows"))),
+ List.of(),
+ List.of(__.constant(Map.of(T.label, "knows"))),
+ null, null
+ },
+ {MergeStepContract.class,
+ g.mergeE(Map.of(T.label, "knows")).option(Merge.onCreate, __.constant(Map.of("weight", 0.5))),
+ List.of(),
+ List.of(new ConstantTraversal<>(Map.of(T.label, "knows")), __.constant(Map.of("weight", 0.5))), // constant MergeMap's are internally boxed in Traversals
+ null, null
+ },
+ {MergeStepContract.class,
+ g.mergeE(__.constant(Map.of(T.label, "knows"))).option(Merge.onCreate, __.constant(Map.of("weight", 0.5))).option(Merge.onMatch, __.constant(Map.of("updated", true))),
+ List.of(),
+ List.of(__.constant(Map.of(T.label, "knows")), __.constant(Map.of("weight", 0.5)), __.constant(Map.of("updated", true))),
+ null, null
+ },
+ {AggregateGlobalStep.class,
+ g.V().aggregate("x"),
+ List.of(),
+ List.of(),
+ null, null
+ },
+ {AggregateGlobalStep.class,
+ g.V().aggregate("x").by("name"),
+ List.of(),
+ List.of(new ValueTraversal("name")),
+ null, null
+ },
+ {AggregateGlobalStep.class,
+ g.V().aggregate("x").by(__.constant("value")),
+ List.of(),
+ List.of(__.constant("value")),
+ null, null
+ },
+ {AggregateLocalStep.class,
+ g.V().aggregate(Scope.local, "x"),
+ List.of(),
+ List.of(),
+ null, null
+ },
+ {AggregateLocalStep.class,
+ g.V().aggregate(Scope.local, "x").by("name"),
+ List.of(),
+ List.of(new ValueTraversal("name")),
+ null, null
+ },
+ {AggregateLocalStep.class,
+ g.V().aggregate(Scope.local, "x").by(__.constant("value")),
+ List.of(),
+ List.of(__.constant("value")),
+ null, null
+ },
+ {AndStep.class,
+ g.V().and(__.outE(), __.has("age", P.gte(32))),
+ List.of(),
+ List.of(__.outE(), __.has("age", P.gte(32))),
+ null, null
+ },
+ {OrStep.class,
+ g.V().or(__.outE(), __.has("age", P.gte(32))),
+ List.of(),
+ List.of(__.outE(), __.has("age", P.gte(32))),
+ null, null
+ },
+ {BranchStep.class,
+ g.V().branch(__.label()).option("person", __.values("name")).option("software", __.values("lang")),
+ List.of(appendComputerAwareEndStep(__.values("name")), appendComputerAwareEndStep(__.values("lang"))),
+ List.of(__.label(), new PredicateTraversal<>(P.eq("person")), new PredicateTraversal<>(P.eq("software"))), // option keys are wrapped in PredicateTraversals internally
+ null, null
+ },
+ {ChooseStep.class,
+ g.V().choose(__.out().count()).option(2L, __.values("name")).option(3L, __.values("age")),
+ List.of(appendComputerAwareEndStep(__.values("name")), appendComputerAwareEndStep(__.values("age")), appendComputerAwareEndStep(__.identity()), appendComputerAwareEndStep(__.identity())),
+ List.of(__.out().count(), new PredicateTraversal<>(P.eq(2L)), new PredicateTraversal<>(P.eq(3L))), // option keys are wrapped in PredicateTraversals internally
+ null, List.of(__.outE().count(), new PredicateTraversal<>(P.eq(2L)), new PredicateTraversal<>(P.eq(3L)))
+ },
+ {CoalesceStep.class,
+ g.V().coalesce(__.out("knows"), __.out("created")),
+ List.of(),
+ List.of(__.out("knows"), __.out("created")),
+ null, null
+ },
+ {CombineStep.class,
+ g.V().fold().combine(__.constant(List.of(1, 2, 3))),
+ List.of(),
+ List.of(__.constant(List.of(1, 2, 3))),
+ null, null
+ },
+ {ConcatStep.class,
+ g.inject("a", "b").concat(__.constant("c"), __.constant("d")),
+ List.of(),
+ List.of(__.constant("c"), __.constant("d")),
+ null, null
+ },
+ {DateDiffStep.class,
+ g.inject(OffsetDateTime.parse("1970-01-01T00:00:00.000Z")).dateDiff(__.constant(OffsetDateTime.parse("1970-02-01T00:00:00.000Z"))),
+ List.of(),
+ List.of(__.constant(OffsetDateTime.parse("1970-02-01T00:00:00.000Z"))),
+ null, null
+ },
+ {DedupGlobalStep.class,
+ g.V().dedup(),
+ List.of(),
+ List.of(),
+ null, null
+ },
+ {DedupGlobalStep.class,
+ g.V().dedup().by("name"),
+ List.of(),
+ List.of(new ValueTraversal("name")),
+ null, null
+ },
+ {DedupGlobalStep.class,
+ g.V().dedup().by(__.constant("value")),
+ List.of(),
+ List.of(__.constant("value")),
+ null, null
+ },
+ {DifferenceStep.class,
+ g.V().fold().difference(__.constant(List.of(1, 2, 3))),
+ List.of(),
+ List.of(__.constant(List.of(1, 2, 3))),
+ null, null
+ },
+ {DisjunctStep.class,
+ g.V().fold().disjunct(__.constant(List.of(1, 2, 3))),
+ List.of(),
+ List.of(__.constant(List.of(1, 2, 3))),
+ null, null
+ },
+ {FormatStep.class,
+ g.V().format("Hello %{name}"),
+ List.of(),
+ List.of(),
+ null, null
+ },
+ {FormatStep.class,
+ g.V().format("Hello %{name}").by("name"),
+ List.of(),
+ List.of(new ValueTraversal("name")),
+ null, null
+ },
+ {FormatStep.class,
+ g.V().format("Hello %{name}").by(__.constant("value")),
+ List.of(),
+ List.of(__.constant("value")),
+ null, null
+ },
+ {GroupCountStep.class,
+ g.V().groupCount(),
+ List.of(),
+ List.of(),
+ null, null
+ },
+ {GroupCountStep.class,
+ g.V().groupCount().by("name"),
+ List.of(),
+ List.of(new ValueTraversal("name")),
+ null, null
+ },
+ {GroupCountStep.class,
+ g.V().groupCount().by(__.constant("value")),
+ List.of(),
+ List.of(__.constant("value")),
+ null, null
+ },
+ {GroupCountSideEffectStep.class,
+ g.V().groupCount("x"),
+ List.of(),
+ List.of(),
+ null, null
+ },
+ {GroupCountSideEffectStep.class,
+ g.V().groupCount("x").by("name"),
+ List.of(),
+ List.of(new ValueTraversal("name")),
+ null, null
+ },
+ {GroupCountSideEffectStep.class,
+ g.V().groupCount("x").by(__.constant("value")),
+ List.of(),
+ List.of(__.constant("value")),
+ null, null
+ },
+ {GroupStep.class,
+ g.V().group(),
+ List.of(),
+ List.of(__.fold()),
+ null, null
+ },
+ {GroupStep.class,
+ g.V().group().by("name"),
+ List.of(),
+ List.of(new ValueTraversal("name"), __.fold()),
+ null, null
+ },
+ {GroupStep.class,
+ g.V().group().by("name").by("age"),
+ List.of(),
+ List.of(new ValueTraversal("name"), __.map(new ValueTraversal("age")).fold()),
+ null, null
+ },
+ {GroupStep.class,
+ g.V().group().by(__.constant("key")).by(__.constant("value")),
+ List.of(),
+ List.of(__.constant("key"), __.constant("value")),
+ null, null
+ },
+ {IntersectStep.class,
+ g.V().fold().intersect(__.constant(List.of(1, 2, 3))),
+ List.of(),
+ List.of(__.constant(List.of(1, 2, 3))),
+ null, null
+ },
+ {LocalStep.class,
+ g.V().local(__.outE().count()),
+ List.of(),
+ List.of(__.outE().count()),
+ null, null
+ },
+ {MatchStep.class,
+ g.V().match(__.as("a").out().as("b"), __.as("b").in().as("c")),
+ List.of(generateMatchChildTraversal("a", "b", __.out().asAdmin()), generateMatchChildTraversal("b", "c", __.in().asAdmin())),
+ List.of(),
+ null, null
+ },
+ {MathStep.class,
+ g.V().math("_ + 1"),
+ List.of(),
+ List.of(),
+ null, null
+ },
+ {MathStep.class,
+ g.V().math("_ + 1").by("age"),
+ List.of(),
+ List.of(new ValueTraversal("age")),
+ null, null
+ },
+ {MathStep.class,
+ g.V().math("_ + _").by("age").by(__.constant(10)),
+ List.of(),
+ List.of(new ValueTraversal("age"), __.constant(10)),
+ null, null
+ },
+ {MergeStep.class,
+ g.V().fold().merge(__.constant(List.of(1, 2, 3))),
+ List.of(),
+ List.of(__.constant(List.of(1, 2, 3))),
+ null, null
+ },
+ {NotStep.class,
+ g.V().not(__.has("age", P.gt(27))),
+ List.of(),
+ List.of(__.has("age", P.gt(27))),
+ null, null
+ },
+ {OptionalStep.class,
+ g.V().optional(__.out("knows")),
+ List.of(),
+ List.of(__.out("knows")),
+ null, null
+ },
+ {OrderGlobalStep.class,
+ g.V().order(),
+ List.of(),
+ List.of(),
+ null, null
+ },
+ {OrderGlobalStep.class,
+ g.V().order().by("name"),
+ List.of(),
+ List.of(new ValueTraversal("name")),
+ null, null
+ },
+ {OrderGlobalStep.class,
+ g.V().order().by("name").by(__.constant("value")),
+ List.of(),
+ List.of(new ValueTraversal("name"), __.constant("value")),
+ null, null
+ },
+ {OrderLocalStep.class,
+ g.V().fold().order(Scope.local),
+ List.of(),
+ List.of(),
+ null, null
+ },
+ {OrderLocalStep.class,
+ g.V().fold().order(Scope.local).by("name"),
+ List.of(),
+ List.of(new ValueTraversal("name")),
+ null, null
+ },
+ {OrderLocalStep.class,
+ g.V().fold().order(Scope.local).by(__.constant("value")),
+ List.of(),
+ List.of(__.constant("value")),
+ null, null
+ },
+ {PathFilterStep.class,
+ g.V().simplePath(),
+ List.of(),
+ List.of(),
+ null, null
+ },
+ {PathFilterStep.class,
+ g.V().cyclicPath(),
+ List.of(),
+ List.of(),
+ null, null
+ },
+ {PathFilterStep.class,
+ g.V().simplePath().by("name"),
+ List.of(),
+ List.of(new ValueTraversal("name")),
+ null, null
+ },
+ {PathFilterStep.class,
+ g.V().simplePath().by(__.constant("value")),
+ List.of(),
+ List.of(__.constant("value")),
+ null, null
+ },
+ {PathFilterStep.class,
+ g.V().cyclicPath().by("age").by(__.constant("value")),
+ List.of(),
+ List.of(new ValueTraversal("age"), __.constant("value")),
+ null, null
+ },
+ {PathStep.class,
+ g.V().path(),
+ List.of(),
+ List.of(),
+ null, null
+ },
+ {PathStep.class,
+ g.V().out().path().by("age").by("name"),
+ List.of(),
+ List.of(new ValueTraversal("age"), new ValueTraversal("name")),
+ null, null
+ },
+ {PathStep.class,
+ g.V().path().by(__.constant("value")),
+ List.of(),
+ List.of(__.constant("value")),
+ null, null
+ },
+ {ProductStep.class,
+ g.V().fold().product(__.constant(List.of(1, 2, 3))),
+ List.of(),
+ List.of(__.constant(List.of(1, 2, 3))),
+ null, null
+ },
+ {ProjectStep.class,
+ g.V().project("a", "b").by("name").by("age"),
+ List.of(),
+ List.of(new ValueTraversal("name"), new ValueTraversal("age")),
+ null, null
+ },
+ {ProjectStep.class,
+ g.V().project("x").by(__.constant("value")),
+ List.of(),
+ List.of(__.constant("value")),
+ null, null
+ },
+ {PropertyMapStep.class,
+ g.V().valueMap(),
+ List.of(),
+ List.of(),
+ null, null
+ },
+ {PropertyMapStep.class,
+ g.V().valueMap().by(__.constant("transformed")),
+ List.of(),
+ List.of(__.constant("transformed")),
+ null, null
+ },
+ {RepeatStep.class,
+ g.V().repeat(__.out()).emit().times(2),
+ List.of(appendRepeatEndStep(__.out())),
+ List.of(new LoopTraversal<>(2), TrueTraversal.instance()),
+ null, null
+ },
+ {RepeatStep.class,
+ g.V().repeat(__.out()).until(__.has("name", "josh")),
+ List.of(appendRepeatEndStep(__.out())),
+ List.of(__.has("name", "josh")),
+ null, null
+ },
+ {RepeatStep.class,
+ g.V().repeat(__.out()).emit(__.has("age")).until(__.has("name", "josh")),
+ List.of(appendRepeatEndStep(__.out())),
+ List.of(__.has("name", "josh"), __.has("age")),
+ null, List.of(__.has("name", "josh"), __.filter(__.properties("age"))),
+ },
+ {SackValueStep.class,
+ g.withSack(0).V().sack(Operator.sum),
+ List.of(),
+ List.of(),
+ null, null
+ },
+ {SackValueStep.class,
+ g.withSack(0).V().sack(Operator.sum).by("age"),
+ List.of(),
+ List.of(new ValueTraversal("age")),
+ null, null
+ },
+ {SackValueStep.class,
+ g.withSack(0).V().sack(Operator.sum).by(__.constant("age")),
+ List.of(),
+ List.of(__.constant("age")),
+ null, null
+ },
+ {SampleGlobalStep.class,
+ g.V().sample(2),
+ List.of(),
+ List.of(new ConstantTraversal<>(1.0)),
+ null, null
+ },
+ {SampleGlobalStep.class,
+ g.E().sample(2).by("weight"),
+ List.of(),
+ List.of(new ValueTraversal("weight")),
+ null, null
+ },
+ {SampleGlobalStep.class,
+ g.E().sample(2).by(__.constant("weight")),
+ List.of(),
+ List.of(__.constant("weight")),
+ null, null
+ },
+ {SelectOneStep.class,
+ g.V().as("a").select("a"),
+ List.of(),
+ List.of(),
+ null, null
+ },
+ {SelectOneStep.class,
+ g.V().as("a").select("a").by("name"),
+ List.of(),
+ List.of(new ValueTraversal("name")),
+ null, null
+ },
+ {SelectOneStep.class,
+ g.V().as("a").select("a").by(__.constant("value")),
+ List.of(),
+ List.of(__.constant("value")),
+ null, null
+ },
+ {SelectStep.class,
+ g.V().as("a").as("b").select("a", "b"),
+ List.of(),
+ List.of(),
+ null, null
+ },
+ {SelectStep.class,
+ g.V().as("a").as("b").select("a", "b").by("name"),
+ List.of(),
+ List.of(new ValueTraversal("name")),
+ null, null
+ },
+ {SelectStep.class,
+ g.V().as("a").as("b").select("a", "b").by(__.constant("value")),
+ List.of(),
+ List.of(__.constant("value")),
+ null, null
+ },
+ {TraversalSelectStep.class,
+ g.V().select((Traversal)__.constant("a")),
+ List.of(),
+ List.of(__.constant("a")),
+ null, null
+ },
+ {TraversalSelectStep.class,
+ g.V().select((Traversal)__.constant("a")).by("name"),
+ List.of(),
+ List.of(__.constant("a"), new ValueTraversal("name")),
+ null, null
+ },
+ {TraversalFilterStep.class,
+ g.V().filter(__.constant(5)), // a bit of an arbitrary case to avoid getting optimized by strategies
+ List.of(),
+ List.of(__.constant(5)),
+ null, null
+ },
+ {TraversalFlatMapStep.class,
+ g.V().flatMap(__.out()),
+ List.of(),
+ List.of(__.out()),
+ null, null
+ },
+ {TraversalFlatMapStep.class,
+ g.V().flatMap(__.constant("value")),
+ List.of(),
+ List.of(__.constant("value")),
+ null, null
+ },
+ {TraversalMapStep.class,
+ g.V().map(__.values("name")),
+ List.of(),
+ List.of(__.values("name")),
+ null, null
+ },
+ {TraversalMapStep.class,
+ g.V().map(__.constant("value")),
+ List.of(),
+ List.of(__.constant("value")),
+ null, null
+ },
+ {TraversalSideEffectStep.class,
+ g.V().sideEffect(__.identity()),
+ List.of(),
+ List.of(__.identity()),
+ null, null
+ },
+ {TraversalSideEffectStep.class,
+ g.V().sideEffect(__.constant("value")),
+ List.of(),
+ List.of(__.constant("value")),
+ null, null
+ },
+ {TreeStep.class,
+ g.V().out().tree(),
+ List.of(),
+ List.of(),
+ null, null
+ },
+ {TreeStep.class,
+ g.V().out().tree().by("name"),
+ List.of(),
+ List.of(new ValueTraversal("name")),
+ null, null
+ },
+ {TreeStep.class,
+ g.V().out().tree().by(__.constant("value")),
+ List.of(),
+ List.of(__.constant("value")),
+ null, null
+ },
+ {TreeSideEffectStep.class,
+ g.V().out().tree("x"),
+ List.of(),
+ List.of(),
+ null, null
+ },
+ {TreeSideEffectStep.class,
+ g.V().out().tree("x").by("name"),
+ List.of(),
+ List.of(new ValueTraversal("name")),
+ null, null
+ },
+ {TreeSideEffectStep.class,
+ g.V().out().tree("x").by(__.constant("value")),
+ List.of(),
+ List.of(__.constant("value")),
+ null, null
+ },
+ {UnionStep.class,
+ g.union(__.V().values("name"), __.V().values("age")),
+ List.of(appendComputerAwareEndStep(__.V().values("name")), appendComputerAwareEndStep(__.V().values("age"))),
+ List.of(new ConstantTraversal<>(Pick.any)),
+ List.of(appendComputerAwareEndStep(__.V().values("name").barrier(2500)), appendComputerAwareEndStep(__.V().values("age").barrier(2500))),
+ null
+ },
+ {UnionStep.class,
+ g.union(__.constant("a"), __.constant("b")),
+ List.of(appendComputerAwareEndStep(__.constant("a")), appendComputerAwareEndStep(__.constant("b"))),
+ List.of(new ConstantTraversal<>(Pick.any)),
+ null, null
+ },
+ {WherePredicateStep.class,
+ g.V().as("a").out().as("b").where("a", P.eq("b")),
+ List.of(),
+ List.of(),
+ null, null
+ },
+ {WherePredicateStep.class,
+ g.V().as("a").out().as("b").where("a", P.eq("b")).by("name"),
+ List.of(),
+ List.of(new ValueTraversal("name")),
+ null, null
+ },
+ {WherePredicateStep.class,
+ g.V().as("a").out().as("b").where("a", P.eq("b")).by(__.constant("value")),
+ List.of(),
+ List.of(__.constant("value")),
+ null, null
+ },
+ {WhereTraversalStep.class,
+ g.V().as("a").out().as("b").where(__.as("a").out().as("c")),
+ List.of(),
+ List.of(generateWhereChildTraversal("a", "c", __.out().asAdmin())),
+ null, null
+ },
+ });
+ }
+
+ @Test
+ public void doTest() {
+ verifyExpectedParents(expectedGlobalChildren, expectedLocalChildren, "(pre-strategy application)");
+
+ traversal = traversal.clone();
+
+ verifyExpectedParents(expectedGlobalChildren, expectedLocalChildren, "(cloned traversal, pre-strategy application)");
+
+ traversal.getStrategies().addStrategies(GValueReductionStrategy.instance());
+ traversal.applyStrategies();
+
+ verifyExpectedParents(postStrategyExpectedGlobalChildren == null ? expectedGlobalChildren : postStrategyExpectedGlobalChildren,
+ postStrategyExpectedLocalChildren == null ? expectedLocalChildren : postStrategyExpectedLocalChildren,
+ "(pre-strategy application)");
+
+ traversal = traversal.clone();
+
+ verifyExpectedParents(postStrategyExpectedGlobalChildren == null ? expectedGlobalChildren : postStrategyExpectedGlobalChildren,
+ postStrategyExpectedLocalChildren == null ? expectedLocalChildren : postStrategyExpectedLocalChildren,
+ "(cloned traversal, pre-strategy application)");
+ }
+
+ private void verifyExpectedParents(List<Traversal.Admin<?,?>> expectedGlobalChildren, List<Traversal.Admin<?,?>> expectedLocalChildren, String messageSuffix) {
+ List<Step> steps = TraversalHelper.getStepsOfAssignableClass(stepClass, traversal);
+ assertTrue(String.format("Expected a single step of class %s to test, found %d %s", stepClass.getName(), steps.size(), messageSuffix), steps.size() == 1);
+ assertTrue(String.format("Expected step to implement TraversalParent %s", messageSuffix), steps.get(0) instanceof TraversalParent);
+
+ TraversalParent testStep = (TraversalParent) steps.get(0);
+ assertThat(String.format("getGlobalChildren() did not produce the expected results %s", messageSuffix), testStep.getGlobalChildren(), containsInAnyOrder(expectedGlobalChildren.toArray()));
Review Comment:
Nit: this method is deprecated
##########
gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/TraversalParentTest.java:
##########
@@ -0,0 +1,1028 @@
+/*
+ * 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 java.time.OffsetDateTime;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.commons.configuration2.MapConfiguration;
+import org.apache.tinkerpop.gremlin.process.traversal.Operator;
+import org.apache.tinkerpop.gremlin.process.traversal.Pick;
+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.GraphTraversalSource;
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
+import org.apache.tinkerpop.gremlin.process.traversal.lambda.AbstractLambdaTraversal;
+import org.apache.tinkerpop.gremlin.process.traversal.lambda.ConstantTraversal;
+import org.apache.tinkerpop.gremlin.process.traversal.Merge;
+import org.apache.tinkerpop.gremlin.process.traversal.Scope;
+import org.apache.tinkerpop.gremlin.process.traversal.P;
+import org.apache.tinkerpop.gremlin.process.traversal.lambda.LoopTraversal;
+import org.apache.tinkerpop.gremlin.process.traversal.lambda.PredicateTraversal;
+import org.apache.tinkerpop.gremlin.process.traversal.lambda.TrueTraversal;
+import org.apache.tinkerpop.gremlin.process.traversal.lambda.ValueTraversal;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.AddEdgeStepContract;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.AddVertexStepContract;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.CallStepContract;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.MergeStepContract;
+import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.AddPropertyStepContract;
+import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.AggregateGlobalStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.AggregateLocalStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.filter.AndStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.filter.OrStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.branch.BranchStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.branch.ChooseStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.CoalesceStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.CombineStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.ConcatStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.DateDiffStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.filter.DedupGlobalStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.DifferenceStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.DisjunctStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.FormatStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.GroupCountStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.GroupCountSideEffectStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.GroupStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.IntersectStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.branch.LocalStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.MatchStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.MathStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.MergeStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.filter.NotStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.branch.OptionalStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.OrderGlobalStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.OrderLocalStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.filter.PathFilterStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.PathStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.ProductStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.ProjectStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.PropertyMapStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.branch.RepeatStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.SackValueStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.filter.SampleGlobalStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.SelectOneStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.SelectStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.TraversalSelectStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.filter.TraversalFilterStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.TraversalFlatMapStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.TraversalMapStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.TraversalSideEffectStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.TreeStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.TreeSideEffectStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.branch.UnionStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.filter.WherePredicateStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.filter.WhereTraversalStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.ComputerAwareStep;
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.GValueReductionStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper;
+import org.apache.tinkerpop.gremlin.structure.T;
+import org.apache.tinkerpop.gremlin.structure.service.Service;
+import org.apache.tinkerpop.gremlin.structure.service.ServiceRegistry;
+
+import org.apache.tinkerpop.gremlin.structure.util.GraphFactoryTest;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import static org.apache.tinkerpop.gremlin.process.traversal.AnonymousTraversalSource.traversal;
+import static org.hamcrest.Matchers.containsInAnyOrder;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+
+@RunWith(Parameterized.class)
+public class TraversalParentTest {
+
+ private static ServiceRegistry mockedRegistry= mock(ServiceRegistry.class);
+ private static Service<?, ?> mockedService = mock(Service.class);
+ private static GraphTraversalSource g = traversal().with(GraphFactoryTest.MockGraph.open(new MapConfiguration(Map.of("service-registry", mockedRegistry))));
+
+ @BeforeClass
+ public static void setupClass() {
+ when(mockedRegistry.get(any(), anyBoolean(), any())).thenReturn(mockedService);
+ when(mockedService.getRequirements()).thenReturn(Set.of());
+ }
+
+ @Parameterized.Parameter(value = 0)
+ public Class stepClass;
+
+ @Parameterized.Parameter(value = 1)
+ public Traversal.Admin traversal;
+
+ @Parameterized.Parameter(value = 2)
+ public List<Traversal.Admin<?,?>> expectedGlobalChildren;
+
+ @Parameterized.Parameter(value = 3)
+ public List<Traversal.Admin<?,?>> expectedLocalChildren;
+
+ /**
+ * Overrides expectedGlobalChildren for assertions following strategy execution. If left null, expectedGlobalChildren is used instead.
+ */
+ @Parameterized.Parameter(value = 4)
+ public List<Traversal.Admin<?,?>> postStrategyExpectedGlobalChildren;
+
+ /**
+ * Overrides expectedLocalChildren for assertions following strategy execution. If left null, expectedLocalChildren is used instead.
+ */
+ @Parameterized.Parameter(value = 5)
+ public List<Traversal.Admin<?,?>> postStrategyExpectedLocalChildren;
+
+ @Parameterized.Parameters(name = "{0}")
+ public static Iterable<Object[]> data() {
+ return Arrays.asList(new Object[][]{
+ {AddVertexStepContract.class,
+ g.addV("label").property("name", __.constant("cole")),
+ List.of(),
+ List.of(__.constant("cole"), new ConstantTraversal<>("label")),
+ null, null
+ },
+ {AddVertexStepContract.class,
+ g.addV(__.constant("label")).property("name", __.constant("cole")),
+ List.of(),
+ List.of(__.constant("cole"), __.constant("label")),
+ null, null
+ },
+ {AddVertexStepContract.class,
+ g.addV().property("name", __.constant("cole")).property(T.label, __.constant("label")).property(T.id, __.constant(1)),
+ List.of(),
+ List.of(__.constant("cole"), __.constant("label"), __.constant(1)),
+ null, null
+ },
+ {AddVertexStepContract.class,
+ g.addV(GValue.of("l", "label")).property("name", GValue.of("name", "cole")),
+ List.of(),
+ List.of(new ConstantTraversal<>("label")), // Property is not stored as a child traversal in this case
+ null, null
+ },
+ {AddVertexStepContract.class,
+ g.addV("label").property(__.constant("name"), __.constant("cole")),
+ List.of(),
+ List.of(__.constant("name"), __.constant("cole"), new ConstantTraversal<>("label")),
+ null, null
+ },
+ {AddVertexStepContract.class,
+ g.inject(1).addV("label").property("name", __.constant("cole")),
+ List.of(),
+ List.of(__.constant("cole"), new ConstantTraversal<>("label")),
+ null, null
+ },
+ {AddVertexStepContract.class,
+ g.inject(1).addV(__.constant("label")).property("name", __.constant("cole")),
+ List.of(),
+ List.of(__.constant("cole"), __.constant("label")),
+ null, null
+ },
+ {AddVertexStepContract.class,
+ g.inject(1).addV(GValue.of("l", "label")).property("name", GValue.of("name", "cole")),
+ List.of(),
+ List.of(new ConstantTraversal<>("label")), // Property is not stored as a child traversal in this case
+ null, null
+ },
+ {AddVertexStepContract.class,
+ g.inject(1).addV("label").property(__.constant("name"), __.constant("cole")),
+ List.of(),
+ List.of(__.constant("name"), __.constant("cole"), new ConstantTraversal<>("label")),
+ null, null
+ },
+ {AddEdgeStepContract.class,
+ g.addE("label").from(1).to(2).property("name", __.constant("cole")),
+ List.of(),
+ List.of(__.constant("cole"), new ConstantTraversal<>("label"), __.constant(1), __.constant(2)),
+ null, null
+ },
+ {AddEdgeStepContract.class,
+ g.addE("label").from(__.V(1)).to(__.V(2))
+ .property("name", __.constant("cole"))
+ .property(T.id, __.constant(5)),
+ List.of(),
+ List.of(__.constant("cole"), new ConstantTraversal<>("label"), __.V(1), __.V(2), __.constant(5)),
+ null, null
+ },
+ {AddEdgeStepContract.class,
+ g.addE("label").from(__.V(1)).to(__.V(2)).property("name", __.constant("cole")),
+ List.of(),
+ List.of(__.constant("cole"), new ConstantTraversal<>("label"), __.V(1), __.V(2)),
+ null, null
+ },
+ {AddEdgeStepContract.class,
+ g.addE(GValue.of("l", "label")).from(GValue.of("from", 1)).to(GValue.of("to", 2)).property("name", GValue.of("name", "cole")),
+ List.of(),
+ List.of(new ConstantTraversal<>("label"), new ConstantTraversal(1), new ConstantTraversal(2)),
+ null, null
+ },
+ {AddEdgeStepContract.class,
+ g.addE("label").from(1).to(2).property(__.constant("name"), __.constant("cole")),
+ List.of(),
+ List.of(__.constant("name"), __.constant("cole"), new ConstantTraversal<>("label"), __.constant(1), __.constant(2)),
+ null, null
+ },
+ {AddEdgeStepContract.class,
+ g.inject(1).addE("label").from(1).to(2).property("name", __.constant("cole")),
+ List.of(),
+ List.of(__.constant("cole"), new ConstantTraversal<>("label"), __.constant(1), __.constant(2)),
+ null, null
+ },
+ {AddEdgeStepContract.class,
+ g.inject(1).addE("label").from(__.V(1)).to(__.V(2)).property("name", __.constant("cole")),
+ List.of(),
+ List.of(__.constant("cole"), new ConstantTraversal<>("label"), __.V(1), __.V(2)),
+ null, null
+ },
+ {AddEdgeStepContract.class,
+ g.inject(1).addE(GValue.of("l", "label")).from(GValue.of("from", 1)).to(GValue.of("to", 2)).property("name", GValue.of("name", "cole")),
+ List.of(),
+ List.of(new ConstantTraversal<>("label"), new ConstantTraversal(1), new ConstantTraversal(2)),
+ null, null
+ },
+ {AddEdgeStepContract.class,
+ g.inject(1).addE("label").from(1).to(2).property(__.constant("name"), __.constant("cole")),
+ List.of(),
+ List.of(__.constant("name"), __.constant("cole"), new ConstantTraversal<>("label"), __.constant(1), __.constant(2)),
+ null, null
+ },
+ {CallStepContract.class,
+ g.call("service"),
+ List.of(),
+ List.of(),
+ null, null
+ },
+ {CallStepContract.class,
+ g.call("service").with("key", __.constant("value")),
+ List.of(),
+ List.of(__.constant("value")),
+ null, null
+ },
+ {CallStepContract.class,
+ g.call("service", __.constant(Map.of("key", "value"))),
+ List.of(),
+ List.of(__.constant(Map.of("key", "value"))),
+ null, null
+ },
+ {CallStepContract.class,
+ g.call("service", __.constant(Map.of("key", "value"))).with("key", __.constant("value")),
+ List.of(),
+ List.of(__.constant(Map.of("key", "value")), __.constant("value")),
+ null, null
+ },
+ {AddPropertyStepContract.class,
+ g.inject(1).property("key", "value"),
+ List.of(),
+ List.of(new ConstantTraversal<>("value")), // constant Value's are internally boxed in Traversals
+ null, null
+ },
+ {AddPropertyStepContract.class,
+ g.inject(1).property("key", __.constant("value")),
+ List.of(),
+ List.of(__.constant("value")),
+ null, null
+ },
+ {AddPropertyStepContract.class,
+ g.inject(1).property(__.constant("key"), __.constant("value")),
+ List.of(),
+ List.of(__.constant("key"), __.constant("value")),
+ null, null
+ },
+ {AddPropertyStepContract.class,
+ g.addV().property("name", "value", "metaKey", "metaValue"),
+ List.of(),
+ List.of(new ConstantTraversal<>("value")), // constant Value's are internally boxed in Traversals
+ null, null
+ },
+ {AddPropertyStepContract.class,
+ g.addV().property("name", __.constant("value"), "metaKey", __.constant("metaValue")),
+ List.of(),
+ List.of(__.constant("value"), __.constant("metaValue")),
+ null, null
+ },
+ {AddPropertyStepContract.class,
+ g.addV().property(__.constant("name"), __.constant("value"), __.constant("metaKey"), __.constant("metaValue")),
+ List.of(),
+ List.of(__.constant("name"), __.constant("value"), __.constant("metaKey"), __.constant("metaValue")),
+ null, null
+ },
+ {AddPropertyStepContract.class,
+ g.addV().property("name", "value", "metaKey1", "metaValue1", "metaKey2", "metaValue2"),
+ List.of(),
+ List.of(new ConstantTraversal<>("value")), // constant Value's are internally boxed in Traversals
+ null, null
+ },
+ {MergeStepContract.class,
+ g.mergeV(Map.of("name", "marko")),
+ List.of(),
+ List.of(new ConstantTraversal<>(Map.of("name", "marko"))), // constant MergeMap's are internally boxed in Traversals
+ null, null
+ },
+ {MergeStepContract.class,
+ g.mergeV(__.constant(Map.of("name", "marko"))),
+ List.of(),
+ List.of(__.constant(Map.of("name", "marko"))),
+ null, null
+ },
+ {MergeStepContract.class,
+ g.mergeV(Map.of("name", "marko")).option(Merge.onCreate, __.constant(Map.of("age", 29))),
+ List.of(),
+ List.of(new ConstantTraversal<>(Map.of("name", "marko")), __.constant(Map.of("age", 29))), // constant MergeMap's are internally boxed in Traversals
+ null, null
+ },
+ {MergeStepContract.class,
+ g.mergeV(__.constant(Map.of("name", "marko"))).option(Merge.onCreate, __.constant(Map.of("age", 29))).option(Merge.onMatch, __.constant(Map.of("updated", true))),
+ List.of(),
+ List.of(__.constant(Map.of("name", "marko")), __.constant(Map.of("age", 29)), __.constant(Map.of("updated", true))),
+ null, null
+ },
+ {MergeStepContract.class,
+ g.mergeE(Map.of(T.label, "knows")),
+ List.of(),
+ List.of(new ConstantTraversal<>(Map.of(T.label, "knows"))), // constant MergeMap's are internally boxed in Traversals
+ null, null
+ },
+ {MergeStepContract.class,
+ g.mergeE(__.constant(Map.of(T.label, "knows"))),
+ List.of(),
+ List.of(__.constant(Map.of(T.label, "knows"))),
+ null, null
+ },
+ {MergeStepContract.class,
+ g.mergeE(Map.of(T.label, "knows")).option(Merge.onCreate, __.constant(Map.of("weight", 0.5))),
+ List.of(),
+ List.of(new ConstantTraversal<>(Map.of(T.label, "knows")), __.constant(Map.of("weight", 0.5))), // constant MergeMap's are internally boxed in Traversals
+ null, null
+ },
+ {MergeStepContract.class,
+ g.mergeE(__.constant(Map.of(T.label, "knows"))).option(Merge.onCreate, __.constant(Map.of("weight", 0.5))).option(Merge.onMatch, __.constant(Map.of("updated", true))),
+ List.of(),
+ List.of(__.constant(Map.of(T.label, "knows")), __.constant(Map.of("weight", 0.5)), __.constant(Map.of("updated", true))),
+ null, null
+ },
+ {AggregateGlobalStep.class,
+ g.V().aggregate("x"),
+ List.of(),
+ List.of(),
+ null, null
+ },
+ {AggregateGlobalStep.class,
+ g.V().aggregate("x").by("name"),
+ List.of(),
+ List.of(new ValueTraversal("name")),
+ null, null
+ },
+ {AggregateGlobalStep.class,
+ g.V().aggregate("x").by(__.constant("value")),
+ List.of(),
+ List.of(__.constant("value")),
+ null, null
+ },
+ {AggregateLocalStep.class,
+ g.V().aggregate(Scope.local, "x"),
+ List.of(),
+ List.of(),
+ null, null
+ },
+ {AggregateLocalStep.class,
+ g.V().aggregate(Scope.local, "x").by("name"),
+ List.of(),
+ List.of(new ValueTraversal("name")),
+ null, null
+ },
+ {AggregateLocalStep.class,
+ g.V().aggregate(Scope.local, "x").by(__.constant("value")),
+ List.of(),
+ List.of(__.constant("value")),
+ null, null
+ },
+ {AndStep.class,
+ g.V().and(__.outE(), __.has("age", P.gte(32))),
+ List.of(),
+ List.of(__.outE(), __.has("age", P.gte(32))),
+ null, null
+ },
+ {OrStep.class,
+ g.V().or(__.outE(), __.has("age", P.gte(32))),
+ List.of(),
+ List.of(__.outE(), __.has("age", P.gte(32))),
+ null, null
+ },
+ {BranchStep.class,
+ g.V().branch(__.label()).option("person", __.values("name")).option("software", __.values("lang")),
+ List.of(appendComputerAwareEndStep(__.values("name")), appendComputerAwareEndStep(__.values("lang"))),
+ List.of(__.label(), new PredicateTraversal<>(P.eq("person")), new PredicateTraversal<>(P.eq("software"))), // option keys are wrapped in PredicateTraversals internally
+ null, null
+ },
+ {ChooseStep.class,
+ g.V().choose(__.out().count()).option(2L, __.values("name")).option(3L, __.values("age")),
+ List.of(appendComputerAwareEndStep(__.values("name")), appendComputerAwareEndStep(__.values("age")), appendComputerAwareEndStep(__.identity()), appendComputerAwareEndStep(__.identity())),
+ List.of(__.out().count(), new PredicateTraversal<>(P.eq(2L)), new PredicateTraversal<>(P.eq(3L))), // option keys are wrapped in PredicateTraversals internally
+ null, List.of(__.outE().count(), new PredicateTraversal<>(P.eq(2L)), new PredicateTraversal<>(P.eq(3L)))
+ },
+ {CoalesceStep.class,
+ g.V().coalesce(__.out("knows"), __.out("created")),
+ List.of(),
+ List.of(__.out("knows"), __.out("created")),
+ null, null
+ },
+ {CombineStep.class,
+ g.V().fold().combine(__.constant(List.of(1, 2, 3))),
+ List.of(),
+ List.of(__.constant(List.of(1, 2, 3))),
+ null, null
+ },
+ {ConcatStep.class,
+ g.inject("a", "b").concat(__.constant("c"), __.constant("d")),
+ List.of(),
+ List.of(__.constant("c"), __.constant("d")),
+ null, null
+ },
+ {DateDiffStep.class,
+ g.inject(OffsetDateTime.parse("1970-01-01T00:00:00.000Z")).dateDiff(__.constant(OffsetDateTime.parse("1970-02-01T00:00:00.000Z"))),
+ List.of(),
+ List.of(__.constant(OffsetDateTime.parse("1970-02-01T00:00:00.000Z"))),
+ null, null
+ },
+ {DedupGlobalStep.class,
+ g.V().dedup(),
+ List.of(),
+ List.of(),
+ null, null
+ },
+ {DedupGlobalStep.class,
+ g.V().dedup().by("name"),
+ List.of(),
+ List.of(new ValueTraversal("name")),
+ null, null
+ },
+ {DedupGlobalStep.class,
+ g.V().dedup().by(__.constant("value")),
+ List.of(),
+ List.of(__.constant("value")),
+ null, null
+ },
+ {DifferenceStep.class,
+ g.V().fold().difference(__.constant(List.of(1, 2, 3))),
+ List.of(),
+ List.of(__.constant(List.of(1, 2, 3))),
+ null, null
+ },
+ {DisjunctStep.class,
+ g.V().fold().disjunct(__.constant(List.of(1, 2, 3))),
+ List.of(),
+ List.of(__.constant(List.of(1, 2, 3))),
+ null, null
+ },
+ {FormatStep.class,
+ g.V().format("Hello %{name}"),
+ List.of(),
+ List.of(),
+ null, null
+ },
+ {FormatStep.class,
+ g.V().format("Hello %{name}").by("name"),
+ List.of(),
+ List.of(new ValueTraversal("name")),
+ null, null
+ },
+ {FormatStep.class,
+ g.V().format("Hello %{name}").by(__.constant("value")),
+ List.of(),
+ List.of(__.constant("value")),
+ null, null
+ },
+ {GroupCountStep.class,
+ g.V().groupCount(),
+ List.of(),
+ List.of(),
+ null, null
+ },
+ {GroupCountStep.class,
+ g.V().groupCount().by("name"),
+ List.of(),
+ List.of(new ValueTraversal("name")),
+ null, null
+ },
+ {GroupCountStep.class,
+ g.V().groupCount().by(__.constant("value")),
+ List.of(),
+ List.of(__.constant("value")),
+ null, null
+ },
+ {GroupCountSideEffectStep.class,
+ g.V().groupCount("x"),
+ List.of(),
+ List.of(),
+ null, null
+ },
+ {GroupCountSideEffectStep.class,
+ g.V().groupCount("x").by("name"),
+ List.of(),
+ List.of(new ValueTraversal("name")),
+ null, null
+ },
+ {GroupCountSideEffectStep.class,
+ g.V().groupCount("x").by(__.constant("value")),
+ List.of(),
+ List.of(__.constant("value")),
+ null, null
+ },
+ {GroupStep.class,
+ g.V().group(),
+ List.of(),
+ List.of(__.fold()),
+ null, null
+ },
+ {GroupStep.class,
+ g.V().group().by("name"),
+ List.of(),
+ List.of(new ValueTraversal("name"), __.fold()),
+ null, null
+ },
+ {GroupStep.class,
+ g.V().group().by("name").by("age"),
+ List.of(),
+ List.of(new ValueTraversal("name"), __.map(new ValueTraversal("age")).fold()),
+ null, null
+ },
+ {GroupStep.class,
+ g.V().group().by(__.constant("key")).by(__.constant("value")),
+ List.of(),
+ List.of(__.constant("key"), __.constant("value")),
+ null, null
+ },
+ {IntersectStep.class,
+ g.V().fold().intersect(__.constant(List.of(1, 2, 3))),
+ List.of(),
+ List.of(__.constant(List.of(1, 2, 3))),
+ null, null
+ },
+ {LocalStep.class,
+ g.V().local(__.outE().count()),
+ List.of(),
+ List.of(__.outE().count()),
+ null, null
+ },
+ {MatchStep.class,
+ g.V().match(__.as("a").out().as("b"), __.as("b").in().as("c")),
+ List.of(generateMatchChildTraversal("a", "b", __.out().asAdmin()), generateMatchChildTraversal("b", "c", __.in().asAdmin())),
+ List.of(),
+ null, null
+ },
+ {MathStep.class,
+ g.V().math("_ + 1"),
+ List.of(),
+ List.of(),
+ null, null
+ },
+ {MathStep.class,
+ g.V().math("_ + 1").by("age"),
+ List.of(),
+ List.of(new ValueTraversal("age")),
+ null, null
+ },
+ {MathStep.class,
+ g.V().math("_ + _").by("age").by(__.constant(10)),
+ List.of(),
+ List.of(new ValueTraversal("age"), __.constant(10)),
+ null, null
+ },
+ {MergeStep.class,
+ g.V().fold().merge(__.constant(List.of(1, 2, 3))),
+ List.of(),
+ List.of(__.constant(List.of(1, 2, 3))),
+ null, null
+ },
+ {NotStep.class,
+ g.V().not(__.has("age", P.gt(27))),
+ List.of(),
+ List.of(__.has("age", P.gt(27))),
+ null, null
+ },
+ {OptionalStep.class,
+ g.V().optional(__.out("knows")),
+ List.of(),
+ List.of(__.out("knows")),
+ null, null
+ },
+ {OrderGlobalStep.class,
+ g.V().order(),
+ List.of(),
+ List.of(),
+ null, null
+ },
+ {OrderGlobalStep.class,
+ g.V().order().by("name"),
+ List.of(),
+ List.of(new ValueTraversal("name")),
+ null, null
+ },
+ {OrderGlobalStep.class,
+ g.V().order().by("name").by(__.constant("value")),
+ List.of(),
+ List.of(new ValueTraversal("name"), __.constant("value")),
+ null, null
+ },
+ {OrderLocalStep.class,
+ g.V().fold().order(Scope.local),
+ List.of(),
+ List.of(),
+ null, null
+ },
+ {OrderLocalStep.class,
+ g.V().fold().order(Scope.local).by("name"),
+ List.of(),
+ List.of(new ValueTraversal("name")),
+ null, null
+ },
+ {OrderLocalStep.class,
+ g.V().fold().order(Scope.local).by(__.constant("value")),
+ List.of(),
+ List.of(__.constant("value")),
+ null, null
+ },
+ {PathFilterStep.class,
+ g.V().simplePath(),
+ List.of(),
+ List.of(),
+ null, null
+ },
+ {PathFilterStep.class,
+ g.V().cyclicPath(),
+ List.of(),
+ List.of(),
+ null, null
+ },
+ {PathFilterStep.class,
+ g.V().simplePath().by("name"),
+ List.of(),
+ List.of(new ValueTraversal("name")),
+ null, null
+ },
+ {PathFilterStep.class,
+ g.V().simplePath().by(__.constant("value")),
+ List.of(),
+ List.of(__.constant("value")),
+ null, null
+ },
+ {PathFilterStep.class,
+ g.V().cyclicPath().by("age").by(__.constant("value")),
+ List.of(),
+ List.of(new ValueTraversal("age"), __.constant("value")),
+ null, null
+ },
+ {PathStep.class,
+ g.V().path(),
+ List.of(),
+ List.of(),
+ null, null
+ },
+ {PathStep.class,
+ g.V().out().path().by("age").by("name"),
+ List.of(),
+ List.of(new ValueTraversal("age"), new ValueTraversal("name")),
+ null, null
+ },
+ {PathStep.class,
+ g.V().path().by(__.constant("value")),
+ List.of(),
+ List.of(__.constant("value")),
+ null, null
+ },
+ {ProductStep.class,
+ g.V().fold().product(__.constant(List.of(1, 2, 3))),
+ List.of(),
+ List.of(__.constant(List.of(1, 2, 3))),
+ null, null
+ },
+ {ProjectStep.class,
+ g.V().project("a", "b").by("name").by("age"),
+ List.of(),
+ List.of(new ValueTraversal("name"), new ValueTraversal("age")),
+ null, null
+ },
+ {ProjectStep.class,
+ g.V().project("x").by(__.constant("value")),
+ List.of(),
+ List.of(__.constant("value")),
+ null, null
+ },
+ {PropertyMapStep.class,
+ g.V().valueMap(),
+ List.of(),
+ List.of(),
+ null, null
+ },
+ {PropertyMapStep.class,
+ g.V().valueMap().by(__.constant("transformed")),
+ List.of(),
+ List.of(__.constant("transformed")),
+ null, null
+ },
+ {RepeatStep.class,
+ g.V().repeat(__.out()).emit().times(2),
+ List.of(appendRepeatEndStep(__.out())),
+ List.of(new LoopTraversal<>(2), TrueTraversal.instance()),
+ null, null
+ },
+ {RepeatStep.class,
+ g.V().repeat(__.out()).until(__.has("name", "josh")),
+ List.of(appendRepeatEndStep(__.out())),
+ List.of(__.has("name", "josh")),
+ null, null
+ },
+ {RepeatStep.class,
+ g.V().repeat(__.out()).emit(__.has("age")).until(__.has("name", "josh")),
+ List.of(appendRepeatEndStep(__.out())),
+ List.of(__.has("name", "josh"), __.has("age")),
+ null, List.of(__.has("name", "josh"), __.filter(__.properties("age"))),
+ },
+ {SackValueStep.class,
+ g.withSack(0).V().sack(Operator.sum),
+ List.of(),
+ List.of(),
+ null, null
+ },
+ {SackValueStep.class,
+ g.withSack(0).V().sack(Operator.sum).by("age"),
+ List.of(),
+ List.of(new ValueTraversal("age")),
+ null, null
+ },
+ {SackValueStep.class,
+ g.withSack(0).V().sack(Operator.sum).by(__.constant("age")),
+ List.of(),
+ List.of(__.constant("age")),
+ null, null
+ },
+ {SampleGlobalStep.class,
+ g.V().sample(2),
+ List.of(),
+ List.of(new ConstantTraversal<>(1.0)),
+ null, null
+ },
+ {SampleGlobalStep.class,
+ g.E().sample(2).by("weight"),
+ List.of(),
+ List.of(new ValueTraversal("weight")),
+ null, null
+ },
+ {SampleGlobalStep.class,
+ g.E().sample(2).by(__.constant("weight")),
+ List.of(),
+ List.of(__.constant("weight")),
+ null, null
+ },
+ {SelectOneStep.class,
+ g.V().as("a").select("a"),
+ List.of(),
+ List.of(),
+ null, null
+ },
+ {SelectOneStep.class,
+ g.V().as("a").select("a").by("name"),
+ List.of(),
+ List.of(new ValueTraversal("name")),
+ null, null
+ },
+ {SelectOneStep.class,
+ g.V().as("a").select("a").by(__.constant("value")),
+ List.of(),
+ List.of(__.constant("value")),
+ null, null
+ },
+ {SelectStep.class,
+ g.V().as("a").as("b").select("a", "b"),
+ List.of(),
+ List.of(),
+ null, null
+ },
+ {SelectStep.class,
+ g.V().as("a").as("b").select("a", "b").by("name"),
+ List.of(),
+ List.of(new ValueTraversal("name")),
+ null, null
+ },
+ {SelectStep.class,
+ g.V().as("a").as("b").select("a", "b").by(__.constant("value")),
+ List.of(),
+ List.of(__.constant("value")),
+ null, null
+ },
+ {TraversalSelectStep.class,
+ g.V().select((Traversal)__.constant("a")),
+ List.of(),
+ List.of(__.constant("a")),
+ null, null
+ },
+ {TraversalSelectStep.class,
+ g.V().select((Traversal)__.constant("a")).by("name"),
+ List.of(),
+ List.of(__.constant("a"), new ValueTraversal("name")),
+ null, null
+ },
+ {TraversalFilterStep.class,
+ g.V().filter(__.constant(5)), // a bit of an arbitrary case to avoid getting optimized by strategies
+ List.of(),
+ List.of(__.constant(5)),
+ null, null
+ },
+ {TraversalFlatMapStep.class,
+ g.V().flatMap(__.out()),
+ List.of(),
+ List.of(__.out()),
+ null, null
+ },
+ {TraversalFlatMapStep.class,
+ g.V().flatMap(__.constant("value")),
+ List.of(),
+ List.of(__.constant("value")),
+ null, null
+ },
+ {TraversalMapStep.class,
+ g.V().map(__.values("name")),
+ List.of(),
+ List.of(__.values("name")),
+ null, null
+ },
+ {TraversalMapStep.class,
+ g.V().map(__.constant("value")),
+ List.of(),
+ List.of(__.constant("value")),
+ null, null
+ },
+ {TraversalSideEffectStep.class,
+ g.V().sideEffect(__.identity()),
+ List.of(),
+ List.of(__.identity()),
+ null, null
+ },
+ {TraversalSideEffectStep.class,
+ g.V().sideEffect(__.constant("value")),
+ List.of(),
+ List.of(__.constant("value")),
+ null, null
+ },
+ {TreeStep.class,
+ g.V().out().tree(),
+ List.of(),
+ List.of(),
+ null, null
+ },
+ {TreeStep.class,
+ g.V().out().tree().by("name"),
+ List.of(),
+ List.of(new ValueTraversal("name")),
+ null, null
+ },
+ {TreeStep.class,
+ g.V().out().tree().by(__.constant("value")),
+ List.of(),
+ List.of(__.constant("value")),
+ null, null
+ },
+ {TreeSideEffectStep.class,
+ g.V().out().tree("x"),
+ List.of(),
+ List.of(),
+ null, null
+ },
+ {TreeSideEffectStep.class,
+ g.V().out().tree("x").by("name"),
+ List.of(),
+ List.of(new ValueTraversal("name")),
+ null, null
+ },
+ {TreeSideEffectStep.class,
+ g.V().out().tree("x").by(__.constant("value")),
+ List.of(),
+ List.of(__.constant("value")),
+ null, null
+ },
+ {UnionStep.class,
+ g.union(__.V().values("name"), __.V().values("age")),
+ List.of(appendComputerAwareEndStep(__.V().values("name")), appendComputerAwareEndStep(__.V().values("age"))),
+ List.of(new ConstantTraversal<>(Pick.any)),
+ List.of(appendComputerAwareEndStep(__.V().values("name").barrier(2500)), appendComputerAwareEndStep(__.V().values("age").barrier(2500))),
+ null
+ },
+ {UnionStep.class,
+ g.union(__.constant("a"), __.constant("b")),
+ List.of(appendComputerAwareEndStep(__.constant("a")), appendComputerAwareEndStep(__.constant("b"))),
+ List.of(new ConstantTraversal<>(Pick.any)),
+ null, null
+ },
+ {WherePredicateStep.class,
+ g.V().as("a").out().as("b").where("a", P.eq("b")),
+ List.of(),
+ List.of(),
+ null, null
+ },
+ {WherePredicateStep.class,
+ g.V().as("a").out().as("b").where("a", P.eq("b")).by("name"),
+ List.of(),
+ List.of(new ValueTraversal("name")),
+ null, null
+ },
+ {WherePredicateStep.class,
+ g.V().as("a").out().as("b").where("a", P.eq("b")).by(__.constant("value")),
+ List.of(),
+ List.of(__.constant("value")),
+ null, null
+ },
+ {WhereTraversalStep.class,
+ g.V().as("a").out().as("b").where(__.as("a").out().as("c")),
+ List.of(),
+ List.of(generateWhereChildTraversal("a", "c", __.out().asAdmin())),
+ null, null
+ },
+ });
+ }
+
+ @Test
+ public void doTest() {
+ verifyExpectedParents(expectedGlobalChildren, expectedLocalChildren, "(pre-strategy application)");
+
+ traversal = traversal.clone();
+
+ verifyExpectedParents(expectedGlobalChildren, expectedLocalChildren, "(cloned traversal, pre-strategy application)");
+
+ traversal.getStrategies().addStrategies(GValueReductionStrategy.instance());
+ traversal.applyStrategies();
+
+ verifyExpectedParents(postStrategyExpectedGlobalChildren == null ? expectedGlobalChildren : postStrategyExpectedGlobalChildren,
+ postStrategyExpectedLocalChildren == null ? expectedLocalChildren : postStrategyExpectedLocalChildren,
+ "(pre-strategy application)");
+
+ traversal = traversal.clone();
+
+ verifyExpectedParents(postStrategyExpectedGlobalChildren == null ? expectedGlobalChildren : postStrategyExpectedGlobalChildren,
+ postStrategyExpectedLocalChildren == null ? expectedLocalChildren : postStrategyExpectedLocalChildren,
+ "(cloned traversal, pre-strategy application)");
+ }
+
+ private void verifyExpectedParents(List<Traversal.Admin<?,?>> expectedGlobalChildren, List<Traversal.Admin<?,?>> expectedLocalChildren, String messageSuffix) {
+ List<Step> steps = TraversalHelper.getStepsOfAssignableClass(stepClass, traversal);
+ assertTrue(String.format("Expected a single step of class %s to test, found %d %s", stepClass.getName(), steps.size(), messageSuffix), steps.size() == 1);
+ assertTrue(String.format("Expected step to implement TraversalParent %s", messageSuffix), steps.get(0) instanceof TraversalParent);
+
+ TraversalParent testStep = (TraversalParent) steps.get(0);
+ assertThat(String.format("getGlobalChildren() did not produce the expected results %s", messageSuffix), testStep.getGlobalChildren(), containsInAnyOrder(expectedGlobalChildren.toArray()));
Review Comment:
Nit: this `assertThat` method is deprecated
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@tinkerpop.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Fix TraversalParent implementations for Placeholder steps [tinkerpop]
Posted by "Cole-Greer (via GitHub)" <gi...@apache.org>.
Cole-Greer commented on code in PR #3209:
URL: https://github.com/apache/tinkerpop/pull/3209#discussion_r2373762184
##########
gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/lambda/GValueConstantTraversal.java:
##########
@@ -57,6 +57,17 @@ public boolean equals(final Object other) {
return constantTraversal.equals(other);
}
+ @Override
+ public GValueConstantTraversal<S, E> clone() {
+ GValueConstantTraversal<S, E> clone = new GValueConstantTraversal<>(GValue.of(this.end.getName(), this.end.get()));
+ try {
+ clone.setGValueManager(this.getGValueManager().clone());
+ } catch (CloneNotSupportedException e) { //TODO:: handle properly
Review Comment:
I have updated this method to include a call to `super.clone()`. I will do a further followup of cloning of GValues/StepPlaceholders in a followup PR.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@tinkerpop.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Fix TraversalParent implementations for Placeholder steps [tinkerpop]
Posted by "Cole-Greer (via GitHub)" <gi...@apache.org>.
Cole-Greer commented on code in PR #3209:
URL: https://github.com/apache/tinkerpop/pull/3209#discussion_r2373005488
##########
gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/TraversalParent.java:
##########
@@ -31,14 +33,31 @@
import java.util.Set;
/**
+ * Indicates that a step can contain child Traversals. Any step which implements this interface should override at least
Review Comment:
That's definitely a compelling idea and would be an improvement over the status quo. I'm not sure about half starting it here in this PR though. I would rather such a change be made all at once, as I'm worried there are a few steps which will be difficult to adapt to the annotation model, and may require tweaking the design. The steps which come to mind which may be difficult are the ones like AddEdge which currently shove all of their arguments into a `Parameters` object and use that to manage child Traversals.
I think this might make for a good JIRA. I don't think it's prohibitively large to tackle all at once as a standalone task. There's only about 60 implementations of TraversalParent when you factor out abstract classes and such, and there's really only a handful of unique patterns within those, they are mostly simple and repetitive.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@tinkerpop.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Fix TraversalParent implementations for Placeholder steps [tinkerpop]
Posted by "andreachild (via GitHub)" <gi...@apache.org>.
andreachild commented on code in PR #3209:
URL: https://github.com/apache/tinkerpop/pull/3209#discussion_r2370911153
##########
gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AbstractAddElementStepPlaceholder.java:
##########
@@ -175,6 +188,9 @@ public void addProperty(Object key, Object value) {
if (key instanceof GValue) {
throw new IllegalArgumentException("GValue cannot be used as a property key");
}
+ if (key instanceof Traversal) {
+ this.integrateChild(((Traversal<?, ?>) key).asAdmin());
Review Comment:
Should `integrateChild` also be called by `setLabel` method if the label is a traversal?
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@tinkerpop.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Fix TraversalParent implementations for Placeholder steps [tinkerpop]
Posted by "Cole-Greer (via GitHub)" <gi...@apache.org>.
Cole-Greer commented on code in PR #3209:
URL: https://github.com/apache/tinkerpop/pull/3209#discussion_r2373558959
##########
gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AbstractMergeElementStepPlaceholder.java:
##########
@@ -65,14 +67,67 @@ protected Traverser.Admin<E> processNextStart() throws NoSuchElementException {
@Override
public AbstractMergeElementStepPlaceholder<S, E> clone() {
- return (AbstractMergeElementStepPlaceholder<S, E>) super.clone();
+ AbstractMergeElementStepPlaceholder<S, E> clone = (AbstractMergeElementStepPlaceholder<S, E>) super.clone();
+ if (mergeTraversal != null){
+ clone.setMerge(mergeTraversal.clone());
+ }
+ if (onMatchTraversal != null) {
+ clone.setOnMatch(onMatchTraversal.clone());
+ }
+ if (onCreateTraversal != null) {
+ clone.setOnCreate(onCreateTraversal.clone());
+ }
+
+ // deep clone properties
+ clone.properties = new HashMap<>();
+ for (Map.Entry<Object, List<Object>> entry : this.properties.entrySet()) {
+ final Object key = entry.getKey();
+ final List<Object> oldValues = entry.getValue();
+ final List<Object> newValues = new ArrayList<>(oldValues.size());
+ for (Object v : oldValues) {
+ if (v instanceof Traversal) {
+ newValues.add(((Traversal<?, ?>) v).asAdmin().clone());
+ } else if (v instanceof GValue) {
+ try {
+ newValues.add(((GValue) v).clone());
+ } catch (CloneNotSupportedException e) {
+ throw new RuntimeException(e);
+ }
+ } else {
+ newValues.add(v);
+ }
+ }
+ clone.properties.put(key, newValues);
+ }
+ return clone;
}
@Override
public Set<TraverserRequirement> getRequirements() {
return super.getRequirements();
}
+ @Override
+ public void setTraversal(final Traversal.Admin<?, ?> parentTraversal) {
+ super.setTraversal(parentTraversal);
+ this.getLocalChildren().forEach(this::integrateChild);
Review Comment:
Every child traversal needs to be integrated when it's added to the step. Within the constructor, the only child traversal present is `mergeTraversal`, which gets integrated in the constructor. Any calls to `setOnMatch()`, `setOnCreate()`, or `setMerge()` result in integrating the newly added child traversal.
When `setTraversal()` is called, `this` step is being assigned a new parent, and we need to re-integrate all children such that their side effects and GValueManagers are synced with the new parent.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@tinkerpop.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Fix TraversalParent implementations for Placeholder steps [tinkerpop]
Posted by "andreachild (via GitHub)" <gi...@apache.org>.
andreachild commented on code in PR #3209:
URL: https://github.com/apache/tinkerpop/pull/3209#discussion_r2370933364
##########
gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AbstractMergeElementStepPlaceholder.java:
##########
Review Comment:
Looking at the `clone` logic, it appears that `properties` can contain traversals. If that is the case then `addProperty` should also call `integrateChild`.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@tinkerpop.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Fix TraversalParent implementations for Placeholder steps [tinkerpop]
Posted by "Cole-Greer (via GitHub)" <gi...@apache.org>.
Cole-Greer commented on code in PR #3209:
URL: https://github.com/apache/tinkerpop/pull/3209#discussion_r2373401373
##########
gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AbstractAddElementStepPlaceholder.java:
##########
@@ -175,6 +188,9 @@ public void addProperty(Object key, Object value) {
if (key instanceof GValue) {
throw new IllegalArgumentException("GValue cannot be used as a property key");
}
+ if (key instanceof Traversal) {
+ this.integrateChild(((Traversal<?, ?>) key).asAdmin());
Review Comment:
Historically speaking, no. The main purpose of integrateChild is to ensure the child is consistent with the parent (has the correct parent set, both traversals merge their side effects, and now they also merge their GValueManagers). Historically speaking there hasn't been much concern about the state of the child after it has been removed, as it is no longer a concern for the TraversalParent. One could argue that the removed child should be given an EmptyTraversal as a new parent, however this has never been enforced in the past.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@tinkerpop.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Fix TraversalParent implementations for Placeholder steps [tinkerpop]
Posted by "andreachild (via GitHub)" <gi...@apache.org>.
andreachild commented on PR #3209:
URL: https://github.com/apache/tinkerpop/pull/3209#issuecomment-3330642294
VOTE +1 pending minor fixes to tests
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@tinkerpop.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Fix TraversalParent implementations for Placeholder steps [tinkerpop]
Posted by "Cole-Greer (via GitHub)" <gi...@apache.org>.
Cole-Greer commented on code in PR #3209:
URL: https://github.com/apache/tinkerpop/pull/3209#discussion_r2356955740
##########
gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/lambda/GValueConstantTraversal.java:
##########
@@ -57,6 +57,17 @@ public boolean equals(final Object other) {
return constantTraversal.equals(other);
}
+ @Override
+ public GValueConstantTraversal<S, E> clone() {
+ GValueConstantTraversal<S, E> clone = new GValueConstantTraversal<>(GValue.of(this.end.getName(), this.end.get()));
+ try {
+ clone.setGValueManager(this.getGValueManager().clone());
+ } catch (CloneNotSupportedException e) { //TODO:: handle properly
Review Comment:
There needs to be a revisit for cloning of GValues, GValueManager, and StepPlaceholders. I consider this out of scope for this PR and intend to address this soon.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@tinkerpop.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Fix TraversalParent implementations for Placeholder steps [tinkerpop]
Posted by "spmallette (via GitHub)" <gi...@apache.org>.
spmallette commented on PR #3209:
URL: https://github.com/apache/tinkerpop/pull/3209#issuecomment-3306891283
taking some build errors it seems - also, i'd think you need to backport changes for `DateDiffStep` and `TraversalSelectStep`.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@tinkerpop.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Fix TraversalParent implementations for Placeholder steps [tinkerpop]
Posted by "Cole-Greer (via GitHub)" <gi...@apache.org>.
Cole-Greer commented on PR #3209:
URL: https://github.com/apache/tinkerpop/pull/3209#issuecomment-3308493321
> taking some build errors it seems - also, i'd think you need to backport changes for `DateDiffStep` and `TraversalSelectStep`.
Ahh, new issues snuck their in with a last minute tweak to merge. Should be good now.
I'll CTR the fixes to `DateDiffStep` and `TraversalSelectStep` back to 3.7-dev separately.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@tinkerpop.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Fix TraversalParent implementations for Placeholder steps [tinkerpop]
Posted by "andreachild (via GitHub)" <gi...@apache.org>.
andreachild commented on code in PR #3209:
URL: https://github.com/apache/tinkerpop/pull/3209#discussion_r2376972961
##########
gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/TraversalParentTest.java:
##########
@@ -0,0 +1,1028 @@
+/*
+ * 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 java.time.OffsetDateTime;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.commons.configuration2.MapConfiguration;
+import org.apache.tinkerpop.gremlin.process.traversal.Operator;
+import org.apache.tinkerpop.gremlin.process.traversal.Pick;
+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.GraphTraversalSource;
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
+import org.apache.tinkerpop.gremlin.process.traversal.lambda.AbstractLambdaTraversal;
+import org.apache.tinkerpop.gremlin.process.traversal.lambda.ConstantTraversal;
+import org.apache.tinkerpop.gremlin.process.traversal.Merge;
+import org.apache.tinkerpop.gremlin.process.traversal.Scope;
+import org.apache.tinkerpop.gremlin.process.traversal.P;
+import org.apache.tinkerpop.gremlin.process.traversal.lambda.LoopTraversal;
+import org.apache.tinkerpop.gremlin.process.traversal.lambda.PredicateTraversal;
+import org.apache.tinkerpop.gremlin.process.traversal.lambda.TrueTraversal;
+import org.apache.tinkerpop.gremlin.process.traversal.lambda.ValueTraversal;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.AddEdgeStepContract;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.AddVertexStepContract;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.CallStepContract;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.MergeStepContract;
+import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.AddPropertyStepContract;
+import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.AggregateGlobalStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.AggregateLocalStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.filter.AndStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.filter.OrStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.branch.BranchStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.branch.ChooseStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.CoalesceStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.CombineStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.ConcatStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.DateDiffStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.filter.DedupGlobalStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.DifferenceStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.DisjunctStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.FormatStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.GroupCountStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.GroupCountSideEffectStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.GroupStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.IntersectStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.branch.LocalStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.MatchStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.MathStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.MergeStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.filter.NotStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.branch.OptionalStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.OrderGlobalStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.OrderLocalStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.filter.PathFilterStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.PathStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.ProductStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.ProjectStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.PropertyMapStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.branch.RepeatStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.SackValueStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.filter.SampleGlobalStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.SelectOneStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.SelectStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.TraversalSelectStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.filter.TraversalFilterStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.TraversalFlatMapStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.TraversalMapStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.TraversalSideEffectStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.TreeStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.TreeSideEffectStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.branch.UnionStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.filter.WherePredicateStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.filter.WhereTraversalStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.ComputerAwareStep;
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.GValueReductionStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper;
+import org.apache.tinkerpop.gremlin.structure.T;
+import org.apache.tinkerpop.gremlin.structure.service.Service;
+import org.apache.tinkerpop.gremlin.structure.service.ServiceRegistry;
+
+import org.apache.tinkerpop.gremlin.structure.util.GraphFactoryTest;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import static org.apache.tinkerpop.gremlin.process.traversal.AnonymousTraversalSource.traversal;
+import static org.hamcrest.Matchers.containsInAnyOrder;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+
+@RunWith(Parameterized.class)
+public class TraversalParentTest {
+
+ private static ServiceRegistry mockedRegistry= mock(ServiceRegistry.class);
+ private static Service<?, ?> mockedService = mock(Service.class);
+ private static GraphTraversalSource g = traversal().with(GraphFactoryTest.MockGraph.open(new MapConfiguration(Map.of("service-registry", mockedRegistry))));
+
+ @BeforeClass
+ public static void setupClass() {
+ when(mockedRegistry.get(any(), anyBoolean(), any())).thenReturn(mockedService);
+ when(mockedService.getRequirements()).thenReturn(Set.of());
+ }
+
+ @Parameterized.Parameter(value = 0)
+ public Class stepClass;
+
+ @Parameterized.Parameter(value = 1)
+ public Traversal.Admin traversal;
+
+ @Parameterized.Parameter(value = 2)
+ public List<Traversal.Admin<?,?>> expectedGlobalChildren;
+
+ @Parameterized.Parameter(value = 3)
+ public List<Traversal.Admin<?,?>> expectedLocalChildren;
+
+ /**
+ * Overrides expectedGlobalChildren for assertions following strategy execution. If left null, expectedGlobalChildren is used instead.
+ */
+ @Parameterized.Parameter(value = 4)
+ public List<Traversal.Admin<?,?>> postStrategyExpectedGlobalChildren;
+
+ /**
+ * Overrides expectedLocalChildren for assertions following strategy execution. If left null, expectedLocalChildren is used instead.
+ */
+ @Parameterized.Parameter(value = 5)
+ public List<Traversal.Admin<?,?>> postStrategyExpectedLocalChildren;
+
+ @Parameterized.Parameters(name = "{0}")
+ public static Iterable<Object[]> data() {
+ return Arrays.asList(new Object[][]{
+ {AddVertexStepContract.class,
+ g.addV("label").property("name", __.constant("cole")),
+ List.of(),
+ List.of(__.constant("cole"), new ConstantTraversal<>("label")),
+ null, null
+ },
+ {AddVertexStepContract.class,
+ g.addV(__.constant("label")).property("name", __.constant("cole")),
+ List.of(),
+ List.of(__.constant("cole"), __.constant("label")),
+ null, null
+ },
+ {AddVertexStepContract.class,
+ g.addV().property("name", __.constant("cole")).property(T.label, __.constant("label")).property(T.id, __.constant(1)),
+ List.of(),
+ List.of(__.constant("cole"), __.constant("label"), __.constant(1)),
+ null, null
+ },
+ {AddVertexStepContract.class,
+ g.addV(GValue.of("l", "label")).property("name", GValue.of("name", "cole")),
+ List.of(),
+ List.of(new ConstantTraversal<>("label")), // Property is not stored as a child traversal in this case
+ null, null
+ },
+ {AddVertexStepContract.class,
+ g.addV("label").property(__.constant("name"), __.constant("cole")),
+ List.of(),
+ List.of(__.constant("name"), __.constant("cole"), new ConstantTraversal<>("label")),
+ null, null
+ },
+ {AddVertexStepContract.class,
+ g.inject(1).addV("label").property("name", __.constant("cole")),
+ List.of(),
+ List.of(__.constant("cole"), new ConstantTraversal<>("label")),
+ null, null
+ },
+ {AddVertexStepContract.class,
+ g.inject(1).addV(__.constant("label")).property("name", __.constant("cole")),
+ List.of(),
+ List.of(__.constant("cole"), __.constant("label")),
+ null, null
+ },
+ {AddVertexStepContract.class,
+ g.inject(1).addV(GValue.of("l", "label")).property("name", GValue.of("name", "cole")),
+ List.of(),
+ List.of(new ConstantTraversal<>("label")), // Property is not stored as a child traversal in this case
+ null, null
+ },
+ {AddVertexStepContract.class,
+ g.inject(1).addV("label").property(__.constant("name"), __.constant("cole")),
+ List.of(),
+ List.of(__.constant("name"), __.constant("cole"), new ConstantTraversal<>("label")),
+ null, null
+ },
+ {AddEdgeStepContract.class,
+ g.addE("label").from(1).to(2).property("name", __.constant("cole")),
+ List.of(),
+ List.of(__.constant("cole"), new ConstantTraversal<>("label"), __.constant(1), __.constant(2)),
+ null, null
+ },
+ {AddEdgeStepContract.class,
+ g.addE("label").from(__.V(1)).to(__.V(2))
+ .property("name", __.constant("cole"))
+ .property(T.id, __.constant(5)),
+ List.of(),
+ List.of(__.constant("cole"), new ConstantTraversal<>("label"), __.V(1), __.V(2), __.constant(5)),
+ null, null
+ },
+ {AddEdgeStepContract.class,
+ g.addE("label").from(__.V(1)).to(__.V(2)).property("name", __.constant("cole")),
+ List.of(),
+ List.of(__.constant("cole"), new ConstantTraversal<>("label"), __.V(1), __.V(2)),
+ null, null
+ },
+ {AddEdgeStepContract.class,
+ g.addE(GValue.of("l", "label")).from(GValue.of("from", 1)).to(GValue.of("to", 2)).property("name", GValue.of("name", "cole")),
+ List.of(),
+ List.of(new ConstantTraversal<>("label"), new ConstantTraversal(1), new ConstantTraversal(2)),
+ null, null
+ },
+ {AddEdgeStepContract.class,
+ g.addE("label").from(1).to(2).property(__.constant("name"), __.constant("cole")),
+ List.of(),
+ List.of(__.constant("name"), __.constant("cole"), new ConstantTraversal<>("label"), __.constant(1), __.constant(2)),
+ null, null
+ },
+ {AddEdgeStepContract.class,
+ g.inject(1).addE("label").from(1).to(2).property("name", __.constant("cole")),
+ List.of(),
+ List.of(__.constant("cole"), new ConstantTraversal<>("label"), __.constant(1), __.constant(2)),
+ null, null
+ },
+ {AddEdgeStepContract.class,
+ g.inject(1).addE("label").from(__.V(1)).to(__.V(2)).property("name", __.constant("cole")),
+ List.of(),
+ List.of(__.constant("cole"), new ConstantTraversal<>("label"), __.V(1), __.V(2)),
+ null, null
+ },
+ {AddEdgeStepContract.class,
+ g.inject(1).addE(GValue.of("l", "label")).from(GValue.of("from", 1)).to(GValue.of("to", 2)).property("name", GValue.of("name", "cole")),
+ List.of(),
+ List.of(new ConstantTraversal<>("label"), new ConstantTraversal(1), new ConstantTraversal(2)),
+ null, null
+ },
+ {AddEdgeStepContract.class,
+ g.inject(1).addE("label").from(1).to(2).property(__.constant("name"), __.constant("cole")),
+ List.of(),
+ List.of(__.constant("name"), __.constant("cole"), new ConstantTraversal<>("label"), __.constant(1), __.constant(2)),
+ null, null
+ },
+ {CallStepContract.class,
+ g.call("service"),
+ List.of(),
+ List.of(),
+ null, null
+ },
+ {CallStepContract.class,
+ g.call("service").with("key", __.constant("value")),
+ List.of(),
+ List.of(__.constant("value")),
+ null, null
+ },
+ {CallStepContract.class,
+ g.call("service", __.constant(Map.of("key", "value"))),
+ List.of(),
+ List.of(__.constant(Map.of("key", "value"))),
+ null, null
+ },
+ {CallStepContract.class,
+ g.call("service", __.constant(Map.of("key", "value"))).with("key", __.constant("value")),
+ List.of(),
+ List.of(__.constant(Map.of("key", "value")), __.constant("value")),
+ null, null
+ },
+ {AddPropertyStepContract.class,
+ g.inject(1).property("key", "value"),
+ List.of(),
+ List.of(new ConstantTraversal<>("value")), // constant Value's are internally boxed in Traversals
+ null, null
+ },
+ {AddPropertyStepContract.class,
+ g.inject(1).property("key", __.constant("value")),
+ List.of(),
+ List.of(__.constant("value")),
+ null, null
+ },
+ {AddPropertyStepContract.class,
+ g.inject(1).property(__.constant("key"), __.constant("value")),
+ List.of(),
+ List.of(__.constant("key"), __.constant("value")),
+ null, null
+ },
+ {AddPropertyStepContract.class,
+ g.addV().property("name", "value", "metaKey", "metaValue"),
+ List.of(),
+ List.of(new ConstantTraversal<>("value")), // constant Value's are internally boxed in Traversals
+ null, null
+ },
+ {AddPropertyStepContract.class,
+ g.addV().property("name", __.constant("value"), "metaKey", __.constant("metaValue")),
+ List.of(),
+ List.of(__.constant("value"), __.constant("metaValue")),
+ null, null
+ },
+ {AddPropertyStepContract.class,
+ g.addV().property(__.constant("name"), __.constant("value"), __.constant("metaKey"), __.constant("metaValue")),
+ List.of(),
+ List.of(__.constant("name"), __.constant("value"), __.constant("metaKey"), __.constant("metaValue")),
+ null, null
+ },
+ {AddPropertyStepContract.class,
+ g.addV().property("name", "value", "metaKey1", "metaValue1", "metaKey2", "metaValue2"),
+ List.of(),
+ List.of(new ConstantTraversal<>("value")), // constant Value's are internally boxed in Traversals
+ null, null
+ },
+ {MergeStepContract.class,
+ g.mergeV(Map.of("name", "marko")),
+ List.of(),
+ List.of(new ConstantTraversal<>(Map.of("name", "marko"))), // constant MergeMap's are internally boxed in Traversals
+ null, null
+ },
+ {MergeStepContract.class,
+ g.mergeV(__.constant(Map.of("name", "marko"))),
+ List.of(),
+ List.of(__.constant(Map.of("name", "marko"))),
+ null, null
+ },
+ {MergeStepContract.class,
+ g.mergeV(Map.of("name", "marko")).option(Merge.onCreate, __.constant(Map.of("age", 29))),
+ List.of(),
+ List.of(new ConstantTraversal<>(Map.of("name", "marko")), __.constant(Map.of("age", 29))), // constant MergeMap's are internally boxed in Traversals
+ null, null
+ },
+ {MergeStepContract.class,
+ g.mergeV(__.constant(Map.of("name", "marko"))).option(Merge.onCreate, __.constant(Map.of("age", 29))).option(Merge.onMatch, __.constant(Map.of("updated", true))),
+ List.of(),
+ List.of(__.constant(Map.of("name", "marko")), __.constant(Map.of("age", 29)), __.constant(Map.of("updated", true))),
+ null, null
+ },
+ {MergeStepContract.class,
+ g.mergeE(Map.of(T.label, "knows")),
+ List.of(),
+ List.of(new ConstantTraversal<>(Map.of(T.label, "knows"))), // constant MergeMap's are internally boxed in Traversals
+ null, null
+ },
+ {MergeStepContract.class,
+ g.mergeE(__.constant(Map.of(T.label, "knows"))),
+ List.of(),
+ List.of(__.constant(Map.of(T.label, "knows"))),
+ null, null
+ },
+ {MergeStepContract.class,
+ g.mergeE(Map.of(T.label, "knows")).option(Merge.onCreate, __.constant(Map.of("weight", 0.5))),
+ List.of(),
+ List.of(new ConstantTraversal<>(Map.of(T.label, "knows")), __.constant(Map.of("weight", 0.5))), // constant MergeMap's are internally boxed in Traversals
+ null, null
+ },
+ {MergeStepContract.class,
+ g.mergeE(__.constant(Map.of(T.label, "knows"))).option(Merge.onCreate, __.constant(Map.of("weight", 0.5))).option(Merge.onMatch, __.constant(Map.of("updated", true))),
+ List.of(),
+ List.of(__.constant(Map.of(T.label, "knows")), __.constant(Map.of("weight", 0.5)), __.constant(Map.of("updated", true))),
+ null, null
+ },
+ {AggregateGlobalStep.class,
+ g.V().aggregate("x"),
+ List.of(),
+ List.of(),
+ null, null
+ },
+ {AggregateGlobalStep.class,
+ g.V().aggregate("x").by("name"),
+ List.of(),
+ List.of(new ValueTraversal("name")),
+ null, null
+ },
+ {AggregateGlobalStep.class,
+ g.V().aggregate("x").by(__.constant("value")),
+ List.of(),
+ List.of(__.constant("value")),
+ null, null
+ },
+ {AggregateLocalStep.class,
+ g.V().aggregate(Scope.local, "x"),
+ List.of(),
+ List.of(),
+ null, null
+ },
+ {AggregateLocalStep.class,
+ g.V().aggregate(Scope.local, "x").by("name"),
+ List.of(),
+ List.of(new ValueTraversal("name")),
+ null, null
+ },
+ {AggregateLocalStep.class,
+ g.V().aggregate(Scope.local, "x").by(__.constant("value")),
+ List.of(),
+ List.of(__.constant("value")),
+ null, null
+ },
+ {AndStep.class,
+ g.V().and(__.outE(), __.has("age", P.gte(32))),
+ List.of(),
+ List.of(__.outE(), __.has("age", P.gte(32))),
+ null, null
+ },
+ {OrStep.class,
+ g.V().or(__.outE(), __.has("age", P.gte(32))),
+ List.of(),
+ List.of(__.outE(), __.has("age", P.gte(32))),
+ null, null
+ },
+ {BranchStep.class,
+ g.V().branch(__.label()).option("person", __.values("name")).option("software", __.values("lang")),
+ List.of(appendComputerAwareEndStep(__.values("name")), appendComputerAwareEndStep(__.values("lang"))),
+ List.of(__.label(), new PredicateTraversal<>(P.eq("person")), new PredicateTraversal<>(P.eq("software"))), // option keys are wrapped in PredicateTraversals internally
+ null, null
+ },
+ {ChooseStep.class,
+ g.V().choose(__.out().count()).option(2L, __.values("name")).option(3L, __.values("age")),
+ List.of(appendComputerAwareEndStep(__.values("name")), appendComputerAwareEndStep(__.values("age")), appendComputerAwareEndStep(__.identity()), appendComputerAwareEndStep(__.identity())),
+ List.of(__.out().count(), new PredicateTraversal<>(P.eq(2L)), new PredicateTraversal<>(P.eq(3L))), // option keys are wrapped in PredicateTraversals internally
+ null, List.of(__.outE().count(), new PredicateTraversal<>(P.eq(2L)), new PredicateTraversal<>(P.eq(3L)))
+ },
+ {CoalesceStep.class,
+ g.V().coalesce(__.out("knows"), __.out("created")),
+ List.of(),
+ List.of(__.out("knows"), __.out("created")),
+ null, null
+ },
+ {CombineStep.class,
+ g.V().fold().combine(__.constant(List.of(1, 2, 3))),
+ List.of(),
+ List.of(__.constant(List.of(1, 2, 3))),
+ null, null
+ },
+ {ConcatStep.class,
+ g.inject("a", "b").concat(__.constant("c"), __.constant("d")),
+ List.of(),
+ List.of(__.constant("c"), __.constant("d")),
+ null, null
+ },
+ {DateDiffStep.class,
+ g.inject(OffsetDateTime.parse("1970-01-01T00:00:00.000Z")).dateDiff(__.constant(OffsetDateTime.parse("1970-02-01T00:00:00.000Z"))),
+ List.of(),
+ List.of(__.constant(OffsetDateTime.parse("1970-02-01T00:00:00.000Z"))),
+ null, null
+ },
+ {DedupGlobalStep.class,
+ g.V().dedup(),
+ List.of(),
+ List.of(),
+ null, null
+ },
+ {DedupGlobalStep.class,
+ g.V().dedup().by("name"),
+ List.of(),
+ List.of(new ValueTraversal("name")),
+ null, null
+ },
+ {DedupGlobalStep.class,
+ g.V().dedup().by(__.constant("value")),
+ List.of(),
+ List.of(__.constant("value")),
+ null, null
+ },
+ {DifferenceStep.class,
+ g.V().fold().difference(__.constant(List.of(1, 2, 3))),
+ List.of(),
+ List.of(__.constant(List.of(1, 2, 3))),
+ null, null
+ },
+ {DisjunctStep.class,
+ g.V().fold().disjunct(__.constant(List.of(1, 2, 3))),
+ List.of(),
+ List.of(__.constant(List.of(1, 2, 3))),
+ null, null
+ },
+ {FormatStep.class,
+ g.V().format("Hello %{name}"),
+ List.of(),
+ List.of(),
+ null, null
+ },
+ {FormatStep.class,
+ g.V().format("Hello %{name}").by("name"),
+ List.of(),
+ List.of(new ValueTraversal("name")),
+ null, null
+ },
+ {FormatStep.class,
+ g.V().format("Hello %{name}").by(__.constant("value")),
+ List.of(),
+ List.of(__.constant("value")),
+ null, null
+ },
+ {GroupCountStep.class,
+ g.V().groupCount(),
+ List.of(),
+ List.of(),
+ null, null
+ },
+ {GroupCountStep.class,
+ g.V().groupCount().by("name"),
+ List.of(),
+ List.of(new ValueTraversal("name")),
+ null, null
+ },
+ {GroupCountStep.class,
+ g.V().groupCount().by(__.constant("value")),
+ List.of(),
+ List.of(__.constant("value")),
+ null, null
+ },
+ {GroupCountSideEffectStep.class,
+ g.V().groupCount("x"),
+ List.of(),
+ List.of(),
+ null, null
+ },
+ {GroupCountSideEffectStep.class,
+ g.V().groupCount("x").by("name"),
+ List.of(),
+ List.of(new ValueTraversal("name")),
+ null, null
+ },
+ {GroupCountSideEffectStep.class,
+ g.V().groupCount("x").by(__.constant("value")),
+ List.of(),
+ List.of(__.constant("value")),
+ null, null
+ },
+ {GroupStep.class,
+ g.V().group(),
+ List.of(),
+ List.of(__.fold()),
+ null, null
+ },
+ {GroupStep.class,
+ g.V().group().by("name"),
+ List.of(),
+ List.of(new ValueTraversal("name"), __.fold()),
+ null, null
+ },
+ {GroupStep.class,
+ g.V().group().by("name").by("age"),
+ List.of(),
+ List.of(new ValueTraversal("name"), __.map(new ValueTraversal("age")).fold()),
+ null, null
+ },
+ {GroupStep.class,
+ g.V().group().by(__.constant("key")).by(__.constant("value")),
+ List.of(),
+ List.of(__.constant("key"), __.constant("value")),
+ null, null
+ },
+ {IntersectStep.class,
+ g.V().fold().intersect(__.constant(List.of(1, 2, 3))),
+ List.of(),
+ List.of(__.constant(List.of(1, 2, 3))),
+ null, null
+ },
+ {LocalStep.class,
+ g.V().local(__.outE().count()),
+ List.of(),
+ List.of(__.outE().count()),
+ null, null
+ },
+ {MatchStep.class,
+ g.V().match(__.as("a").out().as("b"), __.as("b").in().as("c")),
+ List.of(generateMatchChildTraversal("a", "b", __.out().asAdmin()), generateMatchChildTraversal("b", "c", __.in().asAdmin())),
+ List.of(),
+ null, null
+ },
+ {MathStep.class,
+ g.V().math("_ + 1"),
+ List.of(),
+ List.of(),
+ null, null
+ },
+ {MathStep.class,
+ g.V().math("_ + 1").by("age"),
+ List.of(),
+ List.of(new ValueTraversal("age")),
+ null, null
+ },
+ {MathStep.class,
+ g.V().math("_ + _").by("age").by(__.constant(10)),
+ List.of(),
+ List.of(new ValueTraversal("age"), __.constant(10)),
+ null, null
+ },
+ {MergeStep.class,
+ g.V().fold().merge(__.constant(List.of(1, 2, 3))),
+ List.of(),
+ List.of(__.constant(List.of(1, 2, 3))),
+ null, null
+ },
+ {NotStep.class,
+ g.V().not(__.has("age", P.gt(27))),
+ List.of(),
+ List.of(__.has("age", P.gt(27))),
+ null, null
+ },
+ {OptionalStep.class,
+ g.V().optional(__.out("knows")),
+ List.of(),
+ List.of(__.out("knows")),
+ null, null
+ },
+ {OrderGlobalStep.class,
+ g.V().order(),
+ List.of(),
+ List.of(),
+ null, null
+ },
+ {OrderGlobalStep.class,
+ g.V().order().by("name"),
+ List.of(),
+ List.of(new ValueTraversal("name")),
+ null, null
+ },
+ {OrderGlobalStep.class,
+ g.V().order().by("name").by(__.constant("value")),
+ List.of(),
+ List.of(new ValueTraversal("name"), __.constant("value")),
+ null, null
+ },
+ {OrderLocalStep.class,
+ g.V().fold().order(Scope.local),
+ List.of(),
+ List.of(),
+ null, null
+ },
+ {OrderLocalStep.class,
+ g.V().fold().order(Scope.local).by("name"),
+ List.of(),
+ List.of(new ValueTraversal("name")),
+ null, null
+ },
+ {OrderLocalStep.class,
+ g.V().fold().order(Scope.local).by(__.constant("value")),
+ List.of(),
+ List.of(__.constant("value")),
+ null, null
+ },
+ {PathFilterStep.class,
+ g.V().simplePath(),
+ List.of(),
+ List.of(),
+ null, null
+ },
+ {PathFilterStep.class,
+ g.V().cyclicPath(),
+ List.of(),
+ List.of(),
+ null, null
+ },
+ {PathFilterStep.class,
+ g.V().simplePath().by("name"),
+ List.of(),
+ List.of(new ValueTraversal("name")),
+ null, null
+ },
+ {PathFilterStep.class,
+ g.V().simplePath().by(__.constant("value")),
+ List.of(),
+ List.of(__.constant("value")),
+ null, null
+ },
+ {PathFilterStep.class,
+ g.V().cyclicPath().by("age").by(__.constant("value")),
+ List.of(),
+ List.of(new ValueTraversal("age"), __.constant("value")),
+ null, null
+ },
+ {PathStep.class,
+ g.V().path(),
+ List.of(),
+ List.of(),
+ null, null
+ },
+ {PathStep.class,
+ g.V().out().path().by("age").by("name"),
+ List.of(),
+ List.of(new ValueTraversal("age"), new ValueTraversal("name")),
+ null, null
+ },
+ {PathStep.class,
+ g.V().path().by(__.constant("value")),
+ List.of(),
+ List.of(__.constant("value")),
+ null, null
+ },
+ {ProductStep.class,
+ g.V().fold().product(__.constant(List.of(1, 2, 3))),
+ List.of(),
+ List.of(__.constant(List.of(1, 2, 3))),
+ null, null
+ },
+ {ProjectStep.class,
+ g.V().project("a", "b").by("name").by("age"),
+ List.of(),
+ List.of(new ValueTraversal("name"), new ValueTraversal("age")),
+ null, null
+ },
+ {ProjectStep.class,
+ g.V().project("x").by(__.constant("value")),
+ List.of(),
+ List.of(__.constant("value")),
+ null, null
+ },
+ {PropertyMapStep.class,
+ g.V().valueMap(),
+ List.of(),
+ List.of(),
+ null, null
+ },
+ {PropertyMapStep.class,
+ g.V().valueMap().by(__.constant("transformed")),
+ List.of(),
+ List.of(__.constant("transformed")),
+ null, null
+ },
+ {RepeatStep.class,
+ g.V().repeat(__.out()).emit().times(2),
+ List.of(appendRepeatEndStep(__.out())),
+ List.of(new LoopTraversal<>(2), TrueTraversal.instance()),
+ null, null
+ },
+ {RepeatStep.class,
+ g.V().repeat(__.out()).until(__.has("name", "josh")),
+ List.of(appendRepeatEndStep(__.out())),
+ List.of(__.has("name", "josh")),
+ null, null
+ },
+ {RepeatStep.class,
+ g.V().repeat(__.out()).emit(__.has("age")).until(__.has("name", "josh")),
+ List.of(appendRepeatEndStep(__.out())),
+ List.of(__.has("name", "josh"), __.has("age")),
+ null, List.of(__.has("name", "josh"), __.filter(__.properties("age"))),
+ },
+ {SackValueStep.class,
+ g.withSack(0).V().sack(Operator.sum),
+ List.of(),
+ List.of(),
+ null, null
+ },
+ {SackValueStep.class,
+ g.withSack(0).V().sack(Operator.sum).by("age"),
+ List.of(),
+ List.of(new ValueTraversal("age")),
+ null, null
+ },
+ {SackValueStep.class,
+ g.withSack(0).V().sack(Operator.sum).by(__.constant("age")),
+ List.of(),
+ List.of(__.constant("age")),
+ null, null
+ },
+ {SampleGlobalStep.class,
+ g.V().sample(2),
+ List.of(),
+ List.of(new ConstantTraversal<>(1.0)),
+ null, null
+ },
+ {SampleGlobalStep.class,
+ g.E().sample(2).by("weight"),
+ List.of(),
+ List.of(new ValueTraversal("weight")),
+ null, null
+ },
+ {SampleGlobalStep.class,
+ g.E().sample(2).by(__.constant("weight")),
+ List.of(),
+ List.of(__.constant("weight")),
+ null, null
+ },
+ {SelectOneStep.class,
+ g.V().as("a").select("a"),
+ List.of(),
+ List.of(),
+ null, null
+ },
+ {SelectOneStep.class,
+ g.V().as("a").select("a").by("name"),
+ List.of(),
+ List.of(new ValueTraversal("name")),
+ null, null
+ },
+ {SelectOneStep.class,
+ g.V().as("a").select("a").by(__.constant("value")),
+ List.of(),
+ List.of(__.constant("value")),
+ null, null
+ },
+ {SelectStep.class,
+ g.V().as("a").as("b").select("a", "b"),
+ List.of(),
+ List.of(),
+ null, null
+ },
+ {SelectStep.class,
+ g.V().as("a").as("b").select("a", "b").by("name"),
+ List.of(),
+ List.of(new ValueTraversal("name")),
+ null, null
+ },
+ {SelectStep.class,
+ g.V().as("a").as("b").select("a", "b").by(__.constant("value")),
+ List.of(),
+ List.of(__.constant("value")),
+ null, null
+ },
+ {TraversalSelectStep.class,
+ g.V().select((Traversal)__.constant("a")),
+ List.of(),
+ List.of(__.constant("a")),
+ null, null
+ },
+ {TraversalSelectStep.class,
+ g.V().select((Traversal)__.constant("a")).by("name"),
+ List.of(),
+ List.of(__.constant("a"), new ValueTraversal("name")),
+ null, null
+ },
+ {TraversalFilterStep.class,
+ g.V().filter(__.constant(5)), // a bit of an arbitrary case to avoid getting optimized by strategies
+ List.of(),
+ List.of(__.constant(5)),
+ null, null
+ },
+ {TraversalFlatMapStep.class,
+ g.V().flatMap(__.out()),
+ List.of(),
+ List.of(__.out()),
+ null, null
+ },
+ {TraversalFlatMapStep.class,
+ g.V().flatMap(__.constant("value")),
+ List.of(),
+ List.of(__.constant("value")),
+ null, null
+ },
+ {TraversalMapStep.class,
+ g.V().map(__.values("name")),
+ List.of(),
+ List.of(__.values("name")),
+ null, null
+ },
+ {TraversalMapStep.class,
+ g.V().map(__.constant("value")),
+ List.of(),
+ List.of(__.constant("value")),
+ null, null
+ },
+ {TraversalSideEffectStep.class,
+ g.V().sideEffect(__.identity()),
+ List.of(),
+ List.of(__.identity()),
+ null, null
+ },
+ {TraversalSideEffectStep.class,
+ g.V().sideEffect(__.constant("value")),
+ List.of(),
+ List.of(__.constant("value")),
+ null, null
+ },
+ {TreeStep.class,
+ g.V().out().tree(),
+ List.of(),
+ List.of(),
+ null, null
+ },
+ {TreeStep.class,
+ g.V().out().tree().by("name"),
+ List.of(),
+ List.of(new ValueTraversal("name")),
+ null, null
+ },
+ {TreeStep.class,
+ g.V().out().tree().by(__.constant("value")),
+ List.of(),
+ List.of(__.constant("value")),
+ null, null
+ },
+ {TreeSideEffectStep.class,
+ g.V().out().tree("x"),
+ List.of(),
+ List.of(),
+ null, null
+ },
+ {TreeSideEffectStep.class,
+ g.V().out().tree("x").by("name"),
+ List.of(),
+ List.of(new ValueTraversal("name")),
+ null, null
+ },
+ {TreeSideEffectStep.class,
+ g.V().out().tree("x").by(__.constant("value")),
+ List.of(),
+ List.of(__.constant("value")),
+ null, null
+ },
+ {UnionStep.class,
+ g.union(__.V().values("name"), __.V().values("age")),
+ List.of(appendComputerAwareEndStep(__.V().values("name")), appendComputerAwareEndStep(__.V().values("age"))),
+ List.of(new ConstantTraversal<>(Pick.any)),
+ List.of(appendComputerAwareEndStep(__.V().values("name").barrier(2500)), appendComputerAwareEndStep(__.V().values("age").barrier(2500))),
+ null
+ },
+ {UnionStep.class,
+ g.union(__.constant("a"), __.constant("b")),
+ List.of(appendComputerAwareEndStep(__.constant("a")), appendComputerAwareEndStep(__.constant("b"))),
+ List.of(new ConstantTraversal<>(Pick.any)),
+ null, null
+ },
+ {WherePredicateStep.class,
+ g.V().as("a").out().as("b").where("a", P.eq("b")),
+ List.of(),
+ List.of(),
+ null, null
+ },
+ {WherePredicateStep.class,
+ g.V().as("a").out().as("b").where("a", P.eq("b")).by("name"),
+ List.of(),
+ List.of(new ValueTraversal("name")),
+ null, null
+ },
+ {WherePredicateStep.class,
+ g.V().as("a").out().as("b").where("a", P.eq("b")).by(__.constant("value")),
+ List.of(),
+ List.of(__.constant("value")),
+ null, null
+ },
+ {WhereTraversalStep.class,
+ g.V().as("a").out().as("b").where(__.as("a").out().as("c")),
+ List.of(),
+ List.of(generateWhereChildTraversal("a", "c", __.out().asAdmin())),
+ null, null
+ },
+ });
+ }
+
+ @Test
+ public void doTest() {
+ verifyExpectedParents(expectedGlobalChildren, expectedLocalChildren, "(pre-strategy application)");
+
+ traversal = traversal.clone();
+
+ verifyExpectedParents(expectedGlobalChildren, expectedLocalChildren, "(cloned traversal, pre-strategy application)");
+
+ traversal.getStrategies().addStrategies(GValueReductionStrategy.instance());
+ traversal.applyStrategies();
+
+ verifyExpectedParents(postStrategyExpectedGlobalChildren == null ? expectedGlobalChildren : postStrategyExpectedGlobalChildren,
+ postStrategyExpectedLocalChildren == null ? expectedLocalChildren : postStrategyExpectedLocalChildren,
+ "(pre-strategy application)");
+
+ traversal = traversal.clone();
+
+ verifyExpectedParents(postStrategyExpectedGlobalChildren == null ? expectedGlobalChildren : postStrategyExpectedGlobalChildren,
+ postStrategyExpectedLocalChildren == null ? expectedLocalChildren : postStrategyExpectedLocalChildren,
+ "(cloned traversal, pre-strategy application)");
+ }
+
+ private void verifyExpectedParents(List<Traversal.Admin<?,?>> expectedGlobalChildren, List<Traversal.Admin<?,?>> expectedLocalChildren, String messageSuffix) {
+ List<Step> steps = TraversalHelper.getStepsOfAssignableClass(stepClass, traversal);
Review Comment:
```suggestion
List<Step<?, ?>> steps = TraversalHelper.getStepsOfAssignableClass(stepClass, traversal);
```
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@tinkerpop.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Fix TraversalParent implementations for Placeholder steps [tinkerpop]
Posted by "Cole-Greer (via GitHub)" <gi...@apache.org>.
Cole-Greer commented on code in PR #3209:
URL: https://github.com/apache/tinkerpop/pull/3209#discussion_r2372958592
##########
gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AbstractAddEdgeStepPlaceholder.java:
##########
@@ -101,6 +87,18 @@ public boolean isParameterized() {
return false;
}
+ @Override
+ public List<Traversal.Admin<?, ?>> getLocalChildren() {
Review Comment:
The `TraversalParent` interface itself does not use generics. The `S` and `E` type variables are only bound on the `getLocalChildren` method itself. That means that the `S` and `E` defined in `public default <S, E> List<Traversal.Admin<S, E>> getLocalChildren()` are not the same `S` and `E` defined in this implementing step classes.
They should be independent, the addEdge step here uses `<S, Edge>` (can start with anything and always produces an Edge), but it's child traversals do not produce edges, the from/to traversals will produce a Vertex or some ID type, the label traversal will produce a String...
I think it would be most clear if TraversalParent was updated to just return `List<Traversal.Admin<?, ?>>` instead, however I considered that out of scope for this PR.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@tinkerpop.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Fix TraversalParent implementations for Placeholder steps [tinkerpop]
Posted by "Cole-Greer (via GitHub)" <gi...@apache.org>.
Cole-Greer commented on code in PR #3209:
URL: https://github.com/apache/tinkerpop/pull/3209#discussion_r2373561028
##########
gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/AddPropertyStepContract.java:
##########
@@ -47,14 +48,17 @@ default HashSet<PopInstruction> getPopInstructions() {
Object getKey();
/**
- * Get the property value
+ * Gets the property value. If the value was originally passed as a {@link GValue<?>}, {@link ConstantTraversal <?>},
+ * or a literal value, then the literal value is returned. Otherwise, the MergeMap is returned in Traversal form.
Review Comment:
That's a copy-paste error, it should be `value`.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@tinkerpop.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Fix TraversalParent implementations for Placeholder steps [tinkerpop]
Posted by "andreachild (via GitHub)" <gi...@apache.org>.
andreachild commented on code in PR #3209:
URL: https://github.com/apache/tinkerpop/pull/3209#discussion_r2376956891
##########
gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/TraversalParentTest.java:
##########
@@ -0,0 +1,1028 @@
+/*
+ * 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 java.time.OffsetDateTime;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.commons.configuration2.MapConfiguration;
+import org.apache.tinkerpop.gremlin.process.traversal.Operator;
+import org.apache.tinkerpop.gremlin.process.traversal.Pick;
+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.GraphTraversalSource;
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
+import org.apache.tinkerpop.gremlin.process.traversal.lambda.AbstractLambdaTraversal;
+import org.apache.tinkerpop.gremlin.process.traversal.lambda.ConstantTraversal;
+import org.apache.tinkerpop.gremlin.process.traversal.Merge;
+import org.apache.tinkerpop.gremlin.process.traversal.Scope;
+import org.apache.tinkerpop.gremlin.process.traversal.P;
+import org.apache.tinkerpop.gremlin.process.traversal.lambda.LoopTraversal;
+import org.apache.tinkerpop.gremlin.process.traversal.lambda.PredicateTraversal;
+import org.apache.tinkerpop.gremlin.process.traversal.lambda.TrueTraversal;
+import org.apache.tinkerpop.gremlin.process.traversal.lambda.ValueTraversal;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.AddEdgeStepContract;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.AddVertexStepContract;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.CallStepContract;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.MergeStepContract;
+import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.AddPropertyStepContract;
+import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.AggregateGlobalStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.AggregateLocalStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.filter.AndStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.filter.OrStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.branch.BranchStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.branch.ChooseStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.CoalesceStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.CombineStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.ConcatStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.DateDiffStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.filter.DedupGlobalStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.DifferenceStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.DisjunctStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.FormatStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.GroupCountStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.GroupCountSideEffectStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.GroupStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.IntersectStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.branch.LocalStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.MatchStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.MathStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.MergeStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.filter.NotStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.branch.OptionalStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.OrderGlobalStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.OrderLocalStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.filter.PathFilterStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.PathStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.ProductStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.ProjectStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.PropertyMapStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.branch.RepeatStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.SackValueStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.filter.SampleGlobalStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.SelectOneStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.SelectStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.TraversalSelectStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.filter.TraversalFilterStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.TraversalFlatMapStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.TraversalMapStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.TraversalSideEffectStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.TreeStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.TreeSideEffectStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.branch.UnionStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.filter.WherePredicateStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.filter.WhereTraversalStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.ComputerAwareStep;
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.GValueReductionStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper;
+import org.apache.tinkerpop.gremlin.structure.T;
+import org.apache.tinkerpop.gremlin.structure.service.Service;
+import org.apache.tinkerpop.gremlin.structure.service.ServiceRegistry;
+
+import org.apache.tinkerpop.gremlin.structure.util.GraphFactoryTest;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import static org.apache.tinkerpop.gremlin.process.traversal.AnonymousTraversalSource.traversal;
+import static org.hamcrest.Matchers.containsInAnyOrder;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+
+@RunWith(Parameterized.class)
+public class TraversalParentTest {
+
+ private static ServiceRegistry mockedRegistry= mock(ServiceRegistry.class);
+ private static Service<?, ?> mockedService = mock(Service.class);
+ private static GraphTraversalSource g = traversal().with(GraphFactoryTest.MockGraph.open(new MapConfiguration(Map.of("service-registry", mockedRegistry))));
+
+ @BeforeClass
+ public static void setupClass() {
+ when(mockedRegistry.get(any(), anyBoolean(), any())).thenReturn(mockedService);
+ when(mockedService.getRequirements()).thenReturn(Set.of());
+ }
+
+ @Parameterized.Parameter(value = 0)
+ public Class stepClass;
+
+ @Parameterized.Parameter(value = 1)
+ public Traversal.Admin traversal;
Review Comment:
```suggestion
public Traversal.Admin<?, ?> traversal;
```
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@tinkerpop.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Fix TraversalParent implementations for Placeholder steps [tinkerpop]
Posted by "andreachild (via GitHub)" <gi...@apache.org>.
andreachild commented on code in PR #3209:
URL: https://github.com/apache/tinkerpop/pull/3209#discussion_r2376950048
##########
gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/TraversalParentTest.java:
##########
@@ -0,0 +1,1028 @@
+/*
+ * 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 java.time.OffsetDateTime;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.commons.configuration2.MapConfiguration;
+import org.apache.tinkerpop.gremlin.process.traversal.Operator;
+import org.apache.tinkerpop.gremlin.process.traversal.Pick;
+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.GraphTraversalSource;
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
+import org.apache.tinkerpop.gremlin.process.traversal.lambda.AbstractLambdaTraversal;
+import org.apache.tinkerpop.gremlin.process.traversal.lambda.ConstantTraversal;
+import org.apache.tinkerpop.gremlin.process.traversal.Merge;
+import org.apache.tinkerpop.gremlin.process.traversal.Scope;
+import org.apache.tinkerpop.gremlin.process.traversal.P;
+import org.apache.tinkerpop.gremlin.process.traversal.lambda.LoopTraversal;
+import org.apache.tinkerpop.gremlin.process.traversal.lambda.PredicateTraversal;
+import org.apache.tinkerpop.gremlin.process.traversal.lambda.TrueTraversal;
+import org.apache.tinkerpop.gremlin.process.traversal.lambda.ValueTraversal;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.AddEdgeStepContract;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.AddVertexStepContract;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.CallStepContract;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.MergeStepContract;
+import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.AddPropertyStepContract;
+import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.AggregateGlobalStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.AggregateLocalStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.filter.AndStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.filter.OrStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.branch.BranchStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.branch.ChooseStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.CoalesceStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.CombineStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.ConcatStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.DateDiffStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.filter.DedupGlobalStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.DifferenceStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.DisjunctStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.FormatStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.GroupCountStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.GroupCountSideEffectStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.GroupStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.IntersectStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.branch.LocalStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.MatchStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.MathStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.MergeStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.filter.NotStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.branch.OptionalStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.OrderGlobalStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.OrderLocalStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.filter.PathFilterStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.PathStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.ProductStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.ProjectStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.PropertyMapStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.branch.RepeatStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.SackValueStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.filter.SampleGlobalStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.SelectOneStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.SelectStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.TraversalSelectStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.filter.TraversalFilterStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.TraversalFlatMapStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.TraversalMapStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.TraversalSideEffectStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.TreeStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.TreeSideEffectStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.branch.UnionStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.filter.WherePredicateStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.filter.WhereTraversalStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.ComputerAwareStep;
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.GValueReductionStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper;
+import org.apache.tinkerpop.gremlin.structure.T;
+import org.apache.tinkerpop.gremlin.structure.service.Service;
+import org.apache.tinkerpop.gremlin.structure.service.ServiceRegistry;
+
+import org.apache.tinkerpop.gremlin.structure.util.GraphFactoryTest;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import static org.apache.tinkerpop.gremlin.process.traversal.AnonymousTraversalSource.traversal;
+import static org.hamcrest.Matchers.containsInAnyOrder;
+import static org.junit.Assert.assertEquals;
Review Comment:
Nit: unused
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@tinkerpop.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Fix TraversalParent implementations for Placeholder steps [tinkerpop]
Posted by "andreachild (via GitHub)" <gi...@apache.org>.
andreachild commented on code in PR #3209:
URL: https://github.com/apache/tinkerpop/pull/3209#discussion_r2370888205
##########
gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/TraversalParent.java:
##########
@@ -31,14 +33,31 @@
import java.util.Set;
/**
+ * Indicates that a step can contain child Traversals. Any step which implements this interface should override at least
Review Comment:
Nit: Likely out of scope for this PR but I feel it would be helpful in general for TinkerPop to have more custom annotations. In this case there could be a custom annotation like `@ChildTraversal(scope=Type.LOCAL)` to mark step fields that store a child traversal. Then there can be a single common method which handles the presence of child traversals in `AbstractStep.java` like (pseudocode):
```
@Override
public void setTraversal(final Traversal.Admin<?, ?> traversal) {
this.traversal = traversal;
// retrieve any step fields annotated with @ChildTraversal
// for each child traversal, call integrateChild
}
```
And then there could also be an `AbstractTravesalParent.java` which has:
```
<S, E> List<Traversal.Admin<S, E>> getGlobalChildren() {
// use reflection to retrieve fields annotated with @ChildTraversal(type=GLOBAL)
}
<S, E> List<Traversal.Admin<S, E>> getLocalChildren() {
// use reflection to retrieve fields annotated with @ChildTraversal(type=LOCAL)
}
```
Then when adding new steps or adding child traversals to an existing step, all you would need to do is add the custom annotation and you wouldn't have to 'remember' to do the boilerplate logic.
If you agree with this suggestion it's possible to use an annotation for these affected classes only and then slowly migrate towards 100% usage of the annotation in future PRs.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@tinkerpop.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Fix TraversalParent implementations for Placeholder steps [tinkerpop]
Posted by "andreachild (via GitHub)" <gi...@apache.org>.
andreachild commented on code in PR #3209:
URL: https://github.com/apache/tinkerpop/pull/3209#discussion_r2370965992
##########
gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/AddPropertyStepPlaceholder.java:
##########
@@ -66,11 +69,19 @@ public AddPropertyStepPlaceholder(final Traversal.Admin traversal, final VertexP
throw new IllegalArgumentException("GValue is not allowed for property keys");
}
this.key = keyObject;
- this.value = GValue.of(valueObject);
- this.cardinality = cardinality;
+ if (this.key instanceof Traversal) {
+ this.integrateChild(((Traversal<?, ?>) this.key).asAdmin());
+ }
if (valueObject instanceof GValue) {
traversal.getGValueManager().register((GValue<?>) valueObject);
+ this.value = new GValueConstantTraversal<>((GValue<?>) valueObject);
+ } else if (valueObject instanceof Traversal) {
+ this.value = ((Traversal<?, ?>) valueObject).asAdmin();
+ this.integrateChild(((Traversal<?, ?>) valueObject).asAdmin());
+ } else {
+ this.value = new ConstantTraversal<>(valueObject);
Review Comment:
Do `ConstantTraversal`s not need to be integrated as a child traversal?
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@tinkerpop.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Fix TraversalParent implementations for Placeholder steps [tinkerpop]
Posted by "andreachild (via GitHub)" <gi...@apache.org>.
andreachild commented on code in PR #3209:
URL: https://github.com/apache/tinkerpop/pull/3209#discussion_r2370959319
##########
gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/AddPropertyStepContract.java:
##########
@@ -47,14 +48,17 @@ default HashSet<PopInstruction> getPopInstructions() {
Object getKey();
/**
- * Get the property value
+ * Gets the property value. If the value was originally passed as a {@link GValue<?>}, {@link ConstantTraversal <?>},
+ * or a literal value, then the literal value is returned. Otherwise, the MergeMap is returned in Traversal form.
Review Comment:
What is a `MergeMap` in this context?
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@tinkerpop.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Fix TraversalParent implementations for Placeholder steps [tinkerpop]
Posted by "Cole-Greer (via GitHub)" <gi...@apache.org>.
Cole-Greer commented on code in PR #3209:
URL: https://github.com/apache/tinkerpop/pull/3209#discussion_r2373711027
##########
gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AbstractAddElementStepPlaceholder.java:
##########
@@ -175,6 +188,9 @@ public void addProperty(Object key, Object value) {
if (key instanceof GValue) {
throw new IllegalArgumentException("GValue cannot be used as a property key");
}
+ if (key instanceof Traversal) {
+ this.integrateChild(((Traversal<?, ?>) key).asAdmin());
Review Comment:
Once the child is dropped from the parent step, the parent traversal has no references of the child. As long as the user isn't externally storing a reference to the child, it should be get picked up by garbage collection.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@tinkerpop.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Fix TraversalParent implementations for Placeholder steps [tinkerpop]
Posted by "andreachild (via GitHub)" <gi...@apache.org>.
andreachild commented on code in PR #3209:
URL: https://github.com/apache/tinkerpop/pull/3209#discussion_r2370983854
##########
gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AbstractMergeElementStepPlaceholder.java:
##########
@@ -65,14 +67,67 @@ protected Traverser.Admin<E> processNextStart() throws NoSuchElementException {
@Override
public AbstractMergeElementStepPlaceholder<S, E> clone() {
- return (AbstractMergeElementStepPlaceholder<S, E>) super.clone();
+ AbstractMergeElementStepPlaceholder<S, E> clone = (AbstractMergeElementStepPlaceholder<S, E>) super.clone();
+ if (mergeTraversal != null){
+ clone.setMerge(mergeTraversal.clone());
+ }
+ if (onMatchTraversal != null) {
+ clone.setOnMatch(onMatchTraversal.clone());
+ }
+ if (onCreateTraversal != null) {
+ clone.setOnCreate(onCreateTraversal.clone());
+ }
+
+ // deep clone properties
+ clone.properties = new HashMap<>();
+ for (Map.Entry<Object, List<Object>> entry : this.properties.entrySet()) {
+ final Object key = entry.getKey();
+ final List<Object> oldValues = entry.getValue();
+ final List<Object> newValues = new ArrayList<>(oldValues.size());
+ for (Object v : oldValues) {
+ if (v instanceof Traversal) {
+ newValues.add(((Traversal<?, ?>) v).asAdmin().clone());
+ } else if (v instanceof GValue) {
+ try {
+ newValues.add(((GValue) v).clone());
+ } catch (CloneNotSupportedException e) {
+ throw new RuntimeException(e);
+ }
+ } else {
+ newValues.add(v);
+ }
+ }
+ clone.properties.put(key, newValues);
+ }
+ return clone;
}
@Override
public Set<TraverserRequirement> getRequirements() {
return super.getRequirements();
}
+ @Override
+ public void setTraversal(final Traversal.Admin<?, ?> parentTraversal) {
+ super.setTraversal(parentTraversal);
+ this.getLocalChildren().forEach(this::integrateChild);
Review Comment:
Can you clarify why `setTraversal` needs to call `integrateChild` but the constructor which calls `super(traversal)` does not need to call `integrateChild`?
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@tinkerpop.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Fix TraversalParent implementations for Placeholder steps [tinkerpop]
Posted by "andreachild (via GitHub)" <gi...@apache.org>.
andreachild commented on code in PR #3209:
URL: https://github.com/apache/tinkerpop/pull/3209#discussion_r2377024025
##########
gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/TraversalParentTest.java:
##########
Review Comment:
Can you pls do a quick find replace for:
`ConstantTraversal(` replace with `ConstantTraversal<>(`
`ValueTraversal(` replace with `ValueTraversal<>(`
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@tinkerpop.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Fix TraversalParent implementations for Placeholder steps [tinkerpop]
Posted by "andreachild (via GitHub)" <gi...@apache.org>.
andreachild commented on code in PR #3209:
URL: https://github.com/apache/tinkerpop/pull/3209#discussion_r2370517850
##########
gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/lambda/GValueConstantTraversal.java:
##########
@@ -57,6 +57,17 @@ public boolean equals(final Object other) {
return constantTraversal.equals(other);
}
+ @Override
+ public GValueConstantTraversal<S, E> clone() {
+ GValueConstantTraversal<S, E> clone = new GValueConstantTraversal<>(GValue.of(this.end.getName(), this.end.get()));
+ try {
+ clone.setGValueManager(this.getGValueManager().clone());
+ } catch (CloneNotSupportedException e) { //TODO:: handle properly
Review Comment:
Note that there are fields in the parent class `AbstractLambdaTraversal` which are not cloned by this current logic such as `bypassTraversal`.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@tinkerpop.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Fix TraversalParent implementations for Placeholder steps [tinkerpop]
Posted by "Cole-Greer (via GitHub)" <gi...@apache.org>.
Cole-Greer commented on code in PR #3209:
URL: https://github.com/apache/tinkerpop/pull/3209#discussion_r2373568173
##########
gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/AddPropertyStepPlaceholder.java:
##########
@@ -66,11 +69,19 @@ public AddPropertyStepPlaceholder(final Traversal.Admin traversal, final VertexP
throw new IllegalArgumentException("GValue is not allowed for property keys");
}
this.key = keyObject;
- this.value = GValue.of(valueObject);
- this.cardinality = cardinality;
+ if (this.key instanceof Traversal) {
+ this.integrateChild(((Traversal<?, ?>) this.key).asAdmin());
+ }
if (valueObject instanceof GValue) {
traversal.getGValueManager().register((GValue<?>) valueObject);
+ this.value = new GValueConstantTraversal<>((GValue<?>) valueObject);
+ } else if (valueObject instanceof Traversal) {
+ this.value = ((Traversal<?, ?>) valueObject).asAdmin();
+ this.integrateChild(((Traversal<?, ?>) valueObject).asAdmin());
+ } else {
+ this.value = new ConstantTraversal<>(valueObject);
Review Comment:
That's an interesting point. integrating a `ConstantTraversal` as a child won't really do much, as a ConstantTraversal does not make use of GValues, and unless a `bypassTraversal` is set, it can't really have a parent or side effects either.
For the sake of consistency though, it would make sense to also integrate the ConstantTraversal here. I will make the change.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@tinkerpop.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Fix TraversalParent implementations for Placeholder steps [tinkerpop]
Posted by "Cole-Greer (via GitHub)" <gi...@apache.org>.
Cole-Greer commented on code in PR #3209:
URL: https://github.com/apache/tinkerpop/pull/3209#discussion_r2373764077
##########
gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AbstractAddElementStepPlaceholder.java:
##########
@@ -175,6 +188,9 @@ public void addProperty(Object key, Object value) {
if (key instanceof GValue) {
throw new IllegalArgumentException("GValue cannot be used as a property key");
}
+ if (key instanceof Traversal) {
+ this.integrateChild(((Traversal<?, ?>) key).asAdmin());
Review Comment:
I have updated both `setLabel` and `setElementId` to properly integrate child traversals now.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@tinkerpop.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Fix TraversalParent implementations for Placeholder steps [tinkerpop]
Posted by "andreachild (via GitHub)" <gi...@apache.org>.
andreachild commented on code in PR #3209:
URL: https://github.com/apache/tinkerpop/pull/3209#discussion_r2370620747
##########
gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AbstractAddEdgeStepPlaceholder.java:
##########
@@ -101,6 +87,18 @@ public boolean isParameterized() {
return false;
}
+ @Override
+ public List<Traversal.Admin<?, ?>> getLocalChildren() {
Review Comment:
Is the parent interface generic contract which is defined as `List<Traversal.Admin<S, E>> getLocalChildren` too narrow since it needs to be modified here?
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@tinkerpop.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Fix TraversalParent implementations for Placeholder steps [tinkerpop]
Posted by "andreachild (via GitHub)" <gi...@apache.org>.
andreachild commented on code in PR #3209:
URL: https://github.com/apache/tinkerpop/pull/3209#discussion_r2370937989
##########
gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AbstractAddElementStepPlaceholder.java:
##########
@@ -175,6 +188,9 @@ public void addProperty(Object key, Object value) {
if (key instanceof GValue) {
throw new IllegalArgumentException("GValue cannot be used as a property key");
}
+ if (key instanceof Traversal) {
+ this.integrateChild(((Traversal<?, ?>) key).asAdmin());
Review Comment:
Does anything need to be done to 'de-integrate' a child traversal if a property is removed?
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@tinkerpop.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Fix TraversalParent implementations for Placeholder steps [tinkerpop]
Posted by "andreachild (via GitHub)" <gi...@apache.org>.
andreachild commented on code in PR #3209:
URL: https://github.com/apache/tinkerpop/pull/3209#discussion_r2377013333
##########
gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/TraversalParentTest.java:
##########
@@ -0,0 +1,1028 @@
+/*
+ * 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 java.time.OffsetDateTime;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.commons.configuration2.MapConfiguration;
+import org.apache.tinkerpop.gremlin.process.traversal.Operator;
+import org.apache.tinkerpop.gremlin.process.traversal.Pick;
+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.GraphTraversalSource;
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
+import org.apache.tinkerpop.gremlin.process.traversal.lambda.AbstractLambdaTraversal;
+import org.apache.tinkerpop.gremlin.process.traversal.lambda.ConstantTraversal;
+import org.apache.tinkerpop.gremlin.process.traversal.Merge;
+import org.apache.tinkerpop.gremlin.process.traversal.Scope;
+import org.apache.tinkerpop.gremlin.process.traversal.P;
+import org.apache.tinkerpop.gremlin.process.traversal.lambda.LoopTraversal;
+import org.apache.tinkerpop.gremlin.process.traversal.lambda.PredicateTraversal;
+import org.apache.tinkerpop.gremlin.process.traversal.lambda.TrueTraversal;
+import org.apache.tinkerpop.gremlin.process.traversal.lambda.ValueTraversal;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.AddEdgeStepContract;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.AddVertexStepContract;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.CallStepContract;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.MergeStepContract;
+import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.AddPropertyStepContract;
+import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.AggregateGlobalStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.AggregateLocalStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.filter.AndStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.filter.OrStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.branch.BranchStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.branch.ChooseStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.CoalesceStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.CombineStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.ConcatStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.DateDiffStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.filter.DedupGlobalStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.DifferenceStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.DisjunctStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.FormatStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.GroupCountStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.GroupCountSideEffectStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.GroupStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.IntersectStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.branch.LocalStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.MatchStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.MathStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.MergeStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.filter.NotStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.branch.OptionalStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.OrderGlobalStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.OrderLocalStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.filter.PathFilterStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.PathStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.ProductStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.ProjectStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.PropertyMapStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.branch.RepeatStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.SackValueStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.filter.SampleGlobalStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.SelectOneStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.SelectStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.TraversalSelectStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.filter.TraversalFilterStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.TraversalFlatMapStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.TraversalMapStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.TraversalSideEffectStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.TreeStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.TreeSideEffectStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.branch.UnionStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.filter.WherePredicateStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.filter.WhereTraversalStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.ComputerAwareStep;
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.GValueReductionStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper;
+import org.apache.tinkerpop.gremlin.structure.T;
+import org.apache.tinkerpop.gremlin.structure.service.Service;
+import org.apache.tinkerpop.gremlin.structure.service.ServiceRegistry;
+
+import org.apache.tinkerpop.gremlin.structure.util.GraphFactoryTest;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import static org.apache.tinkerpop.gremlin.process.traversal.AnonymousTraversalSource.traversal;
+import static org.hamcrest.Matchers.containsInAnyOrder;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+
+@RunWith(Parameterized.class)
+public class TraversalParentTest {
+
+ private static ServiceRegistry mockedRegistry= mock(ServiceRegistry.class);
+ private static Service<?, ?> mockedService = mock(Service.class);
+ private static GraphTraversalSource g = traversal().with(GraphFactoryTest.MockGraph.open(new MapConfiguration(Map.of("service-registry", mockedRegistry))));
+
+ @BeforeClass
+ public static void setupClass() {
+ when(mockedRegistry.get(any(), anyBoolean(), any())).thenReturn(mockedService);
+ when(mockedService.getRequirements()).thenReturn(Set.of());
+ }
+
+ @Parameterized.Parameter(value = 0)
+ public Class stepClass;
+
+ @Parameterized.Parameter(value = 1)
+ public Traversal.Admin traversal;
+
+ @Parameterized.Parameter(value = 2)
+ public List<Traversal.Admin<?,?>> expectedGlobalChildren;
+
+ @Parameterized.Parameter(value = 3)
+ public List<Traversal.Admin<?,?>> expectedLocalChildren;
+
+ /**
+ * Overrides expectedGlobalChildren for assertions following strategy execution. If left null, expectedGlobalChildren is used instead.
+ */
+ @Parameterized.Parameter(value = 4)
+ public List<Traversal.Admin<?,?>> postStrategyExpectedGlobalChildren;
+
+ /**
+ * Overrides expectedLocalChildren for assertions following strategy execution. If left null, expectedLocalChildren is used instead.
+ */
+ @Parameterized.Parameter(value = 5)
+ public List<Traversal.Admin<?,?>> postStrategyExpectedLocalChildren;
+
+ @Parameterized.Parameters(name = "{0}")
+ public static Iterable<Object[]> data() {
+ return Arrays.asList(new Object[][]{
+ {AddVertexStepContract.class,
+ g.addV("label").property("name", __.constant("cole")),
+ List.of(),
+ List.of(__.constant("cole"), new ConstantTraversal<>("label")),
+ null, null
+ },
+ {AddVertexStepContract.class,
+ g.addV(__.constant("label")).property("name", __.constant("cole")),
+ List.of(),
+ List.of(__.constant("cole"), __.constant("label")),
+ null, null
+ },
+ {AddVertexStepContract.class,
+ g.addV().property("name", __.constant("cole")).property(T.label, __.constant("label")).property(T.id, __.constant(1)),
+ List.of(),
+ List.of(__.constant("cole"), __.constant("label"), __.constant(1)),
+ null, null
+ },
+ {AddVertexStepContract.class,
+ g.addV(GValue.of("l", "label")).property("name", GValue.of("name", "cole")),
+ List.of(),
+ List.of(new ConstantTraversal<>("label")), // Property is not stored as a child traversal in this case
+ null, null
+ },
+ {AddVertexStepContract.class,
+ g.addV("label").property(__.constant("name"), __.constant("cole")),
+ List.of(),
+ List.of(__.constant("name"), __.constant("cole"), new ConstantTraversal<>("label")),
+ null, null
+ },
+ {AddVertexStepContract.class,
+ g.inject(1).addV("label").property("name", __.constant("cole")),
+ List.of(),
+ List.of(__.constant("cole"), new ConstantTraversal<>("label")),
+ null, null
+ },
+ {AddVertexStepContract.class,
+ g.inject(1).addV(__.constant("label")).property("name", __.constant("cole")),
+ List.of(),
+ List.of(__.constant("cole"), __.constant("label")),
+ null, null
+ },
+ {AddVertexStepContract.class,
+ g.inject(1).addV(GValue.of("l", "label")).property("name", GValue.of("name", "cole")),
+ List.of(),
+ List.of(new ConstantTraversal<>("label")), // Property is not stored as a child traversal in this case
+ null, null
+ },
+ {AddVertexStepContract.class,
+ g.inject(1).addV("label").property(__.constant("name"), __.constant("cole")),
+ List.of(),
+ List.of(__.constant("name"), __.constant("cole"), new ConstantTraversal<>("label")),
+ null, null
+ },
+ {AddEdgeStepContract.class,
+ g.addE("label").from(1).to(2).property("name", __.constant("cole")),
+ List.of(),
+ List.of(__.constant("cole"), new ConstantTraversal<>("label"), __.constant(1), __.constant(2)),
+ null, null
+ },
+ {AddEdgeStepContract.class,
+ g.addE("label").from(__.V(1)).to(__.V(2))
+ .property("name", __.constant("cole"))
+ .property(T.id, __.constant(5)),
+ List.of(),
+ List.of(__.constant("cole"), new ConstantTraversal<>("label"), __.V(1), __.V(2), __.constant(5)),
+ null, null
+ },
+ {AddEdgeStepContract.class,
+ g.addE("label").from(__.V(1)).to(__.V(2)).property("name", __.constant("cole")),
+ List.of(),
+ List.of(__.constant("cole"), new ConstantTraversal<>("label"), __.V(1), __.V(2)),
+ null, null
+ },
+ {AddEdgeStepContract.class,
+ g.addE(GValue.of("l", "label")).from(GValue.of("from", 1)).to(GValue.of("to", 2)).property("name", GValue.of("name", "cole")),
+ List.of(),
+ List.of(new ConstantTraversal<>("label"), new ConstantTraversal(1), new ConstantTraversal(2)),
+ null, null
+ },
+ {AddEdgeStepContract.class,
+ g.addE("label").from(1).to(2).property(__.constant("name"), __.constant("cole")),
+ List.of(),
+ List.of(__.constant("name"), __.constant("cole"), new ConstantTraversal<>("label"), __.constant(1), __.constant(2)),
+ null, null
+ },
+ {AddEdgeStepContract.class,
+ g.inject(1).addE("label").from(1).to(2).property("name", __.constant("cole")),
+ List.of(),
+ List.of(__.constant("cole"), new ConstantTraversal<>("label"), __.constant(1), __.constant(2)),
+ null, null
+ },
+ {AddEdgeStepContract.class,
+ g.inject(1).addE("label").from(__.V(1)).to(__.V(2)).property("name", __.constant("cole")),
+ List.of(),
+ List.of(__.constant("cole"), new ConstantTraversal<>("label"), __.V(1), __.V(2)),
+ null, null
+ },
+ {AddEdgeStepContract.class,
+ g.inject(1).addE(GValue.of("l", "label")).from(GValue.of("from", 1)).to(GValue.of("to", 2)).property("name", GValue.of("name", "cole")),
+ List.of(),
+ List.of(new ConstantTraversal<>("label"), new ConstantTraversal(1), new ConstantTraversal(2)),
+ null, null
+ },
+ {AddEdgeStepContract.class,
+ g.inject(1).addE("label").from(1).to(2).property(__.constant("name"), __.constant("cole")),
+ List.of(),
+ List.of(__.constant("name"), __.constant("cole"), new ConstantTraversal<>("label"), __.constant(1), __.constant(2)),
+ null, null
+ },
+ {CallStepContract.class,
+ g.call("service"),
+ List.of(),
+ List.of(),
+ null, null
+ },
+ {CallStepContract.class,
+ g.call("service").with("key", __.constant("value")),
+ List.of(),
+ List.of(__.constant("value")),
+ null, null
+ },
+ {CallStepContract.class,
+ g.call("service", __.constant(Map.of("key", "value"))),
+ List.of(),
+ List.of(__.constant(Map.of("key", "value"))),
+ null, null
+ },
+ {CallStepContract.class,
+ g.call("service", __.constant(Map.of("key", "value"))).with("key", __.constant("value")),
+ List.of(),
+ List.of(__.constant(Map.of("key", "value")), __.constant("value")),
+ null, null
+ },
+ {AddPropertyStepContract.class,
+ g.inject(1).property("key", "value"),
+ List.of(),
+ List.of(new ConstantTraversal<>("value")), // constant Value's are internally boxed in Traversals
+ null, null
+ },
+ {AddPropertyStepContract.class,
+ g.inject(1).property("key", __.constant("value")),
+ List.of(),
+ List.of(__.constant("value")),
+ null, null
+ },
+ {AddPropertyStepContract.class,
+ g.inject(1).property(__.constant("key"), __.constant("value")),
+ List.of(),
+ List.of(__.constant("key"), __.constant("value")),
+ null, null
+ },
+ {AddPropertyStepContract.class,
+ g.addV().property("name", "value", "metaKey", "metaValue"),
+ List.of(),
+ List.of(new ConstantTraversal<>("value")), // constant Value's are internally boxed in Traversals
+ null, null
+ },
+ {AddPropertyStepContract.class,
+ g.addV().property("name", __.constant("value"), "metaKey", __.constant("metaValue")),
+ List.of(),
+ List.of(__.constant("value"), __.constant("metaValue")),
+ null, null
+ },
+ {AddPropertyStepContract.class,
+ g.addV().property(__.constant("name"), __.constant("value"), __.constant("metaKey"), __.constant("metaValue")),
+ List.of(),
+ List.of(__.constant("name"), __.constant("value"), __.constant("metaKey"), __.constant("metaValue")),
+ null, null
+ },
+ {AddPropertyStepContract.class,
+ g.addV().property("name", "value", "metaKey1", "metaValue1", "metaKey2", "metaValue2"),
+ List.of(),
+ List.of(new ConstantTraversal<>("value")), // constant Value's are internally boxed in Traversals
+ null, null
+ },
+ {MergeStepContract.class,
+ g.mergeV(Map.of("name", "marko")),
+ List.of(),
+ List.of(new ConstantTraversal<>(Map.of("name", "marko"))), // constant MergeMap's are internally boxed in Traversals
+ null, null
+ },
+ {MergeStepContract.class,
+ g.mergeV(__.constant(Map.of("name", "marko"))),
+ List.of(),
+ List.of(__.constant(Map.of("name", "marko"))),
+ null, null
+ },
+ {MergeStepContract.class,
+ g.mergeV(Map.of("name", "marko")).option(Merge.onCreate, __.constant(Map.of("age", 29))),
+ List.of(),
+ List.of(new ConstantTraversal<>(Map.of("name", "marko")), __.constant(Map.of("age", 29))), // constant MergeMap's are internally boxed in Traversals
+ null, null
+ },
+ {MergeStepContract.class,
+ g.mergeV(__.constant(Map.of("name", "marko"))).option(Merge.onCreate, __.constant(Map.of("age", 29))).option(Merge.onMatch, __.constant(Map.of("updated", true))),
+ List.of(),
+ List.of(__.constant(Map.of("name", "marko")), __.constant(Map.of("age", 29)), __.constant(Map.of("updated", true))),
+ null, null
+ },
+ {MergeStepContract.class,
+ g.mergeE(Map.of(T.label, "knows")),
+ List.of(),
+ List.of(new ConstantTraversal<>(Map.of(T.label, "knows"))), // constant MergeMap's are internally boxed in Traversals
+ null, null
+ },
+ {MergeStepContract.class,
+ g.mergeE(__.constant(Map.of(T.label, "knows"))),
+ List.of(),
+ List.of(__.constant(Map.of(T.label, "knows"))),
+ null, null
+ },
+ {MergeStepContract.class,
+ g.mergeE(Map.of(T.label, "knows")).option(Merge.onCreate, __.constant(Map.of("weight", 0.5))),
+ List.of(),
+ List.of(new ConstantTraversal<>(Map.of(T.label, "knows")), __.constant(Map.of("weight", 0.5))), // constant MergeMap's are internally boxed in Traversals
+ null, null
+ },
+ {MergeStepContract.class,
+ g.mergeE(__.constant(Map.of(T.label, "knows"))).option(Merge.onCreate, __.constant(Map.of("weight", 0.5))).option(Merge.onMatch, __.constant(Map.of("updated", true))),
+ List.of(),
+ List.of(__.constant(Map.of(T.label, "knows")), __.constant(Map.of("weight", 0.5)), __.constant(Map.of("updated", true))),
+ null, null
+ },
+ {AggregateGlobalStep.class,
+ g.V().aggregate("x"),
+ List.of(),
+ List.of(),
+ null, null
+ },
+ {AggregateGlobalStep.class,
+ g.V().aggregate("x").by("name"),
+ List.of(),
+ List.of(new ValueTraversal("name")),
+ null, null
+ },
+ {AggregateGlobalStep.class,
+ g.V().aggregate("x").by(__.constant("value")),
+ List.of(),
+ List.of(__.constant("value")),
+ null, null
+ },
+ {AggregateLocalStep.class,
+ g.V().aggregate(Scope.local, "x"),
+ List.of(),
+ List.of(),
+ null, null
+ },
+ {AggregateLocalStep.class,
+ g.V().aggregate(Scope.local, "x").by("name"),
+ List.of(),
+ List.of(new ValueTraversal("name")),
+ null, null
+ },
+ {AggregateLocalStep.class,
+ g.V().aggregate(Scope.local, "x").by(__.constant("value")),
+ List.of(),
+ List.of(__.constant("value")),
+ null, null
+ },
+ {AndStep.class,
+ g.V().and(__.outE(), __.has("age", P.gte(32))),
+ List.of(),
+ List.of(__.outE(), __.has("age", P.gte(32))),
+ null, null
+ },
+ {OrStep.class,
+ g.V().or(__.outE(), __.has("age", P.gte(32))),
+ List.of(),
+ List.of(__.outE(), __.has("age", P.gte(32))),
+ null, null
+ },
+ {BranchStep.class,
+ g.V().branch(__.label()).option("person", __.values("name")).option("software", __.values("lang")),
+ List.of(appendComputerAwareEndStep(__.values("name")), appendComputerAwareEndStep(__.values("lang"))),
+ List.of(__.label(), new PredicateTraversal<>(P.eq("person")), new PredicateTraversal<>(P.eq("software"))), // option keys are wrapped in PredicateTraversals internally
+ null, null
+ },
+ {ChooseStep.class,
+ g.V().choose(__.out().count()).option(2L, __.values("name")).option(3L, __.values("age")),
+ List.of(appendComputerAwareEndStep(__.values("name")), appendComputerAwareEndStep(__.values("age")), appendComputerAwareEndStep(__.identity()), appendComputerAwareEndStep(__.identity())),
+ List.of(__.out().count(), new PredicateTraversal<>(P.eq(2L)), new PredicateTraversal<>(P.eq(3L))), // option keys are wrapped in PredicateTraversals internally
+ null, List.of(__.outE().count(), new PredicateTraversal<>(P.eq(2L)), new PredicateTraversal<>(P.eq(3L)))
+ },
+ {CoalesceStep.class,
+ g.V().coalesce(__.out("knows"), __.out("created")),
+ List.of(),
+ List.of(__.out("knows"), __.out("created")),
+ null, null
+ },
+ {CombineStep.class,
+ g.V().fold().combine(__.constant(List.of(1, 2, 3))),
+ List.of(),
+ List.of(__.constant(List.of(1, 2, 3))),
+ null, null
+ },
+ {ConcatStep.class,
+ g.inject("a", "b").concat(__.constant("c"), __.constant("d")),
+ List.of(),
+ List.of(__.constant("c"), __.constant("d")),
+ null, null
+ },
+ {DateDiffStep.class,
+ g.inject(OffsetDateTime.parse("1970-01-01T00:00:00.000Z")).dateDiff(__.constant(OffsetDateTime.parse("1970-02-01T00:00:00.000Z"))),
+ List.of(),
+ List.of(__.constant(OffsetDateTime.parse("1970-02-01T00:00:00.000Z"))),
+ null, null
+ },
+ {DedupGlobalStep.class,
+ g.V().dedup(),
+ List.of(),
+ List.of(),
+ null, null
+ },
+ {DedupGlobalStep.class,
+ g.V().dedup().by("name"),
+ List.of(),
+ List.of(new ValueTraversal("name")),
+ null, null
+ },
+ {DedupGlobalStep.class,
+ g.V().dedup().by(__.constant("value")),
+ List.of(),
+ List.of(__.constant("value")),
+ null, null
+ },
+ {DifferenceStep.class,
+ g.V().fold().difference(__.constant(List.of(1, 2, 3))),
+ List.of(),
+ List.of(__.constant(List.of(1, 2, 3))),
+ null, null
+ },
+ {DisjunctStep.class,
+ g.V().fold().disjunct(__.constant(List.of(1, 2, 3))),
+ List.of(),
+ List.of(__.constant(List.of(1, 2, 3))),
+ null, null
+ },
+ {FormatStep.class,
+ g.V().format("Hello %{name}"),
+ List.of(),
+ List.of(),
+ null, null
+ },
+ {FormatStep.class,
+ g.V().format("Hello %{name}").by("name"),
+ List.of(),
+ List.of(new ValueTraversal("name")),
+ null, null
+ },
+ {FormatStep.class,
+ g.V().format("Hello %{name}").by(__.constant("value")),
+ List.of(),
+ List.of(__.constant("value")),
+ null, null
+ },
+ {GroupCountStep.class,
+ g.V().groupCount(),
+ List.of(),
+ List.of(),
+ null, null
+ },
+ {GroupCountStep.class,
+ g.V().groupCount().by("name"),
+ List.of(),
+ List.of(new ValueTraversal("name")),
+ null, null
+ },
+ {GroupCountStep.class,
+ g.V().groupCount().by(__.constant("value")),
+ List.of(),
+ List.of(__.constant("value")),
+ null, null
+ },
+ {GroupCountSideEffectStep.class,
+ g.V().groupCount("x"),
+ List.of(),
+ List.of(),
+ null, null
+ },
+ {GroupCountSideEffectStep.class,
+ g.V().groupCount("x").by("name"),
+ List.of(),
+ List.of(new ValueTraversal("name")),
+ null, null
+ },
+ {GroupCountSideEffectStep.class,
+ g.V().groupCount("x").by(__.constant("value")),
+ List.of(),
+ List.of(__.constant("value")),
+ null, null
+ },
+ {GroupStep.class,
+ g.V().group(),
+ List.of(),
+ List.of(__.fold()),
+ null, null
+ },
+ {GroupStep.class,
+ g.V().group().by("name"),
+ List.of(),
+ List.of(new ValueTraversal("name"), __.fold()),
+ null, null
+ },
+ {GroupStep.class,
+ g.V().group().by("name").by("age"),
+ List.of(),
+ List.of(new ValueTraversal("name"), __.map(new ValueTraversal("age")).fold()),
+ null, null
+ },
+ {GroupStep.class,
+ g.V().group().by(__.constant("key")).by(__.constant("value")),
+ List.of(),
+ List.of(__.constant("key"), __.constant("value")),
+ null, null
+ },
+ {IntersectStep.class,
+ g.V().fold().intersect(__.constant(List.of(1, 2, 3))),
+ List.of(),
+ List.of(__.constant(List.of(1, 2, 3))),
+ null, null
+ },
+ {LocalStep.class,
+ g.V().local(__.outE().count()),
+ List.of(),
+ List.of(__.outE().count()),
+ null, null
+ },
+ {MatchStep.class,
+ g.V().match(__.as("a").out().as("b"), __.as("b").in().as("c")),
+ List.of(generateMatchChildTraversal("a", "b", __.out().asAdmin()), generateMatchChildTraversal("b", "c", __.in().asAdmin())),
+ List.of(),
+ null, null
+ },
+ {MathStep.class,
+ g.V().math("_ + 1"),
+ List.of(),
+ List.of(),
+ null, null
+ },
+ {MathStep.class,
+ g.V().math("_ + 1").by("age"),
+ List.of(),
+ List.of(new ValueTraversal("age")),
+ null, null
+ },
+ {MathStep.class,
+ g.V().math("_ + _").by("age").by(__.constant(10)),
+ List.of(),
+ List.of(new ValueTraversal("age"), __.constant(10)),
+ null, null
+ },
+ {MergeStep.class,
+ g.V().fold().merge(__.constant(List.of(1, 2, 3))),
+ List.of(),
+ List.of(__.constant(List.of(1, 2, 3))),
+ null, null
+ },
+ {NotStep.class,
+ g.V().not(__.has("age", P.gt(27))),
+ List.of(),
+ List.of(__.has("age", P.gt(27))),
+ null, null
+ },
+ {OptionalStep.class,
+ g.V().optional(__.out("knows")),
+ List.of(),
+ List.of(__.out("knows")),
+ null, null
+ },
+ {OrderGlobalStep.class,
+ g.V().order(),
+ List.of(),
+ List.of(),
+ null, null
+ },
+ {OrderGlobalStep.class,
+ g.V().order().by("name"),
+ List.of(),
+ List.of(new ValueTraversal("name")),
+ null, null
+ },
+ {OrderGlobalStep.class,
+ g.V().order().by("name").by(__.constant("value")),
+ List.of(),
+ List.of(new ValueTraversal("name"), __.constant("value")),
+ null, null
+ },
+ {OrderLocalStep.class,
+ g.V().fold().order(Scope.local),
+ List.of(),
+ List.of(),
+ null, null
+ },
+ {OrderLocalStep.class,
+ g.V().fold().order(Scope.local).by("name"),
+ List.of(),
+ List.of(new ValueTraversal("name")),
+ null, null
+ },
+ {OrderLocalStep.class,
+ g.V().fold().order(Scope.local).by(__.constant("value")),
+ List.of(),
+ List.of(__.constant("value")),
+ null, null
+ },
+ {PathFilterStep.class,
+ g.V().simplePath(),
+ List.of(),
+ List.of(),
+ null, null
+ },
+ {PathFilterStep.class,
+ g.V().cyclicPath(),
+ List.of(),
+ List.of(),
+ null, null
+ },
+ {PathFilterStep.class,
+ g.V().simplePath().by("name"),
+ List.of(),
+ List.of(new ValueTraversal("name")),
+ null, null
+ },
+ {PathFilterStep.class,
+ g.V().simplePath().by(__.constant("value")),
+ List.of(),
+ List.of(__.constant("value")),
+ null, null
+ },
+ {PathFilterStep.class,
+ g.V().cyclicPath().by("age").by(__.constant("value")),
+ List.of(),
+ List.of(new ValueTraversal("age"), __.constant("value")),
+ null, null
+ },
+ {PathStep.class,
+ g.V().path(),
+ List.of(),
+ List.of(),
+ null, null
+ },
+ {PathStep.class,
+ g.V().out().path().by("age").by("name"),
+ List.of(),
+ List.of(new ValueTraversal("age"), new ValueTraversal("name")),
+ null, null
+ },
+ {PathStep.class,
+ g.V().path().by(__.constant("value")),
+ List.of(),
+ List.of(__.constant("value")),
+ null, null
+ },
+ {ProductStep.class,
+ g.V().fold().product(__.constant(List.of(1, 2, 3))),
+ List.of(),
+ List.of(__.constant(List.of(1, 2, 3))),
+ null, null
+ },
+ {ProjectStep.class,
+ g.V().project("a", "b").by("name").by("age"),
+ List.of(),
+ List.of(new ValueTraversal("name"), new ValueTraversal("age")),
+ null, null
+ },
+ {ProjectStep.class,
+ g.V().project("x").by(__.constant("value")),
+ List.of(),
+ List.of(__.constant("value")),
+ null, null
+ },
+ {PropertyMapStep.class,
+ g.V().valueMap(),
+ List.of(),
+ List.of(),
+ null, null
+ },
+ {PropertyMapStep.class,
+ g.V().valueMap().by(__.constant("transformed")),
+ List.of(),
+ List.of(__.constant("transformed")),
+ null, null
+ },
+ {RepeatStep.class,
+ g.V().repeat(__.out()).emit().times(2),
+ List.of(appendRepeatEndStep(__.out())),
+ List.of(new LoopTraversal<>(2), TrueTraversal.instance()),
+ null, null
+ },
+ {RepeatStep.class,
+ g.V().repeat(__.out()).until(__.has("name", "josh")),
+ List.of(appendRepeatEndStep(__.out())),
+ List.of(__.has("name", "josh")),
+ null, null
+ },
+ {RepeatStep.class,
+ g.V().repeat(__.out()).emit(__.has("age")).until(__.has("name", "josh")),
+ List.of(appendRepeatEndStep(__.out())),
+ List.of(__.has("name", "josh"), __.has("age")),
+ null, List.of(__.has("name", "josh"), __.filter(__.properties("age"))),
+ },
+ {SackValueStep.class,
+ g.withSack(0).V().sack(Operator.sum),
+ List.of(),
+ List.of(),
+ null, null
+ },
+ {SackValueStep.class,
+ g.withSack(0).V().sack(Operator.sum).by("age"),
+ List.of(),
+ List.of(new ValueTraversal("age")),
+ null, null
+ },
+ {SackValueStep.class,
+ g.withSack(0).V().sack(Operator.sum).by(__.constant("age")),
+ List.of(),
+ List.of(__.constant("age")),
+ null, null
+ },
+ {SampleGlobalStep.class,
+ g.V().sample(2),
+ List.of(),
+ List.of(new ConstantTraversal<>(1.0)),
+ null, null
+ },
+ {SampleGlobalStep.class,
+ g.E().sample(2).by("weight"),
+ List.of(),
+ List.of(new ValueTraversal("weight")),
+ null, null
+ },
+ {SampleGlobalStep.class,
+ g.E().sample(2).by(__.constant("weight")),
+ List.of(),
+ List.of(__.constant("weight")),
+ null, null
+ },
+ {SelectOneStep.class,
+ g.V().as("a").select("a"),
+ List.of(),
+ List.of(),
+ null, null
+ },
+ {SelectOneStep.class,
+ g.V().as("a").select("a").by("name"),
+ List.of(),
+ List.of(new ValueTraversal("name")),
+ null, null
+ },
+ {SelectOneStep.class,
+ g.V().as("a").select("a").by(__.constant("value")),
+ List.of(),
+ List.of(__.constant("value")),
+ null, null
+ },
+ {SelectStep.class,
+ g.V().as("a").as("b").select("a", "b"),
+ List.of(),
+ List.of(),
+ null, null
+ },
+ {SelectStep.class,
+ g.V().as("a").as("b").select("a", "b").by("name"),
+ List.of(),
+ List.of(new ValueTraversal("name")),
+ null, null
+ },
+ {SelectStep.class,
+ g.V().as("a").as("b").select("a", "b").by(__.constant("value")),
+ List.of(),
+ List.of(__.constant("value")),
+ null, null
+ },
+ {TraversalSelectStep.class,
+ g.V().select((Traversal)__.constant("a")),
+ List.of(),
+ List.of(__.constant("a")),
+ null, null
+ },
+ {TraversalSelectStep.class,
+ g.V().select((Traversal)__.constant("a")).by("name"),
+ List.of(),
+ List.of(__.constant("a"), new ValueTraversal("name")),
+ null, null
+ },
+ {TraversalFilterStep.class,
+ g.V().filter(__.constant(5)), // a bit of an arbitrary case to avoid getting optimized by strategies
+ List.of(),
+ List.of(__.constant(5)),
+ null, null
+ },
+ {TraversalFlatMapStep.class,
+ g.V().flatMap(__.out()),
+ List.of(),
+ List.of(__.out()),
+ null, null
+ },
+ {TraversalFlatMapStep.class,
+ g.V().flatMap(__.constant("value")),
+ List.of(),
+ List.of(__.constant("value")),
+ null, null
+ },
+ {TraversalMapStep.class,
+ g.V().map(__.values("name")),
+ List.of(),
+ List.of(__.values("name")),
+ null, null
+ },
+ {TraversalMapStep.class,
+ g.V().map(__.constant("value")),
+ List.of(),
+ List.of(__.constant("value")),
+ null, null
+ },
+ {TraversalSideEffectStep.class,
+ g.V().sideEffect(__.identity()),
+ List.of(),
+ List.of(__.identity()),
+ null, null
+ },
+ {TraversalSideEffectStep.class,
+ g.V().sideEffect(__.constant("value")),
+ List.of(),
+ List.of(__.constant("value")),
+ null, null
+ },
+ {TreeStep.class,
+ g.V().out().tree(),
+ List.of(),
+ List.of(),
+ null, null
+ },
+ {TreeStep.class,
+ g.V().out().tree().by("name"),
+ List.of(),
+ List.of(new ValueTraversal("name")),
+ null, null
+ },
+ {TreeStep.class,
+ g.V().out().tree().by(__.constant("value")),
+ List.of(),
+ List.of(__.constant("value")),
+ null, null
+ },
+ {TreeSideEffectStep.class,
+ g.V().out().tree("x"),
+ List.of(),
+ List.of(),
+ null, null
+ },
+ {TreeSideEffectStep.class,
+ g.V().out().tree("x").by("name"),
+ List.of(),
+ List.of(new ValueTraversal("name")),
+ null, null
+ },
+ {TreeSideEffectStep.class,
+ g.V().out().tree("x").by(__.constant("value")),
+ List.of(),
+ List.of(__.constant("value")),
+ null, null
+ },
+ {UnionStep.class,
+ g.union(__.V().values("name"), __.V().values("age")),
+ List.of(appendComputerAwareEndStep(__.V().values("name")), appendComputerAwareEndStep(__.V().values("age"))),
+ List.of(new ConstantTraversal<>(Pick.any)),
+ List.of(appendComputerAwareEndStep(__.V().values("name").barrier(2500)), appendComputerAwareEndStep(__.V().values("age").barrier(2500))),
+ null
+ },
+ {UnionStep.class,
+ g.union(__.constant("a"), __.constant("b")),
+ List.of(appendComputerAwareEndStep(__.constant("a")), appendComputerAwareEndStep(__.constant("b"))),
+ List.of(new ConstantTraversal<>(Pick.any)),
+ null, null
+ },
+ {WherePredicateStep.class,
+ g.V().as("a").out().as("b").where("a", P.eq("b")),
+ List.of(),
+ List.of(),
+ null, null
+ },
+ {WherePredicateStep.class,
+ g.V().as("a").out().as("b").where("a", P.eq("b")).by("name"),
+ List.of(),
+ List.of(new ValueTraversal("name")),
+ null, null
+ },
+ {WherePredicateStep.class,
+ g.V().as("a").out().as("b").where("a", P.eq("b")).by(__.constant("value")),
+ List.of(),
+ List.of(__.constant("value")),
+ null, null
+ },
+ {WhereTraversalStep.class,
+ g.V().as("a").out().as("b").where(__.as("a").out().as("c")),
+ List.of(),
+ List.of(generateWhereChildTraversal("a", "c", __.out().asAdmin())),
+ null, null
+ },
+ });
+ }
+
+ @Test
+ public void doTest() {
+ verifyExpectedParents(expectedGlobalChildren, expectedLocalChildren, "(pre-strategy application)");
+
+ traversal = traversal.clone();
+
+ verifyExpectedParents(expectedGlobalChildren, expectedLocalChildren, "(cloned traversal, pre-strategy application)");
+
+ traversal.getStrategies().addStrategies(GValueReductionStrategy.instance());
+ traversal.applyStrategies();
+
+ verifyExpectedParents(postStrategyExpectedGlobalChildren == null ? expectedGlobalChildren : postStrategyExpectedGlobalChildren,
+ postStrategyExpectedLocalChildren == null ? expectedLocalChildren : postStrategyExpectedLocalChildren,
+ "(pre-strategy application)");
+
+ traversal = traversal.clone();
+
+ verifyExpectedParents(postStrategyExpectedGlobalChildren == null ? expectedGlobalChildren : postStrategyExpectedGlobalChildren,
+ postStrategyExpectedLocalChildren == null ? expectedLocalChildren : postStrategyExpectedLocalChildren,
+ "(cloned traversal, pre-strategy application)");
+ }
+
+ private void verifyExpectedParents(List<Traversal.Admin<?,?>> expectedGlobalChildren, List<Traversal.Admin<?,?>> expectedLocalChildren, String messageSuffix) {
+ List<Step> steps = TraversalHelper.getStepsOfAssignableClass(stepClass, traversal);
+ assertTrue(String.format("Expected a single step of class %s to test, found %d %s", stepClass.getName(), steps.size(), messageSuffix), steps.size() == 1);
+ assertTrue(String.format("Expected step to implement TraversalParent %s", messageSuffix), steps.get(0) instanceof TraversalParent);
+
+ TraversalParent testStep = (TraversalParent) steps.get(0);
+ assertThat(String.format("getGlobalChildren() did not produce the expected results %s", messageSuffix), testStep.getGlobalChildren(), containsInAnyOrder(expectedGlobalChildren.toArray()));
+ assertThat(String.format("getLocalChildren() did not produce the expected results %s", messageSuffix), testStep.getLocalChildren(), containsInAnyOrder(expectedLocalChildren.toArray()));
+
+ for (Traversal.Admin<?, ?> child : testStep.getGlobalChildren()) {
+ if (!(child instanceof AbstractLambdaTraversal)) {
+ // Use reference equality to ensure parent points to the correct object. It's not enough that the parents contents match.
+ assertTrue(String.format("Expected child traversal %s to have correctly assigned parent %s", child.toString(), messageSuffix), testStep == child.getParent());
+ }
+ }
+ for (Traversal.Admin<?, ?> child : testStep.getLocalChildren()) {
+ if (!(child instanceof AbstractLambdaTraversal)) {
+ // Use reference equality to ensure parent points to the correct object. It's not enough that the parents contents match.
+ assertTrue(String.format("Expected child traversal %s to have correctly assigned parent %s", child.toString(), messageSuffix), testStep == child.getParent());
+ }
+ }
+ }
+
+ private static Traversal<?, ?> appendComputerAwareEndStep(final Traversal<?, ?> traversal) {
+ traversal.asAdmin().addStep(new ComputerAwareStep.EndStep(traversal.asAdmin()));
Review Comment:
```suggestion
traversal.asAdmin().addStep(new ComputerAwareStep.EndStep<>(traversal.asAdmin()));
```
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@tinkerpop.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Fix TraversalParent implementations for Placeholder steps [tinkerpop]
Posted by "andreachild (via GitHub)" <gi...@apache.org>.
andreachild commented on code in PR #3209:
URL: https://github.com/apache/tinkerpop/pull/3209#discussion_r2376956359
##########
gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/TraversalParentTest.java:
##########
@@ -0,0 +1,1028 @@
+/*
+ * 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 java.time.OffsetDateTime;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.commons.configuration2.MapConfiguration;
+import org.apache.tinkerpop.gremlin.process.traversal.Operator;
+import org.apache.tinkerpop.gremlin.process.traversal.Pick;
+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.GraphTraversalSource;
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
+import org.apache.tinkerpop.gremlin.process.traversal.lambda.AbstractLambdaTraversal;
+import org.apache.tinkerpop.gremlin.process.traversal.lambda.ConstantTraversal;
+import org.apache.tinkerpop.gremlin.process.traversal.Merge;
+import org.apache.tinkerpop.gremlin.process.traversal.Scope;
+import org.apache.tinkerpop.gremlin.process.traversal.P;
+import org.apache.tinkerpop.gremlin.process.traversal.lambda.LoopTraversal;
+import org.apache.tinkerpop.gremlin.process.traversal.lambda.PredicateTraversal;
+import org.apache.tinkerpop.gremlin.process.traversal.lambda.TrueTraversal;
+import org.apache.tinkerpop.gremlin.process.traversal.lambda.ValueTraversal;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.AddEdgeStepContract;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.AddVertexStepContract;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.CallStepContract;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.MergeStepContract;
+import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.AddPropertyStepContract;
+import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.AggregateGlobalStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.AggregateLocalStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.filter.AndStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.filter.OrStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.branch.BranchStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.branch.ChooseStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.CoalesceStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.CombineStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.ConcatStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.DateDiffStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.filter.DedupGlobalStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.DifferenceStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.DisjunctStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.FormatStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.GroupCountStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.GroupCountSideEffectStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.GroupStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.IntersectStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.branch.LocalStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.MatchStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.MathStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.MergeStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.filter.NotStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.branch.OptionalStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.OrderGlobalStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.OrderLocalStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.filter.PathFilterStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.PathStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.ProductStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.ProjectStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.PropertyMapStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.branch.RepeatStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.SackValueStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.filter.SampleGlobalStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.SelectOneStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.SelectStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.TraversalSelectStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.filter.TraversalFilterStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.TraversalFlatMapStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.TraversalMapStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.TraversalSideEffectStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.TreeStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.TreeSideEffectStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.branch.UnionStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.filter.WherePredicateStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.filter.WhereTraversalStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.ComputerAwareStep;
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.GValueReductionStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper;
+import org.apache.tinkerpop.gremlin.structure.T;
+import org.apache.tinkerpop.gremlin.structure.service.Service;
+import org.apache.tinkerpop.gremlin.structure.service.ServiceRegistry;
+
+import org.apache.tinkerpop.gremlin.structure.util.GraphFactoryTest;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import static org.apache.tinkerpop.gremlin.process.traversal.AnonymousTraversalSource.traversal;
+import static org.hamcrest.Matchers.containsInAnyOrder;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+
+@RunWith(Parameterized.class)
+public class TraversalParentTest {
+
+ private static ServiceRegistry mockedRegistry= mock(ServiceRegistry.class);
+ private static Service<?, ?> mockedService = mock(Service.class);
+ private static GraphTraversalSource g = traversal().with(GraphFactoryTest.MockGraph.open(new MapConfiguration(Map.of("service-registry", mockedRegistry))));
+
+ @BeforeClass
+ public static void setupClass() {
+ when(mockedRegistry.get(any(), anyBoolean(), any())).thenReturn(mockedService);
+ when(mockedService.getRequirements()).thenReturn(Set.of());
+ }
+
+ @Parameterized.Parameter(value = 0)
+ public Class stepClass;
Review Comment:
```suggestion
public Class<Step<?,?>> stepClass;
```
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@tinkerpop.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Fix TraversalParent implementations for Placeholder steps [tinkerpop]
Posted by "spmallette (via GitHub)" <gi...@apache.org>.
spmallette commented on code in PR #3209:
URL: https://github.com/apache/tinkerpop/pull/3209#discussion_r2358611570
##########
gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/TraversalParent.java:
##########
@@ -31,14 +33,30 @@
import java.util.Set;
/**
+ * Indicates that a step can contain child Traversals. Any step which implements this interface should override at least
+ * one of getGlobalChildren() or getLocalChildren(). All TraversalParents should call integrateChild() for all child
Review Comment:
nit: `{@link ...` the method references.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@tinkerpop.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Fix TraversalParent implementations for Placeholder steps [tinkerpop]
Posted by "Cole-Greer (via GitHub)" <gi...@apache.org>.
Cole-Greer commented on code in PR #3209:
URL: https://github.com/apache/tinkerpop/pull/3209#discussion_r2373013700
##########
gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AbstractAddElementStepPlaceholder.java:
##########
@@ -175,6 +188,9 @@ public void addProperty(Object key, Object value) {
if (key instanceof GValue) {
throw new IllegalArgumentException("GValue cannot be used as a property key");
}
+ if (key instanceof Traversal) {
+ this.integrateChild(((Traversal<?, ?>) key).asAdmin());
Review Comment:
Yes it should, same goes for `setElementId`. That appears to be a gap in the testing. I will make that fix and add those cases.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@tinkerpop.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Fix TraversalParent implementations for Placeholder steps [tinkerpop]
Posted by "andreachild (via GitHub)" <gi...@apache.org>.
andreachild commented on code in PR #3209:
URL: https://github.com/apache/tinkerpop/pull/3209#discussion_r2370888205
##########
gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/TraversalParent.java:
##########
@@ -31,14 +33,31 @@
import java.util.Set;
/**
+ * Indicates that a step can contain child Traversals. Any step which implements this interface should override at least
Review Comment:
Nit: Likely out of scope for this PR but I feel it would be helpful in general for TinkerPop to have more custom annotations. In this case there could be a custom annotation like `@ChildTraversal(scope=Type.LOCAL)` to mark step fields that store a child traversal. Then there can be a single common method which handles the presence of child traversals in `AbstractStep.java` like (pseudocode):
```
@Override
public void setTraversal(final Traversal.Admin<?, ?> traversal) {
this.traversal = traversal;
// retrieve any step fields annotated with @ChildTraversal
// for each child traversal, call integrateChild
}
```
And then there could also be an `AbstractTravesalParent.java` which has:
```
<S, E> List<Traversal.Admin<S, E>> getGlobalChildren() {
// use reflection to retrieve fields annotated with @ChildTraversal(type=GLOBAL)
}
<S, E> List<Traversal.Admin<S, E>> getLocalChildren() {
// use reflection to retrieve fields annotated with @ChildTraversal(type=LOCAL)
}
```
Then when adding new steps or adding child traversals to an existing step, all you would need to do is add the custom annotation and you wouldn't have to 'remember' to do the boilerplate logic.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@tinkerpop.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Fix TraversalParent implementations for Placeholder steps [tinkerpop]
Posted by "andreachild (via GitHub)" <gi...@apache.org>.
andreachild commented on code in PR #3209:
URL: https://github.com/apache/tinkerpop/pull/3209#discussion_r2373836430
##########
gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/lambda/GValueConstantTraversal.java:
##########
@@ -57,6 +57,17 @@ public boolean equals(final Object other) {
return constantTraversal.equals(other);
}
+ @Override
+ public GValueConstantTraversal<S, E> clone() {
+ GValueConstantTraversal<S, E> clone = new GValueConstantTraversal<>(GValue.of(this.end.getName(), this.end.get()));
+ try {
+ clone.setGValueManager(this.getGValueManager().clone());
+ } catch (CloneNotSupportedException e) { //TODO:: handle properly
Review Comment:
Nit: the call to `super.clone` should go inside the try block
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@tinkerpop.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Fix TraversalParent implementations for Placeholder steps [tinkerpop]
Posted by "andreachild (via GitHub)" <gi...@apache.org>.
andreachild commented on code in PR #3209:
URL: https://github.com/apache/tinkerpop/pull/3209#discussion_r2376956359
##########
gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/TraversalParentTest.java:
##########
@@ -0,0 +1,1028 @@
+/*
+ * 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 java.time.OffsetDateTime;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.commons.configuration2.MapConfiguration;
+import org.apache.tinkerpop.gremlin.process.traversal.Operator;
+import org.apache.tinkerpop.gremlin.process.traversal.Pick;
+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.GraphTraversalSource;
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
+import org.apache.tinkerpop.gremlin.process.traversal.lambda.AbstractLambdaTraversal;
+import org.apache.tinkerpop.gremlin.process.traversal.lambda.ConstantTraversal;
+import org.apache.tinkerpop.gremlin.process.traversal.Merge;
+import org.apache.tinkerpop.gremlin.process.traversal.Scope;
+import org.apache.tinkerpop.gremlin.process.traversal.P;
+import org.apache.tinkerpop.gremlin.process.traversal.lambda.LoopTraversal;
+import org.apache.tinkerpop.gremlin.process.traversal.lambda.PredicateTraversal;
+import org.apache.tinkerpop.gremlin.process.traversal.lambda.TrueTraversal;
+import org.apache.tinkerpop.gremlin.process.traversal.lambda.ValueTraversal;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.AddEdgeStepContract;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.AddVertexStepContract;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.CallStepContract;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.MergeStepContract;
+import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.AddPropertyStepContract;
+import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.AggregateGlobalStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.AggregateLocalStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.filter.AndStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.filter.OrStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.branch.BranchStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.branch.ChooseStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.CoalesceStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.CombineStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.ConcatStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.DateDiffStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.filter.DedupGlobalStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.DifferenceStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.DisjunctStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.FormatStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.GroupCountStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.GroupCountSideEffectStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.GroupStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.IntersectStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.branch.LocalStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.MatchStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.MathStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.MergeStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.filter.NotStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.branch.OptionalStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.OrderGlobalStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.OrderLocalStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.filter.PathFilterStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.PathStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.ProductStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.ProjectStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.PropertyMapStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.branch.RepeatStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.SackValueStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.filter.SampleGlobalStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.SelectOneStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.SelectStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.TraversalSelectStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.filter.TraversalFilterStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.TraversalFlatMapStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.TraversalMapStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.TraversalSideEffectStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.TreeStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.TreeSideEffectStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.branch.UnionStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.filter.WherePredicateStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.filter.WhereTraversalStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.ComputerAwareStep;
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.GValueReductionStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper;
+import org.apache.tinkerpop.gremlin.structure.T;
+import org.apache.tinkerpop.gremlin.structure.service.Service;
+import org.apache.tinkerpop.gremlin.structure.service.ServiceRegistry;
+
+import org.apache.tinkerpop.gremlin.structure.util.GraphFactoryTest;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import static org.apache.tinkerpop.gremlin.process.traversal.AnonymousTraversalSource.traversal;
+import static org.hamcrest.Matchers.containsInAnyOrder;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+
+@RunWith(Parameterized.class)
+public class TraversalParentTest {
+
+ private static ServiceRegistry mockedRegistry= mock(ServiceRegistry.class);
+ private static Service<?, ?> mockedService = mock(Service.class);
+ private static GraphTraversalSource g = traversal().with(GraphFactoryTest.MockGraph.open(new MapConfiguration(Map.of("service-registry", mockedRegistry))));
+
+ @BeforeClass
+ public static void setupClass() {
+ when(mockedRegistry.get(any(), anyBoolean(), any())).thenReturn(mockedService);
+ when(mockedService.getRequirements()).thenReturn(Set.of());
+ }
+
+ @Parameterized.Parameter(value = 0)
+ public Class stepClass;
Review Comment:
```suggestion
public Class<?> stepClass;
```
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@tinkerpop.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Fix TraversalParent implementations for Placeholder steps [tinkerpop]
Posted by "Cole-Greer (via GitHub)" <gi...@apache.org>.
Cole-Greer commented on code in PR #3209:
URL: https://github.com/apache/tinkerpop/pull/3209#discussion_r2377241248
##########
gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/lambda/GValueConstantTraversal.java:
##########
@@ -57,6 +57,17 @@ public boolean equals(final Object other) {
return constantTraversal.equals(other);
}
+ @Override
+ public GValueConstantTraversal<S, E> clone() {
+ GValueConstantTraversal<S, E> clone = new GValueConstantTraversal<>(GValue.of(this.end.getName(), this.end.get()));
+ try {
+ clone.setGValueManager(this.getGValueManager().clone());
+ } catch (CloneNotSupportedException e) { //TODO:: handle properly
Review Comment:
I'm still leaving this scope to a followup on cloning, although `AbstractLambdaTraversal.clone()` does not throw `CloneNotSupportedException` so adding it to the try does not have any effect. There's actually no way for `GValue` or `GValueManager` to throw `CloneNotSupportedException` either given the current implementation, so in the followup this will be corrected and the try-catch will go away altogether.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@tinkerpop.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org