Repository: tinkerpop Updated Branches: refs/heads/tp32 eb1dfb8cb -> f55cb3593
added choose(predicate,traversal) which is a map to choose(predicate,traversal,identity()) and gives us if/then-semantics instead of always requiring if/then/else-semantics. Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/659865bd Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/659865bd Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/659865bd Branch: refs/heads/tp32 Commit: 659865bdb1a5e2db9e01847eb641101cab3d090a Parents: 1eac35b Author: Marko A. Rodriguez <okramma...@gmail.com> Authored: Mon Oct 31 13:23:42 2016 -0600 Committer: Marko A. Rodriguez <okramma...@gmail.com> Committed: Mon Oct 31 13:23:42 2016 -0600 ---------------------------------------------------------------------- CHANGELOG.asciidoc | 1 + docs/src/reference/the-traversal.asciidoc | 15 +++++++++++++-- docs/src/upgrade/release-3.2.x-incubating.asciidoc | 17 +++++++++++++++++ .../traversal/dsl/graph/GraphTraversal.java | 12 ++++++++++++ .../gremlin/process/traversal/dsl/graph/__.java | 14 ++++++++++++++ .../process/traversal/step/branch/BranchStep.java | 11 +++-------- .../traversal/step/branch/ChooseStepTest.java | 11 +++++++++-- .../traversal/step/branch/GroovyChooseTest.groovy | 5 +++++ .../process/traversal/step/branch/ChooseTest.java | 16 ++++++++++++++++ 9 files changed, 90 insertions(+), 12 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/659865bd/CHANGELOG.asciidoc ---------------------------------------------------------------------- diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc index cf8c007..328bc9d 100644 --- a/CHANGELOG.asciidoc +++ b/CHANGELOG.asciidoc @@ -26,6 +26,7 @@ image::https://raw.githubusercontent.com/apache/tinkerpop/master/docs/static/ima TinkerPop 3.2.4 (Release Date: NOT OFFICIALLY RELEASED YET) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +* Added `choose(predicate,traversal)` and `choose(traversal,traversal)` to effect if/then-semantics (no else). Equivalent to `choose(x,y,identity())`. * `SparkGraphComputer` no longer starts a worker iteration if the worker's partition is empty. * Added `ProjectStep.getProjectKeys()` for strategies that rely on such information. * Added `VertexFeatures.supportsDuplicateMultiProperties()` for graphs that only support unique values in multi-properties. http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/659865bd/docs/src/reference/the-traversal.asciidoc ---------------------------------------------------------------------- diff --git a/docs/src/reference/the-traversal.asciidoc b/docs/src/reference/the-traversal.asciidoc index c5c30a3..bbffb0e 100644 --- a/docs/src/reference/the-traversal.asciidoc +++ b/docs/src/reference/the-traversal.asciidoc @@ -449,7 +449,7 @@ Choose Step image::choose-step.png[width=700] The `choose()`-step (*branch*) routes the current traverser to a particular traversal branch option. With `choose()`, -it is possible to implement if/else-based semantics as well as more complicated selections. +it is possible to implement if/then/else-semantics as well as more complicated selections. [gremlin-groovy,modern] ---- @@ -466,7 +466,18 @@ g.V().hasLabel('person'). <1> If the traversal yields an element, then do `in`, else do `out` (i.e. true/false-based option selection). <2> Use the result of the traversal as a key to the map of traversal options (i.e. value-based option selection). -However, note that `choose()` can have an arbitrary number of options and moreover, can take an anonymous traversal as its choice function. +If the "false"-branch is not provided, then if/then-semantics are implemented. + +[gremlin-groovy,modern] +---- +g.V().choose(hasLabel('person'), out('created')).values('name') <1> +g.V().choose(hasLabel('person'), out('created'), identity()).values('name') <2> +---- + +<1> If the vertex is a person, emit the vertices they created, else emit the vertex. +<2> If/then/else with an `identity()` on the false-branch is equivalent to if/then with no false-branch. + +Note that `choose()` can have an arbitrary number of options and moreover, can take an anonymous traversal as its choice function. [gremlin-groovy,modern] ---- http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/659865bd/docs/src/upgrade/release-3.2.x-incubating.asciidoc ---------------------------------------------------------------------- diff --git a/docs/src/upgrade/release-3.2.x-incubating.asciidoc b/docs/src/upgrade/release-3.2.x-incubating.asciidoc index 30daae1..f121aa4 100644 --- a/docs/src/upgrade/release-3.2.x-incubating.asciidoc +++ b/docs/src/upgrade/release-3.2.x-incubating.asciidoc @@ -29,6 +29,23 @@ TinkerPop 3.2.4 Please see the link:https://github.com/apache/tinkerpop/blob/3.2.4/CHANGELOG.asciidoc#release-3-2-4[changelog] for a complete list of all the modifications that are part of this release. +Upgrading for Users +~~~~~~~~~~~~~~~~~~~ + +If/Then-Semantics with Choose Step +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Gremlin's `choose()`-step supports if/then/else-semantics. Thus, to effect if/then-semantics, `identity()` was required. +Thus, the following two traversals below are equivalent with the later being possible in this release. + +[source,groovy] +---- +g.V().choose(hasLabel('person'),out('created'),identity()) +g.V().choose(hasLabel('person'),out('created')) +---- + +See: link:https://issues.apache.org/jira/browse/TINKERPOP-1508[TINKERPOP-1508] + Upgrading for Providers ~~~~~~~~~~~~~~~~~~~~~~~ http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/659865bd/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.java ---------------------------------------------------------------------- diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.java index c8af8ca..088a4de 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.java @@ -1293,6 +1293,12 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> { return this.asAdmin().addStep(new ChooseStep<E, E2, Boolean>(this.asAdmin(), (Traversal.Admin<E, ?>) traversalPredicate, (Traversal.Admin<E, E2>) trueChoice, (Traversal.Admin<E, E2>) falseChoice)); } + public default <E2> GraphTraversal<S, E2> choose(final Traversal<?, ?> traversalPredicate, + final Traversal<?, E2> trueChoice) { + this.asAdmin().getBytecode().addStep(Symbols.choose, traversalPredicate, trueChoice); + return this.asAdmin().addStep(new ChooseStep<E, E2, Boolean>(this.asAdmin(), (Traversal.Admin<E, ?>) traversalPredicate, (Traversal.Admin<E, E2>) trueChoice, (Traversal.Admin<E, E2>) __.identity())); + } + public default <M, E2> GraphTraversal<S, E2> choose(final Function<E, M> choiceFunction) { this.asAdmin().getBytecode().addStep(Symbols.choose, choiceFunction); return this.asAdmin().addStep(new ChooseStep<>(this.asAdmin(), (Traversal.Admin<E, M>) __.map(new FunctionTraverser<>(choiceFunction)))); @@ -1304,6 +1310,12 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> { return this.asAdmin().addStep(new ChooseStep<E, E2, Boolean>(this.asAdmin(), (Traversal.Admin<E, ?>) __.filter(new PredicateTraverser<>(choosePredicate)), (Traversal.Admin<E, E2>) trueChoice, (Traversal.Admin<E, E2>) falseChoice)); } + public default <E2> GraphTraversal<S, E2> choose(final Predicate<E> choosePredicate, + final Traversal<?, E2> trueChoice) { + this.asAdmin().getBytecode().addStep(Symbols.choose, choosePredicate, trueChoice); + return this.asAdmin().addStep(new ChooseStep<E, E2, Boolean>(this.asAdmin(), (Traversal.Admin<E, ?>) __.filter(new PredicateTraverser<>(choosePredicate)), (Traversal.Admin<E, E2>) trueChoice, (Traversal.Admin<E, E2>) __.identity())); + } + public default <E2> GraphTraversal<S, E2> optional(final Traversal<?, E2> optionalTraversal) { this.asAdmin().getBytecode().addStep(Symbols.optional, optionalTraversal); return this.asAdmin().addStep(new ChooseStep<>(this.asAdmin(), (Traversal.Admin<E, ?>) optionalTraversal, (Traversal.Admin<E, E2>) optionalTraversal.asAdmin().clone(), (Traversal.Admin<E, E2>) __.<E2>identity())); http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/659865bd/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/__.java ---------------------------------------------------------------------- diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/__.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/__.java index 1349633..83739d8 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/__.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/__.java @@ -968,6 +968,13 @@ public class __ { } /** + * @see GraphTraversal#choose(Predicate, Traversal) + */ + public static <A, B> GraphTraversal<A, B> choose(final Predicate<A> choosePredicate, final Traversal<?, B> trueChoice) { + return __.<A>start().choose(choosePredicate, trueChoice); + } + + /** * @see GraphTraversal#choose(Function) */ public static <A, M, B> GraphTraversal<A, B> choose(final Function<A, M> choiceFunction) { @@ -989,6 +996,13 @@ public class __ { } /** + * @see GraphTraversal#choose(Traversal, Traversal) + */ + public static <A, M, B> GraphTraversal<A, B> choose(final Traversal<?, M> traversalPredicate, final Traversal<?, B> trueChoice) { + return __.<A>start().choose(traversalPredicate, trueChoice); + } + + /** * @see GraphTraversal#optional(Traversal) */ public static <A> GraphTraversal<A, A> optional(final Traversal<?, A> optionalTraversal) { http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/659865bd/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/BranchStep.java ---------------------------------------------------------------------- diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/BranchStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/BranchStep.java index 19df2a6..778722d 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/BranchStep.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/BranchStep.java @@ -113,17 +113,12 @@ public class BranchStep<S, E, M> extends ComputerAwareStep<S, E> implements Trav private final void handleStart(final Traverser.Admin<S> start) { final M choice = TraversalUtil.apply(start, this.branchTraversal); final List<Traversal.Admin<S, E>> branch = this.traversalOptions.containsKey(choice) ? this.traversalOptions.get(choice) : this.traversalOptions.get(Pick.none); - if (null != branch) { - branch.forEach(traversal -> { - traversal.addStart(start.split()); - }); - } + if (null != branch) + branch.forEach(traversal -> traversal.addStart(start.split())); if (choice != Pick.any) { final List<Traversal.Admin<S, E>> anyBranch = this.traversalOptions.get(Pick.any); if (null != anyBranch) - anyBranch.forEach(traversal -> { - traversal.addStart(start.split()); - }); + anyBranch.forEach(traversal -> traversal.addStart(start.split())); } } http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/659865bd/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/ChooseStepTest.java ---------------------------------------------------------------------- diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/ChooseStepTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/ChooseStepTest.java index ad2c8a8..885da77 100644 --- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/ChooseStepTest.java +++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/ChooseStepTest.java @@ -18,6 +18,7 @@ */ package org.apache.tinkerpop.gremlin.process.traversal.step.branch; +import org.apache.tinkerpop.gremlin.process.traversal.P; import org.apache.tinkerpop.gremlin.process.traversal.Traversal; import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__; import org.apache.tinkerpop.gremlin.process.traversal.step.StepTest; @@ -25,11 +26,14 @@ import org.apache.tinkerpop.gremlin.process.traversal.step.StepTest; import java.util.Arrays; import java.util.List; -import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.*; +import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.in; +import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.out; +import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.values; import static org.apache.tinkerpop.gremlin.process.traversal.step.TraversalOptionParent.Pick.none; /** * @author Daniel Kuppitz (http://gremlin.guru) + * @author Marko A. Rodriguez (http://markorodriguez.com) */ public class ChooseStepTest extends StepTest { @@ -38,7 +42,10 @@ public class ChooseStepTest extends StepTest { return Arrays.asList( __.choose(values("name")).option("marko", out()).option(none, in()), __.choose(values("name")).option("marko", in()).option(none, out()), - __.choose(values("name")).option("josh", out()).option(none, in()) + __.choose(values("name")).option("josh", out()).option(none, in()), + __.choose(out("knows").is(P.gt(0)), out("knows"), out("knows")), + __.choose(out("knows").is(P.gt(0)), out("knows"), out("created")), + __.choose(out("knows").is(P.gt(0)), out("knows")) ); } } http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/659865bd/gremlin-groovy-test/src/main/groovy/org/apache/tinkerpop/gremlin/process/traversal/step/branch/GroovyChooseTest.groovy ---------------------------------------------------------------------- diff --git a/gremlin-groovy-test/src/main/groovy/org/apache/tinkerpop/gremlin/process/traversal/step/branch/GroovyChooseTest.groovy b/gremlin-groovy-test/src/main/groovy/org/apache/tinkerpop/gremlin/process/traversal/step/branch/GroovyChooseTest.groovy index 99bb31b..6c6a4ac 100644 --- a/gremlin-groovy-test/src/main/groovy/org/apache/tinkerpop/gremlin/process/traversal/step/branch/GroovyChooseTest.groovy +++ b/gremlin-groovy-test/src/main/groovy/org/apache/tinkerpop/gremlin/process/traversal/step/branch/GroovyChooseTest.groovy @@ -53,5 +53,10 @@ public abstract class GroovyChooseTest { .option(none, identity()).name """) } + + @Override + public Traversal<Vertex, String> get_g_V_chooseXoutXknowsX_count_isXgtX0XX__outXknowsXX_name() { + new ScriptTraversal<>(g, "gremlin-groovy", "g.V.choose(out('knows').count.is(gt(0)), out('knows')).name") + } } } http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/659865bd/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/ChooseTest.java ---------------------------------------------------------------------- diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/ChooseTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/ChooseTest.java index ce12daf..8938bec 100644 --- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/ChooseTest.java +++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/ChooseTest.java @@ -21,6 +21,7 @@ package org.apache.tinkerpop.gremlin.process.traversal.step.branch; import org.apache.tinkerpop.gremlin.LoadGraphWith; import org.apache.tinkerpop.gremlin.process.AbstractGremlinProcessTest; import org.apache.tinkerpop.gremlin.process.GremlinProcessRunner; +import org.apache.tinkerpop.gremlin.process.traversal.P; import org.apache.tinkerpop.gremlin.process.traversal.Traversal; import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalOptionParent; import org.apache.tinkerpop.gremlin.process.traversal.step.util.MapHelper; @@ -58,6 +59,8 @@ public abstract class ChooseTest extends AbstractGremlinProcessTest { public abstract Traversal<Vertex, String> get_g_V_chooseXlabelX_optionXblah__outXknowsXX_optionXbleep__outXcreatedXX_optionXnone__identityX_name(); + public abstract Traversal<Vertex, String> get_g_V_chooseXoutXknowsX_count_isXgtX0XX__outXknowsXX_name(); + @Test @LoadGraphWith(MODERN) public void g_V_chooseXout_countX_optionX2L__nameX_optionX3L__valueMapX() { @@ -100,6 +103,14 @@ public abstract class ChooseTest extends AbstractGremlinProcessTest { checkResults(Arrays.asList("marko", "vadas", "peter", "josh", "lop", "ripple"), traversal); } + @Test + @LoadGraphWith(MODERN) + public void g_V_chooseXoutXknowsX_count_isXgtX0XX__outXknowsXX_name() { + final Traversal<Vertex, String> traversal = get_g_V_chooseXoutXknowsX_count_isXgtX0XX__outXknowsXX_name(); + printTraversalForm(traversal); + checkResults(Arrays.asList("vadas", "josh", "vadas", "josh", "peter", "lop", "ripple"), traversal); + } + public static class Traversals extends ChooseTest { @Override @@ -126,5 +137,10 @@ public abstract class ChooseTest extends AbstractGremlinProcessTest { .option("bleep", out("created")) .option(TraversalOptionParent.Pick.none, identity()).values("name"); } + + @Override + public Traversal<Vertex, String> get_g_V_chooseXoutXknowsX_count_isXgtX0XX__outXknowsXX_name() { + return g.V().choose(out("knows").count().is(P.gt(0)), out("knows")).values("name"); + } } } \ No newline at end of file