Skip to content

Commit

Permalink
TrimGlobalStep handles unicode characters as Ltrim and Rtrim
Browse files Browse the repository at this point in the history
  • Loading branch information
rdtr committed Jun 28, 2024
1 parent dc6e715 commit d391ce8
Show file tree
Hide file tree
Showing 15 changed files with 115 additions and 57 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ This release also includes changes from <<release-3-6-8, 3.6.8>>.
* 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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -49,15 +51,7 @@ protected E map(final Traverser.Admin<S> 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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,18 +51,9 @@ public Set<TraverserRequirement> 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;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -49,15 +51,7 @@ protected E map(final Traverser.Admin<S> 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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -47,9 +49,7 @@ protected E map(final Traverser.Admin<S> 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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,27 @@ public Set<TraverserRequirement> 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();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -749,7 +749,8 @@ private static IDictionary<string, List<Func<GraphTraversalSource, IDictionary<s
{"g_injectXa_null_bX_intersectXa_cX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject(p["xx1"]).Intersect(p["xx2"])}},
{"g_injectXa_null_bX_intersectXa_null_cX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject(p["xx1"]).Intersect(p["xx2"])}},
{"g_injectX3_threeX_intersectXfive_three_7X", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject(p["xx1"]).Intersect(p["xx2"])}},
{"g_injectX__feature___test__nullX_lTrim", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject<object>(" feature"," one test",null,""," ").LTrim()}},
{"g_injectX__feature___test__nullX_lTrim", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject<object>(" feature"," one test",null,""," ","\u3000abc","abc\u3000","\u3000abc\u3000","\u3000\u3000").LTrim()}},
{"g_injectX__feature___test__nullX_lTrimXlocalX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject(new List<object> {" feature ", " one test ", null, "", " ", "\u3000abc", "abc\u3000", "\u3000abc\u3000", "\u3000\u3000"}).LTrim<object>(Scope.Local)}},
{"g_injectX__feature__X_lTrim", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject(" feature ").LTrim()}},
{"g_injectXListXa_bXX_lTrim", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject(p["xx1"]).LTrim()}},
{"g_injectXListX1_2XX_lTrimXlocalX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject(p["xx1"]).LTrim<object>(Scope.Local)}},
Expand Down Expand Up @@ -1075,7 +1076,8 @@ private static IDictionary<string, List<Func<GraphTraversalSource, IDictionary<s
{"g_V_hasXageX_propertiesXage_nameX_value", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Has("age").Properties<object>("age","name").Value<object>()}},
{"g_V_propertiesXname_age_nullX_value", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Properties<object>("name","age",null).Value<object>()}},
{"g_V_valuesXname_age_nullX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Values<object>("name","age",null)}},
{"g_injectX__feature___test__nullX_rTrim", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject<object>("feature ","one test ",null,""," ").RTrim()}},
{"g_injectX__feature___test__nullX_rTrim", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject<object>("feature ","one test ",null,""," ","\u3000abc","abc\u3000","\u3000abc\u3000","\u3000\u3000").RTrim()}},
{"g_injectX__feature___test__nullX_rTrimXlocalX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject(new List<object> {" feature ", " one test ", null, "", " ", "\u3000abc", "abc\u3000", "\u3000abc\u3000", "\u3000\u3000"}).RTrim<object>(Scope.Local)}},
{"g_injectX__feature__X_rTrim", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject(" feature ").RTrim()}},
{"g_injectXListXa_bXX_rTrim", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject(p["xx1"]).RTrim()}},
{"g_injectXListX1_2XX_rTrimXlocalX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject(p["xx1"]).RTrim<object>(Scope.Local)}},
Expand Down Expand Up @@ -1225,7 +1227,8 @@ private static IDictionary<string, List<Func<GraphTraversalSource, IDictionary<s
{"g_V_valuesXnameX_toUpper", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Values<object>("name").ToUpper()}},
{"g_V_valuesXnameX_toUpperXlocalX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Values<object>("name").ToUpper<object>(Scope.Local)}},
{"g_V_valuesXnameX_order_fold_toUpperXlocalX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Values<object>("name").Order().Fold().ToUpper<object>(Scope.Local)}},
{"g_injectX__feature___test__nullX_trim", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject<object>(" feature "," one test ",null,""," ").Trim()}},
{"g_injectX__feature___test__nullX_trim", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject<object>(" feature "," one test ",null,""," ","\u3000abc","abc\u3000","\u3000abc\u3000","\u3000\u3000").Trim()}},
{"g_injectX__feature___test__nullX_trimXlocalX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject(new List<object> {" feature ", " one test ", null, "", " ", "\u3000abc", "abc\u3000", "\u3000abc\u3000", "\u3000\u3000"}).Trim<object>(Scope.Local)}},
{"g_injectXListXa_bXX_trim", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject(p["xx1"]).Trim()}},
{"g_injectXListX1_2XX_trimXlocalX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject(p["xx1"]).Trim<object>(Scope.Local)}},
{"g_V_valuesXnameX_trim", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.AddV("person").Property("name"," marko ").Property("age",29).As("marko").AddV("person").Property("name"," vadas ").Property("age",27).As("vadas").AddV("software").Property("name"," lop").Property("lang","java").As("lop").AddV("person").Property("name","josh ").Property("age",32).As("josh").AddV("software").Property("name"," ripple ").Property("lang","java").As("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<object>("name").Trim()}},
Expand Down
9 changes: 6 additions & 3 deletions gremlin-go/driver/cucumber/gremlin.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)}},
Expand Down Expand Up @@ -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)}},
Expand Down Expand Up @@ -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()}},
Expand Down
Loading

0 comments on commit d391ce8

Please sign in to comment.