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

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

commit 02fbda155c27dea12225fd98b148399fdb46147f
Author: Stephen Mallette <[email protected]>
AuthorDate: Sun Aug 18 13:55:46 2024 -0400

    wip
---
 .../tinkerpop/gremlin/jsr223/JavaTranslator.java   |   6 +
 .../strategy/decoration/VertexProgramStrategy.java |   1 +
 .../gremlin/process/traversal/Bytecode.java        |   8 +-
 .../process/traversal/TraversalStrategies.java     |   2 +
 .../traversal/dsl/graph/GraphTraversal.java        | 280 ++++++++++++-
 .../traversal/dsl/graph/GraphTraversalSource.java  |  68 +++-
 .../ConstantGVTraversal.java}                      |  42 +-
 .../process/traversal/step/filter/HasStep.java     |   3 +-
 .../process/traversal/step/filter/IsStep.java      |   3 +-
 .../process/traversal/step/map/ConstantStep.java   |   7 +-
 .../process/traversal/step/map/GraphStep.java      |   4 +-
 .../process/traversal/step/map/MergeStep.java      |   7 +-
 .../traversal/step/map/MergeVertexStep.java        |   1 +
 .../traversal/step/sideEffect/AddPropertyStep.java |   4 +-
 .../traversal/step/sideEffect/InjectStep.java      |   3 +-
 .../gremlin/process/traversal/step/util/GType.java |  95 +++++
 .../process/traversal/step/util/GValue.java        | 443 +++++++++++++++++++++
 .../process/traversal/step/util/GValueStep.java    |  93 +++++
 .../process/traversal/step/util/HasContainer.java  |   4 +
 .../step/util/structure/filter/HasStepGV.java      |  74 ++++
 .../util/structure/filter/HasStepStructure.java    |  25 ++
 .../structure/filter/IsStepGV.java}                |  38 +-
 .../util/structure/filter/IsStepStructure.java     |  25 ++
 .../step/util/structure/map/AddEdgeStepGV.java     |  59 +++
 .../util/structure/map/AddEdgeStepStructure.java   |  27 ++
 .../structure/map/ConstantStepGV.java}             |  37 +-
 .../util/structure/map/ConstantStepStructure.java  |  23 ++
 .../step/util/structure/map/GraphStepGV.java       |  62 +++
 .../util/structure/map/GraphStepStructure.java     |  28 ++
 .../step/util/structure/map/MergeEdgeStepGV.java   |  94 +++++
 .../structure/map/MergeElementStepStructure.java   |  44 ++
 .../step/util/structure/map/MergeVertexStepGV.java |  95 +++++
 .../step/util/structure/map/VertexStepGV.java      |  67 ++++
 .../util/structure/map/VertexStepStructure.java    |  30 ++
 .../structure/sideEffect/AddPropertyStepGV.java    |  54 +++
 .../sideEffect/AddPropertyStepStructure.java       |  28 ++
 .../structure/sideEffect/InjectStepGV.java}        |  38 +-
 .../structure/sideEffect/InjectStepStructure.java  |  23 ++
 .../strategy/decoration/ConnectiveStrategy.java    |   1 -
 .../decoration/GValueReplacementStrategy.java      |  97 +++++
 .../process/traversal/util/TraversalHelper.java    |  40 +-
 .../apache/tinkerpop/gremlin/util/ArrayUtil.java   |  42 ++
 42 files changed, 1980 insertions(+), 145 deletions(-)

diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/JavaTranslator.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/JavaTranslator.java
index 1641d823bc..09e5818933 100644
--- 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/JavaTranslator.java
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/JavaTranslator.java
@@ -28,6 +28,7 @@ import 
org.apache.tinkerpop.gremlin.process.traversal.TraversalSource;
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal;
 import 
org.apache.tinkerpop.gremlin.process.traversal.lambda.CardinalityValueTraversal;
 import org.apache.tinkerpop.gremlin.process.traversal.step.util.BulkSet;
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.GValue;
 import org.apache.tinkerpop.gremlin.process.traversal.step.util.Tree;
 import 
org.apache.tinkerpop.gremlin.process.traversal.strategy.TraversalStrategyProxy;
 import org.apache.tinkerpop.gremlin.process.traversal.util.BytecodeHelper;
@@ -38,6 +39,7 @@ import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.lang.reflect.Parameter;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.LinkedHashMap;
@@ -336,6 +338,10 @@ public final class JavaTranslator<S extends 
TraversalSource, T extends Traversal
     private synchronized static void buildMethodCache(final Object delegate, 
final Map<String, List<ReflectedMethod>> methodCache) {
         if (methodCache.isEmpty()) {
             for (final Method method : delegate.getClass().getMethods()) {
+                // skip any methods that use GValue as it can't be used 
remotely or be translated
+                if (Arrays.stream(method.getParameters()).anyMatch(p -> 
p.getType().equals(GValue.class))) {
+                    continue;
+                }
                 final List<ReflectedMethod> list = 
methodCache.computeIfAbsent(method.getName(), k -> new ArrayList<>());
                 list.add(new ReflectedMethod(method));
             }
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/strategy/decoration/VertexProgramStrategy.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/strategy/decoration/VertexProgramStrategy.java
index 7d920ab2f7..e8be03157f 100644
--- 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/strategy/decoration/VertexProgramStrategy.java
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/strategy/decoration/VertexProgramStrategy.java
@@ -44,6 +44,7 @@ import org.apache.tinkerpop.gremlin.structure.Edge;
 import org.apache.tinkerpop.gremlin.structure.Vertex;
 import org.apache.tinkerpop.gremlin.util.iterator.IteratorUtils;
 
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Bytecode.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Bytecode.java
index 5b88cea5fc..a5e5551857 100644
--- 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Bytecode.java
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Bytecode.java
@@ -19,6 +19,7 @@
 
 package org.apache.tinkerpop.gremlin.process.traversal;
 
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.GValue;
 import 
org.apache.tinkerpop.gremlin.process.traversal.strategy.TraversalStrategyProxy;
 import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
 import org.apache.tinkerpop.gremlin.util.iterator.IteratorUtils;
@@ -295,7 +296,12 @@ public class Bytecode implements Cloneable, Serializable {
             if (null != variable)
                 return new Binding<>(variable, convertArgument(argument, 
false));
         }
-        //
+
+        // a GValue gets converted to its value because we don't serialize it. 
it really doesn't have anything to do
+        // with bytecode/remoting. it's an internal construct related to 
parsing with the grammar that is leaking
+        // over here. in 4.x with bytecode removed, we won't need to worry 
about this.
+        if (argument instanceof GValue)
+            return convertArgument(((GValue) argument).get(), false);
         if (argument instanceof Traversal) {
             // prevent use of "g" to spawn child traversals
             if (((Traversal) 
argument).asAdmin().getTraversalSource().isPresent())
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TraversalStrategies.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TraversalStrategies.java
index fc97198ac6..fe4ece057a 100644
--- 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TraversalStrategies.java
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TraversalStrategies.java
@@ -23,6 +23,7 @@ import 
org.apache.tinkerpop.gremlin.process.computer.traversal.strategy.finaliza
 import 
org.apache.tinkerpop.gremlin.process.computer.traversal.strategy.optimization.GraphFilterStrategy;
 import 
org.apache.tinkerpop.gremlin.process.computer.traversal.strategy.optimization.MessagePassingReductionStrategy;
 import 
org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.ConnectiveStrategy;
+import 
org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.GValueReplacementStrategy;
 import 
org.apache.tinkerpop.gremlin.process.traversal.strategy.finalization.ProfileStrategy;
 import 
org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.AdjacentToIncidentStrategy;
 import 
org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.CountStrategy;
@@ -217,6 +218,7 @@ public interface TraversalStrategies extends Serializable, 
Cloneable, Iterable<T
         static {
             final TraversalStrategies graphStrategies = new 
DefaultTraversalStrategies();
             graphStrategies.addStrategies(
+                    GValueReplacementStrategy.instance(),
                     IdentityRemovalStrategy.instance(),
                     ConnectiveStrategy.instance(),
                     EarlyLimitStrategy.instance(),
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 f01afa8197..a917dd76b7 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
@@ -18,6 +18,7 @@
  */
 package org.apache.tinkerpop.gremlin.process.traversal.dsl.graph;
 
+import org.apache.commons.lang3.ArrayUtils;
 import org.apache.tinkerpop.gremlin.process.computer.VertexProgram;
 import 
org.apache.tinkerpop.gremlin.process.computer.clustering.connected.ConnectedComponentVertexProgram;
 import 
org.apache.tinkerpop.gremlin.process.computer.traversal.step.map.ConnectedComponentVertexProgramStep;
@@ -39,6 +40,7 @@ import 
org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
 import 
org.apache.tinkerpop.gremlin.process.traversal.lambda.CardinalityValueTraversal;
 import org.apache.tinkerpop.gremlin.process.traversal.lambda.ColumnTraversal;
+import 
org.apache.tinkerpop.gremlin.process.traversal.lambda.ConstantGVTraversal;
 import org.apache.tinkerpop.gremlin.process.traversal.lambda.ConstantTraversal;
 import org.apache.tinkerpop.gremlin.process.traversal.lambda.FunctionTraverser;
 import org.apache.tinkerpop.gremlin.process.traversal.lambda.LoopTraversal;
@@ -126,6 +128,7 @@ import 
org.apache.tinkerpop.gremlin.process.traversal.step.map.MaxLocalStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.MeanGlobalStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.MeanLocalStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.MergeEdgeStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.MergeStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.MergeVertexStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.MinGlobalStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.MinLocalStep;
@@ -186,9 +189,20 @@ import 
org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.AggregateL
 import 
org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.SubgraphStep;
 import 
org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.TraversalSideEffectStep;
 import 
org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.TreeSideEffectStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.GValue;
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.GValueStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.util.HasContainer;
 import org.apache.tinkerpop.gremlin.process.traversal.step.util.Tree;
 import org.apache.tinkerpop.gremlin.process.traversal.step.util.WithOptions;
+import 
org.apache.tinkerpop.gremlin.process.traversal.step.util.structure.filter.IsStepGV;
+import 
org.apache.tinkerpop.gremlin.process.traversal.step.util.structure.map.ConstantStepGV;
+import 
org.apache.tinkerpop.gremlin.process.traversal.step.util.structure.map.GraphStepGV;
+import 
org.apache.tinkerpop.gremlin.process.traversal.step.util.structure.map.MergeEdgeStepGV;
+import 
org.apache.tinkerpop.gremlin.process.traversal.step.util.structure.map.MergeElementStepStructure;
+import 
org.apache.tinkerpop.gremlin.process.traversal.step.util.structure.map.MergeVertexStepGV;
+import 
org.apache.tinkerpop.gremlin.process.traversal.step.util.structure.map.VertexStepGV;
+import 
org.apache.tinkerpop.gremlin.process.traversal.step.util.structure.sideEffect.AddPropertyStepGV;
+import 
org.apache.tinkerpop.gremlin.process.traversal.step.util.structure.sideEffect.InjectStepGV;
 import 
org.apache.tinkerpop.gremlin.process.traversal.traverser.util.TraverserSet;
 import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper;
 import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalMetrics;
@@ -231,6 +245,208 @@ public interface GraphTraversal<S, E> extends 
Traversal<S, E> {
 
     public interface Admin<S, E> extends Traversal.Admin<S, E>, 
GraphTraversal<S, 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 GValue<String> edgeLabel, final GValue<String>... edgeLabels) {
+            this.asAdmin().getBytecode().addStep(GraphTraversal.Symbols.to, 
direction, edgeLabels);
+            return this.asAdmin().addStep(new VertexStepGV<>(this.asAdmin(), 
Vertex.class, direction, ArrayUtils.addFirst(edgeLabels, edgeLabel)));
+        }
+
+        /**
+         * 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> 
edgeLabel, final GValue<String>... edgeLabels) {
+            this.asAdmin().getBytecode().addStep(GraphTraversal.Symbols.out, 
edgeLabels);
+            return this.asAdmin().addStep(new VertexStepGV<>(this.asAdmin(), 
Vertex.class, Direction.OUT, ArrayUtils.addFirst(edgeLabels, edgeLabel)));
+        }
+
+        /**
+         * 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 GValue<String> 
edgeLabel, final GValue<String>... edgeLabels) {
+            this.asAdmin().getBytecode().addStep(GraphTraversal.Symbols.in, 
edgeLabels);
+            return this.asAdmin().addStep(new VertexStepGV<>(this.asAdmin(), 
Vertex.class, Direction.IN, ArrayUtils.addFirst(edgeLabels, edgeLabel)));
+        }
+
+        /**
+         * 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 GValue<String> 
edgeLabel, final GValue<String>... edgeLabels) {
+            this.asAdmin().getBytecode().addStep(GraphTraversal.Symbols.both, 
edgeLabels);
+            return this.asAdmin().addStep(new VertexStepGV<>(this.asAdmin(), 
Vertex.class, Direction.BOTH, ArrayUtils.addFirst(edgeLabels, edgeLabel)));
+        }
+
+        /**
+         * 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 GValue<String> edgeLabel, final GValue<String>... edgeLabels) {
+            this.asAdmin().getBytecode().addStep(GraphTraversal.Symbols.toE, 
direction, edgeLabels);
+            return this.asAdmin().addStep(new VertexStepGV<>(this.asAdmin(), 
Edge.class, direction, ArrayUtils.addFirst(edgeLabels, edgeLabel)));
+        }
+
+        /**
+         * 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 GValue<String> 
edgeLabel, final GValue<String>... edgeLabels) {
+            this.asAdmin().getBytecode().addStep(GraphTraversal.Symbols.outE, 
edgeLabels);
+            return this.asAdmin().addStep(new VertexStepGV<>(this.asAdmin(), 
Edge.class, Direction.OUT, ArrayUtils.addFirst(edgeLabels, edgeLabel)));
+        }
+
+        /**
+         * 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 GValue<String> 
edgeLabel, final GValue<String>... edgeLabels) {
+            this.asAdmin().getBytecode().addStep(GraphTraversal.Symbols.inE, 
edgeLabels);
+            return this.asAdmin().addStep(new VertexStepGV<>(this.asAdmin(), 
Edge.class, Direction.IN, ArrayUtils.addFirst(edgeLabels, edgeLabel)));
+        }
+
+        /**
+         * 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 GValue<String> 
edgeLabel, final GValue<String>... edgeLabels) {
+            this.asAdmin().getBytecode().addStep(GraphTraversal.Symbols.bothE, 
edgeLabels);
+            return this.asAdmin().addStep(new VertexStepGV<>(this.asAdmin(), 
Edge.class, Direction.BOTH, ArrayUtils.addFirst(edgeLabels, edgeLabel)));
+        }
+
+        /**
+         * 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.6.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 MergeEdgeStepGV<S> step = new 
MergeEdgeStepGV(this.asAdmin(), false, searchCreate);
+            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 3.6.0
+         */
+        public default GraphTraversal<S, Vertex> mergeV(final 
GValue<Map<Object, Object>> searchCreate) {
+            
this.asAdmin().getBytecode().addStep(GraphTraversal.Symbols.mergeV, 
searchCreate);
+            final MergeVertexStepGV step = new 
MergeVertexStepGV(this.asAdmin(), false, searchCreate);
+            return this.asAdmin().addStep(step);
+        }
+
+        /**
+         * 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.6.0
+         */
+        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);
+
+            // handle case where the MergeStep was added instead of a 
MergeVertexStepGV. in this case, mergeV/E was
+            // called such that it did not have a GValue so a standard step 
was added. leave it ot hte
+            // GValueReplacementStrategy to resolve this
+            final Step endStep = this.asAdmin().getEndStep();
+            if (endStep instanceof MergeStep) {
+                this.asAdmin().addStep(new 
GValueStep.MergeOptionStep(this.asAdmin(), (Merge) token, 
GValue.of(m.getName(), m)));
+            } else {
+                ((TraversalOptionParent<M, E, E2>) 
this.asAdmin().getEndStep()).addChildOption(token, (Traversal.Admin<E, E2>) new 
ConstantGVTraversal<>(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.0
+         */
+        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);
+            // do explicit cardinality for every single pair in the map
+            final Map<Object,Object> m1 = m.get();
+            for (Object k : m1.keySet()) {
+                final Object o = m1.get(k);
+                if (!(o instanceof CardinalityValueTraversal))
+                    m1.put(k, new CardinalityValueTraversal(cardinality, o));
+            }
+
+            // handle case where the MergeStep was added instead of a 
MergeVertexStepGV. in this case, mergeV/E was
+            // called such that it did not have a GValue so a standard step 
was added. leave it ot hte
+            // GValueReplacementStrategy to resolve this
+            final Step endStep = this.asAdmin().getEndStep();
+            if (endStep instanceof MergeStep) {
+                this.asAdmin().addStep(new 
GValueStep.MergeOptionStep(this.asAdmin(), merge, GValue.of(m.getName(), m1)));
+            } else {
+                ((TraversalOptionParent<M, E, E2>) 
this.asAdmin().getEndStep()).addChildOption((M) merge, (Traversal.Admin<E, E2>) 
new ConstantGVTraversal<>(m).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);
@@ -352,7 +568,12 @@ public interface GraphTraversal<S, E> extends Traversal<S, 
E> {
      */
     public default <E2> GraphTraversal<S, E2> constant(final E2 e) {
         this.asAdmin().getBytecode().addStep(Symbols.constant, e);
-        return this.asAdmin().addStep(new ConstantStep<E, E2>(this.asAdmin(), 
e));
+
+        if (e instanceof GValue) {
+            return this.asAdmin().addStep(new ConstantStepGV<>(this.asAdmin(), 
(GValue) e));
+        } else {
+            return this.asAdmin().addStep(new ConstantStep<E, 
E2>(this.asAdmin(), e));
+        }
     }
 
     /**
@@ -367,7 +588,12 @@ public interface GraphTraversal<S, E> extends Traversal<S, 
E> {
         // a single null is [null]
         final Object[] ids = null == vertexIdsOrElements ? new Object[] { null 
} : vertexIdsOrElements;
         this.asAdmin().getBytecode().addStep(Symbols.V, ids);
-        return this.asAdmin().addStep(new GraphStep<>(this.asAdmin(), 
Vertex.class, false, ids));
+
+        if (GValue.hasGValue(ids)) {
+            return this.asAdmin().addStep(new GraphStepGV<>(this.asAdmin(), 
Vertex.class, false, GValue.promoteGValues(ids)));
+        } else {
+            return this.asAdmin().addStep(new GraphStep<>(this.asAdmin(), 
Vertex.class, false, ids));
+        }
     }
 
     /**
@@ -382,7 +608,12 @@ public interface GraphTraversal<S, E> extends Traversal<S, 
E> {
         // a single null is [null]
         final Object[] ids = null == edgeIdsOrElements ? new Object[] { null } 
: edgeIdsOrElements;
         this.asAdmin().getBytecode().addStep(Symbols.E, ids);
-        return this.asAdmin().addStep(new GraphStep<>(this.asAdmin(), 
Edge.class, false, ids));
+
+        if (GValue.hasGValue(ids)) {
+            return this.asAdmin().addStep(new GraphStepGV<>(this.asAdmin(), 
Edge.class, false, GValue.promoteGValues(ids)));
+        } else {
+            return this.asAdmin().addStep(new GraphStep<>(this.asAdmin(), 
Edge.class, false, ids));
+        }
     }
 
     /**
@@ -772,11 +1003,8 @@ public interface GraphTraversal<S, E> extends 
Traversal<S, E> {
      * @since 3.2.0-incubating
      */
     public default <E2> GraphTraversal<S, Map<String, E2>> project(final 
String projectKey, final String... otherProjectKeys) {
-        final String[] projectKeys = new String[otherProjectKeys.length + 1];
-        projectKeys[0] = projectKey;
-        System.arraycopy(otherProjectKeys, 0, projectKeys, 1, 
otherProjectKeys.length);
         this.asAdmin().getBytecode().addStep(Symbols.project, projectKey, 
otherProjectKeys);
-        return this.asAdmin().addStep(new ProjectStep<>(this.asAdmin(), 
projectKeys));
+        return this.asAdmin().addStep(new ProjectStep<>(this.asAdmin(), 
ArrayUtils.addFirst(otherProjectKeys, projectKey)));
     }
 
     /**
@@ -792,12 +1020,10 @@ public interface GraphTraversal<S, E> extends 
Traversal<S, E> {
      * @since 3.0.0-incubating
      */
     public default <E2> GraphTraversal<S, Map<String, E2>> select(final Pop 
pop, final String selectKey1, final String selectKey2, String... 
otherSelectKeys) {
-        final String[] selectKeys = new String[otherSelectKeys.length + 2];
-        selectKeys[0] = selectKey1;
-        selectKeys[1] = selectKey2;
-        System.arraycopy(otherSelectKeys, 0, selectKeys, 2, 
otherSelectKeys.length);
+        String[] args = ArrayUtils.addFirst(otherSelectKeys, selectKey2);
+        args = ArrayUtils.addFirst(args, selectKey1);
         this.asAdmin().getBytecode().addStep(Symbols.select, pop, selectKey1, 
selectKey2, otherSelectKeys);
-        return this.asAdmin().addStep(new SelectStep<>(this.asAdmin(), pop, 
selectKeys));
+        return this.asAdmin().addStep(new SelectStep<>(this.asAdmin(), pop, 
args));
     }
 
     /**
@@ -812,12 +1038,10 @@ public interface GraphTraversal<S, E> extends 
Traversal<S, E> {
      * @since 3.0.0-incubating
      */
     public default <E2> GraphTraversal<S, Map<String, E2>> select(final String 
selectKey1, final String selectKey2, String... otherSelectKeys) {
-        final String[] selectKeys = new String[otherSelectKeys.length + 2];
-        selectKeys[0] = selectKey1;
-        selectKeys[1] = selectKey2;
-        System.arraycopy(otherSelectKeys, 0, selectKeys, 2, 
otherSelectKeys.length);
+        String[] args = ArrayUtils.addFirst(otherSelectKeys, selectKey2);
+        args = ArrayUtils.addFirst(args, selectKey1);
         this.asAdmin().getBytecode().addStep(Symbols.select, selectKey1, 
selectKey2, otherSelectKeys);
-        return this.asAdmin().addStep(new SelectStep<>(this.asAdmin(), 
Pop.last, selectKeys));
+        return this.asAdmin().addStep(new SelectStep<>(this.asAdmin(), 
Pop.last, args));
     }
 
     /**
@@ -2051,7 +2275,10 @@ public interface GraphTraversal<S, E> extends 
Traversal<S, E> {
         // a single null is [null]
         final E[] s = null == injections ? (E[]) new Object[] { null } : 
injections;
         this.asAdmin().getBytecode().addStep(Symbols.inject, s);
-        return this.asAdmin().addStep(new InjectStep<>(this.asAdmin(), s));
+        if (GValue.hasGValue(s))
+            return this.asAdmin().addStep(new InjectStepGV<>(this.asAdmin(), 
GValue.promoteGValues(s)));
+        else
+            return this.asAdmin().addStep(new InjectStep<>(this.asAdmin(), s));
     }
 
     /**
@@ -2539,7 +2766,10 @@ public interface GraphTraversal<S, E> extends 
Traversal<S, E> {
      */
     public default GraphTraversal<S, E> is(final P<E> predicate) {
         this.asAdmin().getBytecode().addStep(Symbols.is, predicate);
-        return this.asAdmin().addStep(new IsStep<>(this.asAdmin(), predicate));
+        if (GValue.hasGValueInP(predicate))
+            return this.asAdmin().addStep(new IsStepGV<>(this.asAdmin(), 
predicate));
+        else
+            return this.asAdmin().addStep(new IsStep<>(this.asAdmin(), 
predicate));
     }
 
     /**
@@ -3123,9 +3353,15 @@ public interface GraphTraversal<S, E> extends 
Traversal<S, E> {
                   (key instanceof T || (key instanceof String && null == 
cardinality) || key instanceof Traversal))) {
             ((Mutating) endStep).configure(key, value);
         } else {
-            final AddPropertyStep<Element> addPropertyStep = new 
AddPropertyStep<>(this.asAdmin(), cardinality, key, value);
-            this.asAdmin().addStep(addPropertyStep);
-            addPropertyStep.configure(keyValues);
+            if (value instanceof GValue || GValue.hasGValue(keyValues)) {
+                final AddPropertyStepGV addPropertyStep = new 
AddPropertyStepGV(this.asAdmin(), cardinality, key, GValue.of(value));
+                this.asAdmin().addStep(addPropertyStep);
+                addPropertyStep.configure(keyValues);
+            } else {
+                final AddPropertyStep<Element> addPropertyStep = new 
AddPropertyStep<>(this.asAdmin(), cardinality, key, value);
+                this.asAdmin().addStep(addPropertyStep);
+                addPropertyStep.configure(keyValues);
+            }
         }
         return this;
     }
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..4a4ecfc115 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
@@ -36,6 +36,11 @@ import 
org.apache.tinkerpop.gremlin.process.traversal.step.map.MergeEdgeStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.MergeVertexStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.IoStep;
 import 
org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.InjectStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.GValue;
+import 
org.apache.tinkerpop.gremlin.process.traversal.step.util.structure.map.GraphStepGV;
+import 
org.apache.tinkerpop.gremlin.process.traversal.step.util.structure.map.MergeEdgeStepGV;
+import 
org.apache.tinkerpop.gremlin.process.traversal.step.util.structure.map.MergeVertexStepGV;
+import 
org.apache.tinkerpop.gremlin.process.traversal.step.util.structure.sideEffect.InjectStepGV;
 import 
org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.RequirementsStrategy;
 import 
org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
 import org.apache.tinkerpop.gremlin.structure.Direction;
@@ -68,6 +73,7 @@ public class GraphTraversalSource implements TraversalSource {
     protected final Graph graph;
     protected TraversalStrategies strategies;
     protected Bytecode bytecode = new Bytecode();
+    protected Admin admin;
 
     ////////////////
 
@@ -100,6 +106,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);
@@ -447,7 +459,12 @@ public class GraphTraversalSource implements 
TraversalSource {
         final GraphTraversalSource clone = this.clone();
         clone.bytecode.addStep(GraphTraversal.Symbols.inject, s);
         final GraphTraversal.Admin<S, S> traversal = new 
DefaultGraphTraversal<>(clone);
-        return traversal.addStep(new InjectStep<S>(traversal, s));
+
+        if (GValue.hasGValue(s)) {
+            return traversal.addStep(new InjectStepGV<S>(traversal, 
GValue.promoteGValues(s)));
+        } else {
+            return traversal.addStep(new InjectStep<>(traversal, s));
+        }
     }
 
     /**
@@ -462,7 +479,12 @@ public class GraphTraversalSource implements 
TraversalSource {
         final GraphTraversalSource clone = this.clone();
         clone.bytecode.addStep(GraphTraversal.Symbols.V, ids);
         final GraphTraversal.Admin<Vertex, Vertex> traversal = new 
DefaultGraphTraversal<>(clone);
-        return traversal.addStep(new GraphStep<>(traversal, Vertex.class, 
true, ids));
+
+        if (GValue.hasGValue(ids)) {
+            return traversal.addStep(new GraphStepGV<>(traversal, 
Vertex.class, true, GValue.promoteGValues(ids)));
+        } else {
+            return traversal.addStep(new GraphStep<>(traversal, Vertex.class, 
true, ids));
+        }
     }
 
     /**
@@ -477,7 +499,12 @@ public class GraphTraversalSource implements 
TraversalSource {
         final GraphTraversalSource clone = this.clone();
         clone.bytecode.addStep(GraphTraversal.Symbols.E, ids);
         final GraphTraversal.Admin<Edge, Edge> traversal = new 
DefaultGraphTraversal<>(clone);
-        return traversal.addStep(new GraphStep<>(traversal, Edge.class, true, 
ids));
+
+        if (GValue.hasGValue(ids)) {
+            return traversal.addStep(new GraphStepGV<>(traversal, Edge.class, 
true, GValue.promoteGValues(ids)));
+        } else {
+            return traversal.addStep(new GraphStep<>(traversal, Edge.class, 
true, ids));
+        }
     }
 
     /**
@@ -624,4 +651,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 MergeVertexStepGV(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 MergeEdgeStepGV(traversal, true, 
searchCreate));
+        }
+    }
+
 }
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ConstantStep.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/lambda/ConstantGVTraversal.java
similarity index 51%
copy from 
gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ConstantStep.java
copy to 
gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/lambda/ConstantGVTraversal.java
index 9434cc3b47..03492a0e7c 100644
--- 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ConstantStep.java
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/lambda/ConstantGVTraversal.java
@@ -16,42 +16,48 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.tinkerpop.gremlin.process.traversal.step.map;
+package org.apache.tinkerpop.gremlin.process.traversal.lambda;
 
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
-import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
-import 
org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
-import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.GValue;
 
-import java.util.Collections;
 import java.util.Objects;
-import java.util.Set;
 
-public class ConstantStep<S, E> extends ScalarMapStep<S, E> {
+/**
+ * A {@link Traversal} that always returns a constant value.
+ *
+ * @author Marko A. Rodriguez (http://markorodriguez.com)
+ */
+public final class ConstantGVTraversal<S, E> extends 
AbstractLambdaTraversal<S, E> {
 
-    private final E constant;
+    private final GValue<E> end;
 
-    public ConstantStep(final Traversal.Admin traversal, final E constant) {
-        super(traversal);
-        this.constant = constant;
+    public ConstantGVTraversal(final GValue<E> end) {
+        this.end = end;
     }
 
-    public E getConstant() {
-        return this.constant;
+    public GValue<E> getEnd() {
+        return end;
     }
 
     @Override
-    protected E map(final Traverser.Admin<S> traverser) {
-        return this.constant;
+    public E next() {
+        throw new UnsupportedOperationException("Constant traversals with a 
GValue are not meant to be executed");
     }
 
     @Override
     public String toString() {
-        return StringFactory.stepString(this, this.constant);
+        return "(" + Objects.toString(this.end) + ")";
     }
 
     @Override
     public int hashCode() {
-        return super.hashCode() ^ Objects.hashCode(this.constant);
+        return this.getClass().hashCode() ^ Objects.hashCode(this.end);
+    }
+
+    @Override
+    public boolean equals(final Object other) {
+        return other instanceof ConstantGVTraversal
+                && Objects.equals(((ConstantGVTraversal) other).end, this.end);
     }
-}
+}
\ No newline at end of file
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/HasStep.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/HasStep.java
index 6048ba78fe..e25bc592ce 100644
--- 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/HasStep.java
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/HasStep.java
@@ -24,6 +24,7 @@ import 
org.apache.tinkerpop.gremlin.process.traversal.step.Configuring;
 import org.apache.tinkerpop.gremlin.process.traversal.step.HasContainerHolder;
 import org.apache.tinkerpop.gremlin.process.traversal.step.util.HasContainer;
 import org.apache.tinkerpop.gremlin.process.traversal.step.util.Parameters;
+import 
org.apache.tinkerpop.gremlin.process.traversal.step.util.structure.filter.HasStepStructure;
 import 
org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
 import org.apache.tinkerpop.gremlin.structure.Element;
 import org.apache.tinkerpop.gremlin.structure.Property;
@@ -38,7 +39,7 @@ import java.util.Set;
 /**
  * @author Marko A. Rodriguez (http://markorodriguez.com)
  */
-public class HasStep<S extends Element> extends FilterStep<S> implements 
HasContainerHolder, Configuring {
+public class HasStep<S extends Element> extends FilterStep<S> implements 
HasContainerHolder, Configuring, HasStepStructure {
 
     private final Parameters parameters = new Parameters();
     private List<HasContainer> hasContainers;
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/IsStep.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/IsStep.java
index a2889864a8..abead84787 100644
--- 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/IsStep.java
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/IsStep.java
@@ -21,6 +21,7 @@ package 
org.apache.tinkerpop.gremlin.process.traversal.step.filter;
 import org.apache.tinkerpop.gremlin.process.traversal.P;
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
+import 
org.apache.tinkerpop.gremlin.process.traversal.step.util.structure.filter.IsStepStructure;
 import 
org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
 import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
 
@@ -31,7 +32,7 @@ import java.util.Set;
  * @author Daniel Kuppitz (http://gremlin.guru)
  * @author Marko A. Rodriguez (http://markorodriguez.com)
  */
-public final class IsStep<S> extends FilterStep<S> {
+public final class IsStep<S> extends FilterStep<S> implements 
IsStepStructure<S> {
 
     private P<S> predicate;
 
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ConstantStep.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ConstantStep.java
index 9434cc3b47..bbc5abc731 100644
--- 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ConstantStep.java
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ConstantStep.java
@@ -20,14 +20,12 @@ package 
org.apache.tinkerpop.gremlin.process.traversal.step.map;
 
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
-import 
org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
+import 
org.apache.tinkerpop.gremlin.process.traversal.step.util.structure.map.ConstantStepStructure;
 import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
 
-import java.util.Collections;
 import java.util.Objects;
-import java.util.Set;
 
-public class ConstantStep<S, E> extends ScalarMapStep<S, E> {
+public class ConstantStep<S, E> extends ScalarMapStep<S, E> implements 
ConstantStepStructure<E> {
 
     private final E constant;
 
@@ -54,4 +52,5 @@ public class ConstantStep<S, E> extends ScalarMapStep<S, E> {
     public int hashCode() {
         return super.hashCode() ^ Objects.hashCode(this.constant);
     }
+
 }
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 3b1720ff9a..53cf2cc12f 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
@@ -29,6 +29,7 @@ import 
org.apache.tinkerpop.gremlin.process.traversal.step.GraphComputing;
 import org.apache.tinkerpop.gremlin.process.traversal.step.util.AbstractStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.util.HasContainer;
 import org.apache.tinkerpop.gremlin.process.traversal.step.util.Parameters;
+import 
org.apache.tinkerpop.gremlin.process.traversal.step.util.structure.map.GraphStepStructure;
 import 
org.apache.tinkerpop.gremlin.process.traversal.util.FastNoSuchElementException;
 import org.apache.tinkerpop.gremlin.structure.Edge;
 import org.apache.tinkerpop.gremlin.structure.Element;
@@ -49,7 +50,8 @@ import java.util.function.Supplier;
  * @author Marko A. Rodriguez (http://markorodriguez.com)
  * @author Pieter Martin
  */
-public class GraphStep<S, E extends Element> extends AbstractStep<S, E> 
implements GraphComputing, AutoCloseable, Configuring {
+public class GraphStep<S, E extends Element> extends AbstractStep<S, E> 
implements GraphComputing, AutoCloseable,
+        Configuring, GraphStepStructure<E, Object> {
 
     protected Parameters parameters = new Parameters();
     protected final Class<E> returnClass;
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MergeStep.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MergeStep.java
index 9b0f12d1d6..c87f6576be 100644
--- 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MergeStep.java
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MergeStep.java
@@ -41,6 +41,7 @@ import 
org.apache.tinkerpop.gremlin.process.traversal.step.util.Parameters;
 import 
org.apache.tinkerpop.gremlin.process.traversal.step.util.event.CallbackRegistry;
 import org.apache.tinkerpop.gremlin.process.traversal.step.util.event.Event;
 import 
org.apache.tinkerpop.gremlin.process.traversal.step.util.event.ListCallbackRegistry;
+import 
org.apache.tinkerpop.gremlin.process.traversal.step.util.structure.map.MergeElementStepStructure;
 import 
org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.PartitionStrategy;
 import 
org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
 import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper;
@@ -58,13 +59,13 @@ import 
org.apache.tinkerpop.gremlin.structure.util.StringFactory;
  * Abstract base class for the {@code mergeV/E()} implementations.
  */
 public abstract class MergeStep<S, E, C> extends FlatMapStep<S, E>
-        implements Writing<Event>, Deleting<Event>, 
TraversalOptionParent<Merge, S, C> {
+        implements Writing<Event>, Deleting<Event>, 
TraversalOptionParent<Merge, S, C>, MergeElementStepStructure<S> {
 
     protected final boolean isStart;
     protected boolean first = true;
     protected Traversal.Admin<S, Map> mergeTraversal;
     protected Traversal.Admin<S, Map> onCreateTraversal = null;
-    protected Traversal.Admin<S, Map<String, ?>> onMatchTraversal = null;
+    protected Traversal.Admin<S, Map> onMatchTraversal = null;
 
     protected CallbackRegistry<Event> callbackRegistry;
 
@@ -116,7 +117,7 @@ public abstract class MergeStep<S, E, C> extends 
FlatMapStep<S, E>
      * Gets the traversal that will be used to provide the {@code Map} that 
will be used to modify elements that
      * match the search criteria of {@link #getMergeTraversal()}.
      */
-    public Traversal.Admin<S, Map<String, ?>> getOnMatchTraversal() {
+    public Traversal.Admin<S, Map> getOnMatchTraversal() {
         return onMatchTraversal;
     }
 
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MergeVertexStep.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MergeVertexStep.java
index 11a9fc2ca4..3f59784541 100644
--- 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MergeVertexStep.java
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MergeVertexStep.java
@@ -31,6 +31,7 @@ import 
org.apache.tinkerpop.gremlin.process.traversal.Traverser;
 import 
org.apache.tinkerpop.gremlin.process.traversal.lambda.CardinalityValueTraversal;
 import org.apache.tinkerpop.gremlin.process.traversal.lambda.ConstantTraversal;
 import 
org.apache.tinkerpop.gremlin.process.traversal.step.util.event.EventUtil;
+import 
org.apache.tinkerpop.gremlin.process.traversal.step.util.structure.map.MergeElementStepStructure;
 import org.apache.tinkerpop.gremlin.structure.Graph;
 import org.apache.tinkerpop.gremlin.structure.T;
 import org.apache.tinkerpop.gremlin.structure.Vertex;
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/AddPropertyStep.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/AddPropertyStep.java
index 7d155a40bd..c7fe4d831c 100644
--- 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/AddPropertyStep.java
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/AddPropertyStep.java
@@ -26,6 +26,7 @@ import 
org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent;
 import org.apache.tinkerpop.gremlin.process.traversal.step.Writing;
 import org.apache.tinkerpop.gremlin.process.traversal.step.util.Parameters;
 import org.apache.tinkerpop.gremlin.process.traversal.step.util.event.*;
+import 
org.apache.tinkerpop.gremlin.process.traversal.step.util.structure.sideEffect.AddPropertyStepStructure;
 import 
org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.EventStrategy;
 import 
org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
 import org.apache.tinkerpop.gremlin.structure.Edge;
@@ -48,7 +49,8 @@ import java.util.Set;
  * @author Marko A. Rodriguez (http://markorodriguez.com)
  */
 public class AddPropertyStep<S extends Element> extends SideEffectStep<S>
-        implements Writing<Event.ElementPropertyChangedEvent>, 
Deleting<Event.ElementPropertyChangedEvent>, TraversalParent, Scoping {
+        implements Writing<Event.ElementPropertyChangedEvent>, 
Deleting<Event.ElementPropertyChangedEvent>,
+                   TraversalParent, Scoping, AddPropertyStepStructure {
 
     private Parameters parameters = new Parameters();
     private final VertexProperty.Cardinality cardinality;
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..4ce3137a42 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,12 +19,13 @@
 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.util.structure.sideEffect.InjectStepStructure;
 import org.apache.tinkerpop.gremlin.util.iterator.ArrayIterator;
 
 /**
  * @author Marko A. Rodriguez (http://markorodriguez.com)
  */
-public final class InjectStep<S> extends StartStep<S> {
+public final class InjectStep<S> extends StartStep<S> implements 
InjectStepStructure<S> {
 
     private final S[] injections;
 
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/GType.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/GType.java
new file mode 100644
index 0000000000..534c89baac
--- /dev/null
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/GType.java
@@ -0,0 +1,95 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tinkerpop.gremlin.process.traversal.step.util;
+
+import org.apache.tinkerpop.gremlin.process.traversal.Path;
+import org.apache.tinkerpop.gremlin.structure.Edge;
+import org.apache.tinkerpop.gremlin.structure.Property;
+import org.apache.tinkerpop.gremlin.structure.Vertex;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * An enum that describes types that are used in the Gremlin language.
+ */
+public enum GType {
+    BIG_DECIMAL,
+    BIG_INTEGER,
+    BOOLEAN,
+    DOUBLE,
+    EDGE,
+    INTEGER,
+    LIST,
+    LONG,
+    MAP,
+    PATH,
+    PROPERTY,
+    SET,
+    STRING,
+    UNKNOWN,
+    VERTEX;
+
+    GType() {}
+
+    /**
+     * 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}.
+     */
+    public static GType getType(final Object object) {
+        if (object instanceof String) return STRING;
+        else if (object instanceof Integer) return INTEGER;
+        else if (object instanceof Boolean) return BOOLEAN;
+        else if (object instanceof Double) return DOUBLE;
+        else if (object instanceof Long) return LONG;
+        else if (object instanceof Map) return MAP;
+        else if (object instanceof List) return LIST;
+        else if (object instanceof Set) return SET;
+        else if (object instanceof Vertex) return VERTEX;
+        else if (object instanceof Edge) return EDGE;
+        else if (object instanceof Path) return PATH;
+        else if (object instanceof Property) return PROPERTY;
+        else if (object instanceof BigInteger) return BIG_INTEGER;
+        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/util/GValue.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/GValue.java
new file mode 100644
index 0000000000..47b3b0c287
--- /dev/null
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/GValue.java
@@ -0,0 +1,443 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tinkerpop.gremlin.process.traversal.step.util;
+
+import org.apache.tinkerpop.gremlin.process.traversal.P;
+import org.apache.tinkerpop.gremlin.process.traversal.Path;
+import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
+import org.apache.tinkerpop.gremlin.process.traversal.util.ConnectiveP;
+import org.apache.tinkerpop.gremlin.structure.Edge;
+import org.apache.tinkerpop.gremlin.structure.Property;
+import org.apache.tinkerpop.gremlin.structure.Vertex;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+
+/**
+ * A {@code GValue} is a variable or literal value that is used in a {@link 
Traversal}. It is composed of a key-value
+ * pair where the key is the name given to the variable and the value is the 
object that the variable resolved to. If
+ * the name is not given, the value was provided literally in the traversal. 
The value of the variable can be any
+ * object. The {@code GValue} also includes the {@link GType} that describes 
the type it contains.
+ */
+public class GValue<V> implements Cloneable, Serializable {
+    private final String name;
+    private final GType type;
+
+    private final V value;
+
+    private GValue(final GType type, final V value) {
+        this(null, type, value);
+    }
+
+    private GValue(final String name, final GType type, final V value) {
+        this.name = name;
+        this.type = type;
+        this.value = value;
+    }
+
+    /**
+     * Determines if the value held by this object was defined as a variable 
or a literal value. Literal values simply
+     * have no name.
+     */
+    public boolean isVariable() {
+        return this.name != null;
+    }
+
+    /**
+     * Gets the name of the variable if it was defined as such and returns 
empty if the value was a literal.
+     */
+    public String getName() {
+        return this.name;
+    }
+
+    /**
+     * Gets the type of the value. The explicit type could be determined with 
{@code instanceof} on the value, but this
+     * might be helpful for cases where the value was constructed with a 
{@code null} value which might just return as
+     * {@code Object}.
+     */
+    public GType getType() {
+        return this.type;
+    }
+
+    /**
+     * Determines if the value held is of a {@code null} value.
+     */
+    public boolean isNull() {
+        return this.value == null;
+    }
+
+    /**
+     * Gets the value.
+     */
+    public V get() {
+        return this.value;
+    }
+
+    @Override
+    public String toString() {
+        return isVariable() ?
+                String.format("%s&%s", name, value) : Objects.toString(value);
+    }
+
+    @Override
+    public boolean equals(final Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        final GValue<?> gValue = (GValue<?>) o;
+        return Objects.equals(name, gValue.name) && type == gValue.type && 
Objects.equals(value, gValue.value);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(name, type, value);
+    }
+
+    /**
+     * Create a new {@code Var} from a particular value but without the 
specified name.
+     *
+     * @param value the value of the variable
+     */
+    public static <V> GValue<V> of(final V value) {
+        if (value instanceof GValue)
+            return (GValue<V>) value;
+
+        return new GValue<>(GType.getType(value), value);
+    }
+
+    /**
+     * Create a new {@code Var} with the specified name and value.
+     *
+     * @param name the name of the variable
+     * @param value the value of the variable
+     */
+    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.
+     */
+    public static GValue<String> ofString(final String value) {
+        return new GValue<>(GType.STRING, value);
+    }
+
+    /**
+     * Create a new {@code GValue} for a string value with a specified name.
+     */
+    public static GValue<String> ofString(final String name, final String 
value) {
+        return new GValue<>(name, GType.STRING, value);
+    }
+
+    /**
+     * Create a new {@code GValue} for an integer value.
+     */
+    public static GValue<Integer> ofInteger(final Integer value) {
+        return new GValue<>(GType.INTEGER, value);
+    }
+
+    /**
+     * Create a new {@code GValue} for an integer value with a specified name.
+     */
+    public static GValue<Integer> ofInteger(final String name, final Integer 
value) {
+        return new GValue<>(name, GType.INTEGER, value);
+    }
+
+    /**
+     * Create a new {@code GValue} for a boolean value.
+     */
+    public static GValue<Boolean> ofBoolean(final Boolean value) {
+        return new GValue<>(GType.BOOLEAN, value);
+    }
+
+    /**
+     * Create a new {@code GValue} for a boolean value with a specified name.
+     */
+    public static GValue<Boolean> ofBoolean(final String name, final Boolean 
value) {
+        return new GValue<>(name, GType.BOOLEAN, value);
+    }
+
+    /**
+     * Create a new {@code GValue} for a double value.
+     */
+    public static GValue<Double> ofDouble(final Double value) {
+        return new GValue<>(GType.DOUBLE, value);
+    }
+
+    /**
+     * Create a new {@code GValue} for a double value with a specified name.
+     */
+    public static GValue<Double> ofDouble(final String name, final Double 
value) {
+        return new GValue<>(name, GType.DOUBLE, value);
+    }
+
+    /**
+     * Create a new {@code GValue} for a BigInteger value.
+     */
+    public static GValue<BigInteger> ofBigInteger(final BigInteger value) {
+        return new GValue<>(GType.BIG_INTEGER, value);
+    }
+
+    /**
+     * Create a new {@code GValue} for a BigInteger value with a specified 
name.
+     */
+    public static GValue<BigInteger> ofBigInteger(final String name, final 
BigInteger value) {
+        return new GValue<>(name, GType.BIG_INTEGER, value);
+    }
+
+    /**
+     * Create a new {@code GValue} for a BigDecimal value.
+     */
+    public static GValue<BigDecimal> ofBigDecimal(final BigDecimal value) {
+        return new GValue<>(GType.BIG_DECIMAL, value);
+    }
+
+    /**
+     * Create a new {@code GValue} for a BigDecimal value with a specified 
name.
+     */
+    public static GValue<BigDecimal> ofBigDecimal(final String name, final 
BigDecimal value) {
+        return new GValue<>(name, GType.BIG_DECIMAL, value);
+    }
+
+    /**
+     * Create a new {@code GValue} for a long value.
+     */
+    public static GValue<Long> ofLong(final Long value) {
+        return new GValue<>(GType.LONG, value);
+    }
+
+    /**
+     * Create a new {@code GValue} for a long value with a specified name.
+     */
+    public static GValue<Long> ofLong(final String name, final Long value) {
+        return new GValue<>(name, GType.LONG, value);
+    }
+
+    /**
+     * Create a new {@code GValue} for a map value.
+     */
+    public static GValue<Map> ofMap(final Map value) {
+        return new GValue<>(GType.MAP, value);
+    }
+
+    /**
+     * Create a new {@code GValue} for a map value with a specified name.
+     */
+    public static GValue<Map> ofMap(final String name, final Map value) {
+        return new GValue<>(name, GType.MAP, value);
+    }
+
+    /**
+     * Create a new {@code GValue} for a 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 <T> GValue<List<T>> ofList(final String name, final List<T> 
value) {
+        return new GValue<>(name, GType.LIST, value);
+    }
+
+    /**
+     * Create a new {@code GValue} for a set value.
+     */
+    public static GValue<Set> ofSet(final Set value) {
+        return new GValue<>(GType.SET, value);
+    }
+
+    /**
+     * Create a new {@code GValue} for a set value with a specified name.
+     */
+    public static GValue<Set> ofSet(final String name, final Set value) {
+        return new GValue<>(name, GType.SET, value);
+    }
+
+    /**
+     * Create a new {@code GValue} for a vertex value.
+     */
+    public static GValue<Vertex> ofVertex(final Vertex value) {
+        return new GValue<>(GType.VERTEX, value);
+    }
+
+    /**
+     * Create a new {@code GValue} for a vertex value with a specified name.
+     */
+    public static GValue<Vertex> ofVertex(final String name, final Vertex 
value) {
+        return new GValue<>(name, GType.VERTEX, value);
+    }
+
+    /**
+     * Create a new {@code GValue} for an edge value.
+     */
+    public static GValue<Edge> ofEdge(final Edge value) {
+        return new GValue<>(GType.EDGE, value);
+    }
+
+    /**
+     * Create a new {@code GValue} for an edge value with a specified name.
+     */
+    public static GValue<Edge> ofEdge(final String name, final Edge value) {
+        return new GValue<>(name, GType.EDGE, value);
+    }
+
+    /**
+     * Create a new {@code GValue} for a path value.
+     */
+    public static GValue<Path> ofPath(final Path value) {
+        return new GValue<>(GType.PATH, value);
+    }
+
+    /**
+     * Create a new {@code GValue} for a path value with a specified name.
+     */
+    public static GValue<Path> ofPath(final String name, final Path value) {
+        return new GValue<>(name, GType.PATH, value);
+    }
+
+    /**
+     * Create a new {@code GValue} for a property value.
+     */
+    public static GValue<Property> ofProperty(final Property value) {
+        return new GValue<>(GType.PROPERTY, value);
+    }
+
+    /**
+     * Create a new {@code GValue} for a property value with a specified name.
+     */
+    public static GValue<Property> ofProperty(final String name, final 
Property value) {
+        return new GValue<>(name, GType.PROPERTY, value);
+    }
+
+    public static <T> GValue[] promoteGValues(final Object... objects) {
+        return Arrays.stream(objects).map(o -> {
+            if (o instanceof GValue)
+                return (GValue<T>) o;
+            else
+                return GValue.of(o);
+        }).toArray(GValue[]::new);
+    }
+
+    /**
+     * The objects array is a series of key-value pairs. Construct a new 
object array that ensures that the values
+     * become {@link GValue} instances if they are not already.
+     */
+    public static Object[] promoteGValuesInKeyValues(final Object... objects) {
+        final Object[] keyValues = new Object[objects.length];
+        for (int i = 0; i < objects.length; i++) {
+            final Object o = objects[i];
+
+            // even are keys, odd are values
+            if (i % 2 == 1) {
+                keyValues[i] = o instanceof GValue ? o : GValue.of(o);
+            } else {
+                keyValues[i] = o;
+            }
+        }
+        return keyValues;
+    }
+
+    /**
+     * Resolve all {@link GValue} instance in the array to their value and 
return a new object array.
+     */
+    public static Object[] resolveGValues(final Object... objects) {
+        return Arrays.stream(objects).map(o -> {
+            if (o instanceof GValue)
+                return ((GValue) o).get();
+            else
+                return o;
+        }).toArray();
+    }
+
+    /**
+     * Take an instance of {@link P} and if it is a {@link GValue}, unwrap it 
to its value and reassign it back to
+     * the {@link P} instance. In addition, Detect if the {@link P} instance 
is a {@link ConnectiveP}, then iterate
+     * the list of predicates and convert them to {@link GValue} if they are 
instances of {@link GValue}. This must be
+     * done recursively as the {@link ConnectiveP} can contain other {@link 
ConnectiveP} instances.
+     */
+    public static P resolveGValuesInP(final P p) {
+        final Object o = p.getValue();
+        if (o instanceof GValue) {
+            if (o instanceof GValue) {
+                p.setValue(((GValue) o).get());
+            }
+        } else if (o instanceof List) {
+            final List l = (List) o;
+            final List ln = new ArrayList<>();
+            l.forEach(value -> ln.add(value instanceof GValue ? ((GValue) 
value).get() : value) );
+            p.setValue(ln);
+        } else if (p instanceof ConnectiveP) {
+            final ConnectiveP connectiveP = (ConnectiveP) p;
+            connectiveP.getPredicates().forEach(pred -> resolveGValuesInP((P) 
pred));
+        }
+        return p;
+    }
+
+    public static HasContainer resolveGValuesInHasContainer(final HasContainer 
hasContainer) {
+        final P p = hasContainer.getPredicate();
+        hasContainer.setPredicate(resolveGValuesInP(p));
+        return hasContainer;
+    }
+
+    public static HasContainer[] resolveGValuesInHasContainers(final 
HasContainer... hasContainers) {
+        for (int i = 0; i < hasContainers.length; i++) {
+            hasContainers[i] = resolveGValuesInHasContainer(hasContainers[i]);
+        }
+        return hasContainers;
+    }
+
+    /**
+     * Detects if a value of {@link P} has a {@link GValue} and if so, return 
{@link true} immediately.
+     */
+    public static boolean hasGValueInP(final P p) {
+        final Object o = p.getValue();
+        if (o instanceof GValue)
+            return true;
+        else if (o instanceof List) {
+            final List l = (List) o;
+            for (final Object value : l) {
+                if (value instanceof GValue)
+                    return true;
+            }
+        } else if (p instanceof ConnectiveP) {
+            final ConnectiveP<?> connectiveP = (ConnectiveP) p;
+            for (P pred : connectiveP.getPredicates()) {
+                if (hasGValueInP(pred))
+                    return true;
+            }
+        }
+        return false;
+    }
+
+    public static boolean hasGValue(final Object... objects) {
+        for (Object o : objects) {
+            if (o instanceof GValue)
+                return true;
+        }
+        return false;
+    }
+}
\ No newline at end of file
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/GValueStep.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/GValueStep.java
new file mode 100644
index 0000000000..5dca16e1c1
--- /dev/null
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/GValueStep.java
@@ -0,0 +1,93 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tinkerpop.gremlin.process.traversal.step.util;
+
+import org.apache.tinkerpop.gremlin.process.traversal.Merge;
+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 java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.Objects;
+import java.util.Set;
+
+public class GValueStep<C extends Step, S, E> extends AbstractStep<S,E> {
+
+    protected final C concreteStep;
+
+    public GValueStep(final Traversal.Admin traversal, final C concreteStep) {
+        super(traversal);
+        this.concreteStep = concreteStep;
+    }
+
+    public C getConcreteStep() {
+        return concreteStep;
+    }
+
+    @Override
+    public void addLabel(String label) {
+        this.concreteStep.addLabel(label);
+    }
+
+    @Override
+    public void removeLabel(String label) {
+        this.concreteStep.removeLabel(label);
+    }
+
+    @Override
+    public void clearLabels() {
+        this.concreteStep.clearLabels();
+    }
+
+    @Override
+    public Set<String> getLabels() {
+        return this.concreteStep.getLabels();
+    }
+
+    @Override
+    protected Traverser.Admin<E> processNextStart() throws 
NoSuchElementException {
+        throw new UnsupportedOperationException("GValueStep is a placeholder 
step and should not be executed");
+    }
+
+    @Override
+    public String toString() {
+        return Objects.toString(concreteStep);
+    }
+
+    public static class MergeOptionStep<S,E> extends GValueStep<EmptyStep, S, 
E> {
+        private final Merge merge;
+        private final GValue gvalue;
+
+        public MergeOptionStep(final Traversal.Admin traversal, final Merge 
merge, final GValue<Map<Object, Object>> gvalue) {
+            super(traversal, EmptyStep.instance());
+            this.merge = merge;
+            this.gvalue = gvalue;
+        }
+
+        public Merge getMerge() {
+            return merge;
+        }
+
+        public GValue getGvalue() {
+            return gvalue;
+        }
+    }
+
+}
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..99995d42dc 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
@@ -134,6 +134,10 @@ public class HasContainer implements Serializable, 
Cloneable, Predicate<Element>
         return this.predicate;
     }
 
+    public void setPredicate(final P predicate) {
+        this.predicate = predicate;
+    }
+
     public final BiPredicate<?, ?> getBiPredicate() {
         return this.predicate.getBiPredicate();
     }
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/structure/filter/HasStepGV.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/structure/filter/HasStepGV.java
new file mode 100644
index 0000000000..a50d966b2d
--- /dev/null
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/structure/filter/HasStepGV.java
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package 
org.apache.tinkerpop.gremlin.process.traversal.step.util.structure.filter;
+
+import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
+import org.apache.tinkerpop.gremlin.process.traversal.step.filter.HasStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.GValue;
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.GValueStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.HasContainer;
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.Parameters;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+public class HasStepGV<S> extends GValueStep<HasStep, S, S> implements 
HasStepStructure {
+    private List<HasContainer> hasContainers;
+    private final Parameters parameters = new Parameters();
+
+    public HasStepGV(final Traversal.Admin traversal, final HasContainer... 
hasContainers) {
+        super(traversal, new HasStep(traversal, 
GValue.resolveGValuesInHasContainers(hasContainers)));
+        this.hasContainers = new ArrayList<>();
+        Collections.addAll(this.hasContainers, hasContainers);
+    }
+
+    @Override
+    public void configure(final Object... keyValues) {
+        // all GValues locally stored in the parameters, but resolve them for 
the concrete step
+        this.parameters.set(null, GValue.promoteGValuesInKeyValues(keyValues));
+        this.concreteStep.configure(GValue.resolveGValues(keyValues));
+    }
+
+    @Override
+    public Parameters getParameters() {
+        return concreteStep.getParameters();
+    }
+
+    @Override
+    public List<HasContainer> getHasContainers() {
+        return Collections.unmodifiableList(this.hasContainers);
+    }
+
+    @Override
+    public void removeHasContainer(final HasContainer hasContainer) {
+        // not sure what this means in this context since this object will be 
different from the one in the concrete
+        // step. strategies are the only things that remove HasContainers so 
since the GValueSteps will all be
+        // removed by the time they execute perhaps we don't need to implement 
this.
+        throw new UnsupportedOperationException("Cannot remove HasContainers 
from HasStepGV");
+    }
+
+    @Override
+    public void addHasContainer(final HasContainer hasContainer) {
+        assert(GValue.hasGValueInP(hasContainer.getPredicate()));
+        this.hasContainers.add(hasContainer);
+        
this.concreteStep.addHasContainer(GValue.resolveGValuesInHasContainer(hasContainer));
+    }
+
+}
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/structure/filter/HasStepStructure.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/structure/filter/HasStepStructure.java
new file mode 100644
index 0000000000..397dda4710
--- /dev/null
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/structure/filter/HasStepStructure.java
@@ -0,0 +1,25 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package 
org.apache.tinkerpop.gremlin.process.traversal.step.util.structure.filter;
+
+import org.apache.tinkerpop.gremlin.process.traversal.step.Configuring;
+import org.apache.tinkerpop.gremlin.process.traversal.step.HasContainerHolder;
+
+public interface HasStepStructure extends HasContainerHolder, Configuring {
+}
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/util/structure/filter/IsStepGV.java
similarity index 51%
copy from 
gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/InjectStep.java
copy to 
gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/structure/filter/IsStepGV.java
index 0502f18541..a7aa23a6e7 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/util/structure/filter/IsStepGV.java
@@ -16,39 +16,29 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect;
+package 
org.apache.tinkerpop.gremlin.process.traversal.step.util.structure.filter;
 
+import org.apache.tinkerpop.gremlin.process.traversal.P;
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
-import org.apache.tinkerpop.gremlin.util.iterator.ArrayIterator;
+import org.apache.tinkerpop.gremlin.process.traversal.step.filter.IsStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.GValue;
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.GValueStep;
 
-/**
- * @author Marko A. Rodriguez (http://markorodriguez.com)
- */
-public final class InjectStep<S> extends StartStep<S> {
-
-    private final S[] injections;
+public class IsStepGV<S> extends GValueStep<IsStep, S, S> implements 
IsStepStructure<S> {
+    private P<S> predicate;
 
-    @SafeVarargs
-    public InjectStep(final Traversal.Admin traversal, final S... injections) {
-        super(traversal);
-        this.injections = injections;
-        this.start = new ArrayIterator<>(this.injections);
+    public IsStepGV(final Traversal.Admin traversal, final P<S> predicate) {
+        super(traversal, new IsStep(traversal, 
GValue.resolveGValuesInP(predicate)));
+        this.predicate = predicate;
     }
 
     @Override
-    public InjectStep<S> clone() {
-        final InjectStep<S> clone = (InjectStep<S>) super.clone();
-        clone.start = new ArrayIterator<>(clone.injections);
-        return clone;
+    public P<S> getPredicate() {
+        return predicate;
     }
 
     @Override
-    public void reset() {
-        super.reset();
-        this.start = new ArrayIterator<>(this.injections);
-    }
-
-    public S[] getInjections() {
-        return this.injections;
+    public IsStep<S> getConcreteStep() {
+        return concreteStep;
     }
 }
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/structure/filter/IsStepStructure.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/structure/filter/IsStepStructure.java
new file mode 100644
index 0000000000..0f40305d48
--- /dev/null
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/structure/filter/IsStepStructure.java
@@ -0,0 +1,25 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package 
org.apache.tinkerpop.gremlin.process.traversal.step.util.structure.filter;
+
+import org.apache.tinkerpop.gremlin.process.traversal.P;
+
+public interface IsStepStructure<S> {
+    public P<S> getPredicate();
+}
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/structure/map/AddEdgeStepGV.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/structure/map/AddEdgeStepGV.java
new file mode 100644
index 0000000000..2f896a7e15
--- /dev/null
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/structure/map/AddEdgeStepGV.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tinkerpop.gremlin.process.traversal.step.util.structure.map;
+
+import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.AddEdgeStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.GValue;
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.GValueStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.Parameters;
+import org.apache.tinkerpop.gremlin.structure.T;
+
+public class AddEdgeStepGV<S> extends GValueStep<AddEdgeStep, S, S> implements 
AddEdgeStepStructure {
+    private final Parameters parameters = new Parameters();
+
+    public AddEdgeStepGV(final Traversal.Admin traversal, final GValue<String> 
edgeLabel) {
+        super(traversal, new AddEdgeStep(traversal, edgeLabel.get()));
+        this.parameters.set(this, T.label, edgeLabel);
+    }
+
+    @Override
+    public void configure(final Object... keyValues) {
+        // all GValues locally stored in the parameters, but resolve them for 
the concrete step
+        this.parameters.set(this, GValue.promoteGValuesInKeyValues(keyValues));
+        this.concreteStep.configure(GValue.resolveGValues(keyValues));
+    }
+
+    @Override
+    public Parameters getParameters() {
+        return this.parameters;
+    }
+
+    @Override
+    public void addTo(final Traversal.Admin<?, ?> toObject) {
+        // pass through to the concrete step because it can't a be a GValue 
and it gets called from GraphTraversal
+        this.concreteStep.addTo(toObject);
+    }
+
+    @Override
+    public void addFrom(final Traversal.Admin<?, ?> fromObject) {
+        // pass through to the concrete step because it can't a be a GValue 
and it gets called from GraphTraversal
+        this.concreteStep.addFrom(fromObject);
+    }
+}
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/structure/map/AddEdgeStepStructure.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/structure/map/AddEdgeStepStructure.java
new file mode 100644
index 0000000000..fb0b0e9d6e
--- /dev/null
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/structure/map/AddEdgeStepStructure.java
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tinkerpop.gremlin.process.traversal.step.util.structure.map;
+
+import org.apache.tinkerpop.gremlin.process.traversal.step.Configuring;
+import org.apache.tinkerpop.gremlin.process.traversal.step.FromToModulating;
+import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent;
+
+public interface AddEdgeStepStructure extends Configuring, FromToModulating, 
TraversalParent {
+
+}
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/util/structure/map/ConstantStepGV.java
similarity index 50%
copy from 
gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/InjectStep.java
copy to 
gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/structure/map/ConstantStepGV.java
index 0502f18541..0b61bc81f3 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/util/structure/map/ConstantStepGV.java
@@ -16,39 +16,24 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect;
+package org.apache.tinkerpop.gremlin.process.traversal.step.util.structure.map;
 
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
-import org.apache.tinkerpop.gremlin.util.iterator.ArrayIterator;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.ConstantStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.GValue;
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.GValueStep;
 
-/**
- * @author Marko A. Rodriguez (http://markorodriguez.com)
- */
-public final class InjectStep<S> extends StartStep<S> {
-
-    private final S[] injections;
+public class ConstantStepGV<S> extends GValueStep<ConstantStep, S, S> 
implements ConstantStepStructure<GValue<S>> {
 
-    @SafeVarargs
-    public InjectStep(final Traversal.Admin traversal, final S... injections) {
-        super(traversal);
-        this.injections = injections;
-        this.start = new ArrayIterator<>(this.injections);
-    }
+    private final GValue<S> constant;
 
-    @Override
-    public InjectStep<S> clone() {
-        final InjectStep<S> clone = (InjectStep<S>) super.clone();
-        clone.start = new ArrayIterator<>(clone.injections);
-        return clone;
+    public ConstantStepGV(final Traversal.Admin traversal, final GValue<S> 
constant) {
+        super(traversal, new ConstantStep(traversal, constant.get()));
+        this.constant = constant;
     }
 
     @Override
-    public void reset() {
-        super.reset();
-        this.start = new ArrayIterator<>(this.injections);
-    }
-
-    public S[] getInjections() {
-        return this.injections;
+    public GValue<S> getConstant() {
+        return constant;
     }
 }
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/structure/map/ConstantStepStructure.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/structure/map/ConstantStepStructure.java
new file mode 100644
index 0000000000..4932752477
--- /dev/null
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/structure/map/ConstantStepStructure.java
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tinkerpop.gremlin.process.traversal.step.util.structure.map;
+
+public interface ConstantStepStructure<E> {
+    public E getConstant();
+}
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/structure/map/GraphStepGV.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/structure/map/GraphStepGV.java
new file mode 100644
index 0000000000..6f5cb1d31f
--- /dev/null
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/structure/map/GraphStepGV.java
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tinkerpop.gremlin.process.traversal.step.util.structure.map;
+
+import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.GraphStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.GValue;
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.GValueStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.Parameters;
+
+import java.util.Arrays;
+
+public class GraphStepGV<S, E> extends GValueStep<GraphStep, E, E> implements 
GraphStepStructure<E, GValue<Object>> {
+    private final Parameters parameters = new Parameters();
+    private final GValue<Object>[] ids;
+    private final Class<E> returnClass;
+
+    public GraphStepGV(final Traversal.Admin traversal, final Class<E> 
returnClass, final boolean isStart, final GValue<Object>... ids) {
+        super(traversal, new GraphStep(traversal, returnClass, isStart,
+                Arrays.stream(ids).map(GValue::get).toArray(Object[]::new)));
+        this.returnClass = returnClass;
+        this.ids = ids;
+    }
+
+    @Override
+    public void configure(final Object... keyValues) {
+        // all GValues locally stored in the parameters, but resolve them for 
the concrete step
+        this.parameters.set(null, GValue.promoteGValuesInKeyValues(keyValues));
+        this.concreteStep.configure(GValue.resolveGValues(keyValues));
+    }
+
+    @Override
+    public Parameters getParameters() {
+        return concreteStep.getParameters();
+    }
+
+    @Override
+    public GValue<Object>[] getIds() {
+        return ids;
+    }
+
+    @Override
+    public Class<E> getReturnClass() {
+        return returnClass;
+    }
+}
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/structure/map/GraphStepStructure.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/structure/map/GraphStepStructure.java
new file mode 100644
index 0000000000..76c333f460
--- /dev/null
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/structure/map/GraphStepStructure.java
@@ -0,0 +1,28 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tinkerpop.gremlin.process.traversal.step.util.structure.map;
+
+import org.apache.tinkerpop.gremlin.process.traversal.step.Configuring;
+import org.apache.tinkerpop.gremlin.structure.Direction;
+
+public interface GraphStepStructure<E, A> extends Configuring {
+
+    public A[] getIds();
+    public Class<E> getReturnClass();
+}
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/structure/map/MergeEdgeStepGV.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/structure/map/MergeEdgeStepGV.java
new file mode 100644
index 0000000000..f3cae8bd5f
--- /dev/null
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/structure/map/MergeEdgeStepGV.java
@@ -0,0 +1,94 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tinkerpop.gremlin.process.traversal.step.util.structure.map;
+
+import org.apache.tinkerpop.gremlin.process.traversal.Merge;
+import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
+import 
org.apache.tinkerpop.gremlin.process.traversal.lambda.ConstantGVTraversal;
+import org.apache.tinkerpop.gremlin.process.traversal.lambda.ConstantTraversal;
+import 
org.apache.tinkerpop.gremlin.process.traversal.step.TraversalOptionParent;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.MergeVertexStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.GValue;
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.GValueStep;
+import org.apache.tinkerpop.gremlin.structure.Edge;
+
+import java.util.Map;
+
+public class MergeEdgeStepGV<S> extends GValueStep<MergeVertexStep, S, Edge> 
implements TraversalOptionParent<Merge, S, Map>, MergeElementStepStructure<S> {
+
+    private Traversal.Admin<S, Map> merge;
+    private Traversal.Admin<S, Map> create;
+    private Traversal.Admin<S, Map> match;
+
+
+    public MergeEdgeStepGV(final Traversal.Admin traversal, final boolean 
isStart) {
+        super(traversal, new MergeVertexStep(traversal, isStart));
+    }
+
+    public MergeEdgeStepGV(final Traversal.Admin traversal, final boolean 
isStart, final Map merge) {
+        super(traversal, new MergeVertexStep(traversal, isStart, merge));
+    }
+
+    public MergeEdgeStepGV(final Traversal.Admin traversal, final boolean 
isStart, final GValue<Map> merge) {
+        super(traversal, new MergeVertexStep(traversal, isStart, merge.get()));
+        this.merge = new ConstantGVTraversal<>(merge);
+
+    }
+
+    public MergeEdgeStepGV(final Traversal.Admin traversal, final boolean 
isStart, final Traversal.Admin<S,Map> mergeTraversal) {
+        super(traversal, new MergeVertexStep(traversal, isStart, 
mergeTraversal));
+    }
+
+    @Override
+    public void addChildOption(final Merge token, final Traversal.Admin<S, 
Map> traversalOption) {
+        if (token == Merge.onCreate) {
+            if (traversalOption instanceof ConstantGVTraversal) {
+                this.create = (Traversal.Admin<S, Map>) traversalOption;
+                this.getConcreteStep().addChildOption(token, new 
ConstantTraversal(((ConstantGVTraversal) traversalOption).getEnd()));
+            } else {
+                this.getConcreteStep().addChildOption(token, traversalOption);
+            }
+
+        } else if (token == Merge.onMatch) {
+            if (traversalOption instanceof ConstantGVTraversal) {
+                this.match = (Traversal.Admin<S, Map>) traversalOption;
+                this.getConcreteStep().addChildOption(token, new 
ConstantTraversal(((ConstantGVTraversal) traversalOption).getEnd()));
+            } else {
+                this.getConcreteStep().addChildOption(token, traversalOption);
+            }
+        } else {
+            throw new UnsupportedOperationException(String.format("Option %s 
for Merge is not supported", token.name()));
+        }
+    }
+
+    @Override
+    public Traversal.Admin<S, Map> getMergeTraversal() {
+        return merge;
+    }
+
+    @Override
+    public Traversal.Admin<S, Map> getOnCreateTraversal() {
+        return create;
+    }
+
+    @Override
+    public Traversal.Admin<S, Map> getOnMatchTraversal() {
+        return match;
+    }
+}
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/structure/map/MergeElementStepStructure.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/structure/map/MergeElementStepStructure.java
new file mode 100644
index 0000000000..af2facc97b
--- /dev/null
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/structure/map/MergeElementStepStructure.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tinkerpop.gremlin.process.traversal.step.util.structure.map;
+
+import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
+
+import java.util.Map;
+
+public interface MergeElementStepStructure<S> {
+    /**
+     * Gets the traversal that will be used to provide the {@code Map} that 
will be used to search for elements.
+     * This {@code Map} also will be used as the default data set to be used 
to create the element if the search is not
+     * successful.
+     */
+    public Traversal.Admin<S, Map> getMergeTraversal();
+
+    /**
+     * Gets the traversal that will be used to provide the {@code Map} that 
will be used to create elements that
+     * do not match the search criteria of {@link #getMergeTraversal()}.
+     */
+    public Traversal.Admin<S, Map> getOnCreateTraversal();
+
+    /**
+     * Gets the traversal that will be used to provide the {@code Map} that 
will be used to modify elements that
+     * match the search criteria of {@link #getMergeTraversal()}.
+     */
+    public Traversal.Admin<S, Map> getOnMatchTraversal();
+}
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/structure/map/MergeVertexStepGV.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/structure/map/MergeVertexStepGV.java
new file mode 100644
index 0000000000..773beb00e4
--- /dev/null
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/structure/map/MergeVertexStepGV.java
@@ -0,0 +1,95 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tinkerpop.gremlin.process.traversal.step.util.structure.map;
+
+import org.apache.tinkerpop.gremlin.process.traversal.Merge;
+import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
+import 
org.apache.tinkerpop.gremlin.process.traversal.lambda.ConstantGVTraversal;
+import org.apache.tinkerpop.gremlin.process.traversal.lambda.ConstantTraversal;
+import 
org.apache.tinkerpop.gremlin.process.traversal.step.TraversalOptionParent;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.MergeVertexStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.GValue;
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.GValueStep;
+import org.apache.tinkerpop.gremlin.structure.Vertex;
+
+import java.util.Map;
+import java.util.Set;
+
+public class MergeVertexStepGV<S> extends GValueStep<MergeVertexStep, S, 
Vertex> implements TraversalOptionParent<Merge, S, Map>, 
MergeElementStepStructure<S> {
+
+    private Traversal.Admin<S, Map> merge;
+    private Traversal.Admin<S, Map> create;
+    private Traversal.Admin<S, Map> match;
+
+
+    public MergeVertexStepGV(final Traversal.Admin traversal, final boolean 
isStart) {
+        super(traversal, new MergeVertexStep(traversal, isStart));
+    }
+
+    public MergeVertexStepGV(final Traversal.Admin traversal, final boolean 
isStart, final Map merge) {
+        super(traversal, new MergeVertexStep(traversal, isStart, merge));
+    }
+
+    public MergeVertexStepGV(final Traversal.Admin traversal, final boolean 
isStart, final GValue<Map> merge) {
+        super(traversal, new MergeVertexStep(traversal, isStart, merge.get()));
+        this.merge = new ConstantGVTraversal<>(merge);
+
+    }
+
+    public MergeVertexStepGV(final Traversal.Admin traversal, final boolean 
isStart, final Traversal.Admin<S,Map> mergeTraversal) {
+        super(traversal, new MergeVertexStep(traversal, isStart, 
mergeTraversal));
+    }
+
+    @Override
+    public void addChildOption(final Merge token, final Traversal.Admin<S, 
Map> traversalOption) {
+        if (token == Merge.onCreate) {
+            if (traversalOption instanceof ConstantGVTraversal) {
+                this.create = (Traversal.Admin<S, Map>) traversalOption;
+                this.getConcreteStep().addChildOption(token, new 
ConstantTraversal(((ConstantGVTraversal) traversalOption).getEnd()));
+            } else {
+                this.getConcreteStep().addChildOption(token, traversalOption);
+            }
+
+        } else if (token == Merge.onMatch) {
+            if (traversalOption instanceof ConstantGVTraversal) {
+                this.match = (Traversal.Admin<S, Map>) traversalOption;
+                this.getConcreteStep().addChildOption(token, new 
ConstantTraversal(((ConstantGVTraversal) traversalOption).getEnd()));
+            } else {
+                this.getConcreteStep().addChildOption(token, traversalOption);
+            }
+        } else {
+            throw new UnsupportedOperationException(String.format("Option %s 
for Merge is not supported", token.name()));
+        }
+    }
+
+    @Override
+    public Traversal.Admin<S, Map> getMergeTraversal() {
+        return merge;
+    }
+
+    @Override
+    public Traversal.Admin<S, Map> getOnCreateTraversal() {
+        return create;
+    }
+
+    @Override
+    public Traversal.Admin<S, Map> getOnMatchTraversal() {
+        return match;
+    }
+}
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/structure/map/VertexStepGV.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/structure/map/VertexStepGV.java
new file mode 100644
index 0000000000..b194a46ca7
--- /dev/null
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/structure/map/VertexStepGV.java
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tinkerpop.gremlin.process.traversal.step.util.structure.map;
+
+import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.VertexStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.GValue;
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.GValueStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.Parameters;
+import org.apache.tinkerpop.gremlin.structure.Direction;
+import org.apache.tinkerpop.gremlin.structure.Element;
+
+import java.util.Arrays;
+
+public class VertexStepGV<E extends Element> extends GValueStep<VertexStep, E, 
E> implements VertexStepStructure<E, GValue<String>> {
+    private final GValue<String>[] edgeLabels;
+    private final Parameters parameters = new Parameters();
+
+    public VertexStepGV(final Traversal.Admin traversal, final Class<E> 
returnClass, final Direction direction, final GValue<String>... edgeLabels) {
+        super(traversal, new VertexStep(traversal, returnClass, direction,
+                
Arrays.stream(edgeLabels).map(GValue::get).toArray(String[]::new)));
+        this.edgeLabels = edgeLabels;
+    }
+
+    @Override
+    public void configure(final Object... keyValues) {
+        // all GValues locally stored in the parameters, but resolve them for 
the concrete step
+        this.parameters.set(null, GValue.promoteGValuesInKeyValues(keyValues));
+        this.concreteStep.configure(GValue.resolveGValues(keyValues));
+    }
+
+    @Override
+    public Parameters getParameters() {
+        return concreteStep.getParameters();
+    }
+
+    @Override
+    public Direction getDirection() {
+        return concreteStep.getDirection();
+    }
+
+    @Override
+    public GValue<String>[] getEdgeLabels() {
+        return edgeLabels;
+    }
+
+    @Override
+    public Class<E> getReturnClass() {
+        return concreteStep.getReturnClass();
+    }
+}
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/structure/map/VertexStepStructure.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/structure/map/VertexStepStructure.java
new file mode 100644
index 0000000000..7cba0bd87b
--- /dev/null
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/structure/map/VertexStepStructure.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tinkerpop.gremlin.process.traversal.step.util.structure.map;
+
+import org.apache.tinkerpop.gremlin.process.traversal.step.Configuring;
+import org.apache.tinkerpop.gremlin.structure.Direction;
+
+public interface VertexStepStructure<E, A> extends Configuring {
+    public Direction getDirection();
+
+    public A[] getEdgeLabels();
+
+    public Class<E> getReturnClass();
+}
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/structure/sideEffect/AddPropertyStepGV.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/structure/sideEffect/AddPropertyStepGV.java
new file mode 100644
index 0000000000..c847958697
--- /dev/null
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/structure/sideEffect/AddPropertyStepGV.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package 
org.apache.tinkerpop.gremlin.process.traversal.step.util.structure.sideEffect;
+
+import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
+import 
org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.AddPropertyStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.GValue;
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.GValueStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.Parameters;
+import org.apache.tinkerpop.gremlin.structure.T;
+import org.apache.tinkerpop.gremlin.structure.VertexProperty;
+
+public class AddPropertyStepGV extends GValueStep<AddPropertyStep, Object, 
Object> implements AddPropertyStepStructure {
+    private final Parameters parameters = new Parameters();
+
+    public AddPropertyStepGV(final Traversal.Admin traversal, final 
VertexProperty.Cardinality cardinality,
+                             final Object keyObject, final GValue<Object> 
valueObject) {
+        super(traversal, new AddPropertyStep(traversal, cardinality, 
keyObject, valueObject.get()));
+        this.parameters.set(this, T.key, keyObject, T.value, valueObject);
+    }
+
+    @Override
+    public void configure(final Object... keyValues) {
+        // all GValues locally stored in the parameters, but resolve them for 
the concrete step
+        this.parameters.set(this, GValue.promoteGValuesInKeyValues(keyValues));
+        this.concreteStep.configure(GValue.resolveGValues(keyValues));
+    }
+
+    @Override
+    public Parameters getParameters() {
+        return this.parameters;
+    }
+
+    public VertexProperty.Cardinality getCardinality() {
+        return concreteStep.getCardinality();
+    }
+
+}
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/structure/sideEffect/AddPropertyStepStructure.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/structure/sideEffect/AddPropertyStepStructure.java
new file mode 100644
index 0000000000..0e00a2b5b3
--- /dev/null
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/structure/sideEffect/AddPropertyStepStructure.java
@@ -0,0 +1,28 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package 
org.apache.tinkerpop.gremlin.process.traversal.step.util.structure.sideEffect;
+
+import org.apache.tinkerpop.gremlin.process.traversal.step.Configuring;
+import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent;
+import org.apache.tinkerpop.gremlin.structure.VertexProperty;
+
+public interface AddPropertyStepStructure extends Configuring, TraversalParent 
{
+
+    public VertexProperty.Cardinality getCardinality();
+}
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/util/structure/sideEffect/InjectStepGV.java
similarity index 51%
copy from 
gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/InjectStep.java
copy to 
gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/structure/sideEffect/InjectStepGV.java
index 0502f18541..4764910ec8 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/util/structure/sideEffect/InjectStepGV.java
@@ -16,39 +16,25 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect;
+package 
org.apache.tinkerpop.gremlin.process.traversal.step.util.structure.sideEffect;
 
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
-import org.apache.tinkerpop.gremlin.util.iterator.ArrayIterator;
+import 
org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.InjectStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.GValue;
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.GValueStep;
 
-/**
- * @author Marko A. Rodriguez (http://markorodriguez.com)
- */
-public final class InjectStep<S> extends StartStep<S> {
-
-    private final S[] injections;
+import java.util.Arrays;
 
-    @SafeVarargs
-    public InjectStep(final Traversal.Admin traversal, final S... injections) {
-        super(traversal);
-        this.injections = injections;
-        this.start = new ArrayIterator<>(this.injections);
-    }
+public class InjectStepGV<S> extends GValueStep<InjectStep, S, S> implements 
InjectStepStructure<GValue<S>> {
 
-    @Override
-    public InjectStep<S> clone() {
-        final InjectStep<S> clone = (InjectStep<S>) super.clone();
-        clone.start = new ArrayIterator<>(clone.injections);
-        return clone;
-    }
+    private final GValue<S>[] injections;
 
-    @Override
-    public void reset() {
-        super.reset();
-        this.start = new ArrayIterator<>(this.injections);
+    public InjectStepGV(final Traversal.Admin traversal, final GValue<S>... 
injections) {
+        super(traversal, new InjectStep<>(traversal, 
Arrays.stream(injections).map(GValue::get).toArray(Object[]::new)));
+        this.injections = injections;
     }
 
-    public S[] getInjections() {
-        return this.injections;
+    public GValue<S>[] getInjections() {
+        return injections;
     }
 }
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/structure/sideEffect/InjectStepStructure.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/structure/sideEffect/InjectStepStructure.java
new file mode 100644
index 0000000000..44698339c1
--- /dev/null
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/structure/sideEffect/InjectStepStructure.java
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package 
org.apache.tinkerpop.gremlin.process.traversal.step.util.structure.sideEffect;
+
+public interface InjectStepStructure<S> {
+    public S[] getInjections();
+}
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/ConnectiveStrategy.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/ConnectiveStrategy.java
index d314b4d65c..0eed16fcc8 100644
--- 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/ConnectiveStrategy.java
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/ConnectiveStrategy.java
@@ -34,7 +34,6 @@ import 
org.apache.tinkerpop.gremlin.process.traversal.step.util.EmptyStep;
 import 
org.apache.tinkerpop.gremlin.process.traversal.strategy.AbstractTraversalStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper;
 
-import java.util.Collections;
 import java.util.List;
 import java.util.Set;
 
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/GValueReplacementStrategy.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/GValueReplacementStrategy.java
new file mode 100644
index 0000000000..1813c93622
--- /dev/null
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/GValueReplacementStrategy.java
@@ -0,0 +1,97 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration;
+
+import 
org.apache.tinkerpop.gremlin.process.computer.traversal.strategy.decoration.VertexProgramStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.Merge;
+import org.apache.tinkerpop.gremlin.process.traversal.Step;
+import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
+import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategy;
+import 
org.apache.tinkerpop.gremlin.process.traversal.step.TraversalOptionParent;
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.GValueStep;
+import 
org.apache.tinkerpop.gremlin.process.traversal.step.util.structure.map.MergeElementStepStructure;
+import 
org.apache.tinkerpop.gremlin.process.traversal.strategy.AbstractTraversalStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+public class GValueReplacementStrategy extends 
AbstractTraversalStrategy<TraversalStrategy.DecorationStrategy> implements 
TraversalStrategy.DecorationStrategy {
+    private static final GValueReplacementStrategy INSTANCE = new 
GValueReplacementStrategy();
+
+    /**
+     * This strategy needs to be the first decoration to run as it replaces 
the {@link GValueStep} with the concrete
+     * step.
+     */
+    private static final Set<Class<? extends DecorationStrategy>> POSTS = new 
HashSet<>(Arrays.asList(
+            ConnectiveStrategy.class, ElementIdStrategy.class, 
EventStrategy.class, PartitionStrategy.class,
+            RequirementsStrategy.class, SackStrategy.class, 
SeedStrategy.class, SideEffectStrategy.class,
+            SubgraphStrategy.class, VertexProgramStrategy.class));
+
+    private GValueReplacementStrategy() {
+    }
+
+    public static GValueReplacementStrategy instance() {
+        return INSTANCE;
+    }
+
+    @Override
+    public void apply(Traversal.Admin<?, ?> traversal) {
+        final List<GValueStep> gvalueSteps = 
TraversalHelper.getStepsOfAssignableClass(GValueStep.class, traversal);
+
+        // loop through the graphSteps and replace the GValueStep in the 
traversal with the concrete step
+        for (final GValueStep gvalueStep : gvalueSteps) {
+            if (gvalueStep instanceof GValueStep.MergeOptionStep) {
+                // fold  the option argument into the previous step which 
should be a concrete step. we get in theis
+                // situation where a step like mergeV/E takes a concrete 
argument, but its associated option() takes
+                // a GValue. we can't fold that GValue in at traversal 
creation time. so this section of code cleans
+                // it all up.
+                if (gvalueStep.getPreviousStep() instanceof 
TraversalOptionParent) {
+                    final TraversalOptionParent parent = 
(TraversalOptionParent) gvalueStep.getPreviousStep();
+                    if (gvalueStep instanceof MergeElementStepStructure) {
+                        final MergeElementStepStructure 
mergeElementStepStructure = (MergeElementStepStructure) gvalueStep;
+                        if (mergeElementStepStructure.getOnCreateTraversal() 
!= null)
+                            parent.addChildOption(Merge.onCreate, 
mergeElementStepStructure.getOnCreateTraversal());
+                        else if 
(mergeElementStepStructure.getOnMatchTraversal() != null)
+                            parent.addChildOption(Merge.onMatch, 
mergeElementStepStructure.getOnMatchTraversal());
+                        else
+                            throw new IllegalStateException("No option found 
for MergeElementStepStructure");
+                    } else {
+                        throw new IllegalStateException("The GValueStep is not 
an option argument for a TraversalOptionParent");
+                    }
+                } else {
+                    throw new IllegalStateException("The GValueStep is not an 
option argument for a TraversalOptionParent");
+                }
+
+                // remove the step since its just an option argument
+                traversal.removeStep(gvalueStep);
+            } else {
+                final Step concreteStep = gvalueStep.getConcreteStep();
+                TraversalHelper.replaceStep(gvalueStep, concreteStep, 
traversal);
+            }
+        }
+    }
+
+    @Override
+    public Set<Class<? extends DecorationStrategy>> applyPost() {
+        return POSTS;
+    }
+}
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalHelper.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalHelper.java
index 19117d6e9a..707ade5340 100644
--- 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalHelper.java
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalHelper.java
@@ -47,14 +47,16 @@ import 
org.apache.tinkerpop.gremlin.process.traversal.step.map.VertexStep;
 import 
org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.StartStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.util.BulkSet;
 import org.apache.tinkerpop.gremlin.process.traversal.step.util.EmptyStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.GValue;
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.GValueStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.util.HasContainer;
+import 
org.apache.tinkerpop.gremlin.process.traversal.step.util.structure.filter.HasStepGV;
 import org.apache.tinkerpop.gremlin.structure.Graph;
 import org.apache.tinkerpop.gremlin.structure.T;
 import org.apache.tinkerpop.gremlin.util.iterator.IteratorUtils;
 
 import java.util.ArrayList;
 import java.util.Collection;
-import java.util.Comparator;
 import java.util.EnumSet;
 import java.util.HashSet;
 import java.util.LinkedHashSet;
@@ -296,8 +298,8 @@ public final class TraversalHelper {
     /**
      * Get steps of the specified classes throughout the traversal.
      */
-    public static List<Step<?,?>> getStepsOfAssignableClassRecursively(final 
Traversal.Admin<?, ?> traversal, final Class<?>... stepClasses) {
-        final List<Step<?,?>> list = new ArrayList<>();
+    public static List<Step<?, ?>> getStepsOfAssignableClassRecursively(final 
Traversal.Admin<?, ?> traversal, final Class<?>... stepClasses) {
+        final List<Step<?, ?>> list = new ArrayList<>();
         for (final Step<?, ?> step : traversal.getSteps()) {
             for (Class<?> stepClass : stepClasses) {
                 if (stepClass.isAssignableFrom(step.getClass()))
@@ -320,14 +322,14 @@ public final class TraversalHelper {
      * Get steps of the specified classes throughout the traversal, collecting 
them in a fashion that orders them
      * from the deepest steps first.
      */
-    public static List<Step<?,?>> 
getStepsOfAssignableClassRecursivelyFromDepth(final Traversal.Admin<?, ?> 
traversal, final Class<?>... stepClasses) {
-        final List<Step<?,?>> list = new ArrayList<>();
-        final Stack<Step<?,?>> stack = new Stack<>();
+    public static List<Step<?, ?>> 
getStepsOfAssignableClassRecursivelyFromDepth(final Traversal.Admin<?, ?> 
traversal, final Class<?>... stepClasses) {
+        final List<Step<?, ?>> list = new ArrayList<>();
+        final Stack<Step<?, ?>> stack = new Stack<>();
 
         traversal.getSteps().forEach(stack::push);
 
         while (!stack.isEmpty()) {
-            final Step<?,?> current = stack.pop();
+            final Step<?, ?> current = stack.pop();
             list.add(current);
 
             if (current instanceof TraversalParent) {
@@ -782,10 +784,24 @@ public final class TraversalHelper {
      * @return the has container folded or appended traversal
      */
     public static <T extends Traversal.Admin<?, ?>> T addHasContainer(final T 
traversal, final HasContainer hasContainer) {
-        if (traversal.getEndStep() instanceof HasContainerHolder) {
-            ((HasContainerHolder) 
traversal.getEndStep()).addHasContainer(hasContainer);
-            return traversal;
-        } else
-            return (T) traversal.addStep(new HasStep<>(traversal, 
hasContainer));
+        final boolean containsGValue = 
GValue.hasGValueInP(hasContainer.getPredicate());
+        final Step<?, ?> endStep = traversal.getEndStep();
+
+        // when there is a GValue in the hasContainer then it cannot be folded 
into the previous HasContainerHolder
+        // unless it too held GValue objects.
+        if (containsGValue) {
+            if (endStep instanceof HasContainerHolder && endStep instanceof 
GValueStep) {
+                ((HasContainerHolder) endStep).addHasContainer(hasContainer);
+                return traversal;
+            } else
+                return (T) traversal.addStep(new HasStepGV<>(traversal, 
hasContainer));
+        } else {
+            if (traversal.getEndStep() instanceof HasContainerHolder) {
+                ((HasContainerHolder) 
traversal.getEndStep()).addHasContainer(hasContainer);
+                return traversal;
+            } else
+                return (T) traversal.addStep(new HasStep<>(traversal, 
hasContainer));
+        }
+
     }
 }
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/ArrayUtil.java 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/ArrayUtil.java
new file mode 100644
index 0000000000..3d35909348
--- /dev/null
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/ArrayUtil.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tinkerpop.gremlin.util;
+
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.GValue;
+
+public class ArrayUtil {
+
+    /**
+     * Copies the given array and adds the given element at the beginning of 
the new array.
+     * <p>
+     * The new array contains the same elements of the input array plus the 
given element in the first position. The
+     * component type of the new array is the same as that of the input array.
+     * </p>
+     * <p>
+     * If the input array is {@code null}, a new one element array is returned 
whose component type is the same as the
+     * element.
+     * </p>
+     */
+    public static GValue[] addFirst(final GValue[] array, final GValue 
element) {
+        final GValue[] elements = new GValue[array.length + 1];
+        elements[0] = element;
+        System.arraycopy(array, 0, elements, 1, array.length);
+        return elements;
+    }
+}


Reply via email to