renamed PrunePathStrategy to PathRetractionStrategy to better align with the 
Path API retract() naming. PathRetractionStrategy should NOT execute if there 
are lambdas steps or path steps. Do a global analysis to ensure that. Added a 
new MatchTest to ensure a sneaking suspicion I had with lazy barrier wasn't 
true -- it wasn't, thats good.


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

Branch: refs/heads/TINKERPOP-1278
Commit: 01fd5dc507f9f135f458be32661c92f39569212f
Parents: 983538d
Author: Marko A. Rodriguez <okramma...@gmail.com>
Authored: Mon Jul 11 09:49:28 2016 -0600
Committer: Marko A. Rodriguez <okramma...@gmail.com>
Committed: Mon Jul 11 09:49:28 2016 -0600

----------------------------------------------------------------------
 .../process/traversal/TraversalStrategies.java  |   4 +-
 .../process/traversal/step/map/MatchStep.java   |  40 ++--
 .../AdjacentToIncidentStrategy.java             |   2 +-
 .../IncidentToAdjacentStrategy.java             |   5 +-
 .../optimization/PathRetractionStrategy.java    | 193 ++++++++++++++++++
 .../optimization/PrunePathStrategy.java         | 195 -------------------
 .../traversal/step/map/MatchStepTest.java       |   6 +-
 .../PathRetractionStrategyTest.java             | 184 +++++++++++++++++
 .../optimization/PrunePathStrategyTest.java     | 183 -----------------
 .../groovy/loaders/SugarLoaderTest.groovy       |  12 +-
 .../traversal/step/map/GroovyMatchTest.groovy   |   5 +
 .../process/traversal/step/map/MatchTest.java   |  17 ++
 .../structure/TinkerGraphPlayTest.java          |  10 +-
 13 files changed, 439 insertions(+), 417 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/01fd5dc5/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 ee3fa76..53b2e77 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
@@ -29,7 +29,7 @@ import 
org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.Inci
 import 
org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.MatchPredicateStrategy;
 import 
org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.OrderLimitStrategy;
 import 
org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.PathProcessorStrategy;
-import 
org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.PrunePathStrategy;
+import 
org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.PathRetractionStrategy;
 import 
org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.RangeByIsCountStrategy;
 import 
org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.RepeatUnrollStrategy;
 import 
org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.ComputerVerificationStrategy;
@@ -197,7 +197,7 @@ public interface TraversalStrategies extends Serializable, 
Cloneable {
                     MatchPredicateStrategy.instance(),
                     RepeatUnrollStrategy.instance(),
                     RangeByIsCountStrategy.instance(),
-                    PrunePathStrategy.instance(),
+                    PathRetractionStrategy.instance(),
                     ProfileStrategy.instance(),
                     StandardVerificationStrategy.instance());
 

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/01fd5dc5/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 813b85c..998b7d3 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
@@ -38,7 +38,7 @@ import 
org.apache.tinkerpop.gremlin.process.traversal.step.util.ComputerAwareSte
 import org.apache.tinkerpop.gremlin.process.traversal.step.util.ProfileStep;
 import 
org.apache.tinkerpop.gremlin.process.traversal.step.util.ReducingBarrierStep;
 import 
org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.ConnectiveStrategy;
-import 
org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.PrunePathStrategy;
+import 
org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.PathRetractionStrategy;
 import 
org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
 import 
org.apache.tinkerpop.gremlin.process.traversal.traverser.util.TraverserSet;
 import org.apache.tinkerpop.gremlin.process.traversal.util.DefaultTraversal;
@@ -180,6 +180,24 @@ public final class MatchStep<S, E> extends 
ComputerAwareStep<S, Map<String, E>>
     }
 
     @Override
+    public void setKeepLabels(Set<String> labels) {
+        this.keepLabels = labels;
+    }
+
+    @Override
+    public Set<String> getKeepLabels() {
+        return keepLabels;
+    }
+
+    public Set<String> getMatchEndLabels() {
+        return this.matchEndLabels;
+    }
+
+    public Set<String> getMatchStartLabels() {
+        return this.matchStartLabels;
+    }
+
+    @Override
     public Set<String> getScopeKeys() {
         if (null == this.scopeKeys) {
             this.scopeKeys = new HashSet<>();
@@ -327,7 +345,7 @@ public final class MatchStep<S, E> extends 
ComputerAwareStep<S, Map<String, E>>
             } else if (this.standardAlgorithmBarrier.isEmpty()) {
                 for (final Traversal.Admin<?, ?> matchTraversal : 
this.matchTraversals) {
                     while (matchTraversal.hasNext() &&
-                            this.standardAlgorithmBarrier.size() < 
PrunePathStrategy.MAX_BARRIER_SIZE) { // TODO: perhaps make MatchStep a 
LocalBarrierStep ??
+                            this.standardAlgorithmBarrier.size() < 
PathRetractionStrategy.DEFAULT_STANDARD_BARRIER_SIZE) { // TODO: perhaps make 
MatchStep a LocalBarrierStep ??
                         
this.standardAlgorithmBarrier.add(matchTraversal.getEndStep().next());
                     }
                 }
@@ -752,22 +770,4 @@ public final class MatchStep<S, E> extends 
ComputerAwareStep<S, Map<String, E>>
             }
         }
     }
-
-    @Override
-    public void setKeepLabels(Set<String> labels) {
-        this.keepLabels = labels;
-    }
-
-    @Override
-    public Set<String> getKeepLabels() {
-        return keepLabels;
-    }
-
-    public Set<String> getMatchEndLabels() {
-        return this.matchEndLabels;
-    }
-
-    public Set<String> getMatchStartLabels() {
-        return this.matchStartLabels;
-    }
 }

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/01fd5dc5/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/AdjacentToIncidentStrategy.java
----------------------------------------------------------------------
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/AdjacentToIncidentStrategy.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/AdjacentToIncidentStrategy.java
index aace11a..2d19479 100644
--- 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/AdjacentToIncidentStrategy.java
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/AdjacentToIncidentStrategy.java
@@ -67,7 +67,7 @@ public final class AdjacentToIncidentStrategy extends 
AbstractTraversalStrategy<
     }
 
     @Override
-    public void apply(Traversal.Admin<?, ?> traversal) {
+    public void apply(final Traversal.Admin<?, ?> traversal) {
         final List<Step> steps = traversal.getSteps();
         final int size = steps.size() - 1;
         Step prev = null;

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/01fd5dc5/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/IncidentToAdjacentStrategy.java
----------------------------------------------------------------------
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/IncidentToAdjacentStrategy.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/IncidentToAdjacentStrategy.java
index 712110d..18e1c50 100644
--- 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/IncidentToAdjacentStrategy.java
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/IncidentToAdjacentStrategy.java
@@ -69,9 +69,8 @@ public final class IncidentToAdjacentStrategy extends 
AbstractTraversalStrategy<
     }
 
     @Override
-    public void apply(Traversal.Admin<?, ?> traversal) {
-        final Traversal.Admin root = 
TraversalHelper.getRootTraversal(traversal);
-        if 
(TraversalHelper.hasStepOfAssignableClassRecursively(INVALIDATING_STEP_CLASSES, 
root))
+    public void apply(final Traversal.Admin<?, ?> traversal) {
+        if 
(TraversalHelper.hasStepOfAssignableClassRecursively(INVALIDATING_STEP_CLASSES, 
TraversalHelper.getRootTraversal(traversal)))
             return;
         final Collection<Pair<VertexStep, Step>> stepsToReplace = new 
ArrayList<>();
         Step prev = null;

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/01fd5dc5/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/PathRetractionStrategy.java
----------------------------------------------------------------------
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/PathRetractionStrategy.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/PathRetractionStrategy.java
new file mode 100644
index 0000000..ee697f3
--- /dev/null
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/PathRetractionStrategy.java
@@ -0,0 +1,193 @@
+/*
+ * 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.strategy.optimization;
+
+import org.apache.tinkerpop.gremlin.process.traversal.Step;
+import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
+import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.step.Barrier;
+import org.apache.tinkerpop.gremlin.process.traversal.step.LambdaHolder;
+import org.apache.tinkerpop.gremlin.process.traversal.step.PathProcessor;
+import org.apache.tinkerpop.gremlin.process.traversal.step.branch.RepeatStep;
+import 
org.apache.tinkerpop.gremlin.process.traversal.step.filter.DedupGlobalStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.MapStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.MatchStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.NoOpBarrierStep;
+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 org.javatuples.Pair;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * @author Ted Wilmes (http://twilmes.org)
+ * @author Marko A. Rodriguez (http://markorodriguez.com)
+ */
+public final class PathRetractionStrategy extends 
AbstractTraversalStrategy<TraversalStrategy.OptimizationStrategy> implements 
TraversalStrategy.OptimizationStrategy {
+
+    public static Integer DEFAULT_STANDARD_BARRIER_SIZE = 2500;
+
+    private static final PathRetractionStrategy INSTANCE = new 
PathRetractionStrategy(DEFAULT_STANDARD_BARRIER_SIZE);
+    // these strategies do strong rewrites involving path labeling and thus, 
should run prior to PathRetractionStrategy
+    private static final Set<Class<? extends OptimizationStrategy>> PRIORS = 
new HashSet<>(Arrays.asList(
+            RepeatUnrollStrategy.class, MatchPredicateStrategy.class, 
PathProcessorStrategy.class));
+
+    private final int standardBarrierSize;
+
+    private PathRetractionStrategy(final int standardBarrierSize) {
+        this.standardBarrierSize = standardBarrierSize;
+    }
+
+    public static PathRetractionStrategy instance() {
+        return INSTANCE;
+    }
+
+    @Override
+    public void apply(final Traversal.Admin<?, ?> traversal) {
+        // do not apply this strategy if there are lambdas as you can't 
introspect to know what path information the lambdas are using
+        // do not apply this strategy if a PATH requirement step is being used 
(in the future, we can do PATH requirement lookhead to be more intelligent 
about its usage)
+        if (TraversalHelper.anyStepRecursively(step -> step instanceof 
LambdaHolder || step.getRequirements().contains(TraverserRequirement.PATH), 
TraversalHelper.getRootTraversal(traversal)))
+            return;
+
+        final boolean onGraphComputer = 
TraversalHelper.onGraphComputer(traversal);
+        final Set<String> foundLabels = new HashSet<>();
+        final Set<String> keepLabels = new HashSet<>();
+
+        final List<Step> steps = traversal.getSteps();
+        for (int i = steps.size() - 1; i >= 0; i--) {
+            final Step currentStep = steps.get(i);
+            // maintain our list of labels to keep, repeatedly adding labels 
that were found during
+            // the last iteration
+            keepLabels.addAll(foundLabels);
+
+            final Set<String> labels = 
PathUtil.getReferencedLabels(currentStep);
+            for (final String label : labels) {
+                if (foundLabels.contains(label))
+                    keepLabels.add(label);
+                else
+                    foundLabels.add(label);
+            }
+            // add the keep labels to the path processor
+            if (currentStep instanceof PathProcessor) {
+                final PathProcessor pathProcessor = (PathProcessor) 
currentStep;
+                if (currentStep instanceof MatchStep && 
(currentStep.getNextStep().equals(EmptyStep.instance()) || 
currentStep.getNextStep() instanceof DedupGlobalStep)) {
+                    pathProcessor.setKeepLabels(((MatchStep) 
currentStep).getMatchStartLabels());
+                    pathProcessor.getKeepLabels().addAll(((MatchStep) 
currentStep).getMatchEndLabels());
+                } else
+                    pathProcessor.setKeepLabels(new HashSet<>(keepLabels));
+
+                if (currentStep.getTraversal().getParent() instanceof 
MatchStep) {
+                    pathProcessor.setKeepLabels(((MatchStep) 
currentStep.getTraversal().getParent().asStep()).getMatchStartLabels());
+                    pathProcessor.getKeepLabels().addAll(((MatchStep) 
currentStep.getTraversal().getParent().asStep()).getMatchEndLabels());
+                }
+
+                // OLTP barrier optimization that will try and bulk traversers 
after a path processor step to thin the stream
+                if (!onGraphComputer &&
+                        !(currentStep.getNextStep() instanceof Barrier) &&
+                        !(currentStep.getTraversal().getParent() instanceof 
MatchStep))
+                    TraversalHelper.insertAfterStep(new 
NoOpBarrierStep<>(traversal, this.standardBarrierSize), currentStep, traversal);
+            }
+        }
+
+        keepLabels.addAll(foundLabels);
+
+        // build a list of parent traversals and their required labels
+        Step<?, ?> parent = traversal.getParent().asStep();
+        final List<Pair<Step, Set<String>>> parentKeeperPairs = new 
ArrayList<>();
+        while (!parent.equals(EmptyStep.instance())) {
+            parentKeeperPairs.add(new Pair<>(parent, 
PathUtil.whichLabelsReferencedFromHereForward(parent)));
+            parent = parent.getTraversal().getParent().asStep();
+        }
+
+        // reverse the parent traversal list so that labels are kept from the 
top down
+        Collections.reverse(parentKeeperPairs);
+
+        boolean hasRepeat = false;
+
+        final Set<String> keeperTrail = new HashSet<>();
+        for (final Pair<Step, Set<String>> pair : parentKeeperPairs) {
+            Step step = pair.getValue0();
+            final Set<String> levelLabels = pair.getValue1();
+
+            if (step instanceof RepeatStep) {
+                hasRepeat = true;
+            }
+
+            // propagate requirements of keep labels back through the 
traversal's previous steps
+            // to ensure that the label is not dropped before it reaches the 
step(s) that require it
+            step = step.getPreviousStep();
+            while (!(step.equals(EmptyStep.instance()))) {
+                if (step instanceof PathProcessor) {
+                    if (((PathProcessor) step).getKeepLabels() == null) {
+                        ((PathProcessor) step).setKeepLabels(new 
HashSet<>(keepLabels));
+                    } else {
+                        ((PathProcessor) step).getKeepLabels().addAll(new 
HashSet<>(keepLabels));
+                    }
+                }
+                step = step.getPreviousStep();
+            }
+
+            // propagate keep labels forwards if future steps require a 
particular nested label
+            while (!(step.equals(EmptyStep.instance()))) {
+                if (step instanceof PathProcessor) {
+                    final Set<String> referencedLabels = 
PathUtil.getReferencedLabelsAfterStep(step);
+                    for (final String ref : referencedLabels) {
+                        if (levelLabels.contains(ref)) {
+                            if (((PathProcessor) step).getKeepLabels() == 
null) {
+                                final HashSet<String> newKeepLabels = new 
HashSet<>();
+                                newKeepLabels.add(ref);
+                                ((PathProcessor) 
step).setKeepLabels(newKeepLabels);
+                            } else {
+                                ((PathProcessor) 
step).getKeepLabels().addAll(Collections.singleton(ref));
+                            }
+                        }
+                    }
+                }
+
+                step = step.getNextStep();
+            }
+
+            keeperTrail.addAll(levelLabels);
+        }
+
+        for (final Step currentStep : traversal.getSteps()) {
+            // go back through current level and add all keepers
+            // if there is one more RepeatSteps in this traversal's lineage, 
preserve keep labels
+            if (currentStep instanceof PathProcessor) {
+                ((PathProcessor) 
currentStep).getKeepLabels().addAll(keeperTrail);
+                if (hasRepeat) {
+                    ((PathProcessor) 
currentStep).getKeepLabels().addAll(keepLabels);
+                }
+            }
+        }
+    }
+
+    @Override
+    public Set<Class<? extends OptimizationStrategy>> applyPrior() {
+        return PRIORS;
+    }
+}

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/01fd5dc5/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
deleted file mode 100644
index b8a5b39..0000000
--- 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/PrunePathStrategy.java
+++ /dev/null
@@ -1,195 +0,0 @@
-/*
- * 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.strategy.optimization;
-
-import org.apache.tinkerpop.gremlin.process.traversal.Step;
-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.branch.RepeatStep;
-import 
org.apache.tinkerpop.gremlin.process.traversal.step.filter.DedupGlobalStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.map.MatchStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.map.NoOpBarrierStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.util.EmptyStep;
-import 
org.apache.tinkerpop.gremlin.process.traversal.step.util.ReducingBarrierStep;
-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 org.javatuples.Pair;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-/**
- * @author Ted Wilmes (http://twilmes.org)
- * @author Marko A. Rodriguez (http://markorodriguez.com)
- */
-public final class PrunePathStrategy extends 
AbstractTraversalStrategy<TraversalStrategy.OptimizationStrategy> implements 
TraversalStrategy.OptimizationStrategy {
-
-    public static Integer MAX_BARRIER_SIZE = 2500;
-
-    private static final PrunePathStrategy INSTANCE = new PrunePathStrategy();
-    // 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() {
-    }
-
-    public static PrunePathStrategy instance() {
-        return INSTANCE;
-    }
-
-    @Override
-    public void apply(final Traversal.Admin<?, ?> traversal) {
-        final boolean onGraphComputer = 
TraversalHelper.onGraphComputer(traversal);
-        final Set<String> foundLabels = new HashSet<>();
-        final Set<String> keepLabels = new HashSet<>();
-
-        // check if the traversal contains any PATH requiring steps and if
-        // it does, note it so that the keep labels are set to null
-        // which signals PathProcessors to not drop path information
-        final boolean hasPathStep = TraversalHelper.anyStepRecursively(step -> 
step.getRequirements().contains(TraverserRequirement.PATH), traversal);
-        if (hasPathStep) {
-            for (final Step<?, ?> step : traversal.getSteps()) {
-                if (step instanceof PathProcessor) {
-                    ((PathProcessor) step).setKeepLabels(null);
-                }
-            }
-            return;
-        }
-
-        final List<Step> steps = traversal.getSteps();
-        for (int i = steps.size() - 1; i >= 0; i--) {
-            final Step currentStep = steps.get(i);
-            // maintain our list of labels to keep, repeatedly adding labels 
that were found during
-            // the last iteration
-            keepLabels.addAll(foundLabels);
-
-            final Set<String> labels = 
PathUtil.getReferencedLabels(currentStep);
-            for (final String label : labels) {
-                if (foundLabels.contains(label))
-                    keepLabels.add(label);
-                else
-                    foundLabels.add(label);
-            }
-            // add the keep labels to the path processor
-            if (currentStep instanceof PathProcessor) {
-                PathProcessor pathProcessor = (PathProcessor) currentStep;
-                if (currentStep instanceof MatchStep && 
(currentStep.getNextStep().equals(EmptyStep.instance()) || 
currentStep.getNextStep() instanceof DedupGlobalStep)) {
-                    pathProcessor.setKeepLabels(((MatchStep) 
currentStep).getMatchStartLabels());
-                    pathProcessor.getKeepLabels().addAll(((MatchStep) 
currentStep).getMatchEndLabels());
-                } else
-                    ((PathProcessor) currentStep).setKeepLabels(new 
HashSet<>(keepLabels));
-
-                if (currentStep.getTraversal().getParent() instanceof 
MatchStep) {
-                    pathProcessor.setKeepLabels(((MatchStep) 
currentStep.getTraversal().getParent().asStep()).getMatchStartLabels());
-                    pathProcessor.getKeepLabels().addAll(((MatchStep) 
currentStep.getTraversal().getParent().asStep()).getMatchEndLabels());
-                }
-
-                // OLTP barrier optimization that will try and bulk traversers 
after a path processor step to thin the stream
-                if (!onGraphComputer &&
-                        !(currentStep.getNextStep() instanceof 
ReducingBarrierStep) &&
-                        !(currentStep.getNextStep() instanceof 
NoOpBarrierStep) &&
-                        !(currentStep.getTraversal().getParent() instanceof 
MatchStep))
-                    TraversalHelper.insertAfterStep(new 
NoOpBarrierStep<>(traversal, MAX_BARRIER_SIZE), currentStep, traversal);
-            }
-        }
-
-        keepLabels.addAll(foundLabels);
-
-        // build a list of parent traversals and their required labels
-        Step<?, ?> parent = traversal.getParent().asStep();
-        final List<Pair<Step, Set<String>>> parentKeeperPairs = new 
ArrayList<>();
-        while (!parent.equals(EmptyStep.instance())) {
-            parentKeeperPairs.add(new Pair<>(parent, 
PathUtil.whichLabelsReferencedFromHereForward(parent)));
-            parent = parent.getTraversal().getParent().asStep();
-        }
-
-        // reverse the parent traversal list so that labels are kept from the 
top down
-        Collections.reverse(parentKeeperPairs);
-
-        boolean hasRepeat = false;
-
-        final Set<String> keeperTrail = new HashSet<>();
-        for (final Pair<Step, Set<String>> pair : parentKeeperPairs) {
-            Step step = pair.getValue0();
-            final Set<String> levelLabels = pair.getValue1();
-
-            if (step instanceof RepeatStep) {
-                hasRepeat = true;
-            }
-
-            // propagate requirements of keep labels back through the 
traversal's previous steps
-            // to ensure that the label is not dropped before it reaches the 
step(s) that require it
-            step = step.getPreviousStep();
-            while (!(step.equals(EmptyStep.instance()))) {
-                if (step instanceof PathProcessor) {
-                    if (((PathProcessor) step).getKeepLabels() == null) {
-                        ((PathProcessor) step).setKeepLabels(new 
HashSet<>(keepLabels));
-                    } else {
-                        ((PathProcessor) step).getKeepLabels().addAll(new 
HashSet<>(keepLabels));
-                    }
-                }
-                step = step.getPreviousStep();
-            }
-
-            // propagate keep labels forwards if future steps require a 
particular nested label
-            while (!(step.equals(EmptyStep.instance()))) {
-                if (step instanceof PathProcessor) {
-                    final Set<String> referencedLabels = 
PathUtil.getReferencedLabelsAfterStep(step);
-                    for (final String ref : referencedLabels) {
-                        if (levelLabels.contains(ref)) {
-                            if (((PathProcessor) step).getKeepLabels() == 
null) {
-                                ((PathProcessor) step).setKeepLabels(new 
HashSet<>(Arrays.asList(ref)));
-                            } else {
-                                ((PathProcessor) 
step).getKeepLabels().addAll(new HashSet<>(Arrays.asList(ref)));
-                            }
-                        }
-                    }
-                }
-
-                step = step.getNextStep();
-            }
-
-            keeperTrail.addAll(levelLabels);
-        }
-
-        for (final Step currentStep : traversal.getSteps()) {
-            // go back through current level and add all keepers
-            // if there is one more RepeatSteps in this traversal's lineage, 
preserve keep labels
-            if (currentStep instanceof PathProcessor) {
-                ((PathProcessor) 
currentStep).getKeepLabels().addAll(keeperTrail);
-                if (hasRepeat) {
-                    ((PathProcessor) 
currentStep).getKeepLabels().addAll(keepLabels);
-                }
-            }
-        }
-    }
-
-    @Override
-    public Set<Class<? extends OptimizationStrategy>> applyPrior() {
-        return PRIORS;
-    }
-}

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/01fd5dc5/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MatchStepTest.java
----------------------------------------------------------------------
diff --git 
a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MatchStepTest.java
 
b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MatchStepTest.java
index e47ab4b..201207b 100644
--- 
a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MatchStepTest.java
+++ 
b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MatchStepTest.java
@@ -23,16 +23,14 @@ import 
org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.TraversalEngine;
 import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategies;
 import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
-import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal;
 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.StepTest;
 import org.apache.tinkerpop.gremlin.process.traversal.step.filter.CoinStep;
 import 
org.apache.tinkerpop.gremlin.process.traversal.step.filter.ConnectiveStep;
 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.util.EmptyStep;
-import 
org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.PrunePathStrategy;
+import 
org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.PathRetractionStrategy;
 import 
org.apache.tinkerpop.gremlin.process.traversal.traverser.B_LP_O_P_S_SE_SL_TraverserGenerator;
 import 
org.apache.tinkerpop.gremlin.process.traversal.traverser.util.EmptyTraverser;
 import 
org.apache.tinkerpop.gremlin.process.traversal.util.DefaultTraversalStrategies;
@@ -445,7 +443,7 @@ public class MatchStepTest extends StepTest {
                 mTraversal5).asAdmin();
 
         final TraversalStrategies strategies = new 
DefaultTraversalStrategies();
-        strategies.addStrategies(PrunePathStrategy.instance());
+        strategies.addStrategies(PathRetractionStrategy.instance());
         traversal.asAdmin().setStrategies(strategies);
         traversal.asAdmin().applyStrategies();
 

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/01fd5dc5/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/PathRetractionStrategyTest.java
----------------------------------------------------------------------
diff --git 
a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/PathRetractionStrategyTest.java
 
b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/PathRetractionStrategyTest.java
new file mode 100644
index 0000000..4404cfd
--- /dev/null
+++ 
b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/PathRetractionStrategyTest.java
@@ -0,0 +1,184 @@
+/*
+ * 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.strategy.optimization;
+
+import org.apache.tinkerpop.gremlin.process.traversal.Order;
+import org.apache.tinkerpop.gremlin.process.traversal.P;
+import org.apache.tinkerpop.gremlin.process.traversal.Scope;
+import org.apache.tinkerpop.gremlin.process.traversal.Step;
+import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
+import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategies;
+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;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Set;
+
+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.neq;
+import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.as;
+import static 
org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.limit;
+import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.out;
+import static 
org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.select;
+import static 
org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.values;
+import static 
org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.PathRetractionStrategy.DEFAULT_STANDARD_BARRIER_SIZE;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * @author Ted Wilmes (http://twilmes.org)
+ * @author Marko A. Rodriguez (http://markorodriguez.com)
+ */
+@RunWith(Parameterized.class)
+public class PathRetractionStrategyTest {
+
+    private final List<TraversalStrategies> strategies = Arrays.asList(
+            new 
DefaultTraversalStrategies().addStrategies(PathRetractionStrategy.instance()),
+            new 
DefaultTraversalStrategies().addStrategies(PathRetractionStrategy.instance(), 
PathProcessorStrategy.instance()),
+            new 
DefaultTraversalStrategies().addStrategies(PathRetractionStrategy.instance(), 
PathProcessorStrategy.instance(), MatchPredicateStrategy.instance()),
+            new 
DefaultTraversalStrategies().addStrategies(PathRetractionStrategy.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 String labels;
+
+    @Parameterized.Parameter(value = 2)
+    public Traversal.Admin optimized;
+
+    @Test
+    public void doTest() {
+        for (final TraversalStrategies currentStrategies : this.strategies) {
+            final Traversal.Admin<?, ?> currentTraversal = 
this.traversal.clone();
+            currentTraversal.setStrategies(currentStrategies);
+            currentTraversal.applyStrategies();
+            assertEquals(this.labels, 
getKeepLabels(currentTraversal).toString());
+            if (null != optimized)
+                assertEquals(currentTraversal, optimized);
+        }
+    }
+
+    private List<Object> getKeepLabels(final Traversal.Admin<?, ?> traversal) {
+        List<Object> keepLabels = new ArrayList<>();
+        for (Step step : traversal.getSteps()) {
+            if (step instanceof PathProcessor) {
+                final Set<String> keepers = ((PathProcessor) 
step).getKeepLabels();
+                if (keepers != null)
+                    keepLabels.add(keepers);
+            }
+            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 (final Traversal.Admin<?, ?> child : children) {
+                    final List<Object> childLabels = getKeepLabels(child);
+                    if (childLabels.size() > 0) {
+                        keepLabels.add(childLabels);
+                    }
+                }
+            }
+        }
+        return keepLabels;
+    }
+
+    @Parameterized.Parameters(name = "{0}")
+    public static Iterable<Object[]> generateTestParameters() {
+
+        return Arrays.asList(new Object[][]{
+                {out(), "[]", null},
+                {__.V().as("a").out().as("b").where(neq("a")).out(), "[[]]", 
null},
+                {__.V().as("a").out().where(out().where(neq("a"))).out(), 
"[[[]]]", null},
+                {__.V().as("a").out().where(neq("a")).out().select("a"), 
"[[a], []]", null},
+                
{__.V().as("a").out().as("b").where(neq("a")).out().select("a", 
"b").out().select("b"), "[[a, b], [b], []]", null},
+                {__.V().match(__.as("a").out().as("b")), "[[a, b]]", null},
+                {__.V().match(__.as("a").out().as("b")).select("a"), "[[a], 
[]]", null},
+                {__.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"),
+                        "[[a, c], [a], []]", null},
+                {__.V().as("a").out().select("a").path(), "[]", null},
+                {__.V().as("a").out().select("a").map(t -> t.path().get("a")), 
"[]", null}, // lambda introspection is not possible
+                {__.V().as("a").out().select("a").subgraph("b"), "[[]]", null},
+                {__.V().as("a").out().select("a").subgraph("b").select("a"), 
"[[a], []]", null},
+                {__.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").path(),
+                        "[]", null},
+                
{__.V().out().as("a").where(neq("a")).out().where(neq("a")).out(), "[[a], []]", 
null},
+                
{__.V().out().as("a").where(out().select("a").values("prop").count().is(gte(1))).out().where(neq("a")),
 "[[[a]], []]", null},
+                {__.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"),
+                        "[[[a, b]], [b], []]", null},
+                
{__.outE().inV().group().by(__.inE().outV().groupCount().by(__.both().count().is(P.gt(2)))),
 "[]", null},
+                
{__.V().as("a").repeat(out().where(neq("a"))).emit().select("a").values("test"),
 "[[[a]], []]", null},
+                // 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())}
+                {__.V().as("a").out().as("b").select("a").out().out(), "[[]]", 
__.V().as("a").out().as("b").select("a").barrier(DEFAULT_STANDARD_BARRIER_SIZE).out().out()},
+                {__.V().as("a").out().as("b").select("a").count(), "[[]]", 
__.V().as("a").out().as("b").select("a").count()},
+                {__.V().as("a").out().as("b").select("a").barrier().count(), 
"[[]]", __.V().as("a").out().as("b").select("a").barrier().count()},
+                {__.V().as("a").out().as("b").where(P.gt("a")).out().out(), 
"[[]]", 
__.V().as("a").out().as("b").where(P.gt("a")).barrier(DEFAULT_STANDARD_BARRIER_SIZE).out().out()},
+                {__.V().as("a").out().as("b").where(P.gt("a")).count(), 
"[[]]", __.V().as("a").out().as("b").where(P.gt("a")).count()},
+                
{__.V().as("a").out().as("b").select("a").as("c").where(P.gt("b")).out(), 
"[[b], []]", 
__.V().as("a").out().as("b").select("a").as("c").barrier(DEFAULT_STANDARD_BARRIER_SIZE).where(P.gt("b")).barrier(DEFAULT_STANDARD_BARRIER_SIZE).out()},
+                
{__.V().select("c").map(select("c").map(select("c"))).select("c"), "[[c], [[c], 
[[c]]], []]", null},
+                
{__.V().select("c").map(select("c").map(select("c"))).select("b"), "[[b, c], 
[[b, c], [[b]]], []]", null},
+                {__.V().as("a").out().as("b").select("a").select("b").union(
+                        as("c").out().as("d", "e").select("c", 
"e").out().select("c"),
+                        as("c").out().as("d", "e").select("c", 
"e").out().select("c")).
+                        out().select("c"),
+                        "[[b, c, e], [c, e], [[c], [c]], [[c], [c]], []]", 
null},
+                {__.V().as("a").out().as("b").select("a").select("b").
+                        local(as("c").out().as("d", "e").select("c", 
"e").out().select("c")).
+                        out().select("c"),
+                        "[[b, c, e], [c, e], [[c], [c]], []]", null},
+                // TODO: same as above but note how path() makes things react
+//                
{__.V().as("a").out().as("b").select("a").select("b").path().local(as("c").out().as("d",
 "e").select("c", "e").out().select("c")).out().select("c"),
+//                        "[[[c, e], [c, e]]]", null},
+                
{__.V().as("a").out().as("b").select("a").select("b").repeat(out().as("c").select("b",
 "c").out().select("c")).out().select("c").out().select("b"),
+                        "[[b, c], [b, c], [[b, c], [b, c]], [b], []]", null},
+                
{__.V().as("a").out().as("b").select("a").select("b").repeat(out().as("c").select("b")).out().select("c").out().select("b"),
+                        "[[b, c], [b, c], [[b, c]], [b], []]", null},
+                
{__.V().as("a").out().as("b").select("a").select("b").repeat(out().as("c").select("b")),
+                        "[[b], [b], [[b]]]", null},
+                
{__.V().select("a").map(select("c").map(select("b"))).select("c"),
+                        "[[b, c], [[b, c], [[c]]], []]", null},
+                
{__.V().select("a").map(select("b").repeat(select("c"))).select("a"),
+                        "[[a, b, c], [[a, c], [[a, c]]], []]", null},
+                
{__.V().select("c").map(select("c").map(select("c"))).select("c"), "[[c], [[c], 
[[c]]], []]", null},
+                
{__.V().select("c").map(select("c").map(select("c"))).select("b"), "[[b, c], 
[[b, c], [[b]]], []]", null},
+                
{__.V().select("a").map(select("c").map(select("b"))).select("c"),
+                        "[[b, c], [[b, c], [[c]]], []]", null},
+                
{__.V().select("a").map(select("b").repeat(select("c"))).select("a"),
+                        "[[a, b, c], [[a, c], [[a, c]]], []]", null},
+                {__.V().out("created").project("a", 
"b").by("name").by(__.in("created").count()).order().by(select("b")).select("a"),
 "[[[a]], []]", null},
+                {__.order().by("weight", 
Order.decr).store("w").by("weight").filter(values("weight").as("cw").
+                        select("w").by(limit(Scope.local, 
1)).as("mw").where("cw", eq("mw"))).project("from", "to", 
"weight").by(__.outV()).by(__.inV()).by("weight"),
+                        "[[[cw, mw], []]]", null}
+        });
+    }
+}

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/01fd5dc5/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
deleted file mode 100644
index 44cc333..0000000
--- 
a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/PrunePathStrategyTest.java
+++ /dev/null
@@ -1,183 +0,0 @@
-/*
- * 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.strategy.optimization;
-
-import org.apache.tinkerpop.gremlin.process.traversal.Order;
-import org.apache.tinkerpop.gremlin.process.traversal.P;
-import org.apache.tinkerpop.gremlin.process.traversal.Scope;
-import org.apache.tinkerpop.gremlin.process.traversal.Step;
-import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
-import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategies;
-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;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Set;
-
-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.neq;
-import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.as;
-import static 
org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.limit;
-import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.out;
-import static 
org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.select;
-import static 
org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.values;
-import static 
org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.PrunePathStrategy.MAX_BARRIER_SIZE;
-import static org.junit.Assert.assertEquals;
-
-/**
- * @author Ted Wilmes (http://twilmes.org)
- * @author Marko A. Rodriguez (http://markorodriguez.com)
- */
-@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 String labels;
-
-    @Parameterized.Parameter(value = 2)
-    public Traversal.Admin optimized;
-
-    @Test
-    public void doTest() {
-        for (final TraversalStrategies currentStrategies : this.strategies) {
-            final Traversal.Admin<?, ?> currentTraversal = 
this.traversal.clone();
-            currentTraversal.setStrategies(currentStrategies);
-            currentTraversal.applyStrategies();
-            assertEquals(this.labels, 
getKeepLabels(currentTraversal).toString());
-            if (null != optimized)
-                assertEquals(currentTraversal, optimized);
-        }
-    }
-
-    private List<Object> getKeepLabels(final Traversal.Admin<?, ?> traversal) {
-        List<Object> keepLabels = new ArrayList<>();
-        for (Step step : traversal.getSteps()) {
-            if (step instanceof PathProcessor) {
-                final Set<String> keepers = ((PathProcessor) 
step).getKeepLabels();
-                if (keepers != null)
-                    keepLabels.add(keepers);
-            }
-            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 (final Traversal.Admin<?, ?> child : children) {
-                    final List<Object> childLabels = getKeepLabels(child);
-                    if (childLabels.size() > 0) {
-                        keepLabels.add(childLabels);
-                    }
-                }
-            }
-        }
-        return keepLabels;
-    }
-
-    @Parameterized.Parameters(name = "{0}")
-    public static Iterable<Object[]> generateTestParameters() {
-
-        return Arrays.asList(new Object[][]{
-                {out(), "[]", null},
-                {__.V().as("a").out().as("b").where(neq("a")).out(), "[[]]", 
null},
-                {__.V().as("a").out().where(out().where(neq("a"))).out(), 
"[[[]]]", null},
-                {__.V().as("a").out().where(neq("a")).out().select("a"), 
"[[a], []]", null},
-                
{__.V().as("a").out().as("b").where(neq("a")).out().select("a", 
"b").out().select("b"), "[[a, b], [b], []]", null},
-                {__.V().match(__.as("a").out().as("b")), "[[a, b]]", null},
-                {__.V().match(__.as("a").out().as("b")).select("a"), "[[a], 
[]]", null},
-                {__.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"),
-                        "[[a, c], [a], []]", null},
-                {__.V().as("a").out().select("a").path(), "[]", null},
-                {__.V().as("a").out().select("a").subgraph("b"), "[[]]", null},
-                {__.V().as("a").out().select("a").subgraph("b").select("a"), 
"[[a], []]", null},
-                {__.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").path(),
-                        "[]", null},
-                
{__.V().out().as("a").where(neq("a")).out().where(neq("a")).out(), "[[a], []]", 
null},
-                
{__.V().out().as("a").where(out().select("a").values("prop").count().is(gte(1))).out().where(neq("a")),
 "[[[a]], []]", null},
-                {__.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"),
-                        "[[[a, b]], [b], []]", null},
-                
{__.outE().inV().group().by(__.inE().outV().groupCount().by(__.both().count().is(P.gt(2)))),
 "[]", null},
-                
{__.V().as("a").repeat(out().where(neq("a"))).emit().select("a").values("test"),
 "[[[a]], []]", null},
-                // 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())}
-                {__.V().as("a").out().as("b").select("a").out().out(), "[[]]", 
__.V().as("a").out().as("b").select("a").barrier(MAX_BARRIER_SIZE).out().out()},
-                {__.V().as("a").out().as("b").select("a").count(), "[[]]", 
__.V().as("a").out().as("b").select("a").count()},
-                {__.V().as("a").out().as("b").select("a").barrier().count(), 
"[[]]", __.V().as("a").out().as("b").select("a").barrier().count()},
-                {__.V().as("a").out().as("b").where(P.gt("a")).out().out(), 
"[[]]", 
__.V().as("a").out().as("b").where(P.gt("a")).barrier(MAX_BARRIER_SIZE).out().out()},
-                {__.V().as("a").out().as("b").where(P.gt("a")).count(), 
"[[]]", __.V().as("a").out().as("b").where(P.gt("a")).count()},
-                
{__.V().as("a").out().as("b").select("a").as("c").where(P.gt("b")).out(), 
"[[b], []]", 
__.V().as("a").out().as("b").select("a").as("c").barrier(MAX_BARRIER_SIZE).where(P.gt("b")).barrier(MAX_BARRIER_SIZE).out()},
-                
{__.V().select("c").map(select("c").map(select("c"))).select("c"), "[[c], [[c], 
[[c]]], []]", null},
-                
{__.V().select("c").map(select("c").map(select("c"))).select("b"), "[[b, c], 
[[b, c], [[b]]], []]", null},
-                {__.V().as("a").out().as("b").select("a").select("b").union(
-                        as("c").out().as("d", "e").select("c", 
"e").out().select("c"),
-                        as("c").out().as("d", "e").select("c", 
"e").out().select("c")).
-                        out().select("c"),
-                        "[[b, c, e], [c, e], [[c], [c]], [[c], [c]], []]", 
null},
-                {__.V().as("a").out().as("b").select("a").select("b").
-                        local(as("c").out().as("d", "e").select("c", 
"e").out().select("c")).
-                        out().select("c"),
-                        "[[b, c, e], [c, e], [[c], [c]], []]", null},
-                // TODO: same as above but note how path() makes things react
-//                
{__.V().as("a").out().as("b").select("a").select("b").path().local(as("c").out().as("d",
 "e").select("c", "e").out().select("c")).out().select("c"),
-//                        "[[[c, e], [c, e]]]", null},
-                
{__.V().as("a").out().as("b").select("a").select("b").repeat(out().as("c").select("b",
 "c").out().select("c")).out().select("c").out().select("b"),
-                        "[[b, c], [b, c], [[b, c], [b, c]], [b], []]", null},
-                
{__.V().as("a").out().as("b").select("a").select("b").repeat(out().as("c").select("b")).out().select("c").out().select("b"),
-                        "[[b, c], [b, c], [[b, c]], [b], []]", null},
-                
{__.V().as("a").out().as("b").select("a").select("b").repeat(out().as("c").select("b")),
-                        "[[b], [b], [[b]]]", null},
-                
{__.V().select("a").map(select("c").map(select("b"))).select("c"),
-                        "[[b, c], [[b, c], [[c]]], []]", null},
-                
{__.V().select("a").map(select("b").repeat(select("c"))).select("a"),
-                        "[[a, b, c], [[a, c], [[a, c]]], []]", null},
-                
{__.V().select("c").map(select("c").map(select("c"))).select("c"), "[[c], [[c], 
[[c]]], []]", null},
-                
{__.V().select("c").map(select("c").map(select("c"))).select("b"), "[[b, c], 
[[b, c], [[b]]], []]", null},
-                
{__.V().select("a").map(select("c").map(select("b"))).select("c"),
-                        "[[b, c], [[b, c], [[c]]], []]", null},
-                
{__.V().select("a").map(select("b").repeat(select("c"))).select("a"),
-                        "[[a, b, c], [[a, c], [[a, c]]], []]", null},
-                {__.V().out("created").project("a", 
"b").by("name").by(__.in("created").count()).order().by(select("b")).select("a"),
 "[[[a]], []]", null},
-                {__.order().by("weight", 
Order.decr).store("w").by("weight").filter(values("weight").as("cw").
-                        select("w").by(limit(Scope.local, 
1)).as("mw").where("cw", eq("mw"))).project("from", "to", 
"weight").by(__.outV()).by(__.inV()).by("weight"),
-                        "[[[cw, mw], []]]", null}
-        });
-    }
-}

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/01fd5dc5/gremlin-groovy-test/src/main/groovy/org/apache/tinkerpop/gremlin/groovy/loaders/SugarLoaderTest.groovy
----------------------------------------------------------------------
diff --git 
a/gremlin-groovy-test/src/main/groovy/org/apache/tinkerpop/gremlin/groovy/loaders/SugarLoaderTest.groovy
 
b/gremlin-groovy-test/src/main/groovy/org/apache/tinkerpop/gremlin/groovy/loaders/SugarLoaderTest.groovy
index 54471cd..dc973c4 100644
--- 
a/gremlin-groovy-test/src/main/groovy/org/apache/tinkerpop/gremlin/groovy/loaders/SugarLoaderTest.groovy
+++ 
b/gremlin-groovy-test/src/main/groovy/org/apache/tinkerpop/gremlin/groovy/loaders/SugarLoaderTest.groovy
@@ -22,13 +22,18 @@ import org.apache.tinkerpop.gremlin.AbstractGremlinTest
 import org.apache.tinkerpop.gremlin.LoadGraphWith
 import org.apache.tinkerpop.gremlin.groovy.util.SugarTestHelper
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal
-import org.apache.tinkerpop.gremlin.structure.*
+import org.apache.tinkerpop.gremlin.structure.Edge
+import org.apache.tinkerpop.gremlin.structure.Graph
+import org.apache.tinkerpop.gremlin.structure.Property
+import org.apache.tinkerpop.gremlin.structure.Vertex
+import org.apache.tinkerpop.gremlin.structure.VertexProperty
 import org.apache.tinkerpop.gremlin.structure.util.StringFactory
-import org.junit.Ignore
 import org.junit.Test
 
 import static org.apache.tinkerpop.gremlin.process.traversal.P.eq
-import static org.junit.Assert.*
+import static org.junit.Assert.assertEquals
+import static org.junit.Assert.assertTrue
+import static org.junit.Assert.fail
 
 /**
  * @author Marko A. Rodriguez (http://markorodriguez.com)
@@ -91,7 +96,6 @@ class SugarLoaderTest extends AbstractGremlinTest {
         }
     }
 
-    @Ignore // TODO this is currently set to ignore because the 
PrunePathStrategy has no insight into the ending map and drops the path 
information
     @Test
     @LoadGraphWith(LoadGraphWith.GraphData.MODERN)
     public void shouldUseTraverserCategoryCorrectly() {

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/01fd5dc5/gremlin-groovy-test/src/main/groovy/org/apache/tinkerpop/gremlin/process/traversal/step/map/GroovyMatchTest.groovy
----------------------------------------------------------------------
diff --git 
a/gremlin-groovy-test/src/main/groovy/org/apache/tinkerpop/gremlin/process/traversal/step/map/GroovyMatchTest.groovy
 
b/gremlin-groovy-test/src/main/groovy/org/apache/tinkerpop/gremlin/process/traversal/step/map/GroovyMatchTest.groovy
index b269dfd..2dd2f03 100644
--- 
a/gremlin-groovy-test/src/main/groovy/org/apache/tinkerpop/gremlin/process/traversal/step/map/GroovyMatchTest.groovy
+++ 
b/gremlin-groovy-test/src/main/groovy/org/apache/tinkerpop/gremlin/process/traversal/step/map/GroovyMatchTest.groovy
@@ -348,5 +348,10 @@ public abstract class GroovyMatchTest {
             ).select('b', 'c').count();
             """)
         }
+
+        @Override
+        public Traversal<Vertex, Long> 
get_g_V_matchXa_knows_count_bX_selectXbX() {
+            new ScriptTraversal<>(g, "gremlin-groovy", 
"g.V().match(__.as('a').out('knows').count().as('b')).select('b')")
+        }
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/01fd5dc5/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MatchTest.java
----------------------------------------------------------------------
diff --git 
a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MatchTest.java
 
b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MatchTest.java
index 346caa8..2c4789e 100644
--- 
a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MatchTest.java
+++ 
b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MatchTest.java
@@ -148,6 +148,9 @@ public abstract class MatchTest extends 
AbstractGremlinProcessTest {
 
     public abstract Traversal<Vertex, Long> 
get_g_V_hasLabelXsongsX_matchXa_name_b__a_performances_cX_selectXb_cX_count();
 
+    // reducing barrier on lazy standard shouldn't yield an empty barrier
+    public abstract Traversal<Vertex, Long> 
get_g_V_matchXa_knows_count_bX_selectXbX();
+
     @Test
     @LoadGraphWith(MODERN)
     public void g_V_valueMap_matchXa_selectXnameX_bX() {
@@ -521,6 +524,15 @@ public abstract class MatchTest extends 
AbstractGremlinProcessTest {
         assertFalse(traversal.hasNext());
     }
 
+    @Test
+    @LoadGraphWith(MODERN)
+    public void g_V_matchXa_knows_count_bX_selectXbX() {
+        final Traversal<Vertex, Long> traversal = 
get_g_V_matchXa_knows_count_bX_selectXbX();
+        printTraversalForm(traversal);
+        checkResults(Arrays.asList(0L, 0L, 0L, 0L, 0L, 2L), traversal);
+        assertFalse(traversal.hasNext());
+    }
+
     public static class GreedyMatchTraversals extends Traversals {
         @Before
         public void setupTest() {
@@ -785,5 +797,10 @@ public abstract class MatchTest extends 
AbstractGremlinProcessTest {
                     __.as("a").values("performances").as("c")
             ).select("b", "c").count();
         }
+
+        @Override
+        public Traversal<Vertex, Long> 
get_g_V_matchXa_knows_count_bX_selectXbX() {
+            return 
g.V().match(as("a").out("knows").count().as("b")).select("b");
+        }
     }
 }

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/01fd5dc5/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraphPlayTest.java
----------------------------------------------------------------------
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 5bf3c48..7237dfa 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
@@ -26,7 +26,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.strategy.optimization.PrunePathStrategy;
+import 
org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.PathRetractionStrategy;
 import org.apache.tinkerpop.gremlin.structure.Graph;
 import org.apache.tinkerpop.gremlin.structure.T;
 import org.apache.tinkerpop.gremlin.structure.Vertex;
@@ -69,8 +69,8 @@ public class TinkerGraphPlayTest {
         graph.io(GraphMLIo.build()).readGraph("../data/grateful-dead.xml");
         //Graph graph = TinkerFactory.createModern();
 
-        GraphTraversalSource g = 
graph.traversal().withStrategies(PrunePathStrategy.instance());
-        GraphTraversalSource h = 
graph.traversal().withoutStrategies(PrunePathStrategy.class);
+        GraphTraversalSource g = 
graph.traversal().withStrategies(PathRetractionStrategy.instance());
+        GraphTraversalSource h = 
graph.traversal().withoutStrategies(PathRetractionStrategy.class);
 
         for (final GraphTraversalSource source : Arrays.asList(h, g)) {
             System.out.println(source.V().match(
@@ -309,8 +309,8 @@ public class TinkerGraphPlayTest {
         Graph graph = TinkerGraph.open();
         graph.io(GraphMLIo.build()).readGraph("../data/grateful-dead.xml");
 
-        GraphTraversalSource g = 
graph.traversal().withComputer(Computer.compute().workers(4)).withStrategies(PrunePathStrategy.instance());
-        GraphTraversalSource h = 
graph.traversal().withComputer(Computer.compute().workers(4)).withoutStrategies(PrunePathStrategy.class);
+        GraphTraversalSource g = 
graph.traversal().withComputer(Computer.compute().workers(4)).withStrategies(PathRetractionStrategy.instance());
+        GraphTraversalSource h = 
graph.traversal().withComputer(Computer.compute().workers(4)).withoutStrategies(PathRetractionStrategy.class);
 
         for (final GraphTraversalSource source : Arrays.asList(g, h)) {
             System.out.println(source.V().match(

Reply via email to