Repository: tinkerpop Updated Branches: refs/heads/TINKERPOP-1625 a2fccf11e -> 6515a6f3a (forced update)
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/9265ddf6/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/FromToModulating.java ---------------------------------------------------------------------- diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/FromToModulating.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/FromToModulating.java new file mode 100644 index 0000000..59a51bd --- /dev/null +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/FromToModulating.java @@ -0,0 +1,49 @@ +/* + * 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; + +import org.apache.tinkerpop.gremlin.process.traversal.Path; +import org.apache.tinkerpop.gremlin.process.traversal.Traversal; +import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__; +import org.apache.tinkerpop.gremlin.process.traversal.step.util.MutablePath; + +import java.util.Set; + +/** + * @author Marko A. Rodriguez (http://markorodriguez.com) + */ +public interface FromToModulating { + + public default void addFrom(final Traversal.Admin<?, ?> fromTraversal) { + throw new UnsupportedOperationException("The from()-modulating step does not support traversal-based modulation: " + this); + } + + public default void addTo(final Traversal.Admin<?, ?> toTraversal) { + throw new UnsupportedOperationException("The to()-modulating step does not support traversal-based modulation: " + this); + } + + public default void addFrom(final String fromLabel) { + addFrom(__.select(fromLabel).asAdmin()); + } + + public default void addTo(final String toLabel) { + addTo(__.select(toLabel).asAdmin()); + } +} http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/9265ddf6/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AddEdgeStep.java ---------------------------------------------------------------------- diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AddEdgeStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AddEdgeStep.java index 3f6086a..4308291 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AddEdgeStep.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AddEdgeStep.java @@ -21,6 +21,7 @@ package org.apache.tinkerpop.gremlin.process.traversal.step.map; import org.apache.tinkerpop.gremlin.process.traversal.Parameterizing; import org.apache.tinkerpop.gremlin.process.traversal.Traversal; import org.apache.tinkerpop.gremlin.process.traversal.Traverser; +import org.apache.tinkerpop.gremlin.process.traversal.step.FromToModulating; import org.apache.tinkerpop.gremlin.process.traversal.step.Mutating; import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent; import org.apache.tinkerpop.gremlin.process.traversal.step.util.Parameters; @@ -34,9 +35,7 @@ import org.apache.tinkerpop.gremlin.structure.T; import org.apache.tinkerpop.gremlin.structure.Vertex; import org.apache.tinkerpop.gremlin.structure.util.StringFactory; import org.apache.tinkerpop.gremlin.structure.util.detached.DetachedFactory; -import org.apache.tinkerpop.gremlin.util.iterator.IteratorUtils; -import java.util.Iterator; import java.util.List; import java.util.Set; @@ -44,7 +43,7 @@ import java.util.Set; * @author Marko A. Rodriguez (http://markorodriguez.com) * @author Stephen Mallette (http://stephen.genoprime.com) */ -public final class AddEdgeStep<S> extends MapStep<S, Edge> implements Mutating<Event.EdgeAddedEvent>, TraversalParent, Parameterizing { +public final class AddEdgeStep<S> extends MapStep<S, Edge> implements Mutating<Event.EdgeAddedEvent>, TraversalParent, Parameterizing, FromToModulating { private static final String FROM = Graph.Hidden.hide("from"); private static final String TO = Graph.Hidden.hide("to"); @@ -73,12 +72,14 @@ public final class AddEdgeStep<S> extends MapStep<S, Edge> implements Mutating<E this.parameters.integrateTraversals(this); } - public void addTo(final Object toObject) { + @Override + public void addTo(final Traversal.Admin<?,?> toObject) { this.parameters.set(TO, toObject); this.parameters.integrateTraversals(this); } - public void addFrom(final Object fromObject) { + @Override + public void addFrom(final Traversal.Admin<?,?> fromObject) { this.parameters.set(FROM, fromObject); this.parameters.integrateTraversals(this); } @@ -90,10 +91,10 @@ public final class AddEdgeStep<S> extends MapStep<S, Edge> implements Mutating<E final String edgeLabel = this.parameters.get(traverser, T.label, () -> Edge.DEFAULT_LABEL).get(0); final Edge edge = fromVertex.addEdge(edgeLabel, toVertex, this.parameters.getKeyValues(traverser, TO, FROM, T.label)); - if (callbackRegistry != null) { - final Event.EdgeAddedEvent vae = new Event.EdgeAddedEvent(DetachedFactory.detach(edge, true)); - callbackRegistry.getCallbacks().forEach(c -> c.accept(vae)); - } + if (callbackRegistry != null) { + final Event.EdgeAddedEvent vae = new Event.EdgeAddedEvent(DetachedFactory.detach(edge, true)); + callbackRegistry.getCallbacks().forEach(c -> c.accept(vae)); + } return edge; } http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/9265ddf6/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/PathStep.java ---------------------------------------------------------------------- diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/PathStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/PathStep.java index 705cf0c..06ff947 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/PathStep.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/PathStep.java @@ -22,6 +22,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.Path; import org.apache.tinkerpop.gremlin.process.traversal.Traversal; import org.apache.tinkerpop.gremlin.process.traversal.Traverser; import org.apache.tinkerpop.gremlin.process.traversal.step.ByModulating; +import org.apache.tinkerpop.gremlin.process.traversal.step.FromToModulating; import org.apache.tinkerpop.gremlin.process.traversal.step.PathProcessor; import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent; import org.apache.tinkerpop.gremlin.process.traversal.step.util.MutablePath; @@ -36,10 +37,12 @@ import java.util.Set; /** * @author Marko A. Rodriguez (http://markorodriguez.com) */ -public final class PathStep<S> extends MapStep<S, Path> implements TraversalParent, PathProcessor, ByModulating { +public final class PathStep<S> extends MapStep<S, Path> implements TraversalParent, PathProcessor, ByModulating, FromToModulating { private TraversalRing<Object, Object> traversalRing; private Set<String> keepLabels; + private String fromLabel; + private String toLabel; public PathStep(final Traversal.Admin traversal) { super(traversal); @@ -48,17 +51,18 @@ public final class PathStep<S> extends MapStep<S, Path> implements TraversalPare @Override protected Path map(final Traverser.Admin<S> traverser) { - final Path path; + final Path path = traverser.path().getSubPath(this.fromLabel, this.toLabel); + this.traversalRing.reset(); if (this.traversalRing.isEmpty()) - path = traverser.path(); + return path; else { - path = MutablePath.make(); - traverser.path().forEach((object, labels) -> path.extend(TraversalUtil.applyNullable(object, this.traversalRing.next()), labels)); + final Path byPath = MutablePath.make(); + path.forEach((object, labels) -> byPath.extend(TraversalUtil.applyNullable(object, this.traversalRing.next()), labels)); + return byPath; } - this.traversalRing.reset(); - return path; } + @Override public PathStep<S> clone() { final PathStep<S> clone = (PathStep<S>) super.clone(); @@ -117,4 +121,15 @@ public final class PathStep<S> extends MapStep<S, Path> implements TraversalPare public Set<String> getKeepLabels() { return this.keepLabels; } + + + @Override + public void addFrom(final String fromLabel) { + this.fromLabel = fromLabel; + } + + @Override + public void addTo(final String toLabel) { + this.toLabel = toLabel; + } } http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/9265ddf6/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/PathTest.java ---------------------------------------------------------------------- diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/PathTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/PathTest.java index 5087667..1d21074 100644 --- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/PathTest.java +++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/PathTest.java @@ -33,7 +33,11 @@ import java.util.List; import java.util.function.Supplier; import java.util.stream.Collectors; -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; /** * @author Marko A. Rodriguez (http://markorodriguez.com) @@ -375,4 +379,63 @@ public class PathTest { } } } + + @Test + public void shouldHaveSubPathSupport() { + PATH_SUPPLIERS.forEach(supplier -> { + Path path = supplier.get(); + path = path.extend("marko", Collections.singleton("a")); + path = path.extend("stephen", Collections.singleton("b")); + path = path.extend("matthias", new HashSet<>(Arrays.asList("c", "x"))); + path = path.extend("bob", Collections.singleton("d")); + assertEquals(4, path.size()); + assertEquals(4, path.objects().size()); + assertEquals(4, path.labels().size()); + /// + Path subPath = path.getSubPath("b", "c"); + assertEquals(2, subPath.size()); + assertEquals(2, subPath.objects().size()); + assertEquals(2, subPath.labels().size()); + assertEquals("stephen", subPath.objects().get(0)); + assertEquals("matthias", subPath.objects().get(1)); + assertTrue(subPath.labels().get(0).contains("b")); + assertEquals(1, subPath.labels().get(0).size()); + assertTrue(subPath.labels().get(1).contains("c")); + assertTrue(subPath.labels().get(1).contains("x")); + assertEquals(2, subPath.labels().get(1).size()); + /// + subPath = path.getSubPath("b", "b"); + assertEquals(1, subPath.size()); + assertEquals(1, subPath.objects().size()); + assertEquals(1, subPath.labels().size()); + assertEquals("stephen", subPath.objects().get(0)); + /// + subPath = path.getSubPath("b", "b"); + assertEquals(1, subPath.size()); + assertEquals(1, subPath.objects().size()); + assertEquals(1, subPath.labels().size()); + assertEquals("stephen", subPath.objects().get(0)); + /// + try { + subPath = path.getSubPath("d", "a"); + fail("Path labels must be ordered along path"); + } catch (final IllegalArgumentException e) { + assertTrue(true); + } + /// + try { + subPath = path.getSubPath("a", "e"); + fail("End path label was not found"); + } catch (final IllegalArgumentException e) { + assertEquals(Path.Exceptions.couldNotLocalPathToLabel("e").getMessage(), e.getMessage()); + } + /// + try { + subPath = path.getSubPath("e", "b"); + fail("Start path label was not found"); + } catch (final IllegalArgumentException e) { + assertEquals(Path.Exceptions.couldNotLocalPathFromLabel("e").getMessage(), e.getMessage()); + } + }); + } } http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/9265ddf6/gremlin-groovy-test/src/main/groovy/org/apache/tinkerpop/gremlin/process/traversal/step/map/GroovyPathTest.groovy ---------------------------------------------------------------------- diff --git a/gremlin-groovy-test/src/main/groovy/org/apache/tinkerpop/gremlin/process/traversal/step/map/GroovyPathTest.groovy b/gremlin-groovy-test/src/main/groovy/org/apache/tinkerpop/gremlin/process/traversal/step/map/GroovyPathTest.groovy index 15c499a..c3abf60 100644 --- a/gremlin-groovy-test/src/main/groovy/org/apache/tinkerpop/gremlin/process/traversal/step/map/GroovyPathTest.groovy +++ b/gremlin-groovy-test/src/main/groovy/org/apache/tinkerpop/gremlin/process/traversal/step/map/GroovyPathTest.groovy @@ -59,5 +59,10 @@ public abstract class GroovyPathTest { public Traversal<Vertex, Path> get_g_VX1X_outEXcreatedX_inV_inE_outV_path(final Object v1Id) { new ScriptTraversal<>(g, "gremlin-groovy", "g.V(v1Id).outE('created').inV.inE.outV.path()", "v1Id", v1Id) } + + @Override + public Traversal<Vertex, Path> get_g_V_asXaX_out_asXbX_out_asXcX_path_fromXbX_toXcX_byXnameX() { + new ScriptTraversal<>(g, "gremlin-groovy", "g.V.as('a').out().as('b').out.as('c').path.from('b').to('c').by('name')") + } } } http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/9265ddf6/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/PathTest.java ---------------------------------------------------------------------- diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/PathTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/PathTest.java index 9e18894..3014998 100644 --- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/PathTest.java +++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/PathTest.java @@ -23,11 +23,14 @@ import org.apache.tinkerpop.gremlin.process.AbstractGremlinProcessTest; import org.apache.tinkerpop.gremlin.process.GremlinProcessRunner; import org.apache.tinkerpop.gremlin.process.traversal.Path; import org.apache.tinkerpop.gremlin.process.traversal.Traversal; +import org.apache.tinkerpop.gremlin.process.traversal.step.util.MutablePath; import org.apache.tinkerpop.gremlin.structure.Edge; import org.apache.tinkerpop.gremlin.structure.Vertex; import org.junit.Test; import org.junit.runner.RunWith; +import java.util.Arrays; +import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; @@ -57,6 +60,8 @@ public abstract class PathTest extends AbstractGremlinProcessTest { public abstract Traversal<Vertex, Path> get_g_VX1X_outEXcreatedX_inV_inE_outV_path(final Object v1Id); + public abstract Traversal<Vertex, Path> get_g_V_asXaX_out_asXbX_out_asXcX_path_fromXbX_toXcX_byXnameX(); + @Test @LoadGraphWith(MODERN) public void g_VX1X_name_path() { @@ -157,6 +162,16 @@ public abstract class PathTest extends AbstractGremlinProcessTest { assertFalse(traversal.hasNext()); } + @Test + @LoadGraphWith(MODERN) + public void g_V_asXaX_out_asXbX_out_asXcX_path_fromXbX_toXcX_byXnameX() { + final Traversal<Vertex, Path> traveral = get_g_V_asXaX_out_asXbX_out_asXcX_path_fromXbX_toXcX_byXnameX(); + printTraversalForm(traveral); + checkResults(Arrays.asList( + MutablePath.make().extend("josh", Collections.singleton("b")).extend("lop", Collections.singleton("c")), + MutablePath.make().extend("josh", Collections.singleton("b")).extend("ripple", Collections.singleton("c"))), traveral); + } + public static class Traversals extends PathTest { @Override public Traversal<Vertex, Path> get_g_VX1X_name_path(final Object v1Id) { @@ -187,5 +202,10 @@ public abstract class PathTest extends AbstractGremlinProcessTest { public Traversal<Vertex, Path> get_g_VX1X_outEXcreatedX_inV_inE_outV_path(final Object v1Id) { return g.V(v1Id).outE("created").inV().inE().outV().path(); } + + @Override + public Traversal<Vertex, Path> get_g_V_asXaX_out_asXbX_out_asXcX_path_fromXbX_toXcX_byXnameX() { + return g.V().as("a").out().as("b").out().as("c").path().from("b").to("c").by("name"); + } } } \ No newline at end of file