You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tinkerpop.apache.org by co...@apache.org on 2024/11/19 03:33:14 UTC
(tinkerpop) 04/19: wip
This is an automated email from the ASF dual-hosted git repository.
colegreer pushed a commit to branch cole-gvalue
in repository https://gitbox.apache.org/repos/asf/tinkerpop.git
commit 7da00f720a81a35baf190a5b111cffc3d273dc15
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/sideEffect/InjectStep.java | 2 +-
.../strategy/decoration/SideEffectStrategy.java | 7 +-
gremlin-language/src/main/antlr4/Gremlin.g4 | 7 +-
.../tinkerpop/gremlin/features/StepDefinition.java | 25 ++---
19 files changed, 331 insertions(+), 123 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 4e5a35a595..da60cdcd7e 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/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}.
*/