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/03/19 19:26:46 UTC
[28/40] incubator-tinkerpop git commit: the traversal steps provided
by TinkerPop are the foundation for all dsl. GraphTraversal is just a dsl of
traversal. Refactored the process API to reflect this concept. Fixed #592.
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/4c97e964/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/FilterStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/FilterStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/FilterStep.java
new file mode 100644
index 0000000..ab364d8
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/FilterStep.java
@@ -0,0 +1,45 @@
+/*
+ * 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.process.traversal.Traverser;
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.AbstractStep;
+
+/**
+ * @author Marko A. Rodriguez (http://markorodriguez.com)
+ */
+public abstract class FilterStep<S> extends AbstractStep<S, S> {
+
+ public FilterStep(final Traversal.Admin traversal) {
+ super(traversal);
+ }
+
+ @Override
+ protected Traverser<S> processNextStart() {
+ while (true) {
+ final Traverser.Admin<S> traverser = this.starts.next();
+ if (this.filter(traverser)) {
+ return traverser;
+ }
+ }
+ }
+
+ protected abstract boolean filter(final Traverser.Admin<S> traverser);
+}
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/4c97e964/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/HasStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/HasStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/HasStep.java
new file mode 100644
index 0000000..3efbe5b
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/HasStep.java
@@ -0,0 +1,69 @@
+/*
+ * 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.process.traversal.Traverser;
+import org.apache.tinkerpop.gremlin.process.traversal.step.HasContainerHolder;
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.HasContainer;
+import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper;
+import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
+import org.apache.tinkerpop.gremlin.structure.Element;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * @author Marko A. Rodriguez (http://markorodriguez.com)
+ */
+public class HasStep<S extends Element> extends FilterStep<S> implements HasContainerHolder { // TODO: make final when graph strategies are fixed up
+
+ private final HasContainer hasContainer;
+
+ public HasStep(final Traversal.Admin traversal, final HasContainer hasContainer) {
+ super(traversal);
+ this.hasContainer = hasContainer;
+ }
+
+ @Override
+ protected boolean filter(final Traverser.Admin<S> traverser) {
+ return this.hasContainer.test(traverser.get());
+ }
+
+ @Override
+ public String toString() {
+ return TraversalHelper.makeStepString(this, this.hasContainer);
+ }
+
+ @Override
+ public List<HasContainer> getHasContainers() {
+ return Collections.singletonList(this.hasContainer);
+ }
+
+ @Override
+ public void addHasContainer(final HasContainer hasContainer) {
+ throw new UnsupportedOperationException(this.getClass().getSimpleName() + " does not support adding new HasContainers");
+ }
+
+ @Override
+ public Set<TraverserRequirement> getRequirements() {
+ return Collections.singleton(TraverserRequirement.OBJECT);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/4c97e964/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/HasTraversalStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/HasTraversalStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/HasTraversalStep.java
new file mode 100644
index 0000000..4cdfc8f
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/HasTraversalStep.java
@@ -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.process.traversal.Traverser;
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.AbstractStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent;
+import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper;
+import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalUtil;
+import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.NoSuchElementException;
+import java.util.Set;
+
+/**
+ * @author Marko A. Rodriguez (http://markorodriguez.com)
+ * @author Daniel Kuppitz (http://gremlin.guru)
+ */
+public final class HasTraversalStep<S> extends AbstractStep<S, S> implements TraversalParent {
+
+ private Traversal.Admin<S, ?> hasTraversal;
+ private final boolean negate;
+
+ public HasTraversalStep(final Traversal.Admin traversal, final Traversal.Admin<S, ?> hasTraversal, final boolean negate) {
+ super(traversal);
+ this.negate = negate;
+ this.hasTraversal = this.integrateChild(hasTraversal);
+ }
+
+ @Override
+ protected Traverser<S> processNextStart() throws NoSuchElementException {
+ while (true) {
+ final Traverser.Admin<S> start = this.starts.next();
+ if (TraversalUtil.test(start, this.hasTraversal) != this.negate)
+ return start;
+ }
+ }
+
+ @Override
+ public String toString() {
+ final String stepString = TraversalHelper.makeStepString(this, this.hasTraversal);
+ return this.negate ? stepString.replaceFirst("\\(", "(!") : stepString;
+ }
+
+ @Override
+ public List<Traversal<S, ?>> getLocalChildren() {
+ return Collections.singletonList(this.hasTraversal);
+ }
+
+ @Override
+ public Set<TraverserRequirement> getRequirements() {
+ return this.getSelfAndChildRequirements();
+ }
+
+ @Override
+ public HasTraversalStep<S> clone() {
+ final HasTraversalStep<S> clone = (HasTraversalStep<S>) super.clone();
+ clone.hasTraversal = clone.integrateChild(this.hasTraversal.clone());
+ return clone;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/4c97e964/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/IsStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/IsStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/IsStep.java
new file mode 100644
index 0000000..0f33178
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/IsStep.java
@@ -0,0 +1,66 @@
+/*
+ * 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.process.traversal.Traverser;
+import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper;
+import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
+
+import java.util.Collections;
+import java.util.Set;
+import java.util.function.BiPredicate;
+
+/**
+ * @author Daniel Kuppitz (http://gremlin.guru)
+ */
+public final class IsStep<S> extends FilterStep<S> {
+
+ private final Object value;
+ private final BiPredicate<S, Object> biPredicate;
+
+ public IsStep(final Traversal.Admin traversal, final BiPredicate<S, Object> biPredicate, final Object value) {
+ super(traversal);
+ this.value = value;
+ this.biPredicate = biPredicate;
+ }
+
+ @Override
+ protected boolean filter(final Traverser.Admin<S> traverser) {
+ return this.biPredicate.test(traverser.get(), this.value);
+ }
+
+ @Override
+ public String toString() {
+ return TraversalHelper.makeStepString(this, this.biPredicate, this.value);
+ }
+
+ @Override
+ public Set<TraverserRequirement> getRequirements() {
+ return Collections.singleton(TraverserRequirement.OBJECT);
+ }
+
+ public Object getValue() {
+ return value;
+ }
+
+ public BiPredicate<S, Object> getPredicate() {
+ return biPredicate;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/4c97e964/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/LambdaFilterStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/LambdaFilterStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/LambdaFilterStep.java
new file mode 100644
index 0000000..0036733
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/LambdaFilterStep.java
@@ -0,0 +1,52 @@
+/*
+ * 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.process.traversal.Traverser;
+import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper;
+
+import java.util.function.Predicate;
+
+/**
+ * @author Marko A. Rodriguez (http://markorodriguez.com)
+ */
+public final class LambdaFilterStep<S> extends FilterStep<S> {
+
+ private final Predicate<Traverser<S>> predicate;
+
+ public LambdaFilterStep(final Traversal.Admin traversal, final Predicate<Traverser<S>> predicate) {
+ super(traversal);
+ this.predicate = predicate;
+ }
+
+ public Predicate<Traverser<S>> getPredicate() {
+ return predicate;
+ }
+
+ @Override
+ protected boolean filter(final Traverser.Admin<S> traverser) {
+ return this.predicate.test(traverser);
+ }
+
+ @Override
+ public String toString() {
+ return TraversalHelper.makeStepString(this,this.predicate);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/4c97e964/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/OrStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/OrStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/OrStep.java
new file mode 100644
index 0000000..9f2dec8
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/OrStep.java
@@ -0,0 +1,39 @@
+/*
+ * 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.process.traversal.step.TraversalParent;
+
+/**
+ * @author Marko A. Rodriguez (http://markorodriguez.com)
+ */
+public final class OrStep<S> extends ConjunctionStep<S> implements TraversalParent {
+
+ public OrStep(final Traversal.Admin traversal, final Traversal.Admin<S, ?>... orTraversals) {
+ super(traversal, orTraversals);
+
+ }
+
+ public static final class OrMarker<S> extends ConjunctionMarker<S> {
+ public OrMarker(final Traversal.Admin traversal) {
+ super(traversal);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/4c97e964/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/RangeGlobalStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/RangeGlobalStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/RangeGlobalStep.java
new file mode 100644
index 0000000..72e92ef
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/RangeGlobalStep.java
@@ -0,0 +1,113 @@
+/*
+ * 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.FastNoSuchElementException;
+import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
+import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
+import org.apache.tinkerpop.gremlin.process.traversal.step.Ranging;
+import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper;
+import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
+
+import java.util.Collections;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicLong;
+
+/**
+ * @author Bob Briody (http://bobbriody.com)
+ * @author Marko A. Rodriguez (http://markorodriguez.com)
+ */
+public final class RangeGlobalStep<S> extends FilterStep<S> implements Ranging {
+
+ private final long low;
+ private final long high;
+ private AtomicLong counter = new AtomicLong(0l);
+
+ public RangeGlobalStep(final Traversal.Admin traversal, final long low, final long high) {
+ super(traversal);
+ if (low != -1 && high != -1 && low > high) {
+ throw new IllegalArgumentException("Not a legal range: [" + low + ", " + high + ']');
+ }
+ this.low = low;
+ this.high = high;
+ }
+
+ @Override
+ protected boolean filter(final Traverser.Admin<S> traverser) {
+ if (this.high != -1 && this.counter.get() >= this.high) {
+ throw FastNoSuchElementException.instance();
+ }
+
+ long avail = traverser.bulk();
+ if (this.counter.get() + avail <= this.low) {
+ // Will not surpass the low w/ this traverser. Skip and filter the whole thing.
+ this.counter.getAndAdd(avail);
+ return false;
+ }
+
+ // Skip for the low and trim for the high. Both can happen at once.
+
+ long toSkip = 0;
+ if (this.counter.get() < this.low) {
+ toSkip = this.low - this.counter.get();
+ }
+
+ long toTrim = 0;
+ if (this.high != -1 && this.counter.get() + avail >= this.high) {
+ toTrim = this.counter.get() + avail - this.high;
+ }
+
+ long toEmit = avail - toSkip - toTrim;
+ this.counter.getAndAdd(toSkip + toEmit);
+ traverser.asAdmin().setBulk(toEmit);
+
+ return true;
+ }
+
+ @Override
+ public void reset() {
+ super.reset();
+ this.counter.set(0l);
+ }
+
+ @Override
+ public String toString() {
+ return TraversalHelper.makeStepString(this, this.low, this.high);
+ }
+
+ public long getLowRange() {
+ return this.low;
+ }
+
+ public long getHighRange() {
+ return this.high;
+ }
+
+ @Override
+ public RangeGlobalStep<S> clone() {
+ final RangeGlobalStep<S> clone = (RangeGlobalStep<S>) super.clone();
+ clone.counter = new AtomicLong(0l);
+ return clone;
+ }
+
+ @Override
+ public Set<TraverserRequirement> getRequirements() {
+ return Collections.singleton(TraverserRequirement.BULK);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/4c97e964/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/RetainStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/RetainStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/RetainStep.java
new file mode 100644
index 0000000..bc217d3
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/RetainStep.java
@@ -0,0 +1,97 @@
+/*
+ * 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.process.traversal.Traverser;
+import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper;
+import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+/**
+ * @author Marko A. Rodriguez (http://markorodriguez.com)
+ */
+public final class RetainStep<S> extends FilterStep<S> {
+
+ private final String sideEffectKeyOrPathLabel;
+ private final Collection<S> retainCollection;
+ private final S retainObject;
+ private final short choice;
+
+ public RetainStep(final Traversal.Admin traversal, final String sideEffectKeyOrPathLabel) {
+ super(traversal);
+ this.sideEffectKeyOrPathLabel = sideEffectKeyOrPathLabel;
+ this.retainCollection = null;
+ this.retainObject = null;
+ this.choice = 0;
+ }
+
+ public RetainStep(final Traversal.Admin traversal, final Collection<S> retainCollection) {
+ super(traversal);
+ this.sideEffectKeyOrPathLabel = null;
+ this.retainCollection = retainCollection;
+ this.retainObject = null;
+ this.choice = 1;
+ }
+
+ public RetainStep(final Traversal.Admin traversal, final S retainObject) {
+ super(traversal);
+ this.sideEffectKeyOrPathLabel = null;
+ this.retainCollection = null;
+ this.retainObject = retainObject;
+ this.choice = 2;
+ }
+
+ @Override
+ protected boolean filter(final Traverser.Admin<S> traverser) {
+ switch (this.choice) {
+ case 0: {
+ final Object retain = traverser.asAdmin().getSideEffects().exists(this.sideEffectKeyOrPathLabel) ?
+ traverser.sideEffects(this.sideEffectKeyOrPathLabel) :
+ traverser.path(this.sideEffectKeyOrPathLabel);
+ return retain instanceof Collection ?
+ ((Collection) retain).contains(traverser.get()) :
+ retain.equals(traverser.get());
+ }
+ case 1:
+ return this.retainCollection.contains(traverser.get());
+ default:
+ return this.retainObject.equals(traverser.get());
+ }
+ }
+
+ @Override
+ public String toString() {
+ return TraversalHelper.makeStepString(this, this.sideEffectKeyOrPathLabel);
+ }
+
+ @Override
+ public Set<TraverserRequirement> getRequirements() {
+ return null == this.sideEffectKeyOrPathLabel ?
+ Collections.singleton(TraverserRequirement.OBJECT) :
+ Stream.of(TraverserRequirement.OBJECT,
+ TraverserRequirement.SIDE_EFFECTS,
+ TraverserRequirement.PATH_ACCESS).collect(Collectors.toSet());
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/4c97e964/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/SampleGlobalStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/SampleGlobalStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/SampleGlobalStep.java
new file mode 100644
index 0000000..5817f37
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/SampleGlobalStep.java
@@ -0,0 +1,117 @@
+/*
+ * 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.process.traversal.Traverser;
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.CollectingBarrierStep;
+import org.apache.tinkerpop.gremlin.process.traversal.lambda.ConstantTraversal;
+import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent;
+import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper;
+import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalUtil;
+import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
+import org.apache.tinkerpop.gremlin.process.traversal.traverser.util.TraverserSet;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Random;
+import java.util.Set;
+
+/**
+ * @author Marko A. Rodriguez (http://markorodriguez.com)
+ */
+public final class SampleGlobalStep<S> extends CollectingBarrierStep<S> implements TraversalParent {
+
+ private Traversal.Admin<S, Number> probabilityTraversal = new ConstantTraversal<>(1.0d);
+ private final int amountToSample;
+ private static final Random RANDOM = new Random();
+
+ public SampleGlobalStep(final Traversal.Admin traversal, final int amountToSample) {
+ super(traversal);
+ this.amountToSample = amountToSample;
+ }
+
+ @Override
+ public List<Traversal.Admin<S, Number>> getLocalChildren() {
+ return Collections.singletonList(this.probabilityTraversal);
+ }
+
+ @Override
+ public void addLocalChild(final Traversal.Admin<?, ?> probabilityTraversal) {
+ this.probabilityTraversal = this.integrateChild(probabilityTraversal);
+ }
+
+ @Override
+ public String toString() {
+ return TraversalHelper.makeStepString(this, this.amountToSample, this.probabilityTraversal);
+ }
+
+ @Override
+ public void barrierConsumer(final TraverserSet<S> traverserSet) {
+ // return the entire traverser set if the set is smaller than the amount to sample
+ if (traverserSet.bulkSize() <= this.amountToSample)
+ return;
+ //////////////// else sample the set
+ double totalWeight = 0.0d;
+ for (final Traverser<S> s : traverserSet) {
+ totalWeight = totalWeight + TraversalUtil.apply(s.asAdmin(), this.probabilityTraversal).doubleValue() * s.bulk();
+ }
+ ///////
+ final TraverserSet<S> sampledSet = new TraverserSet<>();
+ int runningAmountToSample = 0;
+ while (runningAmountToSample < this.amountToSample) {
+ boolean reSample = false;
+ double runningWeight = 0.0d;
+ for (final Traverser.Admin<S> s : traverserSet) {
+ long sampleBulk = sampledSet.contains(s) ? sampledSet.get(s).bulk() : 0;
+ if (sampleBulk < s.bulk()) {
+ final double currentWeight = TraversalUtil.apply(s, this.probabilityTraversal).doubleValue();
+ for (int i = 0; i < (s.bulk() - sampleBulk); i++) {
+ runningWeight = runningWeight + currentWeight;
+ if (RANDOM.nextDouble() <= (runningWeight / totalWeight)) {
+ final Traverser.Admin<S> split = s.asAdmin().split();
+ split.asAdmin().setBulk(1l);
+ sampledSet.add(split);
+ runningAmountToSample++;
+ totalWeight = totalWeight - currentWeight;
+ reSample = true;
+ break;
+ }
+ }
+ if (reSample || (runningAmountToSample >= this.amountToSample))
+ break;
+ }
+ }
+ }
+ traverserSet.clear();
+ traverserSet.addAll(sampledSet);
+ }
+
+ @Override
+ public Set<TraverserRequirement> getRequirements() {
+ return this.getSelfAndChildRequirements(TraverserRequirement.BULK);
+ }
+
+ @Override
+ public SampleGlobalStep<S> clone() {
+ final SampleGlobalStep<S> clone = (SampleGlobalStep<S>) super.clone();
+ clone.probabilityTraversal = clone.integrateChild(this.probabilityTraversal.clone());
+ return clone;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/4c97e964/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/SimplePathStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/SimplePathStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/SimplePathStep.java
new file mode 100644
index 0000000..5789803
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/SimplePathStep.java
@@ -0,0 +1,47 @@
+/*
+ * 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.process.traversal.Traverser;
+import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
+
+import java.util.Collections;
+import java.util.Set;
+
+/**
+ * @author Marko A. Rodriguez (http://markorodriguez.com)
+ */
+public final class SimplePathStep<S> extends FilterStep<S> {
+
+ public SimplePathStep(final Traversal.Admin traversal) {
+ super(traversal);
+ }
+
+ @Override
+ protected boolean filter(final Traverser.Admin<S> traverser) {
+ return traverser.path().isSimple();
+ }
+
+ @Override
+ public Set<TraverserRequirement> getRequirements() {
+ return Collections.singleton(TraverserRequirement.PATH);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/4c97e964/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/TimeLimitStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/TimeLimitStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/TimeLimitStep.java
new file mode 100644
index 0000000..c0e5f28
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/TimeLimitStep.java
@@ -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.FastNoSuchElementException;
+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 java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicLong;
+
+/**
+ * @author Randall Barnhart (random pi)
+ * @author Marko A. Rodriguez (http://markorodriguez.com)
+ * @author Stephen Mallette (http://stephen.genoprime.com)
+ */
+public final class TimeLimitStep<S> extends FilterStep<S> {
+
+ private AtomicLong startTime = new AtomicLong(-1);
+ private final long timeLimit;
+ private AtomicBoolean timedOut = new AtomicBoolean(false);
+
+
+ public TimeLimitStep(final Traversal.Admin traversal, final long timeLimit) {
+ super(traversal);
+ this.timeLimit = timeLimit;
+ }
+
+ @Override
+ protected boolean filter(final Traverser.Admin<S> traverser) {
+ if (this.startTime.get() == -1l)
+ this.startTime.set(System.currentTimeMillis());
+ if ((System.currentTimeMillis() - this.startTime.get()) >= this.timeLimit) {
+ this.timedOut.set(true);
+ throw FastNoSuchElementException.instance();
+ }
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ return TraversalHelper.makeStepString(this, this.timeLimit);
+ }
+
+ @Override
+ public void reset() {
+ super.reset();
+ this.startTime.set(-1l);
+ this.timedOut.set(false);
+ }
+
+ public boolean getTimedOut() {
+ return this.timedOut.get();
+ }
+
+ @Override
+ public TimeLimitStep<S> clone() {
+ final TimeLimitStep<S> clone = (TimeLimitStep<S>) super.clone();
+ clone.timedOut = new AtomicBoolean(this.timedOut.get());
+ clone.startTime = new AtomicLong(this.startTime.get());
+ return clone;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/4c97e964/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/WhereStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/WhereStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/WhereStep.java
new file mode 100644
index 0000000..14c541a
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/WhereStep.java
@@ -0,0 +1,132 @@
+/*
+ * 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;
+import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
+import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.MarkerIdentityStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent;
+import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper;
+import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.function.BiPredicate;
+
+/**
+ * @author Marko A. Rodriguez (http://markorodriguez.com)
+ */
+public final class WhereStep<E> extends FilterStep<Map<String, E>> implements TraversalParent {
+
+ private final String firstKey;
+ private final String secondKey;
+ private final BiPredicate biPredicate;
+ private Traversal.Admin constraint;
+
+
+ public WhereStep(final Traversal.Admin traversal, final String firstKey, final String secondKey, final BiPredicate<E, E> biPredicate) {
+ super(traversal);
+ this.firstKey = firstKey;
+ this.secondKey = secondKey;
+ this.biPredicate = biPredicate;
+ this.constraint = null;
+ }
+
+ public WhereStep(final Traversal.Admin traversal, final Traversal.Admin constraint) {
+ super(traversal);
+ this.firstKey = null;
+ this.secondKey = null;
+ this.biPredicate = null;
+ this.constraint = this.integrateChild(constraint);
+ }
+
+ @Override
+ protected boolean filter(final Traverser.Admin<Map<String, E>> traverser) {
+ if (null == this.constraint) {
+ final Map<String, E> map = traverser.get();
+ if (!map.containsKey(this.firstKey))
+ throw new IllegalArgumentException("The provided key is not in the current map: " + this.firstKey);
+ if (!map.containsKey(this.secondKey))
+ throw new IllegalArgumentException("The provided key is not in the current map: " + this.secondKey);
+ return this.biPredicate.test(map.get(this.firstKey), map.get(this.secondKey));
+ } else {
+ final Step<?, ?> startStep = this.constraint.getStartStep();
+ Step<?, ?> endStep = this.constraint.getEndStep();
+ if (endStep instanceof MarkerIdentityStep) // DAH!
+ endStep = endStep.getPreviousStep();
+
+ final Map<String, E> map = traverser.get();
+ if (!map.containsKey(startStep.getLabel().get()))
+ throw new IllegalArgumentException("The provided key is not in the current map: " + startStep.getLabel().get());
+ final Object startObject = map.get(startStep.getLabel().get());
+ final Object endObject;
+ if (endStep.getLabel().isPresent()) {
+ if (!map.containsKey(endStep.getLabel().get()))
+ throw new IllegalArgumentException("The provided key is not in the current map: " + endStep.getLabel().get());
+ endObject = map.get(endStep.getLabel().get());
+ } else
+ endObject = null;
+
+ startStep.addStart(this.getTraversal().asAdmin().getTraverserGenerator().generate(startObject, (Step) startStep, traverser.bulk()));
+ if (null == endObject) {
+ if (this.constraint.hasNext()) {
+ this.constraint.reset();
+ return true;
+ } else {
+ return false;
+ }
+
+ } else {
+ while (this.constraint.hasNext()) {
+ if (this.constraint.next().equals(endObject)) {
+ this.constraint.reset();
+ return true;
+ }
+ }
+ return false;
+ }
+ }
+ }
+
+ @Override
+ public List<Traversal.Admin> getLocalChildren() {
+ return null == this.constraint ? Collections.emptyList() : Collections.singletonList(this.constraint);
+ }
+
+ @Override
+ public String toString() {
+ return TraversalHelper.makeStepString(this, this.firstKey, this.biPredicate, this.secondKey, this.constraint);
+ }
+
+ @Override
+ public WhereStep<E> clone() {
+ final WhereStep<E> clone = (WhereStep<E>) super.clone();
+ if (null != this.constraint)
+ clone.constraint = clone.integrateChild(this.constraint.clone());
+ return clone;
+ }
+
+ @Override
+ public Set<TraverserRequirement> getRequirements() {
+ return this.getSelfAndChildRequirements(TraverserRequirement.OBJECT);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/4c97e964/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AddEdgeByPathStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AddEdgeByPathStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AddEdgeByPathStep.java
new file mode 100644
index 0000000..9671f34
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AddEdgeByPathStep.java
@@ -0,0 +1,95 @@
+/*
+ * 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.step.Mutating;
+import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper;
+import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
+import org.apache.tinkerpop.gremlin.structure.Direction;
+import org.apache.tinkerpop.gremlin.structure.Edge;
+import org.apache.tinkerpop.gremlin.structure.Vertex;
+
+import java.util.EnumSet;
+import java.util.Set;
+
+/**
+ * @author Marko A. Rodriguez (http://markorodriguez.com)
+ */
+public final class AddEdgeByPathStep extends MapStep<Vertex, Edge> implements Mutating {
+
+ private static final Set<TraverserRequirement> REQUIREMENTS = EnumSet.of(
+ TraverserRequirement.PATH,
+ TraverserRequirement.OBJECT
+ );
+
+ // TODO: Weight key based on Traverser.getCount() ?
+
+ private final Direction direction;
+ private final String edgeLabel;
+ private final String stepLabel;
+ private final Object[] keyValues;
+
+ public AddEdgeByPathStep(final Traversal.Admin traversal, final Direction direction, final String edgeLabel, final String stepLabel, final Object... keyValues) {
+ super(traversal);
+ this.direction = direction;
+ if (this.direction.equals(Direction.BOTH))
+ throw new IllegalArgumentException("Only in- and out- directions are supported by " + AddEdgeByPathStep.class.getSimpleName());
+ this.edgeLabel = edgeLabel;
+ this.stepLabel = stepLabel;
+ this.keyValues = keyValues;
+ }
+
+ public Direction getDirection() {
+ return direction;
+ }
+
+ public String getEdgeLabel() {
+ return edgeLabel;
+ }
+
+ public String getStepLabel() {
+ return stepLabel;
+ }
+
+ public Object[] getKeyValues() {
+ return keyValues;
+ }
+
+ @Override
+ public String toString() {
+ return TraversalHelper.makeStepString(this, this.direction.name(), this.edgeLabel, this.stepLabel);
+ }
+
+ @Override
+ protected Edge map(Traverser.Admin<Vertex> traverser) {
+ final Vertex currentVertex = traverser.get();
+ final Vertex otherVertex = traverser.path().get(this.stepLabel);
+ if (this.direction.equals(Direction.IN))
+ return otherVertex.addEdge(this.edgeLabel, currentVertex, this.keyValues);
+ else
+ return currentVertex.addEdge(this.edgeLabel, otherVertex, this.keyValues);
+ }
+
+ @Override
+ public Set<TraverserRequirement> getRequirements() {
+ return REQUIREMENTS;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/4c97e964/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
new file mode 100644
index 0000000..e96c65f
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AddEdgeStep.java
@@ -0,0 +1,86 @@
+/*
+ * 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.step.Mutating;
+import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
+import org.apache.tinkerpop.gremlin.structure.Direction;
+import org.apache.tinkerpop.gremlin.structure.Edge;
+import org.apache.tinkerpop.gremlin.structure.Vertex;
+import org.apache.tinkerpop.gremlin.util.iterator.IteratorUtils;
+
+import java.util.EnumSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * @author Marko A. Rodriguez (http://markorodriguez.com)
+ */
+public final class AddEdgeStep extends FlatMapStep<Vertex, Edge> implements Mutating {
+
+ private static final Set<TraverserRequirement> REQUIREMENTS = EnumSet.of(TraverserRequirement.OBJECT);
+
+ private final String edgeLabel;
+ private final Object[] keyValues;
+ private final List<Vertex> vertices;
+ private final Direction direction;
+
+ public AddEdgeStep(final Traversal.Admin traversal, final Direction direction, final String edgeLabel, final Vertex vertex, final Object... keyValues) {
+ this(traversal, direction, edgeLabel, IteratorUtils.of(vertex), keyValues);
+ }
+
+ public AddEdgeStep(final Traversal.Admin traversal, final Direction direction, final String edgeLabel, final Iterator<Vertex> vertices, final Object... keyValues) {
+ super(traversal);
+ this.direction = direction;
+ this.edgeLabel = edgeLabel;
+ this.vertices = IteratorUtils.list(vertices);
+ this.keyValues = keyValues;
+ }
+
+ public Direction getDirection() {
+ return direction;
+ }
+
+ public String getEdgeLabel() {
+ return edgeLabel;
+ }
+
+ public Object[] getKeyValues() {
+ return keyValues;
+ }
+
+ public List<Vertex> getVertices() {
+ return vertices;
+ }
+
+ @Override
+ protected Iterator<Edge> flatMap(final Traverser.Admin<Vertex> traverser) {
+ return IteratorUtils.map(this.vertices.iterator(), this.direction.equals(Direction.OUT) ?
+ vertex -> traverser.get().addEdge(this.edgeLabel, vertex, this.keyValues) :
+ vertex -> vertex.addEdge(this.edgeLabel, traverser.get(), this.keyValues));
+ }
+
+ @Override
+ public Set<TraverserRequirement> getRequirements() {
+ return REQUIREMENTS;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/4c97e964/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AddVertexStartStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AddVertexStartStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AddVertexStartStep.java
new file mode 100644
index 0000000..2f90ea1
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AddVertexStartStep.java
@@ -0,0 +1,53 @@
+/*
+ * 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.FastNoSuchElementException;
+import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
+import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
+import org.apache.tinkerpop.gremlin.process.traversal.step.Mutating;
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.AbstractStep;
+import org.apache.tinkerpop.gremlin.structure.Vertex;
+
+/**
+ * @author Marko A. Rodriguez (http://markorodriguez.com)
+ */
+public final class AddVertexStartStep extends AbstractStep<Vertex, Vertex> implements Mutating {
+
+ private final Object[] keyValues;
+ private boolean first = true;
+
+ public AddVertexStartStep(final Traversal.Admin traversal, final Object... keyValues) {
+ super(traversal);
+ this.keyValues = keyValues;
+ }
+
+ public Object[] getKeyValues() {
+ return keyValues;
+ }
+
+ @Override
+ protected Traverser<Vertex> processNextStart() {
+ if (this.first) {
+ this.first = false;
+ return this.getTraversal().getTraverserGenerator().generate(this.getTraversal().getGraph().get().addVertex(this.keyValues), this, 1l);
+ } else
+ throw FastNoSuchElementException.instance();
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/4c97e964/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AddVertexStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AddVertexStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AddVertexStep.java
new file mode 100644
index 0000000..0632f87
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AddVertexStep.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.map;
+
+import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
+import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
+import org.apache.tinkerpop.gremlin.process.traversal.step.Mutating;
+import org.apache.tinkerpop.gremlin.structure.Graph;
+import org.apache.tinkerpop.gremlin.structure.Vertex;
+
+/**
+ * @author Marko A. Rodriguez (http://markorodriguez.com)
+ */
+public final class AddVertexStep<S> extends MapStep<S, Vertex> implements Mutating {
+
+ private final Object[] keyValues;
+ private final transient Graph graph;
+
+ public AddVertexStep(final Traversal.Admin traversal, final Object... keyValues) {
+ super(traversal);
+ this.keyValues = keyValues;
+ this.graph = this.getTraversal().getGraph().get();
+ }
+
+ public Object[] getKeyValues() {
+ return keyValues;
+ }
+
+ @Override
+ protected Vertex map(final Traverser.Admin<S> traverser) {
+ return this.graph.addVertex(this.keyValues);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/4c97e964/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/BackStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/BackStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/BackStep.java
new file mode 100644
index 0000000..9d683df
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/BackStep.java
@@ -0,0 +1,64 @@
+/*
+ * 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.TraversalEngine;
+import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
+import org.apache.tinkerpop.gremlin.process.traversal.step.EngineDependent;
+import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper;
+import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
+
+import java.util.Collections;
+import java.util.Set;
+
+/**
+ * @author Marko A. Rodriguez (http://markorodriguez.com)
+ */
+public final class BackStep<S, E> extends MapStep<S, E> implements EngineDependent {
+
+ private final String stepLabel;
+ private boolean requiresPaths = false;
+
+ public BackStep(final Traversal.Admin traversal, final String stepLabel) {
+ super(traversal);
+ this.stepLabel = stepLabel;
+ }
+
+ @Override
+ protected E map(final Traverser.Admin<S> traverser) {
+ return traverser.path(this.stepLabel);
+ }
+
+ @Override
+ public void onEngine(final TraversalEngine traversalEngine) {
+ this.requiresPaths = traversalEngine.isComputer();
+ }
+
+ @Override
+ public Set<TraverserRequirement> getRequirements() {
+ //return this.requiresPaths ? Collections.singleton(TraverserRequirement.PATH) : Collections.singleton(TraverserRequirement.PATH_ACCESS);
+ return Collections.singleton(TraverserRequirement.PATH); // TODO: if the traversal isn't nested, path access works
+ }
+
+ @Override
+ public String toString() {
+ return TraversalHelper.makeStepString(this, this.stepLabel);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/4c97e964/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/CoalesceStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/CoalesceStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/CoalesceStep.java
new file mode 100644
index 0000000..a0a8d7f
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/CoalesceStep.java
@@ -0,0 +1,86 @@
+/*
+ * 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.step.TraversalParent;
+import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper;
+import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
+import org.apache.tinkerpop.gremlin.util.iterator.EmptyIterator;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * @author Daniel Kuppitz (http://gremlin.guru)
+ */
+public final class CoalesceStep<S, E> extends FlatMapStep<S, E> implements TraversalParent {
+
+ private List<Traversal.Admin<S, E>> coalesceTraversals;
+
+ @SafeVarargs
+ public CoalesceStep(final Traversal.Admin traversal, final Traversal.Admin<S, E>... coalesceTraversals) {
+ super(traversal);
+ this.coalesceTraversals = Arrays.asList(coalesceTraversals);
+ for (final Traversal.Admin<S, ?> conjunctionTraversal : this.coalesceTraversals) {
+ this.integrateChild(conjunctionTraversal);
+ }
+ }
+
+ @Override
+ protected Iterator<E> flatMap(final Traverser.Admin<S> traverser) {
+ for (final Traversal.Admin<S, E> coalesceTraversal : this.coalesceTraversals) {
+ coalesceTraversal.reset();
+ coalesceTraversal.addStart(traverser.asAdmin().split());
+ if (coalesceTraversal.hasNext())
+ return coalesceTraversal;
+ }
+ return EmptyIterator.instance();
+ }
+
+ @Override
+ public Set<TraverserRequirement> getRequirements() {
+ return this.getSelfAndChildRequirements();
+ }
+
+ @Override
+ public List<Traversal.Admin<S, E>> getLocalChildren() {
+ return Collections.unmodifiableList(this.coalesceTraversals);
+ }
+
+ @Override
+ public CoalesceStep<S, E> clone() {
+ final CoalesceStep<S, E> clone = (CoalesceStep<S, E>) super.clone();
+ clone.coalesceTraversals = new ArrayList<>();
+ for (final Traversal.Admin<S, ?> conjunctionTraversal : this.coalesceTraversals) {
+ clone.coalesceTraversals.add(clone.integrateChild(conjunctionTraversal.clone()));
+ }
+ return clone;
+ }
+
+ @Override
+ public String toString() {
+ return TraversalHelper.makeStepString(this, this.coalesceTraversals);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/4c97e964/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/CountGlobalStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/CountGlobalStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/CountGlobalStep.java
new file mode 100644
index 0000000..cb7ede4
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/CountGlobalStep.java
@@ -0,0 +1,134 @@
+/*
+ * 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.computer.KeyValue;
+import org.apache.tinkerpop.gremlin.process.computer.MapReduce;
+import org.apache.tinkerpop.gremlin.process.computer.traversal.TraversalVertexProgram;
+import org.apache.tinkerpop.gremlin.process.computer.util.StaticMapReduce;
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.ReducingBarrierStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.MapReducer;
+import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
+import org.apache.tinkerpop.gremlin.process.traversal.traverser.util.TraverserSet;
+import org.apache.tinkerpop.gremlin.structure.Vertex;
+import org.apache.tinkerpop.gremlin.util.function.ConstantSupplier;
+
+import java.io.Serializable;
+import java.util.EnumSet;
+import java.util.Iterator;
+import java.util.Set;
+import java.util.function.BiFunction;
+
+/**
+ * @author Marko A. Rodriguez (http://markorodriguez.com)
+ */
+public final class CountGlobalStep<S> extends ReducingBarrierStep<S, Long> implements MapReducer {
+
+ private static final Set<TraverserRequirement> REQUIREMENTS = EnumSet.of(TraverserRequirement.BULK);
+
+ public CountGlobalStep(final Traversal.Admin traversal) {
+ super(traversal);
+ this.setSeedSupplier(new ConstantSupplier<>(0L));
+ this.setBiFunction(CountBiFunction.<S>instance());
+ }
+
+
+ @Override
+ public Set<TraverserRequirement> getRequirements() {
+ return REQUIREMENTS;
+ }
+
+ @Override
+ public MapReduce<MapReduce.NullObject, Long, MapReduce.NullObject, Long, Long> getMapReduce() {
+ return CountGlobalMapReduce.instance();
+ }
+
+ ///////////
+
+ private static class CountBiFunction<S> implements BiFunction<Long, Traverser<S>, Long>, Serializable {
+
+ private static final CountBiFunction INSTANCE = new CountBiFunction();
+
+ private CountBiFunction() {
+
+ }
+
+ @Override
+ public Long apply(final Long mutatingSeed, final Traverser<S> traverser) {
+ return mutatingSeed + traverser.bulk();
+ }
+
+ public final static <S> CountBiFunction<S> instance() {
+ return INSTANCE;
+ }
+ }
+
+ ///////////
+
+ private static class CountGlobalMapReduce extends StaticMapReduce<MapReduce.NullObject, Long, MapReduce.NullObject, Long, Long> {
+
+ private static CountGlobalMapReduce INSTANCE = new CountGlobalMapReduce();
+
+ private CountGlobalMapReduce() {
+
+ }
+
+ @Override
+ public boolean doStage(final MapReduce.Stage stage) {
+ return true;
+ }
+
+ @Override
+ public void map(final Vertex vertex, final MapEmitter<NullObject, Long> emitter) {
+ vertex.<TraverserSet<?>>property(TraversalVertexProgram.HALTED_TRAVERSERS).ifPresent(traverserSet -> traverserSet.forEach(traverser -> emitter.emit(traverser.bulk())));
+ }
+
+ @Override
+ public void combine(final NullObject key, final Iterator<Long> values, final ReduceEmitter<NullObject, Long> emitter) {
+ this.reduce(key, values, emitter);
+ }
+
+ @Override
+ public void reduce(final NullObject key, final Iterator<Long> values, final ReduceEmitter<NullObject, Long> emitter) {
+ long count = 0l;
+ while (values.hasNext()) {
+ count = count + values.next();
+ }
+ emitter.emit(count);
+ }
+
+ @Override
+ public String getMemoryKey() {
+ return REDUCING;
+ }
+
+ @Override
+ public Long generateFinalResult(final Iterator<KeyValue<NullObject, Long>> keyValues) {
+ return keyValues.hasNext() ? keyValues.next().getValue() : 0L;
+ }
+
+ public static final CountGlobalMapReduce instance() {
+ return INSTANCE;
+ }
+
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/4c97e964/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/CountLocalStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/CountLocalStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/CountLocalStep.java
new file mode 100644
index 0000000..8c6dc9d
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/CountLocalStep.java
@@ -0,0 +1,51 @@
+/*
+ * 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 java.util.Collection;
+import java.util.Collections;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @author Marko A. Rodriguez (http://markorodriguez.com)
+ * @author Daniel Kuppitz (http://gremlin.guru)
+ */
+public final class CountLocalStep<S> extends MapStep<S, Long> {
+
+ public CountLocalStep(final Traversal.Admin traversal) {
+ super(traversal);
+ }
+
+ @Override
+ protected Long map(final Traverser.Admin<S> traverser) {
+ final S item = traverser.get();
+ return (item instanceof Collection) ? ((Collection) item).size()
+ : (item instanceof Map) ? ((Map) item).size() : 1L;
+ }
+
+ @Override
+ public Set<TraverserRequirement> getRequirements() {
+ return Collections.singleton(TraverserRequirement.OBJECT);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/4c97e964/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/DedupLocalStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/DedupLocalStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/DedupLocalStep.java
new file mode 100644
index 0000000..59c66c7
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/DedupLocalStep.java
@@ -0,0 +1,51 @@
+/*
+ * 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 java.util.Collections;
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+/**
+ * @author Daniel Kuppitz (http://gremlin.guru)
+ */
+public final class DedupLocalStep<E, S extends Iterable<E>> extends MapStep<S, Set<E>> {
+
+ public DedupLocalStep(final Traversal.Admin traversal) {
+ super(traversal);
+ }
+
+ @Override
+ protected Set<E> map(final Traverser.Admin<S> traverser) {
+ final Set<E> result = new LinkedHashSet<>();
+ for (final E item : traverser.get()) {
+ result.add(item);
+ }
+ return result;
+ }
+
+ @Override
+ public Set<TraverserRequirement> getRequirements() {
+ return Collections.singleton(TraverserRequirement.OBJECT);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/4c97e964/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/EdgeOtherVertexStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/EdgeOtherVertexStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/EdgeOtherVertexStep.java
new file mode 100644
index 0000000..411737c
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/EdgeOtherVertexStep.java
@@ -0,0 +1,58 @@
+/*
+ * 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.structure.Edge;
+import org.apache.tinkerpop.gremlin.structure.Vertex;
+import org.apache.tinkerpop.gremlin.structure.util.ElementHelper;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * @author Marko A. Rodriguez (http://markorodriguez.com)
+ */
+public final class EdgeOtherVertexStep extends MapStep<Edge, Vertex> {
+
+ public EdgeOtherVertexStep(final Traversal.Admin traversal) {
+ super(traversal);
+ }
+
+ @Override
+ protected Vertex map(final Traverser.Admin<Edge> traverser) {
+ final List<Object> objects = traverser.path().objects();
+ for (int i = objects.size() - 2; i >= 0; i--) {
+ if (objects.get(i) instanceof Vertex) {
+ return ElementHelper.areEqual((Vertex) objects.get(i), traverser.get().outVertex()) ?
+ traverser.get().inVertex() :
+ traverser.get().outVertex();
+ }
+ }
+ throw new IllegalStateException("The path history of the traverser does not contain a previous vertex: " + traverser.path());
+ }
+
+ @Override
+ public Set<TraverserRequirement> getRequirements() {
+ return Collections.singleton(TraverserRequirement.PATH);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/4c97e964/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/EdgeVertexStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/EdgeVertexStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/EdgeVertexStep.java
new file mode 100644
index 0000000..4783e25
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/EdgeVertexStep.java
@@ -0,0 +1,67 @@
+/*
+ * 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.util.TraversalHelper;
+import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
+import org.apache.tinkerpop.gremlin.structure.Direction;
+import org.apache.tinkerpop.gremlin.structure.Edge;
+import org.apache.tinkerpop.gremlin.structure.Vertex;
+
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.Set;
+
+/**
+ * @author Marko A. Rodriguez (http://markorodriguez.com)
+ */
+public final class EdgeVertexStep extends FlatMapStep<Edge, Vertex> {
+
+ private Direction direction;
+
+ public EdgeVertexStep(final Traversal.Admin traversal, final Direction direction) {
+ super(traversal);
+ this.direction = direction;
+ }
+
+ @Override
+ protected Iterator<Vertex> flatMap(final Traverser.Admin<Edge> traverser) {
+ return traverser.get().vertices(this.direction);
+ }
+
+ @Override
+ public String toString() {
+ return TraversalHelper.makeStepString(this, this.direction);
+ }
+
+ public Direction getDirection() {
+ return this.direction;
+ }
+
+ public void reverseDirection() {
+ this.direction = this.direction.opposite();
+ }
+
+ @Override
+ public Set<TraverserRequirement> getRequirements() {
+ return Collections.singleton(TraverserRequirement.OBJECT);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/4c97e964/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/FlatMapStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/FlatMapStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/FlatMapStep.java
new file mode 100644
index 0000000..eb111c8
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/FlatMapStep.java
@@ -0,0 +1,59 @@
+/*
+ * 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.step.util.AbstractStep;
+import org.apache.tinkerpop.gremlin.util.iterator.EmptyIterator;
+
+import java.util.Iterator;
+
+/**
+ * @author Marko A. Rodriguez (http://markorodriguez.com)
+ */
+public abstract class FlatMapStep<S, E> extends AbstractStep<S, E> {
+
+ private Traverser.Admin<S> head = null;
+ private Iterator<E> iterator = EmptyIterator.instance();
+
+ public FlatMapStep(final Traversal.Admin traversal) {
+ super(traversal);
+ }
+
+ @Override
+ protected Traverser<E> processNextStart() {
+ while (true) {
+ if (this.iterator.hasNext()) {
+ return this.head.split(this.iterator.next(), this);
+ } else {
+ this.head = this.starts.next();
+ this.iterator = this.flatMap(this.head);
+ }
+ }
+ }
+
+ protected abstract Iterator<E> flatMap(final Traverser.Admin<S> traverser);
+
+ @Override
+ public void reset() {
+ super.reset();
+ this.iterator = EmptyIterator.instance();
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/4c97e964/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/FoldStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/FoldStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/FoldStep.java
new file mode 100644
index 0000000..27580a9
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/FoldStep.java
@@ -0,0 +1,93 @@
+/*
+ * 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.step.util.ReducingBarrierStep;
+import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
+import org.apache.tinkerpop.gremlin.util.function.ArrayListSupplier;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.EnumSet;
+import java.util.Set;
+import java.util.function.BiFunction;
+import java.util.function.Supplier;
+
+/**
+ * @author Marko A. Rodriguez (http://markorodriguez.com)
+ */
+public final class FoldStep<S, E> extends ReducingBarrierStep<S, E> {
+
+ private static final Set<TraverserRequirement> REQUIREMENTS = EnumSet.of(TraverserRequirement.OBJECT);
+
+ public FoldStep(final Traversal.Admin traversal) {
+ this(traversal, (Supplier) ArrayListSupplier.instance(), (BiFunction) ArrayListBiFunction.instance());
+ }
+
+ public FoldStep(final Traversal.Admin traversal, final Supplier<E> seed, final BiFunction<E, S, E> foldFunction) {
+ super(traversal);
+ this.setSeedSupplier(seed);
+ this.setBiFunction(new FoldBiFunction<>(foldFunction));
+ }
+
+ @Override
+ public Set<TraverserRequirement> getRequirements() {
+ return REQUIREMENTS;
+ }
+
+ /////////
+
+ private static class ArrayListBiFunction<S> implements BiFunction<ArrayList<S>, S, ArrayList<S>>, Serializable {
+
+ private static final ArrayListBiFunction INSTANCE = new ArrayListBiFunction();
+
+ private ArrayListBiFunction() {
+
+ }
+
+ @Override
+ public ArrayList<S> apply(final ArrayList<S> mutatingSeed, final S traverser) {
+ mutatingSeed.add(traverser);
+ return mutatingSeed;
+ }
+
+ public final static <S> ArrayListBiFunction<S> instance() {
+ return INSTANCE;
+ }
+ }
+
+ ///////
+
+ public static class FoldBiFunction<S, E> implements BiFunction<E, Traverser<S>, E>, Serializable {
+
+ private final BiFunction<E, S, E> biFunction;
+
+ public FoldBiFunction(final BiFunction<E, S, E> biFunction) {
+ this.biFunction = biFunction;
+ }
+
+ @Override
+ public E apply(final E seed, final Traverser<S> traverser) {
+ return this.biFunction.apply(seed, traverser.get());
+ }
+
+ }
+}