You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tinkerpop.apache.org by sp...@apache.org on 2024/08/08 20:29:12 UTC
(tinkerpop) branch gvalue updated (3775b6fe71 -> ee43de1be5)
This is an automated email from the ASF dual-hosted git repository.
spmallette pushed a change to branch gvalue
in repository https://gitbox.apache.org/repos/asf/tinkerpop.git
from 3775b6fe71 wip
new 1eec10961d wip
new ee43de1be5 wip
The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
Summary of changes:
.../grammar/DefaultGremlinBaseVisitor.java | 12 +-
.../language/grammar/TraversalMethodVisitor.java | 100 ++++++++++-------
.../grammar/TraversalSourceSpawnMethodVisitor.java | 15 ++-
.../translator/DotNetTranslateVisitor.java | 23 ++--
.../language/translator/TranslateVisitor.java | 5 -
.../gremlin/process/traversal/Operator.java | 10 +-
.../tinkerpop/gremlin/process/traversal/P.java | 20 +++-
.../traversal/dsl/graph/GraphTraversal.java | 124 ++++++++++++++++++++-
.../traversal/dsl/graph/GraphTraversalSource.java | 32 +++++-
.../gremlin/process/traversal/step/GValue.java | 13 ++-
.../process/traversal/step/map/AddEdgeStep.java | 9 +-
.../process/traversal/step/map/CallStep.java | 36 ++++--
.../process/traversal/step/map/ConstantStep.java | 2 +-
.../process/traversal/step/map/DifferenceStep.java | 16 ++-
.../process/traversal/step/map/DisjunctStep.java | 12 +-
.../process/traversal/step/map/GraphStep.java | 13 +++
.../process/traversal/step/map/ProductStep.java | 15 ++-
.../traversal/step/map/TraversalMergeStep.java | 3 +-
.../traversal/step/sideEffect/InjectStep.java | 2 +-
.../process/traversal/step/util/AbstractStep.java | 19 +++-
.../process/traversal/step/util/HasContainer.java | 6 +-
.../strategy/decoration/SideEffectStrategy.java | 7 +-
.../gremlin/process/traversal/step/GValueTest.java | 4 +-
gremlin-language/src/main/antlr4/Gremlin.g4 | 7 +-
.../tinkerpop/gremlin/features/StepDefinition.java | 25 +++--
.../traversal/step/sideEffect/TinkerGraphStep.java | 14 ++-
26 files changed, 404 insertions(+), 140 deletions(-)
(tinkerpop) 02/02: wip
Posted by sp...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
spmallette pushed a commit to branch gvalue
in repository https://gitbox.apache.org/repos/asf/tinkerpop.git
commit ee43de1be589c9b5de12397201c6174756c5b1e1
Author: Stephen Mallette <st...@amazon.com>
AuthorDate: Thu Aug 8 16:24:37 2024 -0400
wip
---
.../tinkerpop/gremlin/process/traversal/P.java | 20 +++++++++++++++++---
.../process/traversal/dsl/graph/GraphTraversal.java | 7 +++++++
.../gremlin/process/traversal/step/GValue.java | 4 ++--
.../process/traversal/step/map/GraphStep.java | 13 +++++++++++++
.../process/traversal/step/util/AbstractStep.java | 19 ++++++++++++++++++-
.../process/traversal/step/util/HasContainer.java | 6 ++++--
.../gremlin/process/traversal/step/GValueTest.java | 4 ++--
.../traversal/step/sideEffect/TinkerGraphStep.java | 14 ++++++++------
8 files changed, 71 insertions(+), 16 deletions(-)
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/P.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/P.java
index 56e1946368..622a3c3e3a 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/P.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/P.java
@@ -25,7 +25,9 @@ import org.apache.tinkerpop.gremlin.process.traversal.util.OrP;
import java.io.Serializable;
import java.util.Arrays;
import java.util.Collection;
+import java.util.List;
import java.util.function.Predicate;
+import java.util.stream.Collectors;
/**
* Predefined {@code Predicate} values that can be used to define filters to {@code has()} and {@code where()}.
@@ -75,10 +77,22 @@ public class P<V> implements Predicate<V>, Serializable, Cloneable {
@Override
public boolean test(final V testValue) {
- if (this.value instanceof GValue)
+ if (this.value instanceof GValue) {
return this.biPredicate.test(testValue, ((GValue<V>) this.value).get());
- else
- return this.biPredicate.test(testValue, this.value);
+ } else {
+ // this might be a bunch of GValue that need to be resolved. zomg
+ if (this.value instanceof List) {
+ return this.biPredicate.test(testValue, (V) ((List) this.value).stream().map(o -> {
+ if (o instanceof GValue) {
+ return ((GValue) o).get();
+ } else {
+ return o;
+ }
+ }).collect(Collectors.toList()));
+ } else {
+ return this.biPredicate.test(testValue, this.value);
+ }
+ }
}
@Override
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.java
index 0a392fc334..a7379fd914 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.java
@@ -25,6 +25,7 @@ import org.apache.tinkerpop.gremlin.process.computer.traversal.step.map.PageRank
import org.apache.tinkerpop.gremlin.process.computer.traversal.step.map.PeerPressureVertexProgramStep;
import org.apache.tinkerpop.gremlin.process.computer.traversal.step.map.ProgramVertexProgramStep;
import org.apache.tinkerpop.gremlin.process.computer.traversal.step.map.ShortestPathVertexProgramStep;
+import org.apache.tinkerpop.gremlin.process.traversal.Contains;
import org.apache.tinkerpop.gremlin.process.traversal.DT;
import org.apache.tinkerpop.gremlin.process.traversal.Failure;
import org.apache.tinkerpop.gremlin.process.traversal.Merge;
@@ -2837,6 +2838,12 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
} else {
this.asAdmin().getBytecode().addStep(Symbols.hasId, id, otherIds);
+ // the logic for dealing with hasId([]) is sketchy historically, just trying to maintain what we were
+ // originally testing prior to GValue.
+ if (id instanceof GValue && ((GValue) id).getType().isCollection()) {
+ return TraversalHelper.addHasContainer(this.asAdmin(), new HasContainer(T.id.getAccessor(), new P(Contains.within, id)));
+ }
+
//using ArrayList given P.within() turns all arguments into lists
final List<Object> ids = new ArrayList<>();
if (id instanceof Object[]) {
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/GValue.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/GValue.java
index 41caaea1a2..da0694acdc 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/GValue.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/GValue.java
@@ -246,14 +246,14 @@ public class GValue<V> implements Cloneable, Serializable {
/**
* Create a new {@code GValue} for a list value.
*/
- public static GValue<List> ofList(final List value) {
+ public static <T> GValue<List<T>> ofList(final List<T> value) {
return new GValue<>(GType.LIST, value);
}
/**
* Create a new {@code GValue} for a list value with a specified name.
*/
- public static GValue<List> ofList(final String name, final List value) {
+ public static <T> GValue<List<T>> ofList(final String name, final List<T> value) {
return new GValue<>(name, GType.LIST, value);
}
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/GraphStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/GraphStep.java
index 5c03500d6e..784ef087f3 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/GraphStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/GraphStep.java
@@ -43,6 +43,7 @@ import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
+import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Supplier;
@@ -56,6 +57,7 @@ public class GraphStep<S, E extends Element> extends AbstractStep<S, E> implemen
protected Parameters parameters = new Parameters();
protected final Class<E> returnClass;
protected GValue<?>[] ids;
+ protected boolean legacyLogicForPassingNoIds = false;
protected transient Supplier<Iterator<E>> iteratorSupplier;
protected boolean isStart;
protected boolean done = false;
@@ -152,10 +154,21 @@ public class GraphStep<S, E extends Element> extends AbstractStep<S, E> implemen
* Gets the ids associated with this step as literal values rather than {@link GValue} objects.
*/
public Object[] getResolvedIds() {
+ if (legacyLogicForPassingNoIds) return null;
return resolveToValues(this.ids);
}
public void addIds(final Object... newIds) {
+ // there is some logic that has been around for a long time that used to set ids to null. it only happened here
+ // in this method and only occurred when the ids were already null or empty and the newIds were length 1 and
+ // an instance of List and that list was empty. so basically it would trigger for something like g.V().hasId([])
+ // which in turn would trigger an empty iterator in TinkerGraphStep and zero results. trying to maintain that
+ // logic now with GValue in the mix is tough because the context of what the meaning is gets lost by the time
+ // you get to calling getResolvedIds(). using a flag to try to maintain that legacy logic, but ultimately, all
+ // this needs to be rethought.
+ this.legacyLogicForPassingNoIds = newIds.length == 1 && ((newIds[0] instanceof List && ((List) newIds[0]).isEmpty()) ||
+ (newIds[0] instanceof GValue && ((GValue) newIds[0]).getType().isCollection() && ((List) ((GValue) newIds[0]).get()).isEmpty()));
+
final GValue[] gvalues = convertToGValues(tryUnrollSingleCollectionArgument(newIds));
this.ids = ArrayUtils.addAll(this.ids, gvalues);
}
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/AbstractStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/AbstractStep.java
index 15ddacdc91..dd6f5fb849 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/AbstractStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/AbstractStep.java
@@ -28,9 +28,11 @@ import org.apache.tinkerpop.gremlin.process.traversal.util.EmptyTraversal;
import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalInterruptedException;
import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
+import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashSet;
+import java.util.List;
import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.Set;
@@ -245,7 +247,22 @@ public abstract class AbstractStep<S, E> implements Step<S, E> {
}
/**
- * Converts {@link GValue} objects the argument array to their values to prevent them from leaking to the Graph API.
+ * Converts {@link GValue} objects arguments to their values to prevent them from leaking to the Graph API.
+ * Providers extending from this step should use this method to get actual values to prevent any {@link GValue}
+ * objects from leaking to the Graph API.
+ */
+ protected Object[] resolveToValues(final List<GValue<?>> gvalues) {
+ // convert gvalues to array
+ final Object[] newIds = new Object[gvalues.size()];
+ int i = 0;
+ for (final GValue<?> gvalue : gvalues) {
+ newIds[i++] = gvalue.get();
+ }
+ return newIds;
+ }
+
+ /**
+ * Converts {@link GValue} objects argument array to their values to prevent them from leaking to the Graph API.
* Providers extending from this step should use this method to get actual values to prevent any {@link GValue}
* objects from leaking to the Graph API.
*/
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/HasContainer.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/HasContainer.java
index c20c68fde0..d456b09df6 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/HasContainer.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/HasContainer.java
@@ -19,10 +19,12 @@
package org.apache.tinkerpop.gremlin.process.traversal.step.util;
import org.apache.tinkerpop.gremlin.process.traversal.P;
+import org.apache.tinkerpop.gremlin.process.traversal.step.GType;
import org.apache.tinkerpop.gremlin.structure.Element;
import org.apache.tinkerpop.gremlin.structure.Property;
import org.apache.tinkerpop.gremlin.structure.T;
import org.apache.tinkerpop.gremlin.structure.util.CloseableIterator;
+import org.apache.tinkerpop.gremlin.process.traversal.step.GValue;
import java.io.Serializable;
import java.util.Collection;
@@ -154,11 +156,11 @@ public class HasContainer implements Serializable, Cloneable, Predicate<Element>
if (predicateValue instanceof Collection) {
final Collection collection = (Collection) predicateValue;
if (!collection.isEmpty()) {
- return ((Collection) predicateValue).stream().allMatch(c -> null == c || c instanceof String);
+ return ((Collection) predicateValue).stream().allMatch(c -> null == c || c instanceof String || (c instanceof GValue && ((GValue) c).getType() == GType.STRING));
}
}
- return predicateValue instanceof String;
+ return predicateValue instanceof String || (predicateValue instanceof GValue && ((GValue) predicateValue).getType() == GType.STRING);
}
return false;
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/GValueTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/GValueTest.java
index d1742e3e29..f4ae56dff8 100644
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/GValueTest.java
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/GValueTest.java
@@ -203,7 +203,7 @@ public class GValueTest {
@Test
public void shouldCreateGValueFromList() {
final List<String> list = Arrays.asList("value1", "value2");
- final GValue<List> gValue = GValue.ofList(list);
+ final GValue<List<String>> gValue = GValue.ofList(list);
assertEquals(list, gValue.get());
assertEquals(GType.LIST, gValue.getType());
assertThat(gValue.isVariable(), is(false));
@@ -212,7 +212,7 @@ public class GValueTest {
@Test
public void shouldCreateGValueFromListWithName() {
final List<String> list = Arrays.asList("value1", "value2");
- final GValue<List> gValue = GValue.ofList("varName", list);
+ final GValue<List<String>> gValue = GValue.ofList("varName", list);
assertEquals(list, gValue.get());
assertEquals(GType.LIST, gValue.getType());
assertEquals("varName", gValue.getName());
diff --git a/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/process/traversal/step/sideEffect/TinkerGraphStep.java b/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/process/traversal/step/sideEffect/TinkerGraphStep.java
index e529d78390..9715c0e4e4 100644
--- a/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/process/traversal/step/sideEffect/TinkerGraphStep.java
+++ b/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/process/traversal/step/sideEffect/TinkerGraphStep.java
@@ -71,11 +71,12 @@ public final class TinkerGraphStep<S, E extends Element> extends GraphStep<S, E>
final AbstractTinkerGraph graph = (AbstractTinkerGraph) this.getTraversal().getGraph().get();
final HasContainer indexedContainer = getIndexKey(Edge.class);
Iterator<Edge> iterator;
+ final Object[] resolvedIds = this.getResolvedIds();
// ids are present, filter on them first
- if (null == this.ids)
+ if (null == resolvedIds)
iterator = Collections.emptyIterator();
- else if (this.ids.length > 0)
- iterator = this.iteratorList(graph.edges(this.getResolvedIds()));
+ else if (resolvedIds.length > 0)
+ iterator = this.iteratorList(graph.edges(resolvedIds));
else
iterator = null == indexedContainer ?
this.iteratorList(graph.edges()) :
@@ -93,11 +94,12 @@ public final class TinkerGraphStep<S, E extends Element> extends GraphStep<S, E>
final AbstractTinkerGraph graph = (AbstractTinkerGraph) this.getTraversal().getGraph().get();
final HasContainer indexedContainer = getIndexKey(Vertex.class);
Iterator<? extends Vertex> iterator;
+ final Object[] resolvedIds = this.getResolvedIds();
// ids are present, filter on them first
- if (null == this.ids)
+ if (null == resolvedIds)
iterator = Collections.emptyIterator();
- else if (this.ids.length > 0)
- iterator = this.iteratorList(graph.vertices(this.getResolvedIds()));
+ else if (resolvedIds.length > 0)
+ iterator = this.iteratorList(graph.vertices(resolvedIds));
else
iterator = (null == indexedContainer ?
this.iteratorList(graph.vertices()) :
(tinkerpop) 01/02: wip
Posted by sp...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
spmallette pushed a commit to branch gvalue
in repository https://gitbox.apache.org/repos/asf/tinkerpop.git
commit 1eec10961d99e68f49c2393ac36e6a15507008d2
Author: Stephen Mallette <st...@amazon.com>
AuthorDate: Wed Aug 7 15:06:28 2024 -0400
wip
---
.../grammar/DefaultGremlinBaseVisitor.java | 12 +--
.../language/grammar/TraversalMethodVisitor.java | 100 ++++++++++--------
.../grammar/TraversalSourceSpawnMethodVisitor.java | 15 ++-
.../translator/DotNetTranslateVisitor.java | 23 ++--
.../language/translator/TranslateVisitor.java | 5 -
.../gremlin/process/traversal/Operator.java | 10 +-
.../traversal/dsl/graph/GraphTraversal.java | 117 ++++++++++++++++++++-
.../traversal/dsl/graph/GraphTraversalSource.java | 32 +++++-
.../gremlin/process/traversal/step/GValue.java | 9 +-
.../process/traversal/step/map/AddEdgeStep.java | 9 +-
.../process/traversal/step/map/CallStep.java | 36 +++++--
.../process/traversal/step/map/ConstantStep.java | 2 +-
.../process/traversal/step/map/DifferenceStep.java | 16 ++-
.../process/traversal/step/map/DisjunctStep.java | 12 ++-
.../process/traversal/step/map/ProductStep.java | 15 ++-
.../traversal/step/map/TraversalMergeStep.java | 3 +-
.../traversal/step/sideEffect/InjectStep.java | 2 +-
.../strategy/decoration/SideEffectStrategy.java | 7 +-
gremlin-language/src/main/antlr4/Gremlin.g4 | 7 +-
.../tinkerpop/gremlin/features/StepDefinition.java | 25 ++---
20 files changed, 333 insertions(+), 124 deletions(-)
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/DefaultGremlinBaseVisitor.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/DefaultGremlinBaseVisitor.java
index 3bfb22d17b..f32e40e44b 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/DefaultGremlinBaseVisitor.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/DefaultGremlinBaseVisitor.java
@@ -414,11 +414,11 @@ public class DefaultGremlinBaseVisitor<T> extends AbstractParseTreeVisitor<T> im
/**
* {@inheritDoc}
*/
- @Override public T visitTraversalMethod_from_Traversal(final GremlinParser.TraversalMethod_from_TraversalContext ctx) { notImplemented(ctx); return null; }
+ @Override public T visitTraversalMethod_from_Vertex(final GremlinParser.TraversalMethod_from_VertexContext ctx) { notImplemented(ctx); return null; }
/**
* {@inheritDoc}
*/
- @Override public T visitTraversalMethod_from_Vertex(final GremlinParser.TraversalMethod_from_VertexContext ctx) { notImplemented(ctx); return null; }
+ @Override public T visitTraversalMethod_from_Traversal(final GremlinParser.TraversalMethod_from_TraversalContext ctx) { notImplemented(ctx); return null; }
/**
* {@inheritDoc}
*/
@@ -854,11 +854,11 @@ public class DefaultGremlinBaseVisitor<T> extends AbstractParseTreeVisitor<T> im
/**
* {@inheritDoc}
*/
- @Override public T visitTraversalMethod_to_Traversal(final GremlinParser.TraversalMethod_to_TraversalContext ctx) { notImplemented(ctx); return null; }
+ @Override public T visitTraversalMethod_to_Vertex(final GremlinParser.TraversalMethod_to_VertexContext ctx) { notImplemented(ctx); return null; }
/**
* {@inheritDoc}
*/
- @Override public T visitTraversalMethod_to_Vertex(final GremlinParser.TraversalMethod_to_VertexContext ctx) { notImplemented(ctx); return null; }
+ @Override public T visitTraversalMethod_to_Traversal(final GremlinParser.TraversalMethod_to_TraversalContext ctx) { notImplemented(ctx); return null; }
/**
* {@inheritDoc}
*/
@@ -1395,10 +1395,6 @@ public class DefaultGremlinBaseVisitor<T> extends AbstractParseTreeVisitor<T> im
* {@inheritDoc}
*/
@Override public T visitTraversalMethod_option_Merge_Map(final GremlinParser.TraversalMethod_option_Merge_MapContext ctx) { notImplemented(ctx); return null; }
- /**
- * {@inheritDoc}
- */
- @Override public T visitTraversalMethod_option_Merge_Traversal(final GremlinParser.TraversalMethod_option_Merge_TraversalContext ctx) { notImplemented(ctx); return null; }
/**
* {@inheritDoc}
*/
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalMethodVisitor.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalMethodVisitor.java
index fe500e6210..daf72820d4 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalMethodVisitor.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalMethodVisitor.java
@@ -25,14 +25,12 @@ import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal;
import org.apache.tinkerpop.gremlin.process.traversal.step.GType;
import org.apache.tinkerpop.gremlin.process.traversal.step.GValue;
+import org.apache.tinkerpop.gremlin.structure.Vertex;
import org.apache.tinkerpop.gremlin.structure.VertexProperty.Cardinality;
-import java.util.Collection;
import java.util.Map;
import java.util.function.BiFunction;
-import static org.apache.tinkerpop.gremlin.process.traversal.SackFunctions.Barrier.normSack;
-
/**
* Specific case of TraversalRootVisitor where all TraversalMethods returns
* a GraphTraversal object.
@@ -535,7 +533,11 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
*/
@Override
public GraphTraversal visitTraversalMethod_difference_Object(final GremlinParser.TraversalMethod_difference_ObjectContext ctx) {
- return graphTraversal.difference(antlr.argumentVisitor.visitGenericLiteralArgument(ctx.genericLiteralArgument()));
+ final Object literalOrVar = antlr.argumentVisitor.visitGenericLiteralArgument(ctx.genericLiteralArgument());
+ if (literalOrVar instanceof GValue && ((GValue) literalOrVar).getType().isCollection())
+ return graphTraversal.difference((GValue<Object>) literalOrVar);
+ else
+ return graphTraversal.difference(literalOrVar);
}
/**
@@ -543,7 +545,11 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
*/
@Override
public GraphTraversal visitTraversalMethod_disjunct_Object(final GremlinParser.TraversalMethod_disjunct_ObjectContext ctx) {
- return graphTraversal.disjunct(antlr.argumentVisitor.visitGenericLiteralArgument(ctx.genericLiteralArgument()));
+ final Object literalOrVar = antlr.argumentVisitor.visitGenericLiteralArgument(ctx.genericLiteralArgument());
+ if (literalOrVar instanceof GValue && ((GValue) literalOrVar).getType().isCollection())
+ return graphTraversal.disjunct((GValue<Object>) literalOrVar);
+ else
+ return graphTraversal.disjunct(literalOrVar);
}
/**
@@ -640,8 +646,22 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
* {@inheritDoc}
*/
@Override
- public GraphTraversal visitTraversalMethod_from_String(final GremlinParser.TraversalMethod_from_StringContext ctx) {
- return graphTraversal.from(antlr.argumentVisitor.parseString(ctx.stringArgument()));
+ public Traversal visitTraversalMethod_from_String(final GremlinParser.TraversalMethod_from_StringContext ctx) {
+ return graphTraversal.from(antlr.genericVisitor.parseString(ctx.stringLiteral()));
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Traversal visitTraversalMethod_from_Vertex(final GremlinParser.TraversalMethod_from_VertexContext ctx) {
+ final Object literalOrVar = antlr.argumentVisitor.visitStructureVertexArgument(ctx.structureVertexArgument());
+ if (literalOrVar instanceof Vertex)
+ return graphTraversal.from((Vertex) literalOrVar);
+ else if (literalOrVar instanceof GValue && ((GValue) literalOrVar).getType() == GType.VERTEX)
+ return graphTraversal.from((GValue<Vertex>) literalOrVar);
+ else
+ throw new IllegalArgumentException("from argument must be a vertex");
}
/**
@@ -1162,15 +1182,6 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
return graphTraversal.option(antlr.argumentVisitor.parseMerge(ctx.traversalMergeArgument()), (Map) literalOrVar);
}
- /**
- * {@inheritDoc}
- */
- @Override
- public GraphTraversal visitTraversalMethod_option_Merge_Traversal(final GremlinParser.TraversalMethod_option_Merge_TraversalContext ctx) {
- return this.graphTraversal.option(antlr.argumentVisitor.parseMerge(ctx.traversalMergeArgument()),
- antlr.tvisitor.visitNestedTraversal(ctx.nestedTraversal()));
- }
-
/**
* {@inheritDoc}
*/
@@ -1298,7 +1309,11 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
*/
@Override
public GraphTraversal visitTraversalMethod_product_Object(final GremlinParser.TraversalMethod_product_ObjectContext ctx) {
- return graphTraversal.product(antlr.argumentVisitor.visitGenericLiteralArgument(ctx.genericLiteralArgument()));
+ final Object literalOrVar = antlr.argumentVisitor.visitGenericLiteralArgument(ctx.genericLiteralArgument());
+ if (literalOrVar instanceof GValue && ((GValue) literalOrVar).getType().isCollection())
+ return graphTraversal.product((GValue<Object>) literalOrVar);
+ else
+ return graphTraversal.product(literalOrVar);
}
/**
@@ -1641,7 +1656,7 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
*/
@Override
public GraphTraversal visitTraversalMethod_to_Direction_String(final GremlinParser.TraversalMethod_to_Direction_StringContext ctx) {
- return graphTraversal.to(antlr.argumentVisitor.parseDirection(ctx.traversalDirectionArgument()),
+ return graphTraversal.to(TraversalEnumParser.parseTraversalDirectionFromContext(ctx.traversalDirection()),
antlr.genericVisitor.parseStringVarargs(ctx.stringLiteralVarargs()));
}
@@ -1649,8 +1664,22 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
* {@inheritDoc}
*/
@Override
- public GraphTraversal visitTraversalMethod_to_String(final GremlinParser.TraversalMethod_to_StringContext ctx) {
- return graphTraversal.to(antlr.argumentVisitor.parseString(ctx.stringArgument()));
+ public Traversal visitTraversalMethod_to_String(final GremlinParser.TraversalMethod_to_StringContext ctx) {
+ return graphTraversal.to(antlr.genericVisitor.parseString(ctx.stringLiteral()));
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Traversal visitTraversalMethod_to_Vertex(final GremlinParser.TraversalMethod_to_VertexContext ctx) {
+ final Object literalOrVar = antlr.argumentVisitor.visitStructureVertexArgument(ctx.structureVertexArgument());
+ if (literalOrVar instanceof Vertex)
+ return graphTraversal.to((Vertex) literalOrVar);
+ else if (literalOrVar instanceof GValue && ((GValue) literalOrVar).getType() == GType.VERTEX)
+ return graphTraversal.to((GValue<Vertex>) literalOrVar);
+ else
+ throw new IllegalArgumentException("from argument must be a vertex");
}
/**
@@ -1789,22 +1818,6 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
antlr.tvisitor.visitNestedTraversal(ctx.nestedTraversal()));
}
- /**
- * {@inheritDoc}
- */
- @Override
- public Traversal visitTraversalMethod_from_Vertex(final GremlinParser.TraversalMethod_from_VertexContext ctx) {
- return graphTraversal.from(antlr.argumentVisitor.parseVertex(ctx.structureVertexArgument()));
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public Traversal visitTraversalMethod_to_Vertex(final GremlinParser.TraversalMethod_to_VertexContext ctx) {
- return graphTraversal.to(antlr.argumentVisitor.parseVertex(ctx.structureVertexArgument()));
- }
-
/**
* {@inheritDoc}
*/
@@ -1826,8 +1839,11 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
*/
@Override
public Traversal visitTraversalMethod_call_string_map(final GremlinParser.TraversalMethod_call_string_mapContext ctx) {
- return graphTraversal.call(antlr.argumentVisitor.parseString(ctx.stringArgument()),
- antlr.argumentVisitor.parseMap(ctx.genericLiteralMapArgument()));
+ final Object literalOrVar = antlr.argumentVisitor.visitGenericLiteralMapArgument(ctx.genericLiteralMapArgument());
+ if (literalOrVar instanceof GValue && ((GValue) literalOrVar).getType() == GType.MAP)
+ return graphTraversal.call(antlr.argumentVisitor.parseString(ctx.stringArgument()), (GValue<Map>) literalOrVar);
+ else
+ return graphTraversal.call(antlr.argumentVisitor.parseString(ctx.stringArgument()), (Map) literalOrVar);
}
/**
@@ -1844,9 +1860,11 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal>
*/
@Override
public Traversal visitTraversalMethod_call_string_map_traversal(final GremlinParser.TraversalMethod_call_string_map_traversalContext ctx) {
- return graphTraversal.call(antlr.argumentVisitor.parseString(ctx.stringArgument()),
- antlr.argumentVisitor.parseMap(ctx.genericLiteralMapArgument()),
- antlr.tvisitor.visitNestedTraversal(ctx.nestedTraversal()));
+ final Object literalOrVar = antlr.argumentVisitor.visitGenericLiteralMapArgument(ctx.genericLiteralMapArgument());
+ if (literalOrVar instanceof GValue && ((GValue) literalOrVar).getType() == GType.MAP)
+ return graphTraversal.call(antlr.argumentVisitor.parseString(ctx.stringArgument()), (GValue<Map>) literalOrVar, antlr.tvisitor.visitNestedTraversal(ctx.nestedTraversal()));
+ else
+ return graphTraversal.call(antlr.argumentVisitor.parseString(ctx.stringArgument()), (Map) literalOrVar, antlr.tvisitor.visitNestedTraversal(ctx.nestedTraversal()));
}
/**
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalSourceSpawnMethodVisitor.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalSourceSpawnMethodVisitor.java
index 8e5ba3ded2..bedf28d487 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalSourceSpawnMethodVisitor.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalSourceSpawnMethodVisitor.java
@@ -177,8 +177,11 @@ public class TraversalSourceSpawnMethodVisitor extends DefaultGremlinBaseVisitor
*/
@Override
public GraphTraversal visitTraversalSourceSpawnMethod_call_string_map(final GremlinParser.TraversalSourceSpawnMethod_call_string_mapContext ctx) {
- return this.traversalSource.call(antlr.argumentVisitor.parseString(ctx.stringArgument()),
- antlr.argumentVisitor.parseMap(ctx.genericLiteralMapArgument()));
+ final Object literalOrVar = antlr.argumentVisitor.visitGenericLiteralMapArgument(ctx.genericLiteralMapArgument());
+ if (literalOrVar instanceof GValue && ((GValue) literalOrVar).getType() == GType.MAP)
+ return this.traversalSource.asAdmin().call(antlr.argumentVisitor.parseString(ctx.stringArgument()), (GValue<Map>) literalOrVar);
+ else
+ return this.traversalSource.call(antlr.argumentVisitor.parseString(ctx.stringArgument()), (Map) literalOrVar);
}
/**
@@ -195,9 +198,11 @@ public class TraversalSourceSpawnMethodVisitor extends DefaultGremlinBaseVisitor
*/
@Override
public GraphTraversal visitTraversalSourceSpawnMethod_call_string_map_traversal(final GremlinParser.TraversalSourceSpawnMethod_call_string_map_traversalContext ctx) {
- return this.traversalSource.call(antlr.argumentVisitor.parseString(ctx.stringArgument()),
- antlr.argumentVisitor.parseMap(ctx.genericLiteralMapArgument()),
- anonymousVisitor.visitNestedTraversal(ctx.nestedTraversal()));
+ final Object literalOrVar = antlr.argumentVisitor.visitGenericLiteralMapArgument(ctx.genericLiteralMapArgument());
+ if (literalOrVar instanceof GValue && ((GValue) literalOrVar).getType() == GType.MAP)
+ return this.traversalSource.asAdmin().call(antlr.argumentVisitor.parseString(ctx.stringArgument()), (GValue<Map>) literalOrVar, anonymousVisitor.visitNestedTraversal(ctx.nestedTraversal()));
+ else
+ return this.traversalSource.call(antlr.argumentVisitor.parseString(ctx.stringArgument()), (Map) literalOrVar, anonymousVisitor.visitNestedTraversal(ctx.nestedTraversal()));
}
/**
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/translator/DotNetTranslateVisitor.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/translator/DotNetTranslateVisitor.java
index 2701819624..f4607ae087 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/translator/DotNetTranslateVisitor.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/translator/DotNetTranslateVisitor.java
@@ -872,16 +872,19 @@ public class DotNetTranslateVisitor extends AbstractTranslateVisitor {
}
@Override
- public Void visitTraversalMethod_option_Merge_Traversal(final GremlinParser.TraversalMethod_option_Merge_TraversalContext ctx) {
- // call is ambiguous without an explicit cast
- visit(ctx.getChild(0));
- sb.append("(");
- visit(ctx.traversalMergeArgument());
- sb.append(", ");
- sb.append("(ITraversal) ");
- visit(ctx.nestedTraversal());
- sb.append(")");
- return null;
+ public Void visitTraversalMethod_option_Object_Traversal(final GremlinParser.TraversalMethod_option_Object_TraversalContext ctx) {
+ if (ctx.genericLiteralArgument().genericLiteral().traversalMerge() != null) {
+ visit(ctx.getChild(0));
+ sb.append("(");
+ visit(ctx.genericLiteralArgument());
+ sb.append(", ");
+ sb.append("(ITraversal) ");
+ visit(ctx.nestedTraversal());
+ sb.append(")");
+ return null;
+ } else {
+ return super.visitTraversalMethod_option_Object_Traversal(ctx);
+ }
}
@Override
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/translator/TranslateVisitor.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/translator/TranslateVisitor.java
index 00a8523b45..553ae00be7 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/translator/TranslateVisitor.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/translator/TranslateVisitor.java
@@ -902,11 +902,6 @@ public class TranslateVisitor extends AbstractParseTreeVisitor<Void> implements
return visitChildren(ctx);
}
- @Override
- public Void visitTraversalMethod_option_Merge_Traversal(final GremlinParser.TraversalMethod_option_Merge_TraversalContext ctx) {
- return visitChildren(ctx);
- }
-
@Override
public Void visitTraversalMethod_option_Object_Traversal(final GremlinParser.TraversalMethod_option_Object_TraversalContext ctx) {
return visitChildren(ctx);
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Operator.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Operator.java
index 5bb2c85b3a..2e2a2ee91d 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Operator.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Operator.java
@@ -186,9 +186,13 @@ public enum Operator implements BinaryOperator<Object> {
if (a instanceof Map && b instanceof Map)
((Map<?,?>) a).putAll((Map) b);
- else if (a instanceof Collection && a instanceof Collection)
- ((Collection<?>) a).addAll((Collection) b);
- else
+ else if (a instanceof Collection && a instanceof Collection) {
+ try {
+ ((Collection<?>) a).addAll((Collection) b);
+ } catch (UnsupportedOperationException uoe) {
+ uoe.printStackTrace();
+ }
+ } else
throw new IllegalArgumentException(String.format("Objects must be both of Map or Collection: a=%s b=%s",
a.getClass().getSimpleName(), b.getClass().getSimpleName()));
return a;
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.java
index 7967688a87..0a392fc334 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.java
@@ -550,6 +550,30 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
return this.asAdmin().addStep(new ConjoinStep<>(this.asAdmin(), delimiter));
}
+ /**
+ * Calculates the difference between the list traverser and list argument.
+ *
+ * @return the traversal with an appended {@link DifferenceStep}.
+ * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#difference-step" target="_blank">Reference Documentation - Difference Step</a>
+ * @since 3.7.1
+ */
+ public default GraphTraversal<S, Set<?>> difference(final GValue<Object> values) {
+ this.asAdmin().getBytecode().addStep(GraphTraversal.Symbols.difference, values);
+ return this.asAdmin().addStep(new DifferenceStep<>(this.asAdmin(), values));
+ }
+
+ /**
+ * Calculates the disjunction between the list traverser and list argument.
+ *
+ * @return the traversal with an appended {@link DisjunctStep}.
+ * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#disjunct-step" target="_blank">Reference Documentation - Disjunct Step</a>
+ * @since 3.7.3
+ */
+ public default GraphTraversal<S, Set<?>> disjunct(final GValue<Object> values) {
+ this.asAdmin().getBytecode().addStep(GraphTraversal.Symbols.disjunct, values);
+ return this.asAdmin().addStep(new DisjunctStep<>(this.asAdmin(), values));
+ }
+
/**
* Calculates the intersection between the list traverser and list argument.
*
@@ -567,13 +591,98 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
*
* @return the traversal with an appended {@link TraversalMergeStep}.
* @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#merge-step" target="_blank">Reference Documentation - Merge Step</a>
- * @since 3.7.1
+ * @since 3.7.3
*/
public default <E2> GraphTraversal<S, E2> merge(final GValue<Object> values) {
this.asAdmin().getBytecode().addStep(GraphTraversal.Symbols.merge, values);
return this.asAdmin().addStep(new TraversalMergeStep<>(this.asAdmin(), values));
}
+ /**
+ * Calculates the cartesian product between the list traverser and list argument.
+ *
+ * @return the traversal with an appended {@link ProductStep}.
+ * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#product-step" target="_blank">Reference Documentation - Product Step</a>
+ * @since 3.7.3
+ */
+ public default GraphTraversal<S, List<List<?>>> product(final GValue<Object> values) {
+ this.asAdmin().getBytecode().addStep(GraphTraversal.Symbols.product, values);
+ return this.asAdmin().addStep(new ProductStep<>(this.asAdmin(), values));
+ }
+
+ /**
+ * When used as a modifier to {@link #addE(String)} this method specifies the traversal to use for selecting the
+ * incoming vertex of the newly added {@link Edge}.
+ *
+ * @param toVertex the vertex for selecting the incoming vertex
+ * @return the traversal with the modified {@link AddEdgeStep}
+ * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#addedge-step" target="_blank">Reference Documentation - From Step</a>
+ * @since 4.0.0
+ */
+ public default GraphTraversal<S, E> to(final GValue<Vertex> toVertex) {
+ final Step<?,?> prev = this.asAdmin().getEndStep();
+ if (!(prev instanceof FromToModulating))
+ throw new IllegalArgumentException(String.format(
+ "The to() step cannot follow %s", prev.getClass().getSimpleName()));
+
+ this.asAdmin().getBytecode().addStep(GraphTraversal.Symbols.to, toVertex);
+ ((FromToModulating) prev).addTo(__.constant(toVertex).asAdmin());
+ return this;
+ }
+
+ /**
+ * When used as a modifier to {@link #addE(String)} this method specifies the traversal to use for selecting the
+ * outgoing vertex of the newly added {@link Edge}.
+ *
+ * @param fromVertex the vertex for selecting the outgoing vertex
+ * @return the traversal with the modified {@link AddEdgeStep}
+ * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#addedge-step" target="_blank">Reference Documentation - From Step</a>
+ * @since 4.0.0
+ */
+ public default GraphTraversal<S, E> from(final GValue<Vertex> fromVertex) {
+ final Step<?,?> prev = this.asAdmin().getEndStep();
+ if (!(prev instanceof FromToModulating))
+ throw new IllegalArgumentException(String.format(
+ "The from() step cannot follow %s", prev.getClass().getSimpleName()));
+
+ this.asAdmin().getBytecode().addStep(GraphTraversal.Symbols.from, fromVertex);
+ ((FromToModulating) prev).addFrom(__.constant(fromVertex).asAdmin());
+ return this;
+ }
+
+ /**
+ * Perform the specified service call with the specified static parameters.
+ *
+ * @param service the name of the service call
+ * @param params static parameter map (no nested traversals)
+ * @return the traversal with an appended {@link CallStep}.
+ * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#call-step" target="_blank">Reference Documentation - Call Step</a>
+ * @since 4.0.0
+ */
+ default <E> GraphTraversal<S, E> call(final String service, final GValue<Map> params) {
+ this.asAdmin().getBytecode().addStep(GraphTraversal.Symbols.call, service, params);
+ final CallStep<S,E> call = new CallStep<>(this.asAdmin(), false, service, params);
+ return this.asAdmin().addStep(call);
+ }
+ /**
+ * Perform the specified service call with both static and dynamic parameters produced by the specified child
+ * traversal. These parameters will be merged at execution time per the provider implementation. Reference
+ * implementation merges dynamic into static (dynamic will overwrite static).
+ *
+ * @param service the name of the service call
+ * @param params static parameter map (no nested traversals)
+ * @param childTraversal a traversal that will produce a Map of parameters for the service call when invoked.
+ * @return the traversal with an appended {@link CallStep}.
+ * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#call-step" target="_blank">Reference Documentation - Call Step</a>
+ * @since 4.0.0
+ */
+ default <E> GraphTraversal<S, E> call(final String service, final GValue<Map> params, final Traversal<?, Map<?,?>> childTraversal) {
+ this.asAdmin().getBytecode().addStep(GraphTraversal.Symbols.call, service, params, childTraversal);
+ final CallStep<S,E> step = null == childTraversal ? new CallStep(this.asAdmin(), false, service, params) :
+ new CallStep(this.asAdmin(), false, service, params, childTraversal.asAdmin());
+ return this.asAdmin().addStep(step);
+ }
+
@Override
public default <E2> GraphTraversal.Admin<S, E2> addStep(final Step<?, E2> step) {
return (GraphTraversal.Admin<S, E2>) Traversal.Admin.super.addStep((Step) step);
@@ -2725,8 +2834,7 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
public default GraphTraversal<S, E> hasId(final Object id, final Object... otherIds) {
if (id instanceof P) {
return this.hasId((P) id);
- }
- else {
+ } else {
this.asAdmin().getBytecode().addStep(Symbols.hasId, id, otherIds);
//using ArrayList given P.within() turns all arguments into lists
@@ -2737,8 +2845,9 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
// as ids are unrolled when it's in array, they should also be unrolled when it's a list.
// this also aligns with behavior of hasId() when it's pushed down to g.V() (TINKERPOP-2863)
ids.addAll((Collection<?>) id);
- } else
+ } else {
ids.add(id);
+ }
// unrolling ids from lists works cleaner with Collection too, as otherwise they will need to
// be turned into array first
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversalSource.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversalSource.java
index 0c0670a7ca..be9ec2d44e 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversalSource.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversalSource.java
@@ -638,6 +638,36 @@ public class GraphTraversalSource implements TraversalSource {
*/
public class Admin {
+ /**
+ * Spawns a {@link GraphTraversal} starting with values produced by the specified service call with the specified
+ * static parameters.
+ *
+ * @param service the name of the service call
+ * @param params static parameter map (no nested traversals)
+ * @since 4.0.0
+ */
+ public <S> GraphTraversal<S, S> call(final String service, final GValue<Map> params) {
+ final GraphTraversalSource clone = GraphTraversalSource.this.clone();
+ clone.bytecode.addStep(GraphTraversal.Symbols.call, service, params);
+ final GraphTraversal.Admin<S, S> traversal = new DefaultGraphTraversal<>(clone);
+ return traversal.addStep(new CallStep<>(traversal, true, service, params));
+ }
+
+ /**
+ * Spawns a {@link GraphTraversal} starting with values produced by the specified service call with the specified
+ * static parameters.
+ *
+ * @param service the name of the service call
+ * @param params static parameter map (no nested traversals)
+ * @since 4.0.0
+ */
+ public <S> GraphTraversal<S, S> call(final String service, final GValue<Map> params, final Traversal<S, Map> childTraversal) {
+ final GraphTraversalSource clone = GraphTraversalSource.this.clone();
+ clone.bytecode.addStep(GraphTraversal.Symbols.call, service, params);
+ final GraphTraversal.Admin<S, S> traversal = new DefaultGraphTraversal<>(clone);
+ return traversal.addStep(new CallStep<>(traversal, true, service, params, childTraversal.asAdmin()));
+ }
+
/**
* Spawns a {@link GraphTraversal} by doing a merge (i.e. upsert) style operation for an {@link Vertex} using a
* {@code Map} as an argument. The {@code Map} represents search criteria and will match each of the supplied
@@ -645,7 +675,7 @@ public class GraphTraversalSource implements TraversalSource {
* made it will use that search criteria to create the new {@link Vertex}.
*
* @param searchCreate This {@code Map} can have a key of {@link T} or a {@code String}.
- * @since 3.6.0
+ * @since 4.0.0
*/
public GraphTraversal<Vertex, Vertex> mergeV(final GValue<Map<Object, Object>> searchCreate) {
final GraphTraversalSource clone = GraphTraversalSource.this.clone();
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/GValue.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/GValue.java
index e05a9e91f4..41caaea1a2 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/GValue.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/GValue.java
@@ -79,6 +79,13 @@ public class GValue<V> implements Cloneable, Serializable {
return this.type;
}
+ /**
+ * Determines if the value held is of a {@code null} value.
+ */
+ public boolean isNull() {
+ return this.value == null;
+ }
+
/**
* Gets the value.
*/
@@ -96,7 +103,7 @@ public class GValue<V> implements Cloneable, Serializable {
public boolean equals(final Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
- GValue<?> gValue = (GValue<?>) o;
+ final GValue<?> gValue = (GValue<?>) o;
return Objects.equals(name, gValue.name) && type == gValue.type && Objects.equals(value, gValue.value);
}
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AddEdgeStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AddEdgeStep.java
index 9dfa4ce754..82c7f3893b 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AddEdgeStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AddEdgeStep.java
@@ -21,6 +21,7 @@ package org.apache.tinkerpop.gremlin.process.traversal.step.map;
import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
import org.apache.tinkerpop.gremlin.process.traversal.step.FromToModulating;
+import org.apache.tinkerpop.gremlin.process.traversal.step.GType;
import org.apache.tinkerpop.gremlin.process.traversal.step.GValue;
import org.apache.tinkerpop.gremlin.process.traversal.step.Scoping;
import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent;
@@ -113,7 +114,7 @@ public class AddEdgeStep<S> extends ScalarMapStep<S, Edge>
edgeLabel, e.getMessage()));
}
- if (!(theTo instanceof Vertex))
+ if (!(theTo instanceof Vertex) && (theTo instanceof GValue && ((GValue) theTo).getType() != GType.VERTEX))
throw new IllegalStateException(String.format(
"The value given to addE(%s).to() must resolve to a Vertex but %s was specified instead", edgeLabel,
null == theTo ? "null" : theTo.getClass().getSimpleName()));
@@ -127,13 +128,13 @@ public class AddEdgeStep<S> extends ScalarMapStep<S, Edge>
edgeLabel, e.getMessage()));
}
- if (!(theFrom instanceof Vertex))
+ if (!(theFrom instanceof Vertex) && (theFrom instanceof GValue && ((GValue) theTo).getType() != GType.VERTEX))
throw new IllegalStateException(String.format(
"The value given to addE(%s).to() must resolve to a Vertex but %s was specified instead", edgeLabel,
null == theFrom ? "null" : theFrom.getClass().getSimpleName()));
- Vertex toVertex = (Vertex) theTo;
- Vertex fromVertex = (Vertex) theFrom;
+ Vertex toVertex = theTo instanceof Vertex ? (Vertex) theTo : ((GValue<Vertex>) theTo).get();
+ Vertex fromVertex = theFrom instanceof Vertex ? (Vertex) theFrom : ((GValue<Vertex>) theFrom).get();
if (toVertex instanceof Attachable)
toVertex = ((Attachable<Vertex>) toVertex)
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/CallStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/CallStep.java
index 2435be373c..3dd99d1703 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/CallStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/CallStep.java
@@ -22,6 +22,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.Step;
import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
import org.apache.tinkerpop.gremlin.process.traversal.step.Configuring;
+import org.apache.tinkerpop.gremlin.process.traversal.step.GValue;
import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent;
import org.apache.tinkerpop.gremlin.process.traversal.step.util.AbstractStep;
import org.apache.tinkerpop.gremlin.process.traversal.step.util.Parameters;
@@ -62,7 +63,7 @@ public final class CallStep<S, E> extends AbstractStep<S, E> implements Traversa
private ServiceCallContext ctx;
private String serviceName;
private Service<S, E> service;
- private Map staticParams;
+ private GValue<Map> staticParams;
private Traversal.Admin<S,Map> mapTraversal;
private Parameters parameters;
@@ -74,20 +75,29 @@ public final class CallStep<S, E> extends AbstractStep<S, E> implements Traversa
}
public CallStep(final Traversal.Admin traversal, final boolean isStart, final String service) {
- this(traversal, isStart, service, null);
+ this(traversal, isStart, service, (Map) null);
}
public CallStep(final Traversal.Admin traversal, final boolean isStart, final String service, final Map staticParams) {
+ this(traversal, isStart, service, GValue.ofMap(staticParams));
+ }
+
+ public CallStep(final Traversal.Admin traversal, final boolean isStart, final String service, final GValue<Map> staticParams) {
this(traversal, isStart, service, staticParams, null);
}
public CallStep(final Traversal.Admin traversal, final boolean isStart, final String service, final Map staticParams,
final Traversal.Admin<S, Map> mapTraversal) {
+ this(traversal, isStart, service, GValue.ofMap(staticParams), mapTraversal);
+ }
+
+ public CallStep(final Traversal.Admin traversal, final boolean isStart, final String service, final GValue<Map> staticParams,
+ final Traversal.Admin<S, Map> mapTraversal) {
super(traversal);
this.isStart = isStart;
this.serviceName = service;
- this.staticParams = staticParams == null ? new LinkedHashMap() : staticParams;
+ this.staticParams = staticParams == null || staticParams.isNull() ? GValue.ofMap(staticParams.getName(), new LinkedHashMap()) : staticParams;
this.mapTraversal = mapTraversal == null ? null : integrateChild(mapTraversal);
this.parameters = new Parameters();
this.ctx = new ServiceCallContext(traversal, this);
@@ -95,13 +105,17 @@ public final class CallStep<S, E> extends AbstractStep<S, E> implements Traversa
protected Service<S, E> service() {
// throws exception for unrecognized service
- return service != null ? service : (service = getServiceRegistry().get(serviceName, isStart, staticParams));
+ return service != null ? service : (service = getServiceRegistry().get(serviceName, isStart, staticParams.get()));
}
public String getServiceName() {
return serviceName;
}
+ public GValue<Map> getStaticParams() {
+ return staticParams;
+ }
+
@Override
protected Traverser.Admin<E> processNextStart() {
if (isStart && first) {
@@ -199,7 +213,7 @@ public final class CallStep<S, E> extends AbstractStep<S, E> implements Traversa
public Map getMergedParams() {
if (mapTraversal == null && parameters.isEmpty()) {
// static params only
- return Collections.unmodifiableMap(this.staticParams);
+ return Collections.unmodifiableMap(this.staticParams.get());
}
return getMergedParams(new DummyTraverser(this.traversal.getTraverserGenerator()));
@@ -208,11 +222,11 @@ public final class CallStep<S, E> extends AbstractStep<S, E> implements Traversa
protected Map getMergedParams(final Traverser.Admin<S> traverser) {
if (mapTraversal == null && parameters.isEmpty()) {
// static params only
- return Collections.unmodifiableMap(this.staticParams);
+ return Collections.unmodifiableMap(this.staticParams.get());
}
// merge dynamic with static params
- final Map params = new LinkedHashMap(this.staticParams);
+ final Map params = new LinkedHashMap(this.staticParams.get());
if (mapTraversal != null) params.putAll(TraversalUtil.apply(traverser, mapTraversal));
final Object[] kvs = this.parameters.getKeyValues(traverser);
for (int i = 0; i < kvs.length; i += 2) {
@@ -225,7 +239,7 @@ public final class CallStep<S, E> extends AbstractStep<S, E> implements Traversa
protected Map getMergedParams(final TraverserSet<S> traverserSet) {
if (mapTraversal == null && parameters.isEmpty()) {
// static params only
- return Collections.unmodifiableMap(this.staticParams);
+ return Collections.unmodifiableMap(this.staticParams.get());
}
/*
@@ -302,7 +316,7 @@ public final class CallStep<S, E> extends AbstractStep<S, E> implements Traversa
public String toString() {
final ArrayList args = new ArrayList();
args.add(serviceName);
- if (!staticParams.isEmpty())
+ if (!staticParams.get().isEmpty())
args.add(staticParams);
if (mapTraversal != null)
args.add(mapTraversal);
@@ -314,8 +328,8 @@ public final class CallStep<S, E> extends AbstractStep<S, E> implements Traversa
@Override
public int hashCode() {
int hashCode = super.hashCode() ^ Objects.hashCode(this.serviceName);
- if (!staticParams.isEmpty())
- hashCode ^= staticParams.hashCode();
+ if (!staticParams.get().isEmpty())
+ hashCode ^= staticParams.get().hashCode();
if (mapTraversal != null)
hashCode ^= mapTraversal.hashCode();
if (!parameters.isEmpty())
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ConstantStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ConstantStep.java
index 245a443e5a..2145f7e966 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ConstantStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ConstantStep.java
@@ -33,7 +33,7 @@ public class ConstantStep<S, E> extends ScalarMapStep<S, E> {
private final GValue<E> constant;
public ConstantStep(final Traversal.Admin traversal, final E constant) {
- this(traversal, GValue.of(constant));
+ this(traversal, constant instanceof GValue ? (GValue) constant : GValue.of(constant));
}
public ConstantStep(final Traversal.Admin traversal, final GValue<E> constant) {
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/DifferenceStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/DifferenceStep.java
index 1317f931c4..87f44f8639 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/DifferenceStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/DifferenceStep.java
@@ -20,6 +20,7 @@ package org.apache.tinkerpop.gremlin.process.traversal.step.map;
import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
+import org.apache.tinkerpop.gremlin.process.traversal.step.GValue;
import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent;
import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
import org.apache.tinkerpop.gremlin.process.traversal.util.ListFunction;
@@ -36,24 +37,33 @@ import java.util.Set;
*/
public final class DifferenceStep<S, E> extends ScalarMapStep<S, Set<?>> implements TraversalParent, ListFunction {
private Traversal.Admin<S, E> valueTraversal;
- private Object parameterItems;
+ private GValue<Object> parameterItems;
+
public DifferenceStep(final Traversal.Admin traversal, final Object values) {
super(traversal);
if (values instanceof Traversal) {
valueTraversal = integrateChild(((Traversal<S, E>) values).asAdmin());
} else {
- parameterItems = values;
+ parameterItems = values instanceof GValue ? (GValue<Object>) values : GValue.of(values);
}
}
+ public Traversal.Admin<S,E> getValueTraversal() {
+ return this.valueTraversal;
+ }
+
+ public GValue<Object> getParameterItems() {
+ return parameterItems;
+ }
+
@Override
public String getStepName() { return "difference"; }
@Override
protected Set<?> map(Traverser.Admin<S> traverser) {
final Collection setA = convertTraverserToCollection(traverser);
- final Collection setB = (null != valueTraversal) ? convertTraversalToCollection(traverser, valueTraversal) : convertArgumentToCollection(parameterItems);
+ final Collection setB = (null != valueTraversal) ? convertTraversalToCollection(traverser, valueTraversal) : convertArgumentToCollection(parameterItems.get());
final Set differenceSet = new HashSet();
for (Object element : setA) {
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/DisjunctStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/DisjunctStep.java
index 60eebf0457..fc890dd2a2 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/DisjunctStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/DisjunctStep.java
@@ -20,6 +20,7 @@ package org.apache.tinkerpop.gremlin.process.traversal.step.map;
import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
+import org.apache.tinkerpop.gremlin.process.traversal.step.GValue;
import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent;
import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
import org.apache.tinkerpop.gremlin.process.traversal.util.ListFunction;
@@ -35,14 +36,15 @@ import java.util.Set;
*/
public final class DisjunctStep<S, E> extends ScalarMapStep<S, Set<?>> implements TraversalParent, ListFunction {
private Traversal.Admin<S, E> valueTraversal;
- private Object parameterItems;
+ private GValue<Object> parameterItems;
+
public DisjunctStep(final Traversal.Admin traversal, final Object values) {
super(traversal);
if (values instanceof Traversal) {
valueTraversal = integrateChild(((Traversal<S, E>) values).asAdmin());
} else {
- parameterItems = values;
+ parameterItems = values instanceof GValue ? (GValue<Object>) values : GValue.of(values);
}
}
@@ -50,8 +52,8 @@ public final class DisjunctStep<S, E> extends ScalarMapStep<S, Set<?>> implement
return this.valueTraversal;
}
- public Object getParameterItems() {
- return this.parameterItems;
+ public GValue<Object> getParameterItems() {
+ return parameterItems;
}
@Override
@@ -60,7 +62,7 @@ public final class DisjunctStep<S, E> extends ScalarMapStep<S, Set<?>> implement
@Override
protected Set<?> map(Traverser.Admin<S> traverser) {
final Set setA = convertTraverserToSet(traverser);
- final Set setB = (null != valueTraversal) ? convertTraversalToSet(traverser, this.valueTraversal) : convertArgumentToSet(parameterItems);
+ final Set setB = (null != valueTraversal) ? convertTraversalToSet(traverser, this.valueTraversal) : convertArgumentToSet(parameterItems.get());
final Set disjunctSet = new HashSet();
if (setA.size() == 0) {
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ProductStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ProductStep.java
index b14c02ba92..4842a313bb 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ProductStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ProductStep.java
@@ -20,6 +20,7 @@ package org.apache.tinkerpop.gremlin.process.traversal.step.map;
import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
+import org.apache.tinkerpop.gremlin.process.traversal.step.GValue;
import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent;
import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
import org.apache.tinkerpop.gremlin.process.traversal.util.ListFunction;
@@ -36,7 +37,7 @@ import java.util.Set;
*/
public final class ProductStep<S, E> extends ScalarMapStep<S, List<List<?>>> implements TraversalParent, ListFunction {
private Traversal.Admin<S, E> valueTraversal;
- private Object parameterItems;
+ private GValue<Object> parameterItems;
public ProductStep(final Traversal.Admin traversal, final Object values) {
super(traversal);
@@ -44,17 +45,25 @@ public final class ProductStep<S, E> extends ScalarMapStep<S, List<List<?>>> imp
if (values instanceof Traversal) {
valueTraversal = integrateChild(((Traversal<S, E>) values).asAdmin());
} else {
- parameterItems = values;
+ parameterItems = values instanceof GValue ? (GValue<Object>) values : GValue.of(values);
}
}
+ public Traversal.Admin<S,E> getValueTraversal() {
+ return this.valueTraversal;
+ }
+
+ public GValue<Object> getParameterItems() {
+ return parameterItems;
+ }
+
@Override
public String getStepName() { return "product"; }
@Override
protected List<List<?>> map(Traverser.Admin<S> traverser) {
final Collection listA = convertTraverserToCollection(traverser);
- final Collection listB = (null != valueTraversal) ? convertTraversalToCollection(traverser, valueTraversal) : convertArgumentToCollection(parameterItems);
+ final Collection listB = (null != valueTraversal) ? convertTraversalToCollection(traverser, valueTraversal) : convertArgumentToCollection(parameterItems.get());
final List elements = new ArrayList();
for (Object elementInA : listA) {
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/TraversalMergeStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/TraversalMergeStep.java
index 74d5c185de..eb82dbf381 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/TraversalMergeStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/TraversalMergeStep.java
@@ -85,9 +85,10 @@ public final class TraversalMergeStep<S, E> extends ScalarMapStep<S, E> implemen
} else {
final Collection listA = convertTraverserToCollection(traverser);
- if (parameterItems.get() instanceof Map) {
+ if (parameterItems != null && parameterItems.get() instanceof Map) {
throw new IllegalArgumentException(getStepName() + " step type mismatch: expected argument to be Iterable but got Map");
}
+
final Collection listB =
(null != valueTraversal)
? convertTraversalToCollection(traverser, valueTraversal)
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/InjectStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/InjectStep.java
index ab57c05ce5..cc3a970f93 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/InjectStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/InjectStep.java
@@ -39,7 +39,7 @@ public final class InjectStep<S> extends StartStep<S> {
@Override
public InjectStep<S> clone() {
final InjectStep<S> clone = (InjectStep<S>) super.clone();
- clone.start = new ArrayIterator<>(clone.injections);
+ clone.start = new ArrayIterator<>(resolveToValues(clone.injections));
return clone;
}
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/SideEffectStrategy.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/SideEffectStrategy.java
index ce794b8b6a..9b309dba3f 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/SideEffectStrategy.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/SideEffectStrategy.java
@@ -22,6 +22,7 @@ package org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration;
import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategies;
import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.step.GValue;
import org.apache.tinkerpop.gremlin.process.traversal.step.util.EmptyStep;
import org.apache.tinkerpop.gremlin.process.traversal.strategy.AbstractTraversalStrategy;
import org.apache.tinkerpop.gremlin.util.function.ConstantSupplier;
@@ -60,7 +61,11 @@ public final class SideEffectStrategy extends AbstractTraversalStrategy<Traversa
strategy = cloneStrategy;
traversalStrategies.addStrategies(strategy);
}
- strategy.sideEffects.add(new Triplet<>(key, value instanceof Supplier ? (Supplier) value : new ConstantSupplier<>(value), reducer));
+
+ // don't want the GValue to leak beyond strategy application or else the Supplier will start producing it
+ // during execution
+ final ConstantSupplier initialValue = value instanceof GValue ? new ConstantSupplier<>(((GValue) value).get()) : new ConstantSupplier<>(value);
+ strategy.sideEffects.add(new Triplet<>(key, value instanceof Supplier ? (Supplier) value : initialValue, reducer));
}
public boolean contains(final String sideEffectKey) {
diff --git a/gremlin-language/src/main/antlr4/Gremlin.g4 b/gremlin-language/src/main/antlr4/Gremlin.g4
index 57bfcca445..5775c27cbb 100644
--- a/gremlin-language/src/main/antlr4/Gremlin.g4
+++ b/gremlin-language/src/main/antlr4/Gremlin.g4
@@ -487,7 +487,7 @@ traversalMethod_fold
;
traversalMethod_from
- : 'from' LPAREN stringArgument RPAREN #traversalMethod_from_String
+ : 'from' LPAREN stringLiteral RPAREN #traversalMethod_from_String
| 'from' LPAREN structureVertexArgument RPAREN #traversalMethod_from_Vertex
| 'from' LPAREN nestedTraversal RPAREN #traversalMethod_from_Traversal
;
@@ -644,7 +644,6 @@ traversalMethod_option
: 'option' LPAREN traversalPredicate COMMA nestedTraversal RPAREN #traversalMethod_option_Predicate_Traversal
| 'option' LPAREN traversalMergeArgument COMMA genericLiteralMapNullableArgument RPAREN #traversalMethod_option_Merge_Map
| 'option' LPAREN traversalMergeArgument COMMA genericLiteralMapNullableArgument COMMA traversalCardinality RPAREN #traversalMethod_option_Merge_Map_Cardinality
- | 'option' LPAREN traversalMergeArgument COMMA nestedTraversal RPAREN #traversalMethod_option_Merge_Traversal
| 'option' LPAREN genericLiteralArgument COMMA nestedTraversal RPAREN #traversalMethod_option_Object_Traversal
| 'option' LPAREN nestedTraversal RPAREN #traversalMethod_option_Traversal
;
@@ -808,8 +807,8 @@ traversalMethod_times
;
traversalMethod_to
- : 'to' LPAREN traversalDirectionArgument (COMMA stringLiteralVarargs)? RPAREN #traversalMethod_to_Direction_String
- | 'to' LPAREN stringArgument RPAREN #traversalMethod_to_String
+ : 'to' LPAREN traversalDirection (COMMA stringLiteralVarargs)? RPAREN #traversalMethod_to_Direction_String
+ | 'to' LPAREN stringLiteral RPAREN #traversalMethod_to_String
| 'to' LPAREN structureVertexArgument RPAREN #traversalMethod_to_Vertex
| 'to' LPAREN nestedTraversal RPAREN #traversalMethod_to_Traversal
;
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/features/StepDefinition.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/features/StepDefinition.java
index 380313e29a..e31b3ff2d4 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/features/StepDefinition.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/features/StepDefinition.java
@@ -75,6 +75,7 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
@@ -183,13 +184,13 @@ public final class StepDefinition {
}
}));
- add(Pair.with(Pattern.compile("l\\[\\]"), s -> Collections.emptyList()));
+ add(Pair.with(Pattern.compile("l\\[\\]"), s -> new ArrayList<>()));
add(Pair.with(Pattern.compile("l\\[(.*)\\]"), s -> {
final String[] items = s.split(",");
return Stream.of(items).map(String::trim).map(x -> convertToObject(x)).collect(Collectors.toList());
}));
- add(Pair.with(Pattern.compile("s\\[\\]"), s -> Collections.emptySet()));
+ add(Pair.with(Pattern.compile("s\\[\\]"), s -> new HashSet<>()));
add(Pair.with(Pattern.compile("s\\[(.*)\\]"), s -> {
final String[] items = s.split(",");
return Stream.of(items).map(String::trim).map(x -> convertToObject(x)).collect(Collectors.toSet());
@@ -235,7 +236,7 @@ public final class StepDefinition {
add(Pair.with(Pattern.compile("e\\[(.+)\\]"), s -> getEdge(g, s)));
add(Pair.with(Pattern.compile("t\\[(.*)\\]"), T::valueOf));
- add(Pair.with(Pattern.compile("D\\[(.*)\\]"), Direction::valueOf));
+ add(Pair.with(Pattern.compile("D\\[(.*)\\]"), StepDefinition::getDirection));
add(Pair.with(Pattern.compile("M\\[(.*)\\]"), Merge::valueOf));
add(Pair.with(Pattern.compile("c\\[(.*)\\]"), s -> {
@@ -382,17 +383,11 @@ public final class StepDefinition {
}
@Then("the graph should return {int} for count of {string}")
- public void theGraphShouldReturnForCountOf(final Integer count, final String gremlin) {
+ public void theGraphShouldReturnForCountOf(final Integer count, final String rawGremlin) {
assertThatNoErrorWasThrown();
- assertEquals(count.longValue(), ((GraphTraversal) parseGremlin(applyParameters(gremlin))).count().next());
- }
-
- @Then("debug the graph should return {int} for count of {string}")
- public void debugTheGraphShouldReturnForCountOf(final Integer count, final String gremlin) {
- assertThatNoErrorWasThrown();
-
- assertEquals(count.longValue(), ((GraphTraversal) parseGremlin(applyParameters(gremlin))).count().next());
+ final String gremlin = world.useParametersLiterally() ? applyParameters(rawGremlin) : rawGremlin;
+ assertEquals(count.longValue(), ((GraphTraversal) parseGremlin(gremlin)).count().next());
}
@Then("the result should be empty")
@@ -604,6 +599,12 @@ public final class StepDefinition {
return docString.replace(relPath, escapeJava(absPath));
}
+ private static Direction getDirection(final String direction) {
+ if (direction.equals("from")) return Direction.OUT;
+ if (direction.equals("to")) return Direction.IN;
+ return Direction.valueOf(direction);
+ }
+
/**
* TinkerPop version of Hamcrest's {code containsInAnyOrder} that can use our custom assertions for {@link Path}.
*/