This is an automated email from the ASF dual-hosted git repository.

dkuppitz pushed a commit to branch TINKERPOP-1084
in repository https://gitbox.apache.org/repos/asf/tinkerpop.git

commit 9a6bf66556f41bdd44b650e36817634b04161cc8
Author: Daniel Kuppitz <daniel_kupp...@hotmail.com>
AuthorDate: Mon Jun 10 12:45:16 2019 -0700

    TINKERPOP-1084 Allow predicates and traversals to be used as options in 
`BranchStep`.
---
 CHANGELOG.asciidoc                                 |   1 +
 docs/src/upgrade/release-3.3.x.asciidoc            |  30 +++++
 .../traversal/lambda/PredicateTraversal.java       |  68 ++++++++++
 .../process/traversal/step/branch/BranchStep.java  | 139 +++++++++++----------
 .../process/traversal/step/branch/ChooseStep.java  |  10 +-
 .../process/traversal/step/branch/UnionStep.java   |   2 +-
 gremlin-test/features/branch/Branch.feature        |  37 +++++-
 .../process/traversal/step/ComplexTest.java        |  46 ++++++-
 .../process/traversal/step/branch/BranchTest.java  |  47 +++++++
 .../tinkergraph/structure/TinkerGraphPlayTest.java |  26 +++-
 10 files changed, 323 insertions(+), 83 deletions(-)

diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc
index 88e8a44..0cd6c8a 100644
--- a/CHANGELOG.asciidoc
+++ b/CHANGELOG.asciidoc
@@ -35,6 +35,7 @@ 
image::https://raw.githubusercontent.com/apache/tinkerpop/master/docs/static/ima
 * Fixed bug in `MatchStep` where the correct was not properly determined.
 * Fixed bug where client/server exception mismatch when server throw 
StackOverflowError
 * Prevent exception when closing a session that doesn't exist
+* Allow predicates and traversals to be used as options in `BranchStep`.
 
 [[release-3-3-7]]
 === TinkerPop 3.3.7 (Release Date: May 28, 2019)
diff --git a/docs/src/upgrade/release-3.3.x.asciidoc 
b/docs/src/upgrade/release-3.3.x.asciidoc
index 51da497..d0fdfb4 100644
--- a/docs/src/upgrade/release-3.3.x.asciidoc
+++ b/docs/src/upgrade/release-3.3.x.asciidoc
@@ -27,6 +27,36 @@ 
image::https://raw.githubusercontent.com/apache/tinkerpop/master/docs/static/ima
 
 Please see the 
link:https://github.com/apache/tinkerpop/blob/3.3.8/CHANGELOG.asciidoc#release-3-3-8[changelog]
 for a complete list of all the modifications that are part of this release.
 
+== Upgrading for Users
+
+==== Branch Steps accept Predicates and Traversals
+
+Prior to this version, branch steps (in particular `BranchStep` and 
`ChooseStep`) could only handle constant values and `Pick` tokens. Starting in 
this version, these steps will also accept
+predicates and traversals as show in the example below.
+
+[source,text]
+----
+gremlin> g = TinkerFactory.createModern().traversal()
+==>graphtraversalsource[tinkergraph[vertices:6 edges:6], standard]
+gremlin> g.V().hasLabel("person").
+......1>   group().
+......2>     by("name").
+......3>     by(branch(values("age")).
+......4>          option(29, constant("almost old")).
+......5>          option(__.is(32), constant("looks like josh")).
+......6>          option(lt(29), constant("pretty young")).
+......7>          option(lt(35), constant("younger than peter")).
+......8>          option(gte(30), constant("pretty old")).
+......9>          option(none, constant("mysterious")).fold()).
+.....10>   unfold()
+==>peter=[pretty old]
+==>vadas=[pretty young, younger than peter]
+==>josh=[looks like josh, younger than peter, pretty old]
+==>marko=[almost old, younger than peter]
+----
+
+See: link:https://issues.apache.org/jira/browse/TINKERPOP-1084[TINKERPOP-1084]
+
 
 == TinkerPop 3.3.7
 
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/lambda/PredicateTraversal.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/lambda/PredicateTraversal.java
new file mode 100644
index 0000000..603ac50
--- /dev/null
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/lambda/PredicateTraversal.java
@@ -0,0 +1,68 @@
+/*
+ * 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.process.traversal.lambda;
+
+import org.apache.tinkerpop.gremlin.process.traversal.P;
+import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
+import 
org.apache.tinkerpop.gremlin.process.traversal.util.FastNoSuchElementException;
+
+import java.util.function.Predicate;
+
+/**
+ * @author Daniel Kuppitz (http://gremlin.guru)
+ */
+public final class PredicateTraversal<S> extends AbstractLambdaTraversal<S, S> 
{
+
+    private final Predicate predicate;
+    private S s;
+    private boolean pass;
+
+    public PredicateTraversal(final Object value) {
+        this.predicate = value instanceof Predicate ? (Predicate) value : 
P.eq(value);
+    }
+
+    @Override
+    public S next() {
+        if (this.pass)
+            return this.s;
+        throw FastNoSuchElementException.instance();
+    }
+
+    @Override
+    public boolean hasNext() {
+        return this.pass;
+    }
+
+    @Override
+    public void addStart(final Traverser.Admin<S> start) {
+        //noinspection unchecked
+        this.pass = this.predicate.test(this.s = start.get());
+    }
+
+    @Override
+    public String toString() {
+        return "(" + this.predicate.toString() + ")";
+    }
+
+    @Override
+    public int hashCode() {
+        return this.getClass().hashCode() ^ this.predicate.hashCode();
+    }
+}
+
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 e35d51e..d92ce2d 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
@@ -18,8 +18,10 @@
  */
 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.Traverser;
+import 
org.apache.tinkerpop.gremlin.process.traversal.lambda.PredicateTraversal;
 import org.apache.tinkerpop.gremlin.process.traversal.step.Barrier;
 import 
org.apache.tinkerpop.gremlin.process.traversal.step.TraversalOptionParent;
 import 
org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.IdentityStep;
@@ -30,7 +32,7 @@ import 
org.apache.tinkerpop.gremlin.process.traversal.util.FastNoSuchElementExce
 import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper;
 import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalUtil;
 import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
-import org.apache.tinkerpop.gremlin.util.NumberHelper;
+import org.javatuples.Pair;
 
 import java.util.ArrayList;
 import java.util.Collections;
@@ -39,17 +41,22 @@ import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.function.Predicate;
 import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
 /**
  * @author Marko A. Rodriguez (http://markorodriguez.com)
+ * @author Daniel Kuppitz (http://gremlin.guru)
  */
 public class BranchStep<S, E, M> extends ComputerAwareStep<S, E> implements 
TraversalOptionParent<M, S, E> {
 
     protected Traversal.Admin<S, M> branchTraversal;
-    protected Map<Object, List<Traversal.Admin<S, E>>> traversalOptions = new 
HashMap<>();
+    protected Map<Pick, List<Traversal.Admin<S, E>>> traversalPickOptions = 
new HashMap<>();
+    protected List<Pair<Traversal.Admin, Traversal.Admin<S, E>>> 
traversalOptions = new ArrayList<>();
+
     private boolean first = true;
-    private boolean hasBarrier = false;
+    private boolean hasBarrier;
 
     public BranchStep(final Traversal.Admin traversal) {
         super(traversal);
@@ -61,12 +68,20 @@ public class BranchStep<S, E, M> extends 
ComputerAwareStep<S, E> implements Trav
 
     @Override
     public void addGlobalChildOption(final M pickToken, final 
Traversal.Admin<S, E> traversalOption) {
-        final Object pickTokenKey = PickTokenKey.make(pickToken);
-        if (this.traversalOptions.containsKey(pickTokenKey))
-            this.traversalOptions.get(pickTokenKey).add(traversalOption);
-        else
-            this.traversalOptions.put(pickTokenKey, new 
ArrayList<>(Collections.singletonList(traversalOption)));
-
+        if (pickToken instanceof Pick) {
+            if (this.traversalPickOptions.containsKey(pickToken))
+                this.traversalPickOptions.get(pickToken).add(traversalOption);
+            else
+                this.traversalPickOptions.put((Pick) pickToken, new 
ArrayList<>(Collections.singletonList(traversalOption)));
+        } else {
+            final Traversal.Admin pickOptionTraversal;
+            if (pickToken instanceof Traversal) {
+                pickOptionTraversal = ((Traversal) pickToken).asAdmin();
+            } else {
+                pickOptionTraversal = new PredicateTraversal(pickToken);
+            }
+            this.traversalOptions.add(Pair.with(pickOptionTraversal, 
traversalOption));
+        }
         // adding an IdentityStep acts as a placeholder when reducing barriers 
get in the way - see the
         // standardAlgorithm() method for more information.
         if 
(TraversalHelper.hasStepOfAssignableClass(ReducingBarrierStep.class, 
traversalOption))
@@ -85,9 +100,9 @@ public class BranchStep<S, E, M> extends 
ComputerAwareStep<S, E> implements Trav
 
     @Override
     public List<Traversal.Admin<S, E>> getGlobalChildren() {
-        return 
Collections.unmodifiableList(this.traversalOptions.values().stream()
-                .flatMap(List::stream)
-                .collect(Collectors.toList()));
+        return Collections.unmodifiableList(Stream.concat(
+                
this.traversalPickOptions.values().stream().flatMap(List::stream),
+                
this.traversalOptions.stream().map(Pair::getValue1)).collect(Collectors.toList()));
     }
 
     @Override
@@ -107,11 +122,9 @@ public class BranchStep<S, E, M> extends 
ComputerAwareStep<S, E> implements Trav
                 // traverser as part of the condition for using that traversal 
option in the output. This is necessary
                 // because barriers like fold(), max(), etc. will always 
return true for hasNext() even if a traverser
                 // was not seeded in applyCurrentTraverser().
-                for (final List<Traversal.Admin<S, E>> options : 
this.traversalOptions.values()) {
-                    for (final Traversal.Admin<S, E> option : options) {
-                        if (option.getStartStep().hasNext() && 
option.hasNext())
-                            return option.getEndStep();
-                    }
+                for (final Traversal.Admin<S, E> option : getGlobalChildren()) 
{
+                    if (option.getStartStep().hasNext() && option.hasNext())
+                        return option.getEndStep();
                 }
             }
 
@@ -138,17 +151,16 @@ public class BranchStep<S, E, M> extends 
ComputerAwareStep<S, E> implements Trav
     private void applyCurrentTraverser(final Traverser.Admin<S> start) {
         // first get the value of the choice based on the current traverser 
and use that to select the right traversal
         // option to which that traverser should be routed
-        final Object choice = PickTokenKey.make(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);
+        final Object choice = TraversalUtil.apply(start, this.branchTraversal);
+        final List<Traversal.Admin<S, E>> branches = pickBranches(choice);
 
         // if a branch is identified, then split the traverser and add it to 
the start of the option so that when
         // that option is iterated (in the calling method) that value can be 
applied.
-        if (null != branch)
-            branch.forEach(traversal -> traversal.addStart(start.split()));
+        if (null != branches)
+            branches.forEach(traversal -> traversal.addStart(start.split()));
 
         if (choice != Pick.any) {
-            final List<Traversal.Admin<S, E>> anyBranch = 
this.traversalOptions.get(Pick.any);
+            final List<Traversal.Admin<S, E>> anyBranch = 
this.traversalPickOptions.get(Pick.any);
             if (null != anyBranch)
                 anyBranch.forEach(traversal -> 
traversal.addStart(start.split()));
         }
@@ -158,10 +170,10 @@ public class BranchStep<S, E, M> extends 
ComputerAwareStep<S, E> implements Trav
     protected Iterator<Traverser.Admin<E>> computerAlgorithm() {
         final List<Traverser.Admin<E>> ends = new ArrayList<>();
         final Traverser.Admin<S> start = this.starts.next();
-        final Object choice = PickTokenKey.make(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 -> {
+        final Object choice = TraversalUtil.apply(start, this.branchTraversal);
+        final List<Traversal.Admin<S, E>> branches = pickBranches(choice);
+        if (null != branches) {
+            branches.forEach(traversal -> {
                 final Traverser.Admin<E> split = (Traverser.Admin<E>) 
start.split();
                 split.setStepId(traversal.getStartStep().getId());
                 //split.addLabels(this.labels);
@@ -169,7 +181,7 @@ public class BranchStep<S, E, M> extends 
ComputerAwareStep<S, E> implements Trav
             });
         }
         if (choice != Pick.any) {
-            final List<Traversal.Admin<S, E>> anyBranch = 
this.traversalOptions.get(Pick.any);
+            final List<Traversal.Admin<S, E>> anyBranch = 
this.traversalPickOptions.get(Pick.any);
             if (null != anyBranch) {
                 anyBranch.forEach(traversal -> {
                     final Traverser.Admin<E> split = (Traverser.Admin<E>) 
start.split();
@@ -182,20 +194,39 @@ public class BranchStep<S, E, M> extends 
ComputerAwareStep<S, E> implements Trav
         return ends.iterator();
     }
 
+    private List<Traversal.Admin<S, E>> pickBranches(final Object choice) {
+        final List<Traversal.Admin<S, E>> branches = new ArrayList<>();
+        if (choice instanceof Pick) {
+            if (this.traversalPickOptions.containsKey(choice)) {
+                branches.addAll(this.traversalPickOptions.get(choice));
+            }
+        }
+        for (final Pair<Traversal.Admin, Traversal.Admin<S, E>> p : 
this.traversalOptions) {
+            if (TraversalUtil.test(choice, p.getValue0())) {
+                branches.add(p.getValue1());
+            }
+        }
+        return branches.isEmpty() ? this.traversalPickOptions.get(Pick.none) : 
branches;
+    }
+
     @Override
     public BranchStep<S, E, M> clone() {
         final BranchStep<S, E, M> clone = (BranchStep<S, E, M>) super.clone();
-        clone.traversalOptions = new HashMap<>(this.traversalOptions.size());
-        for (final Map.Entry<Object, List<Traversal.Admin<S, E>>> entry : 
this.traversalOptions.entrySet()) {
+        clone.traversalPickOptions = new 
HashMap<>(this.traversalPickOptions.size());
+        clone.traversalOptions = new ArrayList<>(this.traversalOptions.size());
+        for (final Map.Entry<Pick, List<Traversal.Admin<S, E>>> entry : 
this.traversalPickOptions.entrySet()) {
             final List<Traversal.Admin<S, E>> traversals = entry.getValue();
             if (traversals.size() > 0) {
-                final List<Traversal.Admin<S, E>> clonedTraversals = 
clone.traversalOptions.compute(entry.getKey(), (k, v) ->
+                final List<Traversal.Admin<S, E>> clonedTraversals = 
clone.traversalPickOptions.compute(entry.getKey(), (k, v) ->
                         (v == null) ? new ArrayList<>(traversals.size()) : v);
                 for (final Traversal.Admin<S, E> traversal : traversals) {
                     clonedTraversals.add(traversal.clone());
                 }
             }
         }
+        for (final Pair<Traversal.Admin, Traversal.Admin<S, E>> pair : 
this.traversalOptions) {
+            clone.traversalOptions.add(Pair.with(pair.getValue0().clone(), 
pair.getValue1().clone()));
+        }
         clone.branchTraversal = this.branchTraversal.clone();
         return clone;
     }
@@ -204,12 +235,14 @@ public class BranchStep<S, E, M> extends 
ComputerAwareStep<S, E> implements Trav
     public void setTraversal(final Traversal.Admin<?, ?> parentTraversal) {
         super.setTraversal(parentTraversal);
         this.integrateChild(this.branchTraversal);
-        
this.traversalOptions.values().stream().flatMap(List::stream).forEach(this::integrateChild);
+        this.getGlobalChildren().forEach(this::integrateChild);
     }
 
     @Override
     public int hashCode() {
         int result = super.hashCode();
+        if (this.traversalPickOptions != null)
+            result ^= this.traversalPickOptions.hashCode();
         if (this.traversalOptions != null)
             result ^= this.traversalOptions.hashCode();
         if (this.branchTraversal != null)
@@ -219,7 +252,10 @@ public class BranchStep<S, E, M> extends 
ComputerAwareStep<S, E> implements Trav
 
     @Override
     public String toString() {
-        return StringFactory.stepString(this, this.branchTraversal, 
this.traversalOptions);
+        final List<Pair> combinedOptions = Stream.concat(
+                this.traversalPickOptions.entrySet().stream().map(e -> 
Pair.with(e.getKey(), e.getValue())),
+                this.traversalOptions.stream()).collect(Collectors.toList());
+        return StringFactory.stepString(this, this.branchTraversal, 
combinedOptions);
     }
 
     @Override
@@ -228,39 +264,4 @@ public class BranchStep<S, E, M> extends 
ComputerAwareStep<S, E> implements Trav
         this.getGlobalChildren().forEach(Traversal.Admin::reset);
         this.first = true;
     }
-
-    /**
-     * PickTokenKey is basically a wrapper for numbers that are used as a 
PickToken. This is
-     * required in order to treat equal numbers of different data types as a 
match.
-     */
-    private static class PickTokenKey {
-
-        final Number number;
-
-        private PickTokenKey(final Number number) {
-            this.number = number;
-        }
-
-        static Object make(final Object value) {
-            return value instanceof Number ? new PickTokenKey((Number) value) 
: value;
-        }
-
-        @Override
-        public boolean equals(final Object o) {
-            if (this == o) return true;
-            if (o == null || getClass() != o.getClass()) return false;
-            final PickTokenKey other = (PickTokenKey) o;
-            return 0 == NumberHelper.compare(number, other.number);
-        }
-
-        @Override
-        public int hashCode() {
-            return number.hashCode();
-        }
-
-        @Override
-        public String toString() {
-            return number.toString();
-        }
-    }
-}
+}
\ No newline at end of file
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/ChooseStep.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/ChooseStep.java
index e699f22..a804d8f 100644
--- 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/ChooseStep.java
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/ChooseStep.java
@@ -42,10 +42,12 @@ public final class ChooseStep<S, E, M> extends 
BranchStep<S, E, M> {
 
     @Override
     public void addGlobalChildOption(final M pickToken, final 
Traversal.Admin<S, E> traversalOption) {
-        if (Pick.any.equals(pickToken))
-            throw new IllegalArgumentException("Choose step can not have an 
any-option as only one option per traverser is allowed");
-        if (this.traversalOptions.containsKey(pickToken))
-            throw new IllegalArgumentException("Choose step can only have one 
traversal per pick token: " + pickToken);
+        if (pickToken instanceof Pick) {
+            if (Pick.any.equals(pickToken))
+                throw new IllegalArgumentException("Choose step can not have 
an any-option as only one option per traverser is allowed");
+            if (this.traversalPickOptions.containsKey(pickToken))
+                throw new IllegalArgumentException("Choose step can only have 
one traversal per pick token: " + pickToken);
+        }
         super.addGlobalChildOption(pickToken, traversalOption);
     }
 }
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/UnionStep.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/UnionStep.java
index 85f3645..de70479 100644
--- 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/UnionStep.java
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/UnionStep.java
@@ -47,6 +47,6 @@ public final class UnionStep<S, E> extends BranchStep<S, E, 
TraversalOptionParen
 
     @Override
     public String toString() {
-        return StringFactory.stepString(this, 
this.traversalOptions.getOrDefault(Pick.any, Collections.emptyList()));
+        return StringFactory.stepString(this, 
this.traversalPickOptions.getOrDefault(Pick.any, Collections.emptyList()));
     }
 }
diff --git a/gremlin-test/features/branch/Branch.feature 
b/gremlin-test/features/branch/Branch.feature
index 6ee261f..e160fc8 100644
--- a/gremlin-test/features/branch/Branch.feature
+++ b/gremlin-test/features/branch/Branch.feature
@@ -89,4 +89,39 @@ Feature: Step - branch()
       | person |
       | person |
       | software |
-      | software |
\ No newline at end of file
+      | software |
+
+  Scenario: 
g_V_branchXageX_optionXltX30X__youngX_optionXgtX30X__oldX_optionXnone__on_the_edgeX
+    Given the modern graph
+    And the traversal of
+      """
+      g.V().hasLabel("person").
+        branch(__.values("age")).
+          option(P.lt(30), __.constant("young")).
+          option(P.gt(30), __.constant("old")).
+          option(Pick.none, __.constant("on the edge"))
+      """
+    When iterated to list
+    Then the result should be unordered
+      | result |
+      | young |
+      | young |
+      | old |
+      | old |
+
+  Scenario: 
g_V_branchXidentityX_optionXhasLabelXsoftwareX__inXcreatedX_name_order_foldX_optionXhasXname_vadasX__ageX_optionXneqX123X__bothE_countX
+    Given the modern graph
+    And the traversal of
+      """
+      g.V().
+        branch(__.identity()).
+          option(__.hasLabel("software"), 
__.in("created").values("name").order().fold()).
+          option(__.has("name","vadas"), __.values("age")).
+          option(P.neq(123), __.bothE().count())
+      """
+    When iterated to list
+    Then the result should be unordered
+      | result |
+      | l[josh,josh,marko,peter] |
+      | d[27].i |
+      | d[12].l |
diff --git 
a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/ComplexTest.java
 
b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/ComplexTest.java
index 75dd0f5..0110d44 100644
--- 
a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/ComplexTest.java
+++ 
b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/ComplexTest.java
@@ -44,6 +44,7 @@ import java.util.Map;
 import static java.util.Collections.emptyList;
 import static org.apache.tinkerpop.gremlin.LoadGraphWith.GraphData.MODERN;
 import static org.apache.tinkerpop.gremlin.process.traversal.P.eq;
+import static org.apache.tinkerpop.gremlin.process.traversal.P.gte;
 import static org.apache.tinkerpop.gremlin.process.traversal.P.lt;
 import static org.apache.tinkerpop.gremlin.process.traversal.P.neq;
 import static org.apache.tinkerpop.gremlin.process.traversal.Pop.all;
@@ -51,6 +52,7 @@ import static 
org.apache.tinkerpop.gremlin.process.traversal.Pop.first;
 import static org.apache.tinkerpop.gremlin.process.traversal.Pop.last;
 import static org.apache.tinkerpop.gremlin.process.traversal.Scope.local;
 import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.both;
+import static 
org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.branch;
 import static 
org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.constant;
 import static 
org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.count;
 import static 
org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.group;
@@ -86,6 +88,8 @@ public abstract class ComplexTest extends 
AbstractGremlinProcessTest {
 
     public abstract Traversal<Vertex, Map<String, List<String>>> 
getPlaylistPaths();
 
+    public abstract Traversal<Vertex, Map<String, List<String>>> 
getAgeComments();
+
     /**
      * Checks the result of both coworkerSummary tests, which is expected to 
look as follows:
      * <p>
@@ -243,6 +247,32 @@ public abstract class ComplexTest extends 
AbstractGremlinProcessTest {
         assertTrue(map.get("artists").contains("Grateful_Dead"));
     }
 
+    @Test
+    @LoadGraphWith(LoadGraphWith.GraphData.MODERN)
+    public void ageComments() {
+        final Traversal<Vertex, Map<String, List<String>>> traversal = 
getAgeComments();
+        printTraversalForm(traversal);
+        assertTrue(traversal.hasNext());
+        Map<String, List<String>> map = traversal.next();
+        assertEquals(4, map.size());
+        assertTrue(map.containsKey("marko"));
+        assertEquals(2, map.get("marko").size());
+        assertTrue(map.get("marko").contains("almost old"));
+        assertTrue(map.get("marko").contains("younger than peter"));
+        assertTrue(map.containsKey("vadas"));
+        assertEquals(2, map.get("vadas").size());
+        assertTrue(map.get("vadas").contains("pretty young"));
+        assertTrue(map.get("vadas").contains("younger than peter"));
+        assertTrue(map.containsKey("josh"));
+        assertEquals(3, map.get("josh").size());
+        assertTrue(map.get("josh").contains("younger than peter"));
+        assertTrue(map.get("josh").contains("pretty old"));
+        assertTrue(map.get("josh").contains("looks like josh"));
+        assertTrue(map.containsKey("peter"));
+        assertEquals(1, map.get("peter").size());
+        assertTrue(map.get("peter").contains("pretty old"));
+    }
+
     public static class Traversals extends ComplexTest {
 
         @Override
@@ -323,6 +353,18 @@ public abstract class ComplexTest extends 
AbstractGremlinProcessTest {
                     by("name").
                     by(__.coalesce(out("sungBy", 
"writtenBy").dedup().values("name"), constant("Unknown")).fold());
         }
-    }
-}
 
+        @Override
+        public Traversal<Vertex, Map<String, List<String>>> getAgeComments() {
+            return g.V().hasLabel("person")
+                    .<String, List<String>> group()
+                        .by("name")
+                        .by(branch(values("age"))
+                                .option(29, constant("almost old"))
+                                .option(__.is(32), constant("looks like josh"))
+                                .option(lt(29), constant("pretty young"))
+                                .option(lt(35), constant("younger than peter"))
+                                .option(gte(30), constant("pretty 
old")).fold());
+        }
+    }
+}
\ No newline at end of file
diff --git 
a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/BranchTest.java
 
b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/BranchTest.java
index 44a63bd..ed4b2e7 100644
--- 
a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/BranchTest.java
+++ 
b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/BranchTest.java
@@ -29,9 +29,19 @@ import org.junit.runner.RunWith;
 import java.util.Arrays;
 
 import static org.apache.tinkerpop.gremlin.LoadGraphWith.GraphData.MODERN;
+import static org.apache.tinkerpop.gremlin.process.traversal.P.gt;
+import static org.apache.tinkerpop.gremlin.process.traversal.P.lt;
+import static org.apache.tinkerpop.gremlin.process.traversal.P.neq;
+import static 
org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.bothE;
+import static 
org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.constant;
+import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.has;
+import static 
org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.hasLabel;
+import static 
org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.identity;
+import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.in;
 import static 
org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.label;
 import static 
org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.values;
 import static 
org.apache.tinkerpop.gremlin.process.traversal.step.TraversalOptionParent.Pick.any;
+import static 
org.apache.tinkerpop.gremlin.process.traversal.step.TraversalOptionParent.Pick.none;
 
 /**
  * @author Marko A. Rodriguez (http://markorodriguez.com)
@@ -45,6 +55,10 @@ public abstract class BranchTest extends 
AbstractGremlinProcessTest {
 
     public abstract Traversal<Vertex, Object> 
get_g_V_branchXlabel_isXpersonX_countX_optionX1__ageX_optionX0__langX_optionX0__nameX_optionXany__labelX();
 
+    public abstract Traversal<Vertex, Object> 
get_g_V_branchXageX_optionXltX30X__youngX_optionXgtX30X__oldX_optionXnone__on_the_edgeX();
+
+    public abstract Traversal<Vertex, Object> 
get_g_V_branchXidentityX_optionXhasLabelXsoftwareX__inXcreatedX_name_order_foldX_optionXhasXname_vadasX__ageX_optionXneqX123X__bothE_countX();
+
     @Test
     @LoadGraphWith(MODERN)
     public void 
g_V_branchXlabel_eq_person__a_bX_optionXa__ageX_optionXb__langX_optionXb__nameX()
 {
@@ -69,6 +83,22 @@ public abstract class BranchTest extends 
AbstractGremlinProcessTest {
         checkResults(Arrays.asList("java", "java", "lop", "ripple", 29, 27, 
32, 35, "person", "person", "person", "person", "software", "software"), 
traversal);
     }
 
+    @Test
+    @LoadGraphWith(MODERN)
+    public void 
g_V_branchXageX_optionXltX30X__youngX_optionXgtX30X__oldX_optionXnone__on_the_edgeX()
 {
+        final Traversal<Vertex, Object> traversal = 
get_g_V_branchXageX_optionXltX30X__youngX_optionXgtX30X__oldX_optionXnone__on_the_edgeX();
+        printTraversalForm(traversal);
+        checkResults(Arrays.asList("young", "young", "old", "old"), traversal);
+    }
+
+    @Test
+    @LoadGraphWith(MODERN)
+    public void 
g_V_branchXidentityX_optionXhasLabelXsoftwareX__inXcreatedX_name_order_foldX_optionXhasXname_vadasX__ageX_optionXneqX123X__bothE_countX()
 {
+        final Traversal<Vertex, Object> traversal = 
get_g_V_branchXidentityX_optionXhasLabelXsoftwareX__inXcreatedX_name_order_foldX_optionXhasXname_vadasX__ageX_optionXneqX123X__bothE_countX();
+        printTraversalForm(traversal);
+        checkResults(Arrays.asList(Arrays.asList("josh", "josh", "marko", 
"peter"), 27, 12L), traversal);
+    }
+
     public static class Traversals extends BranchTest {
 
         @Override
@@ -95,5 +125,22 @@ public abstract class BranchTest extends 
AbstractGremlinProcessTest {
                     .option(0L, values("name"))
                     .option(any, label());
         }
+
+        @Override
+        public Traversal<Vertex, Object> 
get_g_V_branchXageX_optionXltX30X__youngX_optionXgtX30X__oldX_optionXnone__on_the_edgeX()
 {
+            return g.V().hasLabel("person")
+                    .branch(values("age"))
+                    .option(lt(30), constant("young"))
+                    .option(gt(30), constant("old"))
+                    .option(none, constant("on the edge"));
+        }
+
+        @Override
+        public Traversal<Vertex, Object> 
get_g_V_branchXidentityX_optionXhasLabelXsoftwareX__inXcreatedX_name_order_foldX_optionXhasXname_vadasX__ageX_optionXneqX123X__bothE_countX()
 {
+            return g.V().branch(identity())
+                    .option(hasLabel("software"), 
in("created").values("name").order().fold())
+                    .option(has("name","vadas"), values("age"))
+                    .option(neq(123), bothE().count());
+        }
     }
 }
\ No newline at end of file
diff --git 
a/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraphPlayTest.java
 
b/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraphPlayTest.java
index 746689a..31c332b 100644
--- 
a/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraphPlayTest.java
+++ 
b/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraphPlayTest.java
@@ -24,6 +24,7 @@ import 
org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal;
 import 
org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
+import 
org.apache.tinkerpop.gremlin.process.traversal.step.TraversalOptionParent;
 import 
org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.PathRetractionStrategy;
 import org.apache.tinkerpop.gremlin.structure.Graph;
 import org.apache.tinkerpop.gremlin.structure.T;
@@ -41,9 +42,14 @@ import java.util.function.BiFunction;
 import java.util.function.Supplier;
 
 import static org.apache.tinkerpop.gremlin.process.traversal.Operator.sum;
+import static org.apache.tinkerpop.gremlin.process.traversal.P.between;
+import static org.apache.tinkerpop.gremlin.process.traversal.P.gt;
+import static org.apache.tinkerpop.gremlin.process.traversal.P.gte;
+import static org.apache.tinkerpop.gremlin.process.traversal.P.lt;
 import static org.apache.tinkerpop.gremlin.process.traversal.P.neq;
 import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.as;
 import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.both;
+import static 
org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.branch;
 import static 
org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.choose;
 import static 
org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.constant;
 import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.has;
@@ -53,6 +59,7 @@ import static 
org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.sack;
 import static 
org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.select;
 import static 
org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.union;
 import static 
org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.valueMap;
+import static 
org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.values;
 
 /**
  * @author Stephen Mallette (http://stephen.genoprime.com)
@@ -130,12 +137,19 @@ public class TinkerGraphPlayTest {
     @Ignore
     public void testPlayDK() throws Exception {
 
-        final GraphTraversalSource g = 
TinkerFactory.createModern().traversal();
-        g.V().match(
-                __.as("b").out("created").as("c"),
-                __.as("a").hasLabel("person"),
-                __.as("b").hasLabel("person"),
-                
__.as("a").out("knows").as("b")).forEachRemaining(System.out::println);
+        GraphTraversalSource g = TinkerFactory.createModern().traversal();
+        System.out.println(g./*withComputer().*/V().hasLabel("person")
+                .project("name", "age", "comments")
+                    .by("name")
+                    .by("age")
+                    .by(branch(values("age"))
+                            .option(TraversalOptionParent.Pick.any, 
constant("foo"))
+                            .option(29, constant("almost old"))
+                            .option(__.is(32), constant("looks like josh"))
+                            .option(lt(29), constant("pretty young"))
+                            .option(lt(35), constant("younger than peter"))
+                            .option(gte(30), constant("pretty 
old")).fold()).explain());
+                //.forEachRemaining(System.out::println);
     }
 
     @Test

Reply via email to