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

xiazcy pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/tinkerpop.git


The following commit(s) were added to refs/heads/master by this push:
     new a0cf823bf6 Implement asString(), length(), toLower(), and toUpper() 
String Functions (#2205)
a0cf823bf6 is described below

commit a0cf823bf663d80b733ab56d57a22f215517f42f
Author: Yang Xia <55853655+xia...@users.noreply.github.com>
AuthorDate: Mon Sep 18 12:37:59 2023 -0700

    Implement asString(), length(), toLower(), and toUpper() String Functions 
(#2205)
    
    * add asString(), length(), toLower(), and toUpper() string functions
    
    * clean up & update length() to return int
---
 CHANGELOG.asciidoc                                 |   2 +
 docs/src/dev/developer/for-committers.asciidoc     |   5 +-
 docs/src/dev/provider/gremlin-semantics.asciidoc   | 102 +++++++++++++-
 docs/src/reference/the-traversal.asciidoc          |  68 ++++++++++
 docs/src/upgrade/release-3.7.x.asciidoc            |  62 +++++++++
 .../grammar/DefaultGremlinBaseVisitor.java         |  16 +++
 .../language/grammar/TraversalMethodVisitor.java   |  32 +++++
 .../traversal/dsl/graph/GraphTraversal.java        |  59 +++++++++
 .../gremlin/process/traversal/dsl/graph/__.java    |  28 ++++
 .../process/traversal/step/map/AsStringStep.java   |  51 +++++++
 .../process/traversal/step/map/LengthStep.java     |  60 +++++++++
 .../process/traversal/step/map/ToLowerStep.java    |  60 +++++++++
 .../process/traversal/step/map/ToUpperStep.java    |  60 +++++++++
 .../traversal/translator/PythonTranslator.java     |   3 +
 .../process/traversal/util/BytecodeHelper.java     |   8 ++
 .../grammar/TraversalMethodVisitorTest.java        |  20 +++
 .../traversal/step/map/AsStringStepTest.java       |  62 +++++++++
 .../process/traversal/step/map/LengthStepTest.java |  56 ++++++++
 .../traversal/step/map/ToLowerStepTest.java        |  55 ++++++++
 .../traversal/step/map/ToUpperStepTest.java        |  55 ++++++++
 .../Process/Traversal/GraphTraversal.cs            |  36 +++++
 .../src/Gremlin.Net/Process/Traversal/__.cs        |  32 +++++
 .../Gherkin/CommonSteps.cs                         |   1 +
 .../Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs |  18 +++
 gremlin-go/driver/anonymousTraversal.go            |  28 ++++
 gremlin-go/driver/cucumber/cucumberSteps_test.go   |   1 +
 gremlin-go/driver/cucumber/gremlin.go              |  18 +++
 gremlin-go/driver/graph.go                         |   8 +-
 gremlin-go/driver/graphTraversal.go                |  24 ++++
 .../lib/process/graph-traversal.js                 |  44 +++++++
 .../test/cucumber/feature-steps.js                 |   1 +
 .../gremlin-javascript/test/cucumber/gremlin.js    |  18 +++
 gremlin-language/src/main/antlr4/Gremlin.g4        |  21 +++
 .../gremlin_python/process/graph_traversal.py      |  58 +++++++-
 .../src/main/python/radish/feature_steps.py        |   2 +
 gremlin-python/src/main/python/radish/gremlin.py   |  18 +++
 .../tinkerpop/gremlin/features/StepDefinition.java |   3 +
 .../gremlin/test/features/map/AsString.feature     | 146 +++++++++++++++++++++
 .../gremlin/test/features/map/Length.feature       |  60 +++++++++
 .../gremlin/test/features/map/ToLower.feature      |  75 +++++++++++
 .../gremlin/test/features/map/ToUpper.feature      |  74 +++++++++++
 41 files changed, 1543 insertions(+), 7 deletions(-)

diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc
index 797dd7262b..e917de0d91 100644
--- a/CHANGELOG.asciidoc
+++ b/CHANGELOG.asciidoc
@@ -25,6 +25,8 @@ 
image::https://raw.githubusercontent.com/apache/tinkerpop/master/docs/static/ima
 
 This release also includes changes from <<release-3-6-5, 3.6.6>> and 
<<release-3-5-8, 3.5.8>>.
 
+* Added the `asString()`, `length()`, `toLower()`, and `toUpper()` steps to 
perform `String` manipulations.
+* Added Gherkin parsing support for specific string results using `str[]`.
 
 
 [[release-3-7.0]]
diff --git a/docs/src/dev/developer/for-committers.asciidoc 
b/docs/src/dev/developer/for-committers.asciidoc
index 2785894eaa..c5a90d785e 100644
--- a/docs/src/dev/developer/for-committers.asciidoc
+++ b/docs/src/dev/developer/for-committers.asciidoc
@@ -425,7 +425,10 @@ edges, maps, and any other available type.
 * Set - *s[_xxx_,_yyy_,_zzz_,...]* - A comma separated collection of values 
that make up the set should be added to
 between the square brackets. These values respect the type system thus 
allowing for creation of sets of vertices,
 edges, maps, and any other available type.
-* String - Any value not using the system notation will be interpreted as a 
string.
+* String - Any value not using the system notation will be interpreted as
+a string by default.
+** *str[_xxx_]* (Optional) - xxx should be replaced with a string. Optional 
notation used for specific string results,
+such as null and spaces.
 * T - *t[_xxx_]* - The "xxx" should be replaced with a value of the `T` enum, 
such as `id` or `label`.
 * Vertex - *v[_xxx_]* - The "xxx" should be replaced with the "name" property 
of a vertex in the graph. This syntax may
 include the `.id` suffix which would indicate getting the vertex identifier or 
the `.sid` suffix which gets a string
diff --git a/docs/src/dev/provider/gremlin-semantics.asciidoc 
b/docs/src/dev/provider/gremlin-semantics.asciidoc
index b35b0aa16d..c14604bf9b 100644
--- a/docs/src/dev/provider/gremlin-semantics.asciidoc
+++ b/docs/src/dev/provider/gremlin-semantics.asciidoc
@@ -524,6 +524,31 @@ fully demonstrative of Gremlin step semantics. It is also 
hard to simply read th
 step is meant to behave. This section discusses the semantics for individual 
steps to help users and providers
 understand implementation expectations.
 
+[[asString-step]]
+=== asString()
+
+*Description:* Returns the value of incoming traverser as strings
+
+*Syntax:* `asString()`
+
+[width="100%",options="header"]
+|=========================================================
+|Start Step |Mid Step |Modulated |Domain |Range
+|N |Y |N |`any` |`String`
+|=========================================================
+
+*Arguments:*
+
+None
+
+Null values from the incoming traverser are not processed and remain as null 
when returned.
+
+*Exceptions*
+* If the incoming traverser is a non-String value then an 
`IllegalArgumentException` will be thrown.
+
+See: 
link:https://github.com/apache/tinkerpop/tree/x.y.z/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AsStringStep.java[source],
+link:https://tinkerpop.apache.org/docs/x.y.z/reference/#asString-step[reference]
+
 [[call-step]]
 === call()
 
@@ -723,6 +748,31 @@ None
 
 None
 
+[[length-step]]
+=== length()
+
+*Description:* Returns the length incoming string traverser.
+
+*Syntax:* `length()`
+
+[width="100%",options="header"]
+|=========================================================
+|Start Step |Mid Step |Modulated |Domain |Range
+|N |Y |N |`String` |`Integer`
+|=========================================================
+
+*Arguments:*
+
+None
+
+Null values from the incoming traverser are not processed and remain as null 
when returned.
+
+*Exceptions*
+* If the incoming traverser is a non-String value then an 
`IllegalArgumentException` will be thrown.
+
+See: 
link:https://github.com/apache/tinkerpop/tree/x.y.z/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/LengthStep.java[source],
+link:https://tinkerpop.apache.org/docs/x.y.z/reference/#length-step[reference]
+
 [[merge-e-step]]
 === mergeE()
 
@@ -863,4 +913,54 @@ resolve to a `Map`.
 * As is common to Gremlin, it is expected that `Traversal` arguments may 
utilize `sideEffect()` steps.
 
 See: 
link:https://github.com/apache/tinkerpop/tree/x.y.z/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MergeVertexStep.java[source],
-link:https://tinkerpop.apache.org/docs/x.y.z/reference/#mergev-step[reference]
\ No newline at end of file
+link:https://tinkerpop.apache.org/docs/x.y.z/reference/#mergev-step[reference]
+
+[[toLower-step]]
+=== toLower()
+
+*Description:* Returns the lowercase representation of incoming string 
traverser.
+
+*Syntax:* `toLower()`
+
+[width="100%",options="header"]
+|=========================================================
+|Start Step |Mid Step |Modulated |Domain |Range
+|N |Y |N |`String` |`String`
+|=========================================================
+
+*Arguments:*
+
+None
+
+Null values from the incoming traverser are not processed and remain as null 
when returned.
+
+*Exceptions*
+* If the incoming traverser is a non-String value then an 
`IllegalArgumentException` will be thrown.
+
+See: 
link:https://github.com/apache/tinkerpop/tree/x.y.z/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ToLowerStep.java[source],
+link:https://tinkerpop.apache.org/docs/x.y.z/reference/#toLower-step[reference]
+
+[[toUpper-step]]
+=== toUpper()
+
+*Description:* Returns the uppercase representation of incoming string 
traverser.
+
+*Syntax:* `toUpper()`
+
+[width="100%",options="header"]
+|=========================================================
+|Start Step |Mid Step |Modulated |Domain |Range
+|N |Y |N |`String` |`String`
+|=========================================================
+
+*Arguments:*
+
+None
+
+Null values from the incoming traverser are not processed and remain as null 
when returned.
+
+*Exceptions*
+* If the incoming traverser is a non-String value then an 
`IllegalArgumentException` will be thrown.
+
+See: 
link:https://github.com/apache/tinkerpop/tree/x.y.z/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ToUpperStep.java[source],
+link:https://tinkerpop.apache.org/docs/x.y.z/reference/#toUpper-step[reference]
\ No newline at end of file
diff --git a/docs/src/reference/the-traversal.asciidoc 
b/docs/src/reference/the-traversal.asciidoc
index 62c52ab0c3..cdb5631771 100644
--- a/docs/src/reference/the-traversal.asciidoc
+++ b/docs/src/reference/the-traversal.asciidoc
@@ -731,6 +731,24 @@ g.V().hasLabel('software').as('a','b','c').
 
 
link:++https://tinkerpop.apache.org/javadocs/x.y.z/core/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.html#as-java.lang.String-java.lang.String...-++[`as(String,String...)`]
 
+[[asString-step]]
+=== AsString Step
+
+The `asString()`-step (*map*) returns the value of incoming traverser as 
strings. Null values are returned as a string value "null".
+
+[gremlin-groovy,modern]
+----
+g.V().hasLabel('person').values('age').asString() <1>
+g.V().hasLabel('person').values('age').asString().concat(' years old') <2>
+----
+
+<1> Return ages as string.
+<2> Return ages as string and use concat to generate phrases.
+
+*Additional References*
+
+link:++https://tinkerpop.apache.org/javadocs/x.y.z/core/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.html#asString--++[`asString()`]
+
 [[barrier-step]]
 === Barrier Step
 
@@ -1991,6 +2009,23 @@ g.V(1).properties().label()
 
 
link:++https://tinkerpop.apache.org/javadocs/x.y.z/core/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.html#label--++[`label()`]
 
+[[length-step]]
+=== Length Step
+
+The `length()`-step (*map*) returns the length incoming string traverser. Null 
values are not processed and remain as null when returned.
+If the incoming traverser is a non-String value then an 
`IllegalArgumentException` will be thrown.
+
+[gremlin-groovy,modern]
+----
+g.V().values('name').length() <1>
+----
+
+<1> Return the string length of all vertex names.
+
+*Additional References*
+
+link:++https://tinkerpop.apache.org/javadocs/x.y.z/core/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.html#length--++[`length()`]
+
 [[limit-step]]
 === Limit Step
 
@@ -4243,6 +4278,39 @@ 
link:++https://tinkerpop.apache.org/javadocs/x.y.z/core/org/apache/tinkerpop/gre
 
link:++https://tinkerpop.apache.org/javadocs/x.y.z/core/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.html#toV-org.apache.tinkerpop.gremlin.structure.Direction-++[`toV(Direction)`],
 
link:++https://tinkerpop.apache.org/javadocs/x.y.z/core/org/apache/tinkerpop/gremlin/structure/Direction.html++[`Direction`]
 
+[[toLower-step]]
+=== ToLower Step
+
+The `toLower()`-step (*map*) returns the lowercase representation of incoming 
string traverser. Null values are not processed and remain as null when 
returned.
+If the incoming traverser is a non-String value then an 
`IllegalArgumentException` will be thrown.
+
+[gremlin-groovy,modern]
+----
+g.inject("HELLO", "wORlD", null).toLower()
+----
+
+*Additional References*
+
+link:++https://tinkerpop.apache.org/javadocs/x.y.z/core/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.html#toLower--++[`toLower()`]
+
+[[toUpper-step]]
+=== ToUpper Step
+
+The `toUpper()`-step (*map*) returns the uppercase representation of incoming 
string traverser. Null values are not processed and remain as null when 
returned.
+If the incoming traverser is a non-String value then an 
`IllegalArgumentException` will be thrown.
+
+[gremlin-groovy,modern]
+----
+g.inject("hello", "wORlD", null).toUpper()
+g.V().values("name").toUpper() <1>
+----
+
+<1> Returns the upper case representation of all vertex names.
+
+*Additional References*
+
+link:++https://tinkerpop.apache.org/javadocs/x.y.z/core/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.html#toUpper--++[`toUpper()`]
+
 [[tree-step]]
 === Tree Step
 
diff --git a/docs/src/upgrade/release-3.7.x.asciidoc 
b/docs/src/upgrade/release-3.7.x.asciidoc
index b217f59be6..f8c57b7ed2 100644
--- a/docs/src/upgrade/release-3.7.x.asciidoc
+++ b/docs/src/upgrade/release-3.7.x.asciidoc
@@ -29,7 +29,69 @@ complete list of all the modifications that are part of this 
release.
 
 === Upgrading for Users
 
+==== String Manipulation Steps
+Additional String manipulation steps have been added to this version: 
`asString()`, `length()`, `toLower()`, `toUpper()`.
 
+The following example demonstrates the use of a closure to perform the above 
functions:
+[source,text]
+----
+gremlin> g.V().hasLabel("person").values("age").map{it.get().toString()}
+==>29
+==>27
+==>32
+==>35
+gremlin> g.V().values("name").map{it.get().length()}
+==>5
+==>5
+==>3
+==>4
+==>6
+==>5
+gremlin> g.inject("TO", "LoWeR", "cAsE").map{it.get().toLowerCase()}
+==>to
+==>lower
+==>case
+gremlin> g.V().values("name").map{it.get().toUpperCase()}
+==>MARKO
+==>VADAS
+==>LOP
+==>JOSH
+==>RIPPLE
+==>PETER
+----
+With these additional steps this operation can be performed with standard 
Gremlin syntax:
+[source,text]
+----
+gremlin> g.V().hasLabel("person").values("age").asString()
+==>29
+==>27
+==>32
+==>35
+gremlin> g.V().values("name").length()
+==>5
+==>5
+==>3
+==>4
+==>6
+==>5
+gremlin> g.inject("TO", "LoWeR", "cAsE").toLower()
+==>to
+==>lower
+==>case
+gremlin> g.V().values("name").toUpper()
+==>MARKO
+==>VADAS
+==>LOP
+==>JOSH
+==>RIPPLE
+==>PETER
+----
+
+See: link:https://issues.apache.org/jira/browse/TINKERPOP-2672[TINKERPOP-2672],
+link:https://tinkerpop.apache.org/docs/x.y.z/reference/#asString-step[asString()-step],
+link:https://tinkerpop.apache.org/docs/x.y.z/reference/#length-step[length()-step],
+link:https://tinkerpop.apache.org/docs/x.y.z/reference/#toLower-step[toLower()-step],
+link:https://tinkerpop.apache.org/docs/x.y.z/reference/#toUpper-step[toUpper()-step]
 
 === Upgrading for Providers
 
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/DefaultGremlinBaseVisitor.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/DefaultGremlinBaseVisitor.java
index ee160101c1..fbc432253b 100644
--- 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/DefaultGremlinBaseVisitor.java
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/DefaultGremlinBaseVisitor.java
@@ -921,6 +921,22 @@ public class DefaultGremlinBaseVisitor<T> extends 
AbstractParseTreeVisitor<T> im
         */
        @Override
        public T visitTraversalMethod_concat_String(final 
GremlinParser.TraversalMethod_concat_StringContext ctx) { notImplemented(ctx); 
return null; }
+       /**
+        * {@inheritDoc}
+        */
+       @Override public T visitTraversalMethod_asString_Empty(final 
GremlinParser.TraversalMethod_asString_EmptyContext ctx) { notImplemented(ctx); 
return null; }
+       /**
+        * {@inheritDoc}
+        */
+       @Override public T visitTraversalMethod_toUpper_Empty(final 
GremlinParser.TraversalMethod_toUpper_EmptyContext ctx) { notImplemented(ctx); 
return null; }
+       /**
+        * {@inheritDoc}
+        */
+       @Override public T visitTraversalMethod_toLower_Empty(final 
GremlinParser.TraversalMethod_toLower_EmptyContext ctx) { notImplemented(ctx); 
return null; }
+       /**
+        * {@inheritDoc}
+        */
+       @Override public T visitTraversalMethod_length_Empty(final 
GremlinParser.TraversalMethod_length_EmptyContext ctx) { notImplemented(ctx); 
return null; }
        /**
         * {@inheritDoc}
         */
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalMethodVisitor.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalMethodVisitor.java
index 68bf88ddb2..1208361955 100644
--- 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalMethodVisitor.java
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalMethodVisitor.java
@@ -1741,6 +1741,38 @@ public class TraversalMethodVisitor extends 
TraversalRootVisitor<GraphTraversal>
         return 
graphTraversal.concat(antlr.genericVisitor.parseStringVarargs(ctx.stringLiteralVarargs()));
     }
 
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public GraphTraversal visitTraversalMethod_asString_Empty(final 
GremlinParser.TraversalMethod_asString_EmptyContext ctx) {
+        return graphTraversal.asString();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public GraphTraversal visitTraversalMethod_toUpper_Empty(final 
GremlinParser.TraversalMethod_toUpper_EmptyContext ctx) {
+        return graphTraversal.toUpper();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public GraphTraversal visitTraversalMethod_toLower_Empty(final 
GremlinParser.TraversalMethod_toLower_EmptyContext ctx) {
+        return graphTraversal.toLower();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public GraphTraversal visitTraversalMethod_length_Empty(final 
GremlinParser.TraversalMethod_length_EmptyContext ctx) {
+        return graphTraversal.length();
+    }
+
     public GraphTraversal[] getNestedTraversalList(final 
GremlinParser.NestedTraversalListContext ctx) {
         return ctx.nestedTraversalExpr().nestedTraversal()
                 .stream()
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 aa1d2fabb7..dceb08bcc7 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
@@ -79,6 +79,7 @@ import 
org.apache.tinkerpop.gremlin.process.traversal.step.map.AddEdgeStartStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.AddEdgeStep;
 import 
org.apache.tinkerpop.gremlin.process.traversal.step.map.AddVertexStartStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.AddVertexStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.AsStringStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.CallStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.CoalesceStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.ConcatStep;
@@ -100,6 +101,7 @@ import 
org.apache.tinkerpop.gremlin.process.traversal.step.map.LabelStep;
 import 
org.apache.tinkerpop.gremlin.process.traversal.step.map.LambdaCollectingBarrierStep;
 import 
org.apache.tinkerpop.gremlin.process.traversal.step.map.LambdaFlatMapStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.LambdaMapStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.LengthStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.LoopsStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.MatchStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.MathStep;
@@ -128,6 +130,8 @@ import 
org.apache.tinkerpop.gremlin.process.traversal.step.map.SelectStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.SumGlobalStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.SumLocalStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.TailLocalStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.ToLowerStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.ToUpperStep;
 import 
org.apache.tinkerpop.gremlin.process.traversal.step.map.TraversalFlatMapStep;
 import 
org.apache.tinkerpop.gremlin.process.traversal.step.map.TraversalMapStep;
 import 
org.apache.tinkerpop.gremlin.process.traversal.step.map.TraversalSelectStep;
@@ -1437,6 +1441,57 @@ public interface GraphTraversal<S, E> extends 
Traversal<S, E> {
         return this.asAdmin().addStep(new ConcatStep<>(this.asAdmin(), 
concatStrings));
     }
 
+    /**
+     * Returns the value of incoming traverser as strings. Null values are 
returned as a string value "null".
+     *
+     * @return the traversal with an appended {@link AsStringStep}.
+     * @see <a 
href="http://tinkerpop.apache.org/docs/${project.version}/reference/#asString-step";
 target="_blank">Reference Documentation - AsString Step</a>
+     * @since 3.7.1
+     */
+    public default GraphTraversal<S, String> asString() {
+        this.asAdmin().getBytecode().addStep(Symbols.asString);
+        return this.asAdmin().addStep(new AsStringStep<>(this.asAdmin()));
+    }
+
+    /**
+     * Returns the length incoming string traverser. Null values are not 
processed and remain as null when returned.
+     * If the incoming traverser is a non-String value then an {@code 
IllegalArgumentException} will be thrown.
+     *
+     * @return the traversal with an appended {@link LengthStep}.
+     * @see <a 
href="http://tinkerpop.apache.org/docs/${project.version}/reference/#length-step";
 target="_blank">Reference Documentation - Length Step</a>
+     * @since 3.7.1
+     */
+    public default GraphTraversal<S, Integer> length() {
+        this.asAdmin().getBytecode().addStep(Symbols.length);
+        return this.asAdmin().addStep(new LengthStep<>(this.asAdmin()));
+    }
+
+    /**
+     * Returns the lowercase representation of incoming string traverser. Null 
values are not processed and remain
+     * as null when returned. If the incoming traverser is a non-String value 
then an {@code IllegalArgumentException} will be thrown.
+     *
+     * @return the traversal with an appended {@link ToLowerStep}.
+     * @see <a 
href="http://tinkerpop.apache.org/docs/${project.version}/reference/#toLower-step";
 target="_blank">Reference Documentation - ToLower Step</a>
+     * @since 3.7.1
+     */
+    public default GraphTraversal<S, String> toLower() {
+        this.asAdmin().getBytecode().addStep(Symbols.toLower);
+        return this.asAdmin().addStep(new ToLowerStep<>(this.asAdmin()));
+    }
+
+    /**
+     * Returns the uppercase representation of incoming string traverser. Null 
values are not processed and
+     * remain as null when returned. If the incoming traverser is a non-String 
value then an {@code IllegalArgumentException} will be thrown.
+     *
+     * @return the traversal with an appended {@link ToUpperStep}.
+     * @see <a 
href="http://tinkerpop.apache.org/docs/${project.version}/reference/#toUpper-step";
 target="_blank">Reference Documentation - ToUpper Step</a>
+     * @since 3.7.1
+     */
+    public default GraphTraversal<S, String> toUpper() {
+        this.asAdmin().getBytecode().addStep(Symbols.toUpper);
+        return this.asAdmin().addStep(new ToUpperStep<>(this.asAdmin()));
+    }
+
     ///////////////////// FILTER STEPS /////////////////////
 
     /**
@@ -3500,6 +3555,10 @@ public interface GraphTraversal<S, E> extends 
Traversal<S, E> {
         public static final String call = "call";
         public static final String element = "element";
         public static final String concat = "concat";
+        public static final String asString = "asString";
+        public static final String toUpper = "toUpper";
+        public static final String toLower = "toLower";
+        public static final String length = "length";
 
         public static final String timeLimit = "timeLimit";
         public static final String simplePath = "simplePath";
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/__.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/__.java
index ab3aa9fa95..dac4cb2a58 100644
--- 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/__.java
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/__.java
@@ -601,6 +601,34 @@ public class __ {
         return __.<A>start().concat(concatString);
     }
 
+    /**
+     * @see GraphTraversal#asString()
+     */
+    public static <A> GraphTraversal<A, String> asString() {
+        return __.<A>start().asString();
+    }
+
+    /**
+     * @see GraphTraversal#length()
+     */
+    public static <A> GraphTraversal<A, Integer> length() {
+        return __.<A>start().length();
+    }
+
+    /**
+     * @see GraphTraversal#toLower()
+     */
+    public static <A> GraphTraversal<A, String> toLower() {
+        return __.<A>start().toLower();
+    }
+
+    /**
+     * @see GraphTraversal#toUpper()
+     */
+    public static <A> GraphTraversal<A, String> toUpper() {
+        return __.<A>start().toUpper();
+    }
+
     ///////////////////// FILTER STEPS /////////////////////
 
     /**
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AsStringStep.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AsStringStep.java
new file mode 100644
index 0000000000..57b8cd4d27
--- /dev/null
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AsStringStep.java
@@ -0,0 +1,51 @@
+/*
+ * 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.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 java.util.Collections;
+import java.util.Set;
+
+/**
+ * Reference implementation for asString() step, a mid-traversal step which 
returns the incoming traverser value
+ * as a string. Null values are returned as a string value "null".
+ *
+ * @author David Bechberger (http://bechberger.com)
+ * @author Yang Xia (http://github.com/xiazcy)
+ */
+public final class AsStringStep<S> extends ScalarMapStep<S, String> {
+
+    public AsStringStep(final Traversal.Admin traversal) {
+        super(traversal);
+    }
+
+    @Override
+    protected String map(final Traverser.Admin<S> traverser) {
+        return String.valueOf(traverser.get());
+    }
+
+    @Override
+    public Set<TraverserRequirement> getRequirements() {
+        return Collections.singleton(TraverserRequirement.OBJECT);
+    }
+
+}
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/LengthStep.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/LengthStep.java
new file mode 100644
index 0000000000..5f7008b29e
--- /dev/null
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/LengthStep.java
@@ -0,0 +1,60 @@
+/*
+ * 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.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 java.util.Collections;
+import java.util.Set;
+
+/**
+ * Reference implementation for length() step, a mid-traversal step which 
returns the length of the incoming string
+ * traverser. Null values are not processed and remain as null when returned. 
If the incoming traverser is a non-String
+ * value then an {@code IllegalArgumentException} will be thrown.
+ *
+ * @author David Bechberger (http://bechberger.com)
+ * @author Yang Xia (http://github.com/xiazcy)
+ */
+public final class LengthStep<S> extends ScalarMapStep<S, Integer> {
+
+    public LengthStep(final Traversal.Admin traversal) {
+        super(traversal);
+    }
+
+    @Override
+    protected Integer map(final Traverser.Admin<S> traverser) {
+        final S item = traverser.get();
+        // throws when incoming traverser isn't a string
+        if (null != item && !(item instanceof String)) {
+            throw new IllegalArgumentException(
+                    String.format("The length() step can only take string as 
argument, encountered %s", item.getClass()));
+        }
+
+        // we will pass null values to next step
+        return null == item? null : ((String) item).length();
+    }
+
+    @Override
+    public Set<TraverserRequirement> getRequirements() {
+        return Collections.singleton(TraverserRequirement.OBJECT);
+    }
+
+}
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ToLowerStep.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ToLowerStep.java
new file mode 100644
index 0000000000..84cc5dd184
--- /dev/null
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ToLowerStep.java
@@ -0,0 +1,60 @@
+/*
+ * 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.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 java.util.Collections;
+import java.util.Set;
+
+/**
+ * Reference implementation for toLower() step, a mid-traversal step which 
returns a lower case string representation
+ * of the incoming string traverser. Null values are not processed and remain 
as null when returned.
+ * If the incoming traverser is a non-String value then an {@code 
IllegalArgumentException} will be thrown.
+ *
+ * @author David Bechberger (http://bechberger.com)
+ * @author Yang Xia (http://github.com/xiazcy)
+ */
+public final class ToLowerStep<S> extends ScalarMapStep<S, String> {
+
+    public ToLowerStep(final Traversal.Admin traversal) {
+        super(traversal);
+    }
+
+    @Override
+    protected String map(final Traverser.Admin<S> traverser) {
+        final S item = traverser.get();
+        // throws when incoming traverser isn't a string
+        if (null != item && !(item instanceof String)) {
+            throw new IllegalArgumentException(
+                    String.format("The toLower() step can only take string as 
argument, encountered %s", item.getClass()));
+        }
+
+        // we will pass null values to next step
+        return null == item? null : ((String) item).toLowerCase();
+    }
+
+    @Override
+    public Set<TraverserRequirement> getRequirements() {
+        return Collections.singleton(TraverserRequirement.OBJECT);
+    }
+
+}
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ToUpperStep.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ToUpperStep.java
new file mode 100644
index 0000000000..0858153182
--- /dev/null
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ToUpperStep.java
@@ -0,0 +1,60 @@
+/*
+ * 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.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 java.util.Collections;
+import java.util.Set;
+
+/**
+ * Reference implementation for toUpper() step, a mid-traversal step which 
returns an upper case string representation
+ * of the incoming string traverser. Null values are not processed and remain 
as null when returned.
+ * If the incoming traverser is a non-String value then an {@code 
IllegalArgumentException} will be thrown.
+ *
+ * @author David Bechberger (http://bechberger.com)
+ * @author Yang Xia (http://github.com/xiazcy)
+ */
+public final class ToUpperStep<S> extends ScalarMapStep<S, String> {
+
+    public ToUpperStep(final Traversal.Admin traversal) {
+        super(traversal);
+    }
+
+    @Override
+    protected String map(final Traverser.Admin<S> traverser) {
+        final S item = traverser.get();
+        // throws when incoming traverser isn't a string
+        if (null != item && !(item instanceof String)) {
+            throw new IllegalArgumentException(
+                    String.format("The toUpper() step can only take string as 
argument, encountered %s", item.getClass()));
+        }
+
+        // we will pass null values to next step
+        return null == item? null : ((String) item).toUpperCase();
+    }
+
+    @Override
+    public Set<TraverserRequirement> getRequirements() {
+        return Collections.singleton(TraverserRequirement.OBJECT);
+    }
+
+}
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/translator/PythonTranslator.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/translator/PythonTranslator.java
index e26b02f8ad..aa325b36d9 100644
--- 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/translator/PythonTranslator.java
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/translator/PythonTranslator.java
@@ -430,6 +430,7 @@ public final class PythonTranslator implements 
Translator.ScriptTranslator {
             TO_PYTHON_MAP.put("all", "all_");
             TO_PYTHON_MAP.put("and", "and_");
             TO_PYTHON_MAP.put("as", "as_");
+            TO_PYTHON_MAP.put("asString", "as_string");
             TO_PYTHON_MAP.put("filter", "filter_");
             TO_PYTHON_MAP.put("from", "from_");
             TO_PYTHON_MAP.put("id", "id_");
@@ -449,6 +450,8 @@ public final class PythonTranslator implements 
Translator.ScriptTranslator {
             TO_PYTHON_MAP.put("range", "range_");
             TO_PYTHON_MAP.put("set", "set_");
             TO_PYTHON_MAP.put("sum", "sum_");
+            TO_PYTHON_MAP.put("toLower", "to_lower");
+            TO_PYTHON_MAP.put("toUpper", "to_upper");
             TO_PYTHON_MAP.put("with", "with_");
             //
             TO_PYTHON_MAP.forEach((k, v) -> FROM_PYTHON_MAP.put(v, k));
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/BytecodeHelper.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/BytecodeHelper.java
index 85c7191642..648d23557e 100644
--- 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/BytecodeHelper.java
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/BytecodeHelper.java
@@ -62,6 +62,7 @@ import 
org.apache.tinkerpop.gremlin.process.traversal.step.filter.WherePredicate
 import 
org.apache.tinkerpop.gremlin.process.traversal.step.filter.WhereTraversalStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.AddEdgeStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.AddVertexStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.AsStringStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.CallStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.CoalesceStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.ConcatStep;
@@ -82,6 +83,7 @@ import 
org.apache.tinkerpop.gremlin.process.traversal.step.map.LabelStep;
 import 
org.apache.tinkerpop.gremlin.process.traversal.step.map.LambdaCollectingBarrierStep;
 import 
org.apache.tinkerpop.gremlin.process.traversal.step.map.LambdaFlatMapStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.LambdaMapStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.LengthStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.LoopsStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.MatchStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.MathStep;
@@ -109,6 +111,8 @@ import 
org.apache.tinkerpop.gremlin.process.traversal.step.map.SelectStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.SumGlobalStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.SumLocalStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.TailLocalStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.ToLowerStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.ToUpperStep;
 import 
org.apache.tinkerpop.gremlin.process.traversal.step.map.TraversalFlatMapStep;
 import 
org.apache.tinkerpop.gremlin.process.traversal.step.map.TraversalMapStep;
 import 
org.apache.tinkerpop.gremlin.process.traversal.step.map.TraversalSelectStep;
@@ -198,6 +202,10 @@ public final class BytecodeHelper {
             put(GraphTraversal.Symbols.min, Arrays.asList(MinGlobalStep.class, 
MinGlobalStep.class));
             put(GraphTraversal.Symbols.mean, 
Arrays.asList(MeanGlobalStep.class, MeanLocalStep.class));
             put(GraphTraversal.Symbols.concat, 
Collections.singletonList(ConcatStep.class));
+            put(GraphTraversal.Symbols.asString, 
Collections.singletonList(AsStringStep.class));
+            put(GraphTraversal.Symbols.length, 
Collections.singletonList(LengthStep.class));
+            put(GraphTraversal.Symbols.toLower, 
Collections.singletonList(ToLowerStep.class));
+            put(GraphTraversal.Symbols.toUpper, 
Collections.singletonList(ToUpperStep.class));
             put(GraphTraversal.Symbols.group, Arrays.asList(GroupStep.class, 
GroupSideEffectStep.class));
             put(GraphTraversal.Symbols.groupCount, 
Arrays.asList(GroupCountStep.class, GroupCountSideEffectStep.class));
             put(GraphTraversal.Symbols.tree, Arrays.asList(TreeStep.class, 
TreeSideEffectStep.class));
diff --git 
a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalMethodVisitorTest.java
 
b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalMethodVisitorTest.java
index da2833ae91..657dcc9d8a 100644
--- 
a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalMethodVisitorTest.java
+++ 
b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalMethodVisitorTest.java
@@ -1143,4 +1143,24 @@ public class TraversalMethodVisitorTest {
         compare(g.V().coalesce(E(1,2),addE("person")),
                 eval("g.V().coalesce(__.E(1,2),__.addE('person'))"));
     }
+
+    @Test
+    public void shouldParseTraversalMethod_asString_Empty() throws Exception {
+        compare(g.V().asString(), eval("g.V().asString()"));
+    }
+
+    @Test
+    public void shouldParseTraversalMethod_toLower_Empty() throws Exception {
+        compare(g.V().toLower(), eval("g.V().toLower()"));
+    }
+
+    @Test
+    public void shouldParseTraversalMethod_toUpper_Empty() throws Exception {
+        compare(g.V().toUpper(), eval("g.V().toUpper()"));
+    }
+
+    @Test
+    public void shouldParseTraversalMethod_length_Empty() throws Exception {
+        compare(g.V().length(), eval("g.V().length()"));
+    }
 }
diff --git 
a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AsStringStepTest.java
 
b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AsStringStepTest.java
new file mode 100644
index 0000000000..a5391fc185
--- /dev/null
+++ 
b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AsStringStepTest.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.map;
+
+import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
+import org.apache.tinkerpop.gremlin.process.traversal.step.StepTest;
+import org.junit.Test;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+/**
+ * @author Yang Xia (http://github.com/xiazcy)
+ */
+public class AsStringStepTest extends StepTest {
+
+    @Override
+    protected List<Traversal> getTraversals() {
+        return Collections.singletonList(__.asString());
+    }
+
+    @Test
+    public void testReturnTypes() {
+        assertEquals("1", __.__(1).asString().next());
+        assertEquals("[]", __.__(Collections.emptyList()).asString().next());
+        assertEquals("[1, 2]", __.__(Arrays.asList(1, 2)).asString().next());
+        assertEquals("1", __.__(Arrays.asList(1, 
2)).unfold().asString().next());
+        assertArrayEquals(new String[]{"1", "2"}, __.inject(Arrays.asList(1, 
2)).unfold().asString().toList().toArray());
+
+        assertEquals("null", __.__(null).asString().next());
+
+        assertEquals("[1, 2]test", __.__(Arrays.asList(1, 
2)).asString().concat("test").next());
+        assertEquals("1test", __.__(Arrays.asList(1, 
2)).unfold().asString().concat("test").next());
+        assertArrayEquals(new String[]{"1test", "2test"},
+                __.__(Arrays.asList(1, 
2)).unfold().asString().concat("test").toList().toArray());
+        assertArrayEquals(new String[]{"1test", "2test"},
+                __.__(Arrays.asList(1, 
2)).unfold().asString().concat("test").fold().next().toArray());
+    }
+
+}
diff --git 
a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/LengthStepTest.java
 
b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/LengthStepTest.java
new file mode 100644
index 0000000000..22dfef9e90
--- /dev/null
+++ 
b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/LengthStepTest.java
@@ -0,0 +1,56 @@
+/*
+ * 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.map;
+
+import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
+import org.apache.tinkerpop.gremlin.process.traversal.step.StepTest;
+import org.junit.Test;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Optional;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+
+/**
+ * @author Yang Xia (http://github.com/xiazcy)
+ */
+public class LengthStepTest extends StepTest {
+
+    @Override
+    protected List<Traversal> getTraversals() {
+        return Collections.singletonList(__.length());
+    }
+
+    @Test
+    public void testReturnTypes() {
+        assertEquals(Integer.valueOf(4), __.__("test").length().next());
+        assertArrayEquals(new Integer[]{5, 4, null, 0}, __.inject("hello", 
"test", null, "").length().toList().toArray());
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void shouldThrowWithIncomingArrayList() {
+        __.__(Arrays.asList("a", "b", "c")).length().next();
+    }
+
+}
diff --git 
a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ToLowerStepTest.java
 
b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ToLowerStepTest.java
new file mode 100644
index 0000000000..edba0558e9
--- /dev/null
+++ 
b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ToLowerStepTest.java
@@ -0,0 +1,55 @@
+/*
+ * 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.map;
+
+import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
+import org.apache.tinkerpop.gremlin.process.traversal.step.StepTest;
+import org.junit.Test;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * @author Yang Xia (http://github.com/xiazcy)
+ */
+public class ToLowerStepTest extends StepTest {
+
+    @Override
+    protected List<Traversal> getTraversals() {
+        return Collections.singletonList(__.toLower());
+    }
+
+    @Test
+    public void testReturnTypes() {
+        assertEquals("test", __.__("TEST").toLower().next());
+        assertArrayEquals(new String[]{"hello", "test", "no.123", null, ""},
+                __.inject("hElLo", "TEST", "NO.123", null, 
"").toLower().toList().toArray());
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void shouldThrowWithIncomingArrayList() {
+        __.__(Arrays.asList("a", "b", "c")).toLower().next();
+    }
+
+}
diff --git 
a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ToUpperStepTest.java
 
b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ToUpperStepTest.java
new file mode 100644
index 0000000000..3d9cdd9447
--- /dev/null
+++ 
b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ToUpperStepTest.java
@@ -0,0 +1,55 @@
+/*
+ * 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.map;
+
+import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
+import org.apache.tinkerpop.gremlin.process.traversal.step.StepTest;
+import org.junit.Test;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * @author Yang Xia (http://github.com/xiazcy)
+ */
+public class ToUpperStepTest extends StepTest {
+
+    @Override
+    protected List<Traversal> getTraversals() {
+        return Collections.singletonList(__.toUpper());
+    }
+
+    @Test
+    public void testReturnTypes() {
+        assertEquals("TEST", __.__("test").toUpper().next());
+        assertArrayEquals(new String[]{"HELLO", "TEST", "NO.123", null, ""},
+                __.inject("hElLo", "test", "no.123", null, 
"").toUpper().toList().toArray());
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void shouldThrowWithIncomingArrayList() {
+        __.__(Arrays.asList("a", "b", "c")).toUpper().next();
+    }
+
+}
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GraphTraversal.cs 
b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GraphTraversal.cs
index f32dcae128..4c320407ae 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GraphTraversal.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GraphTraversal.cs
@@ -203,6 +203,15 @@ namespace Gremlin.Net.Process.Traversal
             Bytecode.AddStep("as", args.ToArray());
             return Wrap<TStart, TEnd>(this);
         }
+        
+        /// <summary>
+        ///     Adds the asString step to this <see 
cref="GraphTraversal{SType, EType}" />.
+        /// </summary>
+        public GraphTraversal<TStart, string> AsString ()
+        {
+            Bytecode.AddStep("asString");
+            return Wrap<TStart, string>(this);
+        }
 
         /// <summary>
         ///     Adds the barrier step to this <see cref="GraphTraversal{SType, 
EType}" />.
@@ -1115,6 +1124,15 @@ namespace Gremlin.Net.Process.Traversal
             Bytecode.AddStep("label");
             return Wrap<TStart, string>(this);
         }
+        
+        /// <summary>
+        ///     Adds the length step to this <see cref="GraphTraversal{SType, 
EType}" />.
+        /// </summary>
+        public GraphTraversal<TStart, int?> Length ()
+        {
+            Bytecode.AddStep("length");
+            return Wrap<TStart, int?>(this);
+        }
 
         /// <summary>
         ///     Adds the limit step to this <see cref="GraphTraversal{SType, 
EType}" />.
@@ -1932,6 +1950,24 @@ namespace Gremlin.Net.Process.Traversal
             Bytecode.AddStep("toE", args.ToArray());
             return Wrap<TStart, Edge>(this);
         }
+        
+        /// <summary>
+        ///     Adds the toLower step to this <see cref="GraphTraversal{SType, 
EType}" />.
+        /// </summary>
+        public GraphTraversal<TStart, string?> ToLower ()
+        {
+            Bytecode.AddStep("toLower");
+            return Wrap<TStart, string?>(this);
+        }
+        
+        /// <summary>
+        ///     Adds the toUpper step to this <see cref="GraphTraversal{SType, 
EType}" />.
+        /// </summary>
+        public GraphTraversal<TStart, string?> ToUpper ()
+        {
+            Bytecode.AddStep("toUpper");
+            return Wrap<TStart, string?>(this);
+        }
 
         /// <summary>
         ///     Adds the toV step to this <see cref="GraphTraversal{SType, 
EType}" />.
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/__.cs 
b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/__.cs
index 82b147cd75..354aea1450 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/__.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/__.cs
@@ -134,6 +134,14 @@ namespace Gremlin.Net.Process.Traversal
                 ? new GraphTraversal<object, object>().As(label)
                 : new GraphTraversal<object, object>().As(label, labels);      
      
         }
+        
+        /// <summary>
+        ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds 
the asString step to that traversal.
+        /// </summary>
+        public static GraphTraversal<object, string> AsString()
+        {
+            return new GraphTraversal<object, string>().AsString();            
+        }
 
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds 
the barrier step to that traversal.
@@ -772,6 +780,14 @@ namespace Gremlin.Net.Process.Traversal
         {
             return new GraphTraversal<object, string>().Label();            
         }
+        
+        /// <summary>
+        ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds 
the length step to that traversal.
+        /// </summary>
+        public static GraphTraversal<object, int?> Length()
+        {
+            return new GraphTraversal<object, int?>().Length();            
+        }
 
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds 
the limit step to that traversal.
@@ -1348,6 +1364,22 @@ namespace Gremlin.Net.Process.Traversal
                 ? new GraphTraversal<object, Edge>().ToE(direction)
                 : new GraphTraversal<object, Edge>().ToE(direction, 
edgeLabels);            
         }
+        
+        /// <summary>
+        ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds 
the toLower step to that traversal.
+        /// </summary>
+        public static GraphTraversal<object, string?> ToLower()
+        {
+            return new GraphTraversal<object, string?>().ToLower();            
+        }
+        
+        /// <summary>
+        ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds 
the ToUpper step to that traversal.
+        /// </summary>
+        public static GraphTraversal<object, string?> ToUpper()
+        {
+            return new GraphTraversal<object, string?>().ToUpper();            
+        }
 
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds 
the toV step to that traversal.
diff --git 
a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/CommonSteps.cs 
b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/CommonSteps.cs
index db99a831e2..ab453a49f8 100644
--- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/CommonSteps.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/CommonSteps.cs
@@ -57,6 +57,7 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
         private static readonly IDictionary<Regex, Func<string, string, 
object?>> Parsers =
             new Dictionary<string, Func<string, string, object?>>
             {
+                {@"str\[(.*)\]", (x, graphName) => x }, //returns the string 
value as is
                 {@"vp\[(.+)\]", ToVertexProperty},
                 {@"d\[(.*)\]\.([bsilfdmn])", ToNumber},
                 {@"D\[(.+)\]", ToDirection},
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs 
b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs
index 140a6fb68f..997075ba42 100644
--- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs
@@ -470,6 +470,14 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
                {"g_addVXpersonX_propertyXname_joshX_propertyXage_nullX", new 
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> 
{(g,p) =>g.AddV("person").Property("name","josh").Property("age",null), (g,p) 
=>g.V().Has("person","age",(object) null)}}, 
                
{"g_addVXpersonX_propertyXname_markoX_propertyXfriendWeight_null_acl_nullX", 
new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> 
{(g,p) 
=>g.AddV("person").Property("name","marko").Property("friendWeight",null,"acl",null),
 (g,p) =>g.V().Has("person","name","marko").Has("friendWeight",(object) null), 
(g,p) 
=>g.V().Has("person","name","marko").Properties<object>("friendWeight").Has("acl",(object)
 null), (g,p) =>g.V().Has("person","name","marko").Prop [...]
                
{"g_V_hasXperson_name_aliceX_propertyXsingle_age_unionXage_constantX1XX_sumX", 
new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> 
{(g,p) 
=>g.AddV("person").Property("name","alice").Property(Cardinality.Single,"age",50),
 (g,p) 
=>g.V().Has("person","name","alice").Property("age",__.Union<object>(__.Values<object>("age"),__.Constant<object>(1)).Sum<object>()),
 (g,p) =>g.V().Has("person","age",50), (g,p) =>g.V().Has("person","age",51)}}, 
+               {"g_injectX1_2X_asString", new List<Func<GraphTraversalSource, 
IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject(1,2).AsString()}}, 
+               {"g_injectX1_nullX_asString", new 
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> 
{(g,p) =>g.Inject<object>(1,null).AsString()}}, 
+               {"g_V_valueMapXnameX_asString", new 
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> 
{(g,p) =>g.V().ValueMap<object,object>("name").AsString()}}, 
+               {"g_V_asString", new List<Func<GraphTraversalSource, 
IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().AsString()}}, 
+               {"g_E_asString", new List<Func<GraphTraversalSource, 
IDictionary<string, object>, ITraversal>> {(g,p) =>g.E().AsString()}}, 
+               {"g_V_properties", new List<Func<GraphTraversalSource, 
IDictionary<string, object>, ITraversal>> {(g,p) 
=>g.V().Properties<object>().AsString()}}, 
+               {"g_V_hasLabelXpersonX_valuesXageX_asString", new 
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> 
{(g,p) =>g.V().HasLabel("person").Values<object>("age").AsString()}}, 
+               
{"g_V_hasLabelXpersonX_valuesXageX_asString_concatX_years_oldX", new 
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> 
{(g,p) 
=>g.V().HasLabel("person").Values<object>("age").AsString().Concat<object>(" 
years old")}}, 
                {"g_call", new List<Func<GraphTraversalSource, 
IDictionary<string, object>, ITraversal>> {(g,p) =>g.Call<object>()}}, 
                {"g_callXlistX", new List<Func<GraphTraversalSource, 
IDictionary<string, object>, ITraversal>> {(g,p) =>g.Call<object>("--list")}}, 
                {"g_callXlistX_withXstring_stringX", new 
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> 
{(g,p) =>g.Call<object>("--list").With("service","tinker.search")}}, 
@@ -562,6 +570,9 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
                
{"g_V_hasLabelXsoftwareX_name_fold_orderXlocalX_index_unfold_order_byXtailXlocal_1XX",
 new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> 
{(g,p) 
=>g.V().HasLabel("software").Values<object>("name").Fold().Order(Scope.Local).Index<object>().Unfold<object>().Order().By(__.Tail<object>(Scope.Local,1))}},
 
                {"g_V_hasLabelXpersonX_name_fold_orderXlocalX_index_withXmapX", 
new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> 
{(g,p) 
=>g.V().HasLabel("person").Values<object>("name").Fold().Order(Scope.Local).Index<object>().With("~tinkerpop.index.indexer",1)}},
 
                {"g_VX1X_valuesXageX_index_unfold_unfold", new 
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> 
{(g,p) 
=>g.V(p["vid1"]).Values<object>("age").Index<object>().Unfold<object>().Unfold<object>()}},
 
+               {"g_injectXfeature_test_nullX_length", new 
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> 
{(g,p) =>g.Inject<object>("feature","test",null).Length()}}, 
+               {"g_injectXListXa_bXX_length", new 
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> 
{(g,p) =>g.Inject(p["xx1"]).Length()}}, 
+               {"g_V_valuesXnameX_length", new List<Func<GraphTraversalSource, 
IDictionary<string, object>, ITraversal>> {(g,p) 
=>g.V().Values<object>("name").Length()}}, 
                
{"g_VX1X_repeatXboth_simplePathX_untilXhasXname_peterX_or_loops_isX3XX_hasXname_peterX_path_byXnameX",
 new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> 
{(g,p) 
=>g.V(p["vid1"]).Repeat(__.Both().SimplePath()).Until(__.Has("name","peter").Or().Loops().Is(3)).Has("name","peter").Path().By("name")}},
 
                
{"g_VX1X_repeatXboth_simplePathX_untilXhasXname_peterX_or_loops_isX2XX_hasXname_peterX_path_byXnameX",
 new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> 
{(g,p) 
=>g.V(p["vid1"]).Repeat(__.Both().SimplePath()).Until(__.Has("name","peter").Or().Loops().Is(2)).Has("name","peter").Path().By("name")}},
 
                
{"g_VX1X_repeatXboth_simplePathX_untilXhasXname_peterX_and_loops_isX3XX_hasXname_peterX_path_byXnameX",
 new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> 
{(g,p) 
=>g.V(p["vid1"]).Repeat(__.Both().SimplePath()).Until(__.Has("name","peter").And().Loops().Is(3)).Has("name","peter").Path().By("name")}},
 
@@ -926,6 +937,13 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
                {"g_injectXnull_10_5_nullX_sum", new 
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> 
{(g,p) =>g.Inject<object>(null,p["xx1"],p["xx2"],null).Sum<object>()}}, 
                {"g_injectXlistXnull_10_5_nullXX_sumXlocalX", new 
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> 
{(g,p) =>g.Inject(p["xx1"]).Sum<object>(Scope.Local)}}, 
                {"g_VX1X_valuesXageX_sumXlocalX", new 
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> 
{(g,p) =>g.V(p["vid1"]).Values<object>("age").Sum<object>(Scope.Local)}}, 
+               {"g_injectXfeature_test_nullX_toLower", new 
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> 
{(g,p) =>g.Inject<object>("FEATURE","tESt",null).ToLower()}}, 
+               {"g_injectXListXa_bXX_toLower", new 
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> 
{(g,p) =>g.Inject(p["xx1"]).ToLower()}}, 
+               {"g_V_valuesXnameX_toLower", new 
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> 
{(g,p) 
=>g.AddV("person").Property("name","MARKO").Property("age",29).As("marko").AddV("person").Property("name","VADAS").Property("age",27).As("vadas").AddV("software").Property("name","LOP").Property("lang","java").As("lop").AddV("person").Property("name","JOSH").Property("age",32).As("josh").AddV("software").Property("name","RIPPLE").Property("lang","java").As("rip
 [...]
+               {"g_injectXfeature_test_nullX_toUpper", new 
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> 
{(g,p) =>g.Inject<object>("feature","tESt",null).ToUpper()}}, 
+               {"g_injectXfeature_test_nullX_asString_toUpper", new 
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> 
{(g,p) =>g.Inject<object>("feature","tESt",null).AsString().ToUpper()}}, 
+               {"g_injectXListXa_bXX_toUpper", new 
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> 
{(g,p) =>g.Inject(p["xx1"]).ToUpper()}}, 
+               {"g_V_valuesXnameX_toUpper", new 
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> 
{(g,p) =>g.V().Values<object>("name").ToUpper()}}, 
                {"g_V_localXoutE_foldX_unfold", new 
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> 
{(g,p) =>g.V().Local<object>(__.OutE().Fold()).Unfold<object>()}}, 
                {"g_V_valueMap_unfold_mapXkeyX", new 
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> 
{(g,p) 
=>g.V().ValueMap<object,object>().Unfold<object>().Map<object>((IFunction) 
p["l1"])}}, 
                
{"g_VX1X_repeatXboth_simplePathX_untilXhasIdX6XX_path_byXnameX_unfold", new 
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> 
{(g,p) 
=>g.V(p["vid1"]).Repeat(__.Both().SimplePath()).Until(__.HasId(p["vid6"])).Path().By("name").Unfold<object>()}},
 
diff --git a/gremlin-go/driver/anonymousTraversal.go 
b/gremlin-go/driver/anonymousTraversal.go
index a6a03ecc17..8e57f347fb 100644
--- a/gremlin-go/driver/anonymousTraversal.go
+++ b/gremlin-go/driver/anonymousTraversal.go
@@ -59,6 +59,8 @@ type AnonymousTraversal interface {
        And(args ...interface{}) *GraphTraversal
        // As adds the as step to the GraphTraversal.
        As(args ...interface{}) *GraphTraversal
+       // AsString adds the asString step to the GraphTraversal.
+       AsString(args ...interface{}) *GraphTraversal
        // Barrier adds the barrier step to the GraphTraversal.
        Barrier(args ...interface{}) *GraphTraversal
        // Both adds the both step to the GraphTraversal.
@@ -147,6 +149,8 @@ type AnonymousTraversal interface {
        Key(args ...interface{}) *GraphTraversal
        // Label adds the label step to the GraphTraversal.
        Label(args ...interface{}) *GraphTraversal
+       // Length adds the length step to the GraphTraversal.
+       Length(args ...interface{}) *GraphTraversal
        // Limit adds the limit step to the GraphTraversal.
        Limit(args ...interface{}) *GraphTraversal
        // Local adds the local step to the GraphTraversal.
@@ -243,6 +247,10 @@ type AnonymousTraversal interface {
        To(args ...interface{}) *GraphTraversal
        // ToE adds the toE step to the GraphTraversal.
        ToE(args ...interface{}) *GraphTraversal
+       // ToLower adds the toLower step to the GraphTraversal.
+       ToLower(args ...interface{}) *GraphTraversal
+       // ToUpper adds the toUpper step to the GraphTraversal.
+       ToUpper(args ...interface{}) *GraphTraversal
        // ToV adds the toV step to the GraphTraversal.
        ToV(args ...interface{}) *GraphTraversal
        // Tree adds the tree step to the GraphTraversal.
@@ -317,6 +325,11 @@ func (anonymousTraversal *anonymousTraversal) As(args 
...interface{}) *GraphTrav
        return anonymousTraversal.graphTraversal().As(args...)
 }
 
+// AsString adds the asString step to the GraphTraversal.
+func (anonymousTraversal *anonymousTraversal) AsString(args ...interface{}) 
*GraphTraversal {
+       return anonymousTraversal.graphTraversal().AsString(args...)
+}
+
 // Barrier adds the barrier step to the GraphTraversal.
 func (anonymousTraversal *anonymousTraversal) Barrier(args ...interface{}) 
*GraphTraversal {
        return anonymousTraversal.graphTraversal().Barrier(args...)
@@ -537,6 +550,11 @@ func (anonymousTraversal *anonymousTraversal) Label(args 
...interface{}) *GraphT
        return anonymousTraversal.graphTraversal().Label(args...)
 }
 
+// Length adds the length step to the GraphTraversal.
+func (anonymousTraversal *anonymousTraversal) Length(args ...interface{}) 
*GraphTraversal {
+       return anonymousTraversal.graphTraversal().Length(args...)
+}
+
 // Limit adds the limit step to the GraphTraversal.
 func (anonymousTraversal *anonymousTraversal) Limit(args ...interface{}) 
*GraphTraversal {
        return anonymousTraversal.graphTraversal().Limit(args...)
@@ -777,6 +795,16 @@ func (anonymousTraversal *anonymousTraversal) ToE(args 
...interface{}) *GraphTra
        return anonymousTraversal.graphTraversal().ToE(args...)
 }
 
+// ToLower adds the toLower step to the GraphTraversal.
+func (anonymousTraversal *anonymousTraversal) ToLower(args ...interface{}) 
*GraphTraversal {
+       return anonymousTraversal.graphTraversal().ToLower(args...)
+}
+
+// ToUpper adds the toUpper step to the GraphTraversal.
+func (anonymousTraversal *anonymousTraversal) ToUpper(args ...interface{}) 
*GraphTraversal {
+       return anonymousTraversal.graphTraversal().ToUpper(args...)
+}
+
 // ToV adds the toV step to the GraphTraversal.
 func (anonymousTraversal *anonymousTraversal) ToV(args ...interface{}) 
*GraphTraversal {
        return anonymousTraversal.graphTraversal().ToV(args...)
diff --git a/gremlin-go/driver/cucumber/cucumberSteps_test.go 
b/gremlin-go/driver/cucumber/cucumberSteps_test.go
index c8c217037d..dee57762a5 100644
--- a/gremlin-go/driver/cucumber/cucumberSteps_test.go
+++ b/gremlin-go/driver/cucumber/cucumberSteps_test.go
@@ -46,6 +46,7 @@ var toListLock sync.Mutex
 
 func init() {
        parsers = map[*regexp.Regexp]func(string, string) interface{}{
+               regexp.MustCompile(`^str\[(.*)]$`): func(stringVal, graphName 
string) interface{} { return stringVal }, //returns the string value as is
                regexp.MustCompile(`^d\[(.*)]\.[bslfdmn]$`): toNumeric,
                regexp.MustCompile(`^d\[(.*)]\.[i]$`):       toInt32,
                regexp.MustCompile(`^vp\[(.+)]$`):           toVertexProperty,
diff --git a/gremlin-go/driver/cucumber/gremlin.go 
b/gremlin-go/driver/cucumber/gremlin.go
index 6019e19db8..e3e6665009 100644
--- a/gremlin-go/driver/cucumber/gremlin.go
+++ b/gremlin-go/driver/cucumber/gremlin.go
@@ -440,6 +440,14 @@ var translationMap = map[string][]func(g 
*gremlingo.GraphTraversalSource, p map[
     "g_addVXpersonX_propertyXname_joshX_propertyXage_nullX": {func(g 
*gremlingo.GraphTraversalSource, p map[string]interface{}) 
*gremlingo.GraphTraversal {return g.AddV("person").Property("name", 
"josh").Property("age", nil)}, func(g *gremlingo.GraphTraversalSource, p 
map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Has("person", 
"age", nil)}}, 
     
"g_addVXpersonX_propertyXname_markoX_propertyXfriendWeight_null_acl_nullX": 
{func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) 
*gremlingo.GraphTraversal {return g.AddV("person").Property("name", 
"marko").Property("friendWeight", nil, "acl", nil)}, func(g 
*gremlingo.GraphTraversalSource, p map[string]interface{}) 
*gremlingo.GraphTraversal {return g.V().Has("person", "name", 
"marko").Has("friendWeight", nil)}, func(g *gremlingo.GraphTraversalSource, p 
map[string]interfa [...]
     
"g_V_hasXperson_name_aliceX_propertyXsingle_age_unionXage_constantX1XX_sumX": 
{func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) 
*gremlingo.GraphTraversal {return g.AddV("person").Property("name", 
"alice").Property(gremlingo.Cardinality.Single, "age", 50)}, func(g 
*gremlingo.GraphTraversalSource, p map[string]interface{}) 
*gremlingo.GraphTraversal {return g.V().Has("person", "name", 
"alice").Property("age", gremlingo.T__.Union(gremlingo.T__.Values("age"), 
gremlingo.T_ [...]
+    "g_injectX1_2X_asString": {func(g *gremlingo.GraphTraversalSource, p 
map[string]interface{}) *gremlingo.GraphTraversal {return g.Inject(1, 
2).AsString()}}, 
+    "g_injectX1_nullX_asString": {func(g *gremlingo.GraphTraversalSource, p 
map[string]interface{}) *gremlingo.GraphTraversal {return g.Inject(1, 
nil).AsString()}}, 
+    "g_V_valueMapXnameX_asString": {func(g *gremlingo.GraphTraversalSource, p 
map[string]interface{}) *gremlingo.GraphTraversal {return 
g.V().ValueMap("name").AsString()}}, 
+    "g_V_asString": {func(g *gremlingo.GraphTraversalSource, p 
map[string]interface{}) *gremlingo.GraphTraversal {return g.V().AsString()}}, 
+    "g_E_asString": {func(g *gremlingo.GraphTraversalSource, p 
map[string]interface{}) *gremlingo.GraphTraversal {return g.E().AsString()}}, 
+    "g_V_properties": {func(g *gremlingo.GraphTraversalSource, p 
map[string]interface{}) *gremlingo.GraphTraversal {return 
g.V().Properties().AsString()}}, 
+    "g_V_hasLabelXpersonX_valuesXageX_asString": {func(g 
*gremlingo.GraphTraversalSource, p map[string]interface{}) 
*gremlingo.GraphTraversal {return 
g.V().HasLabel("person").Values("age").AsString()}}, 
+    "g_V_hasLabelXpersonX_valuesXageX_asString_concatX_years_oldX": {func(g 
*gremlingo.GraphTraversalSource, p map[string]interface{}) 
*gremlingo.GraphTraversal {return 
g.V().HasLabel("person").Values("age").AsString().Concat(" years old")}}, 
     "g_call": {func(g *gremlingo.GraphTraversalSource, p 
map[string]interface{}) *gremlingo.GraphTraversal {return g.Call()}}, 
     "g_callXlistX": {func(g *gremlingo.GraphTraversalSource, p 
map[string]interface{}) *gremlingo.GraphTraversal {return g.Call("--list")}}, 
     "g_callXlistX_withXstring_stringX": {func(g 
*gremlingo.GraphTraversalSource, p map[string]interface{}) 
*gremlingo.GraphTraversal {return g.Call("--list").With("service", 
"tinker.search")}}, 
@@ -532,6 +540,9 @@ var translationMap = map[string][]func(g 
*gremlingo.GraphTraversalSource, p map[
     
"g_V_hasLabelXsoftwareX_name_fold_orderXlocalX_index_unfold_order_byXtailXlocal_1XX":
 {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) 
*gremlingo.GraphTraversal {return 
g.V().HasLabel("software").Values("name").Fold().Order(gremlingo.Scope.Local).Index().Unfold().Order().By(gremlingo.T__.Tail(gremlingo.Scope.Local,
 1))}}, 
     "g_V_hasLabelXpersonX_name_fold_orderXlocalX_index_withXmapX": {func(g 
*gremlingo.GraphTraversalSource, p map[string]interface{}) 
*gremlingo.GraphTraversal {return 
g.V().HasLabel("person").Values("name").Fold().Order(gremlingo.Scope.Local).Index().With("~tinkerpop.index.indexer",
 1)}}, 
     "g_VX1X_valuesXageX_index_unfold_unfold": {func(g 
*gremlingo.GraphTraversalSource, p map[string]interface{}) 
*gremlingo.GraphTraversal {return 
g.V(p["vid1"]).Values("age").Index().Unfold().Unfold()}}, 
+    "g_injectXfeature_test_nullX_length": {func(g 
*gremlingo.GraphTraversalSource, p map[string]interface{}) 
*gremlingo.GraphTraversal {return g.Inject("feature", "test", nil).Length()}}, 
+    "g_injectXListXa_bXX_length": {func(g *gremlingo.GraphTraversalSource, p 
map[string]interface{}) *gremlingo.GraphTraversal {return 
g.Inject(p["xx1"]).Length()}}, 
+    "g_V_valuesXnameX_length": {func(g *gremlingo.GraphTraversalSource, p 
map[string]interface{}) *gremlingo.GraphTraversal {return 
g.V().Values("name").Length()}}, 
     
"g_VX1X_repeatXboth_simplePathX_untilXhasXname_peterX_or_loops_isX3XX_hasXname_peterX_path_byXnameX":
 {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) 
*gremlingo.GraphTraversal {return 
g.V(p["vid1"]).Repeat(gremlingo.T__.Both().SimplePath()).Until(gremlingo.T__.Has("name",
 "peter").Or().Loops().Is(3)).Has("name", "peter").Path().By("name")}}, 
     
"g_VX1X_repeatXboth_simplePathX_untilXhasXname_peterX_or_loops_isX2XX_hasXname_peterX_path_byXnameX":
 {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) 
*gremlingo.GraphTraversal {return 
g.V(p["vid1"]).Repeat(gremlingo.T__.Both().SimplePath()).Until(gremlingo.T__.Has("name",
 "peter").Or().Loops().Is(2)).Has("name", "peter").Path().By("name")}}, 
     
"g_VX1X_repeatXboth_simplePathX_untilXhasXname_peterX_and_loops_isX3XX_hasXname_peterX_path_byXnameX":
 {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) 
*gremlingo.GraphTraversal {return 
g.V(p["vid1"]).Repeat(gremlingo.T__.Both().SimplePath()).Until(gremlingo.T__.Has("name",
 "peter").And().Loops().Is(3)).Has("name", "peter").Path().By("name")}}, 
@@ -896,6 +907,13 @@ var translationMap = map[string][]func(g 
*gremlingo.GraphTraversalSource, p map[
     "g_injectXnull_10_5_nullX_sum": {func(g *gremlingo.GraphTraversalSource, p 
map[string]interface{}) *gremlingo.GraphTraversal {return g.Inject(nil, 
p["xx1"], p["xx2"], nil).Sum()}}, 
     "g_injectXlistXnull_10_5_nullXX_sumXlocalX": {func(g 
*gremlingo.GraphTraversalSource, p map[string]interface{}) 
*gremlingo.GraphTraversal {return 
g.Inject(p["xx1"]).Sum(gremlingo.Scope.Local)}}, 
     "g_VX1X_valuesXageX_sumXlocalX": {func(g *gremlingo.GraphTraversalSource, 
p map[string]interface{}) *gremlingo.GraphTraversal {return 
g.V(p["vid1"]).Values("age").Sum(gremlingo.Scope.Local)}}, 
+    "g_injectXfeature_test_nullX_toLower": {func(g 
*gremlingo.GraphTraversalSource, p map[string]interface{}) 
*gremlingo.GraphTraversal {return g.Inject("FEATURE", "tESt", nil).ToLower()}}, 
+    "g_injectXListXa_bXX_toLower": {func(g *gremlingo.GraphTraversalSource, p 
map[string]interface{}) *gremlingo.GraphTraversal {return 
g.Inject(p["xx1"]).ToLower()}}, 
+    "g_V_valuesXnameX_toLower": {func(g *gremlingo.GraphTraversalSource, p 
map[string]interface{}) *gremlingo.GraphTraversal {return 
g.AddV("person").Property("name", "MARKO").Property("age", 
29).As("marko").AddV("person").Property("name", "VADAS").Property("age", 
27).As("vadas").AddV("software").Property("name", "LOP").Property("lang", 
"java").As("lop").AddV("person").Property("name", "JOSH").Property("age", 
32).As("josh").AddV("software").Property("name", "RIPPLE").Property("lang", "ja 
[...]
+    "g_injectXfeature_test_nullX_toUpper": {func(g 
*gremlingo.GraphTraversalSource, p map[string]interface{}) 
*gremlingo.GraphTraversal {return g.Inject("feature", "tESt", nil).ToUpper()}}, 
+    "g_injectXfeature_test_nullX_asString_toUpper": {func(g 
*gremlingo.GraphTraversalSource, p map[string]interface{}) 
*gremlingo.GraphTraversal {return g.Inject("feature", "tESt", 
nil).AsString().ToUpper()}}, 
+    "g_injectXListXa_bXX_toUpper": {func(g *gremlingo.GraphTraversalSource, p 
map[string]interface{}) *gremlingo.GraphTraversal {return 
g.Inject(p["xx1"]).ToUpper()}}, 
+    "g_V_valuesXnameX_toUpper": {func(g *gremlingo.GraphTraversalSource, p 
map[string]interface{}) *gremlingo.GraphTraversal {return 
g.V().Values("name").ToUpper()}}, 
     "g_V_localXoutE_foldX_unfold": {func(g *gremlingo.GraphTraversalSource, p 
map[string]interface{}) *gremlingo.GraphTraversal {return 
g.V().Local(gremlingo.T__.OutE().Fold()).Unfold()}}, 
     "g_V_valueMap_unfold_mapXkeyX": {func(g *gremlingo.GraphTraversalSource, p 
map[string]interface{}) *gremlingo.GraphTraversal {return 
g.V().ValueMap().Unfold().Map(p["l1"])}}, 
     "g_VX1X_repeatXboth_simplePathX_untilXhasIdX6XX_path_byXnameX_unfold": 
{func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) 
*gremlingo.GraphTraversal {return 
g.V(p["vid1"]).Repeat(gremlingo.T__.Both().SimplePath()).Until(gremlingo.T__.HasId(p["vid6"])).Path().By("name").Unfold()}},
 
diff --git a/gremlin-go/driver/graph.go b/gremlin-go/driver/graph.go
index ade4c32ab3..3f7910274b 100644
--- a/gremlin-go/driver/graph.go
+++ b/gremlin-go/driver/graph.go
@@ -32,8 +32,8 @@ type Graph struct {
 // Element is the base structure for both Vertex and Edge.
 // The inherited identifier must be unique to the inheriting classes.
 type Element struct {
-       Id    interface{}
-       Label string
+       Id         interface{}
+       Label      string
        Properties interface{}
 }
 
@@ -75,12 +75,12 @@ type Path struct {
 
 // String returns the string representation of the vertex.
 func (v *Vertex) String() string {
-       return fmt.Sprintf("v[%s]", v.Id)
+       return fmt.Sprintf("v[%v]", v.Id)
 }
 
 // String returns the string representation of the edge.
 func (e *Edge) String() string {
-       return fmt.Sprintf("e[%s][%s-%s->%s]", e.Id, e.OutV.Id, e.Label, 
e.InV.Id)
+       return fmt.Sprintf("e[%v][%v-%s->%v]", e.Id, e.OutV.Id, e.Label, 
e.InV.Id)
 }
 
 // String returns the string representation of the vertex property.
diff --git a/gremlin-go/driver/graphTraversal.go 
b/gremlin-go/driver/graphTraversal.go
index 797774ec3e..4e651583fc 100644
--- a/gremlin-go/driver/graphTraversal.go
+++ b/gremlin-go/driver/graphTraversal.go
@@ -94,6 +94,12 @@ func (g *GraphTraversal) As(args ...interface{}) 
*GraphTraversal {
        return g
 }
 
+// AsString adds the asString step to the GraphTraversal.
+func (g *GraphTraversal) AsString(args ...interface{}) *GraphTraversal {
+       g.Bytecode.AddStep("asString", args...)
+       return g
+}
+
 // Barrier adds the barrier step to the GraphTraversal.
 func (g *GraphTraversal) Barrier(args ...interface{}) *GraphTraversal {
        // Force int32 serialization for valid number values for server 
compatibility
@@ -361,6 +367,12 @@ func (g *GraphTraversal) Label(args ...interface{}) 
*GraphTraversal {
        return g
 }
 
+// Length adds the length step to the GraphTraversal.
+func (g *GraphTraversal) Length(args ...interface{}) *GraphTraversal {
+       g.Bytecode.AddStep("length", args...)
+       return g
+}
+
 // Limit adds the limit step to the GraphTraversal.
 func (g *GraphTraversal) Limit(args ...interface{}) *GraphTraversal {
        g.Bytecode.AddStep("limit", args...)
@@ -651,6 +663,18 @@ func (g *GraphTraversal) ToE(args ...interface{}) 
*GraphTraversal {
        return g
 }
 
+// ToLower adds the toLower step to the GraphTraversal.
+func (g *GraphTraversal) ToLower(args ...interface{}) *GraphTraversal {
+       g.Bytecode.AddStep("toLower", args...)
+       return g
+}
+
+// ToUpper adds the toUpper step to the GraphTraversal.
+func (g *GraphTraversal) ToUpper(args ...interface{}) *GraphTraversal {
+       g.Bytecode.AddStep("toUpper", args...)
+       return g
+}
+
 // ToV adds the toV step to the GraphTraversal.
 func (g *GraphTraversal) ToV(args ...interface{}) *GraphTraversal {
        g.Bytecode.AddStep("toV", args...)
diff --git 
a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/process/graph-traversal.js
 
b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/process/graph-traversal.js
index b14a9e578c..114cf9503f 100644
--- 
a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/process/graph-traversal.js
+++ 
b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/process/graph-traversal.js
@@ -434,6 +434,16 @@ class GraphTraversal extends Traversal {
     return this;
   }
 
+  /**
+   * Graph traversal asString method.
+   * @param {...Object} args
+   * @returns {GraphTraversal}
+   */
+  asString(...args) {
+    this.bytecode.addStep('asString', args);
+    return this;
+  }
+
   /**
    * Graph traversal barrier method.
    * @param {...Object} args
@@ -872,6 +882,16 @@ class GraphTraversal extends Traversal {
     return this;
   }
 
+  /**
+   * Graph traversal length method.
+   * @param {...Object} args
+   * @returns {GraphTraversal}
+   */
+  length(...args) {
+    this.bytecode.addStep('length', args);
+    return this;
+  }
+
   /**
    * Graph traversal limit method.
    * @param {...Object} args
@@ -1352,6 +1372,26 @@ class GraphTraversal extends Traversal {
     return this;
   }
 
+  /**
+   * Graph traversal toLower method.
+   * @param {...Object} args
+   * @returns {GraphTraversal}
+   */
+  toLower(...args) {
+    this.bytecode.addStep('toLower', args);
+    return this;
+  }
+
+  /**
+   * Graph traversal toUpper method.
+   * @param {...Object} args
+   * @returns {GraphTraversal}
+   */
+  toUpper(...args) {
+    this.bytecode.addStep('toUpper', args);
+    return this;
+  }
+
   /**
    * Graph traversal toV method.
    * @param {...Object} args
@@ -1519,6 +1559,7 @@ const statics = {
   aggregate: (...args) => callOnEmptyTraversal('aggregate', args),
   and: (...args) => callOnEmptyTraversal('and', args),
   as: (...args) => callOnEmptyTraversal('as', args),
+  asString: (...args) => callOnEmptyTraversal('asString', args),
   barrier: (...args) => callOnEmptyTraversal('barrier', args),
   both: (...args) => callOnEmptyTraversal('both', args),
   bothE: (...args) => callOnEmptyTraversal('bothE', args),
@@ -1560,6 +1601,7 @@ const statics = {
   is: (...args) => callOnEmptyTraversal('is', args),
   key: (...args) => callOnEmptyTraversal('key', args),
   label: (...args) => callOnEmptyTraversal('label', args),
+  length: (...args) => callOnEmptyTraversal('length', args),
   limit: (...args) => callOnEmptyTraversal('limit', args),
   local: (...args) => callOnEmptyTraversal('local', args),
   loops: (...args) => callOnEmptyTraversal('loops', args),
@@ -1600,6 +1642,8 @@ const statics = {
   times: (...args) => callOnEmptyTraversal('times', args),
   to: (...args) => callOnEmptyTraversal('to', args),
   toE: (...args) => callOnEmptyTraversal('toE', args),
+  toLower: (...args) => callOnEmptyTraversal('toLower', args),
+  toUpper: (...args) => callOnEmptyTraversal('toUpper', args),
   toV: (...args) => callOnEmptyTraversal('toV', args),
   tree: (...args) => callOnEmptyTraversal('tree', args),
   unfold: (...args) => callOnEmptyTraversal('unfold', args),
diff --git 
a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/feature-steps.js
 
b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/feature-steps.js
index a44ebd6298..e67755c264 100644
--- 
a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/feature-steps.js
+++ 
b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/feature-steps.js
@@ -43,6 +43,7 @@ const direction = traversalModule.direction;
 const merge = traversalModule.merge;
 
 const parsers = [
+  [ 'str\\[(.*)\\]', (stringValue) => stringValue ], //returns the string 
value as is
   [ 'vp\\[(.+)\\]', toVertexProperty ],
   [ 'd\\[(.*)\\]\\.[bsilfdmn]', toNumeric ],
   [ 'v\\[(.+)\\]', toVertex ],
diff --git 
a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/gremlin.js
 
b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/gremlin.js
index f5984bb91b..e1d6d9c1b9 100644
--- 
a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/gremlin.js
+++ 
b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/gremlin.js
@@ -460,6 +460,14 @@ const gremlins = {
     g_addVXpersonX_propertyXname_joshX_propertyXage_nullX: [function({g}) { 
return g.addV("person").property("name","josh").property("age",null) }, 
function({g}) { return g.V().has("person","age",null) }], 
     g_addVXpersonX_propertyXname_markoX_propertyXfriendWeight_null_acl_nullX: 
[function({g}) { return 
g.addV("person").property("name","marko").property("friendWeight",null,"acl",null)
 }, function({g}) { return 
g.V().has("person","name","marko").has("friendWeight",null) }, function({g}) { 
return 
g.V().has("person","name","marko").properties("friendWeight").has("acl",null) 
}, function({g}) { return 
g.V().has("person","name","marko").properties("friendWeight").count() }], 
     
g_V_hasXperson_name_aliceX_propertyXsingle_age_unionXage_constantX1XX_sumX: 
[function({g}) { return 
g.addV("person").property("name","alice").property(Cardinality.single,"age",50) 
}, function({g}) { return 
g.V().has("person","name","alice").property("age",__.union(__.values("age"),__.constant(1)).sum())
 }, function({g}) { return g.V().has("person","age",50) }, function({g}) { 
return g.V().has("person","age",51) }], 
+    g_injectX1_2X_asString: [function({g}) { return g.inject(1,2).asString() 
}], 
+    g_injectX1_nullX_asString: [function({g}) { return 
g.inject(1,null).asString() }], 
+    g_V_valueMapXnameX_asString: [function({g}) { return 
g.V().valueMap("name").asString() }], 
+    g_V_asString: [function({g}) { return g.V().asString() }], 
+    g_E_asString: [function({g}) { return g.E().asString() }], 
+    g_V_properties: [function({g}) { return g.V().properties().asString() }], 
+    g_V_hasLabelXpersonX_valuesXageX_asString: [function({g}) { return 
g.V().hasLabel("person").values("age").asString() }], 
+    g_V_hasLabelXpersonX_valuesXageX_asString_concatX_years_oldX: 
[function({g}) { return 
g.V().hasLabel("person").values("age").asString().concat(" years old") }], 
     g_call: [function({g}) { return g.call() }], 
     g_callXlistX: [function({g}) { return g.call("--list") }], 
     g_callXlistX_withXstring_stringX: [function({g}) { return 
g.call("--list").with_("service","tinker.search") }], 
@@ -552,6 +560,9 @@ const gremlins = {
     
g_V_hasLabelXsoftwareX_name_fold_orderXlocalX_index_unfold_order_byXtailXlocal_1XX:
 [function({g}) { return 
g.V().hasLabel("software").values("name").fold().order(Scope.local).index().unfold().order().by(__.tail(Scope.local,1))
 }], 
     g_V_hasLabelXpersonX_name_fold_orderXlocalX_index_withXmapX: 
[function({g}) { return 
g.V().hasLabel("person").values("name").fold().order(Scope.local).index().with_("~tinkerpop.index.indexer",1)
 }], 
     g_VX1X_valuesXageX_index_unfold_unfold: [function({g, vid1}) { return 
g.V(vid1).values("age").index().unfold().unfold() }], 
+    g_injectXfeature_test_nullX_length: [function({g}) { return 
g.inject("feature","test",null).length() }], 
+    g_injectXListXa_bXX_length: [function({g, xx1}) { return 
g.inject(xx1).length() }], 
+    g_V_valuesXnameX_length: [function({g}) { return 
g.V().values("name").length() }], 
     
g_VX1X_repeatXboth_simplePathX_untilXhasXname_peterX_or_loops_isX3XX_hasXname_peterX_path_byXnameX:
 [function({g, vid1}) { return 
g.V(vid1).repeat(__.both().simplePath()).until(__.has("name","peter").or().loops().is(3)).has("name","peter").path().by("name")
 }], 
     
g_VX1X_repeatXboth_simplePathX_untilXhasXname_peterX_or_loops_isX2XX_hasXname_peterX_path_byXnameX:
 [function({g, vid1}) { return 
g.V(vid1).repeat(__.both().simplePath()).until(__.has("name","peter").or().loops().is(2)).has("name","peter").path().by("name")
 }], 
     
g_VX1X_repeatXboth_simplePathX_untilXhasXname_peterX_and_loops_isX3XX_hasXname_peterX_path_byXnameX:
 [function({g, vid1}) { return 
g.V(vid1).repeat(__.both().simplePath()).until(__.has("name","peter").and().loops().is(3)).has("name","peter").path().by("name")
 }], 
@@ -916,6 +927,13 @@ const gremlins = {
     g_injectXnull_10_5_nullX_sum: [function({g, xx1, xx2}) { return 
g.inject(null,xx1,xx2,null).sum() }], 
     g_injectXlistXnull_10_5_nullXX_sumXlocalX: [function({g, xx1}) { return 
g.inject(xx1).sum(Scope.local) }], 
     g_VX1X_valuesXageX_sumXlocalX: [function({g, vid1}) { return 
g.V(vid1).values("age").sum(Scope.local) }], 
+    g_injectXfeature_test_nullX_toLower: [function({g}) { return 
g.inject("FEATURE","tESt",null).toLower() }], 
+    g_injectXListXa_bXX_toLower: [function({g, xx1}) { return 
g.inject(xx1).toLower() }], 
+    g_V_valuesXnameX_toLower: [function({g}) { return 
g.addV("person").property("name","MARKO").property("age",29).as("marko").addV("person").property("name","VADAS").property("age",27).as("vadas").addV("software").property("name","LOP").property("lang","java").as("lop").addV("person").property("name","JOSH").property("age",32).as("josh").addV("software").property("name","RIPPLE").property("lang","java").as("ripple").addV("person").property("name","PETER").property("age",35).as("peter").
 [...]
+    g_injectXfeature_test_nullX_toUpper: [function({g}) { return 
g.inject("feature","tESt",null).toUpper() }], 
+    g_injectXfeature_test_nullX_asString_toUpper: [function({g}) { return 
g.inject("feature","tESt",null).asString().toUpper() }], 
+    g_injectXListXa_bXX_toUpper: [function({g, xx1}) { return 
g.inject(xx1).toUpper() }], 
+    g_V_valuesXnameX_toUpper: [function({g}) { return 
g.V().values("name").toUpper() }], 
     g_V_localXoutE_foldX_unfold: [function({g}) { return 
g.V().local(__.outE().fold()).unfold() }], 
     g_V_valueMap_unfold_mapXkeyX: [function({g, l1}) { return 
g.V().valueMap().unfold().map(l1) }], 
     g_VX1X_repeatXboth_simplePathX_untilXhasIdX6XX_path_byXnameX_unfold: 
[function({g, vid6, vid1}) { return 
g.V(vid1).repeat(__.both().simplePath()).until(__.hasId(vid6)).path().by("name").unfold()
 }], 
diff --git a/gremlin-language/src/main/antlr4/Gremlin.g4 
b/gremlin-language/src/main/antlr4/Gremlin.g4
index d4c4612af2..cd67d3aa6e 100644
--- a/gremlin-language/src/main/antlr4/Gremlin.g4
+++ b/gremlin-language/src/main/antlr4/Gremlin.g4
@@ -284,7 +284,12 @@ traversalMethod
     | traversalMethod_element
     | traversalMethod_call
     | traversalMethod_concat
+    | traversalMethod_asString
+    | traversalMethod_toUpper
+    | traversalMethod_toLower
+    | traversalMethod_length
     ;
+
 traversalMethod_V
     : 'V' LPAREN genericLiteralVarargs RPAREN
     ;
@@ -809,6 +814,22 @@ traversalMethod_concat
     | 'concat' LPAREN stringLiteralVarargs RPAREN 
#traversalMethod_concat_String
     ;
 
+traversalMethod_asString
+    : 'asString' LPAREN RPAREN #traversalMethod_asString_Empty
+    ;
+
+traversalMethod_toUpper
+    : 'toUpper' LPAREN RPAREN #traversalMethod_toUpper_Empty
+    ;
+
+traversalMethod_toLower
+    : 'toLower' LPAREN RPAREN #traversalMethod_toLower_Empty
+    ;
+
+traversalMethod_length
+    : 'length' LPAREN RPAREN #traversalMethod_length_Empty
+    ;
+
 /*********************************************
     ARGUMENT AND TERMINAL RULES
 **********************************************/
diff --git 
a/gremlin-python/src/main/python/gremlin_python/process/graph_traversal.py 
b/gremlin-python/src/main/python/gremlin_python/process/graph_traversal.py
index 82a7926feb..47b6e0a9b7 100644
--- a/gremlin-python/src/main/python/gremlin_python/process/graph_traversal.py
+++ b/gremlin-python/src/main/python/gremlin_python/process/graph_traversal.py
@@ -180,7 +180,7 @@ class GraphTraversalSource(object):
         return self.with_computer(graph_computer, workers, result, persist, 
vertices, edges, configuration)
 
     def with_computer(self, graph_computer=None, workers=None, result=None, 
persist=None, vertices=None,
-                  edges=None, configuration=None):
+                      edges=None, configuration=None):
         return self.with_strategies(
             VertexProgramStrategy(graph_computer, workers, result, persist, 
vertices, edges, configuration))
 
@@ -317,6 +317,10 @@ class GraphTraversal(Traversal):
         self.bytecode.add_step("as", *args)
         return self
 
+    def as_string(self, *args):
+        self.bytecode.add_step("asString", *args)
+        return self
+
     def barrier(self, *args):
         self.bytecode.add_step("barrier", *args)
         return self
@@ -591,6 +595,10 @@ class GraphTraversal(Traversal):
         self.bytecode.add_step("label", *args)
         return self
 
+    def length(self, *args):
+        self.bytecode.add_step("length", *args)
+        return self
+
     def limit(self, *args):
         self.bytecode.add_step("limit", *args)
         return self
@@ -860,6 +868,14 @@ class GraphTraversal(Traversal):
         self.bytecode.add_step("toE", *args)
         return self
 
+    def to_lower(self, *args):
+        self.bytecode.add_step("toLower", *args)
+        return self
+
+    def to_upper(self, *args):
+        self.bytecode.add_step("toUpper", *args)
+        return self
+
     def toV(self, *args):
         warnings.warn(
             "gremlin_python.process.GraphTraversalSource.toV will be replaced 
by "
@@ -983,6 +999,10 @@ class __(object, metaclass=MagicType):
     def as_(cls, *args):
         return cls.graph_traversal(None, None, Bytecode()).as_(*args)
 
+    @classmethod
+    def as_string(cls, *args):
+        return cls.graph_traversal(None, None, Bytecode()).as_string(*args)
+
     @classmethod
     def barrier(cls, *args):
         return cls.graph_traversal(None, None, Bytecode()).barrier(*args)
@@ -1251,6 +1271,10 @@ class __(object, metaclass=MagicType):
     def label(cls, *args):
         return cls.graph_traversal(None, None, Bytecode()).label(*args)
 
+    @classmethod
+    def length(cls, *args):
+        return cls.graph_traversal(None, None, Bytecode()).length(*args)
+
     @classmethod
     def limit(cls, *args):
         return cls.graph_traversal(None, None, Bytecode()).limit(*args)
@@ -1475,6 +1499,14 @@ class __(object, metaclass=MagicType):
     def to_e(cls, *args):
         return cls.graph_traversal(None, None, Bytecode()).to_e(*args)
 
+    @classmethod
+    def to_lower(cls, *args):
+        return cls.graph_traversal(None, None, Bytecode()).to_lower(*args)
+
+    @classmethod
+    def to_upper(cls, *args):
+        return cls.graph_traversal(None, None, Bytecode()).to_upper(*args)
+
     @classmethod
     def toV(cls, *args):
         warnings.warn(
@@ -1639,6 +1671,10 @@ def as_(*args):
     return __.as_(*args)
 
 
+def as_string(*args):
+    return __.as_string(*args)
+
+
 def barrier(*args):
     return __.barrier(*args)
 
@@ -1855,6 +1891,10 @@ def label(*args):
     return __.label(*args)
 
 
+def length(*args):
+    return __.length(*args)
+
+
 def limit(*args):
     return __.limit(*args)
 
@@ -2047,6 +2087,14 @@ def to_e(*args):
     return __.to_e(*args)
 
 
+def to_lower(*args):
+    return __.to_lower(*args)
+
+
+def to_upper(*args):
+    return __.to_upper(*args)
+
+
 def toV(*args):
     return __.to_v(*args)
 
@@ -2107,6 +2155,8 @@ statics.add_static('and_', and_)
 
 statics.add_static('as_', as_)
 
+statics.add_static('as_string', as_string)
+
 statics.add_static('barrier', barrier)
 
 statics.add_static('both', both)
@@ -2213,6 +2263,8 @@ statics.add_static('key', key)
 
 statics.add_static('label', label)
 
+statics.add_static('length', length)
+
 statics.add_static('limit', limit)
 
 statics.add_static('local', local)
@@ -2311,6 +2363,10 @@ statics.add_static('to_e', to_e)
 
 statics.add_static('toV', toV)
 
+statics.add_static('to_lower', to_lower)
+
+statics.add_static('to_upper', to_upper)
+
 statics.add_static('to_v', to_v)
 
 statics.add_static('tree', tree)
diff --git a/gremlin-python/src/main/python/radish/feature_steps.py 
b/gremlin-python/src/main/python/radish/feature_steps.py
index 9b4cd42727..fb0f7829ae 100644
--- a/gremlin-python/src/main/python/radish/feature_steps.py
+++ b/gremlin-python/src/main/python/radish/feature_steps.py
@@ -194,6 +194,8 @@ def _convert(val, ctx):
             # convert to tuple key if list/set as neither are hashable
             n[tuple(k) if isinstance(k, (set, list)) else k] = _convert(value, 
ctx)
         return n
+    elif isinstance(val, str) and re.match(r"^str\[.*\]$", val):  # return 
string as is
+        return val[4:-1]
     elif isinstance(val, str) and re.match(r"^l\[.*\]$", val):  # parse list
         return [] if val == "l[]" else list(map((lambda x: _convert(x, ctx)), 
val[2:-1].split(",")))
     elif isinstance(val, str) and re.match(r"^s\[.*\]$", val):  # parse set
diff --git a/gremlin-python/src/main/python/radish/gremlin.py 
b/gremlin-python/src/main/python/radish/gremlin.py
index 829d4492b3..1bc61f3ed4 100644
--- a/gremlin-python/src/main/python/radish/gremlin.py
+++ b/gremlin-python/src/main/python/radish/gremlin.py
@@ -441,6 +441,14 @@ world.gremlins = {
     'g_addVXpersonX_propertyXname_joshX_propertyXage_nullX': [(lambda 
g:g.addV('person').property('name','josh').property('age',None)), (lambda 
g:g.V().has('person','age',None))], 
     
'g_addVXpersonX_propertyXname_markoX_propertyXfriendWeight_null_acl_nullX': 
[(lambda 
g:g.addV('person').property('name','marko').property('friendWeight',None,'acl',None)),
 (lambda g:g.V().has('person','name','marko').has('friendWeight',None)), 
(lambda 
g:g.V().has('person','name','marko').properties('friendWeight').has('acl',None)),
 (lambda 
g:g.V().has('person','name','marko').properties('friendWeight').count())], 
     
'g_V_hasXperson_name_aliceX_propertyXsingle_age_unionXage_constantX1XX_sumX': 
[(lambda 
g:g.addV('person').property('name','alice').property(Cardinality.single,'age',50)),
 (lambda 
g:g.V().has('person','name','alice').property('age',__.union(__.age,__.constant(1)).sum_())),
 (lambda g:g.V().has('person','age',50)), (lambda 
g:g.V().has('person','age',51))], 
+    'g_injectX1_2X_asString': [(lambda g:g.inject(1,2).as_string())], 
+    'g_injectX1_nullX_asString': [(lambda g:g.inject(1,None).as_string())], 
+    'g_V_valueMapXnameX_asString': [(lambda 
g:g.V().valueMap('name').as_string())], 
+    'g_V_asString': [(lambda g:g.V().as_string())], 
+    'g_E_asString': [(lambda g:g.E().as_string())], 
+    'g_V_properties': [(lambda g:g.V().properties().as_string())], 
+    'g_V_hasLabelXpersonX_valuesXageX_asString': [(lambda 
g:g.V().hasLabel('person').age.as_string())], 
+    'g_V_hasLabelXpersonX_valuesXageX_asString_concatX_years_oldX': [(lambda 
g:g.V().hasLabel('person').age.as_string().concat(' years old'))], 
     'g_call': [(lambda g:g.call())], 
     'g_callXlistX': [(lambda g:g.call('--list'))], 
     'g_callXlistX_withXstring_stringX': [(lambda 
g:g.call('--list').with_('service','tinker.search'))], 
@@ -533,6 +541,9 @@ world.gremlins = {
     
'g_V_hasLabelXsoftwareX_name_fold_orderXlocalX_index_unfold_order_byXtailXlocal_1XX':
 [(lambda 
g:g.V().hasLabel('software').name.fold().order(Scope.local).index().unfold().order().by(__.tail(Scope.local,1)))],
 
     'g_V_hasLabelXpersonX_name_fold_orderXlocalX_index_withXmapX': [(lambda 
g:g.V().hasLabel('person').name.fold().order(Scope.local).index().with_('~tinkerpop.index.indexer',1))],
 
     'g_VX1X_valuesXageX_index_unfold_unfold': [(lambda g, 
vid1=None:g.V(vid1).age.index().unfold().unfold())], 
+    'g_injectXfeature_test_nullX_length': [(lambda 
g:g.inject('feature','test',None).length())], 
+    'g_injectXListXa_bXX_length': [(lambda g, 
xx1=None:g.inject(xx1).length())], 
+    'g_V_valuesXnameX_length': [(lambda g:g.V().name.length())], 
     
'g_VX1X_repeatXboth_simplePathX_untilXhasXname_peterX_or_loops_isX3XX_hasXname_peterX_path_byXnameX':
 [(lambda g, 
vid1=None:g.V(vid1).repeat(__.both().simplePath()).until(__.has('name','peter').or_().loops().is_(3)).has('name','peter').path().by('name'))],
 
     
'g_VX1X_repeatXboth_simplePathX_untilXhasXname_peterX_or_loops_isX2XX_hasXname_peterX_path_byXnameX':
 [(lambda g, 
vid1=None:g.V(vid1).repeat(__.both().simplePath()).until(__.has('name','peter').or_().loops().is_(2)).has('name','peter').path().by('name'))],
 
     
'g_VX1X_repeatXboth_simplePathX_untilXhasXname_peterX_and_loops_isX3XX_hasXname_peterX_path_byXnameX':
 [(lambda g, 
vid1=None:g.V(vid1).repeat(__.both().simplePath()).until(__.has('name','peter').and_().loops().is_(3)).has('name','peter').path().by('name'))],
 
@@ -897,6 +908,13 @@ world.gremlins = {
     'g_injectXnull_10_5_nullX_sum': [(lambda g, 
xx1=None,xx2=None:g.inject(None,xx1,xx2,None).sum_())], 
     'g_injectXlistXnull_10_5_nullXX_sumXlocalX': [(lambda g, 
xx1=None:g.inject(xx1).sum_(Scope.local))], 
     'g_VX1X_valuesXageX_sumXlocalX': [(lambda g, 
vid1=None:g.V(vid1).age.sum_(Scope.local))], 
+    'g_injectXfeature_test_nullX_toLower': [(lambda 
g:g.inject('FEATURE','tESt',None).to_lower())], 
+    'g_injectXListXa_bXX_toLower': [(lambda g, 
xx1=None:g.inject(xx1).to_lower())], 
+    'g_V_valuesXnameX_toLower': [(lambda 
g:g.addV('person').property('name','MARKO').property('age',29).as_('marko').addV('person').property('name','VADAS').property('age',27).as_('vadas').addV('software').property('name','LOP').property('lang','java').as_('lop').addV('person').property('name','JOSH').property('age',32).as_('josh').addV('software').property('name','RIPPLE').property('lang','java').as_('ripple').addV('person').property('name','PETER').property('age',35).as_('peter').addE(
 [...]
+    'g_injectXfeature_test_nullX_toUpper': [(lambda 
g:g.inject('feature','tESt',None).to_upper())], 
+    'g_injectXfeature_test_nullX_asString_toUpper': [(lambda 
g:g.inject('feature','tESt',None).as_string().to_upper())], 
+    'g_injectXListXa_bXX_toUpper': [(lambda g, 
xx1=None:g.inject(xx1).to_upper())], 
+    'g_V_valuesXnameX_toUpper': [(lambda g:g.V().name.to_upper())], 
     'g_V_localXoutE_foldX_unfold': [(lambda 
g:g.V().local(__.outE().fold()).unfold())], 
     'g_V_valueMap_unfold_mapXkeyX': [(lambda g, 
l1=None:g.V().valueMap().unfold().map(l1))], 
     'g_VX1X_repeatXboth_simplePathX_untilXhasIdX6XX_path_byXnameX_unfold': 
[(lambda g, 
vid6=None,vid1=None:g.V(vid1).repeat(__.both().simplePath()).until(__.hasId(vid6)).path().by('name').unfold())],
 
diff --git 
a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/features/StepDefinition.java
 
b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/features/StepDefinition.java
index 803320a0cd..d21d5efc64 100644
--- 
a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/features/StepDefinition.java
+++ 
b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/features/StepDefinition.java
@@ -164,6 +164,9 @@ public final class StepDefinition {
     }};
 
     private List<Pair<Pattern, Function<String,Object>>> 
objectMatcherConverters = new ArrayList<Pair<Pattern, 
Function<String,Object>>>() {{
+        // return the string values as is, used to wrap results that may 
contain other regex patterns
+        add(Pair.with(Pattern.compile("str\\[(.*)\\]"), String::valueOf));
+
         // expects json so that should port to the Gremlin script form - 
replace curly json braces with square ones
         // for Gremlin sake.
         add(Pair.with(Pattern.compile("m\\[(.*)\\]"), s -> {
diff --git 
a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/AsString.feature
 
b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/AsString.feature
new file mode 100644
index 0000000000..4f36f9e802
--- /dev/null
+++ 
b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/AsString.feature
@@ -0,0 +1,146 @@
+# 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.
+
+@StepClassMap @StepAsString
+Feature: Step - asString()
+
+  @GraphComputerVerificationInjectionNotSupported
+  Scenario: g_injectX1_2X_asString
+    Given the empty graph
+    And the traversal of
+      """
+      g.inject(1, 2).asString()
+      """
+    When iterated to list
+    Then the result should be unordered
+      | result |
+      | 1 |
+      | 2 |
+
+  @GraphComputerVerificationInjectionNotSupported
+  Scenario: g_injectX1_nullX_asString
+    Given the empty graph
+    And the traversal of
+      """
+      g.inject(1, null).asString()
+      """
+    When iterated to list
+    Then the result should be unordered
+      | result |
+      | 1 |
+      | str[null] |
+
+  Scenario: g_V_valueMapXnameX_asString
+    Given the modern graph
+    And the traversal of
+      """
+      g.V().valueMap("name").asString()
+      """
+    When iterated to list
+    Then the result should be unordered
+      | result |
+      | {name=[marko]} |
+      | {name=[vadas]} |
+      | {name=[lop]} |
+      | {name=[josh]} |
+      | {name=[ripple]} |
+      | {name=[peter]} |
+
+  @UserSuppliedVertexIds
+  Scenario: g_V_asString
+    Given the modern graph
+    And the traversal of
+    """
+    g.V().asString()
+    """
+    When iterated to list
+    Then the result should be unordered
+      | result |
+      | str[v[1]] |
+      | str[v[2]] |
+      | str[v[3]] |
+      | str[v[4]] |
+      | str[v[5]] |
+      | str[v[6]] |
+
+  @UserSuppliedEdgeIds
+  Scenario: g_E_asString
+    Given the modern graph
+    And the traversal of
+    """
+    g.E().asString()
+    """
+    When iterated to list
+    Then the result should be unordered
+      | result |
+      | str[e[7][1-knows->2]] |
+      | str[e[8][1-knows->4]] |
+      | str[e[9][1-created->3]] |
+      | str[e[10][4-created->5]] |
+      | str[e[11][4-created->3]] |
+      | str[e[12][6-created->3]] |
+
+  @UserSuppliedVertexPropertyIds
+  Scenario: g_V_properties
+    Given the modern graph
+    And the traversal of
+      """
+      g.V().properties().asString()
+      """
+    When iterated to list
+    Then the result should be unordered
+      | result |
+      | str[vp[name->marko]] |
+      | str[vp[age->29]] |
+      | str[vp[name->vadas]]  |
+      | str[vp[age->27]] |
+      | str[vp[name->lop]]  |
+      | str[vp[lang->java]]  |
+      | str[vp[name->josh]]  |
+      | str[vp[age->32]] |
+      | str[vp[name->ripple]]  |
+      | str[vp[lang->java]]  |
+      | str[vp[name->peter]]  |
+      | str[vp[age->35]] |
+
+  Scenario: g_V_hasLabelXpersonX_valuesXageX_asString
+    Given the modern graph
+    And the traversal of
+      """
+      g.V().hasLabel("person").values("age").asString()
+      """
+    When iterated to list
+    Then the result should be unordered
+      | result |
+      | 29 |
+      | 27 |
+      | 32 |
+      | 35 |
+
+  Scenario: g_V_hasLabelXpersonX_valuesXageX_asString_concatX_years_oldX
+    Given the modern graph
+    And the traversal of
+      """
+      g.V().hasLabel("person").values("age").asString().concat(" years old")
+      """
+    When iterated to list
+    Then the result should be unordered
+      | result |
+      | 29 years old |
+      | 27 years old |
+      | 32 years old |
+      | 35 years old |
\ No newline at end of file
diff --git 
a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/Length.feature
 
b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/Length.feature
new file mode 100644
index 0000000000..460bc68539
--- /dev/null
+++ 
b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/Length.feature
@@ -0,0 +1,60 @@
+# 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.
+
+@StepClassMap @StepLength
+Feature: Step - length()
+
+  @GraphComputerVerificationInjectionNotSupported
+  Scenario: g_injectXfeature_test_nullX_length
+    Given the empty graph
+    And the traversal of
+      """
+      g.inject("feature", "test", null).length()
+      """
+    When iterated to list
+    Then the result should be unordered
+      | result |
+      | d[7].i |
+      | d[4].i |
+      | null |
+
+  @GraphComputerVerificationInjectionNotSupported
+  Scenario: g_injectXListXa_bXX_length
+    Given the empty graph
+    And using the parameter xx1 defined as "l[a,b]"
+    And the traversal of
+      """
+      g.inject(xx1).length()
+      """
+    When iterated to list
+    Then the traversal will raise an error with message containing text of 
"The length() step can only take string as argument"
+
+  Scenario: g_V_valuesXnameX_length
+    Given the modern graph
+    And the traversal of
+      """
+      g.V().values("name").length()
+      """
+    When iterated to list
+    Then the result should be unordered
+      | result |
+      | d[5].i |
+      | d[5].i |
+      | d[3].i |
+      | d[4].i |
+      | d[6].i |
+      | d[5].i |
diff --git 
a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/ToLower.feature
 
b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/ToLower.feature
new file mode 100644
index 0000000000..480a861b38
--- /dev/null
+++ 
b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/ToLower.feature
@@ -0,0 +1,75 @@
+# 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.
+
+@StepClassMap @StepToLower
+Feature: Step - toLower()
+
+  @GraphComputerVerificationInjectionNotSupported
+  Scenario: g_injectXfeature_test_nullX_toLower
+    Given the empty graph
+    And the traversal of
+      """
+      g.inject("FEATURE", "tESt", null).toLower()
+      """
+    When iterated to list
+    Then the result should be unordered
+      | result |
+      | feature |
+      | test |
+      | null |
+
+  @GraphComputerVerificationInjectionNotSupported
+  Scenario: g_injectXListXa_bXX_toLower
+    Given the empty graph
+    And using the parameter xx1 defined as "l[a,b]"
+    And the traversal of
+      """
+      g.inject(xx1).toLower()
+      """
+    When iterated to list
+    Then the traversal will raise an error with message containing text of 
"The toLower() step can only take string as argument"
+
+  Scenario: g_V_valuesXnameX_toLower
+    Given the empty graph
+    And the graph initializer of
+      """
+      g.addV("person").property("name", "MARKO").property("age", 
29).as("marko").
+        addV("person").property("name", "VADAS").property("age", 
27).as("vadas").
+        addV("software").property("name", "LOP").property("lang", 
"java").as("lop").
+        addV("person").property("name","JOSH").property("age", 32).as("josh").
+        addV("software").property("name", "RIPPLE").property("lang", 
"java").as("ripple").
+        addV("person").property("name", "PETER").property("age", 
35).as('peter').
+        addE("knows").from("marko").to("vadas").property("weight", 0.5d).
+        addE("knows").from("marko").to("josh").property("weight", 1.0d).
+        addE("created").from("marko").to("lop").property("weight", 0.4d).
+        addE("created").from("josh").to("ripple").property("weight", 1.0d).
+        addE("created").from("josh").to("lop").property("weight", 0.4d).
+        addE("created").from("peter").to("lop").property("weight", 0.2d)
+      """
+    And the traversal of
+      """
+      g.V().values("name").toLower()
+      """
+    When iterated to list
+    Then the result should be unordered
+      | result |
+      | marko |
+      | vadas |
+      | lop |
+      | josh |
+      | ripple |
+      | peter |
diff --git 
a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/ToUpper.feature
 
b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/ToUpper.feature
new file mode 100644
index 0000000000..902d530fd9
--- /dev/null
+++ 
b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/ToUpper.feature
@@ -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.
+
+@StepClassMap @StepToUpper
+Feature: Step - toUpper()
+
+  @GraphComputerVerificationInjectionNotSupported
+  Scenario: g_injectXfeature_test_nullX_toUpper
+    Given the empty graph
+    And the traversal of
+      """
+      g.inject("feature", "tESt", null).toUpper()
+      """
+    When iterated to list
+    Then the result should be unordered
+      | result |
+      | FEATURE |
+      | TEST |
+      | null |
+
+  @GraphComputerVerificationInjectionNotSupported
+  Scenario: g_injectXfeature_test_nullX_asString_toUpper
+    Given the empty graph
+    And the traversal of
+      """
+      g.inject("feature", "tESt", null).asString().toUpper()
+      """
+    When iterated to list
+    Then the result should be unordered
+      | result |
+      | FEATURE |
+      | TEST |
+      | NULL |
+
+  @GraphComputerVerificationInjectionNotSupported
+  Scenario: g_injectXListXa_bXX_toUpper
+    Given the empty graph
+    And using the parameter xx1 defined as "l[a,b]"
+    And the traversal of
+      """
+      g.inject(xx1).toUpper()
+      """
+    When iterated to list
+    Then the traversal will raise an error with message containing text of 
"The toUpper() step can only take string as argument"
+
+  Scenario: g_V_valuesXnameX_toUpper
+    Given the modern graph
+    And the traversal of
+      """
+      g.V().values("name").toUpper()
+      """
+    When iterated to list
+    Then the result should be unordered
+      | result |
+      | MARKO |
+      | VADAS |
+      | LOP |
+      | JOSH |
+      | RIPPLE |
+      | PETER |

Reply via email to