This is an automated email from the ASF dual-hosted git repository.
colegreer pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/tinkerpop.git
The following commit(s) were added to refs/heads/master by this push:
new b37e35cf47 TINKERPOP-3083 Change SplitGlobalStep and SplitLocalStep to
use a new StringUtil.split utility method which will split the given string
into a list of individual string characters if the given separator is an empty
string. (#2741)
b37e35cf47 is described below
commit b37e35cf478903957e653fb1a6e4b52170ee4c61
Author: andreachild <[email protected]>
AuthorDate: Tue Aug 27 17:01:52 2024 -0700
TINKERPOP-3083 Change SplitGlobalStep and SplitLocalStep to use a new
StringUtil.split utility method which will split the given string into a list
of individual string characters if the given separator is an empty string.
(#2741)
---
CHANGELOG.asciidoc | 1 +
docs/src/dev/provider/gremlin-semantics.asciidoc | 2 +-
docs/src/reference/the-traversal.asciidoc | 10 ++--
docs/src/upgrade/release-4.x.x.asciidoc | 16 +++++-
.../traversal/step/map/SplitGlobalStep.java | 7 ++-
.../process/traversal/step/map/SplitLocalStep.java | 11 +---
.../apache/tinkerpop/gremlin/util/StringUtil.java | 53 ++++++++++++++++++
.../traversal/step/map/SplitGlobalStepTest.java | 2 +-
.../traversal/step/map/SplitLocalStepTest.java | 1 +
.../tinkerpop/gremlin/util/StringUtilTest.java | 62 ++++++++++++++++++++++
.../Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs | 2 +
gremlin-go/driver/cucumber/gremlin.go | 2 +
.../gremlin-javascript/test/cucumber/gremlin.js | 2 +
gremlin-python/src/main/python/radish/gremlin.py | 2 +
.../gremlin/test/features/map/Split.feature | 29 ++++++++++
15 files changed, 182 insertions(+), 20 deletions(-)
diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc
index c0dafdfb96..8d620a857d 100644
--- a/CHANGELOG.asciidoc
+++ b/CHANGELOG.asciidoc
@@ -46,6 +46,7 @@
image::https://raw.githubusercontent.com/apache/tinkerpop/master/docs/static/ima
* Made `new` keyword optional in the Gremlin grammar.
* Added TypeScript & ECMAScript module support.
* Improved graph structures type definitions in TypeScript.
+* Modified the `split()` step to split a string into a list of its characters
if the given separator is an empty string.
== TinkerPop 3.7.0 (Gremfir Master of the Pan Flute)
diff --git a/docs/src/dev/provider/gremlin-semantics.asciidoc
b/docs/src/dev/provider/gremlin-semantics.asciidoc
index 06c6c35b3e..495235b4db 100644
--- a/docs/src/dev/provider/gremlin-semantics.asciidoc
+++ b/docs/src/dev/provider/gremlin-semantics.asciidoc
@@ -1517,7 +1517,7 @@
link:https://tinkerpop.apache.org/docs/x.y.z/reference/#rTrim-step[reference]
*Arguments:*
* `separator` - The string character(s) used as delimiter to split the input
string. Nullable, a null separator will split on
-whitespaces.
+whitespaces. An empty string separator will split on each character.
* `scope` - Determines the type of traverser it operates on. Both scopes will
operate on the level of individual traversers.
The `global` scope will operate on individual string traverser. The `local`
scope will operate on list traverser with string elements inside.
diff --git a/docs/src/reference/the-traversal.asciidoc
b/docs/src/reference/the-traversal.asciidoc
index 0cdfcc51d0..897b7d39f5 100644
--- a/docs/src/reference/the-traversal.asciidoc
+++ b/docs/src/reference/the-traversal.asciidoc
@@ -4455,8 +4455,8 @@
link:++https://tinkerpop.apache.org/javadocs/x.y.z/core/org/apache/tinkerpop/gre
[[split-step]]
=== Split Step
The `split()`-step (*map*) returns a list of strings created by splitting the
incoming string traverser around the
-matches of the given separator. A null separator will split the string by
whitespaces. Null values from the incoming
-traversers are not processed and remain as null when returned. If the incoming
traverser is a non-String value then an
+matches of the given separator. A null separator will split the string by
whitespaces. An empty string separator will split on each character.
+Null values from the incoming traversers are not processed and remain as null
when returned. If the incoming traverser is a non-String value then an
IllegalArgumentException will be thrown.
[gremlin-groovy,modern]
@@ -4464,12 +4464,14 @@ IllegalArgumentException will be thrown.
g.inject("that", "this", "test", null).split("h") <1>
g.V().hasLabel("person").values("name").split("a") <2>
g.inject("helloworld", "hello world", "hello world").split(null) <3>
-g.V().hasLabel("person").values("name").fold().split(local, "a") <4>
+g.inject("hello", "world", null).split("") <4>
+g.V().hasLabel("person").values("name").fold().split(local, "a") <5>
----
<1> Split the strings by "h".
<2> Split person names by "a".
<3> Splitting by null will split by whitespaces.
-<4> Use `Scope.local` to operate on individual string elements inside incoming
list, which will return a list of results.
+<4> Splitting by "" will split by each character.
+<5> Use `Scope.local` to operate on individual string elements inside incoming
list, which will return a list of results.
*Additional References*
link:++https://tinkerpop.apache.org/javadocs/x.y.z/core/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.html#split(java.lang.String)++[`split(String)`]
diff --git a/docs/src/upgrade/release-4.x.x.asciidoc
b/docs/src/upgrade/release-4.x.x.asciidoc
index 1772321f15..7d369ba2a9 100644
--- a/docs/src/upgrade/release-4.x.x.asciidoc
+++ b/docs/src/upgrade/release-4.x.x.asciidoc
@@ -77,7 +77,7 @@ these were deserialized into arrays.
==== Gremlin Grammar Changes
-A number of changes have been introduce to the Gremlin grammar to help make it
be more consistent and easier to use.
+A number of changes have been introduced to the Gremlin grammar to help make
it be more consistent and easier to use.
*`new` keyword is now optional*
@@ -113,6 +113,20 @@ The `none()` step, which was primarily used by `iterate()`
to discard traversal
renamed to `discard()`. In its place is a new list filtering step `none()`,
which takes a predicate as an argument and
passes lists with no elements matching the predicate.
+==== Splitting a string into characters using split()
+The `split()` step will now split a string into a list of its characters if
the given separator is an empty string.
+[source,groovy]
+----
+// previous implementation
+g.inject("Hello").split("")
+==>[Hello]
+
+// new implementation
+g.inject("Hello").split("")
+==>[H,e,l,l,o]
+----
+See: link:https://issues.apache.org/jira/browse/TINKERPOP-3083[TINKERPOP-3083]
+
==== Improved handling of integer overflows
Integer overflows caused by addition and multiplication operations will throw
an exception instead of being silently
diff --git
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/SplitGlobalStep.java
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/SplitGlobalStep.java
index 14e886edfe..fba728a50b 100644
---
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/SplitGlobalStep.java
+++
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/SplitGlobalStep.java
@@ -18,15 +18,13 @@
*/
package org.apache.tinkerpop.gremlin.process.traversal.step.map;
-import org.apache.commons.lang3.StringUtils;
import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent;
import
org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
+import org.apache.tinkerpop.gremlin.util.StringUtil;
-import java.util.Arrays;
import java.util.Collections;
-import java.util.List;
import java.util.Set;
/**
@@ -57,7 +55,7 @@ public final class SplitGlobalStep<S, E> extends
ScalarMapStep<S, E> implements
}
// we will pass null values to next step
- return null == item? null : (E)
Arrays.asList(StringUtils.splitByWholeSeparator((String) item, this.separator));
+ return null == item? null : (E) StringUtil.split((String)item,
this.separator);
}
public String getSeparator() {
@@ -75,4 +73,5 @@ public final class SplitGlobalStep<S, E> extends
ScalarMapStep<S, E> implements
result = 31 * result + (null != this.separator ?
this.separator.hashCode() : 0);
return result;
}
+
}
diff --git
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/SplitLocalStep.java
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/SplitLocalStep.java
index 5d638c74ca..9576e22b65 100644
---
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/SplitLocalStep.java
+++
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/SplitLocalStep.java
@@ -18,17 +18,10 @@
*/
package org.apache.tinkerpop.gremlin.process.traversal.step.map;
-import org.apache.commons.lang3.StringUtils;
import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
-import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent;
import
org.apache.tinkerpop.gremlin.process.traversal.step.util.StringLocalStep;
-import
org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
-
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-import java.util.Set;
+import org.apache.tinkerpop.gremlin.util.StringUtil;
/**
* Reference implementation for substring step, a mid-traversal step which
returns a list of strings created by
@@ -50,7 +43,7 @@ public final class SplitLocalStep<S, E> extends
StringLocalStep<S, E> implements
@Override
protected E applyStringOperation(String item) {
- return (E) Arrays.asList((StringUtils.splitByWholeSeparator(item,
this.separator)));
+ return (E) StringUtil.split(item, this.separator);
}
@Override
diff --git
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/StringUtil.java
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/StringUtil.java
new file mode 100644
index 0000000000..d352a38df4
--- /dev/null
+++
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/StringUtil.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tinkerpop.gremlin.util;
+
+import java.util.Arrays;
+import java.util.List;
+import org.apache.commons.lang3.StringUtils;
+
+/**
+ * Utility class for Strings.
+ *
+ * @author Andrea Child
+ */
+public final class StringUtil {
+
+ private StringUtil() {
+ }
+
+ /**
+ * Splits the provided string into a List of string by the given
separator, which will not be included in the returned List.
+ *
+ * @param toSplit the string to split
+ * @param separator the separator string to split by - empty will split
into a List of characters
+ * @return a List of parsed strings, not including the given separator
+ */
+ public static List<String> split(final String toSplit, final String
separator) {
+ if (toSplit == null) {
+ throw new IllegalArgumentException("toSplit cannot be null");
+ }
+ if (StringUtils.EMPTY.equals(separator)) {
+ // split into a list of character strings
+ // ie. "ab cd" -> ["a","b"," ","c","d"]
+ return Arrays.asList(toSplit.split(StringUtils.EMPTY));
+ }
+ return Arrays.asList(StringUtils.splitByWholeSeparator(toSplit,
separator));
+ }
+}
diff --git
a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/SplitGlobalStepTest.java
b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/SplitGlobalStepTest.java
index 9a442fa5f0..ceb0598ffd 100644
---
a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/SplitGlobalStepTest.java
+++
b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/SplitGlobalStepTest.java
@@ -48,7 +48,7 @@ public class SplitGlobalStepTest extends StepTest {
assertArrayEquals(new String[]{"helloworld"},
__.__("helloworld").split(null).next().toArray());
assertArrayEquals(new String[]{"hello", "world"}, __.__("hello
world").split(null).next().toArray());
assertArrayEquals(new String[]{"hello", "world"}, __.__("hello
world").split(null).next().toArray());
- assertArrayEquals(new String[]{"hello", "world"}, __.__("hello
world").split("").next().toArray());
+ assertArrayEquals(new String[]{"h","e","l","l","o"," ",
"w","o","r","l","d"}, __.__("hello world").split("").next().toArray());
assertArrayEquals(new String[]{"hello", "world"}, __.__("hello
world").split(" ").next().toArray());
assertArrayEquals(new String[]{"hello world"}, __.__("hello
world").split(" ").next().toArray());
diff --git
a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/SplitLocalStepTest.java
b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/SplitLocalStepTest.java
index b9c792d7d4..cddf7dc4e0 100644
---
a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/SplitLocalStepTest.java
+++
b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/SplitLocalStepTest.java
@@ -42,6 +42,7 @@ public class SplitLocalStepTest extends StepTest {
public void testReturnTypes() {
assertArrayEquals(new String[]{"h", "llo"},
__.__("hello").split(Scope.local, "e").next().toArray());
assertArrayEquals(new String[]{"ab", "bc"},
__.__("abc|abc").split(Scope.local, "c|a").next().toArray());
+ assertArrayEquals(new String[]{"t","e","s","t"},
__.__("test").split(Scope.local, "").next().toArray());
List<List<String>> resList = new ArrayList<>();
resList.add(Arrays.asList("helloworld"));
diff --git
a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/util/StringUtilTest.java
b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/util/StringUtilTest.java
new file mode 100644
index 0000000000..04e112f92d
--- /dev/null
+++
b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/util/StringUtilTest.java
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tinkerpop.gremlin.util;
+
+import java.util.Arrays;
+import org.apache.tinkerpop.gremlin.AssertHelper;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * @author Andrea Child
+ */
+public class StringUtilTest {
+
+ @Test
+ public void shouldBeUtilityClass() throws Exception {
+ AssertHelper.assertIsUtilityClass(StringUtil.class);
+ }
+
+ @Test
+ public void shouldSplitBySeparatorAndNotContainSeparator() {
+ assertEquals(Arrays.asList("h","llo"), StringUtil.split("hello", "e"));
+ }
+
+ @Test
+ public void shouldNotBeSplitIfSeparatorNotPresentInString() {
+ final String toSplit = "test";
+ assertEquals(Arrays.asList(toSplit), StringUtil.split(toSplit, "x"));
+ }
+
+ @Test
+ public void shouldSplitByCharacterIfSeparatorIsEmpty() {
+ assertEquals(Arrays.asList("t","e","s","t"," ","1","2","3"),
StringUtil.split("test 123", ""));
+ }
+
+ @Test
+ public void shouldSplitByWhitespaceIfSeparatorIsNull() {
+ assertEquals(Arrays.asList("test","123"), StringUtil.split("test 123",
null));
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void shouldThrowIfStringToSplitIsNull() {
+ StringUtil.split(null, "test");
+ }
+}
\ No newline at end of file
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs
b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs
index bd0a8e7469..12449a0d9d 100644
--- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs
@@ -1204,9 +1204,11 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
{"g_V_hasXname_vadasX_shortestPath_distanceXweightX_maxDistanceX1_3X", new
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>>
{(g,p) =>g.V().Has("name",
"vadas").ShortestPath().With("~tinkerpop.shortestPath.distance",
"weight").With("~tinkerpop.shortestPath.maxDistance", 1.3)}},
{"g_injectXthat_this_testX_spiltXhX", new
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>>
{(g,p) =>g.Inject<object>("that", "this", "test", null).Split("h")}},
{"g_injectXhello_worldX_spiltXnullX", new
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>>
{(g,p) =>g.Inject<object>("hello world").Split(null)}},
+ {"g_injectXthat_this_test_nullX_splitXemptyX", new
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>>
{(g,p) =>g.Inject<object>("that", "this", "test", null).Split("")}},
{"g_injectXListXa_bXcX_splitXa_bX", new
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>>
{(g,p) =>g.Inject<object>(p["xx1"]).Split("a")}},
{"g_V_hasLabelXpersonX_valueXnameX_splitXnullX", new
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>>
{(g,p) =>g.V().HasLabel("person").Values<object>("name").Split(null)}},
{"g_V_hasLabelXpersonX_valueXnameX_order_fold_splitXlocal_aX_unfold", new
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>>
{(g,p)
=>g.V().HasLabel("person").Values<object>("name").Order().Fold().Split<object>(Scope.Local,
"a").Unfold<object>()}},
+
{"g_V_hasLabelXpersonX_valueXnameX_order_fold_splitXlocal_emptyX_unfold", new
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>>
{(g,p)
=>g.V().HasLabel("person").Values<object>("name").Order().Fold().Split<object>(Scope.Local,
"").Unfold<object>()}},
{"g_injectXthat_this_testX_substringX1_8X", new
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>>
{(g,p) =>g.Inject<object>("test", "hello world", null).Substring(1, 8)}},
{"g_injectXListXa_bXcX_substringX1_2X", new
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>>
{(g,p) =>g.Inject<object>(p["xx1"]).Substring(1, 2)}},
{"g_V_hasLabelXpersonX_valueXnameX_substringX2X", new
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>>
{(g,p) =>g.V().HasLabel("software").Values<object>("name").Substring(2)}},
diff --git a/gremlin-go/driver/cucumber/gremlin.go
b/gremlin-go/driver/cucumber/gremlin.go
index bcb230d8a3..1097cb2a5d 100644
--- a/gremlin-go/driver/cucumber/gremlin.go
+++ b/gremlin-go/driver/cucumber/gremlin.go
@@ -1175,9 +1175,11 @@ var translationMap = map[string][]func(g
*gremlingo.GraphTraversalSource, p map[
"g_V_hasXname_vadasX_shortestPath_distanceXweightX_maxDistanceX1_3X":
{func(g *gremlingo.GraphTraversalSource, p map[string]interface{})
*gremlingo.GraphTraversal {return g.V().Has("name",
"vadas").ShortestPath().With("~tinkerpop.shortestPath.distance",
"weight").With("~tinkerpop.shortestPath.maxDistance", 1.3)}},
"g_injectXthat_this_testX_spiltXhX": {func(g
*gremlingo.GraphTraversalSource, p map[string]interface{})
*gremlingo.GraphTraversal {return g.Inject("that", "this", "test",
nil).Split("h")}},
"g_injectXhello_worldX_spiltXnullX": {func(g
*gremlingo.GraphTraversalSource, p map[string]interface{})
*gremlingo.GraphTraversal {return g.Inject("hello world").Split(nil)}},
+ "g_injectXthat_this_test_nullX_splitXemptyX": {func(g
*gremlingo.GraphTraversalSource, p map[string]interface{})
*gremlingo.GraphTraversal {return g.Inject("that", "this", "test",
nil).Split("")}},
"g_injectXListXa_bXcX_splitXa_bX": {func(g
*gremlingo.GraphTraversalSource, p map[string]interface{})
*gremlingo.GraphTraversal {return g.Inject(p["xx1"]).Split("a")}},
"g_V_hasLabelXpersonX_valueXnameX_splitXnullX": {func(g
*gremlingo.GraphTraversalSource, p map[string]interface{})
*gremlingo.GraphTraversal {return
g.V().HasLabel("person").Values("name").Split(nil)}},
"g_V_hasLabelXpersonX_valueXnameX_order_fold_splitXlocal_aX_unfold":
{func(g *gremlingo.GraphTraversalSource, p map[string]interface{})
*gremlingo.GraphTraversal {return
g.V().HasLabel("person").Values("name").Order().Fold().Split(gremlingo.Scope.Local,
"a").Unfold()}},
+ "g_V_hasLabelXpersonX_valueXnameX_order_fold_splitXlocal_emptyX_unfold":
{func(g *gremlingo.GraphTraversalSource, p map[string]interface{})
*gremlingo.GraphTraversal {return
g.V().HasLabel("person").Values("name").Order().Fold().Split(gremlingo.Scope.Local,
"").Unfold()}},
"g_injectXthat_this_testX_substringX1_8X": {func(g
*gremlingo.GraphTraversalSource, p map[string]interface{})
*gremlingo.GraphTraversal {return g.Inject("test", "hello world",
nil).Substring(1, 8)}},
"g_injectXListXa_bXcX_substringX1_2X": {func(g
*gremlingo.GraphTraversalSource, p map[string]interface{})
*gremlingo.GraphTraversal {return g.Inject(p["xx1"]).Substring(1, 2)}},
"g_V_hasLabelXpersonX_valueXnameX_substringX2X": {func(g
*gremlingo.GraphTraversalSource, p map[string]interface{})
*gremlingo.GraphTraversal {return
g.V().HasLabel("software").Values("name").Substring(2)}},
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 8e0a3c8598..2303335aae 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
@@ -1196,9 +1196,11 @@ const gremlins = {
g_V_hasXname_vadasX_shortestPath_distanceXweightX_maxDistanceX1_3X:
[function({g}) { return g.V().has("name",
"vadas").shortestPath().with_("~tinkerpop.shortestPath.distance",
"weight").with_("~tinkerpop.shortestPath.maxDistance", 1.3) }],
g_injectXthat_this_testX_spiltXhX: [function({g}) { return
g.inject("that", "this", "test", null).split("h") }],
g_injectXhello_worldX_spiltXnullX: [function({g}) { return g.inject("hello
world").split(null) }],
+ g_injectXthat_this_test_nullX_splitXemptyX: [function({g}) { return
g.inject("that", "this", "test", null).split("") }],
g_injectXListXa_bXcX_splitXa_bX: [function({g, xx1}) { return
g.inject(xx1).split("a") }],
g_V_hasLabelXpersonX_valueXnameX_splitXnullX: [function({g}) { return
g.V().hasLabel("person").values("name").split(null) }],
g_V_hasLabelXpersonX_valueXnameX_order_fold_splitXlocal_aX_unfold:
[function({g}) { return
g.V().hasLabel("person").values("name").order().fold().split(Scope.local,
"a").unfold() }],
+ g_V_hasLabelXpersonX_valueXnameX_order_fold_splitXlocal_emptyX_unfold:
[function({g}) { return
g.V().hasLabel("person").values("name").order().fold().split(Scope.local,
"").unfold() }],
g_injectXthat_this_testX_substringX1_8X: [function({g}) { return
g.inject("test", "hello world", null).substring(1, 8) }],
g_injectXListXa_bXcX_substringX1_2X: [function({g, xx1}) { return
g.inject(xx1).substring(1, 2) }],
g_V_hasLabelXpersonX_valueXnameX_substringX2X: [function({g}) { return
g.V().hasLabel("software").values("name").substring(2) }],
diff --git a/gremlin-python/src/main/python/radish/gremlin.py
b/gremlin-python/src/main/python/radish/gremlin.py
index 95114c84d3..b3b4abadc1 100644
--- a/gremlin-python/src/main/python/radish/gremlin.py
+++ b/gremlin-python/src/main/python/radish/gremlin.py
@@ -1178,9 +1178,11 @@ world.gremlins = {
'g_V_hasXname_vadasX_shortestPath_distanceXweightX_maxDistanceX1_3X':
[(lambda g:g.V().has('name',
'vadas').shortest_path().with_('~tinkerpop.shortestPath.distance',
'weight').with_('~tinkerpop.shortestPath.maxDistance', 1.3))],
'g_injectXthat_this_testX_spiltXhX': [(lambda g:g.inject('that', 'this',
'test', None).split('h'))],
'g_injectXhello_worldX_spiltXnullX': [(lambda g:g.inject('hello
world').split(None))],
+ 'g_injectXthat_this_test_nullX_splitXemptyX': [(lambda g:g.inject('that',
'this', 'test', None).split(''))],
'g_injectXListXa_bXcX_splitXa_bX': [(lambda g,
xx1=None:g.inject(xx1).split('a'))],
'g_V_hasLabelXpersonX_valueXnameX_splitXnullX': [(lambda
g:g.V().has_label('person').values('name').split(None))],
'g_V_hasLabelXpersonX_valueXnameX_order_fold_splitXlocal_aX_unfold':
[(lambda
g:g.V().has_label('person').values('name').order().fold().split(Scope.local,
'a').unfold())],
+ 'g_V_hasLabelXpersonX_valueXnameX_order_fold_splitXlocal_emptyX_unfold':
[(lambda
g:g.V().has_label('person').values('name').order().fold().split(Scope.local,
'').unfold())],
'g_injectXthat_this_testX_substringX1_8X': [(lambda g:g.inject('test',
'hello world', None).substring(1, 8))],
'g_injectXListXa_bXcX_substringX1_2X': [(lambda g,
xx1=None:g.inject(xx1).substring(1, 2))],
'g_V_hasLabelXpersonX_valueXnameX_substringX2X': [(lambda
g:g.V().has_label('software').values('name').substring(2))],
diff --git
a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/Split.feature
b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/Split.feature
index 54e04f14ba..3fa024adcd 100644
---
a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/Split.feature
+++
b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/Split.feature
@@ -45,6 +45,21 @@ Feature: Step - split()
| result |
| l[hello,world] |
+ @GraphComputerVerificationInjectionNotSupported
+ Scenario: g_injectXthat_this_test_nullX_splitXemptyX
+ Given the empty graph
+ And the traversal of
+ """
+ g.inject("that", "this", "test", null).split("")
+ """
+ When iterated to list
+ Then the result should be unordered
+ | result |
+ | l[t,h,a,t] |
+ | l[t,h,i,s] |
+ | l[t,e,s,t] |
+ | null |
+
@GraphComputerVerificationInjectionNotSupported
Scenario: g_injectXListXa_bXcX_splitXa_bX
Given the empty graph
@@ -83,3 +98,17 @@ Feature: Step - split()
| l[m,rko] |
| l[peter] |
| l[v,d,s] |
+
+ Scenario:
g_V_hasLabelXpersonX_valueXnameX_order_fold_splitXlocal_emptyX_unfold
+ Given the modern graph
+ And the traversal of
+ """
+
g.V().hasLabel("person").values("name").order().fold().split(Scope.local,
"").unfold()
+ """
+ When iterated to list
+ Then the result should be unordered
+ | result |
+ | l[j,o,s,h] |
+ | l[m,a,r,k,o] |
+ | l[p,e,t,e,r] |
+ | l[v,a,d,a,s] |
\ No newline at end of file