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/05/16 01:14:12 UTC
[05/10] incubator-tinkerpop git commit: TINKERPOP3-670: Add 'tail'
step
TINKERPOP3-670: Add 'tail' step
Project: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/commit/45c8c76d
Tree: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/tree/45c8c76d
Diff: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/diff/45c8c76d
Branch: refs/heads/master
Commit: 45c8c76dd33f0b28f01da7d96facd46de6b51a5b
Parents: 8963c3a
Author: mhfrantz <mf...@redsealnetworks.com>
Authored: Thu May 7 18:29:22 2015 -0700
Committer: mhfrantz <mf...@redsealnetworks.com>
Committed: Fri May 15 14:14:45 2015 -0700
----------------------------------------------------------------------
.../traversal/dsl/graph/GraphTraversal.java | 12 ++
.../traversal/step/filter/TailGlobalStep.java | 82 ++++++++
.../traversal/step/map/RangeLocalStep.java | 29 ++-
.../traversal/step/map/TailLocalStep.java | 81 ++++++++
.../traversal/step/filter/GroovyTailTest.groovy | 80 ++++++++
.../process/GroovyProcessComputerSuite.java | 1 +
.../process/GroovyProcessStandardSuite.java | 2 +
.../gremlin/process/ProcessComputerSuite.java | 2 +
.../gremlin/process/ProcessStandardSuite.java | 3 +
.../process/traversal/step/filter/TailTest.java | 198 +++++++++++++++++++
10 files changed, 485 insertions(+), 5 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/45c8c76d/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 9139263..fa1e092 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
@@ -53,6 +53,7 @@ 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.WhereStep;
import org.apache.tinkerpop.gremlin.process.traversal.step.map.AddEdgeByPathStep;
@@ -91,6 +92,7 @@ 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.TreeStep;
import org.apache.tinkerpop.gremlin.process.traversal.step.map.UnfoldStep;
import org.apache.tinkerpop.gremlin.process.traversal.step.map.VertexStep;
@@ -548,6 +550,16 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
return this.range(scope, 0, limit);
}
+ public default GraphTraversal<S, E> tail(final long limit) {
+ return this.tail(Scope.global, limit);
+ }
+
+ public default GraphTraversal<S, E> tail(final Scope scope, final long limit) {
+ return this.asAdmin().addStep(scope.equals(Scope.global)
+ ? new TailGlobalStep<>(this.asAdmin(), limit)
+ : new TailLocalStep<>(this.asAdmin(), limit));
+ }
+
public default GraphTraversal<S, E> simplePath() {
return this.asAdmin().addStep(new SimplePathStep<>(this.asAdmin()));
}
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/45c8c76d/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/TailGlobalStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/TailGlobalStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/TailGlobalStep.java
new file mode 100644
index 0000000..e4db2a1
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/TailGlobalStep.java
@@ -0,0 +1,82 @@
+/*
+ * 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.filter;
+
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.AbstractStep;
+import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
+import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
+import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper;
+import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
+
+import java.util.ArrayDeque;
+import java.util.Collections;
+import java.util.Deque;
+import java.util.Set;
+
+/**
+ * @author Matt Frantz (http://github.com/mhfrantz)
+ */
+public final class TailGlobalStep<S> extends AbstractStep<S, S> {
+
+ private final long limit;
+ private Deque<Traverser.Admin<S>> tail;
+
+ public TailGlobalStep(final Traversal.Admin traversal, final long limit) {
+ super(traversal);
+ this.limit = limit;
+ this.tail = new ArrayDeque<Traverser.Admin<S>>((int)limit);
+ }
+
+ @Override
+ public Traverser<S> processNextStart() {
+ if (this.starts.hasNext()) {
+ this.starts.forEachRemaining(this::addTail);
+ }
+ return this.tail.pop();
+ }
+
+ @Override
+ public void reset() {
+ super.reset();
+ this.tail.clear();
+ }
+
+ @Override
+ public String toString() {
+ return TraversalHelper.makeStepString(this, this.limit);
+ }
+
+ @Override
+ public TailGlobalStep<S> clone() {
+ final TailGlobalStep<S> clone = (TailGlobalStep<S>) super.clone();
+ clone.tail = new ArrayDeque<Traverser.Admin<S>>(this.tail);
+ return clone;
+ }
+
+ @Override
+ public Set<TraverserRequirement> getRequirements() {
+ return Collections.singleton(TraverserRequirement.BULK);
+ }
+
+ private void addTail(Traverser.Admin<S> start) {
+ if (this.tail.size() >= this.limit)
+ this.tail.pop();
+ this.tail.add(start);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/45c8c76d/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/RangeLocalStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/RangeLocalStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/RangeLocalStep.java
index b3dad36..d0a93a8 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/RangeLocalStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/RangeLocalStep.java
@@ -46,15 +46,34 @@ public final class RangeLocalStep<S> extends MapStep<S, S> {
@Override
protected S map(final Traverser.Admin<S> traverser) {
final S start = traverser.get();
+ return applyRange(start, this.low, this.high);
+ }
+
+ /**
+ * Extracts the specified range of elements from a collection.
+ * Return type depends on dynamic type of start.
+ * <ul>
+ * <li>
+ * Map becomes Map (order-preserving)
+ * </li>
+ * <li>
+ * Set becomes Set (order-preserving)
+ * </li>
+ * <li>
+ * Other Collection types become List
+ * </li>
+ * </ul>
+ */
+ static <S> S applyRange(S start, long low, long high) {
if (start instanceof Map) {
final Map map = (Map) start;
- final long capacity = (this.high != -1 ? this.high : map.size()) - this.low;
+ final long capacity = (high != -1 ? high : map.size()) - low;
final Map result = new LinkedHashMap((int) Math.min(capacity, map.size()));
long c = 0L;
for (final Object obj : map.entrySet()) {
final Map.Entry entry = (Map.Entry) obj;
- if (c >= this.low) {
- if (c < this.high || this.high == -1) {
+ if (c >= low) {
+ if (c < high || high == -1) {
result.put(entry.getKey(), entry.getValue());
} else break;
}
@@ -66,8 +85,8 @@ public final class RangeLocalStep<S> extends MapStep<S, S> {
final Collection result = (collection instanceof Set) ? new LinkedHashSet() : new LinkedList();
long c = 0L;
for (final Object item : collection) {
- if (c >= this.low) {
- if (c < this.high || this.high == -1) {
+ if (c >= low) {
+ if (c < high || high == -1) {
result.add(item);
} else break;
}
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/45c8c76d/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/TailLocalStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/TailLocalStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/TailLocalStep.java
new file mode 100644
index 0000000..e2d76c9
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/TailLocalStep.java
@@ -0,0 +1,81 @@
+/*
+ * 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;
+import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
+import org.apache.tinkerpop.gremlin.process.traversal.util.FastNoSuchElementException;
+import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @author Matt Frantz (http://github.com/mhfrantz)
+ */
+public final class TailLocalStep<S> extends MapStep<S, S> {
+
+ private final long limit;
+
+ public TailLocalStep(final Traversal.Admin traversal, final long limit) {
+ super(traversal);
+ this.limit = limit;
+ }
+
+ @Override
+ protected S map(final Traverser.Admin<S> traverser) {
+ // We may consider optimizing the iteration of these containers using subtype-specific interfaces. For
+ // example, we could use descendingIterator if we have a Deque. But in general, we cannot reliably iterate a
+ // collection in reverse, so we use the range algorithm with dynamically computed boundaries.
+ final S start = traverser.get();
+ final long high =
+ start instanceof Map ? ((Map)start).size() :
+ start instanceof Collection ? ((Collection)start).size() :
+ this.limit;
+ final long low = high - this.limit;
+ final S result = RangeLocalStep.applyRange(start, low, high);
+
+ // If we are limiting a collection to a single item, then emit only that item.
+ if (1 == this.limit && result instanceof Collection) {
+ final Collection c = (Collection) result;
+ if (c.isEmpty()) {
+ // We have nothing to emit, so stop traversal.
+ throw FastNoSuchElementException.instance();
+ } else {
+ return (S) c.iterator().next();
+ }
+ } else {
+ return result;
+ }
+ }
+
+ @Override
+ public String toString() {
+ return TraversalHelper.makeStepString(this, this.limit);
+ }
+
+ @Override
+ public Set<TraverserRequirement> getRequirements() {
+ return Collections.singleton(TraverserRequirement.OBJECT);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/45c8c76d/gremlin-groovy-test/src/main/groovy/org/apache/tinkerpop/gremlin/process/traversal/step/filter/GroovyTailTest.groovy
----------------------------------------------------------------------
diff --git a/gremlin-groovy-test/src/main/groovy/org/apache/tinkerpop/gremlin/process/traversal/step/filter/GroovyTailTest.groovy b/gremlin-groovy-test/src/main/groovy/org/apache/tinkerpop/gremlin/process/traversal/step/filter/GroovyTailTest.groovy
new file mode 100644
index 0000000..a9fde91
--- /dev/null
+++ b/gremlin-groovy-test/src/main/groovy/org/apache/tinkerpop/gremlin/process/traversal/step/filter/GroovyTailTest.groovy
@@ -0,0 +1,80 @@
+/*
+ * 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.filter
+
+import org.apache.tinkerpop.gremlin.process.traversal.Traversal
+import org.apache.tinkerpop.gremlin.structure.T
+import org.apache.tinkerpop.gremlin.structure.Vertex
+
+import java.util.List
+import java.util.Map
+
+import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.limit
+import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.unfold
+import static org.apache.tinkerpop.gremlin.process.traversal.Scope.global
+import static org.apache.tinkerpop.gremlin.process.traversal.Scope.local
+
+/**
+ * @author Matt Frantz (http://github.com/mhfrantz)
+ */
+public abstract class GroovyTailTest {
+
+ public static class Traversals extends TailTest {
+
+ @Override
+ public Traversal<Vertex, Object> get_g_V_id_order_tailXglobal_2X() {
+ g.V.id.order.tail(global, 2)
+ }
+
+ @Override
+ public Traversal<Vertex, Object> get_g_V_id_order_tailX2X() {
+ g.V.id.order.tail(2)
+ }
+
+ @Override
+ public Traversal<Vertex, Object> get_g_V_id_order_tailX7X() {
+ g.V.id.order.tail(7)
+ }
+
+ @Override
+ public Traversal<Vertex, List<Object>> get_g_V_asXaX_out_asXaX_out_asXaX_selectXaX_byXunfold_id_foldX_tailXlocal_2X() {
+ g.V.as('a').out.as('a').out.as('a').select('a').by(unfold().id.fold).tail(local, 2)
+ }
+
+ @Override
+ public Traversal<Vertex, Object> get_g_V_asXaX_out_asXaX_out_asXaX_selectXaX_byXunfold_id_foldX_tailXlocal_1X() {
+ g.V.as('a').out.as('a').out.as('a').select('a').by(unfold().id.fold).tail(local, 1)
+ }
+
+ @Override
+ public Traversal<Vertex, Object> get_g_V_asXaX_out_asXaX_out_asXaX_selectXaX_byXlimitXlocal_0XX_tailXlocal_1X() {
+ g.V.as('a').out.as('a').out.as('a').select('a').by(limit(local, 0)).tail(local, 1)
+ }
+
+ @Override
+ public Traversal<Vertex, Map<String, Object>> get_g_V_asXaX_out_asXbX_out_asXcX_select_byXT_idX_tailXlocal_2X() {
+ g.V.as('a').out.as('b').out.as('c').select.by(T.id).tail(local, 2)
+ }
+
+ @Override
+ public Traversal<Vertex, Map<String, Object>> get_g_V_asXaX_out_asXbX_out_asXcX_select_byXT_idX_tailXlocal_1X() {
+ g.V.as('a').out.as('b').out.as('c').select.by(T.id).tail(local, 1)
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/45c8c76d/gremlin-groovy-test/src/main/java/org/apache/tinkerpop/gremlin/process/GroovyProcessComputerSuite.java
----------------------------------------------------------------------
diff --git a/gremlin-groovy-test/src/main/java/org/apache/tinkerpop/gremlin/process/GroovyProcessComputerSuite.java b/gremlin-groovy-test/src/main/java/org/apache/tinkerpop/gremlin/process/GroovyProcessComputerSuite.java
index a4ee9e7..ba6a419 100644
--- a/gremlin-groovy-test/src/main/java/org/apache/tinkerpop/gremlin/process/GroovyProcessComputerSuite.java
+++ b/gremlin-groovy-test/src/main/java/org/apache/tinkerpop/gremlin/process/GroovyProcessComputerSuite.java
@@ -112,6 +112,7 @@ public class GroovyProcessComputerSuite extends ProcessComputerSuite {
GroovyRangeTest.Traversals.class,
GroovySampleTest.Traversals.class,
GroovySimplePathTest.Traversals.class,
+ GroovyTailTest.Traversals.class,
GroovyWhereTest.Traversals.class,
// map
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/45c8c76d/gremlin-groovy-test/src/main/java/org/apache/tinkerpop/gremlin/process/GroovyProcessStandardSuite.java
----------------------------------------------------------------------
diff --git a/gremlin-groovy-test/src/main/java/org/apache/tinkerpop/gremlin/process/GroovyProcessStandardSuite.java b/gremlin-groovy-test/src/main/java/org/apache/tinkerpop/gremlin/process/GroovyProcessStandardSuite.java
index a12ee68..2d84dd4 100644
--- a/gremlin-groovy-test/src/main/java/org/apache/tinkerpop/gremlin/process/GroovyProcessStandardSuite.java
+++ b/gremlin-groovy-test/src/main/java/org/apache/tinkerpop/gremlin/process/GroovyProcessStandardSuite.java
@@ -41,6 +41,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.step.filter.GroovyOrTest;
import org.apache.tinkerpop.gremlin.process.traversal.step.filter.GroovyRangeTest;
import org.apache.tinkerpop.gremlin.process.traversal.step.filter.GroovySampleTest;
import org.apache.tinkerpop.gremlin.process.traversal.step.filter.GroovySimplePathTest;
+import org.apache.tinkerpop.gremlin.process.traversal.step.filter.GroovyTailTest;
import org.apache.tinkerpop.gremlin.process.traversal.step.filter.GroovyWhereTest;
import org.apache.tinkerpop.gremlin.process.traversal.step.map.GroovyAddEdgeTest;
import org.apache.tinkerpop.gremlin.process.traversal.step.map.GroovyAddVertexTest;
@@ -111,6 +112,7 @@ public class GroovyProcessStandardSuite extends ProcessStandardSuite {
GroovyRangeTest.Traversals.class,
GroovySampleTest.Traversals.class,
GroovySimplePathTest.Traversals.class,
+ GroovyTailTest.Traversals.class,
GroovyWhereTest.Traversals.class,
// map
GroovyAddEdgeTest.Traversals.class,
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/45c8c76d/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/ProcessComputerSuite.java
----------------------------------------------------------------------
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/ProcessComputerSuite.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/ProcessComputerSuite.java
index 85a92d4..b46cc84 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/ProcessComputerSuite.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/ProcessComputerSuite.java
@@ -116,6 +116,7 @@ public class ProcessComputerSuite extends AbstractGremlinSuite {
RangeTest.Traversals.class,
SampleTest.Traversals.class,
SimplePathTest.Traversals.class,
+ TailTest.Traversals.class,
WhereTest.Traversals.class,
// map
@@ -184,6 +185,7 @@ public class ProcessComputerSuite extends AbstractGremlinSuite {
RangeTest.class,
SampleTest.class,
SimplePathTest.class,
+ TailTest.class,
WhereTest.class,
// map
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/45c8c76d/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/ProcessStandardSuite.java
----------------------------------------------------------------------
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/ProcessStandardSuite.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/ProcessStandardSuite.java
index 4fa12c1..1888761 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/ProcessStandardSuite.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/ProcessStandardSuite.java
@@ -39,6 +39,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.step.filter.OrTest;
import org.apache.tinkerpop.gremlin.process.traversal.step.filter.RangeTest;
import org.apache.tinkerpop.gremlin.process.traversal.step.filter.SampleTest;
import org.apache.tinkerpop.gremlin.process.traversal.step.filter.SimplePathTest;
+import org.apache.tinkerpop.gremlin.process.traversal.step.filter.TailTest;
import org.apache.tinkerpop.gremlin.process.traversal.step.filter.WhereTest;
import org.apache.tinkerpop.gremlin.process.traversal.step.map.AddEdgeTest;
import org.apache.tinkerpop.gremlin.process.traversal.step.map.AddVertexTest;
@@ -114,6 +115,7 @@ public class ProcessStandardSuite extends AbstractGremlinSuite {
RangeTest.Traversals.class,
SampleTest.Traversals.class,
SimplePathTest.Traversals.class,
+ TailTest.Traversals.class,
WhereTest.Traversals.class,
// map
@@ -194,6 +196,7 @@ public class ProcessStandardSuite extends AbstractGremlinSuite {
RangeTest.class,
SampleTest.class,
SimplePathTest.class,
+ TailTest.class,
WhereTest.class,
// map
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/45c8c76d/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/TailTest.java
----------------------------------------------------------------------
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/TailTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/TailTest.java
new file mode 100644
index 0000000..26ed69d
--- /dev/null
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/TailTest.java
@@ -0,0 +1,198 @@
+/*
+ * 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.filter;
+
+import org.apache.tinkerpop.gremlin.LoadGraphWith;
+import org.apache.tinkerpop.gremlin.process.AbstractGremlinProcessTest;
+import org.apache.tinkerpop.gremlin.process.GremlinProcessRunner;
+import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
+import org.apache.tinkerpop.gremlin.structure.T;
+import org.apache.tinkerpop.gremlin.structure.Vertex;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.apache.tinkerpop.gremlin.LoadGraphWith.GraphData.MODERN;
+import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.limit;
+import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.unfold;
+import static org.apache.tinkerpop.gremlin.process.traversal.Scope.global;
+import static org.apache.tinkerpop.gremlin.process.traversal.Scope.local;
+import static org.junit.Assert.assertEquals;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Original spec: https://issues.apache.org/jira/browse/TINKERPOP3-670
+ *
+ * @author Matt Frantz (http://github.com/mhfrantz)
+ */
+@RunWith(GremlinProcessRunner.class)
+public abstract class TailTest extends AbstractGremlinProcessTest {
+
+ public abstract Traversal<Vertex, Object> get_g_V_id_order_tailXglobal_2X();
+
+ public abstract Traversal<Vertex, Object> get_g_V_id_order_tailX2X();
+
+ public abstract Traversal<Vertex, Object> get_g_V_id_order_tailX7X();
+
+ public abstract Traversal<Vertex, List<Object>> get_g_V_asXaX_out_asXaX_out_asXaX_selectXaX_byXunfold_id_foldX_tailXlocal_2X();
+
+ public abstract Traversal<Vertex, Object> get_g_V_asXaX_out_asXaX_out_asXaX_selectXaX_byXunfold_id_foldX_tailXlocal_1X();
+
+ public abstract Traversal<Vertex, Object> get_g_V_asXaX_out_asXaX_out_asXaX_selectXaX_byXlimitXlocal_0XX_tailXlocal_1X();
+
+ public abstract Traversal<Vertex, Map<String, Object>> get_g_V_asXaX_out_asXbX_out_asXcX_select_byXT_idX_tailXlocal_2X();
+
+ public abstract Traversal<Vertex, Map<String, Object>> get_g_V_asXaX_out_asXbX_out_asXcX_select_byXT_idX_tailXlocal_1X();
+
+ /** Scenario: Global scope */
+ @Test
+ @LoadGraphWith(MODERN)
+ public void g_V_id_order_tailXglobal_2X() {
+ final Traversal<Vertex, Object> traversal = get_g_V_id_order_tailXglobal_2X();
+ printTraversalForm(traversal);
+ assertEquals(Arrays.asList(5, 6), traversal.toList());
+ }
+
+ /** Scenario: Default scope is global */
+ @Test
+ @LoadGraphWith(MODERN)
+ public void g_V_id_order_tailX2X() {
+ final Traversal<Vertex, Object> traversal = get_g_V_id_order_tailX2X();
+ printTraversalForm(traversal);
+ assertEquals(Arrays.asList(5, 6), traversal.toList());
+ }
+
+ /** Scenario: Global scope, not enough elements */
+ @Test
+ @LoadGraphWith(MODERN)
+ public void g_V_id_order_tailX7X() {
+ final Traversal<Vertex, Object> traversal = get_g_V_id_order_tailX7X();
+ printTraversalForm(traversal);
+ assertEquals(Arrays.asList(1, 2, 3, 4, 5, 6), traversal.toList());
+ }
+
+ /** Scenario: Local scope, List input, N>1 */
+ @Test
+ @LoadGraphWith(MODERN)
+ public void g_V_asXaX_out_asXaX_out_asXaX_selectXaX_byXunfold_id_foldX_tailXlocal_2X() {
+ final Traversal<Vertex, List<Object>> traversal = get_g_V_asXaX_out_asXaX_out_asXaX_selectXaX_byXunfold_id_foldX_tailXlocal_2X();
+ printTraversalForm(traversal);
+ final Set<List<Object>> expected =
+ new HashSet(Arrays.asList(
+ Arrays.asList(4, 5),
+ Arrays.asList(4, 3)));
+ final Set<List<Object>> actual = new HashSet(traversal.toList());
+ assertEquals(expected, actual);
+ }
+
+ /** Scenario: Local scope, List input, N=1 */
+ @Test
+ @LoadGraphWith(MODERN)
+ public void g_V_asXaX_out_asXaX_out_asXaX_selectXaX_byXunfold_id_foldX_tailXlocal_1X() {
+ final Traversal<Vertex, Object> traversal = get_g_V_asXaX_out_asXaX_out_asXaX_selectXaX_byXunfold_id_foldX_tailXlocal_1X();
+ printTraversalForm(traversal);
+ final Set<Object> expected = new HashSet(Arrays.asList(5, 3));
+ final Set<Object> actual = new HashSet(traversal.toList());
+ assertEquals(expected, actual);
+ }
+
+ /** Scenario: Local scope, List input, N=1, empty input */
+ @Test
+ @LoadGraphWith(MODERN)
+ public void g_V_asXaX_out_asXaX_out_asXaX_selectXaX_byXlimitXlocal_0XX_tailXlocal_1X() {
+ final Traversal<Vertex, Object> traversal = get_g_V_asXaX_out_asXaX_out_asXaX_selectXaX_byXlimitXlocal_0XX_tailXlocal_1X();
+ printTraversalForm(traversal);
+ final Set<Object> expected = new HashSet();
+ final Set<Object> actual = new HashSet(traversal.toList());
+ assertEquals(expected, actual);
+ }
+
+ /** Scenario: Local scope, Map input, N>1 */
+ @Test
+ @LoadGraphWith(MODERN)
+ public void g_V_asXaX_out_asXbX_out_asXcX_select_byXT_idX_tailXlocal_2X() {
+ final Traversal<Vertex, Map<String, Object>> traversal = get_g_V_asXaX_out_asXbX_out_asXcX_select_byXT_idX_tailXlocal_2X();
+ printTraversalForm(traversal);
+ final Set<Map<String, Object>> expected = new HashSet(makeMapList(2,
+ "b", 4, "c", 5,
+ "b", 4, "c", 3));
+ final Set<Map<String, Object>> actual = new HashSet(traversal.toList());
+ assertEquals(expected, actual);
+ }
+
+ /** Scenario: Local scope, Map input, N=1 */
+ @Test
+ @LoadGraphWith(MODERN)
+ public void g_V_asXaX_out_asXbX_out_asXcX_select_byXT_idX_tailXlocal_1X() {
+ final Traversal<Vertex, Map<String, Object>> traversal = get_g_V_asXaX_out_asXbX_out_asXcX_select_byXT_idX_tailXlocal_1X();
+ printTraversalForm(traversal);
+ final Set<Map<String, Object>> expected = new HashSet(makeMapList(1,
+ "c", 5,
+ "c", 3));
+ final Set<Map<String, Object>> actual = new HashSet(traversal.toList());
+ assertEquals(expected, actual);
+ }
+
+ public static class Traversals extends TailTest {
+
+ @Override
+ public Traversal<Vertex, Object> get_g_V_id_order_tailXglobal_2X() {
+ return g.V().id().order().tail(global, 2);
+ }
+
+ @Override
+ public Traversal<Vertex, Object> get_g_V_id_order_tailX2X() {
+ return g.V().id().order().tail(2);
+ }
+
+ @Override
+ public Traversal<Vertex, Object> get_g_V_id_order_tailX7X() {
+ return g.V().id().order().tail(7);
+ }
+
+ @Override
+ public Traversal<Vertex, List<Object>> get_g_V_asXaX_out_asXaX_out_asXaX_selectXaX_byXunfold_id_foldX_tailXlocal_2X() {
+ return g.V().as("a").out().as("a").out().as("a").<List<Object>>select("a").by(unfold().id().fold()).tail(local, 2);
+ }
+
+ @Override
+ public Traversal<Vertex, Object> get_g_V_asXaX_out_asXaX_out_asXaX_selectXaX_byXunfold_id_foldX_tailXlocal_1X() {
+ return g.V().as("a").out().as("a").out().as("a").<Object>select("a").by(unfold().id().fold()).tail(local, 1);
+ }
+
+ @Override
+ public Traversal<Vertex, Object> get_g_V_asXaX_out_asXaX_out_asXaX_selectXaX_byXlimitXlocal_0XX_tailXlocal_1X() {
+ return g.V().as("a").out().as("a").out().as("a").<Object>select("a").by(limit(local, 0)).tail(local, 1);
+ }
+
+ @Override
+ public Traversal<Vertex, Map<String, Object>> get_g_V_asXaX_out_asXbX_out_asXcX_select_byXT_idX_tailXlocal_2X() {
+ return g.V().as("a").out().as("b").out().as("c").<Object>select().by(T.id).tail(local, 2);
+ }
+
+ @Override
+ public Traversal<Vertex, Map<String, Object>> get_g_V_asXaX_out_asXbX_out_asXcX_select_byXT_idX_tailXlocal_1X() {
+ return g.V().as("a").out().as("b").out().as("c").<Object>select().by(T.id).tail(local, 1);
+ }
+ }
+}