while reviewing @twilmes work, I made various adjustments. Coding style things 
like finalizing variables, simplifiying some methods using existing Helper 
classes we have, added more tests to PrunePathStrategyTest, added PathProcess 
updates to TreeSideEffectStep. all in all, this is very solid work. I still 
need more time to review as there is one thing the troubles me about dynamic 
pruning in MatchStep. Just want to commit what I have done thus far so I don't 
corrupt it.


Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/f9c6ea62
Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/f9c6ea62
Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/f9c6ea62

Branch: refs/heads/TINKERPOP-1278
Commit: f9c6ea62c4a17d25a681cf0678d9713013302c67
Parents: 88c5d27
Author: Marko A. Rodriguez <okramma...@gmail.com>
Authored: Fri Jul 8 10:01:35 2016 -0600
Committer: Marko A. Rodriguez <okramma...@gmail.com>
Committed: Fri Jul 8 10:01:35 2016 -0600

----------------------------------------------------------------------
 .../process/traversal/TraversalStrategies.java  |  4 +-
 .../process/traversal/step/PathProcessor.java   | 16 ++---
 .../traversal/step/filter/DedupGlobalStep.java  |  4 +-
 .../step/filter/WherePredicateStep.java         |  4 +-
 .../step/filter/WhereTraversalStep.java         |  8 +--
 .../process/traversal/step/map/MatchStep.java   | 49 +++++++++-----
 .../process/traversal/step/map/PathStep.java    |  8 +--
 .../traversal/step/map/SelectOneStep.java       |  2 +-
 .../process/traversal/step/map/SelectStep.java  | 10 +--
 .../step/sideEffect/TreeSideEffectStep.java     |  9 ++-
 .../optimization/PathProcessorStrategy.java     |  3 +-
 .../optimization/PrunePathStrategy.java         | 67 ++++++++----------
 .../process/traversal/util/PathUtil.java        | 10 +--
 .../optimization/PrunePathStrategyTest.java     | 71 +++++++++++---------
 14 files changed, 143 insertions(+), 122 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f9c6ea62/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TraversalStrategies.java
----------------------------------------------------------------------
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TraversalStrategies.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TraversalStrategies.java
index 850db9f..ee3fa76 100644
--- 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TraversalStrategies.java
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TraversalStrategies.java
@@ -197,9 +197,9 @@ public interface TraversalStrategies extends Serializable, 
Cloneable {
                     MatchPredicateStrategy.instance(),
                     RepeatUnrollStrategy.instance(),
                     RangeByIsCountStrategy.instance(),
+                    PrunePathStrategy.instance(),
                     ProfileStrategy.instance(),
-                    StandardVerificationStrategy.instance(),
-                    PrunePathStrategy.instance());
+                    StandardVerificationStrategy.instance());
 
             GRAPH_CACHE.put(Graph.class, graphStrategies);
             GRAPH_CACHE.put(EmptyGraph.class, new 
DefaultTraversalStrategies());

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f9c6ea62/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/PathProcessor.java
----------------------------------------------------------------------
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/PathProcessor.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/PathProcessor.java
index 7d8a497..f3870cb 100644
--- 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/PathProcessor.java
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/PathProcessor.java
@@ -60,15 +60,15 @@ public interface PathProcessor {
         return max;
     }
 
-    void setKeepLabels(final Set<String> labels);
+    public void setKeepLabels(final Set<String> labels);
 
-    static void keepLabels(final Traverser traverser, final Set<String> 
labels) {
-        if(labels == null || labels.isEmpty()) {
-            return;
-        } else {
-            traverser.asAdmin().keepLabels(labels);
-        }
+    public Set<String> getKeepLabels();
+
+    public static <S> Traverser.Admin<S> processTraverserPathLabels(final 
Traverser.Admin<S> traverser, final Set<String> labels) {
+        if (null != labels && !labels.isEmpty())
+            traverser.keepLabels(labels);
+        return traverser;
     }
 
-    Set<String> getKeepLabels();
+
 }

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f9c6ea62/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/DedupGlobalStep.java
----------------------------------------------------------------------
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/DedupGlobalStep.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/DedupGlobalStep.java
index 78fd429..8ef6455 100644
--- 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/DedupGlobalStep.java
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/DedupGlobalStep.java
@@ -83,9 +83,7 @@ public final class DedupGlobalStep<S> extends FilterStep<S> 
implements Traversal
 
     @Override
     protected Traverser.Admin<S> processNextStart() {
-        final Traverser.Admin<S> traverser = super.processNextStart();
-        PathProcessor.keepLabels(traverser, keepLabels);
-        return traverser;
+        return 
PathProcessor.processTraverserPathLabels(super.processNextStart(), 
this.keepLabels);
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f9c6ea62/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/WherePredicateStep.java
----------------------------------------------------------------------
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/WherePredicateStep.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/WherePredicateStep.java
index 0ee7832..bea9aad 100644
--- 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/WherePredicateStep.java
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/WherePredicateStep.java
@@ -120,9 +120,7 @@ public final class WherePredicateStep<S> extends 
FilterStep<S> implements Scopin
 
     @Override
     protected Traverser.Admin<S> processNextStart() {
-        final Traverser.Admin<S> traverser = super.processNextStart();
-        PathProcessor.keepLabels(traverser, keepLabels);
-        return traverser;
+        return 
PathProcessor.processTraverserPathLabels(super.processNextStart(), 
this.keepLabels);
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f9c6ea62/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/WhereTraversalStep.java
----------------------------------------------------------------------
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/WhereTraversalStep.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/WhereTraversalStep.java
index 078a370..762dfed 100644
--- 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/WhereTraversalStep.java
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/WhereTraversalStep.java
@@ -91,9 +91,7 @@ public final class WhereTraversalStep<S> extends 
FilterStep<S> implements Traver
 
     @Override
     protected Traverser.Admin<S> processNextStart() {
-        final Traverser.Admin<S> traverser = super.processNextStart();
-        PathProcessor.keepLabels(traverser, keepLabels);
-        return traverser;
+        return 
PathProcessor.processTraverserPathLabels(super.processNextStart(), 
this.keepLabels);
     }
 
     @Override
@@ -147,7 +145,9 @@ public final class WhereTraversalStep<S> extends 
FilterStep<S> implements Traver
     }
 
     @Override
-    public Set<String> getKeepLabels() { return this.keepLabels; }
+    public Set<String> getKeepLabels() {
+        return this.keepLabels;
+    }
 
     //////////////////////////////
 

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f9c6ea62/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MatchStep.java
----------------------------------------------------------------------
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MatchStep.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MatchStep.java
index 3fb45fc..0a6d59b 100644
--- 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MatchStep.java
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MatchStep.java
@@ -18,11 +18,20 @@
  */
 package org.apache.tinkerpop.gremlin.process.traversal.step.map;
 
-import org.apache.tinkerpop.gremlin.process.traversal.*;
+import org.apache.tinkerpop.gremlin.process.traversal.Path;
+import org.apache.tinkerpop.gremlin.process.traversal.Pop;
+import org.apache.tinkerpop.gremlin.process.traversal.Step;
+import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
+import org.apache.tinkerpop.gremlin.process.traversal.TraversalEngine;
+import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
 import org.apache.tinkerpop.gremlin.process.traversal.step.PathProcessor;
 import org.apache.tinkerpop.gremlin.process.traversal.step.Scoping;
 import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent;
-import org.apache.tinkerpop.gremlin.process.traversal.step.filter.*;
+import org.apache.tinkerpop.gremlin.process.traversal.step.filter.AndStep;
+import 
org.apache.tinkerpop.gremlin.process.traversal.step.filter.ConnectiveStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.filter.NotStep;
+import 
org.apache.tinkerpop.gremlin.process.traversal.step.filter.WherePredicateStep;
+import 
org.apache.tinkerpop.gremlin.process.traversal.step.filter.WhereTraversalStep;
 import 
org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.StartStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.util.AbstractStep;
 import 
org.apache.tinkerpop.gremlin.process.traversal.step.util.ComputerAwareStep;
@@ -38,7 +47,17 @@ import 
org.apache.tinkerpop.gremlin.util.iterator.IteratorUtils;
 
 import java.io.Serializable;
 import java.lang.reflect.InvocationTargetException;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.Optional;
+import java.util.Set;
 import java.util.function.Function;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
@@ -139,7 +158,6 @@ public final class MatchStep<S, E> extends 
ComputerAwareStep<S, Map<String, E>>
     }
 
 
-
     public ConnectiveStep.Connective getConnective() {
         return this.connective;
     }
@@ -373,16 +391,16 @@ public final class MatchStep<S, E> extends 
ComputerAwareStep<S, Map<String, E>>
         }
     }
 
-    protected List<Traversal.Admin> getRemainingTraversals(final 
Traverser.Admin traverser) {
+    protected List<Traversal.Admin<?, ?>> getRemainingTraversals(final 
Traverser.Admin<?> traverser) {
         final Set<String> tags = traverser.getTags();
-        final List<Traversal.Admin> remainingTraversals = new ArrayList<>();
-        for (final Traversal.Admin matchTraversal : matchTraversals) {
+        final List<Traversal.Admin<?, ?>> remainingTraversals = new 
ArrayList<>();
+        for (final Traversal.Admin<?, ?> matchTraversal : matchTraversals) {
             if (!tags.contains(matchTraversal.getStartStep().getId())) {
                 remainingTraversals.add(matchTraversal);
             } else {
                 // include the current traversal that the traverser is 
executing in the list of
                 // remaining traversals
-                for (final Step<?, ?> s : (List<Step<?, 
?>>)matchTraversal.getSteps()) {
+                for (final Step<?, ?> s : matchTraversal.getSteps()) {
                     if (s.getId().equals(traverser.getStepId())) {
                         remainingTraversals.add(matchTraversal);
                         break;
@@ -410,14 +428,13 @@ public final class MatchStep<S, E> extends 
ComputerAwareStep<S, Map<String, E>>
     @Override
     protected Traverser.Admin<Map<String, E>> processNextStart() throws 
NoSuchElementException {
         final Traverser.Admin<Map<String, E>> traverser = 
super.processNextStart();
-        if (keepLabels != null) {
+        if (null != this.keepLabels) {
             final Set<String> keepers = new HashSet<>();
-            List<Traversal.Admin> remainingTraversals = 
getRemainingTraversals(traverser);
-            for (Traversal.Admin trav : remainingTraversals) {
-                keepers.addAll(PathUtil.getReferencedLabels(trav));
+            for (final Traversal.Admin<?, ?> traversal : 
getRemainingTraversals(traverser)) {
+                keepers.addAll(PathUtil.getReferencedLabels(traversal));
             }
-            keepers.addAll(keepLabels);
-            PathProcessor.keepLabels(traverser, keepers);
+            keepers.addAll(this.keepLabels);
+            PathProcessor.processTraverserPathLabels(traverser, keepers);
         }
         return traverser;
     }
@@ -749,5 +766,7 @@ public final class MatchStep<S, E> extends 
ComputerAwareStep<S, Map<String, E>>
         return this.matchEndLabels;
     }
 
-    public Set<String> getMatchStartLabels() { return this.matchStartLabels; }
+    public Set<String> getMatchStartLabels() {
+        return this.matchStartLabels;
+    }
 }

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f9c6ea62/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 885afc1..c4b2534 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
@@ -110,11 +110,11 @@ public final class PathStep<S> extends MapStep<S, Path> 
implements TraversalPare
 
     @Override
     protected Traverser.Admin<Path> processNextStart() {
-        final Traverser.Admin<Path> traverser = super.processNextStart();
-        PathProcessor.keepLabels(traverser, keepLabels);
-        return traverser;
+        return 
PathProcessor.processTraverserPathLabels(super.processNextStart(), 
this.keepLabels);
     }
 
     @Override
-    public Set<String> getKeepLabels() { return this.keepLabels; }
+    public Set<String> getKeepLabels() {
+        return this.keepLabels;
+    }
 }

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f9c6ea62/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/SelectOneStep.java
----------------------------------------------------------------------
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/SelectOneStep.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/SelectOneStep.java
index 3bd5c1d..87a3f9b 100644
--- 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/SelectOneStep.java
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/SelectOneStep.java
@@ -129,7 +129,7 @@ public final class SelectOneStep<S, E> extends MapStep<S, 
E> implements Traversa
     protected Traverser.Admin<E> processNextStart() {
         final Traverser.Admin<E> traverser = super.processNextStart();
         if(!(this.getTraversal().getParent() instanceof MatchStep)) {
-            PathProcessor.keepLabels(traverser, keepLabels);
+            PathProcessor.processTraverserPathLabels(traverser, 
this.keepLabels);
         }
         return traverser;
     }

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f9c6ea62/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/SelectStep.java
----------------------------------------------------------------------
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/SelectStep.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/SelectStep.java
index ecd5581..b875a79 100644
--- 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/SelectStep.java
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/SelectStep.java
@@ -62,7 +62,7 @@ public final class SelectStep<S, E> extends MapStep<S, 
Map<String, E>> implement
 
     @Override
     protected Map<String, E> map(final Traverser.Admin<S> traverser) {
-        final Map<String, E> bindings = new 
LinkedHashMap<>(this.selectKeys.size(),1.0f);
+        final Map<String, E> bindings = new 
LinkedHashMap<>(this.selectKeys.size(), 1.0f);
         for (final String selectKey : this.selectKeys) {
             final E end = this.getNullableScopeValue(this.pop, selectKey, 
traverser);
             if (null != end)
@@ -149,12 +149,12 @@ public final class SelectStep<S, E> extends MapStep<S, 
Map<String, E>> implement
     }
 
     @Override
-    public Set<String> getKeepLabels() { return this.keepLabels; }
+    public Set<String> getKeepLabels() {
+        return this.keepLabels;
+    }
 
     @Override
     protected Traverser.Admin<Map<String, E>> processNextStart() {
-        final Traverser.Admin<Map<String, E>> traverser = 
super.processNextStart();
-        PathProcessor.keepLabels(traverser, keepLabels);
-        return traverser;
+        return 
PathProcessor.processTraverserPathLabels(super.processNextStart(), 
this.keepLabels);
     }
 }

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f9c6ea62/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/TreeSideEffectStep.java
----------------------------------------------------------------------
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/TreeSideEffectStep.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/TreeSideEffectStep.java
index 6351455..4ef5544 100644
--- 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/TreeSideEffectStep.java
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/TreeSideEffectStep.java
@@ -69,6 +69,11 @@ public final class TreeSideEffectStep<S> extends 
SideEffectStep<S> implements Si
     }
 
     @Override
+    protected Traverser.Admin<S> processNextStart() {
+        return 
PathProcessor.processTraverserPathLabels(super.processNextStart(), 
this.keepLabels);
+    }
+
+    @Override
     public String getSideEffectKey() {
         return this.sideEffectKey;
     }
@@ -123,5 +128,7 @@ public final class TreeSideEffectStep<S> extends 
SideEffectStep<S> implements Si
     }
 
     @Override
-    public Set<String> getKeepLabels() { return this.keepLabels; }
+    public Set<String> getKeepLabels() {
+        return this.keepLabels;
+    }
 }

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f9c6ea62/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/PathProcessorStrategy.java
----------------------------------------------------------------------
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/PathProcessorStrategy.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/PathProcessorStrategy.java
index c0286f2..0b40743 100644
--- 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/PathProcessorStrategy.java
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/PathProcessorStrategy.java
@@ -32,6 +32,7 @@ import 
org.apache.tinkerpop.gremlin.process.traversal.strategy.AbstractTraversal
 import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper;
 
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
@@ -44,7 +45,7 @@ public final class PathProcessorStrategy extends 
AbstractTraversalStrategy<Trave
 
     private static final PathProcessorStrategy INSTANCE = new 
PathProcessorStrategy();
 
-    private static final Set<Class<? extends OptimizationStrategy>> PRIORS = 
new HashSet<>(Arrays.asList(MatchPredicateStrategy.class));
+    private static final Set<Class<? extends OptimizationStrategy>> PRIORS = 
Collections.singleton(MatchPredicateStrategy.class);
 
     private PathProcessorStrategy() {
     }

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f9c6ea62/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/PrunePathStrategy.java
----------------------------------------------------------------------
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/PrunePathStrategy.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/PrunePathStrategy.java
index ebb6b66..e3d50bf 100644
--- 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/PrunePathStrategy.java
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/PrunePathStrategy.java
@@ -23,13 +23,13 @@ import 
org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.step.PathProcessor;
 import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent;
-import org.apache.tinkerpop.gremlin.process.traversal.step.map.PathStep;
-import 
org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.SubgraphStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.util.EmptyStep;
 import 
org.apache.tinkerpop.gremlin.process.traversal.strategy.AbstractTraversalStrategy;
+import 
org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
 import org.apache.tinkerpop.gremlin.process.traversal.util.PathUtil;
 import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper;
 
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
@@ -41,11 +41,8 @@ import java.util.Set;
 public final class PrunePathStrategy extends 
AbstractTraversalStrategy<TraversalStrategy.OptimizationStrategy> implements 
TraversalStrategy.OptimizationStrategy {
 
     private static final PrunePathStrategy INSTANCE = new PrunePathStrategy();
-    private static final Set<Class<? extends OptimizationStrategy>> PRIORS = 
new HashSet<>();
-
-    static {
-        PRIORS.add(PathProcessorStrategy.class);
-    }
+    // these strategies do strong rewrites involving path labeling and thus, 
should run prior to PrunePathStrategy
+    private static final Set<Class<? extends OptimizationStrategy>> PRIORS = 
new HashSet<>(Arrays.asList(RepeatUnrollStrategy.class, 
MatchPredicateStrategy.class, PathProcessorStrategy.class));
 
     private PrunePathStrategy() {
     }
@@ -54,10 +51,10 @@ public final class PrunePathStrategy extends 
AbstractTraversalStrategy<Traversal
         return INSTANCE;
     }
 
-    protected Set<String> getAndPropagateReferencedLabels(final 
Traversal.Admin<?, ?> traversal) {
-        if (traversal.getParent().equals(EmptyStep.instance())) {
-            return Collections.EMPTY_SET;
-        }
+    private Set<String> getAndPropagateReferencedLabels(final 
Traversal.Admin<?, ?> traversal) {
+        if (traversal.getParent().equals(EmptyStep.instance()))
+            return Collections.emptySet();
+
         Step<?, ?> parent = traversal.getParent().asStep();
         Set<String> referencedLabels = new HashSet<>();
         // get referenced labels from this traversal
@@ -83,7 +80,7 @@ public final class PrunePathStrategy extends 
AbstractTraversalStrategy<Traversal
                     referencedLabels.addAll(labels);
                 }
                 step = step.getNextStep();
-            } while(!(step.equals(EmptyStep.instance())));
+            } while (!(step.equals(EmptyStep.instance())));
             if (topLevelParent) {
                 step = parent;
                 do {
@@ -105,10 +102,10 @@ public final class PrunePathStrategy extends 
AbstractTraversalStrategy<Traversal
 
     @Override
     public void apply(final Traversal.Admin<?, ?> traversal) {
-        TraversalParent parent = traversal.getParent();
 
-        Set<String> foundLabels = new HashSet<>();
-        Set<String> keepLabels = new HashSet<>();
+        final TraversalParent parent = traversal.getParent();
+        final Set<String> foundLabels = new HashSet<>();
+        final Set<String> keepLabels = new HashSet<>();
 
         // If this traversal has a parent, it will need to inherit its
         // parent's keep labels.  If its direct parent is not a PathProcessor,
@@ -117,27 +114,20 @@ public final class PrunePathStrategy extends 
AbstractTraversalStrategy<Traversal
         if (!parent.equals(EmptyStep.instance())) {
             // start with parents keep labels
             if (parent instanceof PathProcessor) {
-                PathProcessor parentPathProcess = (PathProcessor) parent;
-                if (parentPathProcess.getKeepLabels() != null) 
keepLabels.addAll(parentPathProcess.getKeepLabels());
-            } else {
-                Set<String> labels = 
getAndPropagateReferencedLabels(traversal);
-                keepLabels.addAll(labels);
-            }
+                final PathProcessor parentPathProcess = (PathProcessor) parent;
+                if (null != parentPathProcess.getKeepLabels()) 
keepLabels.addAll(parentPathProcess.getKeepLabels());
+            } else
+                keepLabels.addAll(getAndPropagateReferencedLabels(traversal));
         }
 
-        // check if the traversal contains any path or subgraph steps and if
+        // check if the traversal contains any PATH requiring steps and if
         // it does, note it so that the keep labels are set to null later on
         // which signals PathProcessors to not drop path information
-        boolean hasPathStep = false;
-        final List<PathStep> pathSteps = 
TraversalHelper.getStepsOfAssignableClassRecursively(PathStep.class, traversal);
-        final List<SubgraphStep> subgraphSteps = 
TraversalHelper.getStepsOfAssignableClassRecursively(SubgraphStep.class, 
traversal);
-        if (!pathSteps.isEmpty() || !subgraphSteps.isEmpty()) {
-            hasPathStep = true;
-        }
+        final boolean hasPathStep = TraversalHelper.anyStepRecursively(step -> 
step.getRequirements().contains(TraverserRequirement.PATH), traversal);
 
         final List<Step> steps = traversal.getSteps();
-        for(int i = steps.size() - 1; i >= 0; i--) {
-            Step currentStep = steps.get(i);
+        for (int i = steps.size() - 1; i >= 0; i--) {
+            final Step currentStep = steps.get(i);
             if (!hasPathStep) {
                 // maintain our list of labels to keep, repeatedly adding 
labels that were found during
                 // the last iteration
@@ -145,22 +135,19 @@ public final class PrunePathStrategy extends 
AbstractTraversalStrategy<Traversal
 
                 final Set<String> labels = 
PathUtil.getReferencedLabels(currentStep);
                 for (final String label : labels) {
-                    if (foundLabels.contains(label)) {
+                    if (foundLabels.contains(label))
                         keepLabels.add(label);
-                    } else {
+                    else
                         foundLabels.add(label);
-                    }
                 }
-
-                if (currentStep instanceof PathProcessor) {
+                // add the keep labels to the path processor
+                if (currentStep instanceof PathProcessor)
                     ((PathProcessor) currentStep).setKeepLabels(new 
HashSet<>(keepLabels));
-                }
             } else {
-                // if there is a PathStep or SubgraphStep in the traversal, do 
not drop labels
-                if (currentStep instanceof PathProcessor) {
-                    // set keep labels to null so that no labels are dropped
+                // if there is a PATh requiring step in the traversal, do not 
drop labels
+                // set keep labels to null so that no labels are dropped
+                if (currentStep instanceof PathProcessor)
                     ((PathProcessor) currentStep).setKeepLabels(null);
-                }
             }
         }
     }

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f9c6ea62/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/PathUtil.java
----------------------------------------------------------------------
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/PathUtil.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/PathUtil.java
index d07de50..5a9bb0a 100644
--- 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/PathUtil.java
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/PathUtil.java
@@ -34,7 +34,7 @@ import java.util.Set;
  */
 public class PathUtil {
 
-    public static Set<String> getReferencedLabels(Traversal.Admin<?, ?> 
traversal) {
+    public static Set<String> getReferencedLabels(final Traversal.Admin<?, ?> 
traversal) {
         final Set<String> referencedLabels = new HashSet<>();
         for(final Step<?, ?> step : traversal.getSteps()) {
             referencedLabels.addAll(getReferencedLabels(step));
@@ -42,13 +42,13 @@ public class PathUtil {
         return referencedLabels;
     }
 
-    public static Set<String> getReferencedLabels(Step step) {
+    public static Set<String> getReferencedLabels(final Step step) {
         final Set<String> referencedLabels = new HashSet<>();
 
         if (step instanceof Parameterizing) {
             Parameters parameters = ((Parameterizing) step).getParameters();
-            for (Traversal.Admin trav : parameters.getTraversals()) {
-                for (Object ss : trav.getSteps()) {
+            for (final Traversal.Admin trav : parameters.getTraversals()) {
+                for (final Object ss : trav.getSteps()) {
                     if (ss instanceof Scoping) {
                         Set<String> labels = ((Scoping) ss).getScopeKeys();
                         for (String label : labels) {
@@ -60,7 +60,7 @@ public class PathUtil {
         }
 
         if (step instanceof Scoping) {
-            Set<String> labels = new HashSet<>(((Scoping) 
step).getScopeKeys());
+            final Set<String> labels = new HashSet<>(((Scoping) 
step).getScopeKeys());
             if (step instanceof MatchStep) {
                 // if this is the last step, keep everything, else just add 
founds
                 if (step.getNextStep() instanceof EmptyStep) {

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f9c6ea62/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/PrunePathStrategyTest.java
----------------------------------------------------------------------
diff --git 
a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/PrunePathStrategyTest.java
 
b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/PrunePathStrategyTest.java
index e510066..b064b47 100644
--- 
a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/PrunePathStrategyTest.java
+++ 
b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/PrunePathStrategyTest.java
@@ -26,6 +26,7 @@ import 
org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
 import org.apache.tinkerpop.gremlin.process.traversal.step.PathProcessor;
 import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent;
 import 
org.apache.tinkerpop.gremlin.process.traversal.util.DefaultTraversalStrategies;
+import org.apache.tinkerpop.gremlin.structure.Graph;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
@@ -48,45 +49,48 @@ import static org.junit.Assert.assertEquals;
 @RunWith(Parameterized.class)
 public class PrunePathStrategyTest {
 
+    private final List<TraversalStrategies> strategies = Arrays.asList(
+            new 
DefaultTraversalStrategies().addStrategies(PrunePathStrategy.instance()),
+            new 
DefaultTraversalStrategies().addStrategies(PrunePathStrategy.instance(), 
PathProcessorStrategy.instance()),
+            new 
DefaultTraversalStrategies().addStrategies(PrunePathStrategy.instance(), 
PathProcessorStrategy.instance(), MatchPredicateStrategy.instance()),
+            new 
DefaultTraversalStrategies().addStrategies(PrunePathStrategy.instance(), 
PathProcessorStrategy.instance(), MatchPredicateStrategy.instance(), 
RepeatUnrollStrategy.instance()),
+            TraversalStrategies.GlobalCache.getStrategies(Graph.class));
+
     @Parameterized.Parameter(value = 0)
     public Traversal.Admin traversal;
 
     @Parameterized.Parameter(value = 1)
     public List<Set<String>> labels;
 
-    void applyPrunePathStrategy(final Traversal traversal) {
-        final TraversalStrategies strategies = new 
DefaultTraversalStrategies();
-        strategies.addStrategies(PrunePathStrategy.instance());
-        traversal.asAdmin().setStrategies(strategies);
-        traversal.asAdmin().applyStrategies();
-    }
-
     @Test
     public void doTest() {
-        applyPrunePathStrategy(traversal);
-        // get all path processors
-        List<Object> keepLabels = getKeepLabels(traversal);
-
-        assertEquals(labels, keepLabels);
+        for (final TraversalStrategies currentStrategies : this.strategies) {
+            final Traversal.Admin<?, ?> currentTraversal = 
this.traversal.clone();
+            currentTraversal.setStrategies(currentStrategies);
+            System.out.println(currentStrategies);
+            currentTraversal.applyStrategies();
+            final List<Object> keepLabels = getKeepLabels(currentTraversal);
+            assertEquals(this.labels, keepLabels);
+        }
     }
 
-    private List<Object> getKeepLabels(Traversal.Admin traversal) {
+    private List<Object> getKeepLabels(final Traversal.Admin<?, ?> traversal) {
         List<Object> keepLabels = new ArrayList<>();
-        for(Step step : (List<Step>)traversal.getSteps()) {
-            if(step instanceof PathProcessor) {
+        for (Step step : traversal.getSteps()) {
+            if (step instanceof PathProcessor) {
                 final Set<String> keepers = ((PathProcessor) 
step).getKeepLabels();
-                if(keepers != null) {
+                if (keepers != null) {
                     keepLabels.add(keepers);
                 }
             }
-            if(step instanceof TraversalParent) {
-                TraversalParent parent = (TraversalParent) step;
-                List<Traversal.Admin<?, ?>> children = new ArrayList<>();
+            if (step instanceof TraversalParent) {
+                final TraversalParent parent = (TraversalParent) step;
+                final List<Traversal.Admin<?, ?>> children = new ArrayList<>();
                 children.addAll(parent.getGlobalChildren());
                 children.addAll(parent.getLocalChildren());
-                for(Traversal.Admin<?, ?> child : children) {
-                    List<Object> childLabels = getKeepLabels(child);
-                    if(childLabels.size() > 0) {
+                for (final Traversal.Admin<?, ?> child : children) {
+                    final List<Object> childLabels = getKeepLabels(child);
+                    if (childLabels.size() > 0) {
                         keepLabels.add(childLabels);
                     }
                 }
@@ -99,20 +103,27 @@ public class PrunePathStrategyTest {
     public static Iterable<Object[]> generateTestParameters() {
 
         return Arrays.asList(new Object[][]{
-                {__.V().as("a").out().as("b").where(neq("a")).out(), 
Arrays.asList(Collections.EMPTY_SET)},
-                {__.V().as("a").out().where(neq("a")).out().select("a"), 
Arrays.asList(Collections.singleton("a"), Collections.EMPTY_SET)},
+                {__.out(), Arrays.asList()},
+                {__.V().as("a").out().as("b").where(neq("a")).out(), 
Arrays.asList(Collections.emptySet())},
+                {__.V().as("a").out().where(neq("a")).out().select("a"), 
Arrays.asList(Collections.singleton("a"), Collections.emptySet())},
+                
{__.V().as("a").out().as("b").where(neq("a")).out().select("a", 
"b").out().select("b"), Arrays.asList(new HashSet<>(Arrays.asList("a", "b")), 
Collections.singleton("b"), Collections.emptySet())},
                 {__.V().match(__.as("a").out().as("b")), Arrays.asList(new 
HashSet<>(Arrays.asList("a", "b")))},
-                {__.V().match(__.as("a").out().as("b")).select("a"), 
Arrays.asList(new HashSet<>(Arrays.asList("a", "b")), Collections.EMPTY_SET)},
+                {__.V().match(__.as("a").out().as("b")).select("a"), 
Arrays.asList(new HashSet<>(Arrays.asList("a", "b")), Collections.emptySet())},
                 {__.V().out().out().match(
                         as("a").in("created").as("b"),
                         
as("b").in("knows").as("c")).select("c").out("created").where(neq("a")).values("name"),
-                        Arrays.asList(new HashSet<>(Arrays.asList("a", "b", 
"c")), Collections.singleton("a"), Collections.EMPTY_SET)},
+                        Arrays.asList(new HashSet<>(Arrays.asList("a", "b", 
"c")), Collections.singleton("a"), Collections.emptySet())},
                 {__.V().as("a").out().select("a").path(), Arrays.asList()},
-                {__.V().as("a").out().select("a").subgraph("b"), 
Arrays.asList()},
-                {__.V().out().as("a").where(neq("a")).out().where(neq("a")), 
Arrays.asList(Collections.singleton("a"), Collections.EMPTY_SET)},
-                
{__.V().out().as("a").where(__.out().select("a").values("prop").count().is(gte(1))).out().where(neq("a")),
 Arrays.asList(Arrays.asList(Collections.singleton("a")), 
Collections.EMPTY_SET)},
+                {__.V().as("a").out().select("a").subgraph("b"), 
Arrays.asList(Collections.emptySet())},
+                {__.V().as("a").out().select("a").subgraph("b").select("a"), 
Arrays.asList(Collections.singleton("a"), Collections.emptySet())},
+                
{__.V().out().as("a").where(neq("a")).out().where(neq("a")).out(), 
Arrays.asList(Collections.singleton("a"), Collections.emptySet())},
+                
{__.V().out().as("a").where(__.out().select("a").values("prop").count().is(gte(1))).out().where(neq("a")),
 Arrays.asList(Arrays.asList(Collections.singleton("a")), 
Collections.emptySet())},
+                {__.V().as("a").out().as("b").where(__.out().select("a", "b", 
"c").values("prop").count().is(gte(1))).out().where(neq("a")).out().select("b"),
+                        Arrays.asList(Arrays.asList(new 
HashSet<>(Arrays.asList("a", "b", "c"))), Collections.singleton("b"), 
Collections.emptySet())},
                 
{__.outE().inV().group().by(__.inE().outV().groupCount().by(__.both().count().is(P.gt(2)))),
 Arrays.asList()},
-                
{__.V().as("a").repeat(__.out().where(neq("a"))).emit().select("a").values("test"),
 Arrays.asList(Arrays.asList(Collections.singleton("a")), 
Collections.EMPTY_SET)}
+                
{__.V().as("a").repeat(__.out().where(neq("a"))).emit().select("a").values("test"),
 Arrays.asList(Arrays.asList(Collections.singleton("a")), 
Collections.emptySet())},
+                // given the way this test harness is structured, I have to 
manual test for RepeatUnrollStrategy (and it works) TODO: add more test 
parameters
+                // 
{__.V().as("a").repeat(__.out().where(neq("a"))).times(3).select("a").values("test"),
 Arrays.asList(Collections.singleton("a"), Collections.singleton("a"), 
Collections.singleton("a"), Collections.emptySet())}
         });
     }
 }

Reply via email to