You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tinkerpop.apache.org by sp...@apache.org on 2015/08/25 15:06:12 UTC
[15/17] incubator-tinkerpop git commit: Revert "Revert "Merge
remote-tracking branch 'origin' into tp30""
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/ae644951/gremlin-console/conf/remote-objects.yaml
----------------------------------------------------------------------
diff --git a/gremlin-console/conf/remote-objects.yaml b/gremlin-console/conf/remote-objects.yaml
index 78424fd..f507f4e 100644
--- a/gremlin-console/conf/remote-objects.yaml
+++ b/gremlin-console/conf/remote-objects.yaml
@@ -15,6 +15,27 @@
# specific language governing permissions and limitations
# under the License.
+##############################################################
+# This configuration is meant to have Gremlin Server return
+# Gryo serialized objects. The TinkerGraph IoRegistry is
+# assigned as this is the configuration defined in the
+# pre-packaged Gremlin Server configuration files. The
+# client configuration for serializers should match server.
+# Note that the server configures this via the
+# useMapperFromGraph setting - that simply means to use
+# the registry of the current configured Graph when
+# serializing and for these the pre-packaged purpose,
+# that's TinkerGraph.
+#
+# This file will work with:
+# - gremlin-server.yaml
+# - gremlin-server-classic.yaml
+# - gremlin-server-modern.yaml
+# - gremlin-server-modern-readonly.yaml
+# - gremlin-server-secure.yaml
+##############################################################
+
hosts: [localhost]
port: 8182
-serializer: { className: org.apache.tinkerpop.gremlin.driver.ser.GryoMessageSerializerV1d0}
\ No newline at end of file
+serializer: { className: org.apache.tinkerpop.gremlin.driver.ser.GryoMessageSerializerV1d0,
+ config: { ioRegistries: [org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerIoRegistry] }}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/ae644951/gremlin-console/conf/remote-secure.yaml
----------------------------------------------------------------------
diff --git a/gremlin-console/conf/remote-secure.yaml b/gremlin-console/conf/remote-secure.yaml
index 3e1deae..4f8d22b 100644
--- a/gremlin-console/conf/remote-secure.yaml
+++ b/gremlin-console/conf/remote-secure.yaml
@@ -15,6 +15,15 @@
# specific language governing permissions and limitations
# under the License.
+##############################################################
+# This configuration is meant to have Gremlin Server return
+# text serialized objects. The server will toString()
+# results giving a view into how scripts are executing.
+#
+# This file will work with:
+# - gremlin-server-secure.yaml
+##############################################################
+
hosts: [localhost]
port: 8182
username: stephen
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/ae644951/gremlin-console/conf/remote.yaml
----------------------------------------------------------------------
diff --git a/gremlin-console/conf/remote.yaml b/gremlin-console/conf/remote.yaml
index 7b23779..c181591 100644
--- a/gremlin-console/conf/remote.yaml
+++ b/gremlin-console/conf/remote.yaml
@@ -15,6 +15,18 @@
# specific language governing permissions and limitations
# under the License.
+##############################################################
+# This configuration is meant to have Gremlin Server return
+# text serialized objects. The server will toString()
+# results giving a view into how scripts are executing.
+#
+# This file will work with:
+# - gremlin-server.yaml
+# - gremlin-server-classic.yaml
+# - gremlin-server-modern.yaml
+# - gremlin-server-modern-readonly.yaml
+##############################################################
+
hosts: [localhost]
port: 8182
serializer: { className: org.apache.tinkerpop.gremlin.driver.ser.GryoMessageSerializerV1d0, config: { serializeResultToString: true }}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/ae644951/gremlin-console/pom.xml
----------------------------------------------------------------------
diff --git a/gremlin-console/pom.xml b/gremlin-console/pom.xml
index 5e3210a..f2a2e9d 100644
--- a/gremlin-console/pom.xml
+++ b/gremlin-console/pom.xml
@@ -21,7 +21,7 @@ limitations under the License.
<parent>
<artifactId>tinkerpop</artifactId>
<groupId>org.apache.tinkerpop</groupId>
- <version>3.0.1-SNAPSHOT</version>
+ <version>3.1.0-SNAPSHOT</version>
</parent>
<artifactId>gremlin-console</artifactId>
<name>Apache TinkerPop :: Gremlin Console</name>
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/ae644951/gremlin-console/src/main/groovy/org/apache/tinkerpop/gremlin/console/plugin/GephiRemoteAcceptor.groovy
----------------------------------------------------------------------
diff --git a/gremlin-console/src/main/groovy/org/apache/tinkerpop/gremlin/console/plugin/GephiRemoteAcceptor.groovy b/gremlin-console/src/main/groovy/org/apache/tinkerpop/gremlin/console/plugin/GephiRemoteAcceptor.groovy
index 69dfcda..b8872e9 100644
--- a/gremlin-console/src/main/groovy/org/apache/tinkerpop/gremlin/console/plugin/GephiRemoteAcceptor.groovy
+++ b/gremlin-console/src/main/groovy/org/apache/tinkerpop/gremlin/console/plugin/GephiRemoteAcceptor.groovy
@@ -21,15 +21,20 @@ package org.apache.tinkerpop.gremlin.console.plugin
import groovy.transform.CompileStatic
import org.apache.tinkerpop.gremlin.groovy.plugin.RemoteAcceptor
import org.apache.tinkerpop.gremlin.groovy.plugin.RemoteException
-import org.apache.tinkerpop.gremlin.process.traversal.Traversal
+import org.apache.tinkerpop.gremlin.process.traversal.Path
import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource
+import org.apache.tinkerpop.gremlin.structure.Direction
import org.apache.tinkerpop.gremlin.structure.Edge
import org.apache.tinkerpop.gremlin.structure.Graph
import org.apache.tinkerpop.gremlin.structure.Vertex
import groovy.json.JsonSlurper
import groovyx.net.http.HTTPBuilder
+import org.apache.tinkerpop.gremlin.util.iterator.IteratorUtils
import org.codehaus.groovy.tools.shell.Groovysh
import org.codehaus.groovy.tools.shell.IO
+import org.javatuples.Pair
+
+import java.util.stream.Collectors
import static groovyx.net.http.ContentType.JSON
@@ -46,11 +51,15 @@ class GephiRemoteAcceptor implements RemoteAcceptor {
private final Groovysh shell
private final IO io
- private long vizStepDelay
+ boolean traversalSubmittedForViz = false
+ long vizStepDelay
private float[] vizStartRGBColor
+ private float[] vizDefaultRGBColor
private char vizColorToFade
private float vizColorFadeRate
- private Map<String, Float> fadingVertexColors;
+ private float vizStartSize
+ private float vizSizeDecrementRate
+ private Map vertexAttributes = [:]
public GephiRemoteAcceptor(final Groovysh shell, final IO io) {
this.shell = shell
@@ -59,8 +68,11 @@ class GephiRemoteAcceptor implements RemoteAcceptor {
// traversal visualization defaults
vizStepDelay = 1000; // 1 second pause between viz of steps
vizStartRGBColor = [0.0f, 1.0f, 0.5f] // light aqua green
+ vizDefaultRGBColor = [0.6f, 0.6f, 0.6f] // light grey
vizColorToFade = 'g' // will fade so blue is strongest
vizColorFadeRate = 0.7 // the multiplicative rate to fade visited vertices
+ vizStartSize = 20
+ vizSizeDecrementRate = 0.33f
}
@Override
@@ -79,25 +91,17 @@ class GephiRemoteAcceptor implements RemoteAcceptor {
}
}
- String vizConfig = " with stepDelay:$vizStepDelay, startRGBColor:$vizStartRGBColor, " +
- "colorToFade:$vizColorToFade, colorFadeRate:$vizColorFadeRate"
- if (args.size() >= 4) {
- if (args.size() > 7) {
- vizConfig = configVizOptions(args.subList(3, 6))
- } else {
- vizConfig = configVizOptions(args.subList(3, args.size()))
- }
- }
+ def vizConfig = " with stepDelay:$vizStepDelay, startRGBColor:$vizStartRGBColor, " +
+ "colorToFade:$vizColorToFade, colorFadeRate:$vizColorFadeRate, startSize:$vizStartSize," +
+ "sizeDecrementRate:$vizSizeDecrementRate"
return "Connection to Gephi - http://$host:$port/$workspace" + vizConfig
}
@Override
Object configure(final List<String> args) throws RemoteException {
- if (args.size() != 2)
- throw new RemoteException("Expects [host <hostname>|port <port number>|workspace <name>|" +
- "stepDelay <milliseconds>|startRGBColor <RGB array of floats>|" +
- "colorToFade: <char r|g|b>]|colorFadeRate: <float>")
+ if (args.size() < 2)
+ throw new RemoteException("Invalid config arguments - check syntax")
if (args[0] == "host")
host = args[1]
@@ -117,67 +121,25 @@ class GephiRemoteAcceptor implements RemoteAcceptor {
parseVizColorToFade(args[1])
else if (args[0] == "colorFadeRate")
parseVizColorFadeRate(args[1])
- else
- throw new RemoteException("Expects [host <hostname>|port <port number>|workspace <name>|" +
- "stepDelay <milliseconds>|startRGBColor <RGB array of floats>|" +
- "colorToFade: <char r|g|b>]|colorFadeRate: <float>")
+ else if (args[0] == "sizeDecrementRate")
+ parseVizSizeDecrementRate(args[1])
+ else if (args[0] == "startSize")
+ parseVizStartSize(args[1])
+ else if (args[0] == "visualTraversal") {
+ def graphVar = shell.interp.context.getVariable(args[1])
+ if (!(graphVar instanceof Graph))
+ throw new RemoteException("Invalid argument to 'visualTraversal' - first parameter must be a Graph instance")
+
+ def gVar = args.size() == 3 ? args[2] : "vg"
+ def theG = GraphTraversalSource.build().with(new GephiTraversalVisualizationStrategy(this)).create(graphVar)
+ shell.interp.context.setVariable(gVar, theG)
+ } else
+ throw new RemoteException("Invalid config arguments - check syntax")
return "Connection to Gephi - http://$host:$port/$workspace" +
" with stepDelay:$vizStepDelay, startRGBColor:$vizStartRGBColor, " +
- "colorToFade:$vizColorToFade, colorFadeRate:$vizColorFadeRate"
- }
-
-
- private Object configVizOptions(final List<String> vizConfigArgs) {
- if (vizConfigArgs.size() >= 1)
- parseVizStepDelay(vizConfigArgs[0])
-
- if (vizConfigArgs.size() >= 2)
- parseVizStartRGBColor(vizConfigArgs[1])
-
- if (vizConfigArgs.size() >= 3)
- parseVizColorToFade(vizConfigArgs[2])
-
- if (vizConfigArgs.size() >= 4)
- parseVizColorFadeRate(vizConfigArgs[3])
-
-
- return " with stepDelay:$vizStepDelay, startRGBColor:$vizStartRGBColor, " +
- "colorToFade:$vizColorToFade, colorFadeRate:$vizColorFadeRate"
- }
-
- private void parseVizStepDelay(String arg) {
- try {
- vizStepDelay = Long.parseLong(arg)
- } catch (Exception ignored) {
- throw new RemoteException("The stepDelay must be a long value")
- }
- }
-
- private void parseVizStartRGBColor(String arg) {
- try {
- vizStartRGBColor = arg[1..-2].tokenize(',')*.toFloat()
- assert (vizStartRGBColor.length == 3)
- } catch (Exception ignored) {
- throw new RemoteException("The vizStartRGBColor must be an array of 3 float values, e.g. [0.0,1.0,0.5]")
- }
- }
-
- private void parseVizColorToFade(String arg) {
- try {
- vizColorToFade = arg.charAt(0).toLowerCase();
- assert (vizColorToFade == 'r' || vizColorToFade == 'g' || vizColorToFade == 'b')
- } catch (Exception ignored) {
- throw new RemoteException("The vizColorToFade must be one character value among: r, g, b, R, G, B")
- }
- }
-
- private void parseVizColorFadeRate(String arg) {
- try {
- vizColorFadeRate = Float.parseFloat(arg)
- } catch (Exception ignored) {
- throw new RemoteException("The colorFadeRate must be a float value")
- }
+ "colorToFade:$vizColorToFade, colorFadeRate:$vizColorFadeRate, startSize:$vizStartSize," +
+ "sizeDecrementRate:$vizSizeDecrementRate"
}
@Override
@@ -190,36 +152,70 @@ class GephiRemoteAcceptor implements RemoteAcceptor {
return
}
+ // need to clear the vertex attributes
+ vertexAttributes.clear()
+
+ // this tells the GraphTraversalVisualizationStrategy that if the line eval's to a traversal it should
+ // try to visualize it
+ traversalSubmittedForViz = true
+
+ // get the colors/sizes back to basics before trying visualize
+ resetColorsSizes()
+
final Object o = shell.execute(line)
if (o instanceof Graph) {
clearGraph()
def graph = (Graph) o
def g = graph.traversal()
g.V().sideEffect { addVertexToGephi(g, it.get()) }.iterate()
- } else if (o instanceof Traversal.Admin) {
- fadingVertexColors = [:]
- def traversal = (Traversal.Admin) o
- def memKeys = traversal.getSideEffects().keys()
- def memSize = memKeys.size()
- // assumes user called store("1")...store("n") in ascension
- for (int i = 1; i <= memSize; i++) {
- def stepKey = Integer.toString(i)
- if (memKeys.contains(stepKey)) {
- io.out.print("Visualizing vertices at step: $stepKey... ")
- updateVisitedVertices()
- int visitedCount = 0
-
- if (traversal.getSideEffects().keys().contains(stepKey)) {
- traversal.getSideEffects().get(stepKey).get().each { element ->
- visitVertexToGephi((Vertex) element)
- visitedCount++
+ } else {
+ // an individual Path needs a special case as it is an iterator and gets unrolled by
+ // IteratorUtils.asIterator() if not wrapped in a list prior.
+ final Iterator itty = (o instanceof Path) ? IteratorUtils.asIterator([o]) : IteratorUtils.asIterator(o)
+ def first = true
+ while (itty.hasNext()) {
+ final Object current = itty.next();
+ if (current instanceof Path) {
+ // paths get returned as iterators - so basically any Iterator that has vertices in it will have
+ // their path highlighted
+ final Path path = (Path) current
+ final List<Vertex> verticesInPath = path.stream().map { Pair pair -> pair.getValue0() }
+ .filter { Object e -> e instanceof Vertex }.collect(Collectors.toList())
+
+ for (int ix = 0; ix < verticesInPath.size(); ix++) {
+ final Vertex v = (Vertex) verticesInPath.get(ix)
+
+ // if this vertex has already been highlighted in gephi then no need to do it again,
+ // just update the touch count in memory
+ if (!vertexAttributes.containsKey(v.id().toString())) {
+ // this is a new vertex visited so it needs to get highlighted in gephi
+ visitVertexInGephi(v)
+ if (ix > 0) {
+ final Vertex previous = (Vertex) verticesInPath.get(ix - 1)
+ v.edges(Direction.BOTH).findAll { Edge edge ->
+ edge.bothVertices().any { Vertex vertex -> vertex == previous }
+ }.each { Object edge ->
+ visitEdgeInGephi((Edge) edge)
+ }
+ }
}
+
+ // need to increment the touch even though this may be the first time passed through
+ // because the default for touch=1 when it is added to the graph
+ touch(v)
+ }
+
+ if (itty.hasNext() || !first) {
+ sleep(vizStepDelay)
+ applyRelativeSizingInGephi()
}
- io.out.println("Visited: $visitedCount")
+
+ first = false
}
- sleep(vizStepDelay)
}
}
+
+ traversalSubmittedForViz = false
}
@Override
@@ -227,27 +223,78 @@ class GephiRemoteAcceptor implements RemoteAcceptor {
}
- def updateVisitedVertices() {
- fadingVertexColors.keySet().each { vertex ->
- def currentColor = fadingVertexColors.get(vertex)
+ /**
+ * Visits the last set of vertices traversed and degrades their color and size.
+ */
+ def updateVisitedVertices(def List except = []) {
+ vertexAttributes.keySet().findAll{ vertexId -> !except.contains(vertexId) }.each { String vertexId ->
+ def attrs = vertexAttributes[vertexId]
+ float currentColor = attrs.color
currentColor *= vizColorFadeRate
- fadingVertexColors.put(vertex, currentColor)
- def props = [:]
- props.put(vizColorToFade.toString(), currentColor)
- updateGephiGraph([cn: [(vertex): props]])
+
+ int currentSize = attrs["size"]
+ currentSize = Math.max(1, currentSize - (currentSize * vizSizeDecrementRate))
+
+ vertexAttributes.get(vertexId).color = currentColor
+ vertexAttributes.get(vertexId).size = currentSize
+
+ changeVertexAttributes(vertexId)
+ }
+ }
+
+ def touch(Vertex v) {
+ vertexAttributes.get(v.id().toString()).touch++
+ }
+
+ def applyRelativeSizingInGephi() {
+ def touches = vertexAttributes.values().collect{it["touch"]}
+ def max = touches.max()
+ def min = touches.min()
+
+ vertexAttributes.each { k, v ->
+ double touch = v.touch
+
+ // establishes the relative size of the node with a lower limit of 0.25 of vizStartSize
+ def relative = Math.max((touch - min) / Math.max((max - min).doubleValue(), 0.00001), 0.25)
+ int size = Math.max(1, vizStartSize * relative)
+ v.size = size
+
+ changeVertexAttributes(k)
}
}
- def visitVertexToGephi(def Vertex v) {
+ def changeVertexAttributes(def String vertexId) {
+ def props = [:]
+ props.put(vizColorToFade.toString(), vertexAttributes[vertexId].color)
+ props.put("size", vertexAttributes[vertexId].size)
+ updateGephiGraph([cn: [(vertexId): props]])
+ }
+
+ /**
+ * Visit a vertex traversed and initialize its color and size.
+ */
+ def visitVertexInGephi(def Vertex v, def size = vizStartSize) {
def props = [:]
props.put('r', vizStartRGBColor[0])
props.put('g', vizStartRGBColor[1])
props.put('b', vizStartRGBColor[2])
- props.put('x', 1)
+ props.put('size', size)
+ props.put('visited', 1)
updateGephiGraph([cn: [(v.id().toString()): props]])
- fadingVertexColors.put(v.id().toString(), vizStartRGBColor[fadeColorIndex()])
+ vertexAttributes[v.id().toString()] = [color: vizStartRGBColor[fadeColorIndex()], size: size, touch: 1]
+ }
+
+ def visitEdgeInGephi(def Edge e) {
+ def props = [:]
+ props.put('r', vizStartRGBColor[0])
+ props.put('g', vizStartRGBColor[1])
+ props.put('b', vizStartRGBColor[2])
+ props.put('size', vizStartSize)
+ props.put('visited', 1)
+
+ updateGephiGraph([ce: [(e.id().toString()): props]])
}
def fadeColorIndex() {
@@ -263,6 +310,10 @@ class GephiRemoteAcceptor implements RemoteAcceptor {
// grab the first property value from the strategies of values
def props = g.V(v).valueMap().next().collectEntries { kv -> [(kv.key): kv.value[0]] }
props << [label: v.label()]
+ props.put('r', vizDefaultRGBColor[0])
+ props.put('g', vizDefaultRGBColor[1])
+ props.put('b', vizDefaultRGBColor[2])
+ props.put('visited', 0)
// only add if it does not exist in graph already
if (!getFromGephiGraph([operation: "getNode", id: v.id().toString()]).isPresent())
@@ -282,6 +333,7 @@ class GephiRemoteAcceptor implements RemoteAcceptor {
props.put('source', e.outVertex().id().toString())
props.put('target', e.inVertex().id().toString())
props.put('directed', true)
+ props.put('visited', 0)
// make sure the in vertex is there but don't add its edges - that will happen later as we are looping
// all vertices in the graph
@@ -295,6 +347,13 @@ class GephiRemoteAcceptor implements RemoteAcceptor {
updateGephiGraph([dn: [filter: "ALL"]])
}
+ def resetColorsSizes() {
+ updateGephiGraph([cn: [filter: [nodeAttribute: [attribute: "visited", value: 1]],
+ attributes: [size: 1, r: vizDefaultRGBColor[0], g: vizDefaultRGBColor[1], b: vizDefaultRGBColor[2]]]])
+ updateGephiGraph([ce: [filter: [edgeAttribute: [attribute: "visited", value: 1]],
+ attributes: [size: 1, r: vizDefaultRGBColor[0], g: vizDefaultRGBColor[1], b: vizDefaultRGBColor[2]]]])
+ }
+
def getFromGephiGraph(def Map queryArgs) {
def http = new HTTPBuilder("http://$host:$port/")
def resp = http.get(path: "/$workspace", query: queryArgs).getText()
@@ -310,4 +369,59 @@ class GephiRemoteAcceptor implements RemoteAcceptor {
def http = new HTTPBuilder("http://$host:$port/")
http.post(path: "/$workspace", requestContentType: JSON, body: postBody, query: [format: "JSON", operation: "updateGraph"])
}
+
+ @Override
+ public String toString() {
+ return "Gephi - [$workspace]"
+ }
+
+ private void parseVizStepDelay(String arg) {
+ try {
+ vizStepDelay = Long.parseLong(arg)
+ } catch (Exception ignored) {
+ throw new RemoteException("The stepDelay must be a long value")
+ }
+ }
+
+ private void parseVizStartRGBColor(String arg) {
+ try {
+ vizStartRGBColor = arg[1..-2].tokenize(',')*.toFloat()
+ assert (vizStartRGBColor.length == 3)
+ } catch (Exception ignored) {
+ throw new RemoteException("The vizStartRGBColor must be an array of 3 float values, e.g. [0.0,1.0,0.5]")
+ }
+ }
+
+ private void parseVizColorToFade(String arg) {
+ try {
+ vizColorToFade = arg.charAt(0).toLowerCase();
+ assert (vizColorToFade == 'r' || vizColorToFade == 'g' || vizColorToFade == 'b')
+ } catch (Exception ignored) {
+ throw new RemoteException("The vizColorToFade must be one character value among: r, g, b, R, G, B")
+ }
+ }
+
+ private void parseVizColorFadeRate(String arg) {
+ try {
+ vizColorFadeRate = Float.parseFloat(arg)
+ } catch (Exception ignored) {
+ throw new RemoteException("The colorFadeRate must be a float value")
+ }
+ }
+
+ private void parseVizSizeDecrementRate(String arg) {
+ try {
+ vizSizeDecrementRate = Float.parseFloat(arg)
+ } catch (Exception ignored) {
+ throw new RemoteException("The sizeDecrementRate must be a float value")
+ }
+ }
+
+ private void parseVizStartSize(String arg) {
+ try {
+ vizStartSize = Float.parseFloat(arg)
+ } catch (Exception ignored) {
+ throw new RemoteException("The startSize must be a float value")
+ }
+ }
}
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/ae644951/gremlin-console/src/main/groovy/org/apache/tinkerpop/gremlin/console/plugin/GephiTraversalVisualizationStrategy.groovy
----------------------------------------------------------------------
diff --git a/gremlin-console/src/main/groovy/org/apache/tinkerpop/gremlin/console/plugin/GephiTraversalVisualizationStrategy.groovy b/gremlin-console/src/main/groovy/org/apache/tinkerpop/gremlin/console/plugin/GephiTraversalVisualizationStrategy.groovy
new file mode 100644
index 0000000..661d2ff
--- /dev/null
+++ b/gremlin-console/src/main/groovy/org/apache/tinkerpop/gremlin/console/plugin/GephiTraversalVisualizationStrategy.groovy
@@ -0,0 +1,127 @@
+/*
+ * 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.console.plugin
+
+import groovy.transform.CompileStatic
+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.Traverser
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__
+import org.apache.tinkerpop.gremlin.process.traversal.step.filter.FilterStep
+import org.apache.tinkerpop.gremlin.process.traversal.step.filter.HasStep
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.EdgeOtherVertexStep
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.EdgeVertexStep
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.FoldStep
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.TraversalMapStep
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.UnfoldStep
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.VertexStep
+import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.AggregateStep
+import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.GraphStep
+import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.LambdaSideEffectStep
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.BulkSet
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.NoOpBarrierStep
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.AbstractTraversalStrategy
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.finalization.ProfileStrategy
+import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper
+import org.apache.tinkerpop.gremlin.structure.Vertex
+
+import java.util.stream.Collectors
+
+/**
+ * A strategy that works in conjuction with the {@link GephiRemoteAcceptor} to automatically inject visualization
+ * steps after "vertex" steps to show the vertices traversed for a step. If the traversal was evaluated in the
+ * console normally then the visualization strategy will not be applied. It must be {@code :submit} to the
+ * console for the strategy to be applied.
+ *
+ * @author Stephen Mallette (http://stephen.genoprime.com)
+ */
+@CompileStatic
+class GephiTraversalVisualizationStrategy extends AbstractTraversalStrategy<TraversalStrategy.FinalizationStrategy>
+ implements TraversalStrategy.FinalizationStrategy {
+
+ private static final Set<Class<? extends TraversalStrategy.FinalizationStrategy>> POSTS = new HashSet<>();
+
+ static {
+ POSTS.add(ProfileStrategy.class);
+ }
+
+ private final GephiRemoteAcceptor acceptor
+
+ private final String sideEffectKey = "viz-" + UUID.randomUUID()
+
+ GephiTraversalVisualizationStrategy(final GephiRemoteAcceptor acceptor) {
+ this.acceptor = acceptor
+ }
+
+ @Override
+ void apply(final Traversal.Admin<?, ?> traversal) {
+ if (traversal.getEngine().isComputer())
+ return
+
+ // only apply these strategies if the traversal was :submit to the acceptor - otherwise process as usual
+ if (acceptor.traversalSubmittedForViz) {
+ final List<GraphStep> graphSteps = TraversalHelper.getStepsOfAssignableClass(GraphStep.class, traversal)
+ final List<VertexStep> vertexSteps = TraversalHelper.getStepsOfAssignableClass(VertexStep.class, traversal)
+
+ def List<Step> addAfter = new ArrayList<>()
+ addAfter.addAll(TraversalHelper.getStepsOfAssignableClass(EdgeOtherVertexStep.class, traversal))
+ addAfter.addAll(TraversalHelper.getStepsOfAssignableClass(EdgeVertexStep.class, traversal))
+ addAfter.addAll(vertexSteps.stream().filter { it.returnsVertex() }.collect(Collectors.toList()))
+ addAfter.addAll(graphSteps.stream().filter { it.returnsVertex() }.collect(Collectors.toList()))
+
+ // decay all vertices and visit each one to update their colors to the brightest
+ addAfter.each { Step s ->
+ TraversalHelper.insertAfterStep(new LambdaSideEffectStep(traversal, { Traverser traverser ->
+ final BulkSet<Vertex> vertices = ((BulkSet<Vertex>) traverser.sideEffects(sideEffectKey))
+ if (!vertices.isEmpty()) {
+ acceptor.updateVisitedVertices()
+ vertices.forEach { Vertex v, Long l -> acceptor.visitVertexInGephi(v) }
+ vertices.clear()
+ Thread.sleep(acceptor.vizStepDelay)
+ }
+ }), s, traversal)
+ TraversalHelper.insertAfterStep(new AggregateStep(traversal, sideEffectKey), s, traversal)
+ }
+
+ // decay all vertices except those that made it through the filter - "this way you can watch
+ // the Gremlins dying" - said daniel kuppitz. can't do this easily with generic FilterStep as
+ // it creates odd behaviors when used with loop (extra decay that probably shouldn't be there.
+ // todo: can this be better? maybe we shouldn't do this at all
+ TraversalHelper.getStepsOfAssignableClass(HasStep.class, traversal).each { HasStep s ->
+ TraversalHelper.insertAfterStep(new LambdaSideEffectStep(traversal, { Traverser traverser ->
+ final BulkSet<Object> objects = ((BulkSet<Object>) traverser.sideEffects(sideEffectKey))
+ if (!objects.isEmpty()) {
+ final List<String> vertices = objects.findAll{ Object o -> o instanceof Vertex}
+ .collect { Object o -> ((Vertex) o).id().toString() }
+ acceptor.updateVisitedVertices(vertices)
+ objects.clear()
+ Thread.sleep(acceptor.vizStepDelay)
+ }
+ }), s, traversal)
+ TraversalHelper.insertAfterStep(new AggregateStep(traversal, sideEffectKey), s, traversal)
+ }
+ }
+ }
+
+ @Override
+ public Set<Class<? extends TraversalStrategy.FinalizationStrategy>> applyPost() {
+ return POSTS;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/ae644951/gremlin-console/src/main/resources/org/apache/tinkerpop/gremlin/console/groovy/plugin/UtilitiesGremlinPluginScript.groovy
----------------------------------------------------------------------
diff --git a/gremlin-console/src/main/resources/org/apache/tinkerpop/gremlin/console/groovy/plugin/UtilitiesGremlinPluginScript.groovy b/gremlin-console/src/main/resources/org/apache/tinkerpop/gremlin/console/groovy/plugin/UtilitiesGremlinPluginScript.groovy
index 3727675..5f5e3c6 100644
--- a/gremlin-console/src/main/resources/org/apache/tinkerpop/gremlin/console/groovy/plugin/UtilitiesGremlinPluginScript.groovy
+++ b/gremlin-console/src/main/resources/org/apache/tinkerpop/gremlin/console/groovy/plugin/UtilitiesGremlinPluginScript.groovy
@@ -49,4 +49,4 @@ describeGraph = { Class<? extends org.apache.tinkerpop.gremlin.structure.Graph>
"the implementation itself. Compliant implementations will faithfully and ${lf}" +
"honestly supply these Annotations to provide the most accurate depiction of ${lf}" +
"their support."
-}
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/ae644951/gremlin-console/src/test/java/org/apache/tinkerpop/gremlin/console/groovy/plugin/GephiRemoteAcceptorIntegrateTest.java
----------------------------------------------------------------------
diff --git a/gremlin-console/src/test/java/org/apache/tinkerpop/gremlin/console/groovy/plugin/GephiRemoteAcceptorIntegrateTest.java b/gremlin-console/src/test/java/org/apache/tinkerpop/gremlin/console/groovy/plugin/GephiRemoteAcceptorIntegrateTest.java
index 247fae7..79a7997 100644
--- a/gremlin-console/src/test/java/org/apache/tinkerpop/gremlin/console/groovy/plugin/GephiRemoteAcceptorIntegrateTest.java
+++ b/gremlin-console/src/test/java/org/apache/tinkerpop/gremlin/console/groovy/plugin/GephiRemoteAcceptorIntegrateTest.java
@@ -23,6 +23,8 @@ import org.apache.commons.io.input.NullInputStream;
import org.apache.tinkerpop.gremlin.console.GremlinGroovysh;
import org.apache.tinkerpop.gremlin.console.plugin.GephiRemoteAcceptor;
import org.apache.tinkerpop.gremlin.groovy.plugin.RemoteException;
+import org.apache.tinkerpop.gremlin.structure.Graph;
+import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerFactory;
import org.codehaus.groovy.tools.shell.Groovysh;
import org.codehaus.groovy.tools.shell.IO;
import org.junit.Before;
@@ -37,13 +39,14 @@ import java.net.ServerSocket;
import java.util.Arrays;
import java.util.Collections;
+import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
+import static com.github.tomakehurst.wiremock.client.WireMock.equalTo;
+import static com.github.tomakehurst.wiremock.client.WireMock.equalToJson;
import static com.github.tomakehurst.wiremock.client.WireMock.get;
import static com.github.tomakehurst.wiremock.client.WireMock.getRequestedFor;
import static com.github.tomakehurst.wiremock.client.WireMock.post;
import static com.github.tomakehurst.wiremock.client.WireMock.postRequestedFor;
import static com.github.tomakehurst.wiremock.client.WireMock.stubFor;
-import static com.github.tomakehurst.wiremock.client.WireMock.equalTo;
-import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
import static com.github.tomakehurst.wiremock.client.WireMock.urlPathEqualTo;
import static org.hamcrest.CoreMatchers.startsWith;
import static org.junit.Assert.assertThat;
@@ -57,7 +60,7 @@ public class GephiRemoteAcceptorIntegrateTest {
private GephiRemoteAcceptor acceptor;
- private final InputStream inputStream = new NullInputStream(0);
+ private final InputStream inputStream = new NullInputStream(0);
private final OutputStream outputStream = new ByteArrayOutputStream();
private final OutputStream errorStream = new ByteArrayOutputStream();
private final IO io = new IO(inputStream, outputStream, errorStream);
@@ -65,6 +68,11 @@ public class GephiRemoteAcceptorIntegrateTest {
@Rule
public WireMockRule wireMockRule = new WireMockRule(port);
+ static {
+ final Graph graph = TinkerFactory.createModern();
+ groovysh.getInterp().getContext().setProperty("graph", graph);
+ }
+
@Before
public void before() throws Exception {
acceptor = new GephiRemoteAcceptor(groovysh, io);
@@ -91,24 +99,101 @@ public class GephiRemoteAcceptorIntegrateTest {
acceptor.submit(Arrays.asList("g = org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerGraph.open();g.addVertex();g"));
- wireMockRule.verify(2, postRequestedFor(urlPathEqualTo("/workspace0")));
+ wireMockRule.verify(4, postRequestedFor(urlPathEqualTo("/workspace0")));
wireMockRule.verify(1, getRequestedFor(urlPathEqualTo("/workspace0")));
}
@Test
- public void shouldSubmitTraversal() throws RemoteException {
+ public void shouldSubmitPath() throws RemoteException {
+ stubFor(post(urlPathEqualTo("/workspace0"))
+ .withQueryParam("format", equalTo("JSON"))
+ .withQueryParam("operation", equalTo("updateGraph"))
+ .willReturn(aResponse()
+ .withStatus(200)));
+
+ acceptor.submit(Arrays.asList(
+ "g = graph.traversal();g.V(1).repeat(org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.__().both().dedup()).until(org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.__().hasId(3)).path().next()"));
+
+ wireMockRule.verify(5, postRequestedFor(urlPathEqualTo("/workspace0")));
+ }
+
+ @Test
+ public void shouldSubmitMultiplePaths() throws RemoteException {
+ stubFor(post(urlPathEqualTo("/workspace0"))
+ .withQueryParam("format", equalTo("JSON"))
+ .withQueryParam("operation", equalTo("updateGraph"))
+ .willReturn(aResponse()
+ .withStatus(200)));
+
+ acceptor.submit(Arrays.asList(
+ "g = graph.traversal();g.V(1).repeat(org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.__().both().dedup()).until(org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.__().hasId(3)).path().toList()"));
+
+ wireMockRule.verify(5, postRequestedFor(urlPathEqualTo("/workspace0")));
+ }
+
+ @Test
+ public void shouldSubmitTraversalAfterConfigWithDefaultG() throws RemoteException {
+ stubFor(post(urlPathEqualTo("/workspace0"))
+ .withQueryParam("format", equalTo("JSON"))
+ .withQueryParam("operation", equalTo("updateGraph"))
+ .willReturn(aResponse()
+ .withStatus(200)));
+
+ acceptor.configure(Arrays.asList("visualTraversal", "graph"));
+
+ // call iterate() as groovysh isn't rigged to auto-iterate
+ acceptor.submit(Arrays.asList(
+ "vg.V(2).in('knows').out('knows').has('age',org.apache.tinkerpop.gremlin.process.traversal.P.gt(30)).outE('created').has('weight',org.apache.tinkerpop.gremlin.process.traversal.P.gt(0.5d)).inV().iterate()"));
+
+ wireMockRule.verify(18, postRequestedFor(urlPathEqualTo("/workspace0")));
+ }
+
+ @Test
+ public void shouldSubmitTraversalAfterConfigWithDefinedG() throws RemoteException {
+ stubFor(post(urlPathEqualTo("/workspace0"))
+ .withQueryParam("format", equalTo("JSON"))
+ .withQueryParam("operation", equalTo("updateGraph"))
+ .willReturn(aResponse()
+ .withStatus(200)));
+
+ acceptor.configure(Arrays.asList("visualTraversal", "graph", "x"));
+
+ // call iterate() as groovysh isn't rigged to auto-iterate
+ acceptor.submit(Arrays.asList(
+ "x.V(2).in('knows').out('knows').has('age',org.apache.tinkerpop.gremlin.process.traversal.P.gt(30)).outE('created').has('weight',org.apache.tinkerpop.gremlin.process.traversal.P.gt(0.5d)).inV().iterate()"));
+
+ wireMockRule.verify(18, postRequestedFor(urlPathEqualTo("/workspace0")));
+ }
+
+ @Test
+ public void shouldSubmitTraversalOverRepeat() throws RemoteException {
+ stubFor(post(urlPathEqualTo("/workspace0"))
+ .withQueryParam("format", equalTo("JSON"))
+ .withQueryParam("operation", equalTo("updateGraph"))
+ .willReturn(aResponse()
+ .withStatus(200)));
+
+ acceptor.configure(Arrays.asList("visualTraversal", "graph"));
+
+ // call iterate() as groovysh isn't rigged to auto-iterate
+ acceptor.submit(Arrays.asList(
+ "vg.V(1).repeat(org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.__().out()).times(2).iterate()"));
+
+ wireMockRule.verify(13, postRequestedFor(urlPathEqualTo("/workspace0")));
+ }
+
+ @Test
+ public void shouldClearGraph() throws RemoteException {
stubFor(post(urlPathEqualTo("/workspace0"))
.withQueryParam("format", equalTo("JSON"))
.withQueryParam("operation", equalTo("updateGraph"))
+ .withRequestBody(equalToJson("{\"dn\":{\"filter\":\"ALL\"}}"))
.willReturn(aResponse()
.withStatus(200)));
- acceptor.submit(Arrays.asList("g = org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerFactory.createModern().traversal();" +
- "traversal = g.V(2).store('1').in('knows').store('2').out('knows').has('age',org.apache.tinkerpop.gremlin.process.traversal.P.gt(30)).store('3').outE('created').has('weight',org.apache.tinkerpop.gremlin.process.traversal.P.gt(0.5d)).inV().store('4');" +
- "traversal.iterate();" +
- "traversal"));
+ acceptor.submit(Arrays.asList("clear"));
- wireMockRule.verify(10, postRequestedFor(urlPathEqualTo("/workspace0")));
+ wireMockRule.verify(1, postRequestedFor(urlPathEqualTo("/workspace0")));
}
private static int pickOpenPort() {
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/ae644951/gremlin-core/pom.xml
----------------------------------------------------------------------
diff --git a/gremlin-core/pom.xml b/gremlin-core/pom.xml
index f60f15a..f739355 100644
--- a/gremlin-core/pom.xml
+++ b/gremlin-core/pom.xml
@@ -20,7 +20,7 @@ limitations under the License.
<parent>
<groupId>org.apache.tinkerpop</groupId>
<artifactId>tinkerpop</artifactId>
- <version>3.0.1-SNAPSHOT</version>
+ <version>3.1.0-SNAPSHOT</version>
</parent>
<artifactId>gremlin-core</artifactId>
<name>Apache TinkerPop :: Gremlin Core</name>
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/ae644951/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Path.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Path.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Path.java
index f8fa67b..25e69bb 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Path.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Path.java
@@ -21,12 +21,8 @@ package org.apache.tinkerpop.gremlin.process.traversal;
import org.apache.tinkerpop.gremlin.structure.Graph;
import org.javatuples.Pair;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.Set;
+import java.util.*;
import java.util.function.BiConsumer;
-import java.util.function.Consumer;
import java.util.stream.IntStream;
import java.util.stream.Stream;
@@ -37,7 +33,7 @@ import java.util.stream.Stream;
*
* @author Marko A. Rodriguez (http://markorodriguez.com)
*/
-public interface Path extends Cloneable {
+public interface Path extends Cloneable, Iterable<Object> {
/**
* Get the number of step in the path.
@@ -57,13 +53,13 @@ public interface Path extends Cloneable {
*/
public Path extend(final Object object, final Set<String> labels);
- public default Path extend(final Object object, final String... labels) {
- final Path path = this.extend(object, Collections.emptySet());
- for (final String label : labels) {
- path.addLabel(label);
- }
- return path;
- }
+ /**
+ * Add labels to the head of the path.
+ *
+ * @param labels the labels at the head of the path
+ * @return the path with added labels
+ */
+ public Path extend(final Set<String> labels);
/**
* Get the object associated with the particular label of the path.
@@ -107,7 +103,7 @@ public interface Path extends Cloneable {
* @throws IllegalArgumentException if the path does not contain the label
*/
public default <A> A get(final Pop pop, final String label) throws IllegalArgumentException {
- if(Pop.all == pop) {
+ if (Pop.all == pop) {
if (this.hasLabel(label)) {
final Object object = this.get(label);
if (object instanceof List)
@@ -148,13 +144,6 @@ public interface Path extends Cloneable {
}
/**
- * Add label to the current head of the path.
- *
- * @param label the label to add to the head of the path
- */
- public void addLabel(final String label);
-
- /**
* An ordered list of the objects in the path.
*
* @return the objects of the path
@@ -189,8 +178,8 @@ public interface Path extends Cloneable {
return true;
}
- public default void forEach(final Consumer<Object> consumer) {
- this.objects().forEach(consumer);
+ public default Iterator<Object> iterator() {
+ return this.objects().iterator();
}
public default void forEach(final BiConsumer<Object, Set<String>> consumer) {
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/ae644951/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 bf56d31..e0a63b6 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
@@ -22,7 +22,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.Conjun
import org.apache.tinkerpop.gremlin.process.traversal.strategy.finalization.EngineDependentStrategy;
import org.apache.tinkerpop.gremlin.process.traversal.strategy.finalization.ProfileStrategy;
import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.AdjacentToIncidentStrategy;
-import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.DedupBijectionStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.FilterRankingStrategy;
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.strategy.optimization.MatchPredicateStrategy;
@@ -200,7 +200,7 @@ public interface TraversalStrategies extends Serializable, Cloneable {
ProfileStrategy.instance(),
IncidentToAdjacentStrategy.instance(),
AdjacentToIncidentStrategy.instance(),
- DedupBijectionStrategy.instance(),
+ FilterRankingStrategy.instance(),
IdentityRemovalStrategy.instance(),
MatchPredicateStrategy.instance(),
RangeByIsCountStrategy.instance(),
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/ae644951/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Traverser.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Traverser.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Traverser.java
index fc5d421..06925a8 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Traverser.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Traverser.java
@@ -21,6 +21,7 @@ package org.apache.tinkerpop.gremlin.process.traversal;
import org.apache.tinkerpop.gremlin.structure.util.Attachable;
import java.io.Serializable;
+import java.util.Set;
import java.util.function.Function;
/**
@@ -180,6 +181,8 @@ public interface Traverser<T> extends Serializable, Comparable<Traverser<T>>, Cl
*/
public Admin<T> split();
+ public void addLabels(final Set<String> labels);
+
/**
* Set the current object location of the traverser.
*
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/ae644951/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.java
index 008a46c..a643e48 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.java
@@ -18,137 +18,22 @@
*/
package org.apache.tinkerpop.gremlin.process.traversal.dsl.graph;
-import org.apache.tinkerpop.gremlin.process.traversal.Order;
-import org.apache.tinkerpop.gremlin.process.traversal.P;
-import org.apache.tinkerpop.gremlin.process.traversal.Path;
-import org.apache.tinkerpop.gremlin.process.traversal.Pop;
-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.Traverser;
-import org.apache.tinkerpop.gremlin.process.traversal.lambda.ElementValueTraversal;
-import org.apache.tinkerpop.gremlin.process.traversal.lambda.FunctionTraverser;
-import org.apache.tinkerpop.gremlin.process.traversal.lambda.IdentityTraversal;
-import org.apache.tinkerpop.gremlin.process.traversal.lambda.LoopTraversal;
-import org.apache.tinkerpop.gremlin.process.traversal.lambda.PredicateTraverser;
-import org.apache.tinkerpop.gremlin.process.traversal.lambda.TokenTraversal;
-import org.apache.tinkerpop.gremlin.process.traversal.lambda.TrueTraversal;
+import org.apache.tinkerpop.gremlin.process.traversal.*;
+import org.apache.tinkerpop.gremlin.process.traversal.lambda.*;
import org.apache.tinkerpop.gremlin.process.traversal.step.ComparatorHolder;
import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalOptionParent;
import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent;
-import org.apache.tinkerpop.gremlin.process.traversal.step.branch.BranchStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.branch.ChooseStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.branch.LocalStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.branch.RepeatStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.branch.UnionStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.filter.AndStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.filter.CoinStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.filter.ConjunctionStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.filter.CyclicPathStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.filter.DedupGlobalStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.filter.DropStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.filter.HasStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.filter.IsStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.filter.LambdaFilterStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.filter.NotStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.filter.OrStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.filter.RangeGlobalStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.filter.SampleGlobalStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.filter.SimplePathStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.filter.TailGlobalStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.filter.TimeLimitStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.filter.TraversalFilterStep;
-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.map.AddEdgeStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.map.AddVertexStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.map.CoalesceStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.map.ConstantStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.map.CountGlobalStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.map.CountLocalStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.map.DedupLocalStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.map.EdgeOtherVertexStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.map.EdgeVertexStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.map.FoldStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.map.GroupCountStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.map.GroupStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.map.IdStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.map.LabelStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.map.LambdaFlatMapStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.map.LambdaMapStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.map.MapKeysStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.map.MapValuesStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.map.MatchStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.map.MaxGlobalStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.map.MaxLocalStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.map.MeanGlobalStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.map.MeanLocalStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.map.MinGlobalStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.map.MinLocalStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.map.OrderGlobalStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.map.OrderLocalStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.map.PathStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.map.PropertiesStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.map.PropertyKeyStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.map.PropertyMapStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.map.PropertyValueStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.map.RangeLocalStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.map.SackStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.map.SampleLocalStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.map.SelectOneStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.map.SelectStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.map.SumGlobalStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.map.SumLocalStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.map.TailLocalStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.map.TraversalFlatMapStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.map.TraversalMapStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.map.TreeStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.map.UnfoldStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.map.VertexStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.AddPropertyStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.AggregateStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.GroupCountSideEffectStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.GroupSideEffectStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.IdentityStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.InjectStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.LambdaSideEffectStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.ProfileStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.SackElementValueStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.SackObjectStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.SideEffectCapStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.StartStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.StoreStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.SubgraphStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.TraversalSideEffectStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.TreeSideEffectStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.util.ElementFunctionComparator;
-import org.apache.tinkerpop.gremlin.process.traversal.step.util.ElementValueComparator;
-import org.apache.tinkerpop.gremlin.process.traversal.step.util.HasContainer;
-import org.apache.tinkerpop.gremlin.process.traversal.step.util.NoOpBarrierStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.util.TraversalComparator;
-import org.apache.tinkerpop.gremlin.process.traversal.step.util.Tree;
+import org.apache.tinkerpop.gremlin.process.traversal.step.branch.*;
+import org.apache.tinkerpop.gremlin.process.traversal.step.filter.*;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.*;
+import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.*;
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.*;
import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper;
-import org.apache.tinkerpop.gremlin.structure.Direction;
-import org.apache.tinkerpop.gremlin.structure.Edge;
-import org.apache.tinkerpop.gremlin.structure.Element;
-import org.apache.tinkerpop.gremlin.structure.Property;
-import org.apache.tinkerpop.gremlin.structure.PropertyType;
-import org.apache.tinkerpop.gremlin.structure.T;
-import org.apache.tinkerpop.gremlin.structure.Vertex;
-import org.apache.tinkerpop.gremlin.structure.VertexProperty;
+import org.apache.tinkerpop.gremlin.structure.*;
import org.apache.tinkerpop.gremlin.util.function.ConstantSupplier;
-import java.util.Arrays;
-import java.util.Comparator;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
-import java.util.function.BiFunction;
-import java.util.function.BinaryOperator;
-import java.util.function.Consumer;
-import java.util.function.Function;
-import java.util.function.Predicate;
+import java.util.*;
+import java.util.function.*;
/**
* @author Marko A. Rodriguez (http://markorodriguez.com)
@@ -517,14 +402,18 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
return this.asAdmin().addStep(new SackStep<>(this.asAdmin()));
}
+ public default GraphTraversal<S, Integer> loops() {
+ return this.asAdmin().addStep(new LoopsStep<>(this.asAdmin()));
+ }
+
/**
* Map the {@link Traverser} to a {@link Map} projection of sideEffect values, map values, and/or path values.
*
- * @param pop if there are multiple objects referenced in the path, the {@link Pop} to use.
+ * @param pop if there are multiple objects referenced in the path, the {@link Pop} to use.
* @param selectKey1 the first key to project
* @param selectKey2 the second key to project
* @param otherSelectKeys the third+ keys to project
- * @param <E2> the type of the objects projected
+ * @param <E2> the type of the objects projected
* @return the traversal with an appended {@link SelectStep}.
*/
public default <E2> GraphTraversal<S, Map<String, E2>> select(final Pop pop, final String selectKey1, final String selectKey2, String... otherSelectKeys) {
@@ -541,7 +430,7 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
* @param selectKey1 the first key to project
* @param selectKey2 the second key to project
* @param otherSelectKeys the third+ keys to project
- * @param <E2> the type of the objects projected
+ * @param <E2> the type of the objects projected
* @return the traversal with an appended {@link SelectStep}.
*/
public default <E2> GraphTraversal<S, Map<String, E2>> select(final String selectKey1, final String selectKey2, String... otherSelectKeys) {
@@ -983,7 +872,7 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
}
public default GraphTraversal<S, E> times(final int maxLoops) {
- return this.until(new LoopTraversal(maxLoops));
+ return this.until(new LoopTraversal<>(maxLoops));
}
public default <E2> GraphTraversal<S, E2> local(final Traversal<?, E2> localTraversal) {
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/ae644951/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/__.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/__.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/__.java
index 3d49d7a..e2d9e80 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/__.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/__.java
@@ -18,28 +18,14 @@
*/
package org.apache.tinkerpop.gremlin.process.traversal.dsl.graph;
-import org.apache.tinkerpop.gremlin.process.traversal.P;
-import org.apache.tinkerpop.gremlin.process.traversal.Path;
-import org.apache.tinkerpop.gremlin.process.traversal.Pop;
-import org.apache.tinkerpop.gremlin.process.traversal.Scope;
-import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
-import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
+import org.apache.tinkerpop.gremlin.process.traversal.*;
import org.apache.tinkerpop.gremlin.process.traversal.step.util.Tree;
-import org.apache.tinkerpop.gremlin.structure.Direction;
-import org.apache.tinkerpop.gremlin.structure.Edge;
-import org.apache.tinkerpop.gremlin.structure.Property;
-import org.apache.tinkerpop.gremlin.structure.T;
-import org.apache.tinkerpop.gremlin.structure.Vertex;
-import org.apache.tinkerpop.gremlin.structure.VertexProperty;
+import org.apache.tinkerpop.gremlin.structure.*;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
-import java.util.function.BiFunction;
-import java.util.function.BinaryOperator;
-import java.util.function.Consumer;
-import java.util.function.Function;
-import java.util.function.Predicate;
+import java.util.function.*;
/**
* @author Marko A. Rodriguez (http://markorodriguez.com)
@@ -301,6 +287,13 @@ public class __ {
}
/**
+ * @see {@link GraphTraversal#loops()}
+ */
+ public static <A> GraphTraversal<A, Integer> loops() {
+ return __.<A>start().loops();
+ }
+
+ /**
* @see {@link GraphTraversal#select(Pop, String)}
*/
public static <A, B> GraphTraversal<A, B> select(final Pop pop, final String selectKey) {
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/ae644951/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/lambda/LoopTraversal.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/lambda/LoopTraversal.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/lambda/LoopTraversal.java
index 59321f2..9c37853 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/lambda/LoopTraversal.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/lambda/LoopTraversal.java
@@ -1,21 +1,24 @@
/*
- * 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
+ * * 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.
*
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
*/
+
package org.apache.tinkerpop.gremlin.process.traversal.lambda;
import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
@@ -51,4 +54,4 @@ public final class LoopTraversal<S, E> extends AbstractLambdaTraversal<S, E> {
public int hashCode() {
return this.getClass().hashCode() ^ Long.hashCode(this.maxLoops);
}
-}
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/ae644951/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/Scoping.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/Scoping.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/Scoping.java
index 1ad9f43..6724619 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/Scoping.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/Scoping.java
@@ -38,9 +38,9 @@ public interface Scoping {
public static enum Variable {START, END}
public static final Set<TraverserRequirement> TYPICAL_LOCAL_REQUIREMENTS = EnumSet.of(TraverserRequirement.OBJECT, TraverserRequirement.SIDE_EFFECTS);
- public static final Set<TraverserRequirement> TYPICAL_GLOBAL_REQUIREMENTS = EnumSet.of(TraverserRequirement.OBJECT, TraverserRequirement.PATH, TraverserRequirement.SIDE_EFFECTS);
+ public static final Set<TraverserRequirement> TYPICAL_GLOBAL_REQUIREMENTS = EnumSet.of(TraverserRequirement.OBJECT, TraverserRequirement.LABELED_PATH, TraverserRequirement.SIDE_EFFECTS);
public static final TraverserRequirement[] TYPICAL_LOCAL_REQUIREMENTS_ARRAY = new TraverserRequirement[]{TraverserRequirement.OBJECT, TraverserRequirement.SIDE_EFFECTS};
- public static final TraverserRequirement[] TYPICAL_GLOBAL_REQUIREMENTS_ARRAY = new TraverserRequirement[]{TraverserRequirement.OBJECT, TraverserRequirement.PATH, TraverserRequirement.SIDE_EFFECTS};
+ public static final TraverserRequirement[] TYPICAL_GLOBAL_REQUIREMENTS_ARRAY = new TraverserRequirement[]{TraverserRequirement.OBJECT, TraverserRequirement.LABELED_PATH, TraverserRequirement.SIDE_EFFECTS};
public default <S> S getScopeValue(final Pop pop, final String key, final Traverser.Admin<?> traverser) throws IllegalArgumentException {
if (traverser.getSideEffects().get(key).isPresent())
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/ae644951/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/BranchStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/BranchStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/BranchStep.java
index eee95e7..2989096 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/BranchStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/BranchStep.java
@@ -116,6 +116,7 @@ public class BranchStep<S, E, M> extends ComputerAwareStep<S, E> implements Trav
branch.forEach(traversal -> {
final Traverser.Admin<E> split = (Traverser.Admin<E>) start.split();
split.setStepId(traversal.getStartStep().getId());
+ //split.addLabels(this.labels);
ends.add(split);
});
}
@@ -125,6 +126,7 @@ public class BranchStep<S, E, M> extends ComputerAwareStep<S, E> implements Trav
anyBranch.forEach(traversal -> {
final Traverser.Admin<E> split = (Traverser.Admin<E>) start.split();
split.setStepId(traversal.getStartStep().getId());
+ //split.addLabels(this.labels);
ends.add(split);
});
}
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/ae644951/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/RepeatStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/RepeatStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/RepeatStep.java
index 21d848a..f9e1df6 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/RepeatStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/RepeatStep.java
@@ -28,7 +28,12 @@ import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalUtil;
import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
import org.apache.tinkerpop.gremlin.util.iterator.IteratorUtils;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.NoSuchElementException;
+import java.util.Set;
/**
* @author Marko A. Rodriguez (http://markorodriguez.com)
@@ -164,6 +169,7 @@ public final class RepeatStep<S> extends ComputerAwareStep<S, S> implements Trav
if (doUntil(start, true)) {
start.resetLoops();
start.setStepId(this.getNextStep().getId());
+ start.addLabels(this.labels);
return IteratorUtils.of(start);
} else {
start.setStepId(this.repeatTraversal.getStartStep().getId());
@@ -253,6 +259,7 @@ public final class RepeatStep<S> extends ComputerAwareStep<S, S> implements Trav
if (doUntil(start, false)) {
start.resetLoops();
start.setStepId(RepeatStep.this.getNextStep().getId());
+ start.addLabels(RepeatStep.this.labels);
return IteratorUtils.of(start);
} else {
start.setStepId(RepeatStep.this.getId());
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/ae644951/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/DedupGlobalStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/DedupGlobalStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/DedupGlobalStep.java
index 5dc8510..0dfbe5f 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/DedupGlobalStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/DedupGlobalStep.java
@@ -105,7 +105,7 @@ public final class DedupGlobalStep<S> extends FilterStep<S> implements Traversal
@Override
public Set<TraverserRequirement> getRequirements() {
- return this.dedupLabels == null ? this.getSelfAndChildRequirements(TraverserRequirement.BULK) : this.getSelfAndChildRequirements(TraverserRequirement.PATH, TraverserRequirement.BULK);
+ return this.dedupLabels == null ? this.getSelfAndChildRequirements(TraverserRequirement.BULK) : this.getSelfAndChildRequirements(TraverserRequirement.LABELED_PATH, TraverserRequirement.BULK);
}
@Override
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/ae644951/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/WherePredicateStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/WherePredicateStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/WherePredicateStep.java
index a1a5455..bd4ef03 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/WherePredicateStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/WherePredicateStep.java
@@ -31,24 +31,13 @@ import org.apache.tinkerpop.gremlin.process.traversal.util.ConjunctionP;
import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper;
import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.EnumSet;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Optional;
-import java.util.Set;
+import java.util.*;
/**
* @author Marko A. Rodriguez (http://markorodriguez.com)
*/
public final class WherePredicateStep<S> extends FilterStep<S> implements Scoping {
- private static final Set<TraverserRequirement> LOCAL_REQUIREMENTS = EnumSet.of(TraverserRequirement.OBJECT, TraverserRequirement.SIDE_EFFECTS);
- private static final Set<TraverserRequirement> GLOBAL_REQUIREMENTS = EnumSet.of(TraverserRequirement.PATH, TraverserRequirement.SIDE_EFFECTS);
-
protected String startKey;
protected List<String> selectKeys;
protected P<Object> predicate;
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/ae644951/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/LoopsStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/LoopsStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/LoopsStep.java
new file mode 100644
index 0000000..2db9ab9
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/LoopsStep.java
@@ -0,0 +1,37 @@
+/*
+ * 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.map;
+
+import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
+import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
+
+/**
+ * @author Daniel Kuppitz (http://gremlin.guru)
+ */
+public final class LoopsStep<S> extends MapStep<S, Integer> {
+
+ public LoopsStep(final Traversal.Admin traversal) {
+ super(traversal);
+ }
+
+ @Override
+ protected Integer map(final Traverser.Admin<S> traverser) {
+ return traverser.loops();
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/ae644951/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MapKeysStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MapKeysStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MapKeysStep.java
index 8aea53d..c8e722b 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MapKeysStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MapKeysStep.java
@@ -23,21 +23,29 @@ package org.apache.tinkerpop.gremlin.process.traversal.step.map;
import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
+import org.apache.tinkerpop.gremlin.util.iterator.EmptyIterator;
+import java.util.Collections;
import java.util.Iterator;
import java.util.Map;
/**
* @author Marko A. Rodriguez (http://markorodriguez.com)
+ * @author Daniel Kuppitz (http://gremlin.guru)
*/
-public final class MapKeysStep<S> extends FlatMapStep<Map<S, ?>, S> {
+public final class MapKeysStep<S, E> extends FlatMapStep<S, E> {
public MapKeysStep(final Traversal.Admin traversal) {
super(traversal);
}
@Override
- protected Iterator<S> flatMap(final Traverser.Admin<Map<S, ?>> traverser) {
- return traverser.get().keySet().iterator();
+ protected Iterator<E> flatMap(final Traverser.Admin<S> traverser) {
+ final S s = traverser.get();
+ if (s instanceof Map)
+ return ((Map) s).keySet().iterator();
+ if (s instanceof Map.Entry)
+ return Collections.singleton((E) ((Map.Entry) s).getKey()).iterator();
+ return EmptyIterator.instance();
}
}
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/ae644951/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MapValuesStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MapValuesStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MapValuesStep.java
index fe41d15..10e35e2 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MapValuesStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MapValuesStep.java
@@ -23,21 +23,29 @@ package org.apache.tinkerpop.gremlin.process.traversal.step.map;
import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
+import org.apache.tinkerpop.gremlin.util.iterator.EmptyIterator;
+import java.util.Collections;
import java.util.Iterator;
import java.util.Map;
/**
* @author Marko A. Rodriguez (http://markorodriguez.com)
+ * @author Daniel Kuppitz (http://gremlin.guru)
*/
-public final class MapValuesStep<S> extends FlatMapStep<Map<?, S>, S> {
+public final class MapValuesStep<S, E> extends FlatMapStep<S, E> {
public MapValuesStep(final Traversal.Admin traversal) {
super(traversal);
}
@Override
- protected Iterator<S> flatMap(final Traverser.Admin<Map<?, S>> traverser) {
- return traverser.get().values().iterator();
+ protected Iterator<E> flatMap(final Traverser.Admin<S> traverser) {
+ final S s = traverser.get();
+ if (s instanceof Map)
+ return ((Map) s).values().iterator();
+ if (s instanceof Map.Entry)
+ return Collections.singleton((E) ((Map.Entry) s).getValue()).iterator();
+ return EmptyIterator.instance();
}
}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/ae644951/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 ae1a264..dcb2078 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
@@ -312,8 +312,8 @@ public final class MatchStep<S, E> extends ComputerAwareStep<S, Map<String, E>>
traverser = this.starts.next();
final Path path = traverser.path();
if (!this.matchStartLabels.stream().filter(path::hasLabel).findAny().isPresent())
- path.addLabel(this.computedStartLabel); // if the traverser doesn't have a legal start, then provide it the pre-computed one
- path.addLabel(this.getId()); // so the traverser never returns to this branch ever again
+ traverser.addLabels(Collections.singleton(this.computedStartLabel)); // if the traverser doesn't have a legal start, then provide it the pre-computed one
+ traverser.addLabels(Collections.singleton(this.getId())); // so the traverser never returns to this branch ever again
}
///
if (!this.isDuplicate(traverser)) {
@@ -337,13 +337,14 @@ public final class MatchStep<S, E> extends ComputerAwareStep<S, Map<String, E>>
final Traverser.Admin traverser = this.starts.next();
final Path path = traverser.path();
if (!this.matchStartLabels.stream().filter(path::hasLabel).findAny().isPresent())
- path.addLabel(this.computedStartLabel); // if the traverser doesn't have a legal start, then provide it the pre-computed one
+ traverser.addLabels(Collections.singleton(this.computedStartLabel)); // if the traverser doesn't have a legal start, then provide it the pre-computed one
if (!path.hasLabel(this.getId()))
- path.addLabel(this.getId()); // so the traverser never returns to this branch ever again
+ traverser.addLabels(Collections.singleton(this.getId())); // so the traverser never returns to this branch ever again
///
if (!this.isDuplicate(traverser)) {
if (hasMatched(this.conjunction, traverser)) {
traverser.setStepId(this.getNextStep().getId());
+ traverser.addLabels(this.labels);
return IteratorUtils.of(traverser.split(this.getBindings(traverser), this));
}
if (this.conjunction == ConjunctionStep.Conjunction.AND) {
@@ -374,7 +375,7 @@ public final class MatchStep<S, E> extends ComputerAwareStep<S, Map<String, E>>
@Override
public Set<TraverserRequirement> getRequirements() {
- return this.getSelfAndChildRequirements(TraverserRequirement.PATH, TraverserRequirement.SIDE_EFFECTS);
+ return this.getSelfAndChildRequirements(TraverserRequirement.LABELED_PATH, TraverserRequirement.SIDE_EFFECTS);
}
//////////////////////////////
@@ -392,7 +393,7 @@ public final class MatchStep<S, E> extends ComputerAwareStep<S, Map<String, E>>
@Override
protected Traverser<Object> processNextStart() throws NoSuchElementException {
final Traverser.Admin<Object> traverser = this.starts.next();
- traverser.path().addLabel(this.getId());
+ traverser.addLabels(Collections.singleton(this.getId()));
((MatchStep<?, ?>) this.getTraversal().getParent()).getMatchAlgorithm().recordStart(traverser, this.getTraversal());
// TODO: sideEffect check?
return null == this.selectKey ? traverser : traverser.split(traverser.path().get(Pop.last, this.selectKey), this);
@@ -421,8 +422,8 @@ public final class MatchStep<S, E> extends ComputerAwareStep<S, Map<String, E>>
this.scopeKeys = new HashSet<>();
if (null != this.selectKey)
this.scopeKeys.add(this.selectKey);
- if (this.getNextStep() instanceof Scoping)
- this.scopeKeys.addAll(((Scoping) this.getNextStep()).getScopeKeys());
+ if (this.getNextStep() instanceof WhereTraversalStep || this.getNextStep() instanceof WherePredicateStep)
+ this.scopeKeys.addAll(((Scoping) this.getNextStep()).getScopeKeys());
this.scopeKeys = Collections.unmodifiableSet(this.scopeKeys);
}
return this.scopeKeys;
@@ -444,7 +445,7 @@ public final class MatchStep<S, E> extends ComputerAwareStep<S, Map<String, E>>
final Traverser.Admin traverser = this.starts.next();
// no end label
if (null == this.matchKey) {
- if (this.traverserStepIdSetByChild)
+ if (this.traverserStepIdAndLabelsSetByChild)
traverser.setStepId(((MatchStep<?, ?>) this.getTraversal().getParent()).getId());
((MatchStep<?, ?>) this.getTraversal().getParent()).getMatchAlgorithm().recordEnd(traverser, this.getTraversal());
return traverser;
@@ -453,9 +454,9 @@ public final class MatchStep<S, E> extends ComputerAwareStep<S, Map<String, E>>
// path check
final Path path = traverser.path();
if (!path.hasLabel(this.matchKey) || traverser.get().equals(path.get(Pop.last, this.matchKey))) {
- if (this.traverserStepIdSetByChild)
+ if (this.traverserStepIdAndLabelsSetByChild)
traverser.setStepId(((MatchStep<?, ?>) this.getTraversal().getParent()).getId());
- traverser.path().addLabel(this.matchKey);
+ traverser.addLabels(Collections.singleton(this.matchKey));
((MatchStep<?, ?>) this.getTraversal().getParent()).getMatchAlgorithm().recordEnd(traverser, this.getTraversal());
return traverser;
}