You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tinkerpop.apache.org by ok...@apache.org on 2015/11/18 15:30:41 UTC

[1/5] incubator-tinkerpop git commit: Fixed TINKERPOP3-679. There is now Traversal.explain() which returns a TraversalExplanation that has a pretty-print toString() as well as accessor methods for programmatic introspection. Added ExplainTest (dont want

Repository: incubator-tinkerpop
Updated Branches:
  refs/heads/master c42613ca7 -> 0feaa8b47


Fixed TINKERPOP3-679. There is now Traversal.explain() which returns a TraversalExplanation that has a pretty-print toString() as well as accessor methods for programmatic introspection. Added ExplainTest (dont want to get too crazy here or else provider strategies may cause problems). Added ExplainStep to the docs and made it so both ProfileStep and ExplainStep sections reference each other. Fixed a minor bug in IncidentToAdacentStrategy and AdjacentToIndicentStrategy which was relaized when playing around with explain(). Tada.


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

Branch: refs/heads/master
Commit: 87069b28f47a221f0d84efd675f431c144b13c32
Parents: b060c7d
Author: Marko A. Rodriguez <ok...@gmail.com>
Authored: Tue Nov 17 11:34:42 2015 -0700
Committer: Marko A. Rodriguez <ok...@gmail.com>
Committed: Tue Nov 17 11:34:42 2015 -0700

----------------------------------------------------------------------
 docs/src/the-traversal.asciidoc                 |  20 ++++
 .../gremlin/process/traversal/Traversal.java    |  12 ++
 .../AdjacentToIncidentStrategy.java             |   5 +-
 .../IncidentToAdjacentStrategy.java             |   6 +
 .../traversal/util/TraversalExplanation.java    | 118 +++++++++++++++++++
 .../step/sideEffect/GroovyExplainTest.groovy    |  35 ++++++
 .../process/GroovyProcessComputerSuite.java     |   2 +
 .../process/GroovyProcessStandardSuite.java     |   2 +
 .../gremlin/process/ProcessComputerSuite.java   |   2 +
 .../gremlin/process/ProcessStandardSuite.java   |   2 +
 .../traversal/step/sideEffect/ExplainTest.java  |  83 +++++++++++++
 .../structure/TinkerGraphPlayTest.java          |   4 +-
 12 files changed, 286 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/87069b28/docs/src/the-traversal.asciidoc
----------------------------------------------------------------------
diff --git a/docs/src/the-traversal.asciidoc b/docs/src/the-traversal.asciidoc
index 49d570f..d7134be 100644
--- a/docs/src/the-traversal.asciidoc
+++ b/docs/src/the-traversal.asciidoc
@@ -579,6 +579,24 @@ g.V().drop()
 g.V()
 ----
 
+[[explain-step]]
+Explain Step
+~~~~~~~~~~~~
+
+The `explain()`-step (*sideEffect*) will return a `TraversalExplanation`. A traversal explanation details how the
+traversal (prior to `explain()`) will be compiled given the registered <<traversalstrategy,traversal strategies>>.
+A `TraversalExplanation` has a `toString()` representation with 3-columns. The first column is the
+traversal strategy being applied. The second column is the traversal strategy category: [D]ecoration, [O]ptimization,
+[P]rovider optimization, [F]inalization, and [V]erification. Finally, the third column is the state of the traversal
+post strategy application. The final traversal is the resultant execution plan.
+
+[gremlin-groovy,modern]
+----
+g.V().outE().identity().inV().count().is(gt(5))
+----
+
+For traversal profiling information, please see <<profile-step,`profile()`>>-step.
+
 [[fold-step]]
 Fold Step
 ~~~~~~~~~
@@ -1282,6 +1300,8 @@ into a single traverser. That new traverser has a `Traverser.bulk()` that is the
 bulks. On the other hand, the `Count` represents the sum of all `Traverser.bulk()` results and thus, expresses the
 number of "represented" (not enumerated) traversers. `Traversers` will always be less than or equal to `Count`.
 
+For traversal compilation information, please see <<explain-step,`explain()`>>-step.
+
 [[range-step]]
 Range Step
 ~~~~~~~~~~

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/87069b28/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Traversal.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Traversal.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Traversal.java
index 13a3c57..2c467cf 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Traversal.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Traversal.java
@@ -26,6 +26,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent;
 import org.apache.tinkerpop.gremlin.process.traversal.step.util.BulkSet;
 import org.apache.tinkerpop.gremlin.process.traversal.step.util.EmptyStep;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
+import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalExplanation;
 import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper;
 import org.apache.tinkerpop.gremlin.structure.Graph;
 
@@ -171,6 +172,17 @@ public interface Traversal<S, E> extends Iterator<E>, Serializable, Cloneable {
     }
 
     /**
+     * Return a {@link TraversalExplanation} that shows how this traversal will mutate with each applied {@link TraversalStrategy}.
+     *
+     * @return a traversal explanation
+     */
+    public default TraversalExplanation explain() {
+        if (this.asAdmin().isLocked())
+            throw new IllegalStateException("The traversal is locked and can not be explained on a strategy-by-strategy basis");
+        return new TraversalExplanation(this.asAdmin());
+    }
+
+    /**
      * A traversal can be rewritten such that its defined end type E may yield objects of a different type.
      * This helper method allows for the casting of the output to the known the type.
      *

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/87069b28/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 19757d3..aace11a 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
@@ -35,7 +35,8 @@ import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper;
 import org.apache.tinkerpop.gremlin.structure.Edge;
 import org.apache.tinkerpop.gremlin.structure.PropertyType;
 
-import java.util.Collections;
+import java.util.Arrays;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
 
@@ -60,7 +61,7 @@ public final class AdjacentToIncidentStrategy extends AbstractTraversalStrategy<
         implements TraversalStrategy.OptimizationStrategy {
 
     private static final AdjacentToIncidentStrategy INSTANCE = new AdjacentToIncidentStrategy();
-    private static final Set<Class<? extends OptimizationStrategy>> PRIORS = Collections.singleton(IncidentToAdjacentStrategy.class);
+    private static final Set<Class<? extends OptimizationStrategy>> PRIORS = new HashSet<>(Arrays.asList(IdentityRemovalStrategy.class, IncidentToAdjacentStrategy.class));
 
     private AdjacentToIncidentStrategy() {
     }

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/87069b28/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 de05aa9..15327d3 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
@@ -34,6 +34,7 @@ import org.javatuples.Pair;
 
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.HashSet;
 import java.util.Set;
 
@@ -128,4 +129,9 @@ public final class IncidentToAdjacentStrategy extends AbstractTraversalStrategy<
     public static IncidentToAdjacentStrategy instance() {
         return INSTANCE;
     }
+
+    @Override
+    public Set<Class<? extends OptimizationStrategy>> applyPrior() {
+        return Collections.singleton(IdentityRemovalStrategy.class);
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/87069b28/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalExplanation.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalExplanation.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalExplanation.java
new file mode 100644
index 0000000..d7cdf58
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalExplanation.java
@@ -0,0 +1,118 @@
+/*
+ * 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.util;
+
+import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
+import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategy;
+import org.javatuples.Pair;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+import java.util.stream.Stream;
+
+/**
+ * A TraversalExplanation takes a {@link Traversal} and, for each registered {@link TraversalStrategy}, it creates a mapping reflecting how each strategy alters the traversal.
+ * This is useful for understanding how each traversal strategy mutates the traversal.
+ * This is useful in debugging and analysis of traversal compilation.
+ * The {@link TraversalExplanation#toString()} has a pretty-print representation that is useful in the Gremlin Console.
+ *
+ * @author Marko A. Rodriguez (http://markorodriguez.com)
+ */
+public class TraversalExplanation {
+
+    private final Traversal.Admin<?, ?> traversal;
+    private final List<Pair<TraversalStrategy, Traversal.Admin<?, ?>>> strategyTraversals = new ArrayList<>();
+
+    public TraversalExplanation(final Traversal.Admin<?, ?> traversal) {
+        this.traversal = traversal.clone();
+        Traversal.Admin<?, ?> mutatingTraversal = this.traversal.clone();
+        for (final TraversalStrategy strategy : this.traversal.getStrategies().toList()) {
+            strategy.apply(mutatingTraversal);
+            this.strategyTraversals.add(Pair.with(strategy, mutatingTraversal));
+            mutatingTraversal = mutatingTraversal.clone();
+        }
+    }
+
+    /**
+     * Get the list of {@link TraversalStrategy} applications. For strategy, the resultant mutated {@link Traversal} is provided.
+     *
+     * @return the list of strategy/traversal pairs
+     */
+    public List<Pair<TraversalStrategy, Traversal.Admin<?, ?>>> getStrategyTraversals() {
+        return Collections.unmodifiableList(this.strategyTraversals);
+    }
+
+    /**
+     * Get the original {@link Traversal} used to create this explanation.
+     *
+     * @return the original traversal
+     */
+    public Traversal.Admin<?, ?> getOriginalTraversal() {
+        return this.traversal;
+    }
+
+    /**
+     * A pretty-print representation of the traversal explanation.
+     *
+     * @return a {@link String} representation of the traversal explanation
+     */
+    @Override
+    public String toString() {
+        final String originalTraversal = "Original Traversal";
+        final String finalTraversal = "Final Traversal";
+        final int maxStrategyColumnLength = this.strategyTraversals.stream().map(Pair::getValue0).map(Object::toString).map(String::length).max(Comparator.<Integer>naturalOrder()).get();
+        final int maxTraversalColumnLength = Stream.concat(Stream.of(Pair.with(null, this.traversal)), this.strategyTraversals.stream()).map(Pair::getValue1).map(Object::toString).map(String::length).max(Comparator.<Integer>naturalOrder()).get();
+
+        final StringBuilder builder = new StringBuilder("Traversal Explanation\n");
+        for (int i = 0; i < (maxStrategyColumnLength + 7 + maxTraversalColumnLength); i++) {
+            builder.append("=");
+        }
+        builder.append("\n");
+        builder.append(originalTraversal);
+        for (int i = 0; i < maxStrategyColumnLength - originalTraversal.length() + 7; i++) {
+            builder.append(" ");
+        }
+        builder.append(this.traversal.toString());
+        builder.append("\n\n");
+        for (final Pair<TraversalStrategy, Traversal.Admin<?, ?>> pairs : this.strategyTraversals) {
+            builder.append(pairs.getValue0());
+            int spacesToAdd = maxStrategyColumnLength - pairs.getValue0().toString().length() + 1;
+            for (int i = 0; i < spacesToAdd; i++) {
+                builder.append(" ");
+            }
+            builder.append("[").append(pairs.getValue0().getTraversalCategory().getSimpleName().substring(0, 1)).append("]");
+            for (int i = 0; i < 3; i++) {
+                builder.append(" ");
+            }
+            builder.append(pairs.getValue1().toString()).append("\n");
+        }
+        builder.append("\n");
+        builder.append(finalTraversal);
+        for (int i = 0; i < maxStrategyColumnLength - finalTraversal.length() + 7; i++) {
+            builder.append(" ");
+        }
+        builder.append(this.strategyTraversals.get(this.strategyTraversals.size() - 1).getValue1());
+        builder.append("\n");
+        return builder.toString();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/87069b28/gremlin-groovy-test/src/main/groovy/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroovyExplainTest.groovy
----------------------------------------------------------------------
diff --git a/gremlin-groovy-test/src/main/groovy/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroovyExplainTest.groovy b/gremlin-groovy-test/src/main/groovy/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroovyExplainTest.groovy
new file mode 100644
index 0000000..1c76546
--- /dev/null
+++ b/gremlin-groovy-test/src/main/groovy/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroovyExplainTest.groovy
@@ -0,0 +1,35 @@
+/*
+ * 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.step.sideEffect
+
+import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalExplanation
+
+/**
+ * @author Marko A. Rodriguez (http://markorodriguez.com)
+ */
+public abstract class GroovyExplainTest {
+
+    public static class Traversals extends ExplainTest {
+
+        public TraversalExplanation get_g_V_outE_identity_inV_explain() {
+            g.V().outE().inV().explain();
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/87069b28/gremlin-groovy-test/src/main/java/org/apache/tinkerpop/gremlin/process/GroovyProcessComputerSuite.java
----------------------------------------------------------------------
diff --git a/gremlin-groovy-test/src/main/java/org/apache/tinkerpop/gremlin/process/GroovyProcessComputerSuite.java b/gremlin-groovy-test/src/main/java/org/apache/tinkerpop/gremlin/process/GroovyProcessComputerSuite.java
index 2c1381c..9df7902 100644
--- a/gremlin-groovy-test/src/main/java/org/apache/tinkerpop/gremlin/process/GroovyProcessComputerSuite.java
+++ b/gremlin-groovy-test/src/main/java/org/apache/tinkerpop/gremlin/process/GroovyProcessComputerSuite.java
@@ -66,6 +66,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.step.map.GroovyUnfoldTest;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.GroovyValueMapTest;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.GroovyVertexTest;
 import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.GroovyAggregateTest;
+import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.GroovyExplainTest;
 import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.GroovyGroupCountTest;
 import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.GroovyGroupTest;
 import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.GroovyGroupTestV3d0;
@@ -150,6 +151,7 @@ public class GroovyProcessComputerSuite extends ProcessComputerSuite {
             // sideEffect
             GroovyAddEdgeTest.Traversals.class,
             GroovyAggregateTest.Traversals.class,
+            GroovyExplainTest.Traversals.class,
             GroovyGroupTest.Traversals.class,
             GroovyGroupTestV3d0.Traversals.class,
             GroovyGroupCountTest.Traversals.class,

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/87069b28/gremlin-groovy-test/src/main/java/org/apache/tinkerpop/gremlin/process/GroovyProcessStandardSuite.java
----------------------------------------------------------------------
diff --git a/gremlin-groovy-test/src/main/java/org/apache/tinkerpop/gremlin/process/GroovyProcessStandardSuite.java b/gremlin-groovy-test/src/main/java/org/apache/tinkerpop/gremlin/process/GroovyProcessStandardSuite.java
index 1698eed..ae91b5f 100644
--- a/gremlin-groovy-test/src/main/java/org/apache/tinkerpop/gremlin/process/GroovyProcessStandardSuite.java
+++ b/gremlin-groovy-test/src/main/java/org/apache/tinkerpop/gremlin/process/GroovyProcessStandardSuite.java
@@ -67,6 +67,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.step.map.GroovyUnfoldTest;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.GroovyValueMapTest;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.GroovyVertexTest;
 import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.GroovyAggregateTest;
+import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.GroovyExplainTest;
 import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.GroovyGroupCountTest;
 import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.GroovyGroupTest;
 import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.GroovyGroupTestV3d0;
@@ -147,6 +148,7 @@ public class GroovyProcessStandardSuite extends ProcessStandardSuite {
             GroovyVertexTest.Traversals.class,
             // sideEffect
             GroovyAggregateTest.Traversals.class,
+            GroovyExplainTest.Traversals.class,
             GroovyGroupTest.Traversals.class,
             GroovyGroupTestV3d0.Traversals.class,
             GroovyGroupCountTest.Traversals.class,

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/87069b28/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/ProcessComputerSuite.java
----------------------------------------------------------------------
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/ProcessComputerSuite.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/ProcessComputerSuite.java
index 3943b92..45ec0ef 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/ProcessComputerSuite.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/ProcessComputerSuite.java
@@ -66,6 +66,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.step.map.UnfoldTest;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.ValueMapTest;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.VertexTest;
 import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.AggregateTest;
+import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.ExplainTest;
 import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.GroupCountTest;
 import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.GroupTest;
 import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.GroupTestV3d0;
@@ -156,6 +157,7 @@ public class ProcessComputerSuite extends AbstractGremlinSuite {
             // sideEffect
             AddEdgeTest.Traversals.class,
             AggregateTest.Traversals.class,
+            ExplainTest.Traversals.class,
             GroupTest.Traversals.class,
             GroupTestV3d0.Traversals.class,
             GroupCountTest.Traversals.class,

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/87069b28/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/ProcessStandardSuite.java
----------------------------------------------------------------------
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/ProcessStandardSuite.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/ProcessStandardSuite.java
index 1091812..3b7e634 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/ProcessStandardSuite.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/ProcessStandardSuite.java
@@ -66,6 +66,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.step.map.UnfoldTest;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.ValueMapTest;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.VertexTest;
 import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.AggregateTest;
+import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.ExplainTest;
 import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.GroupCountTest;
 import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.GroupTest;
 import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.GroupTestV3d0;
@@ -155,6 +156,7 @@ public class ProcessStandardSuite extends AbstractGremlinSuite {
 
             // sideEffect
             AggregateTest.Traversals.class,
+            ExplainTest.Traversals.class,
             GroupTest.Traversals.class,
             GroupTestV3d0.Traversals.class,
             GroupCountTest.Traversals.class,

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/87069b28/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/ExplainTest.java
----------------------------------------------------------------------
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/ExplainTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/ExplainTest.java
new file mode 100644
index 0000000..97a9a23
--- /dev/null
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/ExplainTest.java
@@ -0,0 +1,83 @@
+/*
+ * 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.step.sideEffect;
+
+import org.apache.tinkerpop.gremlin.LoadGraphWith;
+import org.apache.tinkerpop.gremlin.process.AbstractGremlinProcessTest;
+import org.apache.tinkerpop.gremlin.process.GremlinProcessRunner;
+import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
+import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.EdgeVertexStep;
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.IdentityRemovalStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.IncidentToAdjacentStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalExplanation;
+import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper;
+import org.javatuples.Pair;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.apache.tinkerpop.gremlin.LoadGraphWith.GraphData.MODERN;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+
+/**
+ * @author Marko A. Rodriguez (http://markorodriguez.com)
+ */
+@RunWith(GremlinProcessRunner.class)
+public abstract class ExplainTest extends AbstractGremlinProcessTest {
+
+    public abstract TraversalExplanation get_g_V_outE_identity_inV_explain();
+
+    @Test
+    @LoadGraphWith(MODERN)
+    public void g_V_outE_identity_inV_explain() {
+        final TraversalExplanation explanation = get_g_V_outE_identity_inV_explain();
+        printTraversalForm(explanation.getOriginalTraversal());
+        boolean beforeIncident = true;
+        boolean beforeIdentity = true;
+        for (final Pair<TraversalStrategy, Traversal.Admin<?, ?>> pair : explanation.getStrategyTraversals()) {
+            if (pair.getValue0().getClass().equals(IncidentToAdjacentStrategy.class))
+                beforeIncident = false;
+            if (pair.getValue0().getClass().equals(IdentityRemovalStrategy.class))
+                beforeIdentity = false;
+
+            if (beforeIdentity)
+                assertEquals(1, TraversalHelper.getStepsOfClass(IdentityStep.class, pair.getValue1()).size());
+
+            if (beforeIncident)
+                assertEquals(1, TraversalHelper.getStepsOfClass(EdgeVertexStep.class, pair.getValue1()).size());
+
+            if (!beforeIdentity)
+                assertEquals(0, TraversalHelper.getStepsOfClass(IdentityStep.class, pair.getValue1()).size());
+
+            if (!beforeIncident)
+                assertEquals(0, TraversalHelper.getStepsOfClass(EdgeVertexStep.class, pair.getValue1()).size());
+        }
+        assertFalse(beforeIncident);
+    }
+
+    public static class Traversals extends ExplainTest {
+
+        public TraversalExplanation get_g_V_outE_identity_inV_explain() {
+            return g.V().outE().identity().inV().explain();
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/87069b28/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 e7c54ce..fdb44ad 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
@@ -53,9 +53,7 @@ public class TinkerGraphPlayTest {
     public void testPlay8() throws Exception {
         Graph graph = TinkerFactory.createModern();
         GraphTraversalSource g = graph.traversal(); //GraphTraversalSource.computer());
-        Traversal traversal = g.V(1).V().values("name");
-        traversal.forEachRemaining(System.out::println);
-        System.out.println(traversal);
+        System.out.println(g.V().outE("knows").identity().inV().count().is(P.eq(5)).explain());
 
     }
 


[5/5] incubator-tinkerpop git commit: Merge branch 'TINKERPOP3-679'

Posted by ok...@apache.org.
Merge branch 'TINKERPOP3-679'


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

Branch: refs/heads/master
Commit: 0feaa8b47de2797e177310cd1ea3bf38d7230420
Parents: c42613c fe8cfa2
Author: Marko A. Rodriguez <ok...@gmail.com>
Authored: Wed Nov 18 07:19:27 2015 -0700
Committer: Marko A. Rodriguez <ok...@gmail.com>
Committed: Wed Nov 18 07:19:27 2015 -0700

----------------------------------------------------------------------
 docs/src/the-traversal.asciidoc                 |  22 ++++
 .../gremlin/process/traversal/Traversal.java    |  12 ++
 .../AdjacentToIncidentStrategy.java             |   5 +-
 .../IncidentToAdjacentStrategy.java             |   6 +
 .../traversal/util/TraversalExplanation.java    | 117 +++++++++++++++++++
 .../step/sideEffect/GroovyExplainTest.groovy    |  35 ++++++
 .../process/GroovyProcessComputerSuite.java     |   2 +
 .../process/GroovyProcessStandardSuite.java     |   2 +
 .../gremlin/process/ProcessComputerSuite.java   |   2 +
 .../gremlin/process/ProcessStandardSuite.java   |   2 +
 .../traversal/step/sideEffect/ExplainTest.java  |  83 +++++++++++++
 .../structure/TinkerGraphPlayTest.java          |   4 +-
 12 files changed, 287 insertions(+), 5 deletions(-)
----------------------------------------------------------------------



[2/5] incubator-tinkerpop git commit: removed a final new-line character so TraversalExplanation.toString() has the same look and feel as ProfileSteps StandardMetrics.

Posted by ok...@apache.org.
removed a final new-line character so TraversalExplanation.toString() has the same look and feel as ProfileSteps StandardMetrics.


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

Branch: refs/heads/master
Commit: 53dcf7988c88cb77f045fb3fca2f40a12a0c655c
Parents: 87069b2
Author: Marko A. Rodriguez <ok...@gmail.com>
Authored: Tue Nov 17 11:43:17 2015 -0700
Committer: Marko A. Rodriguez <ok...@gmail.com>
Committed: Tue Nov 17 11:43:17 2015 -0700

----------------------------------------------------------------------
 .../gremlin/process/traversal/util/TraversalExplanation.java        | 1 -
 1 file changed, 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/53dcf798/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalExplanation.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalExplanation.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalExplanation.java
index d7cdf58..e80e723 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalExplanation.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalExplanation.java
@@ -111,7 +111,6 @@ public class TraversalExplanation {
             builder.append(" ");
         }
         builder.append(this.strategyTraversals.get(this.strategyTraversals.size() - 1).getValue1());
-        builder.append("\n");
         return builder.toString();
     }
 


[4/5] incubator-tinkerpop git commit: doc fix and added a reference to explain() in TraversalStrategy section. --dryRun showed it was good.

Posted by ok...@apache.org.
doc fix and added a reference to explain() in TraversalStrategy section. --dryRun showed it was good.


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

Branch: refs/heads/master
Commit: fe8cfa26b9137a7b3814f0f885ac6958feb0012f
Parents: 517f696
Author: Marko A. Rodriguez <ok...@gmail.com>
Authored: Tue Nov 17 14:31:16 2015 -0700
Committer: Marko A. Rodriguez <ok...@gmail.com>
Committed: Tue Nov 17 14:31:16 2015 -0700

----------------------------------------------------------------------
 docs/src/the-traversal.asciidoc | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/fe8cfa26/docs/src/the-traversal.asciidoc
----------------------------------------------------------------------
diff --git a/docs/src/the-traversal.asciidoc b/docs/src/the-traversal.asciidoc
index d7134be..78619bb 100644
--- a/docs/src/the-traversal.asciidoc
+++ b/docs/src/the-traversal.asciidoc
@@ -592,7 +592,7 @@ post strategy application. The final traversal is the resultant execution plan.
 
 [gremlin-groovy,modern]
 ----
-g.V().outE().identity().inV().count().is(gt(5))
+g.V().outE().identity().inV().count().is(gt(5)).explain()
 ----
 
 For traversal profiling information, please see <<profile-step,`profile()`>>-step.
@@ -2124,6 +2124,8 @@ traversal as it deems fit. This is useful in multiple situations:
  * There are are some final adjustments required before executing the traversal (*finalization*).
  * There are certain traversals that are not legal for the application or traversal engine (*verification*).
 
+NOTE: The <<explain-step,`explain()`>>-step shows the user how each registered strategy mutates the traversal.
+
 A simple `OptimizationStrategy` is the `IdentityRemovalStrategy`.
 
 [source,java]


[3/5] incubator-tinkerpop git commit: updated a test last minute and forgot to update Groovy's version of that test. Sorry to waste your time @twilmes.

Posted by ok...@apache.org.
updated a test last minute and forgot to update Groovy's version of that test. Sorry to waste your time @twilmes.


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

Branch: refs/heads/master
Commit: 517f696b145ca4b3e448f41c3661fa7f87b8ff87
Parents: 53dcf79
Author: Marko A. Rodriguez <ok...@gmail.com>
Authored: Tue Nov 17 13:04:43 2015 -0700
Committer: Marko A. Rodriguez <ok...@gmail.com>
Committed: Tue Nov 17 13:04:43 2015 -0700

----------------------------------------------------------------------
 .../process/traversal/step/sideEffect/GroovyExplainTest.groovy     | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/517f696b/gremlin-groovy-test/src/main/groovy/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroovyExplainTest.groovy
----------------------------------------------------------------------
diff --git a/gremlin-groovy-test/src/main/groovy/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroovyExplainTest.groovy b/gremlin-groovy-test/src/main/groovy/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroovyExplainTest.groovy
index 1c76546..2f60161 100644
--- a/gremlin-groovy-test/src/main/groovy/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroovyExplainTest.groovy
+++ b/gremlin-groovy-test/src/main/groovy/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroovyExplainTest.groovy
@@ -29,7 +29,7 @@ public abstract class GroovyExplainTest {
     public static class Traversals extends ExplainTest {
 
         public TraversalExplanation get_g_V_outE_identity_inV_explain() {
-            g.V().outE().inV().explain();
+            g.V().outE().identity().inV().explain();
         }
     }
 }
\ No newline at end of file