You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tinkerpop.apache.org by dk...@apache.org on 2018/10/04 15:13:00 UTC

[1/7] tinkerpop git commit: TINKERPOP-2041 Added IO tests for TextP

Repository: tinkerpop
Updated Branches:
  refs/heads/master 3a8f58088 -> 8b69b34b6


TINKERPOP-2041 Added IO tests for TextP


Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/8b69b34b
Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/8b69b34b
Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/8b69b34b

Branch: refs/heads/master
Commit: 8b69b34b6393a3071c0cd491ea9ec0ca09a1e5ae
Parents: 9b96586
Author: Stephen Mallette <sp...@genoprime.com>
Authored: Wed Oct 3 15:01:40 2018 -0400
Committer: Daniel Kuppitz <da...@hotmail.com>
Committed: Thu Oct 4 07:45:08 2018 -0700

----------------------------------------------------------------------
 docs/src/dev/io/graphson.asciidoc               | 26 ++++++++++++++++++++
 .../scripts/generate-graphson-resources.groovy  | 12 ++++-----
 .../tinkerpop/gremlin/structure/io/Model.java   |  9 +++++++
 .../io/AbstractTypedCompatibilityTest.java      | 14 +++++++++++
 .../io/graphson/_3_4_0/textp-v2d0-partial.json  |  7 ++++++
 .../io/graphson/_3_4_0/textp-v3d0.json          |  7 ++++++
 .../structure/io/gryo/_3_4_0/textp-v1d0.kryo    |  1 +
 .../structure/io/gryo/_3_4_0/textp-v3d0.kryo    |  1 +
 8 files changed, 71 insertions(+), 6 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/8b69b34b/docs/src/dev/io/graphson.asciidoc
----------------------------------------------------------------------
diff --git a/docs/src/dev/io/graphson.asciidoc b/docs/src/dev/io/graphson.asciidoc
index d140a2f..1c9081c 100644
--- a/docs/src/dev/io/graphson.asciidoc
+++ b/docs/src/dev/io/graphson.asciidoc
@@ -3014,6 +3014,19 @@ The following `Bytecode` example represents the traversal of `g.V().hasLabel('pe
 }
 ----
 
+==== TextP
+
+[source,json]
+----
+{
+  "@type" : "g:TextP",
+  "@value" : {
+    "predicate" : "containing",
+    "value" : "ark"
+  }
+}
+----
+
 ==== TraversalMetrics
 
 [source,json]
@@ -5392,6 +5405,19 @@ Please see <<_p,P>> for additional information on `within`.
 }
 ----
 
+==== TextP
+
+[source,json]
+----
+{
+  "@type" : "g:TextP",
+  "@value" : {
+    "predicate" : "containing",
+    "value" : "ark"
+  }
+}
+----
+
 ==== TraversalMetrics
 
 [source,json]

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/8b69b34b/gremlin-tools/gremlin-io-test/scripts/generate-graphson-resources.groovy
----------------------------------------------------------------------
diff --git a/gremlin-tools/gremlin-io-test/scripts/generate-graphson-resources.groovy b/gremlin-tools/gremlin-io-test/scripts/generate-graphson-resources.groovy
index 55b4fa6..03112ed 100644
--- a/gremlin-tools/gremlin-io-test/scripts/generate-graphson-resources.groovy
+++ b/gremlin-tools/gremlin-io-test/scripts/generate-graphson-resources.groovy
@@ -59,19 +59,19 @@ toJson = { o, type, mapper, comment = "", suffix = "" ->
 
 writeSupportedV1Objects = { writer, mapper ->
     writer.write("=== Graph Structure\n\n")
-    model.entries("Graph Structure").findAll{it.isCompatibleWith(GraphSONCompatibility.V1D0_3_3_0)}.each {
+    model.entries("Graph Structure").findAll{it.isCompatibleWith(GraphSONCompatibility.V1D0_3_4_0)}.each {
         writer.write(toJsonV1d0NoTypes(it.getObject(), it.getTitle(), mapper, it.getDescription()))
     }
 
     writer.write("\n")
     writer.write("=== RequestMessage\n\n")
-    model.entries("RequestMessage").findAll{it.isCompatibleWith(GraphSONCompatibility.V1D0_3_3_0)}.each {
+    model.entries("RequestMessage").findAll{it.isCompatibleWith(GraphSONCompatibility.V1D0_3_4_0)}.each {
         writer.write(toJsonV1d0NoTypes(it.getObject(), it.getTitle(), mapper, it.getDescription()))
     }
 
     writer.write("\n")
     writer.write("=== ResponseMessage\n\n")
-    model.entries("ResponseMessage").findAll{it.isCompatibleWith(GraphSONCompatibility.V1D0_3_3_0)}.each {
+    model.entries("ResponseMessage").findAll{it.isCompatibleWith(GraphSONCompatibility.V1D0_3_4_0)}.each {
         writer.write(toJsonV1d0NoTypes(it.getObject(), it.getTitle(), mapper, it.getDescription()))
     }
 }
@@ -156,7 +156,7 @@ mapper = GraphSONMapper.build().
 
 file = new File("${projectBuildDir}/dev-docs/out-graphson-2d0-partial.txt")
 if (file.exists()) file.delete()
-file.withWriter { writeSupportedV2V3Objects(it, mapper, toJsonV2d0PartialTypes, {it.isCompatibleWith(GraphSONCompatibility.V2D0_PARTIAL_3_3_1)}, v2ExtendedDescription) }
+file.withWriter { writeSupportedV2V3Objects(it, mapper, toJsonV2d0PartialTypes, {it.isCompatibleWith(GraphSONCompatibility.V2D0_PARTIAL_3_4_0)}, v2ExtendedDescription) }
 
 mapper = GraphSONMapper.build().
         addRegistry(TinkerIoRegistryV2d0.instance()).
@@ -167,7 +167,7 @@ mapper = GraphSONMapper.build().
 
 file = new File("${projectBuildDir}/dev-docs/out-graphson-2d0-no-type.txt")
 if (file.exists()) file.delete()
-file.withWriter { writeSupportedV2V3Objects(it, mapper, toJsonV2d0NoTypes, {it.isCompatibleWith(GraphSONCompatibility.V2D0_NO_TYPE_3_3_1)}, v2ExtendedDescription) }
+file.withWriter { writeSupportedV2V3Objects(it, mapper, toJsonV2d0NoTypes, {it.isCompatibleWith(GraphSONCompatibility.V2D0_NO_TYPE_3_4_0)}, v2ExtendedDescription) }
 
 mapper = GraphSONMapper.build().
         addRegistry(TinkerIoRegistryV2d0.instance()).
@@ -189,7 +189,7 @@ mapper = GraphSONMapper.build().
 
 file = new File("${projectBuildDir}/dev-docs/out-graphson-3d0.txt")
 if (file.exists()) file.delete()
-file.withWriter { writeSupportedV2V3Objects(it, mapper, toJsonV3d0, {it.isCompatibleWith(GraphSONCompatibility.V3D0_PARTIAL_3_3_1)}, v3ExtendedDescription) }
+file.withWriter { writeSupportedV2V3Objects(it, mapper, toJsonV3d0, {it.isCompatibleWith(GraphSONCompatibility.V3D0_PARTIAL_3_4_0)}, v3ExtendedDescription) }
 
 def ver = "_" + "${projectVersion}".replace(".","_").replace("-SNAPSHOT","")
 def target = "${projectBaseDir}/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/" + ver

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/8b69b34b/gremlin-tools/gremlin-io-test/src/main/java/org/apache/tinkerpop/gremlin/structure/io/Model.java
----------------------------------------------------------------------
diff --git a/gremlin-tools/gremlin-io-test/src/main/java/org/apache/tinkerpop/gremlin/structure/io/Model.java b/gremlin-tools/gremlin-io-test/src/main/java/org/apache/tinkerpop/gremlin/structure/io/Model.java
index 3ad676f..f01b0fc 100644
--- a/gremlin-tools/gremlin-io-test/src/main/java/org/apache/tinkerpop/gremlin/structure/io/Model.java
+++ b/gremlin-tools/gremlin-io-test/src/main/java/org/apache/tinkerpop/gremlin/structure/io/Model.java
@@ -29,6 +29,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.P;
 import org.apache.tinkerpop.gremlin.process.traversal.Pop;
 import org.apache.tinkerpop.gremlin.process.traversal.SackFunctions;
 import org.apache.tinkerpop.gremlin.process.traversal.Scope;
+import org.apache.tinkerpop.gremlin.process.traversal.TextP;
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
 import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalOptionParent;
 import org.apache.tinkerpop.gremlin.process.traversal.util.DefaultTraversalMetrics;
@@ -106,6 +107,12 @@ public class Model {
         final Compatibility[] noTypeGraphSONPlusGryo3_2_3 = Compatibilities.with(GryoCompatibility.class).beforeRelease("3.2.4").join(Compatibilities.UNTYPED_GRAPHSON).matchToArray();
         final Compatibility[] noTypeGraphSONPlusGryo3_3_0 = Compatibilities.with(GryoCompatibility.class).beforeRelease("3.3.0").join(Compatibilities.UNTYPED_GRAPHSON).matchToArray();
 
+        // the inverse of this definition is basically 3.4.0 or better for both GraphSON and Gryo with no support for
+        // untyped GraphSON anywhere along the way
+        final Compatibility[] before3_4_0 = Compatibilities.with(GryoCompatibility.class).beforeRelease("3.4.0")
+                .join(Compatibilities.with(GraphSONCompatibility.class).configuredAs(".*no-types|v1d0")
+                .join(Compatibilities.with(GraphSONCompatibility.class).beforeRelease("3.4.0"))).matchToArray();
+
         // there is no point to testing gryo for list/map/set as they are kryo primitives essentially
         final Compatibility[] noGraphSONBeforeV3AndNoGryo = Compatibilities.with(GraphSONCompatibility.class).configuredAs(".*v2d0-partial|v1d0|v2d0-no-types").join(Compatibilities.GRYO_ONLY).matchToArray();
 
@@ -164,6 +171,8 @@ public class Model {
         addGraphProcessEntry(P.gt(0).or(P.within(-1, -10, -100)), "P or", "", noTypeGraphSONPlusGryo3_2_3);
         addGraphProcessEntry(Scope.local, "Scope", "", Compatibilities.UNTYPED_GRAPHSON.matchToArray());
         addGraphProcessEntry(T.label, "T", "", Compatibilities.UNTYPED_GRAPHSON.matchToArray());
+        // TextP was only added at 3.4.0 and is not supported with untyped GraphSON of any sort
+        addGraphProcessEntry(TextP.containing("ark"), "TextP", "", before3_4_0);
         addGraphProcessEntry(createStaticTraversalMetrics(), "TraversalMetrics", "", noTypeGraphSONPlusGryo3_3_0);
         addGraphProcessEntry(g.V().hasLabel("person").asAdmin().nextTraverser(), "Traverser", "", Compatibilities.UNTYPED_GRAPHSON.matchToArray());
 

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/8b69b34b/gremlin-tools/gremlin-io-test/src/test/java/org/apache/tinkerpop/gremlin/structure/io/AbstractTypedCompatibilityTest.java
----------------------------------------------------------------------
diff --git a/gremlin-tools/gremlin-io-test/src/test/java/org/apache/tinkerpop/gremlin/structure/io/AbstractTypedCompatibilityTest.java b/gremlin-tools/gremlin-io-test/src/test/java/org/apache/tinkerpop/gremlin/structure/io/AbstractTypedCompatibilityTest.java
index 67e5901..f34a6c4 100644
--- a/gremlin-tools/gremlin-io-test/src/test/java/org/apache/tinkerpop/gremlin/structure/io/AbstractTypedCompatibilityTest.java
+++ b/gremlin-tools/gremlin-io-test/src/test/java/org/apache/tinkerpop/gremlin/structure/io/AbstractTypedCompatibilityTest.java
@@ -28,6 +28,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.Path;
 import org.apache.tinkerpop.gremlin.process.traversal.Pop;
 import org.apache.tinkerpop.gremlin.process.traversal.SackFunctions;
 import org.apache.tinkerpop.gremlin.process.traversal.Scope;
+import org.apache.tinkerpop.gremlin.process.traversal.TextP;
 import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
 import org.apache.tinkerpop.gremlin.process.traversal.step.util.Tree;
 import org.apache.tinkerpop.gremlin.process.traversal.util.Metrics;
@@ -840,6 +841,19 @@ public abstract class AbstractTypedCompatibilityTest extends AbstractCompatibili
     }
 
     @Test
+    public void shouldReadWriteTextP() throws Exception {
+        final String resourceName = "textp";
+        assumeCompatibility(resourceName);
+
+        final TextP resource = findModelEntryObject(resourceName);
+        final TextP fromStatic = read(getCompatibility().readFromResource(resourceName), TextP.class);
+        final TextP recycled = read(write(fromStatic, TextP.class), TextP.class);
+        assertEquals(fromStatic, recycled);
+        assertEquals(resource, fromStatic);
+        assertEquals(resource, recycled);
+    }
+
+    @Test
     public void shouldReadWriteTimestamp() throws Exception {
         final String resourceName = "timestamp";
         assumeCompatibility(resourceName);

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/8b69b34b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_4_0/textp-v2d0-partial.json
----------------------------------------------------------------------
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_4_0/textp-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_4_0/textp-v2d0-partial.json
new file mode 100644
index 0000000..2820989
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_4_0/textp-v2d0-partial.json
@@ -0,0 +1,7 @@
+{
+  "@type" : "g:TextP",
+  "@value" : {
+    "predicate" : "containing",
+    "value" : "ark"
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/8b69b34b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_4_0/textp-v3d0.json
----------------------------------------------------------------------
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_4_0/textp-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_4_0/textp-v3d0.json
new file mode 100644
index 0000000..2820989
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_4_0/textp-v3d0.json
@@ -0,0 +1,7 @@
+{
+  "@type" : "g:TextP",
+  "@value" : {
+    "predicate" : "containing",
+    "value" : "ark"
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/8b69b34b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_4_0/textp-v1d0.kryo
----------------------------------------------------------------------
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_4_0/textp-v1d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_4_0/textp-v1d0.kryo
new file mode 100644
index 0000000..d71eb0f
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_4_0/textp-v1d0.kryo
@@ -0,0 +1 @@
+containin�ar�
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/8b69b34b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_4_0/textp-v3d0.kryo
----------------------------------------------------------------------
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_4_0/textp-v3d0.kryo b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_4_0/textp-v3d0.kryo
new file mode 100644
index 0000000..d71eb0f
--- /dev/null
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/gryo/_3_4_0/textp-v3d0.kryo
@@ -0,0 +1 @@
+containin�ar�
\ No newline at end of file


[3/7] tinkerpop git commit: Renamed `TP` to `TextP` as proposed by @robertdale

Posted by dk...@apache.org.
Renamed `TP` to `TextP` as proposed by @robertdale


Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/f057fb36
Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/f057fb36
Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/f057fb36

Branch: refs/heads/master
Commit: f057fb3601ab12dfe8dc10361c9916c904fc5a0d
Parents: 79d4a05
Author: Daniel Kuppitz <da...@hotmail.com>
Authored: Mon Oct 1 09:27:35 2018 -0700
Committer: Daniel Kuppitz <da...@hotmail.com>
Committed: Thu Oct 4 07:45:08 2018 -0700

----------------------------------------------------------------------
 docs/src/reference/the-traversal.asciidoc       |  16 +--
 docs/src/upgrade/release-3.4.x.asciidoc         |   2 +-
 .../tinkerpop/gremlin/jsr223/CoreImports.java   |   6 +-
 .../tinkerpop/gremlin/process/traversal/TP.java | 107 -------------------
 .../gremlin/process/traversal/TextP.java        | 107 +++++++++++++++++++
 .../structure/io/graphson/GraphSONModule.java   |  10 +-
 .../io/graphson/TraversalSerializersV2d0.java   |  12 +--
 .../io/graphson/TraversalSerializersV3d0.java   |  12 +--
 .../structure/io/gryo/GryoSerializersV1d0.java  |  10 +-
 .../structure/io/gryo/GryoSerializersV3d0.java  |  10 +-
 .../gremlin/structure/io/gryo/GryoVersion.java  |   6 +-
 .../gremlin/process/traversal/PTest.java        |  28 ++---
 .../GraphSONMapperPartialEmbeddedTypeTest.java  |  16 +--
 gremlin-dotnet/glv/TP.template                  |  71 ------------
 gremlin-dotnet/glv/TextP.template               |  71 ++++++++++++
 gremlin-dotnet/glv/generate.groovy              |  12 +--
 .../src/Gremlin.Net/Process/Traversal/TP.cs     |  96 -----------------
 .../src/Gremlin.Net/Process/Traversal/TextP.cs  |  96 +++++++++++++++++
 .../Structure/IO/GraphSON/GraphSONWriter.cs     |   2 +-
 .../Structure/IO/GraphSON/TPSerializer.cs       |  45 --------
 .../Structure/IO/GraphSON/TextPSerializer.cs    |  45 ++++++++
 .../Gherkin/TraversalEvaluation/TPParameter.cs  |  97 -----------------
 .../TraversalEvaluation/TextPParameter.cs       |  97 +++++++++++++++++
 .../TraversalEvaluation/TraversalParser.cs      |   6 +-
 .../gremlin/groovy/jsr223/GroovyTranslator.java |   8 +-
 gremlin-javascript/glv/TraversalSource.template |   6 +-
 gremlin-javascript/glv/generate.groovy          |   6 +-
 .../main/javascript/gremlin-javascript/index.js |   2 +-
 .../gremlin-javascript/lib/process/traversal.js |   6 +-
 .../lib/structure/io/graph-serializer.js        |   4 +-
 .../lib/structure/io/type-serializers.js        |  10 +-
 .../test/cucumber/feature-steps.js              |   2 +-
 gremlin-python/glv/TraversalSource.template     |   6 +-
 gremlin-python/glv/generate.groovy              |   6 +-
 .../gremlin/python/jsr223/PythonTranslator.java |   8 +-
 .../jython/gremlin_python/process/traversal.py  |  26 ++---
 .../gremlin_python/structure/io/graphsonV2d0.py |   8 +-
 .../gremlin_python/structure/io/graphsonV3d0.py |   8 +-
 .../src/main/jython/radish/feature_steps.py     |   4 +-
 gremlin-test/features/filter/Has.feature        |  10 +-
 .../process/traversal/step/filter/HasTest.java  |  12 +--
 41 files changed, 556 insertions(+), 556 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f057fb36/docs/src/reference/the-traversal.asciidoc
----------------------------------------------------------------------
diff --git a/docs/src/reference/the-traversal.asciidoc b/docs/src/reference/the-traversal.asciidoc
index da7260c..fdd261a 100644
--- a/docs/src/reference/the-traversal.asciidoc
+++ b/docs/src/reference/the-traversal.asciidoc
@@ -3357,8 +3357,8 @@ interface. Steps that allow for this type of modulation will explicitly state so
 == A Note on Predicates
 
 A `P` is a predicate of the form `Function<Object,Boolean>`. That is, given some object, return true or false. As of
-the relase of TinkerPop 3.4.0, Gremlin also supports simple text predicates, which only work on `String` values. The `TP`
-text predicates extends the `P` predicates, but are specialized in that they are of the form `Function<String,Boolean>`.
+the relase of TinkerPop 3.4.0, Gremlin also supports simple text predicates, which only work on `String` values. The `TextP`
+text predicates extend the `P` predicates, but are specialized in that they are of the form `Function<String,Boolean>`.
 The provided predicates are outlined in the table below and are used in various steps such as <<has-step,`has()`>>-step,
 <<where-step,`where()`>>-step, <<is-step,`is()`>>-step, etc.
 
@@ -3376,12 +3376,12 @@ The provided predicates are outlined in the table below and are used in various
 | `P.between(number,number)` | Is the incoming number greater than or equal to the first provided number and less than the second?
 | `P.within(objects...)` | Is the incoming object in the array of provided objects?
 | `P.without(objects...)` | Is the incoming object not in the array of the provided objects?
-| `TP.startsWith(string)` | Does the incoming `String` start with the provided `String`?
-| `TP.endsWith(string)` | Does the incoming `String` end with the provided `String`?
-| `TP.contains(string)` | Does the incoming `String` contain the provided `String`?
-| `TP.startsNotWith(string)` | TODO: find a better name
-| `TP.endsNotWith(string)` | TODO: find a better name
-| `TP.absent(string)` | TODO: find a better name
+| `TextP.startsWith(string)` | Does the incoming `String` start with the provided `String`?
+| `TextP.endsWith(string)` | Does the incoming `String` end with the provided `String`?
+| `TextP.contains(string)` | Does the incoming `String` contain the provided `String`?
+| `TextP.startsNotWith(string)` | TODO: find a better name
+| `TextP.endsNotWith(string)` | TODO: find a better name
+| `TextP.absent(string)` | TODO: find a better name
 |=========================================================
 
 [gremlin-groovy]

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f057fb36/docs/src/upgrade/release-3.4.x.asciidoc
----------------------------------------------------------------------
diff --git a/docs/src/upgrade/release-3.4.x.asciidoc b/docs/src/upgrade/release-3.4.x.asciidoc
index c26b9c7..213577a 100644
--- a/docs/src/upgrade/release-3.4.x.asciidoc
+++ b/docs/src/upgrade/release-3.4.x.asciidoc
@@ -31,7 +31,7 @@ Please see the link:https://github.com/apache/tinkerpop/blob/3.4.0/CHANGELOG.asc
 
 ==== Added text predicates
 
-Gremlin now supports simple text predicates on top of the existing `P` predicates. Both, the new `TP` text predicates and the old `P` predicates, can be chained using `and()` and `or()`.
+Gremlin now supports simple text predicates on top of the existing `P` predicates. Both, the new `TextP` text predicates and the old `P` predicates, can be chained using `and()` and `or()`.
 
 [source,groovy]
 ----

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f057fb36/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/CoreImports.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/CoreImports.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/CoreImports.java
index 38ef258..d60502a 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/CoreImports.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/CoreImports.java
@@ -67,7 +67,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.P;
 import org.apache.tinkerpop.gremlin.process.traversal.Pop;
 import org.apache.tinkerpop.gremlin.process.traversal.SackFunctions;
 import org.apache.tinkerpop.gremlin.process.traversal.Scope;
-import org.apache.tinkerpop.gremlin.process.traversal.TP;
+import org.apache.tinkerpop.gremlin.process.traversal.TextP;
 import org.apache.tinkerpop.gremlin.process.traversal.Translator;
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal;
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
@@ -182,7 +182,7 @@ public final class CoreImports {
         CLASS_IMPORTS.add(TraversalOptionParent.class);
         CLASS_IMPORTS.add(TraversalOptionParent.Pick.class);
         CLASS_IMPORTS.add(P.class);
-        CLASS_IMPORTS.add(TP.class);
+        CLASS_IMPORTS.add(TextP.class);
         // remote
         CLASS_IMPORTS.add(RemoteConnection.class);
         CLASS_IMPORTS.add(RemoteGraph.class);
@@ -293,7 +293,7 @@ public final class CoreImports {
 
         uniqueMethods(IoCore.class).forEach(METHOD_IMPORTS::add);
         uniqueMethods(P.class).forEach(METHOD_IMPORTS::add);
-        uniqueMethods(TP.class).forEach(METHOD_IMPORTS::add);
+        uniqueMethods(TextP.class).forEach(METHOD_IMPORTS::add);
         uniqueMethods(__.class).filter(m -> !m.getName().equals("__")).forEach(METHOD_IMPORTS::add);
         uniqueMethods(Computer.class).forEach(METHOD_IMPORTS::add);
         uniqueMethods(TimeUtil.class).forEach(METHOD_IMPORTS::add);

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f057fb36/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TP.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TP.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TP.java
deleted file mode 100644
index fc245a4..0000000
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TP.java
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * 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;
-
-import java.util.function.BiPredicate;
-
-/**
- * @author Daniel Kuppitz (http://gremlin.guru)
- */
-public class TP extends P<String> {
-
-    @SuppressWarnings("WeakerAccess")
-    public TP(final BiPredicate<String, String> biPredicate, final String value) {
-        super(biPredicate, value);
-    }
-
-    @Override
-    public boolean equals(final Object other) {
-        return other instanceof TP && super.equals(other);
-    }
-
-    @Override
-    public String toString() {
-        return null == this.originalValue ? this.biPredicate.toString() : this.biPredicate.toString() + "(" + this.originalValue + ")";
-    }
-
-    @Override
-    public TP negate() {
-        return new TP(this.biPredicate.negate(), this.originalValue);
-    }
-
-    public TP clone() {
-        return (TP) super.clone();
-    }
-
-    //////////////// statics
-
-    /**
-     * Determines if String does start with the given value.
-     *
-     * @since 3.4.0
-     */
-    public static TP startsWith(final String value) {
-        return new TP(Text.startsWith, value);
-    }
-
-    /**
-     * Determines if String does not start with the given value.
-     *
-     * @since 3.4.0
-     */
-    public static TP startsNotWith(final String value) {
-        return new TP(Text.startsNotWith, value);
-    }
-
-    /**
-     * Determines if String does start with the given value.
-     *
-     * @since 3.4.0
-     */
-    public static TP endsWith(final String value) {
-        return new TP(Text.endsWith, value);
-    }
-
-    /**
-     * Determines if String does not start with the given value.
-     *
-     * @since 3.4.0
-     */
-    public static TP endsNotWith(final String value) {
-        return new TP(Text.endsNotWith, value);
-    }
-
-    /**
-     * Determines if String does contain the given value.
-     *
-     * @since 3.4.0
-     */
-    public static TP contains(final String value) {
-        return new TP(Text.contains, value);
-    }
-
-    /**
-     * Determines if String does not contain the given value.
-     *
-     * @since 3.4.0
-     */
-    public static TP absent(final String value) {
-        return new TP(Text.absent, value);
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f057fb36/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TextP.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TextP.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TextP.java
new file mode 100644
index 0000000..2b1b976
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TextP.java
@@ -0,0 +1,107 @@
+/*
+ * 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;
+
+import java.util.function.BiPredicate;
+
+/**
+ * @author Daniel Kuppitz (http://gremlin.guru)
+ */
+public class TextP extends P<String> {
+
+    @SuppressWarnings("WeakerAccess")
+    public TextP(final BiPredicate<String, String> biPredicate, final String value) {
+        super(biPredicate, value);
+    }
+
+    @Override
+    public boolean equals(final Object other) {
+        return other instanceof TextP && super.equals(other);
+    }
+
+    @Override
+    public String toString() {
+        return null == this.originalValue ? this.biPredicate.toString() : this.biPredicate.toString() + "(" + this.originalValue + ")";
+    }
+
+    @Override
+    public TextP negate() {
+        return new TextP(this.biPredicate.negate(), this.originalValue);
+    }
+
+    public TextP clone() {
+        return (TextP) super.clone();
+    }
+
+    //////////////// statics
+
+    /**
+     * Determines if String does start with the given value.
+     *
+     * @since 3.4.0
+     */
+    public static TextP startsWith(final String value) {
+        return new TextP(Text.startsWith, value);
+    }
+
+    /**
+     * Determines if String does not start with the given value.
+     *
+     * @since 3.4.0
+     */
+    public static TextP startsNotWith(final String value) {
+        return new TextP(Text.startsNotWith, value);
+    }
+
+    /**
+     * Determines if String does start with the given value.
+     *
+     * @since 3.4.0
+     */
+    public static TextP endsWith(final String value) {
+        return new TextP(Text.endsWith, value);
+    }
+
+    /**
+     * Determines if String does not start with the given value.
+     *
+     * @since 3.4.0
+     */
+    public static TextP endsNotWith(final String value) {
+        return new TextP(Text.endsNotWith, value);
+    }
+
+    /**
+     * Determines if String does contain the given value.
+     *
+     * @since 3.4.0
+     */
+    public static TextP contains(final String value) {
+        return new TextP(Text.contains, value);
+    }
+
+    /**
+     * Determines if String does not contain the given value.
+     *
+     * @since 3.4.0
+     */
+    public static TextP absent(final String value) {
+        return new TextP(Text.absent, value);
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f057fb36/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONModule.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONModule.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONModule.java
index 74647a1..ed0df64 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONModule.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONModule.java
@@ -28,7 +28,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.Path;
 import org.apache.tinkerpop.gremlin.process.traversal.Pop;
 import org.apache.tinkerpop.gremlin.process.traversal.SackFunctions;
 import org.apache.tinkerpop.gremlin.process.traversal.Scope;
-import org.apache.tinkerpop.gremlin.process.traversal.TP;
+import org.apache.tinkerpop.gremlin.process.traversal.TextP;
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
@@ -146,7 +146,7 @@ abstract class GraphSONModule extends TinkerPopJacksonModule {
                     put(AndP.class, "P");
                     put(OrP.class, "P");
                     put(P.class, "P");
-                    put(TP.class, "TP");
+                    put(TextP.class, "TextP");
                     Stream.of(
                             VertexProperty.Cardinality.class,
                             Column.class,
@@ -272,7 +272,7 @@ abstract class GraphSONModule extends TinkerPopJacksonModule {
                     TraversalOptionParent.Pick.values(),
                     T.values()).flatMap(Stream::of).forEach(e -> addDeserializer(e.getClass(), new TraversalSerializersV3d0.EnumJacksonDeserializer(e.getDeclaringClass())));
             addDeserializer(P.class, new TraversalSerializersV3d0.PJacksonDeserializer());
-            addDeserializer(TP.class, new TraversalSerializersV3d0.TPJacksonDeserializer());
+            addDeserializer(TextP.class, new TraversalSerializersV3d0.TextPJacksonDeserializer());
             addDeserializer(Lambda.class, new TraversalSerializersV3d0.LambdaJacksonDeserializer());
             addDeserializer(Traverser.class, new TraversalSerializersV3d0.TraverserJacksonDeserializer());
             Arrays.asList(
@@ -362,7 +362,7 @@ abstract class GraphSONModule extends TinkerPopJacksonModule {
                     put(AndP.class, "P");
                     put(OrP.class, "P");
                     put(P.class, "P");
-                    put(TP.class, "TP");
+                    put(TextP.class, "TextP");
                     Stream.of(
                             VertexProperty.Cardinality.class,
                             Column.class,
@@ -480,7 +480,7 @@ abstract class GraphSONModule extends TinkerPopJacksonModule {
                     TraversalOptionParent.Pick.values(),
                     T.values()).flatMap(Stream::of).forEach(e -> addDeserializer(e.getClass(), new TraversalSerializersV2d0.EnumJacksonDeserializer(e.getDeclaringClass())));
             addDeserializer(P.class, new TraversalSerializersV2d0.PJacksonDeserializer());
-            addDeserializer(TP.class, new TraversalSerializersV2d0.TPJacksonDeserializer());
+            addDeserializer(TextP.class, new TraversalSerializersV2d0.TextPJacksonDeserializer());
             addDeserializer(Lambda.class, new TraversalSerializersV2d0.LambdaJacksonDeserializer());
             addDeserializer(Traverser.class, new TraversalSerializersV2d0.TraverserJacksonDeserializer());
             Arrays.asList(

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f057fb36/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/TraversalSerializersV2d0.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/TraversalSerializersV2d0.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/TraversalSerializersV2d0.java
index 7ba4ca5..5297733 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/TraversalSerializersV2d0.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/TraversalSerializersV2d0.java
@@ -24,7 +24,7 @@ import org.apache.commons.configuration.MapConfiguration;
 import org.apache.tinkerpop.gremlin.process.remote.traversal.DefaultRemoteTraverser;
 import org.apache.tinkerpop.gremlin.process.traversal.Bytecode;
 import org.apache.tinkerpop.gremlin.process.traversal.P;
-import org.apache.tinkerpop.gremlin.process.traversal.TP;
+import org.apache.tinkerpop.gremlin.process.traversal.TextP;
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
@@ -373,14 +373,14 @@ final class TraversalSerializersV2d0 {
         }
     }
 
-    final static class TPJacksonDeserializer extends StdDeserializer<TP> {
+    final static class TextPJacksonDeserializer extends StdDeserializer<TextP> {
 
-        public TPJacksonDeserializer() {
-            super(TP.class);
+        public TextPJacksonDeserializer() {
+            super(TextP.class);
         }
 
         @Override
-        public TP deserialize(final JsonParser jsonParser, final DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
+        public TextP deserialize(final JsonParser jsonParser, final DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
             String predicate = null;
             String value = null;
 
@@ -395,7 +395,7 @@ final class TraversalSerializersV2d0 {
             }
 
             try {
-                return (TP) TP.class.getMethod(predicate, String.class).invoke(null, value);
+                return (TextP) TextP.class.getMethod(predicate, String.class).invoke(null, value);
             } catch (final Exception e) {
                 throw new IllegalStateException(e.getMessage(), e);
             }

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f057fb36/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/TraversalSerializersV3d0.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/TraversalSerializersV3d0.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/TraversalSerializersV3d0.java
index ca01ec0..d3aa60e 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/TraversalSerializersV3d0.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/TraversalSerializersV3d0.java
@@ -24,7 +24,7 @@ import org.apache.commons.configuration.MapConfiguration;
 import org.apache.tinkerpop.gremlin.process.remote.traversal.DefaultRemoteTraverser;
 import org.apache.tinkerpop.gremlin.process.traversal.Bytecode;
 import org.apache.tinkerpop.gremlin.process.traversal.P;
-import org.apache.tinkerpop.gremlin.process.traversal.TP;
+import org.apache.tinkerpop.gremlin.process.traversal.TextP;
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
@@ -371,14 +371,14 @@ final class TraversalSerializersV3d0 {
         }
     }
 
-    final static class TPJacksonDeserializer extends StdDeserializer<TP> {
+    final static class TextPJacksonDeserializer extends StdDeserializer<TextP> {
 
-        public TPJacksonDeserializer() {
-            super(TP.class);
+        public TextPJacksonDeserializer() {
+            super(TextP.class);
         }
 
         @Override
-        public TP deserialize(final JsonParser jsonParser, final DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
+        public TextP deserialize(final JsonParser jsonParser, final DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
             String predicate = null;
             String value = null;
 
@@ -393,7 +393,7 @@ final class TraversalSerializersV3d0 {
             }
 
             try {
-                return (TP) TP.class.getMethod(predicate, String.class).invoke(null, value);
+                return (TextP) TextP.class.getMethod(predicate, String.class).invoke(null, value);
             } catch (final Exception e) {
                 throw new IllegalStateException(e.getMessage(), e);
             }

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f057fb36/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoSerializersV1d0.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoSerializersV1d0.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoSerializersV1d0.java
index c7de4ec..7697462 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoSerializersV1d0.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoSerializersV1d0.java
@@ -22,7 +22,7 @@ import org.apache.tinkerpop.gremlin.process.remote.traversal.DefaultRemoteTraver
 import org.apache.tinkerpop.gremlin.process.traversal.Bytecode;
 import org.apache.tinkerpop.gremlin.process.traversal.P;
 import org.apache.tinkerpop.gremlin.process.traversal.Path;
-import org.apache.tinkerpop.gremlin.process.traversal.TP;
+import org.apache.tinkerpop.gremlin.process.traversal.TextP;
 import org.apache.tinkerpop.gremlin.process.traversal.TraversalSource;
 import org.apache.tinkerpop.gremlin.process.traversal.util.AndP;
 import org.apache.tinkerpop.gremlin.process.traversal.util.ConnectiveP;
@@ -229,20 +229,20 @@ public final class GryoSerializersV1d0 {
         }
     }
 
-    public final static class TPSerializer implements SerializerShim<TP> {
+    public final static class TextPSerializer implements SerializerShim<TextP> {
         @Override
-        public <O extends OutputShim> void write(final KryoShim<?, O> kryo, final O output, final TP p) {
+        public <O extends OutputShim> void write(final KryoShim<?, O> kryo, final O output, final TextP p) {
             output.writeString(p.getBiPredicate().toString());
             kryo.writeObject(output, p.getValue());
         }
 
         @Override
-        public <I extends InputShim> TP read(final KryoShim<I, ?> kryo, final I input, final Class<TP> clazz) {
+        public <I extends InputShim> TextP read(final KryoShim<I, ?> kryo, final I input, final Class<TextP> clazz) {
             final String predicate = input.readString();
             final String value = kryo.readObject(input, String.class);
 
             try {
-                return (TP) TP.class.getMethod(predicate, String.class).invoke(null, value);
+                return (TextP) TextP.class.getMethod(predicate, String.class).invoke(null, value);
             } catch (final Exception e) {
                 throw new IllegalStateException(e.getMessage(), e);
             }

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f057fb36/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoSerializersV3d0.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoSerializersV3d0.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoSerializersV3d0.java
index ffda00e..e35bd33 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoSerializersV3d0.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoSerializersV3d0.java
@@ -22,7 +22,7 @@ import org.apache.tinkerpop.gremlin.process.remote.traversal.DefaultRemoteTraver
 import org.apache.tinkerpop.gremlin.process.traversal.Bytecode;
 import org.apache.tinkerpop.gremlin.process.traversal.P;
 import org.apache.tinkerpop.gremlin.process.traversal.Path;
-import org.apache.tinkerpop.gremlin.process.traversal.TP;
+import org.apache.tinkerpop.gremlin.process.traversal.TextP;
 import org.apache.tinkerpop.gremlin.process.traversal.TraversalSource;
 import org.apache.tinkerpop.gremlin.process.traversal.util.AndP;
 import org.apache.tinkerpop.gremlin.process.traversal.util.ConnectiveP;
@@ -345,20 +345,20 @@ public final class GryoSerializersV3d0 {
         }
     }
 
-    public final static class TPSerializer implements SerializerShim<TP> {
+    public final static class TextPSerializer implements SerializerShim<TextP> {
         @Override
-        public <O extends OutputShim> void write(final KryoShim<?, O> kryo, final O output, final TP p) {
+        public <O extends OutputShim> void write(final KryoShim<?, O> kryo, final O output, final TextP p) {
             output.writeString(p.getBiPredicate().toString());
             kryo.writeObject(output, p.getValue());
         }
 
         @Override
-        public <I extends InputShim> TP read(final KryoShim<I, ?> kryo, final I input, final Class<TP> clazz) {
+        public <I extends InputShim> TextP read(final KryoShim<I, ?> kryo, final I input, final Class<TextP> clazz) {
             final String predicate = input.readString();
             final String value = kryo.readObject(input, String.class);
 
             try {
-                return (TP) TP.class.getMethod(predicate, String.class).invoke(null, value);
+                return (TextP) TextP.class.getMethod(predicate, String.class).invoke(null, value);
             } catch (final Exception e) {
                 throw new IllegalStateException(e.getMessage(), e);
             }

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f057fb36/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoVersion.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoVersion.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoVersion.java
index fb62fee..0829fbb 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoVersion.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoVersion.java
@@ -33,7 +33,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.Path;
 import org.apache.tinkerpop.gremlin.process.traversal.Pop;
 import org.apache.tinkerpop.gremlin.process.traversal.SackFunctions;
 import org.apache.tinkerpop.gremlin.process.traversal.Scope;
-import org.apache.tinkerpop.gremlin.process.traversal.TP;
+import org.apache.tinkerpop.gremlin.process.traversal.TextP;
 import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalOptionParent;
 import org.apache.tinkerpop.gremlin.process.traversal.step.filter.RangeGlobalStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.FoldStep;
@@ -312,7 +312,7 @@ public enum GryoVersion {
 
             add(GryoTypeReg.of(Bytecode.class, 122, new GryoSerializersV3d0.BytecodeSerializer()));
             add(GryoTypeReg.of(P.class, 124, new GryoSerializersV3d0.PSerializer()));
-            add(GryoTypeReg.of(TP.class, 186, new GryoSerializersV3d0.TPSerializer())); // ***LAST ID***
+            add(GryoTypeReg.of(TextP.class, 186, new GryoSerializersV3d0.TextPSerializer())); // ***LAST ID***
             add(GryoTypeReg.of(Lambda.class, 125, new GryoSerializersV3d0.LambdaSerializer()));
             add(GryoTypeReg.of(Bytecode.Binding.class, 126, new GryoSerializersV3d0.BindingSerializer()));
             add(GryoTypeReg.of(Order.class, 127));
@@ -504,7 +504,7 @@ public enum GryoVersion {
 
             add(GryoTypeReg.of(Bytecode.class, 122, new GryoSerializersV1d0.BytecodeSerializer()));
             add(GryoTypeReg.of(P.class, 124, new GryoSerializersV1d0.PSerializer()));
-            add(GryoTypeReg.of(TP.class, 186, new GryoSerializersV1d0.TPSerializer())); // ***LAST ID***
+            add(GryoTypeReg.of(TextP.class, 186, new GryoSerializersV1d0.TextPSerializer())); // ***LAST ID***
             add(GryoTypeReg.of(Lambda.class, 125, new GryoSerializersV1d0.LambdaSerializer()));
             add(GryoTypeReg.of(Bytecode.Binding.class, 126, new GryoSerializersV1d0.BindingSerializer()));
             add(GryoTypeReg.of(Order.class, 127));

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f057fb36/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/PTest.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/PTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/PTest.java
index 1060b4e..0e21ece 100644
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/PTest.java
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/PTest.java
@@ -95,20 +95,20 @@ public class PTest {
                     {P.between("m", "n").or(P.eq("daniel")), "daniel", true},
                     {P.between("m", "n").or(P.eq("daniel")), "stephen", false},
                     // text predicates
-                    {TP.contains("ark"), "marko", true},
-                    {TP.contains("ark"), "josh", false},
-                    {TP.startsWith("jo"), "marko", false},
-                    {TP.startsWith("jo"), "josh", true},
-                    {TP.endsWith("ter"), "marko", false},
-                    {TP.endsWith("ter"), "peter", true},
-                    {TP.contains("o"), "marko", true},
-                    {TP.contains("o"), "josh", true},
-                    {TP.contains("o").and(P.gte("j")), "marko", true},
-                    {TP.contains("o").and(P.gte("j")), "josh", true},
-                    {TP.contains("o").and(P.gte("j")).and(TP.endsWith("ko")), "marko", true},
-                    {TP.contains("o").and(P.gte("j")).and(TP.endsWith("ko")), "josh", false},
-                    {TP.contains("o").and(P.gte("j").and(TP.endsWith("ko"))), "marko", true},
-                    {TP.contains("o").and(P.gte("j").and(TP.endsWith("ko"))), "josh", false},
+                    {TextP.contains("ark"), "marko", true},
+                    {TextP.contains("ark"), "josh", false},
+                    {TextP.startsWith("jo"), "marko", false},
+                    {TextP.startsWith("jo"), "josh", true},
+                    {TextP.endsWith("ter"), "marko", false},
+                    {TextP.endsWith("ter"), "peter", true},
+                    {TextP.contains("o"), "marko", true},
+                    {TextP.contains("o"), "josh", true},
+                    {TextP.contains("o").and(P.gte("j")), "marko", true},
+                    {TextP.contains("o").and(P.gte("j")), "josh", true},
+                    {TextP.contains("o").and(P.gte("j")).and(TextP.endsWith("ko")), "marko", true},
+                    {TextP.contains("o").and(P.gte("j")).and(TextP.endsWith("ko")), "josh", false},
+                    {TextP.contains("o").and(P.gte("j").and(TextP.endsWith("ko"))), "marko", true},
+                    {TextP.contains("o").and(P.gte("j").and(TextP.endsWith("ko"))), "josh", false},
             }));
         }
 

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f057fb36/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONMapperPartialEmbeddedTypeTest.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONMapperPartialEmbeddedTypeTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONMapperPartialEmbeddedTypeTest.java
index 52a7ee4..92c4df6 100644
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONMapperPartialEmbeddedTypeTest.java
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONMapperPartialEmbeddedTypeTest.java
@@ -21,7 +21,7 @@ package org.apache.tinkerpop.gremlin.structure.io.graphson;
 import org.apache.tinkerpop.gremlin.process.remote.traversal.DefaultRemoteTraverser;
 import org.apache.tinkerpop.gremlin.process.traversal.Bytecode;
 import org.apache.tinkerpop.gremlin.process.traversal.P;
-import org.apache.tinkerpop.gremlin.process.traversal.TP;
+import org.apache.tinkerpop.gremlin.process.traversal.TextP;
 import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
 import org.apache.tinkerpop.shaded.jackson.databind.JsonMappingException;
 import org.apache.tinkerpop.shaded.jackson.databind.ObjectMapper;
@@ -329,15 +329,15 @@ public class GraphSONMapperPartialEmbeddedTypeTest extends AbstractGraphSONTest
                 P.without(Arrays.asList(1,2,3,4)),
                 P.eq(1).and(P.eq(2)),
                 P.eq(1).or(P.eq(2)),
-                TP.contains("ark"),
-                TP.startsWith("mar"),
-                TP.endsWith("ko"),
-                TP.endsWith("ko").and(P.gte("mar")),
-                P.gte("mar").and(TP.endsWith("ko")));
+                TextP.contains("ark"),
+                TextP.startsWith("mar"),
+                TextP.endsWith("ko"),
+                TextP.endsWith("ko").and(P.gte("mar")),
+                P.gte("mar").and(TextP.endsWith("ko")));
 
         for (P p : variantsOfP) {
-            if (p instanceof TP) {
-                assertEquals(p, serializeDeserialize(mapper, p, TP.class));
+            if (p instanceof TextP) {
+                assertEquals(p, serializeDeserialize(mapper, p, TextP.class));
             } else {
                 assertEquals(p, serializeDeserialize(mapper, p, P.class));
             }

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f057fb36/gremlin-dotnet/glv/TP.template
----------------------------------------------------------------------
diff --git a/gremlin-dotnet/glv/TP.template b/gremlin-dotnet/glv/TP.template
deleted file mode 100644
index 22320ea..0000000
--- a/gremlin-dotnet/glv/TP.template
+++ /dev/null
@@ -1,71 +0,0 @@
-#region License
-
-/*
- * 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.
- */
-
-#endregion
-
-// THIS IS A GENERATED FILE - DO NOT MODIFY THIS FILE DIRECTLY - see pom.xml
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Linq;
-using System.Reflection;
-
-namespace Gremlin.Net.Process.Traversal
-{
-#pragma warning disable 1591
-
-    /// <summary>
-    ///     A <see cref="TP" /> is a predicate of the form Func&lt;string, bool&gt;.
-    ///     That is, given some string, return true or false.
-    /// </summary>
-    public class TP : P
-    {
-        /// <summary>
-        ///     Initializes a new instance of the <see cref="TP" /> class.
-        /// </summary>
-        /// <param name="operatorName">The name of the predicate.</param>
-        /// <param name="value">The value of the predicate.</param>
-        /// <param name="other">An optional other predicate that is used as an argument for this predicate.</param>
-        public TP(string operatorName, string value, P other = null) : base(operatorName, value, other)
-        {
-        }
-
-<% tpmethods.each { method -> %>
-        public static TP <%= toCSharpMethodName.call(method) %>(string value)
-        {
-            return new TP("<%= method %>", value);
-        }
-<% } %>
-
-        private static T[] ToGenericArray<T>(ICollection<T> collection)
-        {
-            return collection?.ToArray() ?? new T[0];
-        }
-
-        /// <inheritdoc />
-        public override string ToString()
-        {
-            return Other == null ? \$"{OperatorName}({Value})" : \$"{OperatorName}({Value},{Other})";
-        }
-    }
-
-#pragma warning restore 1591
-}

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f057fb36/gremlin-dotnet/glv/TextP.template
----------------------------------------------------------------------
diff --git a/gremlin-dotnet/glv/TextP.template b/gremlin-dotnet/glv/TextP.template
new file mode 100644
index 0000000..3e289f6
--- /dev/null
+++ b/gremlin-dotnet/glv/TextP.template
@@ -0,0 +1,71 @@
+#region License
+
+/*
+ * 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.
+ */
+
+#endregion
+
+// THIS IS A GENERATED FILE - DO NOT MODIFY THIS FILE DIRECTLY - see pom.xml
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+
+namespace Gremlin.Net.Process.Traversal
+{
+#pragma warning disable 1591
+
+    /// <summary>
+    ///     A <see cref="TextP" /> is a predicate of the form Func&lt;string, bool&gt;.
+    ///     That is, given some string, return true or false.
+    /// </summary>
+    public class TextP : P
+    {
+        /// <summary>
+        ///     Initializes a new instance of the <see cref="TextP" /> class.
+        /// </summary>
+        /// <param name="operatorName">The name of the predicate.</param>
+        /// <param name="value">The value of the predicate.</param>
+        /// <param name="other">An optional other predicate that is used as an argument for this predicate.</param>
+        public TextP(string operatorName, string value, P other = null) : base(operatorName, value, other)
+        {
+        }
+
+<% tpmethods.each { method -> %>
+        public static TextP <%= toCSharpMethodName.call(method) %>(string value)
+        {
+            return new TextP("<%= method %>", value);
+        }
+<% } %>
+
+        private static T[] ToGenericArray<T>(ICollection<T> collection)
+        {
+            return collection?.ToArray() ?? new T[0];
+        }
+
+        /// <inheritdoc />
+        public override string ToString()
+        {
+            return Other == null ? \$"{OperatorName}({Value})" : \$"{OperatorName}({Value},{Other})";
+        }
+    }
+
+#pragma warning restore 1591
+}

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f057fb36/gremlin-dotnet/glv/generate.groovy
----------------------------------------------------------------------
diff --git a/gremlin-dotnet/glv/generate.groovy b/gremlin-dotnet/glv/generate.groovy
index 3dbd959..0655fd1 100644
--- a/gremlin-dotnet/glv/generate.groovy
+++ b/gremlin-dotnet/glv/generate.groovy
@@ -26,7 +26,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.TraversalSource
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource
 import org.apache.tinkerpop.gremlin.process.traversal.P
-import org.apache.tinkerpop.gremlin.process.traversal.TP
+import org.apache.tinkerpop.gremlin.process.traversal.TextP
 import org.apache.tinkerpop.gremlin.process.traversal.IO
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__
 import org.apache.tinkerpop.gremlin.structure.Direction
@@ -60,7 +60,7 @@ def toCSharpTypeMap = ["Long": "long",
                        "Traversal[]": "ITraversal[]",
                        "Predicate": "IPredicate",
                        "P": "P",
-                       "TP": "TP",
+                       "TextP": "TextP",
                        "TraversalStrategy": "ITraversalStrategy",
                        "TraversalStrategy[]": "ITraversalStrategy[]",
                        "Function": "IFunction",
@@ -243,9 +243,9 @@ def binding = ["pmethods": P.class.getMethods().
         collect { it.name }.
         unique().
         sort { a, b -> a <=> b },
-               "tpmethods": TP.class.getMethods().
+               "tpmethods": TextP.class.getMethods().
                        findAll { Modifier.isStatic(it.getModifiers()) }.
-                       findAll { TP.class.isAssignableFrom(it.returnType) }.
+                       findAll { TextP.class.isAssignableFrom(it.returnType) }.
                        collect { it.name }.
                        unique().
                        sort { a, b -> a <=> b },
@@ -342,8 +342,8 @@ def pTemplate = engine.createTemplate(new File("${projectBaseDir}/glv/P.template
 def pFile = new File("${projectBaseDir}/src/Gremlin.Net/Process/Traversal/P.cs")
 pFile.newWriter().withWriter{ it << pTemplate }
 
-def tpTemplate = engine.createTemplate(new File("${projectBaseDir}/glv/TP.template")).make(binding)
-def tpFile = new File("${projectBaseDir}/src/Gremlin.Net/Process/Traversal/TP.cs")
+def tpTemplate = engine.createTemplate(new File("${projectBaseDir}/glv/TextP.template")).make(binding)
+def tpFile = new File("${projectBaseDir}/src/Gremlin.Net/Process/Traversal/TextP.cs")
 tpFile.newWriter().withWriter{ it << tpTemplate }
 
 binding.tokens.each {k,v ->

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f057fb36/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/TP.cs
----------------------------------------------------------------------
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/TP.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/TP.cs
deleted file mode 100644
index abebd1e..0000000
--- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/TP.cs
+++ /dev/null
@@ -1,96 +0,0 @@
-#region License
-
-/*
- * 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.
- */
-
-#endregion
-
-// THIS IS A GENERATED FILE - DO NOT MODIFY THIS FILE DIRECTLY - see pom.xml
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Linq;
-using System.Reflection;
-
-namespace Gremlin.Net.Process.Traversal
-{
-#pragma warning disable 1591
-
-    /// <summary>
-    ///     A <see cref="TP" /> is a predicate of the form Func&lt;string, bool&gt;.
-    ///     That is, given some string, return true or false.
-    /// </summary>
-    public class TP : P
-    {
-        /// <summary>
-        ///     Initializes a new instance of the <see cref="TP" /> class.
-        /// </summary>
-        /// <param name="operatorName">The name of the predicate.</param>
-        /// <param name="value">The value of the predicate.</param>
-        /// <param name="other">An optional other predicate that is used as an argument for this predicate.</param>
-        public TP(string operatorName, string value, P other = null) : base(operatorName, value, other)
-        {
-        }
-
-
-        public static TP Absent(string value)
-        {
-            return new TP("absent", value);
-        }
-
-        public static TP Contains(string value)
-        {
-            return new TP("contains", value);
-        }
-
-        public static TP EndsNotWith(string value)
-        {
-            return new TP("endsNotWith", value);
-        }
-
-        public static TP EndsWith(string value)
-        {
-            return new TP("endsWith", value);
-        }
-
-        public static TP StartsNotWith(string value)
-        {
-            return new TP("startsNotWith", value);
-        }
-
-        public static TP StartsWith(string value)
-        {
-            return new TP("startsWith", value);
-        }
-
-
-        private static T[] ToGenericArray<T>(ICollection<T> collection)
-        {
-            return collection?.ToArray() ?? new T[0];
-        }
-
-        /// <inheritdoc />
-        public override string ToString()
-        {
-            return Other == null ? $"{OperatorName}({Value})" : $"{OperatorName}({Value},{Other})";
-        }
-    }
-
-#pragma warning restore 1591
-}

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f057fb36/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/TextP.cs
----------------------------------------------------------------------
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/TextP.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/TextP.cs
new file mode 100644
index 0000000..b8e8a64
--- /dev/null
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/TextP.cs
@@ -0,0 +1,96 @@
+#region License
+
+/*
+ * 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.
+ */
+
+#endregion
+
+// THIS IS A GENERATED FILE - DO NOT MODIFY THIS FILE DIRECTLY - see pom.xml
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+
+namespace Gremlin.Net.Process.Traversal
+{
+#pragma warning disable 1591
+
+    /// <summary>
+    ///     A <see cref="TextP" /> is a predicate of the form Func&lt;string, bool&gt;.
+    ///     That is, given some string, return true or false.
+    /// </summary>
+    public class TextP : P
+    {
+        /// <summary>
+        ///     Initializes a new instance of the <see cref="TextP" /> class.
+        /// </summary>
+        /// <param name="operatorName">The name of the predicate.</param>
+        /// <param name="value">The value of the predicate.</param>
+        /// <param name="other">An optional other predicate that is used as an argument for this predicate.</param>
+        public TextP(string operatorName, string value, P other = null) : base(operatorName, value, other)
+        {
+        }
+
+
+        public static TextP Absent(string value)
+        {
+            return new TextP("absent", value);
+        }
+
+        public static TextP Contains(string value)
+        {
+            return new TextP("contains", value);
+        }
+
+        public static TextP EndsNotWith(string value)
+        {
+            return new TextP("endsNotWith", value);
+        }
+
+        public static TextP EndsWith(string value)
+        {
+            return new TextP("endsWith", value);
+        }
+
+        public static TextP StartsNotWith(string value)
+        {
+            return new TextP("startsNotWith", value);
+        }
+
+        public static TextP StartsWith(string value)
+        {
+            return new TextP("startsWith", value);
+        }
+
+
+        private static T[] ToGenericArray<T>(ICollection<T> collection)
+        {
+            return collection?.ToArray() ?? new T[0];
+        }
+
+        /// <inheritdoc />
+        public override string ToString()
+        {
+            return Other == null ? $"{OperatorName}({Value})" : $"{OperatorName}({Value},{Other})";
+        }
+    }
+
+#pragma warning restore 1591
+}

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f057fb36/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/GraphSONWriter.cs
----------------------------------------------------------------------
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/GraphSONWriter.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/GraphSONWriter.cs
index 3178d21..3268ae4 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/GraphSONWriter.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/GraphSONWriter.cs
@@ -58,7 +58,7 @@ namespace Gremlin.Net.Structure.IO.GraphSON
                 {typeof(Type), new ClassSerializer()},
                 {typeof(EnumWrapper), new EnumSerializer()},
                 {typeof(P), new PSerializer()},
-                {typeof(TP), new TPSerializer()},
+                {typeof(TextP), new TextPSerializer()},
                 {typeof(Vertex), new VertexSerializer()},
                 {typeof(Edge), new EdgeSerializer()},
                 {typeof(Property), new PropertySerializer()},

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f057fb36/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/TPSerializer.cs
----------------------------------------------------------------------
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/TPSerializer.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/TPSerializer.cs
deleted file mode 100644
index 22ed358..0000000
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/TPSerializer.cs
+++ /dev/null
@@ -1,45 +0,0 @@
-#region License
-
-/*
- * 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.
- */
-
-#endregion
-
-using System.Collections.Generic;
-using Gremlin.Net.Process.Traversal;
-
-namespace Gremlin.Net.Structure.IO.GraphSON
-{
-    internal class TPSerializer : IGraphSONSerializer
-    {
-        public Dictionary<string, dynamic> Dictify(dynamic predicate, GraphSONWriter writer)
-        {
-            TP p = predicate;
-            var value = p.Other == null
-                ? writer.ToDict(p.Value)
-                : new List<dynamic> {writer.ToDict(p.Value), writer.ToDict(p.Other)};
-            var dict = new Dictionary<string, dynamic>
-            {
-                {"predicate", p.OperatorName},
-                {"value", value}
-            };
-            return GraphSONUtil.ToTypedValue("TP", dict);
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f057fb36/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/TextPSerializer.cs
----------------------------------------------------------------------
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/TextPSerializer.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/TextPSerializer.cs
new file mode 100644
index 0000000..586be2d
--- /dev/null
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/TextPSerializer.cs
@@ -0,0 +1,45 @@
+#region License
+
+/*
+ * 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.
+ */
+
+#endregion
+
+using System.Collections.Generic;
+using Gremlin.Net.Process.Traversal;
+
+namespace Gremlin.Net.Structure.IO.GraphSON
+{
+    internal class TextPSerializer : IGraphSONSerializer
+    {
+        public Dictionary<string, dynamic> Dictify(dynamic predicate, GraphSONWriter writer)
+        {
+            TextP p = predicate;
+            var value = p.Other == null
+                ? writer.ToDict(p.Value)
+                : new List<dynamic> {writer.ToDict(p.Value), writer.ToDict(p.Other)};
+            var dict = new Dictionary<string, dynamic>
+            {
+                {"predicate", p.OperatorName},
+                {"value", value}
+            };
+            return GraphSONUtil.ToTypedValue("TextP", dict);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f057fb36/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TPParameter.cs
----------------------------------------------------------------------
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TPParameter.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TPParameter.cs
deleted file mode 100644
index 9100c6f..0000000
--- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TPParameter.cs
+++ /dev/null
@@ -1,97 +0,0 @@
-#region License
-
-/*
- * 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.
- */
-
-#endregion
-
-using System;
-using System.Collections.Generic;
-using System.Dynamic;
-using System.Linq;
-using System.Reflection;
-using Gremlin.Net.Process.Traversal;
-
-namespace Gremlin.Net.IntegrationTest.Gherkin.TraversalEvaluation
-{
-    /// <summary>
-    /// Represents a parameter for a traversal predicate (ie: TP.contains())
-    /// </summary>
-    internal class TPParameter : ITokenParameter, IEquatable<TPParameter>
-    {
-        private IDictionary<string, object> _contextParameterValues;
-        public IList<Token> Tokens { get; }
-        
-        public TPParameter(IList<Token> tokens)
-        {
-            Tokens = tokens;
-        }
-
-        public bool Equals(TPParameter other)
-        {
-            return Tokens.SequenceEqual(other.Tokens);
-        }
-
-        public override bool Equals(object obj)
-        {
-            if (ReferenceEquals(null, obj)) return false;
-            if (ReferenceEquals(this, obj)) return true;
-            if (obj.GetType() != GetType()) return false;
-            return Equals((TPParameter) obj);
-        }
-
-        public override int GetHashCode()
-        {
-            return Tokens != null ? Tokens.GetHashCode() : 0;
-        }
-
-        public object GetValue()
-        {
-            var type = typeof(TP);
-            object instance = null;
-            for (var i = 1; i < Tokens.Count; i++)
-            {
-                var token = Tokens[i];
-                token.SetContextParameterValues(_contextParameterValues);
-                var method = type.GetMethod(TraversalParser.GetCsharpName(token.Name),
-                    BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public);
-                if (method == null)
-                {
-                    throw new InvalidOperationException($"Predicate (TP) method '{token}' not found for testing");
-                }
-                
-                var parameters = method.IsStatic
-                    ? new object[] {token.Parameters.Select(p => p.GetValue().ToString()).First()}
-                    : token.Parameters.Select(p => p.GetValue()).ToArray();
-                instance = method.Invoke(instance, parameters);
-            }
-            return instance;
-        }
-
-        public Type GetParameterType()
-        {
-            return typeof(TP);
-        }
-
-        public void SetContextParameterValues(IDictionary<string, object> parameterValues)
-        {
-            _contextParameterValues = parameterValues;
-        }
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f057fb36/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TextPParameter.cs
----------------------------------------------------------------------
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TextPParameter.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TextPParameter.cs
new file mode 100644
index 0000000..5999659
--- /dev/null
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TextPParameter.cs
@@ -0,0 +1,97 @@
+#region License
+
+/*
+ * 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.
+ */
+
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Dynamic;
+using System.Linq;
+using System.Reflection;
+using Gremlin.Net.Process.Traversal;
+
+namespace Gremlin.Net.IntegrationTest.Gherkin.TraversalEvaluation
+{
+    /// <summary>
+    /// Represents a parameter for a traversal predicate (ie: TextP.contains())
+    /// </summary>
+    internal class TextPParameter : ITokenParameter, IEquatable<TextPParameter>
+    {
+        private IDictionary<string, object> _contextParameterValues;
+        public IList<Token> Tokens { get; }
+        
+        public TextPParameter(IList<Token> tokens)
+        {
+            Tokens = tokens;
+        }
+
+        public bool Equals(TextPParameter other)
+        {
+            return Tokens.SequenceEqual(other.Tokens);
+        }
+
+        public override bool Equals(object obj)
+        {
+            if (ReferenceEquals(null, obj)) return false;
+            if (ReferenceEquals(this, obj)) return true;
+            if (obj.GetType() != GetType()) return false;
+            return Equals((TextPParameter) obj);
+        }
+
+        public override int GetHashCode()
+        {
+            return Tokens != null ? Tokens.GetHashCode() : 0;
+        }
+
+        public object GetValue()
+        {
+            var type = typeof(TextP);
+            object instance = null;
+            for (var i = 1; i < Tokens.Count; i++)
+            {
+                var token = Tokens[i];
+                token.SetContextParameterValues(_contextParameterValues);
+                var method = type.GetMethod(TraversalParser.GetCsharpName(token.Name),
+                    BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public);
+                if (method == null)
+                {
+                    throw new InvalidOperationException($"Predicate (TextP) method '{token}' not found for testing");
+                }
+                
+                var parameters = method.IsStatic
+                    ? new object[] {token.Parameters.Select(p => p.GetValue().ToString()).First()}
+                    : token.Parameters.Select(p => p.GetValue()).ToArray();
+                instance = method.Invoke(instance, parameters);
+            }
+            return instance;
+        }
+
+        public Type GetParameterType()
+        {
+            return typeof(TextP);
+        }
+
+        public void SetContextParameterValues(IDictionary<string, object> parameterValues)
+        {
+            _contextParameterValues = parameterValues;
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f057fb36/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TraversalParser.cs
----------------------------------------------------------------------
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TraversalParser.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TraversalParser.cs
index 1065780..139cd2d 100644
--- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TraversalParser.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TraversalParser.cs
@@ -406,9 +406,9 @@ namespace Gremlin.Net.IntegrationTest.Gherkin.TraversalEvaluation
                 var tokens = ParseTokens(text, ref i);
                 return new StaticTraversalParameter(tokens, text.Substring(startIndex, i - startIndex));
             }
-            if (text.Length >= i + 3 && text.Substring(i, 3) == "TP.")
+            if (text.Length >= i + 6 && text.Substring(i, 6) == "TextP.")
             {
-                return new TPParameter(ParseTokens(text, ref i));
+                return new TextPParameter(ParseTokens(text, ref i));
             }
             if (text.Substring(i, 2).StartsWith("P."))
             {
@@ -482,4 +482,4 @@ namespace Gremlin.Net.IntegrationTest.Gherkin.TraversalEvaluation
             EndParameters
         }
     }
-}
\ No newline at end of file
+}

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f057fb36/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GroovyTranslator.java
----------------------------------------------------------------------
diff --git a/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GroovyTranslator.java b/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GroovyTranslator.java
index a3e593a..ae892f3 100644
--- a/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GroovyTranslator.java
+++ b/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GroovyTranslator.java
@@ -24,7 +24,7 @@ import org.apache.commons.configuration.ConfigurationConverter;
 import org.apache.tinkerpop.gremlin.process.traversal.Bytecode;
 import org.apache.tinkerpop.gremlin.process.traversal.P;
 import org.apache.tinkerpop.gremlin.process.traversal.SackFunctions;
-import org.apache.tinkerpop.gremlin.process.traversal.TP;
+import org.apache.tinkerpop.gremlin.process.traversal.TextP;
 import org.apache.tinkerpop.gremlin.process.traversal.Translator;
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategy;
@@ -226,7 +226,7 @@ public final class GroovyTranslator implements Translator.ScriptTranslator {
     }
 
     private StringBuilder convertPToString(final P p, final StringBuilder current) {
-        if (p instanceof TP) return convertTPToString((TP) p, current);
+        if (p instanceof TextP) return convertTextPToString((TextP) p, current);
         if (p instanceof ConnectiveP) {
             final List<P<?>> list = ((ConnectiveP) p).getPredicates();
             for (int i = 0; i < list.size(); i++) {
@@ -240,8 +240,8 @@ public final class GroovyTranslator implements Translator.ScriptTranslator {
         return current;
     }
 
-    private StringBuilder convertTPToString(final TP p, final StringBuilder current) {
-        current.append("TP.").append(p.getBiPredicate().toString()).append("(").append(convertToString(p.getValue())).append(")");
+    private StringBuilder convertTextPToString(final TextP p, final StringBuilder current) {
+        current.append("TextP.").append(p.getBiPredicate().toString()).append("(").append(convertToString(p.getValue())).append(")");
         return current;
     }
 }

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f057fb36/gremlin-javascript/glv/TraversalSource.template
----------------------------------------------------------------------
diff --git a/gremlin-javascript/glv/TraversalSource.template b/gremlin-javascript/glv/TraversalSource.template
index 14df95b..46d96b5 100644
--- a/gremlin-javascript/glv/TraversalSource.template
+++ b/gremlin-javascript/glv/TraversalSource.template
@@ -162,7 +162,7 @@ function createP(operator, args) {
   return new (Function.prototype.bind.apply(P, args));
 }
 
-class TP {
+class TextP {
   /**
    * Represents an operation.
    * @constructor
@@ -201,7 +201,7 @@ class TP {
 
 function createTP(operator, args) {
   args.unshift(null, operator);
-  return new (Function.prototype.bind.apply(TP, args));
+  return new (Function.prototype.bind.apply(TextP, args));
 }
 
 class Traverser {
@@ -241,7 +241,7 @@ class EnumValue {
 module.exports = {
   EnumValue,
   P,
-  TP,
+  TextP,
   IO,
   Traversal,
   TraversalSideEffects,

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f057fb36/gremlin-javascript/glv/generate.groovy
----------------------------------------------------------------------
diff --git a/gremlin-javascript/glv/generate.groovy b/gremlin-javascript/glv/generate.groovy
index 243c607..575f847 100644
--- a/gremlin-javascript/glv/generate.groovy
+++ b/gremlin-javascript/glv/generate.groovy
@@ -28,7 +28,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.TraversalSource
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource
 import org.apache.tinkerpop.gremlin.process.traversal.P
-import org.apache.tinkerpop.gremlin.process.traversal.TP
+import org.apache.tinkerpop.gremlin.process.traversal.TextP
 import org.apache.tinkerpop.gremlin.process.traversal.IO
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__
 import java.lang.reflect.Modifier
@@ -70,9 +70,9 @@ def binding = ["enums": CoreImports.getClassImports()
                        collect { it.name }.
                        unique().
                        sort { a, b -> a <=> b },
-               "tpmethods": TP.class.getMethods().
+               "tpmethods": TextP.class.getMethods().
                        findAll { Modifier.isStatic(it.getModifiers()) }.
-                       findAll { TP.class.isAssignableFrom(it.returnType) }.
+                       findAll { TextP.class.isAssignableFrom(it.returnType) }.
                        collect { it.name }.
                        unique().
                        sort { a, b -> a <=> b },

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f057fb36/gremlin-javascript/src/main/javascript/gremlin-javascript/index.js
----------------------------------------------------------------------
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/index.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/index.js
index b15ecbc..f6456b7 100644
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/index.js
+++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/index.js
@@ -49,7 +49,7 @@ module.exports = {
     Bytecode: Bytecode,
     EnumValue: t.EnumValue,
     P: t.P,
-    TP: t.TP,
+    TextP: t.TextP,
     Traversal: t.Traversal,
     TraversalSideEffects: t.TraversalSideEffects,
     TraversalStrategies: strategiesModule.TraversalStrategies,

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f057fb36/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/process/traversal.js
----------------------------------------------------------------------
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/process/traversal.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/process/traversal.js
index ca9d062..89f8ddc 100644
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/process/traversal.js
+++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/process/traversal.js
@@ -310,7 +310,7 @@ function createP(operator, args) {
   return new (Function.prototype.bind.apply(P, args));
 }
 
-class TP {
+class TextP {
   /**
    * Represents an operation.
    * @constructor
@@ -374,7 +374,7 @@ class TP {
 
 function createTP(operator, args) {
   args.unshift(null, operator);
-  return new (Function.prototype.bind.apply(TP, args));
+  return new (Function.prototype.bind.apply(TextP, args));
 }
 
 class Traverser {
@@ -414,7 +414,7 @@ class EnumValue {
 module.exports = {
   EnumValue,
   P,
-  TP,
+  TextP,
   IO,
   Traversal,
   TraversalSideEffects,

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f057fb36/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/graph-serializer.js
----------------------------------------------------------------------
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/graph-serializer.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/graph-serializer.js
index fca8375..52d9e93 100644
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/graph-serializer.js
+++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/graph-serializer.js
@@ -162,7 +162,7 @@ const deserializers = {
   'g:Property': typeSerializers.PropertySerializer,
   'g:Path': typeSerializers.Path3Serializer,
   'g:T': typeSerializers.TSerializer,
-  'g:TP': typeSerializers.TPSerializer,
+  'g:TextP': typeSerializers.TextPSerializer,
   'g:List': typeSerializers.ListSerializer,
   'g:Set': typeSerializers.SetSerializer,
   'g:Map': typeSerializers.MapSerializer
@@ -174,7 +174,7 @@ const serializers = [
   typeSerializers.BytecodeSerializer,
   typeSerializers.TraverserSerializer,
   typeSerializers.PSerializer,
-  typeSerializers.TPSerializer,
+  typeSerializers.TextPSerializer,
   typeSerializers.LambdaSerializer,
   typeSerializers.EnumSerializer,
   typeSerializers.VertexSerializer,

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f057fb36/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/type-serializers.js
----------------------------------------------------------------------
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/type-serializers.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/type-serializers.js
index 576c721..2ea3d27 100644
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/type-serializers.js
+++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/type-serializers.js
@@ -150,11 +150,11 @@ class PSerializer extends TypeSerializer {
   }
 }
 
-class TPSerializer extends TypeSerializer {
-  /** @param {TP} item */
+class TextPSerializer extends TypeSerializer {
+  /** @param {TextP} item */
   serialize(item) {
     const result = {};
-    result[typeKey] = 'g:TP';
+    result[typeKey] = 'g:TextP';
     const resultValue = result[valueKey] = {
       'predicate': item.operator
     };
@@ -168,7 +168,7 @@ class TPSerializer extends TypeSerializer {
   }
 
   canBeUsedFor(value) {
-    return (value instanceof t.TP);
+    return (value instanceof t.TextP);
   }
 }
 
@@ -406,7 +406,7 @@ module.exports = {
   PathSerializer,
   PropertySerializer,
   PSerializer,
-  TPSerializer,
+  TextPSerializer,
   SetSerializer,
   TSerializer,
   TraverserSerializer,

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f057fb36/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/feature-steps.js
----------------------------------------------------------------------
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 abef2a2..d1d5b52 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
@@ -218,7 +218,7 @@ function getSandbox(g, parameters) {
     },
     Order: traversalModule.order,
     P: traversalModule.P,
-    TP: traversalModule.TP,
+    TextP: traversalModule.TextP,
     IO: traversalModule.IO,
     Pick: traversalModule.pick,
     Pop: traversalModule.pop,

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f057fb36/gremlin-python/glv/TraversalSource.template
----------------------------------------------------------------------
diff --git a/gremlin-python/glv/TraversalSource.template b/gremlin-python/glv/TraversalSource.template
index 00a5934..4f40a5f 100644
--- a/gremlin-python/glv/TraversalSource.template
+++ b/gremlin-python/glv/TraversalSource.template
@@ -152,13 +152,13 @@ def <%= method %>(*args):
 statics.add_static('<%= method %>',<%= method %>)
 <% } %>
 
-class TP(P):
+class TextP(P):
     def __init__(self, operator, value, other=None):
         P.__init__(self, operator, value, other)
 <% tpmethods.each { method -> %>
     @staticmethod
     def <%= method %>(*args):
-        return TP("<%= toJava.call(method) %>", *args)
+        return TextP("<%= toJava.call(method) %>", *args)
 <% } %>
     def __eq__(self, other):
         return isinstance(other, self.__class__) and self.operator == other.operator and self.value == other.value and self.other == other.other
@@ -167,7 +167,7 @@ class TP(P):
         return self.operator + "(" + str(self.value) + ")" if self.other is None else self.operator + "(" + str(self.value) + "," + str(self.other) + ")"
 <% tpmethods.findAll{!it.equals("clone")}.each { method -> %>
 def <%= method %>(*args):
-    return TP.<%= method %>(*args)
+    return TextP.<%= method %>(*args)
 statics.add_static('<%= method %>',<%= method %>)
 <% } %>
 

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f057fb36/gremlin-python/glv/generate.groovy
----------------------------------------------------------------------
diff --git a/gremlin-python/glv/generate.groovy b/gremlin-python/glv/generate.groovy
index 8c3d647..60d8381 100644
--- a/gremlin-python/glv/generate.groovy
+++ b/gremlin-python/glv/generate.groovy
@@ -26,7 +26,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.TraversalSource
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource
 import org.apache.tinkerpop.gremlin.process.traversal.P
-import org.apache.tinkerpop.gremlin.process.traversal.TP
+import org.apache.tinkerpop.gremlin.process.traversal.TextP
 import org.apache.tinkerpop.gremlin.process.traversal.IO
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__
 import java.lang.reflect.Modifier
@@ -64,9 +64,9 @@ def binding = ["enums": CoreImports.getClassImports()
                        collect { toPython(it.name) }.
                        unique().
                        sort { a, b -> a <=> b },
-               "tpmethods": TP.class.getMethods().
+               "tpmethods": TextP.class.getMethods().
                        findAll { Modifier.isStatic(it.getModifiers()) }.
-                       findAll { TP.class.isAssignableFrom(it.returnType) }.
+                       findAll { TextP.class.isAssignableFrom(it.returnType) }.
                        collect { toPython(it.name) }.
                        unique().
                        sort { a, b -> a <=> b },

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f057fb36/gremlin-python/src/main/java/org/apache/tinkerpop/gremlin/python/jsr223/PythonTranslator.java
----------------------------------------------------------------------
diff --git a/gremlin-python/src/main/java/org/apache/tinkerpop/gremlin/python/jsr223/PythonTranslator.java b/gremlin-python/src/main/java/org/apache/tinkerpop/gremlin/python/jsr223/PythonTranslator.java
index 0d2695a..59669b1 100644
--- a/gremlin-python/src/main/java/org/apache/tinkerpop/gremlin/python/jsr223/PythonTranslator.java
+++ b/gremlin-python/src/main/java/org/apache/tinkerpop/gremlin/python/jsr223/PythonTranslator.java
@@ -24,7 +24,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.Bytecode;
 import org.apache.tinkerpop.gremlin.process.traversal.Operator;
 import org.apache.tinkerpop.gremlin.process.traversal.P;
 import org.apache.tinkerpop.gremlin.process.traversal.SackFunctions;
-import org.apache.tinkerpop.gremlin.process.traversal.TP;
+import org.apache.tinkerpop.gremlin.process.traversal.TextP;
 import org.apache.tinkerpop.gremlin.process.traversal.Translator;
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.TraversalSource;
@@ -225,7 +225,7 @@ public class PythonTranslator implements Translator.ScriptTranslator {
     }
 
     private StringBuilder convertPToString(final P p, final StringBuilder current) {
-        if (p instanceof TP) return convertTPToString((TP) p, current);
+        if (p instanceof TextP) return convertTextPToString((TextP) p, current);
         if (p instanceof ConnectiveP) {
             final List<P<?>> list = ((ConnectiveP) p).getPredicates();
             for (int i = 0; i < list.size(); i++) {
@@ -239,8 +239,8 @@ public class PythonTranslator implements Translator.ScriptTranslator {
         return current;
     }
 
-    private StringBuilder convertTPToString(final TP p, final StringBuilder current) {
-        current.append(convertStatic("TP.")).append(p.getBiPredicate().toString()).append("(").append(convertToString(p.getValue())).append(")");
+    private StringBuilder convertTextPToString(final TextP p, final StringBuilder current) {
+        current.append(convertStatic("TextP.")).append(p.getBiPredicate().toString()).append("(").append(convertToString(p.getValue())).append(")");
         return current;
     }
 

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f057fb36/gremlin-python/src/main/jython/gremlin_python/process/traversal.py
----------------------------------------------------------------------
diff --git a/gremlin-python/src/main/jython/gremlin_python/process/traversal.py b/gremlin-python/src/main/jython/gremlin_python/process/traversal.py
index a4d9708..7d7d518 100644
--- a/gremlin-python/src/main/jython/gremlin_python/process/traversal.py
+++ b/gremlin-python/src/main/jython/gremlin_python/process/traversal.py
@@ -322,33 +322,33 @@ def without(*args):
 statics.add_static('without',without)
 
 
-class TP(P):
+class TextP(P):
     def __init__(self, operator, value, other=None):
         P.__init__(self, operator, value, other)
 
     @staticmethod
     def absent(*args):
-        return TP("absent", *args)
+        return TextP("absent", *args)
 
     @staticmethod
     def contains(*args):
-        return TP("contains", *args)
+        return TextP("contains", *args)
 
     @staticmethod
     def endsNotWith(*args):
-        return TP("endsNotWith", *args)
+        return TextP("endsNotWith", *args)
 
     @staticmethod
     def endsWith(*args):
-        return TP("endsWith", *args)
+        return TextP("endsWith", *args)
 
     @staticmethod
     def startsNotWith(*args):
-        return TP("startsNotWith", *args)
+        return TextP("startsNotWith", *args)
 
     @staticmethod
     def startsWith(*args):
-        return TP("startsWith", *args)
+        return TextP("startsWith", *args)
 
     def __eq__(self, other):
         return isinstance(other, self.__class__) and self.operator == other.operator and self.value == other.value and self.other == other.other
@@ -357,27 +357,27 @@ class TP(P):
         return self.operator + "(" + str(self.value) + ")" if self.other is None else self.operator + "(" + str(self.value) + "," + str(self.other) + ")"
 
 def absent(*args):
-    return TP.absent(*args)
+    return TextP.absent(*args)
 statics.add_static('absent',absent)
 
 def contains(*args):
-    return TP.contains(*args)
+    return TextP.contains(*args)
 statics.add_static('contains',contains)
 
 def endsNotWith(*args):
-    return TP.endsNotWith(*args)
+    return TextP.endsNotWith(*args)
 statics.add_static('endsNotWith',endsNotWith)
 
 def endsWith(*args):
-    return TP.endsWith(*args)
+    return TextP.endsWith(*args)
 statics.add_static('endsWith',endsWith)
 
 def startsNotWith(*args):
-    return TP.startsNotWith(*args)
+    return TextP.startsNotWith(*args)
 statics.add_static('startsNotWith',startsNotWith)
 
 def startsWith(*args):
-    return TP.startsWith(*args)
+    return TextP.startsWith(*args)
 statics.add_static('startsWith',startsWith)
 
 

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f057fb36/gremlin-python/src/main/jython/gremlin_python/structure/io/graphsonV2d0.py
----------------------------------------------------------------------
diff --git a/gremlin-python/src/main/jython/gremlin_python/structure/io/graphsonV2d0.py b/gremlin-python/src/main/jython/gremlin_python/structure/io/graphsonV2d0.py
index 2cb0b5b..490269a 100644
--- a/gremlin-python/src/main/jython/gremlin_python/structure/io/graphsonV2d0.py
+++ b/gremlin-python/src/main/jython/gremlin_python/structure/io/graphsonV2d0.py
@@ -27,7 +27,7 @@ from aenum import Enum
 
 from gremlin_python import statics
 from gremlin_python.statics import FloatType, FunctionType, IntType, LongType, TypeType
-from gremlin_python.process.traversal import Binding, Bytecode, P, TP, Traversal, Traverser, TraversalStrategy
+from gremlin_python.process.traversal import Binding, Bytecode, P, TextP, Traversal, Traverser, TraversalStrategy
 from gremlin_python.structure.graph import Edge, Property, Vertex, VertexProperty, Path
 
 # When we fall back to a superclass's serializer, we iterate over this map.
@@ -278,15 +278,15 @@ class PSerializer(_GraphSONTypeIO):
         return GraphSONUtil.typedValue("P", out)
 
 
-class TPSerializer(_GraphSONTypeIO):
-    python_type = TP
+class TextPSerializer(_GraphSONTypeIO):
+    python_type = TextP
 
     @classmethod
     def dictify(cls, p, writer):
         out = {"predicate": p.operator,
                "value": [writer.toDict(p.value), writer.toDict(p.other)] if p.other is not None else
                writer.toDict(p.value)}
-        return GraphSONUtil.typedValue("TP", out)
+        return GraphSONUtil.typedValue("TextP", out)
 
 
 class BindingSerializer(_GraphSONTypeIO):


[7/7] tinkerpop git commit: TINKERPOP-2041 Fixed .NET tests around TP predicates

Posted by dk...@apache.org.
TINKERPOP-2041 Fixed .NET tests around TP predicates


Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/79d4a056
Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/79d4a056
Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/79d4a056

Branch: refs/heads/master
Commit: 79d4a056e311971c765bf1b9bd84b48582df7698
Parents: 68c47af
Author: Stephen Mallette <sp...@genoprime.com>
Authored: Fri Sep 28 08:27:25 2018 -0400
Committer: Daniel Kuppitz <da...@hotmail.com>
Committed: Thu Oct 4 07:45:08 2018 -0700

----------------------------------------------------------------------
 .../src/Gremlin.Net/Process/Traversal/TP.cs     |  2 +-
 .../Gherkin/TraversalEvaluation/TPParameter.cs  | 97 ++++++++++++++++++++
 .../TraversalEvaluation/TraversalParser.cs      |  4 +
 3 files changed, 102 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/79d4a056/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/TP.cs
----------------------------------------------------------------------
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/TP.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/TP.cs
index ac6415d..abebd1e 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/TP.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/TP.cs
@@ -39,7 +39,7 @@ namespace Gremlin.Net.Process.Traversal
     public class TP : P
     {
         /// <summary>
-        ///     Initializes a new instance of the <see cref="P" /> class.
+        ///     Initializes a new instance of the <see cref="TP" /> class.
         /// </summary>
         /// <param name="operatorName">The name of the predicate.</param>
         /// <param name="value">The value of the predicate.</param>

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/79d4a056/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TPParameter.cs
----------------------------------------------------------------------
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TPParameter.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TPParameter.cs
new file mode 100644
index 0000000..9100c6f
--- /dev/null
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TPParameter.cs
@@ -0,0 +1,97 @@
+#region License
+
+/*
+ * 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.
+ */
+
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Dynamic;
+using System.Linq;
+using System.Reflection;
+using Gremlin.Net.Process.Traversal;
+
+namespace Gremlin.Net.IntegrationTest.Gherkin.TraversalEvaluation
+{
+    /// <summary>
+    /// Represents a parameter for a traversal predicate (ie: TP.contains())
+    /// </summary>
+    internal class TPParameter : ITokenParameter, IEquatable<TPParameter>
+    {
+        private IDictionary<string, object> _contextParameterValues;
+        public IList<Token> Tokens { get; }
+        
+        public TPParameter(IList<Token> tokens)
+        {
+            Tokens = tokens;
+        }
+
+        public bool Equals(TPParameter other)
+        {
+            return Tokens.SequenceEqual(other.Tokens);
+        }
+
+        public override bool Equals(object obj)
+        {
+            if (ReferenceEquals(null, obj)) return false;
+            if (ReferenceEquals(this, obj)) return true;
+            if (obj.GetType() != GetType()) return false;
+            return Equals((TPParameter) obj);
+        }
+
+        public override int GetHashCode()
+        {
+            return Tokens != null ? Tokens.GetHashCode() : 0;
+        }
+
+        public object GetValue()
+        {
+            var type = typeof(TP);
+            object instance = null;
+            for (var i = 1; i < Tokens.Count; i++)
+            {
+                var token = Tokens[i];
+                token.SetContextParameterValues(_contextParameterValues);
+                var method = type.GetMethod(TraversalParser.GetCsharpName(token.Name),
+                    BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public);
+                if (method == null)
+                {
+                    throw new InvalidOperationException($"Predicate (TP) method '{token}' not found for testing");
+                }
+                
+                var parameters = method.IsStatic
+                    ? new object[] {token.Parameters.Select(p => p.GetValue().ToString()).First()}
+                    : token.Parameters.Select(p => p.GetValue()).ToArray();
+                instance = method.Invoke(instance, parameters);
+            }
+            return instance;
+        }
+
+        public Type GetParameterType()
+        {
+            return typeof(TP);
+        }
+
+        public void SetContextParameterValues(IDictionary<string, object> parameterValues)
+        {
+            _contextParameterValues = parameterValues;
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/79d4a056/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TraversalParser.cs
----------------------------------------------------------------------
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TraversalParser.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TraversalParser.cs
index f8e4095..1065780 100644
--- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TraversalParser.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TraversalParser.cs
@@ -406,6 +406,10 @@ namespace Gremlin.Net.IntegrationTest.Gherkin.TraversalEvaluation
                 var tokens = ParseTokens(text, ref i);
                 return new StaticTraversalParameter(tokens, text.Substring(startIndex, i - startIndex));
             }
+            if (text.Length >= i + 3 && text.Substring(i, 3) == "TP.")
+            {
+                return new TPParameter(ParseTokens(text, ref i));
+            }
             if (text.Substring(i, 2).StartsWith("P."))
             {
                 return new PParameter(ParseTokens(text, ref i));


[6/7] tinkerpop git commit: renamed text predicates and added some javadoc comments

Posted by dk...@apache.org.
renamed text predicates and added some javadoc comments


Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/9b965861
Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/9b965861
Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/9b965861

Branch: refs/heads/master
Commit: 9b965861ed95ffff04beaebe07f99f0ce427f702
Parents: f057fb3
Author: Daniel Kuppitz <da...@hotmail.com>
Authored: Tue Oct 2 13:11:23 2018 -0700
Committer: Daniel Kuppitz <da...@hotmail.com>
Committed: Thu Oct 4 07:45:08 2018 -0700

----------------------------------------------------------------------
 docs/src/reference/the-traversal.asciidoc       | 12 +--
 docs/src/upgrade/release-3.4.x.asciidoc         |  4 +-
 .../gremlin/process/traversal/Text.java         | 78 ++++++++++++++------
 .../gremlin/process/traversal/TextP.java        | 28 +++----
 .../gremlin/process/traversal/PTest.java        | 28 +++----
 .../GraphSONMapperPartialEmbeddedTypeTest.java  | 10 +--
 .../src/Gremlin.Net/Process/Traversal/TextP.cs  | 24 +++---
 .../TraversalEvaluation/TextPParameter.cs       |  2 +-
 gremlin-javascript/glv/TraversalSource.template |  4 +-
 .../gremlin-javascript/lib/process/traversal.js | 26 +++----
 .../jython/gremlin_python/process/traversal.py  | 60 +++++++--------
 gremlin-test/features/filter/Has.feature        | 20 ++---
 .../process/traversal/step/filter/HasTest.java  | 50 ++++++-------
 13 files changed, 191 insertions(+), 155 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/9b965861/docs/src/reference/the-traversal.asciidoc
----------------------------------------------------------------------
diff --git a/docs/src/reference/the-traversal.asciidoc b/docs/src/reference/the-traversal.asciidoc
index fdd261a..85dc1c0 100644
--- a/docs/src/reference/the-traversal.asciidoc
+++ b/docs/src/reference/the-traversal.asciidoc
@@ -3376,12 +3376,12 @@ The provided predicates are outlined in the table below and are used in various
 | `P.between(number,number)` | Is the incoming number greater than or equal to the first provided number and less than the second?
 | `P.within(objects...)` | Is the incoming object in the array of provided objects?
 | `P.without(objects...)` | Is the incoming object not in the array of the provided objects?
-| `TextP.startsWith(string)` | Does the incoming `String` start with the provided `String`?
-| `TextP.endsWith(string)` | Does the incoming `String` end with the provided `String`?
-| `TextP.contains(string)` | Does the incoming `String` contain the provided `String`?
-| `TextP.startsNotWith(string)` | TODO: find a better name
-| `TextP.endsNotWith(string)` | TODO: find a better name
-| `TextP.absent(string)` | TODO: find a better name
+| `TextP.startingWith(string)` | Does the incoming `String` start with the provided `String`?
+| `TextP.endingWith(string)` | Does the incoming `String` end with the provided `String`?
+| `TextP.containing(string)` | Does the incoming `String` contain the provided `String`?
+| `TextP.notStartingWith(string)` | Does the incoming `String` not start with the provided `String`?
+| `TextP.notEndingWith(string)` | Does the incoming `String` not end with the provided `String`?
+| `TextP.notContaining(string)` | Does the incoming `String` not contain the provided `String`?
 |=========================================================
 
 [gremlin-groovy]

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/9b965861/docs/src/upgrade/release-3.4.x.asciidoc
----------------------------------------------------------------------
diff --git a/docs/src/upgrade/release-3.4.x.asciidoc b/docs/src/upgrade/release-3.4.x.asciidoc
index 213577a..21e1899 100644
--- a/docs/src/upgrade/release-3.4.x.asciidoc
+++ b/docs/src/upgrade/release-3.4.x.asciidoc
@@ -35,10 +35,10 @@ Gremlin now supports simple text predicates on top of the existing `P` predicate
 
 [source,groovy]
 ----
-gremlin> g.V().has("person","name", contains("o")).valueMap()
+gremlin> g.V().has("person","name", containing("o")).valueMap()
 ==>[name:[marko],age:[29]]
 ==>[name:[josh],age:[32]]
-gremlin> g.V().has("person","name", contains("o").and(gte("j").and(endsWith("ko")))).valueMap()
+gremlin> g.V().has("person","name", containing("o").and(gte("j").and(endingWith("ko")))).valueMap()
 ==>[name:[marko],age:[29]]
 ----
 

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/9b965861/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Text.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Text.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Text.java
index 5169309..9c25825 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Text.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Text.java
@@ -21,97 +21,131 @@ package org.apache.tinkerpop.gremlin.process.traversal;
 import java.util.function.BiPredicate;
 
 /**
+ * {@link Text} is a {@link java.util.function.BiPredicate} that determines whether the first string starts with, starts
+ * not with, ends with, ends not with, contains or does not contain the second string argument.
+ *
  * @author Daniel Kuppitz (http://gremlin.guru)
+ * @since 3.4.0
  */
 public enum Text implements BiPredicate<String, String> {
 
-    startsWith {
+    /**
+     * Evaluates if the first string starts with the second.
+     *
+     * @since 3.4.0
+     */
+    startingWith {
         @Override
         public boolean test(final String value, final String prefix) {
             return value.startsWith(prefix);
         }
 
         /**
-         * The negative of {@code startsWith} is {@link #startsNotWith}.
+         * The negative of {@code startsWith} is {@link #notStartingWith}.
          */
         @Override
         public Text negate() {
-            return startsNotWith;
+            return notStartingWith;
         }
     },
 
-    startsNotWith {
+    /**
+     * Evaluates if the first string does not start with the second.
+     *
+     * @since 3.4.0
+     */
+    notStartingWith {
         @Override
         public boolean test(final String value, final String prefix) {
-            return !startsWith.test(value, prefix);
+            return !startingWith.test(value, prefix);
         }
 
         /**
-         * The negative of {@code startsNotWith} is {@link #startsWith}.
+         * The negative of {@code startsNotWith} is {@link #startingWith}.
          */
         @Override
         public Text negate() {
-            return startsWith;
+            return startingWith;
         }
     },
 
-    endsWith {
+    /**
+     * Evaluates if the first string ends with the second.
+     *
+     * @since 3.4.0
+     */
+    endingWith {
         @Override
         public boolean test(final String value, final String suffix) {
             return value.endsWith(suffix);
         }
 
         /**
-         * The negative of {@code endsWith} is {@link #endsNotWith}.
+         * The negative of {@code endsWith} is {@link #notEndingWith}.
          */
         @Override
         public Text negate() {
-            return endsNotWith;
+            return notEndingWith;
         }
     },
 
-    endsNotWith {
+    /**
+     * Evaluates if the first string does not end with the second.
+     *
+     * @since 3.4.0
+     */
+    notEndingWith {
         @Override
         public boolean test(final String value, final String prefix) {
-            return !endsWith.test(value, prefix);
+            return !endingWith.test(value, prefix);
         }
 
         /**
-         * The negative of {@code endsNotWith} is {@link #endsWith}.
+         * The negative of {@code endsNotWith} is {@link #endingWith}.
          */
         @Override
         public Text negate() {
-            return endsWith;
+            return endingWith;
         }
     },
 
-    contains {
+    /**
+     * Evaluates if the first string contains the second.
+     *
+     * @since 3.4.0
+     */
+    containing {
         @Override
         public boolean test(final String value, final String search) {
             return value.contains(search);
         }
 
         /**
-         * The negative of {@code contains} is {@link #absent}.
+         * The negative of {@code contains} is {@link #notContaining}.
          */
         @Override
         public Text negate() {
-            return absent;
+            return notContaining;
         }
     },
 
-    absent{
+    /**
+     * Evaluates if the first string does not contain the second.
+     *
+     * @since 3.4.0
+     */
+    notContaining {
         @Override
         public boolean test(final String value, final String search) {
-            return !contains.test(value, search);
+            return !containing.test(value, search);
         }
 
         /**
-         * The negative of {@code absent} is {@link #contains}.
+         * The negative of {@code absent} is {@link #containing}.
          */
         @Override
         public Text negate() {
-            return contains;
+            return containing;
         }
     };
 
@@ -120,4 +154,4 @@ public enum Text implements BiPredicate<String, String> {
      */
     @Override
     public abstract Text negate();
-}
\ No newline at end of file
+}

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/9b965861/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TextP.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TextP.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TextP.java
index 2b1b976..2c28853 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TextP.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TextP.java
@@ -21,6 +21,8 @@ package org.apache.tinkerpop.gremlin.process.traversal;
 import java.util.function.BiPredicate;
 
 /**
+ * Predefined {@code Predicate} values that can be used as {@code String} filters.
+ *
  * @author Daniel Kuppitz (http://gremlin.guru)
  */
 public class TextP extends P<String> {
@@ -56,8 +58,8 @@ public class TextP extends P<String> {
      *
      * @since 3.4.0
      */
-    public static TextP startsWith(final String value) {
-        return new TextP(Text.startsWith, value);
+    public static TextP startingWith(final String value) {
+        return new TextP(Text.startingWith, value);
     }
 
     /**
@@ -65,8 +67,8 @@ public class TextP extends P<String> {
      *
      * @since 3.4.0
      */
-    public static TextP startsNotWith(final String value) {
-        return new TextP(Text.startsNotWith, value);
+    public static TextP notStartingWith(final String value) {
+        return new TextP(Text.notStartingWith, value);
     }
 
     /**
@@ -74,8 +76,8 @@ public class TextP extends P<String> {
      *
      * @since 3.4.0
      */
-    public static TextP endsWith(final String value) {
-        return new TextP(Text.endsWith, value);
+    public static TextP endingWith(final String value) {
+        return new TextP(Text.endingWith, value);
     }
 
     /**
@@ -83,8 +85,8 @@ public class TextP extends P<String> {
      *
      * @since 3.4.0
      */
-    public static TextP endsNotWith(final String value) {
-        return new TextP(Text.endsNotWith, value);
+    public static TextP notEndingWith(final String value) {
+        return new TextP(Text.notEndingWith, value);
     }
 
     /**
@@ -92,8 +94,8 @@ public class TextP extends P<String> {
      *
      * @since 3.4.0
      */
-    public static TextP contains(final String value) {
-        return new TextP(Text.contains, value);
+    public static TextP containing(final String value) {
+        return new TextP(Text.containing, value);
     }
 
     /**
@@ -101,7 +103,7 @@ public class TextP extends P<String> {
      *
      * @since 3.4.0
      */
-    public static TextP absent(final String value) {
-        return new TextP(Text.absent, value);
+    public static TextP notContaining(final String value) {
+        return new TextP(Text.notContaining, value);
     }
-}
\ No newline at end of file
+}

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/9b965861/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/PTest.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/PTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/PTest.java
index 0e21ece..686fd0e 100644
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/PTest.java
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/PTest.java
@@ -95,20 +95,20 @@ public class PTest {
                     {P.between("m", "n").or(P.eq("daniel")), "daniel", true},
                     {P.between("m", "n").or(P.eq("daniel")), "stephen", false},
                     // text predicates
-                    {TextP.contains("ark"), "marko", true},
-                    {TextP.contains("ark"), "josh", false},
-                    {TextP.startsWith("jo"), "marko", false},
-                    {TextP.startsWith("jo"), "josh", true},
-                    {TextP.endsWith("ter"), "marko", false},
-                    {TextP.endsWith("ter"), "peter", true},
-                    {TextP.contains("o"), "marko", true},
-                    {TextP.contains("o"), "josh", true},
-                    {TextP.contains("o").and(P.gte("j")), "marko", true},
-                    {TextP.contains("o").and(P.gte("j")), "josh", true},
-                    {TextP.contains("o").and(P.gte("j")).and(TextP.endsWith("ko")), "marko", true},
-                    {TextP.contains("o").and(P.gte("j")).and(TextP.endsWith("ko")), "josh", false},
-                    {TextP.contains("o").and(P.gte("j").and(TextP.endsWith("ko"))), "marko", true},
-                    {TextP.contains("o").and(P.gte("j").and(TextP.endsWith("ko"))), "josh", false},
+                    {TextP.containing("ark"), "marko", true},
+                    {TextP.containing("ark"), "josh", false},
+                    {TextP.startingWith("jo"), "marko", false},
+                    {TextP.startingWith("jo"), "josh", true},
+                    {TextP.endingWith("ter"), "marko", false},
+                    {TextP.endingWith("ter"), "peter", true},
+                    {TextP.containing("o"), "marko", true},
+                    {TextP.containing("o"), "josh", true},
+                    {TextP.containing("o").and(P.gte("j")), "marko", true},
+                    {TextP.containing("o").and(P.gte("j")), "josh", true},
+                    {TextP.containing("o").and(P.gte("j")).and(TextP.endingWith("ko")), "marko", true},
+                    {TextP.containing("o").and(P.gte("j")).and(TextP.endingWith("ko")), "josh", false},
+                    {TextP.containing("o").and(P.gte("j").and(TextP.endingWith("ko"))), "marko", true},
+                    {TextP.containing("o").and(P.gte("j").and(TextP.endingWith("ko"))), "josh", false},
             }));
         }
 

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/9b965861/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONMapperPartialEmbeddedTypeTest.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONMapperPartialEmbeddedTypeTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONMapperPartialEmbeddedTypeTest.java
index 92c4df6..9533353 100644
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONMapperPartialEmbeddedTypeTest.java
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONMapperPartialEmbeddedTypeTest.java
@@ -329,11 +329,11 @@ public class GraphSONMapperPartialEmbeddedTypeTest extends AbstractGraphSONTest
                 P.without(Arrays.asList(1,2,3,4)),
                 P.eq(1).and(P.eq(2)),
                 P.eq(1).or(P.eq(2)),
-                TextP.contains("ark"),
-                TextP.startsWith("mar"),
-                TextP.endsWith("ko"),
-                TextP.endsWith("ko").and(P.gte("mar")),
-                P.gte("mar").and(TextP.endsWith("ko")));
+                TextP.containing("ark"),
+                TextP.startingWith("mar"),
+                TextP.endingWith("ko"),
+                TextP.endingWith("ko").and(P.gte("mar")),
+                P.gte("mar").and(TextP.endingWith("ko")));
 
         for (P p : variantsOfP) {
             if (p instanceof TextP) {

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/9b965861/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/TextP.cs
----------------------------------------------------------------------
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/TextP.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/TextP.cs
index b8e8a64..3047f75 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/TextP.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/TextP.cs
@@ -49,34 +49,34 @@ namespace Gremlin.Net.Process.Traversal
         }
 
 
-        public static TextP Absent(string value)
+        public static TextP Containing(string value)
         {
-            return new TextP("absent", value);
+            return new TextP("containing", value);
         }
 
-        public static TextP Contains(string value)
+        public static TextP EndingWith(string value)
         {
-            return new TextP("contains", value);
+            return new TextP("endingWith", value);
         }
 
-        public static TextP EndsNotWith(string value)
+        public static TextP NotContaining(string value)
         {
-            return new TextP("endsNotWith", value);
+            return new TextP("notContaining", value);
         }
 
-        public static TextP EndsWith(string value)
+        public static TextP NotEndingWith(string value)
         {
-            return new TextP("endsWith", value);
+            return new TextP("notEndingWith", value);
         }
 
-        public static TextP StartsNotWith(string value)
+        public static TextP NotStartingWith(string value)
         {
-            return new TextP("startsNotWith", value);
+            return new TextP("notStartingWith", value);
         }
 
-        public static TextP StartsWith(string value)
+        public static TextP StartingWith(string value)
         {
-            return new TextP("startsWith", value);
+            return new TextP("startingWith", value);
         }
 
 

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/9b965861/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TextPParameter.cs
----------------------------------------------------------------------
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TextPParameter.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TextPParameter.cs
index 5999659..198cd74 100644
--- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TextPParameter.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TextPParameter.cs
@@ -31,7 +31,7 @@ using Gremlin.Net.Process.Traversal;
 namespace Gremlin.Net.IntegrationTest.Gherkin.TraversalEvaluation
 {
     /// <summary>
-    /// Represents a parameter for a traversal predicate (ie: TextP.contains())
+    /// Represents a parameter for a traversal predicate (ie: TextP.containing())
     /// </summary>
     internal class TextPParameter : ITokenParameter, IEquatable<TextPParameter>
     {

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/9b965861/gremlin-javascript/glv/TraversalSource.template
----------------------------------------------------------------------
diff --git a/gremlin-javascript/glv/TraversalSource.template b/gremlin-javascript/glv/TraversalSource.template
index 46d96b5..cdbec26 100644
--- a/gremlin-javascript/glv/TraversalSource.template
+++ b/gremlin-javascript/glv/TraversalSource.template
@@ -194,12 +194,12 @@ class TextP {
 <% tpmethods.each{ method -> %>
   /** @param {...Object} args */
   static <%= toJs.call(method) %>(...args) {
-    return createTP('<%= method %>', args);
+    return createTextP('<%= method %>', args);
   }
 <% } %>
 }
 
-function createTP(operator, args) {
+function createTextP(operator, args) {
   args.unshift(null, operator);
   return new (Function.prototype.bind.apply(TextP, args));
 }

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/9b965861/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/process/traversal.js
----------------------------------------------------------------------
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/process/traversal.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/process/traversal.js
index 89f8ddc..81853a6 100644
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/process/traversal.js
+++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/process/traversal.js
@@ -341,38 +341,38 @@ class TextP {
   }
 
   /** @param {...Object} args */
-  static absent(...args) {
-    return createTP('absent', args);
+  static containing(...args) {
+    return createTextP('containing', args);
   }
 
   /** @param {...Object} args */
-  static contains(...args) {
-    return createTP('contains', args);
+  static endingWith(...args) {
+    return createTextP('endingWith', args);
   }
 
   /** @param {...Object} args */
-  static endsNotWith(...args) {
-    return createTP('endsNotWith', args);
+  static notContaining(...args) {
+    return createTextP('notContaining', args);
   }
 
   /** @param {...Object} args */
-  static endsWith(...args) {
-    return createTP('endsWith', args);
+  static notEndingWith(...args) {
+    return createTextP('notEndingWith', args);
   }
 
   /** @param {...Object} args */
-  static startsNotWith(...args) {
-    return createTP('startsNotWith', args);
+  static notStartingWith(...args) {
+    return createTextP('notStartingWith', args);
   }
 
   /** @param {...Object} args */
-  static startsWith(...args) {
-    return createTP('startsWith', args);
+  static startingWith(...args) {
+    return createTextP('startingWith', args);
   }
 
 }
 
-function createTP(operator, args) {
+function createTextP(operator, args) {
   args.unshift(null, operator);
   return new (Function.prototype.bind.apply(TextP, args));
 }

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/9b965861/gremlin-python/src/main/jython/gremlin_python/process/traversal.py
----------------------------------------------------------------------
diff --git a/gremlin-python/src/main/jython/gremlin_python/process/traversal.py b/gremlin-python/src/main/jython/gremlin_python/process/traversal.py
index 7d7d518..c1458bc 100644
--- a/gremlin-python/src/main/jython/gremlin_python/process/traversal.py
+++ b/gremlin-python/src/main/jython/gremlin_python/process/traversal.py
@@ -327,28 +327,28 @@ class TextP(P):
         P.__init__(self, operator, value, other)
 
     @staticmethod
-    def absent(*args):
-        return TextP("absent", *args)
+    def containing(*args):
+        return TextP("containing", *args)
 
     @staticmethod
-    def contains(*args):
-        return TextP("contains", *args)
+    def endingWith(*args):
+        return TextP("endingWith", *args)
 
     @staticmethod
-    def endsNotWith(*args):
-        return TextP("endsNotWith", *args)
+    def notContaining(*args):
+        return TextP("notContaining", *args)
 
     @staticmethod
-    def endsWith(*args):
-        return TextP("endsWith", *args)
+    def notEndingWith(*args):
+        return TextP("notEndingWith", *args)
 
     @staticmethod
-    def startsNotWith(*args):
-        return TextP("startsNotWith", *args)
+    def notStartingWith(*args):
+        return TextP("notStartingWith", *args)
 
     @staticmethod
-    def startsWith(*args):
-        return TextP("startsWith", *args)
+    def startingWith(*args):
+        return TextP("startingWith", *args)
 
     def __eq__(self, other):
         return isinstance(other, self.__class__) and self.operator == other.operator and self.value == other.value and self.other == other.other
@@ -356,29 +356,29 @@ class TextP(P):
     def __repr__(self):
         return self.operator + "(" + str(self.value) + ")" if self.other is None else self.operator + "(" + str(self.value) + "," + str(self.other) + ")"
 
-def absent(*args):
-    return TextP.absent(*args)
-statics.add_static('absent',absent)
+def containing(*args):
+    return TextP.containing(*args)
+statics.add_static('containing',containing)
 
-def contains(*args):
-    return TextP.contains(*args)
-statics.add_static('contains',contains)
+def endingWith(*args):
+    return TextP.endingWith(*args)
+statics.add_static('endingWith',endingWith)
 
-def endsNotWith(*args):
-    return TextP.endsNotWith(*args)
-statics.add_static('endsNotWith',endsNotWith)
+def notContaining(*args):
+    return TextP.notContaining(*args)
+statics.add_static('notContaining',notContaining)
 
-def endsWith(*args):
-    return TextP.endsWith(*args)
-statics.add_static('endsWith',endsWith)
+def notEndingWith(*args):
+    return TextP.notEndingWith(*args)
+statics.add_static('notEndingWith',notEndingWith)
 
-def startsNotWith(*args):
-    return TextP.startsNotWith(*args)
-statics.add_static('startsNotWith',startsNotWith)
+def notStartingWith(*args):
+    return TextP.notStartingWith(*args)
+statics.add_static('notStartingWith',notStartingWith)
 
-def startsWith(*args):
-    return TextP.startsWith(*args)
-statics.add_static('startsWith',startsWith)
+def startingWith(*args):
+    return TextP.startingWith(*args)
+statics.add_static('startingWith',startingWith)
 
 
 

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/9b965861/gremlin-test/features/filter/Has.feature
----------------------------------------------------------------------
diff --git a/gremlin-test/features/filter/Has.feature b/gremlin-test/features/filter/Has.feature
index e272c05..30fc4b3 100644
--- a/gremlin-test/features/filter/Has.feature
+++ b/gremlin-test/features/filter/Has.feature
@@ -559,55 +559,55 @@ Feature: Step - has()
       | result |
       | d[6].l |
 
-  Scenario: g_V_hasXname_containsXarkXX
+  Scenario: g_V_hasXname_containingXarkXX
     Given the modern graph
     And the traversal of
       """
-      g.V().has("name", TextP.contains("ark"))
+      g.V().has("name", TextP.containing("ark"))
       """
     When iterated to list
     Then the result should be unordered
       | result |
       | v[marko] |
 
-  Scenario: g_V_hasXname_startsWithXmarXX
+  Scenario: g_V_hasXname_startingWithXmarXX
     Given the modern graph
     And the traversal of
       """
-      g.V().has("name", TextP.startsWith("mar"))
+      g.V().has("name", TextP.startingWith("mar"))
       """
     When iterated to list
     Then the result should be unordered
       | result |
       | v[marko] |
 
-  Scenario: g_V_hasXname_endsWithXasXX
+  Scenario: g_V_hasXname_endingWithXasXX
     Given the modern graph
     And the traversal of
       """
-      g.V().has("name", TextP.endsWith("as"))
+      g.V().has("name", TextP.endingWith("as"))
       """
     When iterated to list
     Then the result should be unordered
       | result |
       | v[vadas] |
 
-  Scenario: g_V_hasXperson_name_containsXoX_andXltXmXXX
+  Scenario: g_V_hasXperson_name_containingXoX_andXltXmXXX
     Given the modern graph
     And the traversal of
       """
-      g.V().has("person", "name", TextP.contains("o").and(P.lt("m")))
+      g.V().has("person", "name", TextP.containing("o").and(P.lt("m")))
       """
     When iterated to list
     Then the result should be unordered
       | result |
       | v[josh] |
 
-  Scenario: g_V_hasXname_gtXmX_andXcontainsXoXXX
+  Scenario: g_V_hasXname_gtXmX_andXcontainingXoXXX
     Given the modern graph
     And the traversal of
       """
-      g.V().has("name", P.gt("m").and(TextP.contains("o")))
+      g.V().has("name", P.gt("m").and(TextP.containing("o")))
       """
     When iterated to list
     Then the result should be unordered

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/9b965861/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/HasTest.java
----------------------------------------------------------------------
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/HasTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/HasTest.java
index 8f7d035..ce075da 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/HasTest.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/HasTest.java
@@ -126,15 +126,15 @@ public abstract class HasTest extends AbstractGremlinProcessTest {
 
     public abstract Traversal<Vertex, Long> get_g_V_hasXage_withoutX27_29X_count();
 
-    public abstract Traversal<Vertex, Vertex> get_g_V_hasXname_containsXarkXX();
+    public abstract Traversal<Vertex, Vertex> get_g_V_hasXname_containingXarkXX();
 
-    public abstract Traversal<Vertex,Vertex> get_g_V_hasXname_startsWithXmarXX();
+    public abstract Traversal<Vertex,Vertex> get_g_V_hasXname_startingWithXmarXX();
 
-    public abstract Traversal<Vertex,Vertex> get_g_V_hasXname_endsWithXasXX();
+    public abstract Traversal<Vertex,Vertex> get_g_V_hasXname_endingWithXasXX();
 
-    public abstract Traversal<Vertex,Vertex> get_g_V_hasXperson_name_containsXoX_andXltXmXXX();
+    public abstract Traversal<Vertex,Vertex> get_g_V_hasXperson_name_containingXoX_andXltXmXXX();
 
-    public abstract Traversal<Vertex,Vertex> get_g_V_hasXname_gtXmX_andXcontainsXoXXX();
+    public abstract Traversal<Vertex,Vertex> get_g_V_hasXname_gtXmX_andXcontainingXoXXX();
 
     @Test
     @LoadGraphWith(MODERN)
@@ -560,8 +560,8 @@ public abstract class HasTest extends AbstractGremlinProcessTest {
 
     @Test
     @LoadGraphWith(MODERN)
-    public void g_V_hasXname_containsXarkXX() {
-        final Traversal<Vertex, Vertex> traversal = get_g_V_hasXname_containsXarkXX();
+    public void g_V_hasXname_containingXarkXX() {
+        final Traversal<Vertex, Vertex> traversal = get_g_V_hasXname_containingXarkXX();
         printTraversalForm(traversal);
         assertTrue(traversal.hasNext());
         assertTrue(traversal.next().value("name").equals("marko"));
@@ -570,8 +570,8 @@ public abstract class HasTest extends AbstractGremlinProcessTest {
 
     @Test
     @LoadGraphWith(MODERN)
-    public void g_V_hasXname_startsWithXmarXX() {
-        final Traversal<Vertex, Vertex> traversal = get_g_V_hasXname_startsWithXmarXX();
+    public void g_V_hasXname_startingWithXmarXX() {
+        final Traversal<Vertex, Vertex> traversal = get_g_V_hasXname_startingWithXmarXX();
         printTraversalForm(traversal);
         assertTrue(traversal.hasNext());
         assertTrue(traversal.next().value("name").equals("marko"));
@@ -580,8 +580,8 @@ public abstract class HasTest extends AbstractGremlinProcessTest {
 
     @Test
     @LoadGraphWith(MODERN)
-    public void g_V_hasXname_endsWithXasXX() {
-        final Traversal<Vertex, Vertex> traversal = get_g_V_hasXname_endsWithXasXX();
+    public void g_V_hasXname_endingWithXasXX() {
+        final Traversal<Vertex, Vertex> traversal = get_g_V_hasXname_endingWithXasXX();
         printTraversalForm(traversal);
         assertTrue(traversal.hasNext());
         assertTrue(traversal.next().value("name").equals("vadas"));
@@ -590,8 +590,8 @@ public abstract class HasTest extends AbstractGremlinProcessTest {
 
     @Test
     @LoadGraphWith(MODERN)
-    public void g_V_hasXperson_name_containsXoX_andXltXmXXX() {
-        final Traversal<Vertex, Vertex> traversal = get_g_V_hasXperson_name_containsXoX_andXltXmXXX();
+    public void g_V_hasXperson_name_containingXoX_andXltXmXXX() {
+        final Traversal<Vertex, Vertex> traversal = get_g_V_hasXperson_name_containingXoX_andXltXmXXX();
         printTraversalForm(traversal);
         assertTrue(traversal.hasNext());
         assertTrue(traversal.next().value("name").equals("josh"));
@@ -600,8 +600,8 @@ public abstract class HasTest extends AbstractGremlinProcessTest {
 
     @Test
     @LoadGraphWith(MODERN)
-    public void g_V_hasXname_gtXmX_andXcontainsXoXXX() {
-        final Traversal<Vertex, Vertex> traversal = get_g_V_hasXname_gtXmX_andXcontainsXoXXX();
+    public void g_V_hasXname_gtXmX_andXcontainingXoXXX() {
+        final Traversal<Vertex, Vertex> traversal = get_g_V_hasXname_gtXmX_andXcontainingXoXXX();
         printTraversalForm(traversal);
         assertTrue(traversal.hasNext());
         assertTrue(traversal.next().value("name").equals("marko"));
@@ -790,28 +790,28 @@ public abstract class HasTest extends AbstractGremlinProcessTest {
         }
 
         @Override
-        public Traversal<Vertex, Vertex> get_g_V_hasXname_containsXarkXX() {
-            return g.V().has("name", TextP.contains("ark"));
+        public Traversal<Vertex, Vertex> get_g_V_hasXname_containingXarkXX() {
+            return g.V().has("name", TextP.containing("ark"));
         }
 
         @Override
-        public Traversal<Vertex, Vertex> get_g_V_hasXname_startsWithXmarXX() {
-            return g.V().has("name", TextP.startsWith("mar"));
+        public Traversal<Vertex, Vertex> get_g_V_hasXname_startingWithXmarXX() {
+            return g.V().has("name", TextP.startingWith("mar"));
         }
 
         @Override
-        public Traversal<Vertex, Vertex> get_g_V_hasXname_endsWithXasXX() {
-            return g.V().has("name", TextP.endsWith("as"));
+        public Traversal<Vertex, Vertex> get_g_V_hasXname_endingWithXasXX() {
+            return g.V().has("name", TextP.endingWith("as"));
         }
 
         @Override
-        public Traversal<Vertex, Vertex> get_g_V_hasXperson_name_containsXoX_andXltXmXXX() {
-            return g.V().has("person","name", TextP.contains("o").and(P.lt("m")));
+        public Traversal<Vertex, Vertex> get_g_V_hasXperson_name_containingXoX_andXltXmXXX() {
+            return g.V().has("person","name", TextP.containing("o").and(P.lt("m")));
         }
 
         @Override
-        public Traversal<Vertex, Vertex> get_g_V_hasXname_gtXmX_andXcontainsXoXXX() {
-            return g.V().has("name", P.gt("m").and(TextP.contains("o")));
+        public Traversal<Vertex, Vertex> get_g_V_hasXname_gtXmX_andXcontainingXoXXX() {
+            return g.V().has("name", P.gt("m").and(TextP.containing("o")));
         }
     }
 }
\ No newline at end of file


[2/7] tinkerpop git commit: Renamed `TP` to `TextP` as proposed by @robertdale

Posted by dk...@apache.org.
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f057fb36/gremlin-python/src/main/jython/gremlin_python/structure/io/graphsonV3d0.py
----------------------------------------------------------------------
diff --git a/gremlin-python/src/main/jython/gremlin_python/structure/io/graphsonV3d0.py b/gremlin-python/src/main/jython/gremlin_python/structure/io/graphsonV3d0.py
index 266e23d..2d32d47 100644
--- a/gremlin-python/src/main/jython/gremlin_python/structure/io/graphsonV3d0.py
+++ b/gremlin-python/src/main/jython/gremlin_python/structure/io/graphsonV3d0.py
@@ -27,7 +27,7 @@ from aenum import Enum
 
 from gremlin_python import statics
 from gremlin_python.statics import FloatType, FunctionType, IntType, LongType, TypeType, DictType, ListType, SetType
-from gremlin_python.process.traversal import Binding, Bytecode, P, TP, Traversal, Traverser, TraversalStrategy, T
+from gremlin_python.process.traversal import Binding, Bytecode, P, TextP, Traversal, Traverser, TraversalStrategy, T
 from gremlin_python.structure.graph import Edge, Property, Vertex, VertexProperty, Path
 
 # When we fall back to a superclass's serializer, we iterate over this map.
@@ -284,15 +284,15 @@ class PSerializer(_GraphSONTypeIO):
         return GraphSONUtil.typedValue("P", out)
 
 
-class TPSerializer(_GraphSONTypeIO):
-    python_type = TP
+class TextPSerializer(_GraphSONTypeIO):
+    python_type = TextP
 
     @classmethod
     def dictify(cls, p, writer):
         out = {"predicate": p.operator,
                "value": [writer.toDict(p.value), writer.toDict(p.other)] if p.other is not None else
                writer.toDict(p.value)}
-        return GraphSONUtil.typedValue("TP", out)
+        return GraphSONUtil.typedValue("TextP", out)
 
 
 class BindingSerializer(_GraphSONTypeIO):

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f057fb36/gremlin-python/src/main/jython/radish/feature_steps.py
----------------------------------------------------------------------
diff --git a/gremlin-python/src/main/jython/radish/feature_steps.py b/gremlin-python/src/main/jython/radish/feature_steps.py
index 151d6d5..4777ef3 100644
--- a/gremlin-python/src/main/jython/radish/feature_steps.py
+++ b/gremlin-python/src/main/jython/radish/feature_steps.py
@@ -21,7 +21,7 @@ import json
 import re
 from gremlin_python.structure.graph import Graph, Path
 from gremlin_python.process.graph_traversal import __
-from gremlin_python.process.traversal import Barrier, Cardinality, P, TP, Pop, Scope, Column, Order, Direction, T, Pick, Operator, IO
+from gremlin_python.process.traversal import Barrier, Cardinality, P, TextP, Pop, Scope, Column, Order, Direction, T, Pick, Operator, IO
 from radish import given, when, then
 from hamcrest import *
 
@@ -256,7 +256,7 @@ def _make_traversal(g, traversal_string, params):
          "Direction": Direction,
          "Order": Order,
          "P": P,
-         "TP": TP,
+         "TextP": TextP,
          "IO": IO,
          "Pick": Pick,
          "Pop": Pop,

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f057fb36/gremlin-test/features/filter/Has.feature
----------------------------------------------------------------------
diff --git a/gremlin-test/features/filter/Has.feature b/gremlin-test/features/filter/Has.feature
index 9d2bf4f..e272c05 100644
--- a/gremlin-test/features/filter/Has.feature
+++ b/gremlin-test/features/filter/Has.feature
@@ -563,7 +563,7 @@ Feature: Step - has()
     Given the modern graph
     And the traversal of
       """
-      g.V().has("name", TP.contains("ark"))
+      g.V().has("name", TextP.contains("ark"))
       """
     When iterated to list
     Then the result should be unordered
@@ -574,7 +574,7 @@ Feature: Step - has()
     Given the modern graph
     And the traversal of
       """
-      g.V().has("name", TP.startsWith("mar"))
+      g.V().has("name", TextP.startsWith("mar"))
       """
     When iterated to list
     Then the result should be unordered
@@ -585,7 +585,7 @@ Feature: Step - has()
     Given the modern graph
     And the traversal of
       """
-      g.V().has("name", TP.endsWith("as"))
+      g.V().has("name", TextP.endsWith("as"))
       """
     When iterated to list
     Then the result should be unordered
@@ -596,7 +596,7 @@ Feature: Step - has()
     Given the modern graph
     And the traversal of
       """
-      g.V().has("person", "name", TP.contains("o").and(P.lt("m")))
+      g.V().has("person", "name", TextP.contains("o").and(P.lt("m")))
       """
     When iterated to list
     Then the result should be unordered
@@ -607,7 +607,7 @@ Feature: Step - has()
     Given the modern graph
     And the traversal of
       """
-      g.V().has("name", P.gt("m").and(TP.contains("o")))
+      g.V().has("name", P.gt("m").and(TextP.contains("o")))
       """
     When iterated to list
     Then the result should be unordered

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f057fb36/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/HasTest.java
----------------------------------------------------------------------
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/HasTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/HasTest.java
index cb4abab..8f7d035 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/HasTest.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/HasTest.java
@@ -23,7 +23,7 @@ import org.apache.tinkerpop.gremlin.LoadGraphWith;
 import org.apache.tinkerpop.gremlin.process.AbstractGremlinProcessTest;
 import org.apache.tinkerpop.gremlin.process.GremlinProcessRunner;
 import org.apache.tinkerpop.gremlin.process.traversal.P;
-import org.apache.tinkerpop.gremlin.process.traversal.TP;
+import org.apache.tinkerpop.gremlin.process.traversal.TextP;
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
 import org.apache.tinkerpop.gremlin.structure.Edge;
@@ -791,27 +791,27 @@ public abstract class HasTest extends AbstractGremlinProcessTest {
 
         @Override
         public Traversal<Vertex, Vertex> get_g_V_hasXname_containsXarkXX() {
-            return g.V().has("name", TP.contains("ark"));
+            return g.V().has("name", TextP.contains("ark"));
         }
 
         @Override
         public Traversal<Vertex, Vertex> get_g_V_hasXname_startsWithXmarXX() {
-            return g.V().has("name", TP.startsWith("mar"));
+            return g.V().has("name", TextP.startsWith("mar"));
         }
 
         @Override
         public Traversal<Vertex, Vertex> get_g_V_hasXname_endsWithXasXX() {
-            return g.V().has("name", TP.endsWith("as"));
+            return g.V().has("name", TextP.endsWith("as"));
         }
 
         @Override
         public Traversal<Vertex, Vertex> get_g_V_hasXperson_name_containsXoX_andXltXmXXX() {
-            return g.V().has("person","name", TP.contains("o").and(P.lt("m")));
+            return g.V().has("person","name", TextP.contains("o").and(P.lt("m")));
         }
 
         @Override
         public Traversal<Vertex, Vertex> get_g_V_hasXname_gtXmX_andXcontainsXoXXX() {
-            return g.V().has("name", P.gt("m").and(TP.contains("o")));
+            return g.V().has("name", P.gt("m").and(TextP.contains("o")));
         }
     }
 }
\ No newline at end of file


[4/7] tinkerpop git commit: TINKERPOP-2041 Implemented text predicates

Posted by dk...@apache.org.
TINKERPOP-2041 Implemented text predicates


Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/519ca65c
Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/519ca65c
Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/519ca65c

Branch: refs/heads/master
Commit: 519ca65c0aef496a1fc1c4d2166622c41ff9c1e4
Parents: 3a8f580
Author: Daniel Kuppitz <da...@hotmail.com>
Authored: Wed Sep 26 15:44:35 2018 -0700
Committer: Daniel Kuppitz <da...@hotmail.com>
Committed: Thu Oct 4 07:45:08 2018 -0700

----------------------------------------------------------------------
 CHANGELOG.asciidoc                              |   1 +
 docs/src/reference/the-traversal.asciidoc       |  34 +++--
 docs/src/upgrade/release-3.4.x.asciidoc         |  15 +++
 .../tinkerpop/gremlin/jsr223/CoreImports.java   |   3 +
 .../tinkerpop/gremlin/process/traversal/TP.java | 107 ++++++++++++++++
 .../gremlin/process/traversal/Text.java         | 123 +++++++++++++++++++
 .../structure/io/graphson/GraphSONModule.java   |   5 +
 .../io/graphson/TraversalSerializersV2d0.java   |  35 ++++++
 .../io/graphson/TraversalSerializersV3d0.java   |  35 ++++++
 .../structure/io/gryo/GryoSerializersV1d0.java  |  21 ++++
 .../structure/io/gryo/GryoSerializersV3d0.java  |  21 ++++
 .../gremlin/structure/io/gryo/GryoVersion.java  |   7 +-
 .../gremlin/process/traversal/PTest.java        |  15 +++
 .../GraphSONMapperPartialEmbeddedTypeTest.java  |  14 ++-
 gremlin-dotnet/glv/TP.template                  |  71 +++++++++++
 gremlin-dotnet/glv/generate.groovy              |  14 ++-
 .../src/Gremlin.Net/Process/Traversal/TP.cs     |  96 +++++++++++++++
 .../Structure/IO/GraphSON/GraphSONWriter.cs     |   3 +-
 .../Structure/IO/GraphSON/TPSerializer.cs       |  45 +++++++
 .../gremlin/groovy/jsr223/GroovyTranslator.java |   7 ++
 gremlin-javascript/glv/TraversalSource.template |  45 ++++++-
 gremlin-javascript/glv/generate.groovy          |   7 ++
 .../main/javascript/gremlin-javascript/index.js |   1 +
 .../gremlin-javascript/lib/process/traversal.js |  70 ++++++++++-
 .../lib/structure/io/type-serializers.js        |  24 +++-
 .../test/cucumber/feature-steps.js              |   1 +
 gremlin-python/glv/TraversalSource.template     |  21 +++-
 gremlin-python/glv/generate.groovy              |   9 +-
 .../gremlin/python/jsr223/PythonTranslator.java |   7 ++
 .../jython/gremlin_python/process/traversal.py  |  61 ++++++++-
 .../gremlin_python/structure/io/graphsonV2d0.py |  13 +-
 .../gremlin_python/structure/io/graphsonV3d0.py |  13 +-
 .../src/main/jython/radish/feature_steps.py     |   3 +-
 gremlin-test/features/filter/Has.feature        |  57 ++++++++-
 .../process/traversal/step/filter/HasTest.java  |  86 +++++++++++++
 35 files changed, 1061 insertions(+), 29 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/519ca65c/CHANGELOG.asciidoc
----------------------------------------------------------------------
diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc
index b475c86..554ec2f 100644
--- a/CHANGELOG.asciidoc
+++ b/CHANGELOG.asciidoc
@@ -25,6 +25,7 @@ image::https://raw.githubusercontent.com/apache/tinkerpop/master/docs/static/ima
 
 This release also includes changes from <<release-3-3-3, 3.3.3>>.
 
+* Added text predicates.
 * Rewrote `ConnectiveStrategy` to support an arbitrary number of infix notations in a single traversal.
 * GraphSON `MessageSerializer`s will automatically register the GremlinServerModule to a provided GraphSONMapper.
 * Removed support for `-i` option in Gremlin Server which was previously deprecated.

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/519ca65c/docs/src/reference/the-traversal.asciidoc
----------------------------------------------------------------------
diff --git a/docs/src/reference/the-traversal.asciidoc b/docs/src/reference/the-traversal.asciidoc
index 6146f9b..da7260c 100644
--- a/docs/src/reference/the-traversal.asciidoc
+++ b/docs/src/reference/the-traversal.asciidoc
@@ -3356,24 +3356,32 @@ interface. Steps that allow for this type of modulation will explicitly state so
 [[a-note-on-predicates]]
 == A Note on Predicates
 
-A `P` is a predicate of the form `Function<Object,Boolean>`. That is, given some object, return true or false. The
-provided predicates are outlined in the table below and are used in various steps such as <<has-step,`has()`>>-step,
+A `P` is a predicate of the form `Function<Object,Boolean>`. That is, given some object, return true or false. As of
+the relase of TinkerPop 3.4.0, Gremlin also supports simple text predicates, which only work on `String` values. The `TP`
+text predicates extends the `P` predicates, but are specialized in that they are of the form `Function<String,Boolean>`.
+The provided predicates are outlined in the table below and are used in various steps such as <<has-step,`has()`>>-step,
 <<where-step,`where()`>>-step, <<is-step,`is()`>>-step, etc.
 
 [width="100%",cols="3,15",options="header"]
 |=========================================================
 | Predicate | Description
-| `eq(object)` | Is the incoming object equal to the provided object?
-| `neq(object)` | Is the incoming object not equal to the provided object?
-| `lt(number)` | Is the incoming number less than the provided number?
-| `lte(number)` | Is the incoming number less than or equal to the provided number?
-| `gt(number)` | Is the incoming number greater than the provided number?
-| `gte(number)` | Is the incoming number greater than or equal to the provided number?
-| `inside(number,number)` | Is the incoming number greater than the first provided number and less than the second?
-| `outside(number,number)` | Is the incoming number less than the first provided number or greater than the second?
-| `between(number,number)` | Is the incoming number greater than or equal to the first provided number and less than the second?
-| `within(objects...)` | Is the incoming object in the array of provided objects?
-| `without(objects...)` | Is the incoming object not in the array of the provided objects?
+| `P.eq(object)` | Is the incoming object equal to the provided object?
+| `P.neq(object)` | Is the incoming object not equal to the provided object?
+| `P.lt(number)` | Is the incoming number less than the provided number?
+| `P.lte(number)` | Is the incoming number less than or equal to the provided number?
+| `P.gt(number)` | Is the incoming number greater than the provided number?
+| `P.gte(number)` | Is the incoming number greater than or equal to the provided number?
+| `P.inside(number,number)` | Is the incoming number greater than the first provided number and less than the second?
+| `P.outside(number,number)` | Is the incoming number less than the first provided number or greater than the second?
+| `P.between(number,number)` | Is the incoming number greater than or equal to the first provided number and less than the second?
+| `P.within(objects...)` | Is the incoming object in the array of provided objects?
+| `P.without(objects...)` | Is the incoming object not in the array of the provided objects?
+| `TP.startsWith(string)` | Does the incoming `String` start with the provided `String`?
+| `TP.endsWith(string)` | Does the incoming `String` end with the provided `String`?
+| `TP.contains(string)` | Does the incoming `String` contain the provided `String`?
+| `TP.startsNotWith(string)` | TODO: find a better name
+| `TP.endsNotWith(string)` | TODO: find a better name
+| `TP.absent(string)` | TODO: find a better name
 |=========================================================
 
 [gremlin-groovy]

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/519ca65c/docs/src/upgrade/release-3.4.x.asciidoc
----------------------------------------------------------------------
diff --git a/docs/src/upgrade/release-3.4.x.asciidoc b/docs/src/upgrade/release-3.4.x.asciidoc
index 69a2502..c26b9c7 100644
--- a/docs/src/upgrade/release-3.4.x.asciidoc
+++ b/docs/src/upgrade/release-3.4.x.asciidoc
@@ -29,6 +29,21 @@ Please see the link:https://github.com/apache/tinkerpop/blob/3.4.0/CHANGELOG.asc
 
 === Upgrading for Users
 
+==== Added text predicates
+
+Gremlin now supports simple text predicates on top of the existing `P` predicates. Both, the new `TP` text predicates and the old `P` predicates, can be chained using `and()` and `or()`.
+
+[source,groovy]
+----
+gremlin> g.V().has("person","name", contains("o")).valueMap()
+==>[name:[marko],age:[29]]
+==>[name:[josh],age:[32]]
+gremlin> g.V().has("person","name", contains("o").and(gte("j").and(endsWith("ko")))).valueMap()
+==>[name:[marko],age:[29]]
+----
+
+See: link:https://issues.apache.org/jira/browse/TINKERPOP-2041[TINKERPOP-2041]
+
 ==== Changed infix behavior
 
 The infix notation of `and()` and `or()` now supports an arbitrary number of traversals and `ConnectiveStrategy` produces a traversal with proper AND and OR semantics.

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/519ca65c/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/CoreImports.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/CoreImports.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/CoreImports.java
index 2b1e33e..38ef258 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/CoreImports.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/CoreImports.java
@@ -67,6 +67,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.P;
 import org.apache.tinkerpop.gremlin.process.traversal.Pop;
 import org.apache.tinkerpop.gremlin.process.traversal.SackFunctions;
 import org.apache.tinkerpop.gremlin.process.traversal.Scope;
+import org.apache.tinkerpop.gremlin.process.traversal.TP;
 import org.apache.tinkerpop.gremlin.process.traversal.Translator;
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal;
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
@@ -181,6 +182,7 @@ public final class CoreImports {
         CLASS_IMPORTS.add(TraversalOptionParent.class);
         CLASS_IMPORTS.add(TraversalOptionParent.Pick.class);
         CLASS_IMPORTS.add(P.class);
+        CLASS_IMPORTS.add(TP.class);
         // remote
         CLASS_IMPORTS.add(RemoteConnection.class);
         CLASS_IMPORTS.add(RemoteGraph.class);
@@ -291,6 +293,7 @@ public final class CoreImports {
 
         uniqueMethods(IoCore.class).forEach(METHOD_IMPORTS::add);
         uniqueMethods(P.class).forEach(METHOD_IMPORTS::add);
+        uniqueMethods(TP.class).forEach(METHOD_IMPORTS::add);
         uniqueMethods(__.class).filter(m -> !m.getName().equals("__")).forEach(METHOD_IMPORTS::add);
         uniqueMethods(Computer.class).forEach(METHOD_IMPORTS::add);
         uniqueMethods(TimeUtil.class).forEach(METHOD_IMPORTS::add);

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/519ca65c/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TP.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TP.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TP.java
new file mode 100644
index 0000000..fc245a4
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TP.java
@@ -0,0 +1,107 @@
+/*
+ * 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;
+
+import java.util.function.BiPredicate;
+
+/**
+ * @author Daniel Kuppitz (http://gremlin.guru)
+ */
+public class TP extends P<String> {
+
+    @SuppressWarnings("WeakerAccess")
+    public TP(final BiPredicate<String, String> biPredicate, final String value) {
+        super(biPredicate, value);
+    }
+
+    @Override
+    public boolean equals(final Object other) {
+        return other instanceof TP && super.equals(other);
+    }
+
+    @Override
+    public String toString() {
+        return null == this.originalValue ? this.biPredicate.toString() : this.biPredicate.toString() + "(" + this.originalValue + ")";
+    }
+
+    @Override
+    public TP negate() {
+        return new TP(this.biPredicate.negate(), this.originalValue);
+    }
+
+    public TP clone() {
+        return (TP) super.clone();
+    }
+
+    //////////////// statics
+
+    /**
+     * Determines if String does start with the given value.
+     *
+     * @since 3.4.0
+     */
+    public static TP startsWith(final String value) {
+        return new TP(Text.startsWith, value);
+    }
+
+    /**
+     * Determines if String does not start with the given value.
+     *
+     * @since 3.4.0
+     */
+    public static TP startsNotWith(final String value) {
+        return new TP(Text.startsNotWith, value);
+    }
+
+    /**
+     * Determines if String does start with the given value.
+     *
+     * @since 3.4.0
+     */
+    public static TP endsWith(final String value) {
+        return new TP(Text.endsWith, value);
+    }
+
+    /**
+     * Determines if String does not start with the given value.
+     *
+     * @since 3.4.0
+     */
+    public static TP endsNotWith(final String value) {
+        return new TP(Text.endsNotWith, value);
+    }
+
+    /**
+     * Determines if String does contain the given value.
+     *
+     * @since 3.4.0
+     */
+    public static TP contains(final String value) {
+        return new TP(Text.contains, value);
+    }
+
+    /**
+     * Determines if String does not contain the given value.
+     *
+     * @since 3.4.0
+     */
+    public static TP absent(final String value) {
+        return new TP(Text.absent, value);
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/519ca65c/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Text.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Text.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Text.java
new file mode 100644
index 0000000..5169309
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Text.java
@@ -0,0 +1,123 @@
+/*
+ * 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;
+
+import java.util.function.BiPredicate;
+
+/**
+ * @author Daniel Kuppitz (http://gremlin.guru)
+ */
+public enum Text implements BiPredicate<String, String> {
+
+    startsWith {
+        @Override
+        public boolean test(final String value, final String prefix) {
+            return value.startsWith(prefix);
+        }
+
+        /**
+         * The negative of {@code startsWith} is {@link #startsNotWith}.
+         */
+        @Override
+        public Text negate() {
+            return startsNotWith;
+        }
+    },
+
+    startsNotWith {
+        @Override
+        public boolean test(final String value, final String prefix) {
+            return !startsWith.test(value, prefix);
+        }
+
+        /**
+         * The negative of {@code startsNotWith} is {@link #startsWith}.
+         */
+        @Override
+        public Text negate() {
+            return startsWith;
+        }
+    },
+
+    endsWith {
+        @Override
+        public boolean test(final String value, final String suffix) {
+            return value.endsWith(suffix);
+        }
+
+        /**
+         * The negative of {@code endsWith} is {@link #endsNotWith}.
+         */
+        @Override
+        public Text negate() {
+            return endsNotWith;
+        }
+    },
+
+    endsNotWith {
+        @Override
+        public boolean test(final String value, final String prefix) {
+            return !endsWith.test(value, prefix);
+        }
+
+        /**
+         * The negative of {@code endsNotWith} is {@link #endsWith}.
+         */
+        @Override
+        public Text negate() {
+            return endsWith;
+        }
+    },
+
+    contains {
+        @Override
+        public boolean test(final String value, final String search) {
+            return value.contains(search);
+        }
+
+        /**
+         * The negative of {@code contains} is {@link #absent}.
+         */
+        @Override
+        public Text negate() {
+            return absent;
+        }
+    },
+
+    absent{
+        @Override
+        public boolean test(final String value, final String search) {
+            return !contains.test(value, search);
+        }
+
+        /**
+         * The negative of {@code absent} is {@link #contains}.
+         */
+        @Override
+        public Text negate() {
+            return contains;
+        }
+    };
+
+    /**
+     * Produce the opposite representation of the current {@code Text} enum.
+     */
+    @Override
+    public abstract Text negate();
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/519ca65c/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONModule.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONModule.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONModule.java
index 1bccd7c..74647a1 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONModule.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONModule.java
@@ -28,6 +28,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.Path;
 import org.apache.tinkerpop.gremlin.process.traversal.Pop;
 import org.apache.tinkerpop.gremlin.process.traversal.SackFunctions;
 import org.apache.tinkerpop.gremlin.process.traversal.Scope;
+import org.apache.tinkerpop.gremlin.process.traversal.TP;
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
@@ -145,6 +146,7 @@ abstract class GraphSONModule extends TinkerPopJacksonModule {
                     put(AndP.class, "P");
                     put(OrP.class, "P");
                     put(P.class, "P");
+                    put(TP.class, "TP");
                     Stream.of(
                             VertexProperty.Cardinality.class,
                             Column.class,
@@ -270,6 +272,7 @@ abstract class GraphSONModule extends TinkerPopJacksonModule {
                     TraversalOptionParent.Pick.values(),
                     T.values()).flatMap(Stream::of).forEach(e -> addDeserializer(e.getClass(), new TraversalSerializersV3d0.EnumJacksonDeserializer(e.getDeclaringClass())));
             addDeserializer(P.class, new TraversalSerializersV3d0.PJacksonDeserializer());
+            addDeserializer(TP.class, new TraversalSerializersV3d0.TPJacksonDeserializer());
             addDeserializer(Lambda.class, new TraversalSerializersV3d0.LambdaJacksonDeserializer());
             addDeserializer(Traverser.class, new TraversalSerializersV3d0.TraverserJacksonDeserializer());
             Arrays.asList(
@@ -359,6 +362,7 @@ abstract class GraphSONModule extends TinkerPopJacksonModule {
                     put(AndP.class, "P");
                     put(OrP.class, "P");
                     put(P.class, "P");
+                    put(TP.class, "TP");
                     Stream.of(
                             VertexProperty.Cardinality.class,
                             Column.class,
@@ -476,6 +480,7 @@ abstract class GraphSONModule extends TinkerPopJacksonModule {
                     TraversalOptionParent.Pick.values(),
                     T.values()).flatMap(Stream::of).forEach(e -> addDeserializer(e.getClass(), new TraversalSerializersV2d0.EnumJacksonDeserializer(e.getDeclaringClass())));
             addDeserializer(P.class, new TraversalSerializersV2d0.PJacksonDeserializer());
+            addDeserializer(TP.class, new TraversalSerializersV2d0.TPJacksonDeserializer());
             addDeserializer(Lambda.class, new TraversalSerializersV2d0.LambdaJacksonDeserializer());
             addDeserializer(Traverser.class, new TraversalSerializersV2d0.TraverserJacksonDeserializer());
             Arrays.asList(

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/519ca65c/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/TraversalSerializersV2d0.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/TraversalSerializersV2d0.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/TraversalSerializersV2d0.java
index 2a07723..7ba4ca5 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/TraversalSerializersV2d0.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/TraversalSerializersV2d0.java
@@ -24,6 +24,7 @@ import org.apache.commons.configuration.MapConfiguration;
 import org.apache.tinkerpop.gremlin.process.remote.traversal.DefaultRemoteTraverser;
 import org.apache.tinkerpop.gremlin.process.traversal.Bytecode;
 import org.apache.tinkerpop.gremlin.process.traversal.P;
+import org.apache.tinkerpop.gremlin.process.traversal.TP;
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
@@ -372,6 +373,40 @@ final class TraversalSerializersV2d0 {
         }
     }
 
+    final static class TPJacksonDeserializer extends StdDeserializer<TP> {
+
+        public TPJacksonDeserializer() {
+            super(TP.class);
+        }
+
+        @Override
+        public TP deserialize(final JsonParser jsonParser, final DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
+            String predicate = null;
+            String value = null;
+
+            while (jsonParser.nextToken() != JsonToken.END_OBJECT) {
+                if (jsonParser.getCurrentName().equals(GraphSONTokens.PREDICATE)) {
+                    jsonParser.nextToken();
+                    predicate = jsonParser.getText();
+                } else if (jsonParser.getCurrentName().equals(GraphSONTokens.VALUE)) {
+                    jsonParser.nextToken();
+                    value = deserializationContext.readValue(jsonParser, String.class);
+                }
+            }
+
+            try {
+                return (TP) TP.class.getMethod(predicate, String.class).invoke(null, value);
+            } catch (final Exception e) {
+                throw new IllegalStateException(e.getMessage(), e);
+            }
+        }
+
+        @Override
+        public boolean isCachable() {
+            return true;
+        }
+    }
+
     final static class LambdaJacksonDeserializer extends StdDeserializer<Lambda> {
 
         public LambdaJacksonDeserializer() {

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/519ca65c/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/TraversalSerializersV3d0.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/TraversalSerializersV3d0.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/TraversalSerializersV3d0.java
index eaa7b0f..ca01ec0 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/TraversalSerializersV3d0.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/TraversalSerializersV3d0.java
@@ -24,6 +24,7 @@ import org.apache.commons.configuration.MapConfiguration;
 import org.apache.tinkerpop.gremlin.process.remote.traversal.DefaultRemoteTraverser;
 import org.apache.tinkerpop.gremlin.process.traversal.Bytecode;
 import org.apache.tinkerpop.gremlin.process.traversal.P;
+import org.apache.tinkerpop.gremlin.process.traversal.TP;
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
@@ -370,6 +371,40 @@ final class TraversalSerializersV3d0 {
         }
     }
 
+    final static class TPJacksonDeserializer extends StdDeserializer<TP> {
+
+        public TPJacksonDeserializer() {
+            super(TP.class);
+        }
+
+        @Override
+        public TP deserialize(final JsonParser jsonParser, final DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
+            String predicate = null;
+            String value = null;
+
+            while (jsonParser.nextToken() != JsonToken.END_OBJECT) {
+                if (jsonParser.getCurrentName().equals(GraphSONTokens.PREDICATE)) {
+                    jsonParser.nextToken();
+                    predicate = jsonParser.getText();
+                } else if (jsonParser.getCurrentName().equals(GraphSONTokens.VALUE)) {
+                    jsonParser.nextToken();
+                    value = deserializationContext.readValue(jsonParser, String.class);
+                }
+            }
+
+            try {
+                return (TP) TP.class.getMethod(predicate, String.class).invoke(null, value);
+            } catch (final Exception e) {
+                throw new IllegalStateException(e.getMessage(), e);
+            }
+        }
+
+        @Override
+        public boolean isCachable() {
+            return true;
+        }
+    }
+
     final static class LambdaJacksonDeserializer extends StdDeserializer<Lambda> {
 
         public LambdaJacksonDeserializer() {

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/519ca65c/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoSerializersV1d0.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoSerializersV1d0.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoSerializersV1d0.java
index ca7c241..c7de4ec 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoSerializersV1d0.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoSerializersV1d0.java
@@ -22,6 +22,7 @@ import org.apache.tinkerpop.gremlin.process.remote.traversal.DefaultRemoteTraver
 import org.apache.tinkerpop.gremlin.process.traversal.Bytecode;
 import org.apache.tinkerpop.gremlin.process.traversal.P;
 import org.apache.tinkerpop.gremlin.process.traversal.Path;
+import org.apache.tinkerpop.gremlin.process.traversal.TP;
 import org.apache.tinkerpop.gremlin.process.traversal.TraversalSource;
 import org.apache.tinkerpop.gremlin.process.traversal.util.AndP;
 import org.apache.tinkerpop.gremlin.process.traversal.util.ConnectiveP;
@@ -228,6 +229,26 @@ public final class GryoSerializersV1d0 {
         }
     }
 
+    public final static class TPSerializer implements SerializerShim<TP> {
+        @Override
+        public <O extends OutputShim> void write(final KryoShim<?, O> kryo, final O output, final TP p) {
+            output.writeString(p.getBiPredicate().toString());
+            kryo.writeObject(output, p.getValue());
+        }
+
+        @Override
+        public <I extends InputShim> TP read(final KryoShim<I, ?> kryo, final I input, final Class<TP> clazz) {
+            final String predicate = input.readString();
+            final String value = kryo.readObject(input, String.class);
+
+            try {
+                return (TP) TP.class.getMethod(predicate, String.class).invoke(null, value);
+            } catch (final Exception e) {
+                throw new IllegalStateException(e.getMessage(), e);
+            }
+        }
+    }
+
     public final static class LambdaSerializer implements SerializerShim<Lambda> {
         @Override
         public <O extends OutputShim> void write(final KryoShim<?, O> kryo, final O output, final Lambda lambda) {

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/519ca65c/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoSerializersV3d0.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoSerializersV3d0.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoSerializersV3d0.java
index fee9345..ffda00e 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoSerializersV3d0.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoSerializersV3d0.java
@@ -22,6 +22,7 @@ import org.apache.tinkerpop.gremlin.process.remote.traversal.DefaultRemoteTraver
 import org.apache.tinkerpop.gremlin.process.traversal.Bytecode;
 import org.apache.tinkerpop.gremlin.process.traversal.P;
 import org.apache.tinkerpop.gremlin.process.traversal.Path;
+import org.apache.tinkerpop.gremlin.process.traversal.TP;
 import org.apache.tinkerpop.gremlin.process.traversal.TraversalSource;
 import org.apache.tinkerpop.gremlin.process.traversal.util.AndP;
 import org.apache.tinkerpop.gremlin.process.traversal.util.ConnectiveP;
@@ -344,6 +345,26 @@ public final class GryoSerializersV3d0 {
         }
     }
 
+    public final static class TPSerializer implements SerializerShim<TP> {
+        @Override
+        public <O extends OutputShim> void write(final KryoShim<?, O> kryo, final O output, final TP p) {
+            output.writeString(p.getBiPredicate().toString());
+            kryo.writeObject(output, p.getValue());
+        }
+
+        @Override
+        public <I extends InputShim> TP read(final KryoShim<I, ?> kryo, final I input, final Class<TP> clazz) {
+            final String predicate = input.readString();
+            final String value = kryo.readObject(input, String.class);
+
+            try {
+                return (TP) TP.class.getMethod(predicate, String.class).invoke(null, value);
+            } catch (final Exception e) {
+                throw new IllegalStateException(e.getMessage(), e);
+            }
+        }
+    }
+
     public final static class LambdaSerializer implements SerializerShim<Lambda> {
         @Override
         public <O extends OutputShim> void write(final KryoShim<?, O> kryo, final O output, final Lambda lambda) {

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/519ca65c/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoVersion.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoVersion.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoVersion.java
index 7af3766..fb62fee 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoVersion.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoVersion.java
@@ -33,6 +33,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.Path;
 import org.apache.tinkerpop.gremlin.process.traversal.Pop;
 import org.apache.tinkerpop.gremlin.process.traversal.SackFunctions;
 import org.apache.tinkerpop.gremlin.process.traversal.Scope;
+import org.apache.tinkerpop.gremlin.process.traversal.TP;
 import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalOptionParent;
 import org.apache.tinkerpop.gremlin.process.traversal.step.filter.RangeGlobalStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.FoldStep;
@@ -244,7 +245,7 @@ public enum GryoVersion {
             add(GryoTypeReg.of(Collections.singleton(null).getClass(), 54));
             add(GryoTypeReg.of(Collections.singletonList(null).getClass(), 24));
             add(GryoTypeReg.of(Collections.singletonMap(null, null).getClass(), 23));
-            add(GryoTypeReg.of(Types.COLLECTIONS_SYNCHRONIZED_MAP, 185, new UtilSerializers.SynchronizedMapSerializer()));  // ***LAST ID***
+            add(GryoTypeReg.of(Types.COLLECTIONS_SYNCHRONIZED_MAP, 185, new UtilSerializers.SynchronizedMapSerializer()));
             add(GryoTypeReg.of(Contains.class, 49));
             add(GryoTypeReg.of(Currency.class, 40));
             add(GryoTypeReg.of(Date.class, 38));
@@ -311,6 +312,7 @@ public enum GryoVersion {
 
             add(GryoTypeReg.of(Bytecode.class, 122, new GryoSerializersV3d0.BytecodeSerializer()));
             add(GryoTypeReg.of(P.class, 124, new GryoSerializersV3d0.PSerializer()));
+            add(GryoTypeReg.of(TP.class, 186, new GryoSerializersV3d0.TPSerializer())); // ***LAST ID***
             add(GryoTypeReg.of(Lambda.class, 125, new GryoSerializersV3d0.LambdaSerializer()));
             add(GryoTypeReg.of(Bytecode.Binding.class, 126, new GryoSerializersV3d0.BindingSerializer()));
             add(GryoTypeReg.of(Order.class, 127));
@@ -436,7 +438,7 @@ public enum GryoVersion {
             add(GryoTypeReg.of(Collections.singleton(null).getClass(), 54));
             add(GryoTypeReg.of(Collections.singletonList(null).getClass(), 24));
             add(GryoTypeReg.of(Collections.singletonMap(null, null).getClass(), 23));
-            add(GryoTypeReg.of(Types.COLLECTIONS_SYNCHRONIZED_MAP, 185, new UtilSerializers.SynchronizedMapSerializer()));  // ***LAST ID***
+            add(GryoTypeReg.of(Types.COLLECTIONS_SYNCHRONIZED_MAP, 185, new UtilSerializers.SynchronizedMapSerializer()));
             add(GryoTypeReg.of(Contains.class, 49));
             add(GryoTypeReg.of(Currency.class, 40));
             add(GryoTypeReg.of(Date.class, 38));
@@ -502,6 +504,7 @@ public enum GryoVersion {
 
             add(GryoTypeReg.of(Bytecode.class, 122, new GryoSerializersV1d0.BytecodeSerializer()));
             add(GryoTypeReg.of(P.class, 124, new GryoSerializersV1d0.PSerializer()));
+            add(GryoTypeReg.of(TP.class, 186, new GryoSerializersV1d0.TPSerializer())); // ***LAST ID***
             add(GryoTypeReg.of(Lambda.class, 125, new GryoSerializersV1d0.LambdaSerializer()));
             add(GryoTypeReg.of(Bytecode.Binding.class, 126, new GryoSerializersV1d0.BindingSerializer()));
             add(GryoTypeReg.of(Order.class, 127));

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/519ca65c/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/PTest.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/PTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/PTest.java
index 6ec33cc..1060b4e 100644
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/PTest.java
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/PTest.java
@@ -94,6 +94,21 @@ public class PTest {
                     {P.between("m", "n").or(P.eq("daniel")), "marko", true},
                     {P.between("m", "n").or(P.eq("daniel")), "daniel", true},
                     {P.between("m", "n").or(P.eq("daniel")), "stephen", false},
+                    // text predicates
+                    {TP.contains("ark"), "marko", true},
+                    {TP.contains("ark"), "josh", false},
+                    {TP.startsWith("jo"), "marko", false},
+                    {TP.startsWith("jo"), "josh", true},
+                    {TP.endsWith("ter"), "marko", false},
+                    {TP.endsWith("ter"), "peter", true},
+                    {TP.contains("o"), "marko", true},
+                    {TP.contains("o"), "josh", true},
+                    {TP.contains("o").and(P.gte("j")), "marko", true},
+                    {TP.contains("o").and(P.gte("j")), "josh", true},
+                    {TP.contains("o").and(P.gte("j")).and(TP.endsWith("ko")), "marko", true},
+                    {TP.contains("o").and(P.gte("j")).and(TP.endsWith("ko")), "josh", false},
+                    {TP.contains("o").and(P.gte("j").and(TP.endsWith("ko"))), "marko", true},
+                    {TP.contains("o").and(P.gte("j").and(TP.endsWith("ko"))), "josh", false},
             }));
         }
 

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/519ca65c/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONMapperPartialEmbeddedTypeTest.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONMapperPartialEmbeddedTypeTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONMapperPartialEmbeddedTypeTest.java
index 4e86ebd..52a7ee4 100644
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONMapperPartialEmbeddedTypeTest.java
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONMapperPartialEmbeddedTypeTest.java
@@ -21,6 +21,7 @@ package org.apache.tinkerpop.gremlin.structure.io.graphson;
 import org.apache.tinkerpop.gremlin.process.remote.traversal.DefaultRemoteTraverser;
 import org.apache.tinkerpop.gremlin.process.traversal.Bytecode;
 import org.apache.tinkerpop.gremlin.process.traversal.P;
+import org.apache.tinkerpop.gremlin.process.traversal.TP;
 import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
 import org.apache.tinkerpop.shaded.jackson.databind.JsonMappingException;
 import org.apache.tinkerpop.shaded.jackson.databind.ObjectMapper;
@@ -327,10 +328,19 @@ public class GraphSONMapperPartialEmbeddedTypeTest extends AbstractGraphSONTest
                 P.without(1,2,3,4),
                 P.without(Arrays.asList(1,2,3,4)),
                 P.eq(1).and(P.eq(2)),
-                P.eq(1).or(P.eq(2)));
+                P.eq(1).or(P.eq(2)),
+                TP.contains("ark"),
+                TP.startsWith("mar"),
+                TP.endsWith("ko"),
+                TP.endsWith("ko").and(P.gte("mar")),
+                P.gte("mar").and(TP.endsWith("ko")));
 
         for (P p : variantsOfP) {
-            assertEquals(p, serializeDeserialize(mapper, p, P.class));
+            if (p instanceof TP) {
+                assertEquals(p, serializeDeserialize(mapper, p, TP.class));
+            } else {
+                assertEquals(p, serializeDeserialize(mapper, p, P.class));
+            }
         }
     }
 

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/519ca65c/gremlin-dotnet/glv/TP.template
----------------------------------------------------------------------
diff --git a/gremlin-dotnet/glv/TP.template b/gremlin-dotnet/glv/TP.template
new file mode 100644
index 0000000..22320ea
--- /dev/null
+++ b/gremlin-dotnet/glv/TP.template
@@ -0,0 +1,71 @@
+#region License
+
+/*
+ * 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.
+ */
+
+#endregion
+
+// THIS IS A GENERATED FILE - DO NOT MODIFY THIS FILE DIRECTLY - see pom.xml
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+
+namespace Gremlin.Net.Process.Traversal
+{
+#pragma warning disable 1591
+
+    /// <summary>
+    ///     A <see cref="TP" /> is a predicate of the form Func&lt;string, bool&gt;.
+    ///     That is, given some string, return true or false.
+    /// </summary>
+    public class TP : P
+    {
+        /// <summary>
+        ///     Initializes a new instance of the <see cref="TP" /> class.
+        /// </summary>
+        /// <param name="operatorName">The name of the predicate.</param>
+        /// <param name="value">The value of the predicate.</param>
+        /// <param name="other">An optional other predicate that is used as an argument for this predicate.</param>
+        public TP(string operatorName, string value, P other = null) : base(operatorName, value, other)
+        {
+        }
+
+<% tpmethods.each { method -> %>
+        public static TP <%= toCSharpMethodName.call(method) %>(string value)
+        {
+            return new TP("<%= method %>", value);
+        }
+<% } %>
+
+        private static T[] ToGenericArray<T>(ICollection<T> collection)
+        {
+            return collection?.ToArray() ?? new T[0];
+        }
+
+        /// <inheritdoc />
+        public override string ToString()
+        {
+            return Other == null ? \$"{OperatorName}({Value})" : \$"{OperatorName}({Value},{Other})";
+        }
+    }
+
+#pragma warning restore 1591
+}

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/519ca65c/gremlin-dotnet/glv/generate.groovy
----------------------------------------------------------------------
diff --git a/gremlin-dotnet/glv/generate.groovy b/gremlin-dotnet/glv/generate.groovy
index 0c93f3d..3dbd959 100644
--- a/gremlin-dotnet/glv/generate.groovy
+++ b/gremlin-dotnet/glv/generate.groovy
@@ -26,6 +26,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.TraversalSource
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource
 import org.apache.tinkerpop.gremlin.process.traversal.P
+import org.apache.tinkerpop.gremlin.process.traversal.TP
 import org.apache.tinkerpop.gremlin.process.traversal.IO
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__
 import org.apache.tinkerpop.gremlin.structure.Direction
@@ -59,6 +60,7 @@ def toCSharpTypeMap = ["Long": "long",
                        "Traversal[]": "ITraversal[]",
                        "Predicate": "IPredicate",
                        "P": "P",
+                       "TP": "TP",
                        "TraversalStrategy": "ITraversalStrategy",
                        "TraversalStrategy[]": "ITraversalStrategy[]",
                        "Function": "IFunction",
@@ -241,6 +243,12 @@ def binding = ["pmethods": P.class.getMethods().
         collect { it.name }.
         unique().
         sort { a, b -> a <=> b },
+               "tpmethods": TP.class.getMethods().
+                       findAll { Modifier.isStatic(it.getModifiers()) }.
+                       findAll { TP.class.isAssignableFrom(it.returnType) }.
+                       collect { it.name }.
+                       unique().
+                       sort { a, b -> a <=> b },
                "sourceStepMethods": GraphTraversalSource.getMethods(). // SOURCE STEPS
                         findAll { GraphTraversalSource.class.equals(it.returnType) }.
                         findAll {
@@ -334,6 +342,10 @@ def pTemplate = engine.createTemplate(new File("${projectBaseDir}/glv/P.template
 def pFile = new File("${projectBaseDir}/src/Gremlin.Net/Process/Traversal/P.cs")
 pFile.newWriter().withWriter{ it << pTemplate }
 
+def tpTemplate = engine.createTemplate(new File("${projectBaseDir}/glv/TP.template")).make(binding)
+def tpFile = new File("${projectBaseDir}/src/Gremlin.Net/Process/Traversal/TP.cs")
+tpFile.newWriter().withWriter{ it << tpTemplate }
+
 binding.tokens.each {k,v ->
     def tokenTemplate = engine.createTemplate(new File("${projectBaseDir}/glv/Token.template")).make([tokenFields: v, tokenName: k])
     def tokenFile = new File("${projectBaseDir}/src/Gremlin.Net/Process/Traversal/${k}.cs")
@@ -382,4 +394,4 @@ def templateCsprojFile = new File("${projectBaseDir}/src/Gremlin.Net.Template/Gr
 templateCsprojFile.newWriter().withWriter{ it << templateCsprojTemplate }
 def nuspecTemplate = engine.createTemplate(new File("${projectBaseDir}/glv/Gremlin.Net.Template.nuspec.template")).make(["projectVersion":versionToUse])
 def nuspecFile = new File("${projectBaseDir}/src/Gremlin.Net.Template/Gremlin.Net.Template.nuspec")
-nuspecFile.newWriter().withWriter{ it << nuspecTemplate }
\ No newline at end of file
+nuspecFile.newWriter().withWriter{ it << nuspecTemplate }

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/519ca65c/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/TP.cs
----------------------------------------------------------------------
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/TP.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/TP.cs
new file mode 100644
index 0000000..ac6415d
--- /dev/null
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/TP.cs
@@ -0,0 +1,96 @@
+#region License
+
+/*
+ * 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.
+ */
+
+#endregion
+
+// THIS IS A GENERATED FILE - DO NOT MODIFY THIS FILE DIRECTLY - see pom.xml
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+
+namespace Gremlin.Net.Process.Traversal
+{
+#pragma warning disable 1591
+
+    /// <summary>
+    ///     A <see cref="TP" /> is a predicate of the form Func&lt;string, bool&gt;.
+    ///     That is, given some string, return true or false.
+    /// </summary>
+    public class TP : P
+    {
+        /// <summary>
+        ///     Initializes a new instance of the <see cref="P" /> class.
+        /// </summary>
+        /// <param name="operatorName">The name of the predicate.</param>
+        /// <param name="value">The value of the predicate.</param>
+        /// <param name="other">An optional other predicate that is used as an argument for this predicate.</param>
+        public TP(string operatorName, string value, P other = null) : base(operatorName, value, other)
+        {
+        }
+
+
+        public static TP Absent(string value)
+        {
+            return new TP("absent", value);
+        }
+
+        public static TP Contains(string value)
+        {
+            return new TP("contains", value);
+        }
+
+        public static TP EndsNotWith(string value)
+        {
+            return new TP("endsNotWith", value);
+        }
+
+        public static TP EndsWith(string value)
+        {
+            return new TP("endsWith", value);
+        }
+
+        public static TP StartsNotWith(string value)
+        {
+            return new TP("startsNotWith", value);
+        }
+
+        public static TP StartsWith(string value)
+        {
+            return new TP("startsWith", value);
+        }
+
+
+        private static T[] ToGenericArray<T>(ICollection<T> collection)
+        {
+            return collection?.ToArray() ?? new T[0];
+        }
+
+        /// <inheritdoc />
+        public override string ToString()
+        {
+            return Other == null ? $"{OperatorName}({Value})" : $"{OperatorName}({Value},{Other})";
+        }
+    }
+
+#pragma warning restore 1591
+}

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/519ca65c/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/GraphSONWriter.cs
----------------------------------------------------------------------
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/GraphSONWriter.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/GraphSONWriter.cs
index 9349e57..3178d21 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/GraphSONWriter.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/GraphSONWriter.cs
@@ -58,6 +58,7 @@ namespace Gremlin.Net.Structure.IO.GraphSON
                 {typeof(Type), new ClassSerializer()},
                 {typeof(EnumWrapper), new EnumSerializer()},
                 {typeof(P), new PSerializer()},
+                {typeof(TP), new TPSerializer()},
                 {typeof(Vertex), new VertexSerializer()},
                 {typeof(Edge), new EdgeSerializer()},
                 {typeof(Property), new PropertySerializer()},
@@ -163,4 +164,4 @@ namespace Gremlin.Net.Structure.IO.GraphSON
                 yield return ToDict(e);
         }
     }
-}
\ No newline at end of file
+}

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/519ca65c/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/TPSerializer.cs
----------------------------------------------------------------------
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/TPSerializer.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/TPSerializer.cs
new file mode 100644
index 0000000..22ed358
--- /dev/null
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/TPSerializer.cs
@@ -0,0 +1,45 @@
+#region License
+
+/*
+ * 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.
+ */
+
+#endregion
+
+using System.Collections.Generic;
+using Gremlin.Net.Process.Traversal;
+
+namespace Gremlin.Net.Structure.IO.GraphSON
+{
+    internal class TPSerializer : IGraphSONSerializer
+    {
+        public Dictionary<string, dynamic> Dictify(dynamic predicate, GraphSONWriter writer)
+        {
+            TP p = predicate;
+            var value = p.Other == null
+                ? writer.ToDict(p.Value)
+                : new List<dynamic> {writer.ToDict(p.Value), writer.ToDict(p.Other)};
+            var dict = new Dictionary<string, dynamic>
+            {
+                {"predicate", p.OperatorName},
+                {"value", value}
+            };
+            return GraphSONUtil.ToTypedValue("TP", dict);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/519ca65c/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GroovyTranslator.java
----------------------------------------------------------------------
diff --git a/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GroovyTranslator.java b/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GroovyTranslator.java
index 717e1bc..a3e593a 100644
--- a/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GroovyTranslator.java
+++ b/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GroovyTranslator.java
@@ -24,6 +24,7 @@ import org.apache.commons.configuration.ConfigurationConverter;
 import org.apache.tinkerpop.gremlin.process.traversal.Bytecode;
 import org.apache.tinkerpop.gremlin.process.traversal.P;
 import org.apache.tinkerpop.gremlin.process.traversal.SackFunctions;
+import org.apache.tinkerpop.gremlin.process.traversal.TP;
 import org.apache.tinkerpop.gremlin.process.traversal.Translator;
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategy;
@@ -225,6 +226,7 @@ public final class GroovyTranslator implements Translator.ScriptTranslator {
     }
 
     private StringBuilder convertPToString(final P p, final StringBuilder current) {
+        if (p instanceof TP) return convertTPToString((TP) p, current);
         if (p instanceof ConnectiveP) {
             final List<P<?>> list = ((ConnectiveP) p).getPredicates();
             for (int i = 0; i < list.size(); i++) {
@@ -237,4 +239,9 @@ public final class GroovyTranslator implements Translator.ScriptTranslator {
             current.append("P.").append(p.getBiPredicate().toString()).append("(").append(convertToString(p.getValue())).append(")");
         return current;
     }
+
+    private StringBuilder convertTPToString(final TP p, final StringBuilder current) {
+        current.append("TP.").append(p.getBiPredicate().toString()).append("(").append(convertToString(p.getValue())).append(")");
+        return current;
+    }
 }

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/519ca65c/gremlin-javascript/glv/TraversalSource.template
----------------------------------------------------------------------
diff --git a/gremlin-javascript/glv/TraversalSource.template b/gremlin-javascript/glv/TraversalSource.template
index ffe0fbc..14df95b 100644
--- a/gremlin-javascript/glv/TraversalSource.template
+++ b/gremlin-javascript/glv/TraversalSource.template
@@ -162,6 +162,48 @@ function createP(operator, args) {
   return new (Function.prototype.bind.apply(P, args));
 }
 
+class TP {
+  /**
+   * Represents an operation.
+   * @constructor
+   */
+  constructor(operator, value, other) {
+    this.operator = operator;
+    this.value = value;
+    this.other = other;
+  }
+
+  /**
+   * Returns the string representation of the instance.
+   * @returns {string}
+   */
+  toString() {
+    if (this.other === undefined) {
+      return this.operator + '(' + this.value + ')';
+    }
+    return this.operator + '(' + this.value + ', ' + this.other + ')';
+  }
+
+  and(arg) {
+    return new P('and', this, arg);
+  }
+
+  or(arg) {
+    return new P('or', this, arg);
+  }
+<% tpmethods.each{ method -> %>
+  /** @param {...Object} args */
+  static <%= toJs.call(method) %>(...args) {
+    return createTP('<%= method %>', args);
+  }
+<% } %>
+}
+
+function createTP(operator, args) {
+  args.unshift(null, operator);
+  return new (Function.prototype.bind.apply(TP, args));
+}
+
 class Traverser {
   constructor(object, bulk) {
     this.object = object;
@@ -199,6 +241,7 @@ class EnumValue {
 module.exports = {
   EnumValue,
   P,
+  TP,
   IO,
   Traversal,
   TraversalSideEffects,
@@ -208,4 +251,4 @@ enums.each{ enumClass ->
         enumClass.getEnumConstants().sort { a, b -> a.name() <=> b.name() }.collect { toJs.call(it.name()) }.join(' ') + "')"
 }
 %>
-};
\ No newline at end of file
+};

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/519ca65c/gremlin-javascript/glv/generate.groovy
----------------------------------------------------------------------
diff --git a/gremlin-javascript/glv/generate.groovy b/gremlin-javascript/glv/generate.groovy
index aab55d4..243c607 100644
--- a/gremlin-javascript/glv/generate.groovy
+++ b/gremlin-javascript/glv/generate.groovy
@@ -28,6 +28,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.TraversalSource
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource
 import org.apache.tinkerpop.gremlin.process.traversal.P
+import org.apache.tinkerpop.gremlin.process.traversal.TP
 import org.apache.tinkerpop.gremlin.process.traversal.IO
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__
 import java.lang.reflect.Modifier
@@ -69,6 +70,12 @@ def binding = ["enums": CoreImports.getClassImports()
                        collect { it.name }.
                        unique().
                        sort { a, b -> a <=> b },
+               "tpmethods": TP.class.getMethods().
+                       findAll { Modifier.isStatic(it.getModifiers()) }.
+                       findAll { TP.class.isAssignableFrom(it.returnType) }.
+                       collect { it.name }.
+                       unique().
+                       sort { a, b -> a <=> b },
                "sourceStepMethods": GraphTraversalSource.getMethods(). // SOURCE STEPS
                        findAll { GraphTraversalSource.class.equals(it.returnType) }.
                        findAll {

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/519ca65c/gremlin-javascript/src/main/javascript/gremlin-javascript/index.js
----------------------------------------------------------------------
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/index.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/index.js
index c2e810d..b15ecbc 100644
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/index.js
+++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/index.js
@@ -49,6 +49,7 @@ module.exports = {
     Bytecode: Bytecode,
     EnumValue: t.EnumValue,
     P: t.P,
+    TP: t.TP,
     Traversal: t.Traversal,
     TraversalSideEffects: t.TraversalSideEffects,
     TraversalStrategies: strategiesModule.TraversalStrategies,

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/519ca65c/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/process/traversal.js
----------------------------------------------------------------------
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/process/traversal.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/process/traversal.js
index 2b9ba26..ca9d062 100644
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/process/traversal.js
+++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/process/traversal.js
@@ -310,6 +310,73 @@ function createP(operator, args) {
   return new (Function.prototype.bind.apply(P, args));
 }
 
+class TP {
+  /**
+   * Represents an operation.
+   * @constructor
+   */
+  constructor(operator, value, other) {
+    this.operator = operator;
+    this.value = value;
+    this.other = other;
+  }
+
+  /**
+   * Returns the string representation of the instance.
+   * @returns {string}
+   */
+  toString() {
+    if (this.other === undefined) {
+      return this.operator + '(' + this.value + ')';
+    }
+    return this.operator + '(' + this.value + ', ' + this.other + ')';
+  }
+
+  and(arg) {
+    return new P('and', this, arg);
+  }
+
+  or(arg) {
+    return new P('or', this, arg);
+  }
+
+  /** @param {...Object} args */
+  static absent(...args) {
+    return createTP('absent', args);
+  }
+
+  /** @param {...Object} args */
+  static contains(...args) {
+    return createTP('contains', args);
+  }
+
+  /** @param {...Object} args */
+  static endsNotWith(...args) {
+    return createTP('endsNotWith', args);
+  }
+
+  /** @param {...Object} args */
+  static endsWith(...args) {
+    return createTP('endsWith', args);
+  }
+
+  /** @param {...Object} args */
+  static startsNotWith(...args) {
+    return createTP('startsNotWith', args);
+  }
+
+  /** @param {...Object} args */
+  static startsWith(...args) {
+    return createTP('startsWith', args);
+  }
+
+}
+
+function createTP(operator, args) {
+  args.unshift(null, operator);
+  return new (Function.prototype.bind.apply(TP, args));
+}
+
 class Traverser {
   constructor(object, bulk) {
     this.object = object;
@@ -347,6 +414,7 @@ class EnumValue {
 module.exports = {
   EnumValue,
   P,
+  TP,
   IO,
   Traversal,
   TraversalSideEffects,
@@ -363,4 +431,4 @@ module.exports = {
   pop: toEnum('Pop', 'all first last mixed'),
   scope: toEnum('Scope', 'global local'),
   t: toEnum('T', 'id key label value')
-};
\ No newline at end of file
+};

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/519ca65c/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/type-serializers.js
----------------------------------------------------------------------
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/type-serializers.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/type-serializers.js
index 0e17cc8..ca81c2a 100644
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/type-serializers.js
+++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/type-serializers.js
@@ -150,6 +150,28 @@ class PSerializer extends TypeSerializer {
   }
 }
 
+class TPSerializer extends TypeSerializer {
+  /** @param {TP} item */
+  serialize(item) {
+    const result = {};
+    result[typeKey] = 'g:TP';
+    const resultValue = result[valueKey] = {
+      'predicate': item.operator
+    };
+    if (item.other === undefined || item.other === null) {
+      resultValue['value'] = this.writer.adaptObject(item.value);
+    }
+    else {
+      resultValue['value'] = [ this.writer.adaptObject(item.value), this.writer.adaptObject(item.other) ];
+    }
+    return result;
+  }
+
+  canBeUsedFor(value) {
+    return (value instanceof t.TP);
+  }
+}
+
 class LambdaSerializer extends TypeSerializer {
   /** @param {Function} item */
   serialize(item) {
@@ -391,4 +413,4 @@ module.exports = {
   valueKey,
   VertexPropertySerializer,
   VertexSerializer
-};
\ No newline at end of file
+};

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/519ca65c/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/feature-steps.js
----------------------------------------------------------------------
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 a0ddddb..abef2a2 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
@@ -218,6 +218,7 @@ function getSandbox(g, parameters) {
     },
     Order: traversalModule.order,
     P: traversalModule.P,
+    TP: traversalModule.TP,
     IO: traversalModule.IO,
     Pick: traversalModule.pick,
     Pop: traversalModule.pop,

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/519ca65c/gremlin-python/glv/TraversalSource.template
----------------------------------------------------------------------
diff --git a/gremlin-python/glv/TraversalSource.template b/gremlin-python/glv/TraversalSource.template
index 713681b..00a5934 100644
--- a/gremlin-python/glv/TraversalSource.template
+++ b/gremlin-python/glv/TraversalSource.template
@@ -152,6 +152,25 @@ def <%= method %>(*args):
 statics.add_static('<%= method %>',<%= method %>)
 <% } %>
 
+class TP(P):
+    def __init__(self, operator, value, other=None):
+        P.__init__(self, operator, value, other)
+<% tpmethods.each { method -> %>
+    @staticmethod
+    def <%= method %>(*args):
+        return TP("<%= toJava.call(method) %>", *args)
+<% } %>
+    def __eq__(self, other):
+        return isinstance(other, self.__class__) and self.operator == other.operator and self.value == other.value and self.other == other.other
+
+    def __repr__(self):
+        return self.operator + "(" + str(self.value) + ")" if self.other is None else self.operator + "(" + str(self.value) + "," + str(self.other) + ")"
+<% tpmethods.findAll{!it.equals("clone")}.each { method -> %>
+def <%= method %>(*args):
+    return TP.<%= method %>(*args)
+statics.add_static('<%= method %>',<%= method %>)
+<% } %>
+
 <% tokens.each { k,v -> %>
 '''
 <%= k %>
@@ -324,4 +343,4 @@ class Binding(object):
         return hash(self.key) + hash(self.value)
 
     def __repr__(self):
-        return "binding[" + self.key + "=" + str(self.value) + "]"
\ No newline at end of file
+        return "binding[" + self.key + "=" + str(self.value) + "]"

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/519ca65c/gremlin-python/glv/generate.groovy
----------------------------------------------------------------------
diff --git a/gremlin-python/glv/generate.groovy b/gremlin-python/glv/generate.groovy
index c7ad241..8c3d647 100644
--- a/gremlin-python/glv/generate.groovy
+++ b/gremlin-python/glv/generate.groovy
@@ -26,6 +26,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.TraversalSource
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource
 import org.apache.tinkerpop.gremlin.process.traversal.P
+import org.apache.tinkerpop.gremlin.process.traversal.TP
 import org.apache.tinkerpop.gremlin.process.traversal.IO
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__
 import java.lang.reflect.Modifier
@@ -63,6 +64,12 @@ def binding = ["enums": CoreImports.getClassImports()
                        collect { toPython(it.name) }.
                        unique().
                        sort { a, b -> a <=> b },
+               "tpmethods": TP.class.getMethods().
+                       findAll { Modifier.isStatic(it.getModifiers()) }.
+                       findAll { TP.class.isAssignableFrom(it.returnType) }.
+                       collect { toPython(it.name) }.
+                       unique().
+                       sort { a, b -> a <=> b },
                "sourceStepMethods": GraphTraversalSource.getMethods(). // SOURCE STEPS
                        findAll { GraphTraversalSource.class.equals(it.returnType) }.
                        findAll {
@@ -102,4 +109,4 @@ traversalFile.newWriter().withWriter{ it << traversalTemplate }
 
 def graphTraversalTemplate = engine.createTemplate(new File("${projectBaseDir}/glv/GraphTraversalSource.template")).make(binding)
 def graphTraversalFile = new File("${projectBaseDir}/src/main/jython/gremlin_python/process/graph_traversal.py")
-graphTraversalFile.newWriter().withWriter{ it << graphTraversalTemplate }
\ No newline at end of file
+graphTraversalFile.newWriter().withWriter{ it << graphTraversalTemplate }

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/519ca65c/gremlin-python/src/main/java/org/apache/tinkerpop/gremlin/python/jsr223/PythonTranslator.java
----------------------------------------------------------------------
diff --git a/gremlin-python/src/main/java/org/apache/tinkerpop/gremlin/python/jsr223/PythonTranslator.java b/gremlin-python/src/main/java/org/apache/tinkerpop/gremlin/python/jsr223/PythonTranslator.java
index 0bc324e..0d2695a 100644
--- a/gremlin-python/src/main/java/org/apache/tinkerpop/gremlin/python/jsr223/PythonTranslator.java
+++ b/gremlin-python/src/main/java/org/apache/tinkerpop/gremlin/python/jsr223/PythonTranslator.java
@@ -24,6 +24,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.Bytecode;
 import org.apache.tinkerpop.gremlin.process.traversal.Operator;
 import org.apache.tinkerpop.gremlin.process.traversal.P;
 import org.apache.tinkerpop.gremlin.process.traversal.SackFunctions;
+import org.apache.tinkerpop.gremlin.process.traversal.TP;
 import org.apache.tinkerpop.gremlin.process.traversal.Translator;
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.TraversalSource;
@@ -224,6 +225,7 @@ public class PythonTranslator implements Translator.ScriptTranslator {
     }
 
     private StringBuilder convertPToString(final P p, final StringBuilder current) {
+        if (p instanceof TP) return convertTPToString((TP) p, current);
         if (p instanceof ConnectiveP) {
             final List<P<?>> list = ((ConnectiveP) p).getPredicates();
             for (int i = 0; i < list.size(); i++) {
@@ -237,6 +239,11 @@ public class PythonTranslator implements Translator.ScriptTranslator {
         return current;
     }
 
+    private StringBuilder convertTPToString(final TP p, final StringBuilder current) {
+        current.append(convertStatic("TP.")).append(p.getBiPredicate().toString()).append("(").append(convertToString(p.getValue())).append(")");
+        return current;
+    }
+
     protected String convertLambdaToString(final Lambda lambda) {
         final String lambdaString = lambda.getLambdaScript().trim();
         return lambdaString.startsWith("lambda") ? lambdaString : "lambda " + lambdaString;

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/519ca65c/gremlin-python/src/main/jython/gremlin_python/process/traversal.py
----------------------------------------------------------------------
diff --git a/gremlin-python/src/main/jython/gremlin_python/process/traversal.py b/gremlin-python/src/main/jython/gremlin_python/process/traversal.py
index 094bd6d..a4d9708 100644
--- a/gremlin-python/src/main/jython/gremlin_python/process/traversal.py
+++ b/gremlin-python/src/main/jython/gremlin_python/process/traversal.py
@@ -322,6 +322,65 @@ def without(*args):
 statics.add_static('without',without)
 
 
+class TP(P):
+    def __init__(self, operator, value, other=None):
+        P.__init__(self, operator, value, other)
+
+    @staticmethod
+    def absent(*args):
+        return TP("absent", *args)
+
+    @staticmethod
+    def contains(*args):
+        return TP("contains", *args)
+
+    @staticmethod
+    def endsNotWith(*args):
+        return TP("endsNotWith", *args)
+
+    @staticmethod
+    def endsWith(*args):
+        return TP("endsWith", *args)
+
+    @staticmethod
+    def startsNotWith(*args):
+        return TP("startsNotWith", *args)
+
+    @staticmethod
+    def startsWith(*args):
+        return TP("startsWith", *args)
+
+    def __eq__(self, other):
+        return isinstance(other, self.__class__) and self.operator == other.operator and self.value == other.value and self.other == other.other
+
+    def __repr__(self):
+        return self.operator + "(" + str(self.value) + ")" if self.other is None else self.operator + "(" + str(self.value) + "," + str(self.other) + ")"
+
+def absent(*args):
+    return TP.absent(*args)
+statics.add_static('absent',absent)
+
+def contains(*args):
+    return TP.contains(*args)
+statics.add_static('contains',contains)
+
+def endsNotWith(*args):
+    return TP.endsNotWith(*args)
+statics.add_static('endsNotWith',endsNotWith)
+
+def endsWith(*args):
+    return TP.endsWith(*args)
+statics.add_static('endsWith',endsWith)
+
+def startsNotWith(*args):
+    return TP.startsNotWith(*args)
+statics.add_static('startsNotWith',startsNotWith)
+
+def startsWith(*args):
+    return TP.startsWith(*args)
+statics.add_static('startsWith',startsWith)
+
+
 
 '''
 IO
@@ -556,4 +615,4 @@ class Binding(object):
         return hash(self.key) + hash(self.value)
 
     def __repr__(self):
-        return "binding[" + self.key + "=" + str(self.value) + "]"
\ No newline at end of file
+        return "binding[" + self.key + "=" + str(self.value) + "]"

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/519ca65c/gremlin-python/src/main/jython/gremlin_python/structure/io/graphsonV2d0.py
----------------------------------------------------------------------
diff --git a/gremlin-python/src/main/jython/gremlin_python/structure/io/graphsonV2d0.py b/gremlin-python/src/main/jython/gremlin_python/structure/io/graphsonV2d0.py
index d53a080..2cb0b5b 100644
--- a/gremlin-python/src/main/jython/gremlin_python/structure/io/graphsonV2d0.py
+++ b/gremlin-python/src/main/jython/gremlin_python/structure/io/graphsonV2d0.py
@@ -27,7 +27,7 @@ from aenum import Enum
 
 from gremlin_python import statics
 from gremlin_python.statics import FloatType, FunctionType, IntType, LongType, TypeType
-from gremlin_python.process.traversal import Binding, Bytecode, P, Traversal, Traverser, TraversalStrategy
+from gremlin_python.process.traversal import Binding, Bytecode, P, TP, Traversal, Traverser, TraversalStrategy
 from gremlin_python.structure.graph import Edge, Property, Vertex, VertexProperty, Path
 
 # When we fall back to a superclass's serializer, we iterate over this map.
@@ -278,6 +278,17 @@ class PSerializer(_GraphSONTypeIO):
         return GraphSONUtil.typedValue("P", out)
 
 
+class TPSerializer(_GraphSONTypeIO):
+    python_type = TP
+
+    @classmethod
+    def dictify(cls, p, writer):
+        out = {"predicate": p.operator,
+               "value": [writer.toDict(p.value), writer.toDict(p.other)] if p.other is not None else
+               writer.toDict(p.value)}
+        return GraphSONUtil.typedValue("TP", out)
+
+
 class BindingSerializer(_GraphSONTypeIO):
     python_type = Binding
 

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/519ca65c/gremlin-python/src/main/jython/gremlin_python/structure/io/graphsonV3d0.py
----------------------------------------------------------------------
diff --git a/gremlin-python/src/main/jython/gremlin_python/structure/io/graphsonV3d0.py b/gremlin-python/src/main/jython/gremlin_python/structure/io/graphsonV3d0.py
index 5539448..266e23d 100644
--- a/gremlin-python/src/main/jython/gremlin_python/structure/io/graphsonV3d0.py
+++ b/gremlin-python/src/main/jython/gremlin_python/structure/io/graphsonV3d0.py
@@ -27,7 +27,7 @@ from aenum import Enum
 
 from gremlin_python import statics
 from gremlin_python.statics import FloatType, FunctionType, IntType, LongType, TypeType, DictType, ListType, SetType
-from gremlin_python.process.traversal import Binding, Bytecode, P, Traversal, Traverser, TraversalStrategy, T
+from gremlin_python.process.traversal import Binding, Bytecode, P, TP, Traversal, Traverser, TraversalStrategy, T
 from gremlin_python.structure.graph import Edge, Property, Vertex, VertexProperty, Path
 
 # When we fall back to a superclass's serializer, we iterate over this map.
@@ -284,6 +284,17 @@ class PSerializer(_GraphSONTypeIO):
         return GraphSONUtil.typedValue("P", out)
 
 
+class TPSerializer(_GraphSONTypeIO):
+    python_type = TP
+
+    @classmethod
+    def dictify(cls, p, writer):
+        out = {"predicate": p.operator,
+               "value": [writer.toDict(p.value), writer.toDict(p.other)] if p.other is not None else
+               writer.toDict(p.value)}
+        return GraphSONUtil.typedValue("TP", out)
+
+
 class BindingSerializer(_GraphSONTypeIO):
     python_type = Binding
 

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/519ca65c/gremlin-python/src/main/jython/radish/feature_steps.py
----------------------------------------------------------------------
diff --git a/gremlin-python/src/main/jython/radish/feature_steps.py b/gremlin-python/src/main/jython/radish/feature_steps.py
index aff73dc..151d6d5 100644
--- a/gremlin-python/src/main/jython/radish/feature_steps.py
+++ b/gremlin-python/src/main/jython/radish/feature_steps.py
@@ -21,7 +21,7 @@ import json
 import re
 from gremlin_python.structure.graph import Graph, Path
 from gremlin_python.process.graph_traversal import __
-from gremlin_python.process.traversal import Barrier, Cardinality, P, Pop, Scope, Column, Order, Direction, T, Pick, Operator, IO
+from gremlin_python.process.traversal import Barrier, Cardinality, P, TP, Pop, Scope, Column, Order, Direction, T, Pick, Operator, IO
 from radish import given, when, then
 from hamcrest import *
 
@@ -256,6 +256,7 @@ def _make_traversal(g, traversal_string, params):
          "Direction": Direction,
          "Order": Order,
          "P": P,
+         "TP": TP,
          "IO": IO,
          "Pick": Pick,
          "Pop": Pop,

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/519ca65c/gremlin-test/features/filter/Has.feature
----------------------------------------------------------------------
diff --git a/gremlin-test/features/filter/Has.feature b/gremlin-test/features/filter/Has.feature
index ddf9984..9d2bf4f 100644
--- a/gremlin-test/features/filter/Has.feature
+++ b/gremlin-test/features/filter/Has.feature
@@ -557,4 +557,59 @@ Feature: Step - has()
     When iterated to list
     Then the result should be unordered
       | result |
-      | d[6].l |
\ No newline at end of file
+      | d[6].l |
+
+  Scenario: g_V_hasXname_containsXarkXX
+    Given the modern graph
+    And the traversal of
+      """
+      g.V().has("name", TP.contains("ark"))
+      """
+    When iterated to list
+    Then the result should be unordered
+      | result |
+      | v[marko] |
+
+  Scenario: g_V_hasXname_startsWithXmarXX
+    Given the modern graph
+    And the traversal of
+      """
+      g.V().has("name", TP.startsWith("mar"))
+      """
+    When iterated to list
+    Then the result should be unordered
+      | result |
+      | v[marko] |
+
+  Scenario: g_V_hasXname_endsWithXasXX
+    Given the modern graph
+    And the traversal of
+      """
+      g.V().has("name", TP.endsWith("as"))
+      """
+    When iterated to list
+    Then the result should be unordered
+      | result |
+      | v[vadas] |
+
+  Scenario: g_V_hasXperson_name_containsXoX_andXltXmXXX
+    Given the modern graph
+    And the traversal of
+      """
+      g.V().has("person", "name", TP.contains("o").and(P.lt("m")))
+      """
+    When iterated to list
+    Then the result should be unordered
+      | result |
+      | v[josh] |
+
+  Scenario: g_V_hasXname_gtXmX_andXcontainsXoXXX
+    Given the modern graph
+    And the traversal of
+      """
+      g.V().has("name", P.gt("m").and(TP.contains("o")))
+      """
+    When iterated to list
+    Then the result should be unordered
+      | result |
+      | v[marko] |

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/519ca65c/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/HasTest.java
----------------------------------------------------------------------
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/HasTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/HasTest.java
index 3bdb24a..cb4abab 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/HasTest.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/HasTest.java
@@ -23,6 +23,7 @@ import org.apache.tinkerpop.gremlin.LoadGraphWith;
 import org.apache.tinkerpop.gremlin.process.AbstractGremlinProcessTest;
 import org.apache.tinkerpop.gremlin.process.GremlinProcessRunner;
 import org.apache.tinkerpop.gremlin.process.traversal.P;
+import org.apache.tinkerpop.gremlin.process.traversal.TP;
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
 import org.apache.tinkerpop.gremlin.structure.Edge;
@@ -125,6 +126,16 @@ public abstract class HasTest extends AbstractGremlinProcessTest {
 
     public abstract Traversal<Vertex, Long> get_g_V_hasXage_withoutX27_29X_count();
 
+    public abstract Traversal<Vertex, Vertex> get_g_V_hasXname_containsXarkXX();
+
+    public abstract Traversal<Vertex,Vertex> get_g_V_hasXname_startsWithXmarXX();
+
+    public abstract Traversal<Vertex,Vertex> get_g_V_hasXname_endsWithXasXX();
+
+    public abstract Traversal<Vertex,Vertex> get_g_V_hasXperson_name_containsXoX_andXltXmXXX();
+
+    public abstract Traversal<Vertex,Vertex> get_g_V_hasXname_gtXmX_andXcontainsXoXXX();
+
     @Test
     @LoadGraphWith(MODERN)
     public void g_V_outXcreatedX_hasXname__mapXlengthX_isXgtX3XXX_name() {
@@ -547,6 +558,56 @@ public abstract class HasTest extends AbstractGremlinProcessTest {
         assertEquals(2L, traversal.next().longValue());
     }
 
+    @Test
+    @LoadGraphWith(MODERN)
+    public void g_V_hasXname_containsXarkXX() {
+        final Traversal<Vertex, Vertex> traversal = get_g_V_hasXname_containsXarkXX();
+        printTraversalForm(traversal);
+        assertTrue(traversal.hasNext());
+        assertTrue(traversal.next().value("name").equals("marko"));
+        assertFalse(traversal.hasNext());
+    }
+
+    @Test
+    @LoadGraphWith(MODERN)
+    public void g_V_hasXname_startsWithXmarXX() {
+        final Traversal<Vertex, Vertex> traversal = get_g_V_hasXname_startsWithXmarXX();
+        printTraversalForm(traversal);
+        assertTrue(traversal.hasNext());
+        assertTrue(traversal.next().value("name").equals("marko"));
+        assertFalse(traversal.hasNext());
+    }
+
+    @Test
+    @LoadGraphWith(MODERN)
+    public void g_V_hasXname_endsWithXasXX() {
+        final Traversal<Vertex, Vertex> traversal = get_g_V_hasXname_endsWithXasXX();
+        printTraversalForm(traversal);
+        assertTrue(traversal.hasNext());
+        assertTrue(traversal.next().value("name").equals("vadas"));
+        assertFalse(traversal.hasNext());
+    }
+
+    @Test
+    @LoadGraphWith(MODERN)
+    public void g_V_hasXperson_name_containsXoX_andXltXmXXX() {
+        final Traversal<Vertex, Vertex> traversal = get_g_V_hasXperson_name_containsXoX_andXltXmXXX();
+        printTraversalForm(traversal);
+        assertTrue(traversal.hasNext());
+        assertTrue(traversal.next().value("name").equals("josh"));
+        assertFalse(traversal.hasNext());
+    }
+
+    @Test
+    @LoadGraphWith(MODERN)
+    public void g_V_hasXname_gtXmX_andXcontainsXoXXX() {
+        final Traversal<Vertex, Vertex> traversal = get_g_V_hasXname_gtXmX_andXcontainsXoXXX();
+        printTraversalForm(traversal);
+        assertTrue(traversal.hasNext());
+        assertTrue(traversal.next().value("name").equals("marko"));
+        assertFalse(traversal.hasNext());
+    }
+
     public static class Traversals extends HasTest {
         @Override
         public Traversal<Edge, Edge> get_g_EX11X_outV_outE_hasXid_10X(final Object e11Id, final Object e10Id) {
@@ -727,5 +788,30 @@ public abstract class HasTest extends AbstractGremlinProcessTest {
         public Traversal<Vertex, Long> get_g_V_hasXage_withoutX27_29X_count() {
             return g.V().has("age", P.without(27, 29)).count();
         }
+
+        @Override
+        public Traversal<Vertex, Vertex> get_g_V_hasXname_containsXarkXX() {
+            return g.V().has("name", TP.contains("ark"));
+        }
+
+        @Override
+        public Traversal<Vertex, Vertex> get_g_V_hasXname_startsWithXmarXX() {
+            return g.V().has("name", TP.startsWith("mar"));
+        }
+
+        @Override
+        public Traversal<Vertex, Vertex> get_g_V_hasXname_endsWithXasXX() {
+            return g.V().has("name", TP.endsWith("as"));
+        }
+
+        @Override
+        public Traversal<Vertex, Vertex> get_g_V_hasXperson_name_containsXoX_andXltXmXXX() {
+            return g.V().has("person","name", TP.contains("o").and(P.lt("m")));
+        }
+
+        @Override
+        public Traversal<Vertex, Vertex> get_g_V_hasXname_gtXmX_andXcontainsXoXXX() {
+            return g.V().has("name", P.gt("m").and(TP.contains("o")));
+        }
     }
 }
\ No newline at end of file


[5/7] tinkerpop git commit: TINKERPOP-2041 Fixed gremlin-javascript serializers for TP

Posted by dk...@apache.org.
TINKERPOP-2041 Fixed gremlin-javascript serializers for TP


Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/68c47afa
Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/68c47afa
Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/68c47afa

Branch: refs/heads/master
Commit: 68c47afa017deb9deabba1cf025ecddd68cd42fa
Parents: 519ca65
Author: Stephen Mallette <sp...@genoprime.com>
Authored: Thu Sep 27 16:33:26 2018 -0400
Committer: Daniel Kuppitz <da...@hotmail.com>
Committed: Thu Oct 4 07:45:08 2018 -0700

----------------------------------------------------------------------
 .../gremlin-javascript/lib/structure/io/graph-serializer.js        | 2 ++
 .../gremlin-javascript/lib/structure/io/type-serializers.js        | 1 +
 2 files changed, 3 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/68c47afa/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/graph-serializer.js
----------------------------------------------------------------------
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/graph-serializer.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/graph-serializer.js
index 9ce1761..fca8375 100644
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/graph-serializer.js
+++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/graph-serializer.js
@@ -162,6 +162,7 @@ const deserializers = {
   'g:Property': typeSerializers.PropertySerializer,
   'g:Path': typeSerializers.Path3Serializer,
   'g:T': typeSerializers.TSerializer,
+  'g:TP': typeSerializers.TPSerializer,
   'g:List': typeSerializers.ListSerializer,
   'g:Set': typeSerializers.SetSerializer,
   'g:Map': typeSerializers.MapSerializer
@@ -173,6 +174,7 @@ const serializers = [
   typeSerializers.BytecodeSerializer,
   typeSerializers.TraverserSerializer,
   typeSerializers.PSerializer,
+  typeSerializers.TPSerializer,
   typeSerializers.LambdaSerializer,
   typeSerializers.EnumSerializer,
   typeSerializers.VertexSerializer,

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/68c47afa/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/type-serializers.js
----------------------------------------------------------------------
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/type-serializers.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/type-serializers.js
index ca81c2a..576c721 100644
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/type-serializers.js
+++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/type-serializers.js
@@ -406,6 +406,7 @@ module.exports = {
   PathSerializer,
   PropertySerializer,
   PSerializer,
+  TPSerializer,
   SetSerializer,
   TSerializer,
   TraverserSerializer,