You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tinkerpop.apache.org by ok...@apache.org on 2015/06/15 23:49:15 UTC
incubator-tinkerpop git commit: XMatchStep now has the same API as
MatchStep -- startKey, traversals and returns Map.
Repository: incubator-tinkerpop
Updated Branches:
refs/heads/xmatch c77521cc1 -> 538af16b4
XMatchStep now has the same API as MatchStep -- startKey,traversals and returns Map<String,E>.
Project: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/commit/538af16b
Tree: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/tree/538af16b
Diff: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/diff/538af16b
Branch: refs/heads/xmatch
Commit: 538af16b453090a332f1bf571e55ea21462ac53e
Parents: c77521c
Author: Marko A. Rodriguez <ok...@gmail.com>
Authored: Mon Jun 15 15:49:04 2015 -0600
Committer: Marko A. Rodriguez <ok...@gmail.com>
Committed: Mon Jun 15 15:49:04 2015 -0600
----------------------------------------------------------------------
.../traversal/dsl/graph/GraphTraversal.java | 5 +-
.../gremlin/process/traversal/dsl/graph/__.java | 4 +-
.../traversal/step/filter/exp/XMatchStep.java | 94 ++++++++++++++++----
.../tinkergraph/structure/TinkerGraphTest.java | 5 +-
4 files changed, 83 insertions(+), 25 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/538af16b/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 8b9db86..06a3951 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
@@ -465,6 +465,7 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
public default <E2> GraphTraversal<S, Map<String, E2>> match(final String startLabel, final Traversal<?, ?>... traversals) {
return (GraphTraversal) this.asAdmin().addStep(new MatchStep<E, Map<String, E2>>(this.asAdmin(), startLabel, traversals));
+ //return (GraphTraversal) this.asAdmin().addStep(new XMatchStep(this.asAdmin(), startLabel, XMatchStep.Conjunction.AND, traversals));
}
/**
@@ -1010,8 +1011,8 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
////
- public default GraphTraversal<S, E> xmatch(final Traversal<?, ?>... andTraversals) {
- return this.asAdmin().addStep(new XMatchStep<>(this.asAdmin(), XMatchStep.Conjunction.AND, andTraversals));
+ public default <E2> GraphTraversal<S, Map<String,E2>> xmatch(final String startKey, final Traversal<?, ?>... andTraversals) {
+ return this.asAdmin().addStep(new XMatchStep<>(this.asAdmin(), startKey, XMatchStep.Conjunction.AND, andTraversals));
}
@Override
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/538af16b/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 7011036..af17803 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
@@ -774,8 +774,8 @@ public class __ {
return __.<A>start().barrier(maxBarrierSize);
}
- public static <A> GraphTraversal<A, A> xmatch(final Traversal<?, ?>... andTraversals) {
- return __.<A>start().xmatch(andTraversals);
+ public static <A,B> GraphTraversal<A, Map<String,B>> xmatch(final String startKey, final Traversal<?, ?>... andTraversals) {
+ return __.<A>start().xmatch(startKey, andTraversals);
}
}
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/538af16b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/exp/XMatchStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/exp/XMatchStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/exp/XMatchStep.java
index 9e72bc5..8debce5 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/exp/XMatchStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/exp/XMatchStep.java
@@ -27,6 +27,7 @@ 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.step.Scoping;
import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent;
import org.apache.tinkerpop.gremlin.process.traversal.step.filter.AndStep;
import org.apache.tinkerpop.gremlin.process.traversal.step.filter.ConjunctionStep;
@@ -41,9 +42,11 @@ import org.apache.tinkerpop.gremlin.util.iterator.IteratorUtils;
import java.util.ArrayList;
import java.util.Collections;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
+import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Optional;
import java.util.Set;
@@ -54,19 +57,22 @@ import java.util.stream.Stream;
/**
* @author Marko A. Rodriguez (http://markorodriguez.com)
*/
-public final class XMatchStep<S> extends ComputerAwareStep<S, S> implements TraversalParent {
+public final class XMatchStep<S, E> extends ComputerAwareStep<S, Map<String, E>> implements TraversalParent, Scoping {
public enum Conjunction {AND, OR}
private List<Traversal.Admin<Object, Object>> conjunctionTraversals = new ArrayList<>();
private boolean first = true;
private Set<String> matchStartLabels = null;
+ private Set<String> matchEndLabels = null;
private final Conjunction conjunction;
+ private final String startKey;
private final MatchAlgorithm matchAlgorithm = new GreedyMatchAlgorithm();
- public XMatchStep(final Traversal.Admin traversal, final Conjunction conjunction, final Traversal... conjunctionTraversals) {
+ public XMatchStep(final Traversal.Admin traversal, final String startKey, final Conjunction conjunction, final Traversal... conjunctionTraversals) {
super(traversal);
this.conjunction = conjunction;
+ this.traversal.getEndStep().addLabel(this.startKey = startKey);
this.conjunctionTraversals = (List) Stream.of(conjunctionTraversals).map(Traversal::asAdmin).map(this::integrateChild).collect(Collectors.toList());
this.conjunctionTraversals.forEach(this::configureStartAndEndSteps); // recursively convert to SelectOneStep, XMatchStep, or XMatchEndStep
}
@@ -76,14 +82,17 @@ public final class XMatchStep<S> extends ComputerAwareStep<S, S> implements Trav
// START STEP to SelectOneStep OR XMatchStep
final Step<?, ?> startStep = conjunctionTraversal.getStartStep();
if (startStep instanceof ConjunctionStep) {
- final XMatchStep xMatchStep = new XMatchStep(conjunctionTraversal,
+ final XMatchStep xMatchStep = new XMatchStep(conjunctionTraversal, this.startKey,
startStep instanceof AndStep ? XMatchStep.Conjunction.AND : XMatchStep.Conjunction.OR,
((ConjunctionStep<?>) startStep).getLocalChildren().toArray(new Traversal[((ConjunctionStep<?>) startStep).getLocalChildren().size()]));
TraversalHelper.replaceStep(startStep, xMatchStep, conjunctionTraversal);
} else if (startStep instanceof StartStep && !startStep.getLabels().isEmpty()) {
if (startStep.getLabels().size() > 1)
throw new IllegalArgumentException("The start step of a match()-traversal can only have one label: " + startStep);
- TraversalHelper.replaceStep(conjunctionTraversal.getStartStep(), new SelectOneStep<>(conjunctionTraversal, Scope.global, Pop.head, startStep.getLabels().iterator().next()), conjunctionTraversal);
+ final String label = startStep.getLabels().iterator().next();
+ final Step selectOneStep = new SelectOneStep<>(conjunctionTraversal, Scope.global, Pop.head, label);
+ selectOneStep.addLabel(label);
+ TraversalHelper.replaceStep(conjunctionTraversal.getStartStep(), selectOneStep, conjunctionTraversal);
}
// END STEP to XMatchStep
final Step<?, ?> endStep = conjunctionTraversal.getEndStep();
@@ -101,21 +110,55 @@ public final class XMatchStep<S> extends ComputerAwareStep<S, S> implements Trav
public Set<String> getMatchStartLabels() {
if (null == this.matchStartLabels) {
this.matchStartLabels = new HashSet<>();
- for (final Traversal.Admin<Object, Object> conjunctionTraversals : this.conjunctionTraversals) {
- this.matchStartLabels.addAll(conjunctionTraversals.getStartStep() instanceof XMatchStep ?
- ((XMatchStep) conjunctionTraversals.getStartStep()).getMatchStartLabels() :
- ((SelectOneStep) conjunctionTraversals.getStartStep()).getScopeKeys());
+ for (final Traversal.Admin<Object, Object> conjunctionTraversal : this.conjunctionTraversals) {
+ this.matchStartLabels.addAll(conjunctionTraversal.getStartStep() instanceof XMatchStep ?
+ ((XMatchStep) conjunctionTraversal.getStartStep()).getMatchStartLabels() :
+ ((SelectOneStep) conjunctionTraversal.getStartStep()).getScopeKeys());
}
this.matchStartLabels = Collections.unmodifiableSet(this.matchStartLabels);
}
return this.matchStartLabels;
}
+ public Set<String> getMatchEndLabels() {
+ if (null == this.matchEndLabels) {
+ this.matchEndLabels = new HashSet<>();
+ for (final Traversal.Admin<Object, Object> conjunctionTraversal : this.conjunctionTraversals) {
+ if (conjunctionTraversal.getStartStep() instanceof XMatchStep) {
+ this.matchEndLabels.addAll(((XMatchStep) conjunctionTraversal.getStartStep()).getMatchEndLabels());
+ }
+ this.matchEndLabels.add(((XMatchEndStep) (Step<?, ?>) conjunctionTraversal.getEndStep()).matchKey);
+ }
+ this.matchEndLabels = Collections.unmodifiableSet(this.matchEndLabels);
+ }
+ return this.matchEndLabels;
+ }
+
public List<Traversal.Admin<Object, Object>> getGlobalChildren() {
return Collections.unmodifiableList(this.conjunctionTraversals);
}
@Override
+ public Scope getScope() {
+ return Scope.global;
+ }
+
+ @Override
+ public Scope recommendNextScope() {
+ return Scope.local;
+ }
+
+ @Override
+ public void setScope(final Scope scope) {
+
+ }
+
+ @Override
+ public Set<String> getScopeKeys() {
+ return this.getMatchEndLabels();
+ }
+
+ @Override
public String toString() {
return StringFactory.stepString(this, this.conjunction, this.conjunctionTraversals);
}
@@ -127,8 +170,8 @@ public final class XMatchStep<S> extends ComputerAwareStep<S, S> implements Trav
}
@Override
- public XMatchStep<S> clone() {
- final XMatchStep<S> clone = (XMatchStep<S>) super.clone();
+ public XMatchStep<S, E> clone() {
+ final XMatchStep<S, E> clone = (XMatchStep<S, E>) super.clone();
clone.conjunctionTraversals = new ArrayList<>();
for (final Traversal.Admin<Object, Object> traversal : this.conjunctionTraversals) {
clone.conjunctionTraversals.add(clone.integrateChild(traversal.clone()));
@@ -146,11 +189,26 @@ public final class XMatchStep<S> extends ComputerAwareStep<S, S> implements Trav
counter++;
}
}
+ // if (counter == 0) traverser.path().addLabel(this.startKey); // for computer to add the start key
return this.conjunctionTraversals.size() == counter;
}
+ private Map<String, E> getBindings(final Traverser<S> traverser) {
+ final Map<String, E> bindings = new HashMap<>();
+ traverser.path().forEach((object, labels) -> {
+ for (final String label : labels) {
+ if (this.getMatchEndLabels().contains(label)) {
+ bindings.put(label, (E) object);
+ } else if (this.getMatchStartLabels().contains(label)) {
+ bindings.put(label, (E) object);
+ }
+ }
+ });
+ return bindings;
+ }
+
@Override
- protected Iterator<Traverser<S>> standardAlgorithm() throws NoSuchElementException {
+ protected Iterator<Traverser<Map<String, E>>> standardAlgorithm() throws NoSuchElementException {
while (true) {
Traverser.Admin traverser = null;
if (this.first) {
@@ -164,10 +222,10 @@ public final class XMatchStep<S> extends ComputerAwareStep<S, S> implements Trav
}
}
}
- if (null == traverser)
+ if (null == traverser) {
traverser = this.starts.next();
- else if (hasMatched(this.conjunction, traverser))
- return IteratorUtils.of(traverser);
+ } else if (hasMatched(this.conjunction, traverser))
+ return IteratorUtils.of(traverser.split(this.getBindings(traverser), this));
if (this.conjunction == Conjunction.AND) {
final Traversal.Admin<Object, Object> conjunctionTraversal = this.matchAlgorithm.apply(traverser); // determine which sub-pattern the traverser should try next
@@ -184,7 +242,7 @@ public final class XMatchStep<S> extends ComputerAwareStep<S, S> implements Trav
}
@Override
- protected Iterator<Traverser<S>> computerAlgorithm() throws NoSuchElementException {
+ protected Iterator<Traverser<Map<String, E>>> computerAlgorithm() throws NoSuchElementException {
if (this.first) {
this.matchAlgorithm.initialize(this.conjunctionTraversals);
this.first = false;
@@ -192,7 +250,7 @@ public final class XMatchStep<S> extends ComputerAwareStep<S, S> implements Trav
final Traverser.Admin traverser = this.starts.next();
if (hasMatched(this.conjunction, traverser)) {
traverser.setStepId(this.getNextStep().getId());
- return IteratorUtils.of(traverser);
+ return IteratorUtils.of(traverser.split(this.getBindings(traverser), this));
}
if (this.conjunction == Conjunction.AND) {
@@ -201,7 +259,7 @@ public final class XMatchStep<S> extends ComputerAwareStep<S, S> implements Trav
traverser.setStepId(conjunctionTraversal.getStartStep().getId()); // go down the traversal match sub-pattern
return IteratorUtils.of(traverser);
} else {
- final List<Traverser<S>> traversers = new ArrayList<>();
+ final List<Traverser<Map<String, E>>> traversers = new ArrayList<>();
this.conjunctionTraversals.forEach(conjunctionTraversal -> {
final Traverser.Admin split = traverser.split();
split.path().addLabel(conjunctionTraversal.getStartStep().getId());
@@ -299,7 +357,7 @@ public final class XMatchStep<S> extends ComputerAwareStep<S, S> implements Trav
return this.traversals.get(i);
}
}
- throw new IllegalStateException("The provided match pattern is unsolvable: " + this.traversals);
+ throw new IllegalArgumentException("The provided match pattern is unsolvable: " + this.traversals);
}
}
}
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/538af16b/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraphTest.java
----------------------------------------------------------------------
diff --git a/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraphTest.java b/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraphTest.java
index de6d55e..12995fe 100644
--- a/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraphTest.java
+++ b/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraphTest.java
@@ -158,7 +158,7 @@ public class TinkerGraphTest {
@Ignore
public void testPlay5() throws Exception {
GraphTraversalSource g = TinkerFactory.createModern().traversal(GraphTraversalSource.standard());
- final Supplier<Traversal<?, ?>> traversal = () -> g.V().as("a").xmatch(
+ final Supplier<Traversal<?, ?>> traversal = () -> g.V().xmatch("a",
as("a").out("created").as("b"),
or(
as("a").out("knows").as("c"),
@@ -166,8 +166,7 @@ public class TinkerGraphTest {
as("a").out("created").has("name", "ripple"),
as("a").out().out()
)
- ))
- .select(Pop.head);
+ ));
/*
g.V().as("a").xmatch(
as("a").out("knows").as("b"),