From d391ce8c55f10df7f8a92ec2d8b4a9b553d892b8 Mon Sep 17 00:00:00 2001 From: Norio Akagi Date: Tue, 25 Jun 2024 17:57:21 -0700 Subject: [PATCH] TrimGlobalStep handles unicode characters as Ltrim and Rtrim --- CHANGELOG.asciidoc | 1 + .../traversal/step/map/LTrimGlobalStep.java | 12 +++-------- .../traversal/step/map/LTrimLocalStep.java | 11 +--------- .../traversal/step/map/RTrimGlobalStep.java | 12 +++-------- .../traversal/step/map/RTrimLocalStep.java | 11 +--------- .../traversal/step/map/TrimGlobalStep.java | 6 +++--- .../traversal/step/map/TrimLocalStep.java | 2 +- .../traversal/step/util/StringLocalStep.java | 21 +++++++++++++++++++ .../Gherkin/Gremlin.cs | 9 +++++--- gremlin-go/driver/cucumber/gremlin.go | 9 +++++--- .../test/cucumber/gremlin.js | 9 +++++--- .../src/main/python/radish/gremlin.py | 9 +++++--- .../gremlin/test/features/map/LTrim.feature | 20 +++++++++++++++++- .../gremlin/test/features/map/RTrim.feature | 20 +++++++++++++++++- .../gremlin/test/features/map/Trim.feature | 20 +++++++++++++++++- 15 files changed, 115 insertions(+), 57 deletions(-) diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc index 50a30e99b13..1930bdfcadd 100644 --- a/CHANGELOG.asciidoc +++ b/CHANGELOG.asciidoc @@ -30,6 +30,7 @@ This release also includes changes from <>. * Deprecated public constructor for `SeedStrategy` in favor of builder pattern to be consistent with other strategies. * Allow specifying a customized Spark app name * CoinStep has a getter method for its probability field +* Fixed so that TrimGlobalStep and TrimLocalStep have the same character control handling as Ltrim and Rtrim [[release-3-7-2]] === TinkerPop 3.7.2 (April 8, 2024) diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/LTrimGlobalStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/LTrimGlobalStep.java index 84dbd5cbf36..8ce2104c97a 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/LTrimGlobalStep.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/LTrimGlobalStep.java @@ -25,6 +25,8 @@ import java.util.Collections; import java.util.Set; +import static org.apache.tinkerpop.gremlin.process.traversal.step.util.StringLocalStep.getTrimmedString; + /** * Reference implementation for lTrim() step, a mid-traversal step which returns a string with leading * whitespace removed. Null values are not processed and remain as null when returned. @@ -49,15 +51,7 @@ protected E map(final Traverser.Admin traverser) { } // we will pass null values to next step - if (null == item) - return null; - - int i = 0; - while (i < ((String) item).length() && Character.isWhitespace(((String) item).charAt(i))) { - i++; - } - - return (E) ((String) item).substring(i); + return (E) getTrimmedString((String) item, true, false); } @Override diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/LTrimLocalStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/LTrimLocalStep.java index 15920673926..db12f62b1cb 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/LTrimLocalStep.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/LTrimLocalStep.java @@ -51,18 +51,9 @@ public Set getRequirements() { @Override protected E applyStringOperation(String item) { - return (E) item.substring(getIdx(item)); + return (E) getTrimmedString(item, true, false); } @Override public String getStepName() { return "lTrim(local)"; } - - private int getIdx(final String str) { - int idx = 0; - while (idx < str.length() && Character.isWhitespace(str.charAt(idx))) { - idx++; - } - return idx; - } - } diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/RTrimGlobalStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/RTrimGlobalStep.java index aae0c5028d5..3e524461ebd 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/RTrimGlobalStep.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/RTrimGlobalStep.java @@ -25,6 +25,8 @@ import java.util.Collections; import java.util.Set; +import static org.apache.tinkerpop.gremlin.process.traversal.step.util.StringLocalStep.getTrimmedString; + /** * Reference implementation for rTrim() step, a mid-traversal step which a string with trailing * whitespace removed. Null values are not processed and remain as null when returned. @@ -49,15 +51,7 @@ protected E map(final Traverser.Admin traverser) { } // we will pass null values to next step - if (null == item) - return null; - - int i = ((String) item).length() - 1; - while (i >= 0 && Character.isWhitespace(((String) item).charAt(i))) { - i--; - } - - return (E) ((String) item).substring(0,i+1); + return (E) getTrimmedString((String) item, false, true); } @Override diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/RTrimLocalStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/RTrimLocalStep.java index 1b1182dfc8d..ee7c39c0b07 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/RTrimLocalStep.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/RTrimLocalStep.java @@ -37,18 +37,9 @@ public RTrimLocalStep(final Traversal.Admin traversal) { @Override protected E applyStringOperation(String item) { - return (E) item.substring(0,getEndIdx(item)+1); + return (E) getTrimmedString(item, false, true); } @Override public String getStepName() { return "rTrim(local)"; } - - private int getEndIdx(final String str) { - int idx = str.length() - 1; - while (idx >= 0 && Character.isWhitespace(str.charAt(idx))) { - idx--; - } - return idx; - } - } diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/TrimGlobalStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/TrimGlobalStep.java index 72f2a4123c6..a543e2b46a9 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/TrimGlobalStep.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/TrimGlobalStep.java @@ -25,6 +25,8 @@ import java.util.Collections; import java.util.Set; +import static org.apache.tinkerpop.gremlin.process.traversal.step.util.StringLocalStep.getTrimmedString; + /** * Reference implementation for trim() step, a mid-traversal step which returns a string with leading and trailing * whitespace removed. Null values are not processed and remain as null when returned. @@ -47,9 +49,7 @@ protected E map(final Traverser.Admin traverser) { throw new IllegalArgumentException( String.format("The trim() step can only take string as argument, encountered %s", item.getClass())); } - - // we will pass null values to next step - return null == item? null : (E) ((String) item).trim(); + return (E) getTrimmedString((String) item, true, true); } @Override diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/TrimLocalStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/TrimLocalStep.java index dd6752fda23..4b35734b319 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/TrimLocalStep.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/TrimLocalStep.java @@ -37,7 +37,7 @@ public TrimLocalStep(final Traversal.Admin traversal) { @Override protected E applyStringOperation(String item) { - return (E) item.trim(); + return (E) getTrimmedString(item, true, true); } @Override diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/StringLocalStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/StringLocalStep.java index d27a4545632..37f4a6976a4 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/StringLocalStep.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/StringLocalStep.java @@ -72,6 +72,27 @@ public Set getRequirements() { return Collections.singleton(TraverserRequirement.OBJECT); } + public static String getTrimmedString(final String s, final boolean lTrim, final boolean rTrim) { + if (s == null) { + return null; + } + + int start = 0; + if (lTrim) { + while (start < s.length() && Character.isWhitespace(s.charAt(start))) { + start++; + } + } + + int end = s.length() - 1; + if (rTrim) { + while (end >= start && Character.isWhitespace(s.charAt(end))) { + end--; + } + } + return s.substring(start, end + 1); + } + protected abstract E applyStringOperation(final String item); protected abstract String getStepName(); diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs index b10a2db7ab5..eba82174435 100644 --- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs +++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs @@ -749,7 +749,8 @@ private static IDictionary, ITraversal>> {(g,p) =>g.Inject(p["xx1"]).Intersect(p["xx2"])}}, {"g_injectXa_null_bX_intersectXa_null_cX", new List, ITraversal>> {(g,p) =>g.Inject(p["xx1"]).Intersect(p["xx2"])}}, {"g_injectX3_threeX_intersectXfive_three_7X", new List, ITraversal>> {(g,p) =>g.Inject(p["xx1"]).Intersect(p["xx2"])}}, - {"g_injectX__feature___test__nullX_lTrim", new List, ITraversal>> {(g,p) =>g.Inject(" feature"," one test",null,""," ").LTrim()}}, + {"g_injectX__feature___test__nullX_lTrim", new List, ITraversal>> {(g,p) =>g.Inject(" feature"," one test",null,""," ","\u3000abc","abc\u3000","\u3000abc\u3000","\u3000\u3000").LTrim()}}, + {"g_injectX__feature___test__nullX_lTrimXlocalX", new List, ITraversal>> {(g,p) =>g.Inject(new List {" feature ", " one test ", null, "", " ", "\u3000abc", "abc\u3000", "\u3000abc\u3000", "\u3000\u3000"}).LTrim(Scope.Local)}}, {"g_injectX__feature__X_lTrim", new List, ITraversal>> {(g,p) =>g.Inject(" feature ").LTrim()}}, {"g_injectXListXa_bXX_lTrim", new List, ITraversal>> {(g,p) =>g.Inject(p["xx1"]).LTrim()}}, {"g_injectXListX1_2XX_lTrimXlocalX", new List, ITraversal>> {(g,p) =>g.Inject(p["xx1"]).LTrim(Scope.Local)}}, @@ -1075,7 +1076,8 @@ private static IDictionary, ITraversal>> {(g,p) =>g.V().Has("age").Properties("age","name").Value()}}, {"g_V_propertiesXname_age_nullX_value", new List, ITraversal>> {(g,p) =>g.V().Properties("name","age",null).Value()}}, {"g_V_valuesXname_age_nullX", new List, ITraversal>> {(g,p) =>g.V().Values("name","age",null)}}, - {"g_injectX__feature___test__nullX_rTrim", new List, ITraversal>> {(g,p) =>g.Inject("feature ","one test ",null,""," ").RTrim()}}, + {"g_injectX__feature___test__nullX_rTrim", new List, ITraversal>> {(g,p) =>g.Inject("feature ","one test ",null,""," ","\u3000abc","abc\u3000","\u3000abc\u3000","\u3000\u3000").RTrim()}}, + {"g_injectX__feature___test__nullX_rTrimXlocalX", new List, ITraversal>> {(g,p) =>g.Inject(new List {" feature ", " one test ", null, "", " ", "\u3000abc", "abc\u3000", "\u3000abc\u3000", "\u3000\u3000"}).RTrim(Scope.Local)}}, {"g_injectX__feature__X_rTrim", new List, ITraversal>> {(g,p) =>g.Inject(" feature ").RTrim()}}, {"g_injectXListXa_bXX_rTrim", new List, ITraversal>> {(g,p) =>g.Inject(p["xx1"]).RTrim()}}, {"g_injectXListX1_2XX_rTrimXlocalX", new List, ITraversal>> {(g,p) =>g.Inject(p["xx1"]).RTrim(Scope.Local)}}, @@ -1225,7 +1227,8 @@ private static IDictionary, ITraversal>> {(g,p) =>g.V().Values("name").ToUpper()}}, {"g_V_valuesXnameX_toUpperXlocalX", new List, ITraversal>> {(g,p) =>g.V().Values("name").ToUpper(Scope.Local)}}, {"g_V_valuesXnameX_order_fold_toUpperXlocalX", new List, ITraversal>> {(g,p) =>g.V().Values("name").Order().Fold().ToUpper(Scope.Local)}}, - {"g_injectX__feature___test__nullX_trim", new List, ITraversal>> {(g,p) =>g.Inject(" feature "," one test ",null,""," ").Trim()}}, + {"g_injectX__feature___test__nullX_trim", new List, ITraversal>> {(g,p) =>g.Inject(" feature "," one test ",null,""," ","\u3000abc","abc\u3000","\u3000abc\u3000","\u3000\u3000").Trim()}}, + {"g_injectX__feature___test__nullX_trimXlocalX", new List, ITraversal>> {(g,p) =>g.Inject(new List {" feature ", " one test ", null, "", " ", "\u3000abc", "abc\u3000", "\u3000abc\u3000", "\u3000\u3000"}).Trim(Scope.Local)}}, {"g_injectXListXa_bXX_trim", new List, ITraversal>> {(g,p) =>g.Inject(p["xx1"]).Trim()}}, {"g_injectXListX1_2XX_trimXlocalX", new List, ITraversal>> {(g,p) =>g.Inject(p["xx1"]).Trim(Scope.Local)}}, {"g_V_valuesXnameX_trim", new List, ITraversal>> {(g,p) =>g.AddV("person").Property("name"," marko ").Property("age",29).As("marko").AddV("person").Property("name"," vadas ").Property("age",27).As("vadas").AddV("software").Property("name"," lop").Property("lang","java").As("lop").AddV("person").Property("name","josh ").Property("age",32).As("josh").AddV("software").Property("name"," ripple ").Property("lang","java").As("ripple").AddV("person").Property("name","peter").Property("age",35).As("peter").AddE("knows").From("marko").To("vadas").Property("weight",0.5).AddE("knows").From("marko").To("josh").Property("weight",1.0).AddE("created").From("marko").To("lop").Property("weight",0.4).AddE("created").From("josh").To("ripple").Property("weight",1.0).AddE("created").From("josh").To("lop").Property("weight",0.4).AddE("created").From("peter").To("lop").Property("weight",0.2), (g,p) =>g.V().Values("name").Trim()}}, diff --git a/gremlin-go/driver/cucumber/gremlin.go b/gremlin-go/driver/cucumber/gremlin.go index 677a4dd2fb0..0922e724659 100644 --- a/gremlin-go/driver/cucumber/gremlin.go +++ b/gremlin-go/driver/cucumber/gremlin.go @@ -720,7 +720,8 @@ var translationMap = map[string][]func(g *gremlingo.GraphTraversalSource, p map[ "g_injectXa_null_bX_intersectXa_cX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.Inject(p["xx1"]).Intersect(p["xx2"])}}, "g_injectXa_null_bX_intersectXa_null_cX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.Inject(p["xx1"]).Intersect(p["xx2"])}}, "g_injectX3_threeX_intersectXfive_three_7X": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.Inject(p["xx1"]).Intersect(p["xx2"])}}, - "g_injectX__feature___test__nullX_lTrim": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.Inject(" feature", " one test", nil, "", " ").LTrim()}}, + "g_injectX__feature___test__nullX_lTrim": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.Inject(" feature", " one test", nil, "", " ", "\u3000abc", "abc\u3000", "\u3000abc\u3000", "\u3000\u3000").LTrim()}}, + "g_injectX__feature___test__nullX_lTrimXlocalX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.Inject([]interface{}{" feature ", " one test ", nil, "", " ", "\u3000abc", "abc\u3000", "\u3000abc\u3000", "\u3000\u3000"}).LTrim(gremlingo.Scope.Local)}}, "g_injectX__feature__X_lTrim": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.Inject(" feature ").LTrim()}}, "g_injectXListXa_bXX_lTrim": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.Inject(p["xx1"]).LTrim()}}, "g_injectXListX1_2XX_lTrimXlocalX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.Inject(p["xx1"]).LTrim(gremlingo.Scope.Local)}}, @@ -1046,7 +1047,8 @@ var translationMap = map[string][]func(g *gremlingo.GraphTraversalSource, p map[ "g_V_hasXageX_propertiesXage_nameX_value": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Has("age").Properties("age", "name").Value()}}, "g_V_propertiesXname_age_nullX_value": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Properties("name", "age", nil).Value()}}, "g_V_valuesXname_age_nullX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Values("name", "age", nil)}}, - "g_injectX__feature___test__nullX_rTrim": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.Inject("feature ", "one test ", nil, "", " ").RTrim()}}, + "g_injectX__feature___test__nullX_rTrim": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.Inject("feature ", "one test ", nil, "", " ", "\u3000abc", "abc\u3000", "\u3000abc\u3000", "\u3000\u3000").RTrim()}}, + "g_injectX__feature___test__nullX_rTrimXlocalX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.Inject([]interface{}{" feature ", " one test ", nil, "", " ", "\u3000abc", "abc\u3000", "\u3000abc\u3000", "\u3000\u3000"}).RTrim(gremlingo.Scope.Local)}}, "g_injectX__feature__X_rTrim": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.Inject(" feature ").RTrim()}}, "g_injectXListXa_bXX_rTrim": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.Inject(p["xx1"]).RTrim()}}, "g_injectXListX1_2XX_rTrimXlocalX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.Inject(p["xx1"]).RTrim(gremlingo.Scope.Local)}}, @@ -1196,7 +1198,8 @@ var translationMap = map[string][]func(g *gremlingo.GraphTraversalSource, p map[ "g_V_valuesXnameX_toUpper": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Values("name").ToUpper()}}, "g_V_valuesXnameX_toUpperXlocalX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Values("name").ToUpper(gremlingo.Scope.Local)}}, "g_V_valuesXnameX_order_fold_toUpperXlocalX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Values("name").Order().Fold().ToUpper(gremlingo.Scope.Local)}}, - "g_injectX__feature___test__nullX_trim": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.Inject(" feature ", " one test ", nil, "", " ").Trim()}}, + "g_injectX__feature___test__nullX_trim": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.Inject(" feature ", " one test ", nil, "", " ", "\u3000abc", "abc\u3000", "\u3000abc\u3000", "\u3000\u3000").Trim()}}, + "g_injectX__feature___test__nullX_trimXlocalX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.Inject([]interface{}{" feature ", " one test ", nil, "", " ", "\u3000abc", "abc\u3000", "\u3000abc\u3000", "\u3000\u3000"}).Trim(gremlingo.Scope.Local)}}, "g_injectXListXa_bXX_trim": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.Inject(p["xx1"]).Trim()}}, "g_injectXListX1_2XX_trimXlocalX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.Inject(p["xx1"]).Trim(gremlingo.Scope.Local)}}, "g_V_valuesXnameX_trim": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.AddV("person").Property("name", " marko ").Property("age", 29).As("marko").AddV("person").Property("name", " vadas ").Property("age", 27).As("vadas").AddV("software").Property("name", " lop").Property("lang", "java").As("lop").AddV("person").Property("name", "josh ").Property("age", 32).As("josh").AddV("software").Property("name", " ripple ").Property("lang", "java").As("ripple").AddV("person").Property("name", "peter").Property("age", 35).As("peter").AddE("knows").From("marko").To("vadas").Property("weight", 0.5).AddE("knows").From("marko").To("josh").Property("weight", 1.0).AddE("created").From("marko").To("lop").Property("weight", 0.4).AddE("created").From("josh").To("ripple").Property("weight", 1.0).AddE("created").From("josh").To("lop").Property("weight", 0.4).AddE("created").From("peter").To("lop").Property("weight", 0.2)}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Values("name").Trim()}}, diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/gremlin.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/gremlin.js index fe3804f3a0d..8eaca3b803b 100644 --- a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/gremlin.js +++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/gremlin.js @@ -740,7 +740,8 @@ const gremlins = { g_injectXa_null_bX_intersectXa_cX: [function({g, xx1, xx2}) { return g.inject(xx1).intersect(xx2) }], g_injectXa_null_bX_intersectXa_null_cX: [function({g, xx1, xx2}) { return g.inject(xx1).intersect(xx2) }], g_injectX3_threeX_intersectXfive_three_7X: [function({g, xx1, xx2}) { return g.inject(xx1).intersect(xx2) }], - g_injectX__feature___test__nullX_lTrim: [function({g}) { return g.inject(" feature"," one test",null,""," ").lTrim() }], + g_injectX__feature___test__nullX_lTrim: [function({g}) { return g.inject(" feature"," one test",null,""," ","\u3000abc","abc\u3000","\u3000abc\u3000","\u3000\u3000").lTrim() }], + g_injectX__feature___test__nullX_lTrimXlocalX: [function({g}) { return g.inject([" feature ", " one test ", null, "", " ", "\u3000abc", "abc\u3000", "\u3000abc\u3000", "\u3000\u3000"]).lTrim(Scope.local) }], g_injectX__feature__X_lTrim: [function({g}) { return g.inject(" feature ").lTrim() }], g_injectXListXa_bXX_lTrim: [function({g, xx1}) { return g.inject(xx1).lTrim() }], g_injectXListX1_2XX_lTrimXlocalX: [function({g, xx1}) { return g.inject(xx1).lTrim(Scope.local) }], @@ -1066,7 +1067,8 @@ const gremlins = { g_V_hasXageX_propertiesXage_nameX_value: [function({g}) { return g.V().has("age").properties("age","name").value() }], g_V_propertiesXname_age_nullX_value: [function({g}) { return g.V().properties("name","age",null).value() }], g_V_valuesXname_age_nullX: [function({g}) { return g.V().values("name","age",null) }], - g_injectX__feature___test__nullX_rTrim: [function({g}) { return g.inject("feature ","one test ",null,""," ").rTrim() }], + g_injectX__feature___test__nullX_rTrim: [function({g}) { return g.inject("feature ","one test ",null,""," ","\u3000abc","abc\u3000","\u3000abc\u3000","\u3000\u3000").rTrim() }], + g_injectX__feature___test__nullX_rTrimXlocalX: [function({g}) { return g.inject([" feature ", " one test ", null, "", " ", "\u3000abc", "abc\u3000", "\u3000abc\u3000", "\u3000\u3000"]).rTrim(Scope.local) }], g_injectX__feature__X_rTrim: [function({g}) { return g.inject(" feature ").rTrim() }], g_injectXListXa_bXX_rTrim: [function({g, xx1}) { return g.inject(xx1).rTrim() }], g_injectXListX1_2XX_rTrimXlocalX: [function({g, xx1}) { return g.inject(xx1).rTrim(Scope.local) }], @@ -1216,7 +1218,8 @@ const gremlins = { g_V_valuesXnameX_toUpper: [function({g}) { return g.V().values("name").toUpper() }], g_V_valuesXnameX_toUpperXlocalX: [function({g}) { return g.V().values("name").toUpper(Scope.local) }], g_V_valuesXnameX_order_fold_toUpperXlocalX: [function({g}) { return g.V().values("name").order().fold().toUpper(Scope.local) }], - g_injectX__feature___test__nullX_trim: [function({g}) { return g.inject(" feature "," one test ",null,""," ").trim() }], + g_injectX__feature___test__nullX_trim: [function({g}) { return g.inject(" feature "," one test ",null,""," ","\u3000abc","abc\u3000","\u3000abc\u3000","\u3000\u3000").trim() }], + g_injectX__feature___test__nullX_trimXlocalX: [function({g}) { return g.inject([" feature ", " one test ", null, "", " ", "\u3000abc", "abc\u3000", "\u3000abc\u3000", "\u3000\u3000"]).trim(Scope.local) }], g_injectXListXa_bXX_trim: [function({g, xx1}) { return g.inject(xx1).trim() }], g_injectXListX1_2XX_trimXlocalX: [function({g, xx1}) { return g.inject(xx1).trim(Scope.local) }], g_V_valuesXnameX_trim: [function({g}) { return g.addV("person").property("name"," marko ").property("age",29).as("marko").addV("person").property("name"," vadas ").property("age",27).as("vadas").addV("software").property("name"," lop").property("lang","java").as("lop").addV("person").property("name","josh ").property("age",32).as("josh").addV("software").property("name"," ripple ").property("lang","java").as("ripple").addV("person").property("name","peter").property("age",35).as("peter").addE("knows").from_("marko").to("vadas").property("weight",0.5).addE("knows").from_("marko").to("josh").property("weight",1.0).addE("created").from_("marko").to("lop").property("weight",0.4).addE("created").from_("josh").to("ripple").property("weight",1.0).addE("created").from_("josh").to("lop").property("weight",0.4).addE("created").from_("peter").to("lop").property("weight",0.2) }, function({g}) { return g.V().values("name").trim() }], diff --git a/gremlin-python/src/main/python/radish/gremlin.py b/gremlin-python/src/main/python/radish/gremlin.py index 70c1751a5cc..9847e87e0fe 100644 --- a/gremlin-python/src/main/python/radish/gremlin.py +++ b/gremlin-python/src/main/python/radish/gremlin.py @@ -722,7 +722,8 @@ 'g_injectXa_null_bX_intersectXa_cX': [(lambda g, xx1=None,xx2=None:g.inject(xx1).intersect(xx2))], 'g_injectXa_null_bX_intersectXa_null_cX': [(lambda g, xx1=None,xx2=None:g.inject(xx1).intersect(xx2))], 'g_injectX3_threeX_intersectXfive_three_7X': [(lambda g, xx1=None,xx2=None:g.inject(xx1).intersect(xx2))], - 'g_injectX__feature___test__nullX_lTrim': [(lambda g:g.inject(' feature',' one test',None,'',' ').lTrim())], + 'g_injectX__feature___test__nullX_lTrim': [(lambda g:g.inject(' feature',' one test',None,'',' ',' abc','abc ',' abc ','  ').lTrim())], + 'g_injectX__feature___test__nullX_lTrimXlocalX': [(lambda g:g.inject([' feature ',' one test ',None,'',' ',' abc','abc ',' abc ','  ']).lTrim(Scope.local))], 'g_injectX__feature__X_lTrim': [(lambda g:g.inject(' feature ').lTrim())], 'g_injectXListXa_bXX_lTrim': [(lambda g, xx1=None:g.inject(xx1).lTrim())], 'g_injectXListX1_2XX_lTrimXlocalX': [(lambda g, xx1=None:g.inject(xx1).lTrim(Scope.local))], @@ -1048,7 +1049,8 @@ 'g_V_hasXageX_propertiesXage_nameX_value': [(lambda g:g.V().has('age').properties('age','name').value())], 'g_V_propertiesXname_age_nullX_value': [(lambda g:g.V().properties('name','age',None).value())], 'g_V_valuesXname_age_nullX': [(lambda g:g.V().values('name','age',None))], - 'g_injectX__feature___test__nullX_rTrim': [(lambda g:g.inject('feature ','one test ',None,'',' ').rTrim())], + 'g_injectX__feature___test__nullX_rTrim': [(lambda g:g.inject('feature ','one test ',None,'',' ',' abc','abc ',' abc ','  ').rTrim())], + 'g_injectX__feature___test__nullX_rTrimXlocalX': [(lambda g:g.inject([' feature ',' one test ',None,'',' ',' abc','abc ',' abc ','  ']).rTrim(Scope.local))], 'g_injectX__feature__X_rTrim': [(lambda g:g.inject(' feature ').rTrim())], 'g_injectXListXa_bXX_rTrim': [(lambda g, xx1=None:g.inject(xx1).rTrim())], 'g_injectXListX1_2XX_rTrimXlocalX': [(lambda g, xx1=None:g.inject(xx1).rTrim(Scope.local))], @@ -1198,7 +1200,8 @@ 'g_V_valuesXnameX_toUpper': [(lambda g:g.V().name.to_upper())], 'g_V_valuesXnameX_toUpperXlocalX': [(lambda g:g.V().name.to_upper(Scope.local))], 'g_V_valuesXnameX_order_fold_toUpperXlocalX': [(lambda g:g.V().name.order().fold().to_upper(Scope.local))], - 'g_injectX__feature___test__nullX_trim': [(lambda g:g.inject(' feature ',' one test ',None,'',' ').trim())], + 'g_injectX__feature___test__nullX_trim': [(lambda g:g.inject(' feature ',' one test ',None,'',' ',' abc','abc ',' abc ','  ').trim())], + 'g_injectX__feature___test__nullX_trimXlocalX': [(lambda g:g.inject([' feature ',' one test ',None,'',' ',' abc','abc ',' abc ','  ']).trim(Scope.local))], 'g_injectXListXa_bXX_trim': [(lambda g, xx1=None:g.inject(xx1).trim())], 'g_injectXListX1_2XX_trimXlocalX': [(lambda g, xx1=None:g.inject(xx1).trim(Scope.local))], 'g_V_valuesXnameX_trim': [(lambda g:g.addV('person').property('name',' marko ').property('age',29).as_('marko').addV('person').property('name',' vadas ').property('age',27).as_('vadas').addV('software').property('name',' lop').property('lang','java').as_('lop').addV('person').property('name','josh ').property('age',32).as_('josh').addV('software').property('name',' ripple ').property('lang','java').as_('ripple').addV('person').property('name','peter').property('age',35).as_('peter').addE('knows').from_('marko').to('vadas').property('weight',float(0.5)).addE('knows').from_('marko').to('josh').property('weight',float(1.0)).addE('created').from_('marko').to('lop').property('weight',float(0.4)).addE('created').from_('josh').to('ripple').property('weight',float(1.0)).addE('created').from_('josh').to('lop').property('weight',float(0.4)).addE('created').from_('peter').to('lop').property('weight',float(0.2))), (lambda g:g.V().name.trim())], diff --git a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/LTrim.feature b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/LTrim.feature index 4ca49151095..67b664c9618 100644 --- a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/LTrim.feature +++ b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/LTrim.feature @@ -19,11 +19,12 @@ Feature: Step - lTrim() @GraphComputerVerificationInjectionNotSupported + # This verifies both ASCII control space and ideographic space character \u3000 are property trimmed. Scenario: g_injectX__feature___test__nullX_lTrim Given the empty graph And the traversal of """ - g.inject(" feature", " one test", null, "", " ").lTrim() + g.inject(" feature", " one test", null, "", " ", " abc", "abc ", " abc ", "  ").lTrim() """ When iterated to list Then the result should be unordered @@ -33,6 +34,23 @@ Feature: Step - lTrim() | null | | str[] | | str[] | + | str[abc] | + | str[abc ] | + | str[abc ] | + | str[] | + + @GraphComputerVerificationInjectionNotSupported + # This verifies both ASCII control space and ideographic space character \u3000 are property trimmed. + Scenario: g_injectX__feature___test__nullX_lTrimXlocalX + Given the empty graph + And the traversal of + """ + g.inject([" feature ", " one test ", null, "", " ", " abc", "abc ", " abc ", "  "]).lTrim(Scope.local) + """ + When iterated to list + Then the result should be unordered + | result | + | l[str[feature ],str[one test ],null,str[],str[],str[abc],str[abc ],str[abc ],str[]] | @GraphComputerVerificationInjectionNotSupported Scenario: g_injectX__feature__X_lTrim diff --git a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/RTrim.feature b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/RTrim.feature index 23df32f871a..4b171b8602e 100644 --- a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/RTrim.feature +++ b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/RTrim.feature @@ -19,11 +19,12 @@ Feature: Step - rTrim() @GraphComputerVerificationInjectionNotSupported + # This verifies both ASCII control space and ideographic space character \u3000 are property trimmed. Scenario: g_injectX__feature___test__nullX_rTrim Given the empty graph And the traversal of """ - g.inject("feature ", "one test ", null, "", " ").rTrim() + g.inject("feature ", "one test ", null, "", " ", " abc", "abc ", " abc ", "  ").rTrim() """ When iterated to list Then the result should be unordered @@ -33,6 +34,23 @@ Feature: Step - rTrim() | null | | str[] | | str[] | + | str[ abc] | + | str[abc] | + | str[ abc] | + | str[] | + + @GraphComputerVerificationInjectionNotSupported + # This verifies both ASCII control space and ideographic space character \u3000 are property trimmed. + Scenario: g_injectX__feature___test__nullX_rTrimXlocalX + Given the empty graph + And the traversal of + """ + g.inject([" feature ", " one test ", null, "", " ", " abc", "abc ", " abc ", "  "]).rTrim(Scope.local) + """ + When iterated to list + Then the result should be unordered + | result | + | l[str[ feature],str[ one test],null,str[],str[],str[ abc],str[abc],str[ abc],str[]] | @GraphComputerVerificationInjectionNotSupported Scenario: g_injectX__feature__X_rTrim diff --git a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/Trim.feature b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/Trim.feature index feda1856f93..6279ca4dc3f 100644 --- a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/Trim.feature +++ b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/Trim.feature @@ -19,11 +19,12 @@ Feature: Step - trim() @GraphComputerVerificationInjectionNotSupported + # This verifies both ASCII control space and ideographic space character \u3000 are property trimmed. Scenario: g_injectX__feature___test__nullX_trim Given the empty graph And the traversal of """ - g.inject(" feature ", " one test ", null, "", " ").trim() + g.inject(" feature ", " one test ", null, "", " ", " abc", "abc ", " abc ", "  ").trim() """ When iterated to list Then the result should be unordered @@ -33,6 +34,23 @@ Feature: Step - trim() | null | | str[] | | str[] | + | str[abc] | + | str[abc] | + | str[abc] | + | str[] | + + @GraphComputerVerificationInjectionNotSupported + # This verifies both ASCII control space and ideographic space character \u3000 are property trimmed. + Scenario: g_injectX__feature___test__nullX_trimXlocalX + Given the empty graph + And the traversal of + """ + g.inject([" feature ", " one test ", null, "", " ", " abc", "abc ", " abc ", "  "]).trim(Scope.local) + """ + When iterated to list + Then the result should be unordered + | result | + | l[str[feature],str[one test],null,str[],str[],str[abc],str[abc],str[abc],str[]] | @GraphComputerVerificationInjectionNotSupported Scenario: g_injectXListXa_bXX_trim