added test support for simplePath() and cyclicPath() by()/to()/from(). Really cool. Works great and makes sense. Updated this-traversal.asciidoc with examples.
Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/35ecf8c0 Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/35ecf8c0 Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/35ecf8c0 Branch: refs/heads/TINKERPOP-1625 Commit: 35ecf8c0f56139953187769ee719c95b66cfa477 Parents: 8ec49c4 Author: Marko A. Rodriguez <okramma...@gmail.com> Authored: Thu Mar 16 10:03:28 2017 -0600 Committer: Marko A. Rodriguez <okramma...@gmail.com> Committed: Thu Mar 16 10:03:28 2017 -0600 ---------------------------------------------------------------------- docs/src/reference/the-traversal.asciidoc | 10 ++++++ .../gremlin/process/traversal/Path.java | 7 ++-- .../traversal/step/filter/PathFilterStep.java | 3 +- .../process/traversal/step/map/PathStep.java | 2 +- .../optimization/FilterRankingStrategy.java | 37 ++++---------------- .../gremlin/process/traversal/PathTest.java | 17 +++++++++ .../step/filter/GroovySimplePathTest.groovy | 5 +++ .../traversal/step/filter/SimplePathTest.java | 29 +++++++++++++-- 8 files changed, 71 insertions(+), 39 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/35ecf8c0/docs/src/reference/the-traversal.asciidoc ---------------------------------------------------------------------- diff --git a/docs/src/reference/the-traversal.asciidoc b/docs/src/reference/the-traversal.asciidoc index 75d740f..c333373 100644 --- a/docs/src/reference/the-traversal.asciidoc +++ b/docs/src/reference/the-traversal.asciidoc @@ -2032,6 +2032,16 @@ objects in it, the traverser is filtered. If cyclic behavior is desired, see <<c g.V(1).both().both() g.V(1).both().both().simplePath() g.V(1).both().both().simplePath().path() +g.V().out().as('a').out().as('b').out().as('c'). + simplePath().by(label). + path() +g.V().out().as('a').out().as('b').out().as('c'). + simplePath(). + by(label). + from('b'). + to('c'). + path(). + by('name') ---- [[store-step]] http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/35ecf8c0/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 cefe7d9..d231a52 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 @@ -252,18 +252,19 @@ public interface Path extends Cloneable, Iterable<Object> { return this; else { Path subPath = MutablePath.make(); - boolean record = false; int size = this.size(); + boolean record = false; for (int i = 0; i < size; i++) { final Set<String> labels = this.labels().get(i); - if (labels.contains(fromLabel) || null == fromLabel) + 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); - return subPath; + else + return subPath; } } if (null == toLabel) http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/35ecf8c0/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/PathFilterStep.java ---------------------------------------------------------------------- diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/PathFilterStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/PathFilterStep.java index e8e0607..b9583fa 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/PathFilterStep.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/PathFilterStep.java @@ -56,14 +56,13 @@ public final class PathFilterStep<S> extends FilterStep<S> implements FromToModu @Override protected boolean filter(final Traverser.Admin<S> traverser) { final Path path = traverser.path().getSubPath(this.fromLabel, this.toLabel); - this.traversalRing.reset(); if (this.traversalRing.isEmpty()) return path.isSimple() == this.isSimple; else { + this.traversalRing.reset(); final Path byPath = MutablePath.make(); path.forEach((object, labels) -> byPath.extend(TraversalUtil.applyNullable(object, this.traversalRing.next()), labels)); return byPath.isSimple() == this.isSimple; - } } http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/35ecf8c0/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/PathStep.java ---------------------------------------------------------------------- diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/PathStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/PathStep.java index 06ff947..6b030f9 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/PathStep.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/PathStep.java @@ -52,10 +52,10 @@ public final class PathStep<S> extends MapStep<S, Path> implements TraversalPare @Override protected Path map(final Traverser.Admin<S> traverser) { final Path path = traverser.path().getSubPath(this.fromLabel, this.toLabel); - this.traversalRing.reset(); if (this.traversalRing.isEmpty()) return path; else { + this.traversalRing.reset(); final Path byPath = MutablePath.make(); path.forEach((object, labels) -> byPath.extend(TraversalUtil.applyNullable(object, this.traversalRing.next()), labels)); return byPath; http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/35ecf8c0/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/FilterRankingStrategy.java ---------------------------------------------------------------------- diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/FilterRankingStrategy.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/FilterRankingStrategy.java index 6ca676a..bec2502 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/FilterRankingStrategy.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/FilterRankingStrategy.java @@ -32,7 +32,6 @@ import org.apache.tinkerpop.gremlin.process.traversal.step.filter.HasStep; import org.apache.tinkerpop.gremlin.process.traversal.step.filter.IsStep; import org.apache.tinkerpop.gremlin.process.traversal.step.filter.NotStep; import org.apache.tinkerpop.gremlin.process.traversal.step.filter.OrStep; -import org.apache.tinkerpop.gremlin.process.traversal.step.filter.PathFilterStep; import org.apache.tinkerpop.gremlin.process.traversal.step.filter.TraversalFilterStep; import org.apache.tinkerpop.gremlin.process.traversal.step.filter.WherePredicateStep; import org.apache.tinkerpop.gremlin.process.traversal.step.filter.WhereTraversalStep; @@ -48,26 +47,6 @@ import java.util.Set; * FilterRankingStrategy reorders filter- and order-steps according to their rank. It will also do its best to push * step labels as far "right" as possible in order to keep traversers as small and bulkable as possible prior to the * absolute need for path-labeling. - * <p/> - * <table> - * <thead> - * <tr><th>Step</th><th>Rank</th></tr> - * </thead> - * <tbody> - * <tr><td>is(predicate)</td><td>1</td></tr> - * <tr><td>has(predicate)</td><td>2</td></tr> - * <tr><td>where(predicate)</td><td>3</td></tr> - * <tr><td>simplePath()</td><td>4</td></tr> - * <tr><td>cyclicPath()</td><td>4</td></tr> - * <tr><td>filter(traversal)</td><td>5</td></tr> - * <tr><td>not(traversal)</td>td>5</td></tr> - * <tr><td>where(traversal)</td><td>6</td></tr> - * <tr><td>or(...)</td><td>7</td></tr> - * <tr><td>and(...)</td><td>8</td></tr> - * <tr><td>dedup()</td><td>9</td></tr> - * <tr><td>order()</td><td>10</td></tr> - * </tbody> - * </table> * * @author Daniel Kuppitz (http://gremlin.guru) * @author Marko A. Rodriguez (http://markorodriguez.com) @@ -128,22 +107,20 @@ public final class FilterRankingStrategy extends AbstractTraversalStrategy<Trave rank = 2; else if (step instanceof WherePredicateStep && ((WherePredicateStep) step).getLocalChildren().isEmpty()) rank = 3; - else if (step instanceof PathFilterStep) - rank = 4; else if (step instanceof TraversalFilterStep || step instanceof NotStep) - rank = 5; + rank = 4; else if (step instanceof WhereTraversalStep) - rank = 6; + rank = 5; else if (step instanceof OrStep) - rank = 7; + rank = 6; else if (step instanceof AndStep) - rank = 8; + rank = 7; else if (step instanceof WherePredicateStep) // has by()-modulation - rank = 9; + rank = 8; else if (step instanceof DedupGlobalStep) - rank = 10; + rank = 9; else if (step instanceof OrderGlobalStep) - rank = 11; + rank = 10; else return 0; //////////// http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/35ecf8c0/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 1d21074..1f7ec85 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 @@ -416,6 +416,23 @@ public class PathTest { assertEquals(1, subPath.labels().size()); assertEquals("stephen", subPath.objects().get(0)); /// + subPath = path.getSubPath("c", "d"); + 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.getSubPath("a","d"); + assertEquals(4, subPath.size()); + assertEquals(4, subPath.objects().size()); + assertEquals(4, subPath.labels().size()); + /// try { subPath = path.getSubPath("d", "a"); fail("Path labels must be ordered along path"); http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/35ecf8c0/gremlin-groovy-test/src/main/groovy/org/apache/tinkerpop/gremlin/process/traversal/step/filter/GroovySimplePathTest.groovy ---------------------------------------------------------------------- diff --git a/gremlin-groovy-test/src/main/groovy/org/apache/tinkerpop/gremlin/process/traversal/step/filter/GroovySimplePathTest.groovy b/gremlin-groovy-test/src/main/groovy/org/apache/tinkerpop/gremlin/process/traversal/step/filter/GroovySimplePathTest.groovy index e1206df..e0d813f 100644 --- a/gremlin-groovy-test/src/main/groovy/org/apache/tinkerpop/gremlin/process/traversal/step/filter/GroovySimplePathTest.groovy +++ b/gremlin-groovy-test/src/main/groovy/org/apache/tinkerpop/gremlin/process/traversal/step/filter/GroovySimplePathTest.groovy @@ -39,5 +39,10 @@ public abstract class GroovySimplePathTest { public Traversal<Vertex, Path> get_g_V_repeatXboth_simplePathX_timesX3X_path() { new ScriptTraversal<>(g, "gremlin-groovy", "g.V.repeat(__.both.simplePath).times(3).path()"); } + + @Override + public Traversal<Vertex, Path> get_g_V_asXaX_out_asXbX_out_asXcX_simplePath_byXlabelX_fromXbX_toXcX_path_byXnameX() { + new ScriptTraversal<>(g, "gremlin-groovy", "g.V.as('a').out.as('b').out.as('c').simplePath.by(label).from('b').to('c').path.by('name')") + } } } http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/35ecf8c0/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/SimplePathTest.java ---------------------------------------------------------------------- diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/SimplePathTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/SimplePathTest.java index 7e2d8d3..f51478e 100644 --- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/SimplePathTest.java +++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/SimplePathTest.java @@ -23,14 +23,20 @@ import org.apache.tinkerpop.gremlin.process.AbstractGremlinProcessTest; import org.apache.tinkerpop.gremlin.process.GremlinProcessRunner; import org.apache.tinkerpop.gremlin.process.traversal.Path; import org.apache.tinkerpop.gremlin.process.traversal.Traversal; -import org.apache.tinkerpop.gremlin.process.traversal.TraversalEngine; +import org.apache.tinkerpop.gremlin.process.traversal.step.util.MutablePath; +import org.apache.tinkerpop.gremlin.structure.T; import org.apache.tinkerpop.gremlin.structure.Vertex; import org.junit.Test; import org.junit.runner.RunWith; +import java.util.Arrays; +import java.util.Collections; + import static org.apache.tinkerpop.gremlin.LoadGraphWith.GraphData.MODERN; -import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.*; -import static org.junit.Assert.*; +import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.both; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; /** * @author Marko A. Rodriguez (http://markorodriguez.com) @@ -42,6 +48,8 @@ public abstract class SimplePathTest extends AbstractGremlinProcessTest { public abstract Traversal<Vertex, Path> get_g_V_repeatXboth_simplePathX_timesX3X_path(); + public abstract Traversal<Vertex, Path> get_g_V_asXaX_out_asXbX_out_asXcX_simplePath_byXlabelX_fromXbX_toXcX_path_byXnameX(); + @Test @LoadGraphWith(MODERN) public void g_VX1X_outXcreatedX_inXcreatedX_simplePath() { @@ -71,6 +79,16 @@ public abstract class SimplePathTest extends AbstractGremlinProcessTest { assertFalse(traversal.hasNext()); } + @Test + @LoadGraphWith(MODERN) + public void g_V_asXaX_out_asXbX_out_asXcX_simplePath_byXlabelX_fromXbX_toXcX_path_byXnameX() { + final Traversal<Vertex, Path> traversal = get_g_V_asXaX_out_asXbX_out_asXcX_simplePath_byXlabelX_fromXbX_toXcX_path_byXnameX(); + printTraversalForm(traversal); + checkResults(Arrays.asList( + MutablePath.make().extend("marko", Collections.singleton("a")).extend("josh", Collections.singleton("b")).extend("ripple", Collections.singleton("c")), + MutablePath.make().extend("marko", Collections.singleton("a")).extend("josh", Collections.singleton("b")).extend("lop", Collections.singleton("c"))), traversal); + } + public static class Traversals extends SimplePathTest { @Override public Traversal<Vertex, Vertex> get_g_VX1X_outXcreatedX_inXcreatedX_simplePath(final Object v1Id) { @@ -82,5 +100,10 @@ public abstract class SimplePathTest extends AbstractGremlinProcessTest { public Traversal<Vertex, Path> get_g_V_repeatXboth_simplePathX_timesX3X_path() { return g.V().repeat(both().simplePath()).times(3).path(); } + + @Override + public Traversal<Vertex, Path> get_g_V_asXaX_out_asXbX_out_asXcX_simplePath_byXlabelX_fromXbX_toXcX_path_byXnameX() { + return g.V().as("a").out().as("b").out().as("c").simplePath().by(T.label).from("b").to("c").path().by("name"); + } } }