TraversalExplanation now supports word wrapping and VertexProgamStep.toStrings() have GraphFilter information attached.
Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/fc62efec Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/fc62efec Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/fc62efec Branch: refs/heads/TINKERPOP-1274 Commit: fc62efec4d578b5e767676b04789cf35535f53f0 Parents: 1a526eb Author: Marko A. Rodriguez <okramma...@gmail.com> Authored: Wed Jun 15 07:00:44 2016 -0600 Committer: Marko A. Rodriguez <okramma...@gmail.com> Committed: Wed Jun 15 07:00:44 2016 -0600 ---------------------------------------------------------------------- .../gremlin/process/computer/GraphFilter.java | 11 ++++ .../step/map/PageRankVertexProgramStep.java | 3 +- .../step/map/PeerPressureVertexProgramStep.java | 3 +- .../step/map/ProgramVertexProgramStep.java | 3 +- .../step/map/TraversalVertexProgramStep.java | 3 +- .../traversal/util/TraversalExplanation.java | 56 ++++++++++++++++++-- .../util/TraversalExplanationTest.java | 42 ++++++++++++++- 7 files changed, 111 insertions(+), 10 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/fc62efec/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/GraphFilter.java ---------------------------------------------------------------------- diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/GraphFilter.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/GraphFilter.java index 59c654d..3718d16 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/GraphFilter.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/GraphFilter.java @@ -83,6 +83,17 @@ public final class GraphFilter implements Cloneable, Serializable { private Map<Direction, Map<String, Legal>> edgeLegality = new HashMap<>(); private boolean allowNoEdges = false; + public GraphFilter() { + // no args constructor + } + + public GraphFilter(final Computer computer) { + if (null != computer.getVertices()) + this.setVertexFilter(computer.getVertices()); + if (null != computer.getEdges()) + this.setEdgeFilter(computer.getEdges()); + } + /** * Set the filter for selecting vertices from the source graph. * The vertex filter can only access the vertex, its properties, and its properties properties. http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/fc62efec/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/step/map/PageRankVertexProgramStep.java ---------------------------------------------------------------------- diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/step/map/PageRankVertexProgramStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/step/map/PageRankVertexProgramStep.java index fcb2eec..364d092 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/step/map/PageRankVertexProgramStep.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/step/map/PageRankVertexProgramStep.java @@ -19,6 +19,7 @@ package org.apache.tinkerpop.gremlin.process.computer.traversal.step.map; +import org.apache.tinkerpop.gremlin.process.computer.GraphFilter; import org.apache.tinkerpop.gremlin.process.computer.Memory; import org.apache.tinkerpop.gremlin.process.computer.ranking.pagerank.PageRankVertexProgram; import org.apache.tinkerpop.gremlin.process.computer.traversal.lambda.HaltedTraversersCountTraversal; @@ -78,7 +79,7 @@ public final class PageRankVertexProgramStep extends VertexProgramStep implement @Override public String toString() { - return StringFactory.stepString(this, this.edgeTraversal.get(), this.pageRankProperty, this.times); + return StringFactory.stepString(this, this.edgeTraversal.get(), this.pageRankProperty, this.times, new GraphFilter(this.computer)); } @Override http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/fc62efec/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/step/map/PeerPressureVertexProgramStep.java ---------------------------------------------------------------------- diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/step/map/PeerPressureVertexProgramStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/step/map/PeerPressureVertexProgramStep.java index 0ea5112..47d4160 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/step/map/PeerPressureVertexProgramStep.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/step/map/PeerPressureVertexProgramStep.java @@ -19,6 +19,7 @@ package org.apache.tinkerpop.gremlin.process.computer.traversal.step.map; +import org.apache.tinkerpop.gremlin.process.computer.GraphFilter; import org.apache.tinkerpop.gremlin.process.computer.Memory; import org.apache.tinkerpop.gremlin.process.computer.clustering.peerpressure.PeerPressureVertexProgram; import org.apache.tinkerpop.gremlin.process.computer.traversal.lambda.HaltedTraversersCountTraversal; @@ -81,7 +82,7 @@ public final class PeerPressureVertexProgramStep extends VertexProgramStep imple @Override public String toString() { - return StringFactory.stepString(this, this.edgeTraversal.get(), this.clusterProperty, this.times); + return StringFactory.stepString(this, this.edgeTraversal.get(), this.clusterProperty, this.times, new GraphFilter(this.computer)); } @Override http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/fc62efec/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/step/map/ProgramVertexProgramStep.java ---------------------------------------------------------------------- diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/step/map/ProgramVertexProgramStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/step/map/ProgramVertexProgramStep.java index 82e70dd..31eb04b 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/step/map/ProgramVertexProgramStep.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/step/map/ProgramVertexProgramStep.java @@ -20,6 +20,7 @@ package org.apache.tinkerpop.gremlin.process.computer.traversal.step.map; import org.apache.commons.configuration.MapConfiguration; +import org.apache.tinkerpop.gremlin.process.computer.GraphFilter; import org.apache.tinkerpop.gremlin.process.computer.Memory; import org.apache.tinkerpop.gremlin.process.computer.VertexProgram; import org.apache.tinkerpop.gremlin.process.computer.traversal.TraversalVertexProgram; @@ -67,6 +68,6 @@ public final class ProgramVertexProgramStep extends VertexProgramStep { @Override public String toString() { - return StringFactory.stepString(this, this.toStringOfVertexProgram); + return StringFactory.stepString(this, this.toStringOfVertexProgram, new GraphFilter(this.computer)); } } http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/fc62efec/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/step/map/TraversalVertexProgramStep.java ---------------------------------------------------------------------- diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/step/map/TraversalVertexProgramStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/step/map/TraversalVertexProgramStep.java index 58e44a2..0eee43a 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/step/map/TraversalVertexProgramStep.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/step/map/TraversalVertexProgramStep.java @@ -20,6 +20,7 @@ package org.apache.tinkerpop.gremlin.process.computer.traversal.step.map; import org.apache.tinkerpop.gremlin.process.computer.GraphComputer; +import org.apache.tinkerpop.gremlin.process.computer.GraphFilter; import org.apache.tinkerpop.gremlin.process.computer.Memory; import org.apache.tinkerpop.gremlin.process.computer.traversal.MemoryTraversalSideEffects; import org.apache.tinkerpop.gremlin.process.computer.traversal.TraversalVertexProgram; @@ -54,7 +55,7 @@ public final class TraversalVertexProgramStep extends VertexProgramStep implemen @Override public String toString() { - return StringFactory.stepString(this, this.computerTraversal.get()); + return StringFactory.stepString(this, this.computerTraversal.get(), new GraphFilter(this.computer)); } @Override http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/fc62efec/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 98cef69..675291d 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 @@ -85,10 +85,26 @@ public class TraversalExplanation implements Serializable { */ @Override public String toString() { + final int maxLineLength = 75; 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()).orElse(15); - 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 int maxStrategyColumnLength = this.strategyTraversals.stream() + .map(Pair::getValue0) + .map(Object::toString) + .map(String::length) + .max(Comparator.naturalOrder()) + .orElse(15); + final int newLineIndent = maxStrategyColumnLength + 10; + int maxTraversalColumnLength = Stream.concat(Stream.of(Pair.with(null, this.traversal)), this.strategyTraversals.stream()) + .map(Pair::getValue1) + .map(Object::toString) + .map(s -> wordWrap(s, maxLineLength, newLineIndent)) + .flatMap(s -> Stream.of(s.split("\n"))) + .map(String::trim) + .map(s -> s.trim().startsWith("[") ? s : " " + s) // 3 indent on new lines + .map(String::length) + .max(Comparator.naturalOrder()) + .get(); final StringBuilder builder = new StringBuilder("Traversal Explanation\n"); for (int i = 0; i < (maxStrategyColumnLength + 7 + maxTraversalColumnLength); i++) { @@ -99,7 +115,7 @@ public class TraversalExplanation implements Serializable { for (int i = 0; i < maxStrategyColumnLength - originalTraversal.length() + 7; i++) { builder.append(" "); } - builder.append(this.traversal.toString()); + builder.append(wordWrap(this.traversal.toString(), maxLineLength, newLineIndent)); builder.append("\n\n"); for (final Pair<TraversalStrategy, Traversal.Admin<?, ?>> pairs : this.strategyTraversals) { builder.append(pairs.getValue0()); @@ -111,15 +127,45 @@ public class TraversalExplanation implements Serializable { for (int i = 0; i < 3; i++) { builder.append(" "); } - builder.append(pairs.getValue1().toString()).append("\n"); + builder.append(wordWrap(pairs.getValue1().toString(), maxLineLength, newLineIndent)).append("\n"); } builder.append("\n"); builder.append(finalTraversal); for (int i = 0; i < maxStrategyColumnLength - finalTraversal.length() + 7; i++) { builder.append(" "); } - builder.append(this.strategyTraversals.size() > 0 ? this.strategyTraversals.get(this.strategyTraversals.size() - 1).getValue1() : this.traversal); + builder.append(wordWrap((this.strategyTraversals.size() > 0 ? + this.strategyTraversals.get(this.strategyTraversals.size() - 1).getValue1().toString() : + this.traversal.toString()), maxLineLength, newLineIndent)); return builder.toString(); } + private String wordWrap(final String longString, final int maxLengthPerLine, final int newLineIndent) { + if (longString.length() <= maxLengthPerLine) + return longString; + + StringBuilder builder = new StringBuilder(); + int counter = 0; + for (final String shortString : longString.split(", ")) { + if (0 == counter) + builder.append(shortString).append(", "); + else if (counter < maxLengthPerLine) + builder.append(shortString).append(", "); + else { + builder.deleteCharAt(builder.length() - 1); // remove the " " + builder.append("\n"); + for (int i = 0; i < newLineIndent; i++) { + builder.append(" "); + } + builder.append(shortString).append(", "); + counter = 0; + } + counter = counter + shortString.length(); + } + + return builder + .delete(builder.length() - 2, builder.length()) // remove the final ", " + .toString(); + } + } http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/fc62efec/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalExplanationTest.java ---------------------------------------------------------------------- diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalExplanationTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalExplanationTest.java index 3059879..57841e4 100644 --- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalExplanationTest.java +++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalExplanationTest.java @@ -22,11 +22,15 @@ package org.apache.tinkerpop.gremlin.process.traversal.util; import org.apache.tinkerpop.gremlin.process.traversal.P; 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.GraphTraversal; import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__; import org.apache.tinkerpop.gremlin.structure.Graph; import org.junit.Test; +import java.util.stream.Stream; + import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; /** @@ -43,6 +47,40 @@ public class TraversalExplanationTest { } @Test + public void shouldWordWrapCorrectly() { + GraphTraversal<?, ?> traversal = __.V().out().out(); + String toString = traversal.explain().toString(); + assertFalse(toString.contains("VertexStep(OUT,vertex),\n")); + //System.out.println(toString); + /// + traversal = __.V().out().out().out().out(); + toString = traversal.explain().toString(); + assertTrue(toString.contains("VertexStep(OUT,vertex),\n")); + //System.out.println(toString); + /// + for (int i = 0; i < 30; i++) { + traversal = __.V(); + for (int j = 0; j < i; j++) { + traversal.out(); + } + traversal.asAdmin().setStrategies(TraversalStrategies.GlobalCache.getStrategies(Graph.class)); + toString = traversal.explain().toString(); + if (i < 4) + assertFalse(toString.contains("VertexStep(OUT,vertex),\n")); + else { + assertFalse(Stream.of(toString.split("\n")) + .filter(s -> s.startsWith(" ")) + .map(String::trim) + .filter(s -> Character.isLowerCase(s.charAt(0))) + .findAny() + .isPresent()); // all indented word wraps should start with steps + assertTrue(toString.contains("VertexStep(OUT,vertex),\n")); + } + //System.out.println(toString); + } + } + + @Test public void shouldApplyStrategiesCorrectly() { Traversal.Admin<?, ?> traversal = __.out().count().asAdmin(); traversal.setStrategies(TraversalStrategies.GlobalCache.getStrategies(Graph.class)); @@ -64,8 +102,10 @@ public class TraversalExplanationTest { /// traversal = __.outE().inV().group().by(__.inE().outV().groupCount().by(__.both().count().is(P.gt(2)))).asAdmin(); traversal.setStrategies(TraversalStrategies.GlobalCache.getStrategies(Graph.class).clone()); + // System.out.println(traversal.explain()); found = 0; - for (final String line : traversal.explain().toString().split("\n")) { + for (final String line : traversal.explain().toString().split("]\n")) { // need to split cause of word wrap + //System.out.println(line + "\n\n"); if (line.contains("IncidentToAdjacentStrategy") && line.contains("[VertexStep(IN,vertex)")) found++; if (line.contains("IncidentToAdjacentStrategy") && line.contains("[VertexStep(OUT,vertex)"))