updated Path.subGraph() so the semantics are Pop.last like select, match, where, etc. Smart @dkuppitz.
Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/9160573a Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/9160573a Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/9160573a Branch: refs/heads/TINKERPOP-1625 Commit: 9160573a7aeda2480903b1e3b31f3eaea5944038 Parents: 9ffd250 Author: Marko A. Rodriguez <[email protected]> Authored: Thu Mar 23 09:49:45 2017 -0600 Committer: Marko A. Rodriguez <[email protected]> Committed: Thu Mar 23 09:49:45 2017 -0600 ---------------------------------------------------------------------- .../gremlin/process/traversal/Path.java | 49 +++++++++++++------- .../gremlin/process/traversal/PathTest.java | 18 +++++-- 2 files changed, 46 insertions(+), 21 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/9160573a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Path.java ---------------------------------------------------------------------- diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Path.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Path.java index 91e0c05..1119775 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Path.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Path.java @@ -242,6 +242,8 @@ public interface Path extends Cloneable, Iterable<Object> { /** * Isolate a sub-path from the path object. The isolation is based solely on the path labels. * The to-label is inclusive. Thus, from "b" to "c" would isolate the example path as follows {@code a,[b,c],d}. + * Note that if there are multiple path segments with the same label, then its the last occurrence that is isolated. + * For instance, from "b" to "c" would be {@code a,b,[b,c,d,c]}. * * @param fromLabel The label to start recording the sub-path from. * @param toLabel The label to end recording the sub-path to. @@ -253,24 +255,31 @@ public interface Path extends Cloneable, Iterable<Object> { else { Path subPath = MutablePath.make(); final int size = this.size(); - boolean record = false; - for (int i = 0; i < size; i++) { + int fromIndex = -1; + int toIndex = -1; + for (int i = size - 1; i >= 0; i--) { final Set<String> labels = this.labels().get(i); - if (!record && (labels.contains(fromLabel) || null == fromLabel)) - record = true; - if (record) - subPath = subPath.extend(this.get(i), labels); - if (labels.contains(toLabel)) { - if (!record) - throw Path.Exceptions.couldNotLocalPathFromLabel(fromLabel); - else - return subPath; - } + if (-1 == fromIndex && labels.contains(fromLabel)) + fromIndex = i; + if (-1 == toIndex && labels.contains(toLabel)) + toIndex = i; + } + if (null != fromLabel && -1 == fromIndex) + throw Path.Exceptions.couldNotLocatePathFromLabel(fromLabel); + if (null != toLabel && -1 == toIndex) + throw Path.Exceptions.couldNotLocatePathToLabel(toLabel); + + if (fromIndex == -1) + fromIndex = 0; + if (toIndex == -1) + toIndex = size-1; + if (fromIndex > toIndex) + throw Path.Exceptions.couldNotIsolatedSubPath(fromLabel, toLabel); + for (int i = fromIndex; i <= toIndex; i++) { + final Set<String> labels = this.labels().get(i); + subPath.extend(this.get(i), labels); } - if (null == toLabel) - return subPath; - else - throw Path.Exceptions.couldNotLocalPathToLabel(toLabel); + return subPath; } } @@ -280,12 +289,16 @@ public interface Path extends Cloneable, Iterable<Object> { return new IllegalArgumentException("The step with label " + label + " does not exist"); } - public static IllegalArgumentException couldNotLocalPathFromLabel(final String fromLabel) { + public static IllegalArgumentException couldNotLocatePathFromLabel(final String fromLabel) { return new IllegalArgumentException("Could not locate path from-label: " + fromLabel); } - public static IllegalArgumentException couldNotLocalPathToLabel(final String toLabel) { + public static IllegalArgumentException couldNotLocatePathToLabel(final String toLabel) { return new IllegalArgumentException("Could not locate path to-label: " + toLabel); } + + public static IllegalArgumentException couldNotIsolatedSubPath(final String fromLabel, final String toLabel) { + return new IllegalArgumentException("Could not isolate path because from comes after to: " + fromLabel + "->" + toLabel); + } } } http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/9160573a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/PathTest.java ---------------------------------------------------------------------- diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/PathTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/PathTest.java index 590ce69..ce21732 100644 --- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/PathTest.java +++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/PathTest.java @@ -428,6 +428,18 @@ public class PathTest { assertTrue(subPath.labels().get(1).contains("d")); assertEquals(1, subPath.labels().get(1).size()); /// + subPath = path.subPath("c",null); + assertEquals(2, subPath.size()); + assertEquals(2, subPath.objects().size()); + assertEquals(2, subPath.labels().size()); + assertEquals("matthias", subPath.objects().get(0)); + assertEquals("bob", subPath.objects().get(1)); + assertTrue(subPath.labels().get(0).contains("c")); + assertTrue(subPath.labels().get(0).contains("x")); + assertEquals(2, subPath.labels().get(0).size()); + assertTrue(subPath.labels().get(1).contains("d")); + assertEquals(1, subPath.labels().get(1).size()); + /// subPath = path.subPath("a","d"); assertEquals(4, subPath.size()); assertEquals(4, subPath.objects().size()); @@ -437,21 +449,21 @@ public class PathTest { subPath = path.subPath("d", "a"); fail("Path labels must be ordered along path"); } catch (final IllegalArgumentException e) { - assertTrue(true); + assertEquals(Path.Exceptions.couldNotIsolatedSubPath("d","a").getMessage(), e.getMessage()); } /// try { subPath = path.subPath("a", "e"); fail("End path label was not found"); } catch (final IllegalArgumentException e) { - assertEquals(Path.Exceptions.couldNotLocalPathToLabel("e").getMessage(), e.getMessage()); + assertEquals(Path.Exceptions.couldNotLocatePathToLabel("e").getMessage(), e.getMessage()); } /// try { subPath = path.subPath("e", "b"); fail("Start path label was not found"); } catch (final IllegalArgumentException e) { - assertEquals(Path.Exceptions.couldNotLocalPathFromLabel("e").getMessage(), e.getMessage()); + assertEquals(Path.Exceptions.couldNotLocatePathFromLabel("e").getMessage(), e.getMessage()); } }); }
