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/27 16:39:21 UTC

(tinkerpop) branch gvalue-3.7 updated: wip - removed admin interface methods - doesn't work nice

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 c6abf2a789 wip - removed admin interface methods - doesn't work nice
c6abf2a789 is described below

commit c6abf2a789359e782147ffecdbd5a6b83b1c49aa
Author: Stephen Mallette <st...@amazon.com>
AuthorDate: Tue Aug 27 12:38:32 2024 -0400

    wip - removed admin interface methods - doesn't work nice
---
 .../traversal/dsl/graph/GraphTraversal.java        | 750 +++++++++++----------
 .../traversal/dsl/graph/GraphTraversalSource.java  |  72 +-
 .../gremlin/process/traversal/dsl/graph/__.java    | 113 ++++
 .../gremlin/process/traversal/step/GValue.java     |  42 ++
 .../process/traversal/step/map/GraphStep.java      |  10 +-
 .../process/traversal/step/map/VertexStep.java     |  16 +-
 .../traversal/step/sideEffect/InjectStep.java      |  10 +-
 .../process/traversal/step/util/AbstractStep.java  |  44 --
 .../optimization/InlineFilterStrategy.java         |   2 +-
 .../tinkerpop/gremlin/util/CollectionUtil.java     |  21 +
 .../traversal/translator/DotNetTranslatorTest.java |   2 +-
 11 files changed, 598 insertions(+), 484 deletions(-)

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 9e38327b86..b64f379d76 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
@@ -203,8 +203,10 @@ import org.apache.tinkerpop.gremlin.structure.PropertyType;
 import org.apache.tinkerpop.gremlin.structure.T;
 import org.apache.tinkerpop.gremlin.structure.Vertex;
 import org.apache.tinkerpop.gremlin.structure.VertexProperty;
+import org.apache.tinkerpop.gremlin.util.CollectionUtil;
 import org.apache.tinkerpop.gremlin.util.function.ConstantSupplier;
 
+import java.lang.reflect.Array;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
@@ -241,346 +243,6 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
      */
     public interface Admin<S, E> extends Traversal.Admin<S, E>, GraphTraversal<S, E> {
 
-        /**
-         * Filter the <code>E</code> object given a biased coin toss. For internal use for  parameterization features.
-         *
-         * @param probability the probability that the object will pass through the filter
-         * @return the traversal with an appended {@link CoinStep}.
-         * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#coin-step" target="_blank">Reference Documentation - Coin Step</a>
-         * @since 3.7.3
-         */
-        public default GraphTraversal<S, E> coin(final GValue<Double> probability) {
-            this.asAdmin().getBytecode().addStep(GraphTraversal.Symbols.coin, probability);
-            return this.asAdmin().addStep(new CoinStep<>(this.asAdmin(), probability));
-        }
-
-        /**
-         * Map any object to a fixed <code>E</code> value. For internal use for  parameterization features.
-         *
-         * @return the traversal with an appended {@link ConstantStep}.
-         * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#constant-step" target="_blank">Reference Documentation - Constant Step</a>
-         * @since 3.7.3
-         */
-        public default <E2> GraphTraversal<S, E2> constant(final GValue<E2> e) {
-            this.asAdmin().getBytecode().addStep(GraphTraversal.Symbols.constant, e);
-            return this.asAdmin().addStep(new ConstantStep<E, E2>(this.asAdmin(), e));
-        }
-
-        /**
-         * Map the {@link Vertex} to its adjacent vertices given a direction and edge labels. The arguments for the
-         * labels must be either a {@code String} or a {@link GValue<String>}. For internal use for  parameterization.
-         *
-         * @param direction  the direction to traverse from the current vertex
-         * @param edgeLabels the edge labels to traverse
-         * @return the traversal with an appended {@link VertexStep}.
-         * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#vertex-steps" target="_blank">Reference Documentation - Vertex Step</a>
-         * @since 3.7.3
-         */
-        public default GraphTraversal<S, Vertex> to(final Direction direction, final Object... edgeLabels) {
-            this.asAdmin().getBytecode().addStep(GraphTraversal.Symbols.to, direction, edgeLabels);
-            return this.asAdmin().addStep(new VertexStep<>(this.asAdmin(), Vertex.class, direction, edgeLabels));
-        }
-
-        /**
-         * Map the {@link Vertex} to its outgoing adjacent vertices given the edge labels. The arguments for the
-         * labels must be either a {@code String} or a {@link GValue<String>}. For internal use for  parameterization.
-         *
-         * @param edgeLabels the edge labels to traverse
-         * @return the traversal with an appended {@link VertexStep}.
-         * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#vertex-steps" target="_blank">Reference Documentation - Vertex Step</a>
-         * @since 3.7.3
-         */
-        public default GraphTraversal<S, Vertex> out(final Object... edgeLabels) {
-            this.asAdmin().getBytecode().addStep(GraphTraversal.Symbols.out, edgeLabels);
-            return this.asAdmin().addStep(new VertexStep<>(this.asAdmin(), Vertex.class, Direction.OUT, edgeLabels));
-        }
-
-        /**
-         * Map the {@link Vertex} to its incoming adjacent vertices given the edge labels. The arguments for the
-         * labels must be either a {@code String} or a {@link GValue<String>}. For internal use for  parameterization.
-         *
-         * @param edgeLabels the edge labels to traverse
-         * @return the traversal with an appended {@link VertexStep}.
-         * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#vertex-steps" target="_blank">Reference Documentation - Vertex Step</a>
-         * @since 3.7.3
-         */
-        public default GraphTraversal<S, Vertex> in(final Object... edgeLabels) {
-            this.asAdmin().getBytecode().addStep(GraphTraversal.Symbols.in, edgeLabels);
-            return this.asAdmin().addStep(new VertexStep<>(this.asAdmin(), Vertex.class, Direction.IN, edgeLabels));
-        }
-
-        /**
-         * Map the {@link Vertex} to its adjacent vertices given the edge labels. The arguments for the labels must be
-         * either a {@code String} or a {@link GValue<String>}. For internal use for  parameterization.
-         *
-         * @param edgeLabels the edge labels to traverse
-         * @return the traversal with an appended {@link VertexStep}.
-         * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#vertex-steps" target="_blank">Reference Documentation - Vertex Step</a>
-         * @since 3.7.3
-         */
-        public default GraphTraversal<S, Vertex> both(final Object... edgeLabels) {
-            this.asAdmin().getBytecode().addStep(GraphTraversal.Symbols.both, edgeLabels);
-            return this.asAdmin().addStep(new VertexStep<>(this.asAdmin(), Vertex.class, Direction.BOTH, edgeLabels));
-        }
-
-        /**
-         * Map the {@link Vertex} to its incident edges given the direction and edge labels. The arguments for the
-         * labels must be either a {@code String} or a {@link GValue<String>}. For internal use for  parameterization.
-         *
-         * @param direction  the direction to traverse from the current vertex
-         * @param edgeLabels the edge labels to traverse
-         * @return the traversal with an appended {@link VertexStep}.
-         * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#vertex-steps" target="_blank">Reference Documentation - Vertex Step</a>
-         * @since 3.7.3
-         */
-        public default GraphTraversal<S, Edge> toE(final Direction direction, final Object... edgeLabels) {
-            this.asAdmin().getBytecode().addStep(GraphTraversal.Symbols.toE, direction, edgeLabels);
-            return this.asAdmin().addStep(new VertexStep<>(this.asAdmin(), Edge.class, direction, edgeLabels));
-        }
-
-        /**
-         * Map the {@link Vertex} to its outgoing incident edges given the edge labels. The arguments for the labels
-         * must be either a {@code String} or a {@link GValue<String>}. For internal use for  parameterization.
-         *
-         * @param edgeLabels the edge labels to traverse
-         * @return the traversal with an appended {@link VertexStep}.
-         * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#vertex-steps" target="_blank">Reference Documentation - Vertex Step</a>
-         * @since 3.7.3
-         */
-        public default GraphTraversal<S, Edge> outE(final Object... edgeLabels) {
-            this.asAdmin().getBytecode().addStep(GraphTraversal.Symbols.outE, edgeLabels);
-            return this.asAdmin().addStep(new VertexStep<>(this.asAdmin(), Edge.class, Direction.OUT, edgeLabels));
-        }
-
-        /**
-         * Map the {@link Vertex} to its incoming incident edges given the edge labels. The arguments for the labels
-         * must be either a {@code String} or a {@link GValue<String>}. For internal use for  parameterization.
-         *
-         * @param edgeLabels the edge labels to traverse
-         * @return the traversal with an appended {@link VertexStep}.
-         * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#vertex-steps" target="_blank">Reference Documentation - Vertex Step</a>
-         * @since 3.7.3
-         */
-        public default GraphTraversal<S, Edge> inE(final Object... edgeLabels) {
-            this.asAdmin().getBytecode().addStep(GraphTraversal.Symbols.inE, edgeLabels);
-            return this.asAdmin().addStep(new VertexStep<>(this.asAdmin(), Edge.class, Direction.IN, edgeLabels));
-        }
-
-        /**
-         * Map the {@link Vertex} to its incident edges given the edge labels. The arguments for the labels must be
-         * either a {@code String} or a {@link GValue<String>}. For internal use for  parameterization.
-         *
-         * @param edgeLabels the edge labels to traverse
-         * @return the traversal with an appended {@link VertexStep}.
-         * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#vertex-steps" target="_blank">Reference Documentation - Vertex Step</a>
-         * @since 3.7.3
-         */
-        public default GraphTraversal<S, Edge> bothE(final Object... edgeLabels) {
-            this.asAdmin().getBytecode().addStep(GraphTraversal.Symbols.bothE, edgeLabels);
-            return this.asAdmin().addStep(new VertexStep<>(this.asAdmin(), Edge.class, Direction.BOTH, edgeLabels));
-        }
-
-        /**
-         * Adds a {@link Vertex}.
-         *
-         * @param vertexLabel the label of the {@link Vertex} to add
-         * @return the traversal with the {@link AddVertexStep} added
-         * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#addvertex-step" target="_blank">Reference Documentation - AddVertex Step</a>
-         * @since 3.7.3
-         */
-        public default GraphTraversal<S, Vertex> addV(final GValue<String> vertexLabel) {
-            if (null == vertexLabel || null == vertexLabel.get()) throw new IllegalArgumentException("vertexLabel cannot be null");
-            this.asAdmin().getBytecode().addStep(GraphTraversal.Symbols.addV, vertexLabel);
-            return this.asAdmin().addStep(new AddVertexStep<>(this.asAdmin(), vertexLabel));
-        }
-
-        /**
-         * Performs 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 3.7.3
-         */
-        public default GraphTraversal<S, Vertex> mergeV(final GValue<Map<Object, Object>> searchCreate) {
-            this.asAdmin().getBytecode().addStep(GraphTraversal.Symbols.mergeV, searchCreate);
-            final MergeVertexStep<S> step = new MergeVertexStep(this.asAdmin(), false, null == searchCreate ? GValue.ofMap(null) : searchCreate);
-            return this.asAdmin().addStep(step);
-        }
-
-        /**
-         * 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 3.7.3
-         */
-        public default GraphTraversal<S, Edge> mergeE(final GValue<Map<Object, Object>> searchCreate) {
-            // get a construction time exception if the Map is bad
-            this.asAdmin().getBytecode().addStep(GraphTraversal.Symbols.mergeE, searchCreate);
-            final MergeEdgeStep<S> step = new MergeEdgeStep(this.asAdmin(), false, null == searchCreate ? GValue.ofMap(null) : searchCreate);
-            return this.asAdmin().addStep(step);
-        }
-
-        /**
-         * Adds an {@link Edge} with the specified edge label.
-         *
-         * @param edgeLabel the label of the newly added edge
-         * @return the traversal with the {@link AddEdgeStep} added
-         * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#addedge-step" target="_blank">Reference Documentation - AddEdge Step</a>
-         * @since 3.7.3
-         */
-        public default GraphTraversal<S, Edge> addE(final GValue<String> edgeLabel) {
-            this.asAdmin().getBytecode().addStep(GraphTraversal.Symbols.addE, edgeLabel);
-            return this.asAdmin().addStep(new AddEdgeStep<>(this.asAdmin(), edgeLabel));
-        }
-
-        /**
-         * Filters vertices, edges and vertex properties based on their label.
-         *
-         * @param label       the label of the {@link Element}
-         * @param otherLabels additional labels of the {@link Element}
-         * @return the traversal with an appended {@link HasStep}
-         * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#has-step" target="_blank">Reference Documentation - Has Step</a>
-         * @since 3.2.2
-         */
-        public default GraphTraversal<S, E> hasLabel(final GValue<String> label, final GValue<String>... otherLabels) {
-            this.asAdmin().getBytecode().addStep(GraphTraversal.Symbols.hasLabel, label, otherLabels);
-
-            // groovy evaluation seems to do strange things with varargs given hasLabel(null, null). odd someone would
-            // do this but the failure is ugly if not handled.
-            final int otherLabelsLength = null == otherLabels ? 0 : otherLabels.length;
-            final Object[] labels = new Object[otherLabelsLength + 1];
-            labels[0] = label;
-            if (otherLabelsLength > 0)
-                System.arraycopy(otherLabels, 0, labels, 1, otherLabelsLength);
-            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
-         * the documentation of such steps to understand the usage context.
-         *
-         * @param m Provides a {@code Map} as the option which is the same as doing {@code constant(m)}.
-         * @return the traversal with the modulated step
-         * @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.7.3
-         */
-        public default <M, E2> GraphTraversal<S, E> option(final M token, final GValue<Map<Object, Object>> m) {
-            this.asAdmin().getBytecode().addStep(GraphTraversal.Symbols.option, token, m);
-            ((TraversalOptionParent<M, E, E2>) this.asAdmin().getEndStep()).addChildOption(token, (Traversal.Admin<E, E2>) new ConstantTraversal<>(m).asAdmin());
-            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
-         * the documentation of such steps to understand the usage context.
-         *
-         * @param m Provides a {@code Map} as the option which is the same as doing {@code constant(m)}.
-         * @return the traversal with the modulated step
-         * @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.7.3
-         */
-        public default <M, E2> GraphTraversal<S, E> option(final Merge merge, final GValue<Map<Object, Object>> m, final VertexProperty.Cardinality cardinality) {
-            this.asAdmin().getBytecode().addStep(GraphTraversal.Symbols.option, merge, m, cardinality);
-
-            final Map<Object, Object> map = m.get();
-
-            // do explicit cardinality for every single pair in the map
-            for (Object k : map.keySet()) {
-                final Object o = map.get(k);
-                if (!(o instanceof CardinalityValueTraversal))
-                    map.put(k, new CardinalityValueTraversal(cardinality, o));
-            }
-            ((TraversalOptionParent<M, E, E2>) this.asAdmin().getEndStep()).addChildOption((M) merge, (Traversal.Admin<E, E2>) new ConstantTraversal<>(m).asAdmin());
-            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;
-        }
-
-        /**
-         * Filters vertices, edges and vertex properties based on their properties.
-         *
-         * @param label       the label of the {@link Element}
-         * @param propertyKey the key of the property to filter on
-         * @param value       the value to compare the accessor value to for equality
-         * @return the traversal with an appended {@link HasStep}
-         * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#has-step" target="_blank">Reference Documentation - Has Step</a>
-         * @since 4.0.0
-         */
-        public default GraphTraversal<S, E> has(final GValue<String> label, final String propertyKey, final Object value) {
-            this.asAdmin().getBytecode().addStep(GraphTraversal.Symbols.has, label.get(), propertyKey, value);
-            TraversalHelper.addHasContainer(this.asAdmin(), new HasContainer(T.label.getAccessor(), P.eq(label)));
-            return TraversalHelper.addHasContainer(this.asAdmin(), new HasContainer(propertyKey, value instanceof P ? (P) value : P.eq(value)));
-        }
-
         @Override
         public default <E2> GraphTraversal.Admin<S, E2> addStep(final Step<?, E2> step) {
             return (GraphTraversal.Admin<S, E2>) Traversal.Admin.super.addStep((Step) step);
@@ -705,6 +367,18 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
         return this.asAdmin().addStep(new ConstantStep<E, E2>(this.asAdmin(), e));
     }
 
+    /**
+     * Map any object to a fixed <code>E</code> value. For internal use for  parameterization features.
+     *
+     * @return the traversal with an appended {@link ConstantStep}.
+     * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#constant-step" target="_blank">Reference Documentation - Constant Step</a>
+     * @since 4.0.0
+     */
+    public default <E2> GraphTraversal<S, E2> constant(final GValue<E2> e) {
+        this.asAdmin().getBytecode().addStep(GraphTraversal.Symbols.constant, e);
+        return this.asAdmin().addStep(new ConstantStep<E, E2>(this.asAdmin(), e));
+    }
+
     /**
      * A {@code V} step is usually used to start a traversal but it may also be used mid-traversal.
      *
@@ -749,6 +423,22 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
         return this.asAdmin().addStep(new VertexStep<>(this.asAdmin(), Vertex.class, direction, edgeLabels));
     }
 
+    /**
+     * Map the {@link Vertex} to its adjacent vertices given a direction and edge labels. The arguments for the
+     * labels must be either a {@code String} or a {@link GValue<String>}. For internal use for  parameterization.
+     *
+     * @param direction  the direction to traverse from the current vertex
+     * @param edgeLabels the edge labels to traverse
+     * @return the traversal with an appended {@link VertexStep}.
+     * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#vertex-steps" target="_blank">Reference Documentation - Vertex Step</a>
+     * @since 4.0.0
+     */
+    public default GraphTraversal<S, Vertex> to(final Direction direction, final GValue<String> edgeLabel, final GValue<String>... edgeLabels) {
+        this.asAdmin().getBytecode().addStep(GraphTraversal.Symbols.to, direction, edgeLabel, edgeLabels);
+        final GValue<String>[] labels = CollectionUtil.addFirst(edgeLabels, edgeLabel, GValue.class);
+        return this.asAdmin().addStep(new VertexStep<>(this.asAdmin(), Vertex.class, direction, labels));
+    }
+
     /**
      * Map the {@link Vertex} to its outgoing adjacent vertices given the edge labels.
      *
@@ -762,6 +452,21 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
         return this.asAdmin().addStep(new VertexStep<>(this.asAdmin(), Vertex.class, Direction.OUT, edgeLabels));
     }
 
+    /**
+     * Map the {@link Vertex} to its outgoing adjacent vertices given the edge labels. The arguments for the
+     * labels must be either a {@code String} or a {@link GValue<String>}. For internal use for  parameterization.
+     *
+     * @param edgeLabels the edge labels to traverse
+     * @return the traversal with an appended {@link VertexStep}.
+     * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#vertex-steps" target="_blank">Reference Documentation - Vertex Step</a>
+     * @since 3.7.3
+     */
+    public default GraphTraversal<S, Vertex> out(final GValue<String> label, final GValue<String>... edgeLabels) {
+        final GValue<String>[] labels = CollectionUtil.addFirst(edgeLabels, label, GValue.class);
+        this.asAdmin().getBytecode().addStep(GraphTraversal.Symbols.out, label, edgeLabels);
+        return this.asAdmin().addStep(new VertexStep<>(this.asAdmin(), Vertex.class, Direction.OUT, labels));
+    }
+
     /**
      * Map the {@link Vertex} to its incoming adjacent vertices given the edge labels.
      *
@@ -775,6 +480,21 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
         return this.asAdmin().addStep(new VertexStep<>(this.asAdmin(), Vertex.class, Direction.IN, edgeLabels));
     }
 
+    /**
+     * Map the {@link Vertex} to its incoming adjacent vertices given the edge labels. The arguments for the
+     * labels must be either a {@code String} or a {@link GValue<String>}. For internal use for  parameterization.
+     *
+     * @param edgeLabels the edge labels to traverse
+     * @return the traversal with an appended {@link VertexStep}.
+     * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#vertex-steps" target="_blank">Reference Documentation - Vertex Step</a>
+     * @since 4.0.0
+     */
+    public default GraphTraversal<S, Vertex> in(final GValue<String> label, final GValue<String>... edgeLabels) {
+        final GValue<String>[] labels = CollectionUtil.addFirst(edgeLabels, label, GValue.class);
+        this.asAdmin().getBytecode().addStep(GraphTraversal.Symbols.in, label, edgeLabels);
+        return this.asAdmin().addStep(new VertexStep<>(this.asAdmin(), Vertex.class, Direction.IN, labels));
+    }
+
     /**
      * Map the {@link Vertex} to its adjacent vertices given the edge labels.
      *
@@ -788,6 +508,21 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
         return this.asAdmin().addStep(new VertexStep<>(this.asAdmin(), Vertex.class, Direction.BOTH, edgeLabels));
     }
 
+    /**
+     * Map the {@link Vertex} to its adjacent vertices given the edge labels. The arguments for the labels must be
+     * either a {@code String} or a {@link GValue<String>}. For internal use for  parameterization.
+     *
+     * @param edgeLabels the edge labels to traverse
+     * @return the traversal with an appended {@link VertexStep}.
+     * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#vertex-steps" target="_blank">Reference Documentation - Vertex Step</a>
+     * @since 4.0.0
+     */
+    public default GraphTraversal<S, Vertex> both(final GValue<String> label, final GValue<String>... edgeLabels) {
+        final GValue<String>[] labels = CollectionUtil.addFirst(edgeLabels, label, GValue.class);
+        this.asAdmin().getBytecode().addStep(GraphTraversal.Symbols.both, label, edgeLabels);
+        return this.asAdmin().addStep(new VertexStep<>(this.asAdmin(), Vertex.class, Direction.BOTH, labels));
+    }
+
     /**
      * Map the {@link Vertex} to its incident edges given the direction and edge labels.
      *
@@ -802,6 +537,23 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
         return this.asAdmin().addStep(new VertexStep<>(this.asAdmin(), Edge.class, direction, edgeLabels));
     }
 
+
+    /**
+     * Map the {@link Vertex} to its incident edges given the direction and edge labels. The arguments for the
+     * labels must be either a {@code String} or a {@link GValue<String>}. For internal use for  parameterization.
+     *
+     * @param direction  the direction to traverse from the current vertex
+     * @param edgeLabels the edge labels to traverse
+     * @return the traversal with an appended {@link VertexStep}.
+     * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#vertex-steps" target="_blank">Reference Documentation - Vertex Step</a>
+     * @since 4.0.0
+     */
+    public default GraphTraversal<S, Edge> toE(final Direction direction, final GValue<String> edgeLabel, final GValue<String>... edgeLabels) {
+        this.asAdmin().getBytecode().addStep(GraphTraversal.Symbols.toE, direction, edgeLabel, edgeLabels);
+        final GValue<String>[] labels = CollectionUtil.addFirst(edgeLabels, edgeLabel, GValue.class);
+        return this.asAdmin().addStep(new VertexStep<>(this.asAdmin(), Edge.class, direction, labels));
+    }
+
     /**
      * Map the {@link Vertex} to its outgoing incident edges given the edge labels.
      *
@@ -815,6 +567,21 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
         return this.asAdmin().addStep(new VertexStep<>(this.asAdmin(), Edge.class, Direction.OUT, edgeLabels));
     }
 
+    /**
+     * Map the {@link Vertex} to its outgoing incident edges given the edge labels. The arguments for the labels
+     * must be either a {@code String} or a {@link GValue<String>}. For internal use for  parameterization.
+     *
+     * @param edgeLabels the edge labels to traverse
+     * @return the traversal with an appended {@link VertexStep}.
+     * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#vertex-steps" target="_blank">Reference Documentation - Vertex Step</a>
+     * @since 4.0.0
+     */
+    public default GraphTraversal<S, Edge> outE(final GValue<String> label, final GValue<String>... edgeLabels) {
+        final GValue<String>[] labels = CollectionUtil.addFirst(edgeLabels, label, GValue.class);
+        this.asAdmin().getBytecode().addStep(GraphTraversal.Symbols.outE, label, edgeLabels);
+        return this.asAdmin().addStep(new VertexStep<>(this.asAdmin(), Edge.class, Direction.OUT, labels));
+    }
+
     /**
      * Map the {@link Vertex} to its incoming incident edges given the edge labels.
      *
@@ -828,6 +595,22 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
         return this.asAdmin().addStep(new VertexStep<>(this.asAdmin(), Edge.class, Direction.IN, edgeLabels));
     }
 
+    /**
+     * Map the {@link Vertex} to its incoming incident edges given the edge labels. The arguments for the labels
+     * must be either a {@code String} or a {@link GValue<String>}. For internal use for  parameterization.
+     *
+     * @param edgeLabels the edge labels to traverse
+     * @return the traversal with an appended {@link VertexStep}.
+     * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#vertex-steps" target="_blank">Reference Documentation - Vertex Step</a>
+     * @since 4.0.0
+     */
+    public default GraphTraversal<S, Edge> inE(final GValue<String> label, final GValue<String>... edgeLabels) {
+        final GValue<String>[] labels = CollectionUtil.addFirst(edgeLabels, label, GValue.class);
+        this.asAdmin().getBytecode().addStep(GraphTraversal.Symbols.inE, label, edgeLabels);
+        return this.asAdmin().addStep(new VertexStep<>(this.asAdmin(), Edge.class, Direction.IN, labels));
+    }
+
+
     /**
      * Map the {@link Vertex} to its incident edges given the edge labels.
      *
@@ -841,6 +624,21 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
         return this.asAdmin().addStep(new VertexStep<>(this.asAdmin(), Edge.class, Direction.BOTH, edgeLabels));
     }
 
+    /**
+     * Map the {@link Vertex} to its incident edges given the edge labels. The arguments for the labels must be
+     * either a {@code String} or a {@link GValue<String>}. For internal use for  parameterization.
+     *
+     * @param edgeLabels the edge labels to traverse
+     * @return the traversal with an appended {@link VertexStep}.
+     * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#vertex-steps" target="_blank">Reference Documentation - Vertex Step</a>
+     * @since 4.0.0
+     */
+    public default GraphTraversal<S, Edge> bothE(final GValue<String> label, final GValue<String>... edgeLabels) {
+        final GValue<String>[] labels = CollectionUtil.addFirst(edgeLabels, label, GValue.class);
+        this.asAdmin().getBytecode().addStep(GraphTraversal.Symbols.bothE, label, edgeLabels);
+        return this.asAdmin().addStep(new VertexStep<>(this.asAdmin(), Edge.class, Direction.BOTH, labels));
+    }
+
     /**
      * Map the {@link Edge} to its incident vertices given the direction.
      *
@@ -1470,6 +1268,20 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
         return this.asAdmin().addStep(new AddVertexStep<>(this.asAdmin(), vertexLabelTraversal.asAdmin()));
     }
 
+    /**
+     * Adds a {@link Vertex}.
+     *
+     * @param vertexLabel the label of the {@link Vertex} to add
+     * @return the traversal with the {@link AddVertexStep} added
+     * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#addvertex-step" target="_blank">Reference Documentation - AddVertex Step</a>
+     * @since 4.0.0
+     */
+    public default GraphTraversal<S, Vertex> addV(final GValue<String> vertexLabel) {
+        if (null == vertexLabel || null == vertexLabel.get()) throw new IllegalArgumentException("vertexLabel cannot be null");
+        this.asAdmin().getBytecode().addStep(GraphTraversal.Symbols.addV, vertexLabel);
+        return this.asAdmin().addStep(new AddVertexStep<>(this.asAdmin(), vertexLabel));
+    }
+
     /**
      * Adds a {@link Vertex} with a default vertex label.
      *
@@ -1528,6 +1340,21 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
         return this.asAdmin().addStep(step);
     }
 
+    /**
+     * Performs 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 default GraphTraversal<S, Vertex> mergeV(final GValue<Map<Object, Object>> searchCreate) {
+        this.asAdmin().getBytecode().addStep(GraphTraversal.Symbols.mergeV, searchCreate);
+        final MergeVertexStep<S> step = new MergeVertexStep(this.asAdmin(), false, null == searchCreate ? GValue.ofMap(null) : searchCreate);
+        return this.asAdmin().addStep(step);
+    }
+
     /**
      * Spawns a {@link GraphTraversal} by doing a merge (i.e. upsert) style operation for an {@link Edge} using an
      * incoming {@code Map} as an argument.
@@ -1569,6 +1396,20 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
         return this.asAdmin().addStep(step);
     }
 
+    /**
+     * 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 default GraphTraversal<S, Edge> mergeE(final GValue<Map<Object, Object>> searchCreate) {
+        // get a construction time exception if the Map is bad
+        this.asAdmin().getBytecode().addStep(GraphTraversal.Symbols.mergeE, searchCreate);
+        final MergeEdgeStep<S> step = new MergeEdgeStep(this.asAdmin(), false, null == searchCreate ? GValue.ofMap(null) : searchCreate);
+        return this.asAdmin().addStep(step);
+    }
+
     /**
      * Adds an {@link Edge} with the specified edge label.
      *
@@ -1595,21 +1436,35 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
     }
 
     /**
-     * Provide {@code to()}-modulation to respective steps.
+     * Adds an {@link Edge} with the specified edge label.
      *
-     * @param toStepLabel the step label to modulate to.
-     * @return the traversal with the modified {@link FromToModulating} step.
-     * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#to-step" target="_blank">Reference Documentation - To Step</a>
+     * @param edgeLabel the label of the newly added edge
+     * @return the traversal with the {@link AddEdgeStep} added
+     * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#addedge-step" target="_blank">Reference Documentation - AddEdge Step</a>
+     * @since 4.0.0
+     */
+    public default GraphTraversal<S, Edge> addE(final GValue<String> edgeLabel) {
+        this.asAdmin().getBytecode().addStep(GraphTraversal.Symbols.addE, edgeLabel);
+        return this.asAdmin().addStep(new AddEdgeStep<>(this.asAdmin(), edgeLabel));
+    }
+
+    /**
+     * 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 traversal 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 3.1.0-incubating
      */
-    public default GraphTraversal<S, E> to(final String toStepLabel) {
+    public default GraphTraversal<S, E> from(final Traversal<?, Vertex> fromVertex) {
         final Step<?,?> prev = this.asAdmin().getEndStep();
         if (!(prev instanceof FromToModulating))
             throw new IllegalArgumentException(String.format(
-                    "The to() step cannot follow %s", prev.getClass().getSimpleName()));
+                    "The from() step cannot follow %s", prev.getClass().getSimpleName()));
 
-        this.asAdmin().getBytecode().addStep(Symbols.to, toStepLabel);
-        ((FromToModulating) prev).addTo(toStepLabel);
+        this.asAdmin().getBytecode().addStep(Symbols.from, fromVertex);
+        ((FromToModulating) prev).addFrom(fromVertex.asAdmin());
         return this;
     }
 
@@ -1634,21 +1489,21 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
 
     /**
      * 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}.
+     * outgoing vertex of the newly added {@link Edge}.
      *
-     * @param toVertex the traversal for selecting the incoming vertex
+     * @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 3.1.0-incubating
+     * @since 4.0.0
      */
-    public default GraphTraversal<S, E> to(final Traversal<?, Vertex> toVertex) {
+    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 to() step cannot follow %s", prev.getClass().getSimpleName()));
+                    "The from() step cannot follow %s", prev.getClass().getSimpleName()));
 
-        this.asAdmin().getBytecode().addStep(Symbols.to, toVertex);
-        ((FromToModulating) prev).addTo(toVertex.asAdmin());
+        this.asAdmin().getBytecode().addStep(GraphTraversal.Symbols.from, fromVertex);
+        ((FromToModulating) prev).addFrom(__.constant(fromVertex).asAdmin());
         return this;
     }
 
@@ -1656,19 +1511,38 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
      * 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 traversal for selecting the outgoing vertex
+     * @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 3.1.0-incubating
+     * @since 3.3.0
      */
-    public default GraphTraversal<S, E> from(final Traversal<?, Vertex> fromVertex) {
+    public default GraphTraversal<S, E> from(final 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(Symbols.from, fromVertex);
-        ((FromToModulating) prev).addFrom(fromVertex.asAdmin());
+        ((FromToModulating) prev).addFrom(__.constant(fromVertex).asAdmin());
+        return this;
+    }
+
+    /**
+     * Provide {@code to()}-modulation to respective steps.
+     *
+     * @param toStepLabel the step label to modulate to.
+     * @return the traversal with the modified {@link FromToModulating} step.
+     * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#to-step" target="_blank">Reference Documentation - To Step</a>
+     * @since 3.1.0-incubating
+     */
+    public default GraphTraversal<S, E> to(final String toStepLabel) {
+        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(Symbols.to, toStepLabel);
+        ((FromToModulating) prev).addTo(toStepLabel);
         return this;
     }
 
@@ -1679,36 +1553,56 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
      * @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 3.3.0
+     * @since 4.0.0
      */
-    public default GraphTraversal<S, E> to(final Vertex toVertex) {
+    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(Symbols.to, toVertex);
+        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}.
+     * incoming vertex of the newly added {@link Edge}.
      *
-     * @param fromVertex the vertex for selecting the outgoing vertex
+     * @param toVertex the traversal 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 3.1.0-incubating
+     */
+    public default GraphTraversal<S, E> to(final Traversal<?, 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(Symbols.to, toVertex);
+        ((FromToModulating) prev).addTo(toVertex.asAdmin());
+        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 3.3.0
      */
-    public default GraphTraversal<S, E> from(final Vertex fromVertex) {
+    public default GraphTraversal<S, E> to(final Vertex toVertex) {
         final Step<?,?> prev = this.asAdmin().getEndStep();
         if (!(prev instanceof FromToModulating))
             throw new IllegalArgumentException(String.format(
-                    "The from() step cannot follow %s", prev.getClass().getSimpleName()));
+                    "The to() step cannot follow %s", prev.getClass().getSimpleName()));
 
-        this.asAdmin().getBytecode().addStep(Symbols.from, fromVertex);
-        ((FromToModulating) prev).addFrom(__.constant(fromVertex).asAdmin());
+        this.asAdmin().getBytecode().addStep(Symbols.to, toVertex);
+        ((FromToModulating) prev).addTo(__.constant(toVertex).asAdmin());
         return this;
     }
 
@@ -2666,6 +2560,22 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
         return this.asAdmin().addStep(new TraversalFilterStep(this.asAdmin(), __.values(propertyKey)));
     }
 
+    /**
+     * Filters vertices, edges and vertex properties based on their properties.
+     *
+     * @param label       the label of the {@link Element}
+     * @param propertyKey the key of the property to filter on
+     * @param value       the value to compare the accessor value to for equality
+     * @return the traversal with an appended {@link HasStep}
+     * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#has-step" target="_blank">Reference Documentation - Has Step</a>
+     * @since 4.0.0
+     */
+    public default GraphTraversal<S, E> has(final GValue<String> label, final String propertyKey, final Object value) {
+        this.asAdmin().getBytecode().addStep(GraphTraversal.Symbols.has, label.get(), propertyKey, value);
+        TraversalHelper.addHasContainer(this.asAdmin(), new HasContainer(T.label.getAccessor(), P.eq(label)));
+        return TraversalHelper.addHasContainer(this.asAdmin(), new HasContainer(propertyKey, value instanceof P ? (P) value : P.eq(value)));
+    }
+
     /**
      * Filters vertices, edges and vertex properties based on the non-existence of properties.
      *
@@ -2693,11 +2603,7 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
 
         // groovy evaluation seems to do strange things with varargs given hasLabel(null, null). odd someone would
         // do this but the failure is ugly if not handled.
-        final int otherLabelsLength = null == otherLabels ? 0 : otherLabels.length;
-        final String[] labels = new String[otherLabelsLength + 1];
-        labels[0] = label;
-        if (otherLabelsLength > 0)
-            System.arraycopy(otherLabels, 0, labels, 1, otherLabelsLength);
+        final String[] labels = CollectionUtil.addFirst(otherLabels, label, String.class);
         return TraversalHelper.addHasContainer(this.asAdmin(), new HasContainer(T.label.getAccessor(), labels.length == 1 ? P.eq(labels[0]) : P.within(labels)));
     }
 
@@ -2720,6 +2626,24 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
         }
     }
 
+    /**
+     * Filters vertices, edges and vertex properties based on their label.
+     *
+     * @param label       the label of the {@link Element}
+     * @param otherLabels additional labels of the {@link Element}
+     * @return the traversal with an appended {@link HasStep}
+     * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#has-step" target="_blank">Reference Documentation - Has Step</a>
+     * @since 4.0.0
+     */
+    public default GraphTraversal<S, E> hasLabel(final GValue<String> label, final GValue<String>... otherLabels) {
+        this.asAdmin().getBytecode().addStep(GraphTraversal.Symbols.hasLabel, label, otherLabels);
+
+        // groovy evaluation seems to do strange things with varargs given hasLabel(null, null). odd someone would
+        // do this but the failure is ugly if not handled.
+        final Object[] labels = CollectionUtil.addFirst(otherLabels, label, GValue.class);
+        return TraversalHelper.addHasContainer(this.asAdmin(), new HasContainer(T.label.getAccessor(), labels.length == 1 ? P.eq(labels[0]) : P.within(labels)));
+    }
+
     /**
      * Filters vertices, edges and vertex properties based on their identifier.
      *
@@ -2931,6 +2855,19 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
         return this.asAdmin().addStep(new CoinStep<>(this.asAdmin(), probability));
     }
 
+    /**
+     * Filter the <code>E</code> object given a biased coin toss. For internal use for  parameterization features.
+     *
+     * @param probability the probability that the object will pass through the filter
+     * @return the traversal with an appended {@link CoinStep}.
+     * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#coin-step" target="_blank">Reference Documentation - Coin Step</a>
+     * @since 4.0.0
+     */
+    public default GraphTraversal<S, E> coin(final GValue<Double> probability) {
+        this.asAdmin().getBytecode().addStep(GraphTraversal.Symbols.coin, probability);
+        return this.asAdmin().addStep(new CoinStep<>(this.asAdmin(), probability));
+    }
+
     /**
      * Filter the objects in the traversal by the number of them to pass through the stream. Those before the value
      * of {@code low} do not pass through and those that exceed the value of {@code high} will end the iteration.
@@ -4295,6 +4232,73 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
         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
+     * 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
+     * the documentation of such steps to understand the usage context.
+     *
+     * @param m Provides a {@code Map} as the option which is the same as doing {@code constant(m)}.
+     * @return the traversal with the modulated step
+     * @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.7.3
+     */
+    public default <M, E2> GraphTraversal<S, E> option(final M token, final GValue<Map<Object, Object>> m) {
+        this.asAdmin().getBytecode().addStep(GraphTraversal.Symbols.option, token, m);
+        ((TraversalOptionParent<M, E, E2>) this.asAdmin().getEndStep()).addChildOption(token, (Traversal.Admin<E, E2>) new ConstantTraversal<>(m).asAdmin());
+        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
+     * the documentation of such steps to understand the usage context.
+     *
+     * @param m Provides a {@code Map} as the option which is the same as doing {@code constant(m)}.
+     * @return the traversal with the modulated step
+     * @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.7.3
+     */
+    public default <M, E2> GraphTraversal<S, E> option(final Merge merge, final GValue<Map<Object, Object>> m, final VertexProperty.Cardinality cardinality) {
+        this.asAdmin().getBytecode().addStep(GraphTraversal.Symbols.option, merge, m, cardinality);
+
+        final Map<Object, Object> map = m.get();
+
+        // do explicit cardinality for every single pair in the map
+        for (Object k : map.keySet()) {
+            final Object o = map.get(k);
+            if (!(o instanceof CardinalityValueTraversal))
+                map.put(k, new CardinalityValueTraversal(cardinality, o));
+        }
+        ((TraversalOptionParent<M, E, E2>) this.asAdmin().getEndStep()).addChildOption((M) merge, (Traversal.Admin<E, E2>) new ConstantTraversal<>(m).asAdmin());
+        return this;
+    }
+
     ////
 
     ///////////////////// IO STEPS /////////////////////
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 961ba8c59c..6197ce751f 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
@@ -69,7 +69,6 @@ public class GraphTraversalSource implements TraversalSource {
     protected final Graph graph;
     protected TraversalStrategies strategies;
     protected Bytecode bytecode = new Bytecode();
-    protected Admin admin;
 
     ////////////////
 
@@ -102,12 +101,6 @@ 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);
@@ -414,6 +407,22 @@ public class GraphTraversalSource implements TraversalSource {
         return traversal.addStep(step);
     }
 
+    /**
+     * 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.
@@ -446,6 +455,20 @@ public class GraphTraversalSource implements TraversalSource {
         return traversal.addStep(step);
     }
 
+    /**
+     * 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));
+    }
+
     /**
      * Spawns a {@link GraphTraversal} starting it with arbitrary values.
      */
@@ -632,39 +655,4 @@ 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/dsl/graph/__.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/__.java
index d6cdc1ef7f..009f67be38 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/__.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/__.java
@@ -25,6 +25,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.Pop;
 import org.apache.tinkerpop.gremlin.process.traversal.Scope;
 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.map.FormatStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.util.Tree;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.util.TraverserSet;
@@ -110,6 +111,13 @@ public class __ {
         return __.<A>start().constant(a);
     }
 
+    /**
+     * @see GraphTraversal#constant(GValue)
+     */
+    public static <A> GraphTraversal<A, A> constant(final GValue<A> a) {
+        return __.<A>start().constant(a);
+    }
+
     /**
      * @see GraphTraversal#label()
      */
@@ -145,6 +153,13 @@ public class __ {
         return __.<Vertex>start().to(direction, edgeLabels);
     }
 
+    /**
+     * @see GraphTraversal#to(Direction, GValue, GValue...)
+     */
+    public static GraphTraversal<Vertex, Vertex> to(final Direction direction, final GValue<String> edgeLabel, final GValue<String>... edgeLabels) {
+        return __.<Vertex>start().to(direction, edgeLabel, edgeLabels);
+    }
+
     /**
      * @see GraphTraversal#out(String...)
      */
@@ -152,6 +167,13 @@ public class __ {
         return __.<Vertex>start().out(edgeLabels);
     }
 
+    /**
+     * @see GraphTraversal#out(GValue, GValue...)
+     */
+    public static GraphTraversal<Vertex, Vertex> out(final GValue<String> edgeLabel, final GValue<String>... edgeLabels) {
+        return __.<Vertex>start().out(edgeLabel, edgeLabels);
+    }
+
     /**
      * @see GraphTraversal#in(String...)
      */
@@ -159,6 +181,13 @@ public class __ {
         return __.<Vertex>start().in(edgeLabels);
     }
 
+    /**
+     * @see GraphTraversal#in(String...)
+     */
+    public static GraphTraversal<Vertex, Vertex> in(final GValue<String> edgeLabel, final GValue<String>... edgeLabels) {
+        return __.<Vertex>start().in(edgeLabel, edgeLabels);
+    }
+
     /**
      * @see GraphTraversal#both(String...)
      */
@@ -166,6 +195,13 @@ public class __ {
         return __.<Vertex>start().both(edgeLabels);
     }
 
+    /**
+     * @see GraphTraversal#both(GValue, GValue...)
+     */
+    public static GraphTraversal<Vertex, Vertex> both(final GValue<String> edgeLabel, final GValue<String>... edgeLabels) {
+        return __.<Vertex>start().both(edgeLabel, edgeLabels);
+    }
+
     /**
      * @see GraphTraversal#toE(Direction, String...)
      */
@@ -173,6 +209,13 @@ public class __ {
         return __.<Vertex>start().toE(direction, edgeLabels);
     }
 
+    /**
+     * @see GraphTraversal#toE(Direction, GValue, GValue...)
+     */
+    public static GraphTraversal<Vertex, Edge> toE(final Direction direction, final GValue<String> edgeLabel, final GValue<String>... edgeLabels) {
+        return __.<Vertex>start().toE(direction, edgeLabel, edgeLabels);
+    }
+
     /**
      * @see GraphTraversal#outE(String...)
      */
@@ -180,6 +223,13 @@ public class __ {
         return __.<Vertex>start().outE(edgeLabels);
     }
 
+    /**
+     * @see GraphTraversal#outE(GValue, GValue...)
+     */
+    public static GraphTraversal<Vertex, Edge> outE(final GValue<String> edgeLabel, final GValue<String>... edgeLabels) {
+        return __.<Vertex>start().outE(edgeLabel, edgeLabels);
+    }
+
     /**
      * @see GraphTraversal#inE(String...)
      */
@@ -187,6 +237,13 @@ public class __ {
         return __.<Vertex>start().inE(edgeLabels);
     }
 
+    /**
+     * @see GraphTraversal#inE(GValue, GValue...)
+     */
+    public static GraphTraversal<Vertex, Edge> inE(final GValue<String> edgeLabel, final GValue<String>... edgeLabels) {
+        return __.<Vertex>start().inE(edgeLabel, edgeLabels);
+    }
+
     /**
      * @see GraphTraversal#bothE(String...)
      */
@@ -194,6 +251,13 @@ public class __ {
         return __.<Vertex>start().bothE(edgeLabels);
     }
 
+    /**
+     * @see GraphTraversal#bothE(GValue, GValue...)
+     */
+    public static GraphTraversal<Vertex, Edge> bothE(final GValue<String> edgeLabel, final GValue<String>... edgeLabels) {
+        return __.<Vertex>start().bothE(edgeLabel, edgeLabels);
+    }
+
     /**
      * @see GraphTraversal#toV(Direction)
      */
@@ -512,6 +576,13 @@ public class __ {
         return __.<A>start().addV(vertexLabel);
     }
 
+    /**
+     * @see GraphTraversal#addV(GValue)
+     */
+    public static <A> GraphTraversal<A, Vertex> addV(final GValue<String> vertexLabel) {
+        return __.<A>start().addV(vertexLabel);
+    }
+
     /**
      * @see GraphTraversal#addV(org.apache.tinkerpop.gremlin.process.traversal.Traversal)
      */
@@ -540,6 +611,13 @@ public class __ {
         return __.<A>start().mergeV(searchCreate);
     }
 
+    /**
+     * @see GraphTraversal#mergeV(GValue)
+     */
+    public static <A> GraphTraversal<A, Vertex> mergeV(final GValue<Map<Object, Object>> searchCreate) {
+        return __.<A>start().mergeV(searchCreate);
+    }
+
     /**
      * @see GraphTraversal#mergeV(Traversal)
      */
@@ -554,6 +632,13 @@ public class __ {
         return __.<A>start().addE(edgeLabel);
     }
 
+    /**
+     * @see GraphTraversal#addE(GValue)
+     */
+    public static <A> GraphTraversal<A, Edge> addE(final GValue<String> edgeLabel) {
+        return __.<A>start().addE(edgeLabel);
+    }
+
     /**
      * @see GraphTraversal#addE(Traversal)
      */
@@ -575,6 +660,13 @@ public class __ {
         return __.<A>start().mergeE(searchCreate);
     }
 
+    /**
+     * @see GraphTraversal#mergeE(GValue)
+     */
+    public static <A> GraphTraversal<A, Edge> mergeE(final GValue<Map<Object, Object>> searchCreate) {
+        return __.<A>start().mergeE(searchCreate);
+    }
+
     /**
      * @see GraphTraversal#mergeE(Traversal)
      */
@@ -934,6 +1026,13 @@ public class __ {
         return __.<A>start().has(label, propertyKey, value);
     }
 
+    /**
+     * @see GraphTraversal#has(GValue, String, Object)
+     */
+    public static <A> GraphTraversal<A, A> has(final GValue<String> label, final String propertyKey, final Object value) {
+        return __.<A>start().has(label, propertyKey, value);
+    }
+
     /**
      * @see GraphTraversal#has(String, String, P)
      */
@@ -976,6 +1075,13 @@ public class __ {
         return __.<A>start().hasLabel(label, otherLabels);
     }
 
+    /**
+     * @see GraphTraversal#hasLabel(GValue, GValue...)
+     */
+    public static <A> GraphTraversal<A, A> hasLabel(final GValue<String> label, GValue<String>... otherLabels) {
+        return __.<A>start().hasLabel(label, otherLabels);
+    }
+
     /**
      * @see GraphTraversal#hasLabel(P)
      */
@@ -1074,6 +1180,13 @@ public class __ {
         return __.<A>start().coin(probability);
     }
 
+    /**
+     * @see GraphTraversal#coin(GValue)
+     */
+    public static <A> GraphTraversal<A, A> coin(final GValue<Double> probability) {
+        return __.<A>start().coin(probability);
+    }
+
     /**
      * @see GraphTraversal#range(long, long)
      */
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 5af5109ac6..5b50c64cad 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
@@ -34,6 +34,7 @@ import java.util.Map;
 import java.util.Objects;
 import java.util.Optional;
 import java.util.Set;
+import java.util.stream.Stream;
 
 /**
  * A {@code GValue} is a variable or literal value that is used in a {@link Traversal}. It is composed of a key-value
@@ -57,6 +58,47 @@ public class GValue<V> implements Cloneable, Serializable {
         this.value = value;
     }
 
+    /**
+     * 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.
+     */
+    public static <T> GValue<T>[] convertToGValues(final Object[] args) {
+        return Stream.of(args).map(id -> {
+            if (id instanceof GValue)
+                return (GValue<?>) id;
+            else
+                return 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.
+     */
+    public static 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.
+     */
+    public static 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;
+    }
+
     /**
      * Determines if the value held by this object was defined as a variable or a literal value. Literal values simply
      * have no name.
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 f22683fd14..d6f66f20f4 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
@@ -70,13 +70,13 @@ public class GraphStep<S, E extends Element> extends AbstractStep<S, E> implemen
         this.returnClass = returnClass;
 
         // if ids is a single collection like g.V(['a','b','c']), then unroll it into an array of ids
-        this.ids = convertToGValues(tryUnrollSingleCollectionArgument(ids));
+        this.ids = GValue.convertToGValues(tryUnrollSingleCollectionArgument(ids));
 
         this.isStart = isStart;
 
         this.iteratorSupplier = () -> (Iterator<E>) (Vertex.class.isAssignableFrom(this.returnClass) ?
-                this.getTraversal().getGraph().get().vertices(resolveToValues(this.ids)) :
-                this.getTraversal().getGraph().get().edges(resolveToValues(this.ids)));
+                this.getTraversal().getGraph().get().vertices(GValue.resolveToValues(this.ids)) :
+                this.getTraversal().getGraph().get().edges(GValue.resolveToValues(this.ids)));
     }
 
     /**
@@ -148,7 +148,7 @@ public class GraphStep<S, E extends Element> extends AbstractStep<S, E> implemen
 
     public Object[] getIds() {
         if (legacyLogicForPassingNoIds) return null;
-        return resolveToValues(this.ids);
+        return GValue.resolveToValues(this.ids);
     }
 
     public void addIds(final Object... newIds) {
@@ -162,7 +162,7 @@ public class GraphStep<S, E extends Element> extends AbstractStep<S, E> implemen
         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));
+        final GValue[] gvalues = GValue.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/map/VertexStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/VertexStep.java
index e27fbb3802..896934668d 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/VertexStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/VertexStep.java
@@ -54,24 +54,14 @@ public class VertexStep<E extends Element> extends FlatMapStep<Vertex, E> implem
     private final Class<E> returnClass;
 
     public VertexStep(final Traversal.Admin traversal, final Class<E> returnClass, final Direction direction, final String... edgeLabels) {
-        this(traversal, returnClass, direction, (Object[]) edgeLabels);
+        this(traversal, returnClass, direction, GValue.convertToGValues(edgeLabels));
     }
 
-    public VertexStep(final Traversal.Admin traversal, final Class<E> returnClass, final Direction direction, final Object... edgeLabels) {
+    public VertexStep(final Traversal.Admin traversal, final Class<E> returnClass, final Direction direction, final GValue<String>... edgeLabels) {
         super(traversal);
         this.direction = direction;
         this.returnClass = returnClass;
-
-        // check each edgeLabel to ensure it is a string or a GValue with a GType.STRING in it. if it is just a string
-        // then convert edgeLabels to a GValue<String> or otherwise throw an exception
-        this.edgeLabelsGValue = Arrays.stream(edgeLabels).map(edgeLabel -> {
-            if (edgeLabel instanceof String)
-                return GValue.ofString((String) edgeLabel);
-            else if (edgeLabel instanceof GValue && ((GValue<String>) edgeLabel).get().getClass().equals(String.class))
-                return (GValue<String>) edgeLabel;
-            else
-                throw new IllegalArgumentException("All edge labels must be strings");
-        }).toArray(GValue[]::new);
+        this.edgeLabelsGValue = edgeLabels;
 
         // convert the GValue<String> to a String[] for the edgeLabels field to cache the values
         this.edgeLabels = Arrays.stream(this.edgeLabelsGValue).map(GValue::get).toArray(String[]::new);
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 627f0f7b79..f3cdcdafbc 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
@@ -32,28 +32,28 @@ public final class InjectStep<S> extends StartStep<S> {
     @SafeVarargs
     public InjectStep(final Traversal.Admin traversal, final S... injections) {
         super(traversal);
-        this.injections = convertToGValues(injections);
-        this.start = new ArrayIterator<>(resolveToValues(this.injections));
+        this.injections = GValue.convertToGValues(injections);
+        this.start = new ArrayIterator<>(GValue.resolveToValues(this.injections));
     }
 
     @Override
     public InjectStep<S> clone() {
         final InjectStep<S> clone = (InjectStep<S>) super.clone();
-        clone.start = new ArrayIterator<>(resolveToValues(clone.injections));
+        clone.start = new ArrayIterator<>(GValue.resolveToValues(clone.injections));
         return clone;
     }
 
     @Override
     public void reset() {
         super.reset();
-        this.start = new ArrayIterator<>(resolveToValues(this.injections));
+        this.start = new ArrayIterator<>(GValue.resolveToValues(this.injections));
     }
 
     /**
      * Get the injections of the step.
      */
     public S[] getInjections() {
-        return (S[]) resolveToValues(injections);
+        return (S[]) GValue.resolveToValues(injections);
     }
 
     public GValue<S>[] getInjectionsGValue() {
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 94c5866b14..72f03b5a95 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,7 +21,6 @@ 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;
@@ -31,11 +30,9 @@ 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)
@@ -231,45 +228,4 @@ 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/strategy/optimization/InlineFilterStrategy.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/InlineFilterStrategy.java
index 5ff63b3e0f..c0903c0783 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/InlineFilterStrategy.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/InlineFilterStrategy.java
@@ -161,7 +161,7 @@ public final class InlineFilterStrategy extends AbstractTraversalStrategy<Traver
                 }
             }
             if (!edgeLabels.isEmpty()) {
-                final VertexStep<Edge> newVertexStep = new VertexStep<>(traversal, Edge.class, previousStep.getDirection(), edgeLabels.toArray(new Object[edgeLabels.size()]));
+                final VertexStep<Edge> newVertexStep = new VertexStep<>(traversal, Edge.class, previousStep.getDirection(), GValue.convertToGValues(edgeLabels.toArray()));
                 TraversalHelper.replaceStep(previousStep, newVertexStep, traversal);
                 TraversalHelper.copyLabels(previousStep, newVertexStep, false);
                 if (step.getHasContainers().isEmpty()) {
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/CollectionUtil.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/CollectionUtil.java
index 1242d16af7..61d9d7573d 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/CollectionUtil.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/CollectionUtil.java
@@ -19,6 +19,9 @@
 
 package org.apache.tinkerpop.gremlin.util;
 
+import org.apache.commons.lang3.ArrayUtils;
+
+import java.lang.reflect.Array;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
@@ -74,4 +77,22 @@ public final class CollectionUtil {
 
         return result;
     }
+
+    /**
+     * Adds the element argument to the start of the supplied array argument, but if the array is null then return the
+     * element as a new array with just that item in it.
+     */
+    public static <T> T[] addFirst(final T[] array, final T element, final Class<T> clazz) {
+        if (null == array && null == element) {
+            final T[] singleElementArray = (T[]) Array.newInstance(clazz, 1);
+            singleElementArray[0] = null;
+            return singleElementArray;
+        } else if (null == array) {
+            final T[] singleElementArray = (T[]) Array.newInstance(clazz, 1);
+            singleElementArray[0] = element;
+            return singleElementArray;
+        } else {
+            return ArrayUtils.addFirst(array, element);
+        }
+    }
 }
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/translator/DotNetTranslatorTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/translator/DotNetTranslatorTest.java
index 21f8f2e457..05b0365ee4 100644
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/translator/DotNetTranslatorTest.java
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/translator/DotNetTranslatorTest.java
@@ -184,7 +184,7 @@ public class DotNetTranslatorTest {
     public void shouldTranslateHasLabelNull() {
         String script = translator.translate(g.V().hasLabel(null).asAdmin().getBytecode()).getScript();
         assertEquals("g.V().HasLabel((string) null)", script);
-        script = translator.translate(g.V().hasLabel(null, null).asAdmin().getBytecode()).getScript();
+        script = translator.translate(g.V().hasLabel((String) null, null).asAdmin().getBytecode()).getScript();
         assertEquals("g.V().HasLabel(null,null)", script);
         script = translator.translate(g.V().hasLabel(null, "person").asAdmin().getBytecode()).getScript();
         assertEquals("g.V().HasLabel(null,\"person\")", script);