This is an automated email from the ASF dual-hosted git repository.

spmallette pushed a commit to branch gvalue-3.7
in repository https://gitbox.apache.org/repos/asf/tinkerpop.git


The following commit(s) were added to refs/heads/gvalue-3.7 by this push:
     new f70d0d5f26 Brought back some changes from gvalue branch bound to master
f70d0d5f26 is described below

commit f70d0d5f264160f03aa270983ce30fb5252f9070
Author: Stephen Mallette <[email protected]>
AuthorDate: Thu Aug 15 09:32:41 2024 -0400

    Brought back some changes from gvalue branch bound to master
---
 .../gremlin/process/traversal/Operator.java        |  2 +-
 .../tinkerpop/gremlin/process/traversal/P.java     | 20 ++++++-
 .../traversal/dsl/graph/GraphTraversal.java        | 64 ++++++++++++++++++++++
 .../traversal/dsl/graph/GraphTraversalSource.java  | 43 +++++++++++++++
 .../gremlin/process/traversal/step/GType.java      | 18 +++++-
 .../gremlin/process/traversal/step/GValue.java     | 20 +++++--
 .../traversal/step/sideEffect/InjectStep.java      | 18 +++---
 .../process/traversal/step/util/AbstractStep.java  | 43 +++++++++++++++
 .../process/traversal/step/util/HasContainer.java  |  6 +-
 .../strategy/decoration/SideEffectStrategy.java    |  7 ++-
 .../gremlin/process/traversal/step/GValueTest.java | 34 ++++++------
 11 files changed, 236 insertions(+), 39 deletions(-)

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 b4d3cb23a0..3100084294 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,7 +186,7 @@ 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)
+            else if (a instanceof Collection && b instanceof Collection)
                 ((Collection<?>) a).addAll((Collection) b);
             else
                 throw new IllegalArgumentException(String.format("Objects must 
be both of Map or Collection: a=%s b=%s",
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 3d9cd3e088..c49eadaf7d 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
@@ -458,6 +458,30 @@ public interface GraphTraversal<S, E> extends Traversal<S, 
E> {
             return TraversalHelper.addHasContainer(this.asAdmin(), new 
HasContainer(T.label.getAccessor(), labels.length == 1 ? P.eq(labels[0]) : 
P.within(labels)));
         }
 
+        /**
+         * This is a step modulator to a {@link TraversalOptionParent} like 
{@code choose()} or {@code mergeV()} where the
+         * provided argument associated to the {@code token} is applied 
according to the semantics of the step. Please see
+         * the documentation of such steps to understand the usage context.
+         *
+         * @param token       the token that would trigger this option which 
may be a {@link Pick}, {@link Merge},
+         *                    a {@link Traversal}, {@link Predicate}, or 
object depending on the step being modulated.
+         * @param traversalOption the option as a traversal
+         * @return the traversal with the modulated step
+         * @see <a 
href="http://tinkerpop.apache.org/docs/${project.version}/reference/#choose-step";
 target="_blank">Reference Documentation - Choose Step</a>
+         * @see <a 
href="http://tinkerpop.apache.org/docs/${project.version}/reference/#mergev-step";
 target="_blank">Reference Documentation - MergeV Step</a>
+         * @see <a 
href="http://tinkerpop.apache.org/docs/${project.version}/reference/#mergee-step";
 target="_blank">Reference Documentation - MergeE Step</a>
+         * @since 3.0.0-incubating
+         */
+        public default <M, E2> GraphTraversal<S, E> option(final GValue<M> 
token, final Traversal<?, E2> traversalOption) {
+            
this.asAdmin().getBytecode().addStep(GraphTraversal.Symbols.option, token, 
traversalOption);
+
+            // handle null similar to how option() with Map handles it, 
otherwise we get a NPE if this one gets used
+            final Traversal.Admin<E,E2> t = null == traversalOption ?
+                    new ConstantTraversal<>(null) : (Traversal.Admin<E, E2>) 
traversalOption.asAdmin();
+            ((TraversalOptionParent<M, E, E2>) 
this.asAdmin().getEndStep()).addChildOption(token.get(), t);
+            return this;
+        }
+
         /**
          * This is a step modulator to a {@link TraversalOptionParent} like 
{@code choose()} or {@code mergeV()} where the
          * provided argument associated to the {@code token} is applied 
according to the semantics of the step. Please see
@@ -501,6 +525,46 @@ public interface GraphTraversal<S, E> extends Traversal<S, 
E> {
             return this;
         }
 
+        /**
+         * When used as a modifier to {@link #addE(String)} this method 
specifies the traversal to use for selecting the
+         * incoming vertex of the newly added {@link Edge}.
+         *
+         * @param toVertex the vertex for selecting the incoming vertex
+         * @return the traversal with the modified {@link AddEdgeStep}
+         * @see <a 
href="http://tinkerpop.apache.org/docs/${project.version}/reference/#addedge-step";
 target="_blank">Reference Documentation - From Step</a>
+         * @since 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;
+        }
+
         @Override
         public default <E2> GraphTraversal.Admin<S, E2> addStep(final Step<?, 
E2> step) {
             return (GraphTraversal.Admin<S, E2>) 
Traversal.Admin.super.addStep((Step) step);
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 dc15306fce..961ba8c59c 100644
--- 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversalSource.java
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversalSource.java
@@ -27,6 +27,7 @@ import 
org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.TraversalSource;
 import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategies;
 import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.step.GValue;
 import org.apache.tinkerpop.gremlin.process.traversal.step.branch.UnionStep;
 import 
org.apache.tinkerpop.gremlin.process.traversal.step.map.AddEdgeStartStep;
 import 
org.apache.tinkerpop.gremlin.process.traversal.step.map.AddVertexStartStep;
@@ -68,6 +69,7 @@ public class GraphTraversalSource implements TraversalSource {
     protected final Graph graph;
     protected TraversalStrategies strategies;
     protected Bytecode bytecode = new Bytecode();
+    protected Admin admin;
 
     ////////////////
 
@@ -100,6 +102,12 @@ public class GraphTraversalSource implements 
TraversalSource {
         this.strategies.addStrategies(new RemoteStrategy(connection));
     }
 
+    public GraphTraversalSource.Admin asAdmin() {
+        if (null == this.admin)
+            this.admin = new Admin();
+        return this.admin;
+    }
+
     @Override
     public Optional<Class<?>> getAnonymousTraversalClass() {
         return Optional.of(__.class);
@@ -624,4 +632,39 @@ public class GraphTraversalSource implements 
TraversalSource {
         return StringFactory.traversalSourceString(this);
     }
 
+    /**
+     * This class masks spawn steps that are more reserved for advanced usage.
+     */
+    public class Admin {
+
+        /**
+         * Spawns a {@link GraphTraversal} by doing a merge (i.e. upsert) 
style operation for an {@link Vertex} using a
+         * {@code Map} as an argument. The {@code Map} represents search 
criteria and will match each of the supplied
+         * key/value pairs where the keys may be {@code String} property 
values or a value of {@link T}. If a match is not
+         * made it will use that search criteria to create the new {@link 
Vertex}.
+         *
+         * @param searchCreate This {@code Map} can have a key of {@link T} or 
a {@code String}.
+         * @since 4.0.0
+         */
+        public GraphTraversal<Vertex, Vertex> mergeV(final GValue<Map<Object, 
Object>> searchCreate) {
+            final GraphTraversalSource clone = 
GraphTraversalSource.this.clone();
+            clone.bytecode.addStep(GraphTraversal.Symbols.mergeV, 
searchCreate);
+            final GraphTraversal.Admin<Vertex, Vertex> traversal = new 
DefaultGraphTraversal<>(clone);
+            return traversal.addStep(new MergeVertexStep(traversal, true, 
searchCreate));
+        }
+
+        /**
+         * Spawns a {@link GraphTraversal} by doing a merge (i.e. upsert) 
style operation for an {@link Edge} using a
+         * {@code Map} as an argument.
+         *
+         * @param searchCreate This {@code Map} can have a key of {@link T} 
{@link Direction} or a {@code String}.
+         * @since 4.0.0
+         */
+        public GraphTraversal<Edge, Edge> mergeE(final GValue<Map<?, Object>> 
searchCreate) {
+            final GraphTraversalSource clone = 
GraphTraversalSource.this.clone();
+            clone.bytecode.addStep(GraphTraversal.Symbols.mergeE, 
searchCreate);
+            final GraphTraversal.Admin<Edge, Edge> traversal = new 
DefaultGraphTraversal<>(clone);
+            return traversal.addStep(new MergeEdgeStep(traversal, true, 
searchCreate));
+        }
+    }
 }
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/GType.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/GType.java
index 89a8b79098..23dd8be5f2 100644
--- 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/GType.java
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/GType.java
@@ -52,12 +52,26 @@ public enum GType {
     GType() {}
 
     /**
-     * Returns true if the type is a number.
+     * Returns {@code true} if the type is a number.
      */
     public boolean isNumeric() {
         return this == INTEGER || this == DOUBLE || this == LONG || this == 
BIG_INTEGER || this == BIG_DECIMAL;
     }
 
+    /**
+     * Returns {@code true} if the type is a collection.v
+     */
+    public boolean isCollection() {
+        return this == LIST || this == SET;
+    }
+
+    /**
+     * Returns {@code true} if the type is an element.
+     */
+    public boolean isElement() {
+        return this == VERTEX || this == EDGE;
+    }
+
     /**
      * Convert an object to a matching {@link GType} and if not matched return 
{@link GType#UNKNOWN}.
      */
@@ -78,4 +92,4 @@ public enum GType {
         else if (object instanceof BigDecimal) return BIG_DECIMAL;
         else return UNKNOWN;
     }
-}
+}
\ No newline at end of file
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 4de2ca1f8e..a7271c3ad9 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
@@ -66,8 +66,8 @@ public class GValue<V> implements Cloneable, Serializable {
     /**
      * Gets the name of the variable if it was defined as such and returns 
empty if the value was a literal.
      */
-    public Optional<String> getName() {
-        return Optional.ofNullable(this.name);
+    public String getName() {
+        return this.name;
     }
 
     /**
@@ -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);
     }
 
@@ -123,6 +130,7 @@ public class GValue<V> implements Cloneable, Serializable {
     public static <V> GValue<V> of(final String name, final V value) {
         return new GValue<>(name, GType.getType(value), value);
     }
+
     /**
      * Create a new {@code GValue} for a string value.
      */
@@ -238,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);
     }
 
@@ -318,4 +326,4 @@ public class GValue<V> implements Cloneable, Serializable {
     public static GValue<Property> ofProperty(final String name, final 
Property value) {
         return new GValue<>(name, GType.PROPERTY, value);
     }
-}
+}
\ No newline at end of file
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/InjectStep.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/InjectStep.java
index 0502f18541..e22bbaa382 100644
--- 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/InjectStep.java
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/InjectStep.java
@@ -19,6 +19,7 @@
 package org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect;
 
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
+import org.apache.tinkerpop.gremlin.process.traversal.step.GValue;
 import org.apache.tinkerpop.gremlin.util.iterator.ArrayIterator;
 
 /**
@@ -26,29 +27,32 @@ import 
org.apache.tinkerpop.gremlin.util.iterator.ArrayIterator;
  */
 public final class InjectStep<S> extends StartStep<S> {
 
-    private final S[] injections;
+    private final GValue<S>[] injections;
 
     @SafeVarargs
     public InjectStep(final Traversal.Admin traversal, final S... injections) {
         super(traversal);
-        this.injections = injections;
-        this.start = new ArrayIterator<>(this.injections);
+        this.injections = convertToGValues(injections);
+        this.start = new ArrayIterator<>(resolveToValues(this.injections));
     }
 
     @Override
     public InjectStep<S> clone() {
         final InjectStep<S> clone = (InjectStep<S>) super.clone();
-        clone.start = new ArrayIterator<>(clone.injections);
+        clone.start = new ArrayIterator<>(resolveToValues(clone.injections));
         return clone;
     }
 
     @Override
     public void reset() {
         super.reset();
-        this.start = new ArrayIterator<>(this.injections);
+        this.start = new ArrayIterator<>(resolveToValues(this.injections));
     }
 
-    public S[] getInjections() {
+    /**
+     * Get the injections of the step.
+     */
+    public GValue<S>[] getInjections() {
         return this.injections;
     }
-}
+}
\ No newline at end of file
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/AbstractStep.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/AbstractStep.java
index d4545ead5c..94c5866b14 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
@@ -21,6 +21,7 @@ package 
org.apache.tinkerpop.gremlin.process.traversal.step.util;
 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.GValue;
 import 
org.apache.tinkerpop.gremlin.process.traversal.traverser.util.EmptyTraverser;
 import 
org.apache.tinkerpop.gremlin.process.traversal.traverser.util.TraverserSet;
 import org.apache.tinkerpop.gremlin.process.traversal.util.EmptyTraversal;
@@ -30,9 +31,11 @@ import 
org.apache.tinkerpop.gremlin.structure.util.StringFactory;
 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;
+import java.util.stream.Stream;
 
 /**
  * @author Marko A. Rodriguez (http://markorodriguez.com)
@@ -229,4 +232,44 @@ public abstract class AbstractStep<S, E> implements 
Step<S, E> {
         return traverser;
     }
 
+    /**
+     * The elements in object array argument are examined to see if they are 
{@link GValue} objects. If they are, they
+     * are preserved as is. If they are not then they are wrapped in a {@link 
GValue} object.
+     */
+    protected static <T> GValue<T>[] convertToGValues(final Object[] args) {
+        return Stream.of(args).map(id -> {
+            if (id instanceof GValue)
+                return (GValue<?>) id;
+            else
+                return GValue.of(id);
+        }).toArray(GValue[]::new);
+    }
+
+    /**
+     * 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.
+     */
+    protected Object[] resolveToValues(final GValue<?>[] gvalues) {
+        final Object[] newIds = new Object[gvalues.length];
+        for (int i = 0; i < gvalues.length; i++) {
+            newIds[i] = gvalues[i].get();
+        }
+        return newIds;
+    }
 }
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..d62c366a4c 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,6 +19,8 @@
 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.process.traversal.step.GValue;
 import org.apache.tinkerpop.gremlin.structure.Element;
 import org.apache.tinkerpop.gremlin.structure.Property;
 import org.apache.tinkerpop.gremlin.structure.T;
@@ -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/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/SideEffectStrategy.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/SideEffectStrategy.java
index ce794b8b6a..9b309dba3f 100644
--- 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/SideEffectStrategy.java
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/SideEffectStrategy.java
@@ -22,6 +22,7 @@ package 
org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration;
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategies;
 import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.step.GValue;
 import org.apache.tinkerpop.gremlin.process.traversal.step.util.EmptyStep;
 import 
org.apache.tinkerpop.gremlin.process.traversal.strategy.AbstractTraversalStrategy;
 import org.apache.tinkerpop.gremlin.util.function.ConstantSupplier;
@@ -60,7 +61,11 @@ public final class SideEffectStrategy extends 
AbstractTraversalStrategy<Traversa
             strategy = cloneStrategy;
             traversalStrategies.addStrategies(strategy);
         }
-        strategy.sideEffects.add(new Triplet<>(key, value instanceof Supplier 
? (Supplier) value : new ConstantSupplier<>(value), reducer));
+
+        // don't want the GValue to leak beyond strategy application or else 
the Supplier will start producing it
+        // during execution
+        final ConstantSupplier initialValue = value instanceof GValue ? new 
ConstantSupplier<>(((GValue) value).get()) : new ConstantSupplier<>(value);
+        strategy.sideEffects.add(new Triplet<>(key, value instanceof Supplier 
? (Supplier) value : initialValue, reducer));
     }
 
     public boolean contains(final String sideEffectKey) {
diff --git 
a/gremlin-core/src/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 fcfac9b9d9..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
@@ -54,7 +54,7 @@ public class GValueTest {
         final GValue<Integer> gValue = GValue.of("varName", 123);
         assertEquals(123, gValue.get().intValue());
         assertEquals(GType.INTEGER, gValue.getType());
-        assertEquals("varName", gValue.getName().get());
+        assertEquals("varName", gValue.getName());
         assertThat(gValue.isVariable(), is(true));
     }
 
@@ -71,7 +71,7 @@ public class GValueTest {
         final GValue<String> gValue = GValue.ofString("varName", "test");
         assertEquals("test", gValue.get());
         assertEquals(GType.STRING, gValue.getType());
-        assertEquals("varName", gValue.getName().get());
+        assertEquals("varName", gValue.getName());
         assertThat(gValue.isVariable(), is(true));
     }
 
@@ -88,7 +88,7 @@ public class GValueTest {
         final GValue<Integer> gValue = GValue.ofInteger("varName", 123);
         assertEquals(123, gValue.get().intValue());
         assertEquals(GType.INTEGER, gValue.getType());
-        assertEquals("varName", gValue.getName().get());
+        assertEquals("varName", gValue.getName());
         assertThat(gValue.isVariable(), is(true));
     }
 
@@ -105,7 +105,7 @@ public class GValueTest {
         final GValue<Boolean> gValue = GValue.ofBoolean("varName", true);
         assertEquals(true, gValue.get());
         assertEquals(GType.BOOLEAN, gValue.getType());
-        assertEquals("varName", gValue.getName().get());
+        assertEquals("varName", gValue.getName());
         assertThat(gValue.isVariable(), is(true));
     }
 
@@ -122,7 +122,7 @@ public class GValueTest {
         final GValue<Double> gValue = GValue.ofDouble("varName", 123.45);
         assertEquals(123.45, gValue.get(), 0.0);
         assertEquals(GType.DOUBLE, gValue.getType());
-        assertEquals("varName", gValue.getName().get());
+        assertEquals("varName", gValue.getName());
         assertThat(gValue.isVariable(), is(true));
     }
 
@@ -139,7 +139,7 @@ public class GValueTest {
         final GValue<BigInteger> gValue = GValue.ofBigInteger("varName", 
BigInteger.ONE);
         assertEquals(BigInteger.ONE, gValue.get());
         assertEquals(GType.BIG_INTEGER, gValue.getType());
-        assertEquals("varName", gValue.getName().get());
+        assertEquals("varName", gValue.getName());
         assertThat(gValue.isVariable(), is(true));
     }
 
@@ -156,7 +156,7 @@ public class GValueTest {
         final GValue<BigDecimal> gValue = GValue.ofBigDecimal("varName", 
BigDecimal.ONE);
         assertEquals(BigDecimal.ONE, gValue.get());
         assertEquals(GType.BIG_DECIMAL, gValue.getType());
-        assertEquals("varName", gValue.getName().get());
+        assertEquals("varName", gValue.getName());
         assertThat(gValue.isVariable(), is(true));
     }
 
@@ -173,7 +173,7 @@ public class GValueTest {
         final GValue<Long> gValue = GValue.ofLong("varName", 123L);
         assertEquals(123L, gValue.get().longValue());
         assertEquals(GType.LONG, gValue.getType());
-        assertEquals("varName", gValue.getName().get());
+        assertEquals("varName", gValue.getName());
         assertThat(gValue.isVariable(), is(true));
     }
 
@@ -196,14 +196,14 @@ public class GValueTest {
         final GValue<Map> gValue = GValue.ofMap("varName", map);
         assertEquals(map, gValue.get());
         assertEquals(GType.MAP, gValue.getType());
-        assertEquals("varName", gValue.getName().get());
+        assertEquals("varName", gValue.getName());
         assertThat(gValue.isVariable(), is(true));
     }
 
     @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,10 +212,10 @@ 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().get());
+        assertEquals("varName", gValue.getName());
         assertThat(gValue.isVariable(), is(true));
     }
 
@@ -234,7 +234,7 @@ public class GValueTest {
         final GValue<Set> gValue = GValue.ofSet("varName", set);
         assertEquals(set, gValue.get());
         assertEquals(GType.SET, gValue.getType());
-        assertEquals("varName", gValue.getName().get());
+        assertEquals("varName", gValue.getName());
         assertThat(gValue.isVariable(), is(true));
     }
 
@@ -253,7 +253,7 @@ public class GValueTest {
         final GValue<Vertex> gValue = GValue.ofVertex("varName", vertex);
         assertEquals(vertex, gValue.get());
         assertEquals(GType.VERTEX, gValue.getType());
-        assertEquals("varName", gValue.getName().get());
+        assertEquals("varName", gValue.getName());
         assertThat(gValue.isVariable(), is(true));
     }
 
@@ -272,7 +272,7 @@ public class GValueTest {
         final GValue<Edge> gValue = GValue.ofEdge("varName", edge);
         assertEquals(edge, gValue.get());
         assertEquals(GType.EDGE, gValue.getType());
-        assertEquals("varName", gValue.getName().get());
+        assertEquals("varName", gValue.getName());
         assertThat(gValue.isVariable(), is(true));
     }
 
@@ -291,7 +291,7 @@ public class GValueTest {
         final GValue<Path> gValue = GValue.ofPath("varName", path);
         assertEquals(path, gValue.get());
         assertEquals(GType.PATH, gValue.getType());
-        assertEquals("varName", gValue.getName().get());
+        assertEquals("varName", gValue.getName());
         assertThat(gValue.isVariable(), is(true));
     }
 
@@ -310,7 +310,7 @@ public class GValueTest {
         final GValue<Property> gValue = GValue.ofProperty("varName", property);
         assertEquals(property, gValue.get());
         assertEquals(GType.PROPERTY, gValue.getType());
-        assertEquals("varName", gValue.getName().get());
+        assertEquals("varName", gValue.getName());
         assertThat(gValue.isVariable(), is(true));
     }
 }
\ No newline at end of file

Reply via email to