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:47 UTC

[29/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/AbstractStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/AbstractStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/AbstractStep.java
deleted file mode 100644
index 36db578..0000000
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/AbstractStep.java
+++ /dev/null
@@ -1,183 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.tinkerpop.gremlin.process.traversal.step;
-
-import org.apache.tinkerpop.gremlin.process.Step;
-import org.apache.tinkerpop.gremlin.process.Traversal;
-import org.apache.tinkerpop.gremlin.process.Traverser;
-import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper;
-
-import java.util.Iterator;
-import java.util.NoSuchElementException;
-import java.util.Objects;
-import java.util.Optional;
-
-/**
- * @author Marko A. Rodriguez (http://markorodriguez.com)
- */
-public abstract class AbstractStep<S, E> implements Step<S, E> {
-
-    protected String label = null;
-    protected String id = Traverser.Admin.HALT;
-    protected Traversal.Admin traversal;
-    protected ExpandableStepIterator<S> starts;
-    protected Traverser<E> nextEnd = null;
-    protected boolean traverserStepIdSetByChild = false; // TODO: Step.teleport(traverser, step)
-
-    protected Step<?, S> previousStep = EmptyStep.instance();
-    protected Step<E, ?> nextStep = EmptyStep.instance();
-
-    public AbstractStep(final Traversal.Admin traversal) {
-        this.traversal = traversal;
-        this.starts = new ExpandableStepIterator<S>((Step) this);
-    }
-
-    @Override
-    public void setId(final String id) {
-        Objects.nonNull(id);
-        this.id = id;
-    }
-
-    @Override
-    public String getId() {
-        return this.id;
-    }
-
-    @Override
-    public void setLabel(final String label) {
-        Objects.nonNull(label);
-        this.label = label;
-    }
-
-    @Override
-    public Optional<String> getLabel() {
-        return Optional.ofNullable(this.label);
-    }
-
-    @Override
-    public void reset() {
-        this.starts.clear();
-        this.nextEnd = null;
-    }
-
-    @Override
-    public void addStarts(final Iterator<Traverser<S>> starts) {
-        this.starts.add((Iterator) starts);
-    }
-
-    @Override
-    public void addStart(final Traverser<S> start) {
-        this.starts.add((Traverser.Admin<S>) start);
-    }
-
-    @Override
-    public void setPreviousStep(final Step<?, S> step) {
-        this.previousStep = step;
-    }
-
-    @Override
-    public Step<?, S> getPreviousStep() {
-        return this.previousStep;
-    }
-
-    @Override
-    public void setNextStep(final Step<E, ?> step) {
-        this.nextStep = step;
-    }
-
-    @Override
-    public Step<E, ?> getNextStep() {
-        return this.nextStep;
-    }
-
-    @Override
-    public Traverser<E> next() {
-        if (null != this.nextEnd) {
-            try {
-                return this.prepareTraversalForNextStep(this.nextEnd);
-            } finally {
-                this.nextEnd = null;
-            }
-        } else {
-            while (true) {
-                final Traverser<E> traverser = this.processNextStart();
-                if (0 != traverser.bulk()) {
-                    return this.prepareTraversalForNextStep(traverser);
-                }
-            }
-        }
-    }
-
-    @Override
-    public boolean hasNext() {
-        if (null != this.nextEnd)
-            return true;
-        else {
-            try {
-                while (true) {
-                    this.nextEnd = this.processNextStart();
-                    if (0 != this.nextEnd.bulk())
-                        return true;
-                    else
-                        this.nextEnd = null;
-                }
-            } catch (final NoSuchElementException e) {
-                return false;
-            }
-        }
-    }
-
-    @Override
-    public <A, B> Traversal.Admin<A, B> getTraversal() {
-        return this.traversal;
-    }
-
-    @Override
-    public void setTraversal(final Traversal.Admin<?, ?> traversal) {
-        this.traversal = traversal;
-    }
-
-    protected abstract Traverser<E> processNextStart() throws NoSuchElementException;
-
-    public String toString() {
-        return TraversalHelper.makeStepString(this);
-    }
-
-    @Override
-    @SuppressWarnings("CloneDoesntDeclareCloneNotSupportedException")
-    public AbstractStep<S, E> clone() {
-        try {
-            final AbstractStep clone = (AbstractStep) super.clone();
-            clone.starts = new ExpandableStepIterator<S>(clone);
-            clone.previousStep = EmptyStep.instance();
-            clone.nextStep = EmptyStep.instance();
-            clone.nextEnd = null;
-            return clone;
-        } catch (CloneNotSupportedException e) {
-            throw new IllegalStateException(e.getMessage(), e);
-        }
-    }
-
-    private final Traverser<E> prepareTraversalForNextStep(final Traverser<E> traverser) {
-        if (!this.traverserStepIdSetByChild) ((Traverser.Admin<E>) traverser).setStepId(this.nextStep.getId());
-        if (null != this.label) traverser.path().addLabel(this.label);
-        return 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/ComparatorHolder.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/ComparatorHolder.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/ComparatorHolder.java
new file mode 100644
index 0000000..e8a7141
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/ComparatorHolder.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tinkerpop.gremlin.process.traversal.step;
+
+import java.util.Comparator;
+import java.util.List;
+
+/**
+ * @author Marko A. Rodriguez (http://markorodriguez.com)
+ */
+public interface ComparatorHolder<S> {
+
+    public void addComparator(final Comparator<S> comparator);
+
+    public List<Comparator<S>> getComparators();
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/4c97e964/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/ElementFunctionComparator.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/ElementFunctionComparator.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/ElementFunctionComparator.java
deleted file mode 100644
index c6a6702..0000000
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/ElementFunctionComparator.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.tinkerpop.gremlin.process.traversal.step;
-
-import org.apache.tinkerpop.gremlin.structure.Element;
-
-import java.io.Serializable;
-import java.util.Comparator;
-import java.util.function.Function;
-
-/**
- * @author Marko A. Rodriguez (http://markorodriguez.com)
- */
-public final class ElementFunctionComparator<V> implements Comparator<Element>, Serializable {
-
-    private final Function<Element, V> elementFunction;
-    private final Comparator<V> valueComparator;
-
-    public ElementFunctionComparator(final Function<Element, V> elementFunction, final Comparator<V> valueComparator) {
-        this.elementFunction = elementFunction;
-        this.valueComparator = valueComparator;
-    }
-
-    public Function<Element, V> getElementFunction() {
-        return this.elementFunction;
-    }
-
-    public Comparator<V> getValueComparator() {
-        return this.valueComparator;
-    }
-
-    @Override
-    public int compare(final Element elementA, final Element elementB) {
-        return this.valueComparator.compare(this.elementFunction.apply(elementA), this.elementFunction.apply(elementB));
-    }
-
-    @Override
-    public String toString() {
-        return this.valueComparator.toString() + "(" + this.elementFunction + ')';
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/4c97e964/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/ElementValueComparator.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/ElementValueComparator.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/ElementValueComparator.java
deleted file mode 100644
index 1062b9b..0000000
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/ElementValueComparator.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.tinkerpop.gremlin.process.traversal.step;
-
-import org.apache.tinkerpop.gremlin.structure.Element;
-
-import java.io.Serializable;
-import java.util.Comparator;
-
-/**
- * @author Marko A. Rodriguez (http://markorodriguez.com)
- */
-public final class ElementValueComparator<V> implements Comparator<Element>, Serializable {
-
-    private final String propertyKey;
-    private final Comparator<V> valueComparator;
-
-    public ElementValueComparator(final String propertyKey, final Comparator<V> valueComparator) {
-        this.propertyKey = propertyKey;
-        this.valueComparator = valueComparator;
-    }
-
-    public String getPropertyKey() {
-        return this.propertyKey;
-    }
-
-    public Comparator<V> getValueComparator() {
-        return this.valueComparator;
-    }
-
-    @Override
-    public int compare(final Element elementA, final Element elementB) {
-        return this.valueComparator.compare(elementA.value(this.propertyKey), elementB.value(this.propertyKey));
-    }
-
-    @Override
-    public String toString() {
-        return this.valueComparator.toString() + '(' + this.propertyKey + ')';
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/4c97e964/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/EmptyStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/EmptyStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/EmptyStep.java
deleted file mode 100644
index 3a3e9ed..0000000
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/EmptyStep.java
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.tinkerpop.gremlin.process.traversal.step;
-
-import org.apache.tinkerpop.gremlin.process.FastNoSuchElementException;
-import org.apache.tinkerpop.gremlin.process.Step;
-import org.apache.tinkerpop.gremlin.process.Traversal;
-import org.apache.tinkerpop.gremlin.process.Traverser;
-import org.apache.tinkerpop.gremlin.process.traversal.util.EmptyTraversal;
-import org.apache.tinkerpop.gremlin.process.traverser.TraverserRequirement;
-
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.Optional;
-import java.util.Set;
-
-/**
- * @author Marko A. Rodriguez (http://markorodriguez.com)
- */
-public final class EmptyStep<S, E> implements Step<S, E>, TraversalParent {
-
-    private static final EmptyStep INSTANCE = new EmptyStep<>();
-
-    public static <S, E> Step<S, E> instance() {
-        return INSTANCE;
-    }
-
-    private EmptyStep() {
-    }
-
-    @Override
-    public void addStarts(final Iterator<Traverser<S>> starts) {
-
-    }
-
-    @Override
-    public void addStart(final Traverser<S> start) {
-
-    }
-
-    @Override
-    public void setPreviousStep(final Step<?, S> step) {
-
-    }
-
-    @Override
-    public void reset() {
-
-    }
-
-    @Override
-    public Step<?, S> getPreviousStep() {
-        return INSTANCE;
-    }
-
-    @Override
-    public void setNextStep(final Step<E, ?> step) {
-
-    }
-
-    @Override
-    public Step<E, ?> getNextStep() {
-        return INSTANCE;
-    }
-
-    @Override
-    public <A, B> Traversal.Admin<A, B> getTraversal() {
-        return EmptyTraversal.instance();
-    }
-
-    @Override
-    public void setTraversal(final Traversal.Admin<?, ?> traversal) {
-
-    }
-
-    @Override
-    @SuppressWarnings("CloneDoesntCallSuperClone")
-    public EmptyStep<S, E> clone() {
-        return INSTANCE;
-    }
-
-    @Override
-    public Optional<String> getLabel() {
-        return Optional.empty();
-    }
-
-    @Override
-    public void setLabel(final String label) {
-
-    }
-
-    @Override
-    public void setId(final String id) {
-
-    }
-
-    @Override
-    public String getId() {
-        return Traverser.Admin.HALT;
-    }
-
-    @Override
-    public boolean hasNext() {
-        return false;
-    }
-
-    @Override
-    public Traverser<E> next() {
-        throw FastNoSuchElementException.instance();
-    }
-
-    @Override
-    public int hashCode() {
-        return -1691648095;
-    }
-
-    @Override
-    public boolean equals(final Object object) {
-        return object instanceof EmptyStep;
-    }
-
-    @Override
-    public Set<TraverserRequirement> getRequirements() {
-        return Collections.emptySet();
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/4c97e964/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/EngineDependent.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/EngineDependent.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/EngineDependent.java
index 7853fa7..cb1aeec 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/EngineDependent.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/EngineDependent.java
@@ -18,7 +18,7 @@
  */
 package org.apache.tinkerpop.gremlin.process.traversal.step;
 
-import org.apache.tinkerpop.gremlin.process.TraversalEngine;
+import org.apache.tinkerpop.gremlin.process.traversal.TraversalEngine;
 
 /**
  * @author Marko A. Rodriguez (http://markorodriguez.com)

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/4c97e964/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/ExpandableStepIterator.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/ExpandableStepIterator.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/ExpandableStepIterator.java
deleted file mode 100644
index 19ba213..0000000
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/ExpandableStepIterator.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.tinkerpop.gremlin.process.traversal.step;
-
-import org.apache.tinkerpop.gremlin.process.Step;
-import org.apache.tinkerpop.gremlin.process.Traverser;
-import org.apache.tinkerpop.gremlin.util.iterator.MultiIterator;
-import org.apache.tinkerpop.gremlin.process.util.TraverserSet;
-
-import java.io.Serializable;
-import java.util.Iterator;
-
-/**
- * @author Marko A. Rodriguez (http://markorodriguez.com)
- */
-public final class ExpandableStepIterator<E> implements Iterator<Traverser.Admin<E>>, Serializable {
-
-    private final TraverserSet<E> traverserSet = new TraverserSet<>();
-    private final MultiIterator<Traverser.Admin<E>> traverserIterators = new MultiIterator<>();
-    private final Step<?, E> hostStep;
-
-    public ExpandableStepIterator(final Step<?, E> hostStep) {
-        this.hostStep = hostStep;
-    }
-
-    @Override
-    public boolean hasNext() {
-        return !this.traverserSet.isEmpty() || this.hostStep.getPreviousStep().hasNext() || this.traverserIterators.hasNext();
-    }
-
-    @Override
-    public Traverser.Admin<E> next() {
-        if (!this.traverserSet.isEmpty())
-            return this.traverserSet.remove();
-        if (this.traverserIterators.hasNext())
-            return this.traverserIterators.next();
-        /////////////
-        if (this.hostStep.getPreviousStep().hasNext())
-            return (Traverser.Admin<E>) this.hostStep.getPreviousStep().next();
-        /////////////
-        return this.traverserSet.remove();
-    }
-
-    public void add(final Iterator<Traverser.Admin<E>> iterator) {
-        this.traverserIterators.addIterator(iterator);
-    }
-
-    public void add(final Traverser.Admin<E> traverser) {
-        this.traverserSet.add(traverser);
-    }
-
-    @Override
-    public String toString() {
-        return this.traverserSet.toString();
-    }
-
-    public void clear() {
-        this.traverserIterators.clear();
-        this.traverserSet.clear();
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/4c97e964/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/HasContainerHolder.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/HasContainerHolder.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/HasContainerHolder.java
new file mode 100644
index 0000000..cd7f493
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/HasContainerHolder.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tinkerpop.gremlin.process.traversal.step;
+
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.HasContainer;
+
+import java.util.List;
+
+/**
+ * @author Marko A. Rodriguez (http://markorodriguez.com)
+ */
+public interface HasContainerHolder {
+
+    public List<HasContainer> getHasContainers();
+
+    public void addHasContainer(final HasContainer hasContainer);
+}

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/4c97e964/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/Mutating.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/Mutating.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/Mutating.java
new file mode 100644
index 0000000..13ce032
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/Mutating.java
@@ -0,0 +1,28 @@
+/*
+ * 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;
+
+/**
+ * A marker interface for steps that modify the graph.
+ *
+ * @author Stephen Mallette (http://stephen.genoprime.com)
+ */
+public interface Mutating {
+}

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/4c97e964/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/Ranging.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/Ranging.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/Ranging.java
new file mode 100644
index 0000000..db205b6
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/Ranging.java
@@ -0,0 +1,30 @@
+/*
+ * 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;
+
+/**
+ * @author Marko A. Rodriguez (http://markorodriguez.com)
+ */
+public interface Ranging {
+
+    public long getLowRange();
+
+    public long getHighRange();
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/4c97e964/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/SideEffectCapable.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/SideEffectCapable.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/SideEffectCapable.java
new file mode 100644
index 0000000..786e161
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/SideEffectCapable.java
@@ -0,0 +1,28 @@
+/*
+ * 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;
+
+/**
+ * @author Marko A. Rodriguez (http://markorodriguez.com)
+ */
+public interface SideEffectCapable {
+
+    public String getSideEffectKey();
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/4c97e964/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/TraversalComparator.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/TraversalComparator.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/TraversalComparator.java
deleted file mode 100644
index df1ce3a..0000000
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/TraversalComparator.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.tinkerpop.gremlin.process.traversal.step;
-
-import org.apache.tinkerpop.gremlin.process.Traversal;
-import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalUtil;
-
-import java.io.Serializable;
-import java.util.Comparator;
-
-/**
- * @author Marko A. Rodriguez (http://markorodriguez.com)
- */
-public final class TraversalComparator<S, E> implements Comparator<S>, Serializable, Cloneable {
-
-    private Traversal.Admin<S, E> traversal;
-    private final Comparator<E> comparator;
-
-    public TraversalComparator(final Traversal.Admin<S, E> traversal, final Comparator<E> comparator) {
-        this.traversal = traversal;
-        this.comparator = comparator;
-    }
-
-    @Override
-    public String toString() {
-        return this.comparator.toString() + "(" + this.traversal + ")";
-    }
-
-    @Override
-    public int compare(final S start1, final S start2) {
-        return this.comparator.compare(TraversalUtil.apply(start1, this.traversal), TraversalUtil.apply(start2, this.traversal));
-    }
-
-    @Override
-    public TraversalComparator clone() throws CloneNotSupportedException {
-        final TraversalComparator clone = (TraversalComparator) super.clone();
-        clone.traversal = this.traversal.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/TraversalOptionParent.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/TraversalOptionParent.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/TraversalOptionParent.java
new file mode 100644
index 0000000..6eb60a2
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/TraversalOptionParent.java
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tinkerpop.gremlin.process.traversal.step;
+
+import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
+
+/**
+ * @author Marko A. Rodriguez (http://markorodriguez.com)
+ */
+public interface TraversalOptionParent<M, S, E> extends TraversalParent {
+
+    public static enum Pick {any, none}
+
+    public void addGlobalChildOption(final M pickToken, final Traversal.Admin<S, E> traversalOption);
+}

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/4c97e964/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/TraversalParent.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/TraversalParent.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/TraversalParent.java
index 2a24ad2..bd8ee99 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/TraversalParent.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/TraversalParent.java
@@ -18,9 +18,9 @@
  */
 package org.apache.tinkerpop.gremlin.process.traversal.step;
 
-import org.apache.tinkerpop.gremlin.process.Step;
-import org.apache.tinkerpop.gremlin.process.Traversal;
-import org.apache.tinkerpop.gremlin.process.traverser.TraverserRequirement;
+import org.apache.tinkerpop.gremlin.process.traversal.Step;
+import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
+import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
 
 import java.util.Collections;
 import java.util.EnumSet;

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/4c97e964/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/BranchStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/BranchStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/BranchStep.java
new file mode 100644
index 0000000..f49103d
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/BranchStep.java
@@ -0,0 +1,166 @@
+/*
+ * 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.branch;
+
+import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
+import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
+import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalOptionParent;
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.ComputerAwareStep;
+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.*;
+import java.util.stream.Collectors;
+
+/**
+ * @author Marko A. Rodriguez (http://markorodriguez.com)
+ */
+public class BranchStep<S, E, M> extends ComputerAwareStep<S, E> implements TraversalOptionParent<M, S, E> {
+
+    protected Traversal.Admin<S, M> branchTraversal;
+    protected Map<M, List<Traversal.Admin<S, E>>> traversalOptions = new HashMap<>();
+    private boolean first = true;
+
+    public BranchStep(final Traversal.Admin traversal) {
+        super(traversal);
+    }
+
+    public void setBranchTraversal(final Traversal.Admin<S, M> branchTraversal) {
+        this.branchTraversal = this.integrateChild(branchTraversal);
+    }
+
+    @Override
+    public void addGlobalChildOption(final M pickToken, final Traversal.Admin<S, E> traversalOption) {
+        if (this.traversalOptions.containsKey(pickToken))
+            this.traversalOptions.get(pickToken).add(traversalOption);
+        else
+            this.traversalOptions.put(pickToken, new ArrayList<>(Collections.singletonList(traversalOption)));
+        traversalOption.addStep(new EndStep(traversalOption));
+        this.integrateChild(traversalOption);
+    }
+
+    @Override
+    public Set<TraverserRequirement> getRequirements() {
+        return this.getSelfAndChildRequirements();
+    }
+
+    @Override
+    public List<Traversal.Admin<S, E>> getGlobalChildren() {
+        return Collections.unmodifiableList(this.traversalOptions.values().stream()
+                .flatMap(list -> list.stream())
+                .collect(Collectors.toList()));
+    }
+
+    @Override
+    public List<Traversal.Admin<S, M>> getLocalChildren() {
+        return Collections.singletonList(this.branchTraversal);
+    }
+
+    @Override
+    protected Iterator<Traverser<E>> standardAlgorithm() {
+        while (true) {
+            if (!this.first) {
+                for (final List<Traversal.Admin<S, E>> options : this.traversalOptions.values()) {
+                    for (final Traversal.Admin<S, E> option : options) {
+                        if (option.hasNext())
+                            return option.getEndStep();
+                    }
+                }
+            }
+            this.first = false;
+            ///
+            final Traverser.Admin<S> start = this.starts.next();
+            final M choice = TraversalUtil.apply(start, this.branchTraversal);
+            final List<Traversal.Admin<S, E>> branch = this.traversalOptions.containsKey(choice) ? this.traversalOptions.get(choice) : this.traversalOptions.get(Pick.none);
+            if (null != branch) {
+                branch.forEach(traversal -> {
+                    traversal.reset();
+                    traversal.addStart(start.split());
+                });
+            }
+            if (choice != Pick.any) {
+                final List<Traversal.Admin<S, E>> anyBranch = this.traversalOptions.get(Pick.any);
+                if (null != anyBranch)
+                    anyBranch.forEach(traversal -> {
+                        traversal.reset();
+                        traversal.addStart(start.split());
+                    });
+            }
+        }
+    }
+
+    @Override
+    protected Iterator<Traverser<E>> computerAlgorithm() {
+        final List<Traverser<E>> ends = new ArrayList<>();
+        final Traverser.Admin<S> start = this.starts.next();
+        final M choice = TraversalUtil.apply(start, this.branchTraversal);
+        final List<Traversal.Admin<S, E>> branch = this.traversalOptions.containsKey(choice) ? this.traversalOptions.get(choice) : this.traversalOptions.get(Pick.none);
+        if (null != branch) {
+            branch.forEach(traversal -> {
+                final Traverser.Admin<E> split = (Traverser.Admin<E>) start.split();
+                split.setStepId(traversal.getStartStep().getId());
+                ends.add(split);
+            });
+        }
+        if (choice != Pick.any) {
+            final List<Traversal.Admin<S, E>> anyBranch = this.traversalOptions.get(Pick.any);
+            if (null != anyBranch) {
+                anyBranch.forEach(traversal -> {
+                    final Traverser.Admin<E> split = (Traverser.Admin<E>) start.split();
+                    split.setStepId(traversal.getStartStep().getId());
+                    ends.add(split);
+                });
+            }
+        }
+        return ends.iterator();
+    }
+
+    @Override
+    public BranchStep<S, E, M> clone() {
+        final BranchStep<S, E, M> clone = (BranchStep<S, E, M>) super.clone();
+        clone.traversalOptions = new HashMap<>(this.traversalOptions.size());
+        for (final Map.Entry<M, List<Traversal.Admin<S, E>>> entry : this.traversalOptions.entrySet()) {
+            final List<Traversal.Admin<S, E>> traversals = entry.getValue();
+            if (traversals.size() > 0) {
+                final List<Traversal.Admin<S, E>> clonedTraversals = clone.traversalOptions.compute(entry.getKey(), (k, v) ->
+                        (v == null) ? new ArrayList<>(traversals.size()) : v);
+                for (final Traversal.Admin<S, E> traversal : traversals) {
+                    final Traversal.Admin<S, E> clonedTraversal = traversal.clone();
+                    clonedTraversals.add(clonedTraversal);
+                    clone.integrateChild(clonedTraversal);
+                }
+            }
+        }
+        clone.branchTraversal = this.branchTraversal.clone();
+        clone.integrateChild(clone.branchTraversal);
+        return clone;
+    }
+
+    @Override
+    public String toString() {
+        return TraversalHelper.makeStepString(this, this.branchTraversal, this.traversalOptions);
+    }
+
+    @Override
+    public void reset() {
+        super.reset();
+        this.first = true;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/4c97e964/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/ChooseStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/ChooseStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/ChooseStep.java
new file mode 100644
index 0000000..09af7e2
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/ChooseStep.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.branch;
+
+import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
+import org.apache.tinkerpop.gremlin.process.traversal.lambda.HasNextTraversal;
+
+/**
+ * A step which offers a choice of two or more Traversals to take.
+ *
+ * @author Joshua Shinavier (http://fortytwo.net)
+ * @author Marko A. Rodriguez (http://markorodriguez.com)
+ */
+public final class ChooseStep<S, E, M> extends BranchStep<S, E, M> {
+
+    public ChooseStep(final Traversal.Admin traversal, final Traversal.Admin<S, M> choiceTraversal) {
+        super(traversal);
+        this.setBranchTraversal(choiceTraversal);
+    }
+
+    public ChooseStep(final Traversal.Admin traversal, final Traversal.Admin<S, ?> predicateTraversal, final Traversal.Admin<S, E> trueChoice, final Traversal.Admin<S, E> falseChoice) {
+        this(traversal, new HasNextTraversal(predicateTraversal));
+        this.addGlobalChildOption((M) Boolean.TRUE, trueChoice);
+        this.addGlobalChildOption((M) Boolean.FALSE, falseChoice);
+    }
+
+    @Override
+    public void addGlobalChildOption(final M pickToken, final Traversal.Admin<S, E> traversalOption) {
+        if (Pick.any.equals(pickToken))
+            throw new IllegalArgumentException("Choose step can not have an any-option as only one option per traverser is allowed");
+        if (this.traversalOptions.containsKey(pickToken))
+            throw new IllegalArgumentException("Choose step can only have one traversal per pick token: " + pickToken);
+        super.addGlobalChildOption(pickToken, traversalOption);
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/4c97e964/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/LocalStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/LocalStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/LocalStep.java
new file mode 100644
index 0000000..2e5ba18
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/LocalStep.java
@@ -0,0 +1,87 @@
+/*
+ * 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.branch;
+
+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.TraversalParent;
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.AbstractStep;
+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.NoSuchElementException;
+import java.util.Set;
+
+/**
+ * @author Marko A. Rodriguez (http://markorodriguez.com)
+ */
+public final class LocalStep<S, E> extends AbstractStep<S, E> implements TraversalParent {
+
+    private Traversal.Admin<S, E> localTraversal;
+    private boolean first = true;
+
+    public LocalStep(final Traversal.Admin traversal, final Traversal.Admin<S, E> localTraversal) {
+        super(traversal);
+        this.localTraversal = this.integrateChild(localTraversal);
+    }
+
+    @Override
+    public LocalStep<S, E> clone() {
+        final LocalStep<S, E> clone = (LocalStep<S, E>) super.clone();
+        clone.localTraversal = clone.integrateChild(this.localTraversal.clone());
+        clone.first = true;
+        return clone;
+    }
+
+    @Override
+    public String toString() {
+        return TraversalHelper.makeStepString(this, this.localTraversal);
+    }
+
+    @Override
+    public List<Traversal.Admin<S, E>> getLocalChildren() {
+        return Collections.singletonList(this.localTraversal);
+    }
+
+    @Override
+    public Set<TraverserRequirement> getRequirements() {
+        return this.localTraversal.getTraverserRequirements();
+    }
+
+    @Override
+    protected Traverser<E> processNextStart() throws NoSuchElementException {
+        if (this.first) {
+            this.first = false;
+            this.localTraversal.addStart(this.starts.next());
+        }
+        while (true) {
+            if (this.localTraversal.hasNext())
+                return this.localTraversal.getEndStep().next();
+            else if (this.starts.hasNext()) {
+                this.localTraversal.reset();
+                this.localTraversal.addStart(this.starts.next());
+            } 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/branch/RepeatStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/RepeatStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/RepeatStep.java
new file mode 100644
index 0000000..3dc2941
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/RepeatStep.java
@@ -0,0 +1,263 @@
+/*
+ * 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.branch;
+
+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.TraversalParent;
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.ComputerAwareStep;
+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.util.iterator.IteratorUtils;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.NoSuchElementException;
+import java.util.Set;
+
+/**
+ * @author Marko A. Rodriguez (http://markorodriguez.com)
+ */
+public final class RepeatStep<S> extends ComputerAwareStep<S, S> implements TraversalParent {
+
+    private Traversal.Admin<S, S> repeatTraversal = null;
+    private Traversal.Admin<S, ?> untilTraversal = null;
+    private Traversal.Admin<S, ?> emitTraversal = null;
+    public boolean untilFirst = false;
+    public boolean emitFirst = false;
+
+    public RepeatStep(final Traversal.Admin traversal) {
+        super(traversal);
+    }
+
+    @Override
+    public Set<TraverserRequirement> getRequirements() {
+        final Set<TraverserRequirement> requirements = this.getSelfAndChildRequirements(TraverserRequirement.BULK);
+        if (requirements.contains(TraverserRequirement.SINGLE_LOOP))
+            requirements.add(TraverserRequirement.NESTED_LOOP);
+        requirements.add(TraverserRequirement.SINGLE_LOOP);
+        return requirements;
+    }
+
+    @SuppressWarnings("unchecked")
+    public void setRepeatTraversal(final Traversal.Admin<S, S> repeatTraversal) {
+        this.repeatTraversal = repeatTraversal; // .clone();
+        this.repeatTraversal.addStep(new RepeatEndStep(this.repeatTraversal));
+        this.integrateChild(this.repeatTraversal);
+    }
+
+    public void setUntilTraversal(final Traversal.Admin<S, ?> untilTraversal) {
+        if (null == this.repeatTraversal) this.untilFirst = true;
+        this.untilTraversal = this.integrateChild(untilTraversal);
+    }
+
+    public void setEmitTraversal(final Traversal.Admin<S, ?> emitTraversal) {
+        if (null == this.repeatTraversal) this.emitFirst = true;
+        this.emitTraversal = this.integrateChild(emitTraversal);
+    }
+
+    public List<Traversal.Admin<S, S>> getGlobalChildren() {
+        return null == this.repeatTraversal ? Collections.emptyList() : Collections.singletonList(this.repeatTraversal);
+    }
+
+    public List<Traversal.Admin<S, ?>> getLocalChildren() {
+        final List<Traversal.Admin<S, ?>> list = new ArrayList<>();
+        if (null != this.untilTraversal)
+            list.add(this.untilTraversal);
+        if (null != this.emitTraversal)
+            list.add(this.emitTraversal);
+        return list;
+    }
+
+    public final boolean doUntil(final Traverser.Admin<S> traverser, boolean utilFirst) {
+        return utilFirst == this.untilFirst && null != this.untilTraversal && TraversalUtil.test(traverser, this.untilTraversal);
+    }
+
+    public final boolean doEmit(final Traverser.Admin<S> traverser, boolean emitFirst) {
+        return emitFirst == this.emitFirst && null != this.emitTraversal && TraversalUtil.test(traverser, this.emitTraversal);
+    }
+
+    @Override
+    public String toString() {
+        if (this.untilFirst && this.emitFirst)
+            return TraversalHelper.makeStepString(this, untilString(), emitString(), this.repeatTraversal);
+        else if (this.emitFirst)
+            return TraversalHelper.makeStepString(this, emitString(), this.repeatTraversal, untilString());
+        else if (this.untilFirst)
+            return TraversalHelper.makeStepString(this, untilString(), this.repeatTraversal, emitString());
+        else
+            return TraversalHelper.makeStepString(this, this.repeatTraversal, untilString(), emitString());
+    }
+
+    private final String untilString() {
+        return null == this.untilTraversal ? "until(false)" : "until(" + this.untilTraversal + ')';
+    }
+
+    private final String emitString() {
+        return null == this.emitTraversal ? "emit(false)" : "emit(" + this.emitTraversal + ')';
+    }
+
+    /////////////////////////
+
+    @Override
+    public RepeatStep<S> clone() {
+        final RepeatStep<S> clone = (RepeatStep<S>) super.clone();
+        clone.repeatTraversal = clone.integrateChild(this.repeatTraversal.clone());
+        if (null != this.untilTraversal)
+            clone.untilTraversal = clone.integrateChild(this.untilTraversal.clone());
+        if (null != this.emitTraversal)
+            clone.emitTraversal = clone.integrateChild(this.emitTraversal.clone());
+        return clone;
+    }
+
+    @Override
+    protected Iterator<Traverser<S>> standardAlgorithm() throws NoSuchElementException {
+        while (true) {
+            if (this.repeatTraversal.getEndStep().hasNext()) {
+                return this.repeatTraversal.getEndStep();
+            } else {
+                final Traverser.Admin<S> start = this.starts.next();
+                if (doUntil(start, true)) {
+                    start.resetLoops();
+                    return IteratorUtils.of(start);
+                }
+                this.repeatTraversal.addStart(start);
+                if (doEmit(start, true)) {
+                    final Traverser.Admin<S> emitSplit = start.split();
+                    emitSplit.resetLoops();
+                    return IteratorUtils.of(emitSplit);
+                }
+            }
+        }
+    }
+
+    @Override
+    protected Iterator<Traverser<S>> computerAlgorithm() throws NoSuchElementException {
+        final Traverser.Admin<S> start = this.starts.next();
+        if (doUntil(start, true)) {
+            start.resetLoops();
+            start.setStepId(this.getNextStep().getId());
+            return IteratorUtils.of(start);
+        } else {
+            start.setStepId(this.repeatTraversal.getStartStep().getId());
+            if (doEmit(start, true)) {
+                final Traverser.Admin<S> emitSplit = start.split();
+                emitSplit.resetLoops();
+                emitSplit.setStepId(this.getNextStep().getId());
+                return IteratorUtils.of(start, emitSplit);
+            } else {
+                return IteratorUtils.of(start);
+            }
+        }
+    }
+
+    /////////////////////////
+
+    public static <A, B, C extends Traversal<A, B>> C addRepeatToTraversal(final C traversal, final Traversal.Admin<B, B> repeatTraversal) {
+        final Step<?, B> step = traversal.asAdmin().getEndStep();
+        if (step instanceof RepeatStep && null == ((RepeatStep) step).repeatTraversal) {
+            ((RepeatStep<B>) step).setRepeatTraversal(repeatTraversal);
+        } else {
+            final RepeatStep<B> repeatStep = new RepeatStep<>(traversal.asAdmin());
+            repeatStep.setRepeatTraversal(repeatTraversal);
+            traversal.asAdmin().addStep(repeatStep);
+        }
+        return traversal;
+    }
+
+    public static <A, B, C extends Traversal<A, B>> C addUntilToTraversal(final C traversal, final Traversal.Admin<B, ?> untilPredicate) {
+        final Step<?, B> step = traversal.asAdmin().getEndStep();
+        if (step instanceof RepeatStep && null == ((RepeatStep) step).untilTraversal) {
+            ((RepeatStep<B>) step).setUntilTraversal(untilPredicate);
+        } else {
+            final RepeatStep<B> repeatStep = new RepeatStep<>(traversal.asAdmin());
+            repeatStep.setUntilTraversal(untilPredicate);
+            traversal.asAdmin().addStep(repeatStep);
+        }
+        return traversal;
+    }
+
+    public static <A, B, C extends Traversal<A, B>> C addEmitToTraversal(final C traversal, final Traversal.Admin<B, ?> emitPredicate) {
+        final Step<?, B> step = traversal.asAdmin().getEndStep();
+        if (step instanceof RepeatStep && null == ((RepeatStep) step).emitTraversal) {
+            ((RepeatStep<B>) step).setEmitTraversal(emitPredicate);
+        } else {
+            final RepeatStep<B> repeatStep = new RepeatStep<>(traversal.asAdmin());
+            repeatStep.setEmitTraversal(emitPredicate);
+            traversal.asAdmin().addStep(repeatStep);
+        }
+        return traversal;
+    }
+
+    ///////////////////////////////////
+
+    public class RepeatEndStep extends ComputerAwareStep<S, S> {
+
+        public RepeatEndStep(final Traversal.Admin traversal) {
+            super(traversal);
+        }
+
+        @Override
+        protected Iterator<Traverser<S>> standardAlgorithm() throws NoSuchElementException {
+            while (true) {
+                final Traverser.Admin<S> start = this.starts.next();
+                start.incrLoops(this.getId());
+                if (doUntil(start, false)) {
+                    start.resetLoops();
+                    return IteratorUtils.of(start);
+                } else {
+                    if (!RepeatStep.this.untilFirst && !RepeatStep.this.emitFirst)
+                        RepeatStep.this.repeatTraversal.addStart(start);
+                    else
+                        RepeatStep.this.addStart(start);
+                    if (doEmit(start, false)) {
+                        final Traverser.Admin<S> emitSplit = start.split();
+                        emitSplit.resetLoops();
+                        return IteratorUtils.of(emitSplit);
+                    }
+                }
+            }
+        }
+
+        @Override
+        protected Iterator<Traverser<S>> computerAlgorithm() throws NoSuchElementException {
+            final Traverser.Admin<S> start = this.starts.next();
+            start.incrLoops(RepeatStep.this.getId());
+            if (doUntil(start, false)) {
+                start.resetLoops();
+                start.setStepId(RepeatStep.this.getNextStep().getId());
+                return IteratorUtils.of(start);
+            } else {
+                start.setStepId(RepeatStep.this.getId());
+                if (doEmit(start, false)) {
+                    final Traverser.Admin<S> emitSplit = start.split();
+                    emitSplit.resetLoops();
+                    emitSplit.setStepId(RepeatStep.this.getNextStep().getId());
+                    return IteratorUtils.of(start, emitSplit);
+                }
+                return IteratorUtils.of(start);
+            }
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/4c97e964/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/UnionStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/UnionStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/UnionStep.java
new file mode 100644
index 0000000..b74beca
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/UnionStep.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.branch;
+
+import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
+import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalOptionParent;
+import org.apache.tinkerpop.gremlin.process.traversal.lambda.ConstantTraversal;
+import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper;
+
+import java.util.Collections;
+
+/**
+ * @author Marko A. Rodriguez (http://markorodriguez.com)
+ */
+public final class UnionStep<S, E> extends BranchStep<S, E, TraversalOptionParent.Pick> {
+
+    public UnionStep(final Traversal.Admin traversal, final Traversal.Admin<?, E>... unionTraversals) {
+        super(traversal);
+        this.setBranchTraversal(new ConstantTraversal<>(Pick.any));
+        for (final Traversal.Admin<?, E> union : unionTraversals) {
+            this.addGlobalChildOption(Pick.any, (Traversal.Admin) union);
+        }
+    }
+
+    @Override
+    public void addGlobalChildOption(final Pick pickToken, final Traversal.Admin<S, E> traversalOption) {
+        if (Pick.any != pickToken)
+            throw new IllegalArgumentException("Union step only supports the any token: " + pickToken);
+        super.addGlobalChildOption(pickToken, traversalOption);
+    }
+
+    @Override
+    public String toString() {
+        return TraversalHelper.makeStepString(this, this.traversalOptions.getOrDefault(Pick.any, Collections.emptyList()));
+    }
+}

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/AndStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/AndStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/AndStep.java
new file mode 100644
index 0000000..0f1f19d
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/AndStep.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 AndStep<S> extends ConjunctionStep<S> implements TraversalParent {
+
+    public AndStep(final Traversal.Admin traversal, final Traversal.Admin<S, ?>... andTraversals) {
+        super(traversal, andTraversals);
+
+    }
+
+    public static final class AndMarker<S> extends ConjunctionMarker<S> {
+        public AndMarker(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/CoinStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/CoinStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/CoinStep.java
new file mode 100644
index 0000000..6d95875
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/CoinStep.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.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.Random;
+import java.util.Set;
+
+/**
+ * @author Marko A. Rodriguez (http://markorodriguez.com)
+ */
+public final class CoinStep<S> extends FilterStep<S> {
+
+    private static final Random RANDOM = new Random();
+    private final double probability;
+
+    public CoinStep(final Traversal.Admin traversal, final double probability) {
+        super(traversal);
+        this.probability = probability;
+    }
+
+    @Override
+    protected boolean filter(final Traverser.Admin<S> traverser) {
+        long newBulk = 0l;
+        for (int i = 0; i < traverser.bulk(); i++) {
+            if (this.probability >= RANDOM.nextDouble())
+                newBulk++;
+        }
+        if (0 == newBulk) return false;
+        traverser.setBulk(newBulk);
+        return true;
+    }
+
+    @Override
+    public String toString() {
+        return TraversalHelper.makeStepString(this, this.probability);
+    }
+
+    @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/ConjunctionStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/ConjunctionStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/ConjunctionStep.java
new file mode 100644
index 0000000..8d8b50e
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/ConjunctionStep.java
@@ -0,0 +1,193 @@
+/*
+ * 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.HasContainer;
+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.traverser.TraverserRequirement;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.NoSuchElementException;
+import java.util.Set;
+
+/**
+ * @author Marko A. Rodriguez (http://markorodriguez.com)
+ */
+public abstract class ConjunctionStep<S> extends AbstractStep<S, S> implements TraversalParent {
+
+    private List<Traversal.Admin<S, ?>> conjunctionTraversals;
+    private final boolean isAnd;
+
+    public ConjunctionStep(final Traversal.Admin traversal, final Traversal.Admin<S, ?>... conjunctionTraversals) {
+        super(traversal);
+        this.isAnd = this.getClass().equals(AndStep.class);
+        this.conjunctionTraversals = Arrays.asList(conjunctionTraversals);
+        for (final Traversal.Admin<S, ?> conjunctionTraversal : this.conjunctionTraversals) {
+            this.integrateChild(conjunctionTraversal);
+        }
+    }
+
+    @Override
+    protected Traverser<S> processNextStart() throws NoSuchElementException {
+        while (true) {
+            final Traverser.Admin<S> start = this.starts.next();
+            boolean found = false;
+            for (final Traversal.Admin<S, ?> traversal : this.conjunctionTraversals) {
+                traversal.addStart(start.split());
+                found = traversal.hasNext();
+                traversal.reset();
+                if (this.isAnd) {
+                    if (!found)
+                        break;
+                } else if (found)
+                    break;
+            }
+            if (found) return start;
+        }
+    }
+
+    @Override
+    public Set<TraverserRequirement> getRequirements() {
+        return this.getSelfAndChildRequirements();
+    }
+
+    @Override
+    public List<Traversal.Admin<S, ?>> getLocalChildren() {
+        return Collections.unmodifiableList(this.conjunctionTraversals);
+    }
+
+    @Override
+    public ConjunctionStep<S> clone() {
+        final ConjunctionStep<S> clone = (ConjunctionStep<S>) super.clone();
+        clone.conjunctionTraversals = new ArrayList<>();
+        for (final Traversal.Admin<S, ?> conjunctionTraversal : this.conjunctionTraversals) {
+            clone.conjunctionTraversals.add(clone.integrateChild(conjunctionTraversal.clone()));
+        }
+        return clone;
+    }
+
+    @Override
+    public String toString() {
+        return TraversalHelper.makeStepString(this, this.conjunctionTraversals);
+    }
+
+    public boolean isConjunctionHasTree() {
+        for (final Traversal.Admin<S, ?> conjunctionTraversal : this.conjunctionTraversals) {
+            for (final Step<?, ?> step : conjunctionTraversal.getSteps()) {
+                if (step instanceof ConjunctionStep) {
+                    if (!((ConjunctionStep) step).isConjunctionHasTree())
+                        return false;
+                } else if (!(step instanceof HasStep))
+                    return false;
+            }
+        }
+        return true;
+    }
+
+    public ConjunctionTree getConjunctionHasTree() {
+        return new ConjunctionTree(this);
+    }
+
+
+    ////////
+
+    public static class ConjunctionMarker<S> extends AbstractStep<S, S> {
+
+        public ConjunctionMarker(final Traversal.Admin traversal) {
+            super(traversal);
+        }
+
+        @Override
+        protected Traverser<S> processNextStart() throws NoSuchElementException {
+            throw new IllegalStateException("This step should have been removed via a strategy: " + this.getClass().getCanonicalName());
+        }
+    }
+
+    ////////
+
+    public static class ConjunctionTree implements Iterable<ConjunctionTree.Entry> {
+
+        private final List<Entry> tree = new ArrayList<>();
+        private final boolean isAnd;
+
+        public ConjunctionTree(final ConjunctionStep<?> conjunctionStep) {
+            this.isAnd = conjunctionStep.isAnd;
+            for (final Traversal.Admin<?, ?> conjunctionTraversal : conjunctionStep.conjunctionTraversals) {
+                for (final Step<?, ?> step : conjunctionTraversal.getSteps()) {
+                    if (step instanceof HasStep) {
+                        (((HasStep<?>) step).getHasContainers()).forEach(container -> this.tree.add(new Entry(HasContainer.class, container)));
+                    } else if (step instanceof ConjunctionStep) {
+                        this.tree.add(new Entry(ConjunctionTree.class, ((ConjunctionStep) step).getConjunctionHasTree()));
+                    } else {
+                        throw new IllegalArgumentException("This conjunction supports more complex steps than HasStep");
+                    }
+                }
+            }
+        }
+
+        @Override
+        public String toString() {
+            return (this.isAnd ? "and" : "or") + this.tree.toString();
+        }
+
+        public boolean isAnd() {
+            return this.isAnd;
+        }
+
+        @Override
+        public Iterator<Entry> iterator() {
+            return this.tree.iterator();
+        }
+
+        public static class Entry {
+            private Class entryClass;
+            private Object entryValue;
+
+            public Entry(final Class entryClass, final Object entryValue) {
+                this.entryClass = entryClass;
+                this.entryValue = entryValue;
+            }
+
+            public <V> V getValue() {
+                return (V) this.entryValue;
+            }
+
+            public boolean isHasContainer() {
+                return this.entryClass.equals(HasContainer.class);
+            }
+
+            public boolean isConjunctionTree() {
+                return this.entryClass.equals(ConjunctionTree.class);
+            }
+
+            public String toString() {
+                return this.entryValue.toString();
+            }
+        }
+    }
+}

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/CyclicPathStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/CyclicPathStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/CyclicPathStep.java
new file mode 100644
index 0000000..e9c5dcf
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/CyclicPathStep.java
@@ -0,0 +1,46 @@
+/*
+ * 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 CyclicPathStep<S> extends FilterStep<S> {
+
+    public CyclicPathStep(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/DedupGlobalStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/DedupGlobalStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/DedupGlobalStep.java
new file mode 100644
index 0000000..9357e43
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/DedupGlobalStep.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.filter;
+
+import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
+import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
+import org.apache.tinkerpop.gremlin.process.traversal.lambda.IdentityTraversal;
+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.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * @author Marko A. Rodriguez (http://markorodriguez.com)
+ */
+public final class DedupGlobalStep<S> extends FilterStep<S> implements TraversalParent {
+
+    private Traversal.Admin<S, Object> dedupTraversal = new IdentityTraversal<>();
+    private Set<Object> duplicateSet = new HashSet<>();
+
+    public DedupGlobalStep(final Traversal.Admin traversal) {
+        super(traversal);
+    }
+
+    @Override
+    protected boolean filter(final Traverser.Admin<S> traverser) {
+        traverser.setBulk(1);
+        return this.duplicateSet.add(TraversalUtil.apply(traverser, this.dedupTraversal));
+    }
+
+
+    @Override
+    public List<Traversal<S, Object>> getLocalChildren() {
+        return Collections.singletonList(this.dedupTraversal);
+    }
+
+    @Override
+    public void addLocalChild(final Traversal.Admin dedupTraversal) {
+        this.dedupTraversal = this.integrateChild(dedupTraversal);
+    }
+
+    @Override
+    public DedupGlobalStep<S> clone() {
+        final DedupGlobalStep<S> clone = (DedupGlobalStep<S>) super.clone();
+        clone.duplicateSet = new HashSet<>();
+        clone.dedupTraversal = clone.integrateChild(this.dedupTraversal.clone());
+        return clone;
+    }
+
+    @Override
+    public void reset() {
+        super.reset();
+        this.duplicateSet.clear();
+    }
+
+    @Override
+    public String toString() {
+        return TraversalHelper.makeStepString(this, this.dedupTraversal);
+    }
+
+    @Override
+    public Set<TraverserRequirement> getRequirements() {
+        return this.getSelfAndChildRequirements(TraverserRequirement.SIDE_EFFECTS);
+    }
+}

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/ExceptStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/ExceptStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/ExceptStep.java
new file mode 100644
index 0000000..332037e
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/ExceptStep.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 ExceptStep<S> extends FilterStep<S> {
+
+    private final String sideEffectKeyOrPathLabel;
+    private final Collection<S> exceptCollection;
+    private final S exceptObject;
+    private final short choice;
+
+    public ExceptStep(final Traversal.Admin traversal, final String sideEffectKeyOrPathLabel) {
+        super(traversal);
+        this.sideEffectKeyOrPathLabel = sideEffectKeyOrPathLabel;
+        this.exceptCollection = null;
+        this.exceptObject = null;
+        this.choice = 0;
+    }
+
+    public ExceptStep(final Traversal.Admin traversal, final Collection<S> exceptionCollection) {
+        super(traversal);
+        this.sideEffectKeyOrPathLabel = null;
+        this.exceptCollection = exceptionCollection;
+        this.exceptObject = null;
+        this.choice = 1;
+    }
+
+    public ExceptStep(final Traversal.Admin traversal, final S exceptionObject) {
+        super(traversal);
+        this.sideEffectKeyOrPathLabel = null;
+        this.exceptCollection = null;
+        this.exceptObject = exceptionObject;
+        this.choice = 2;
+    }
+
+    @Override
+    protected boolean filter(final Traverser.Admin<S> traverser) {
+        switch (this.choice) {
+            case 0: {
+                final Object except = traverser.asAdmin().getSideEffects().exists(this.sideEffectKeyOrPathLabel) ?
+                        traverser.sideEffects(this.sideEffectKeyOrPathLabel) :
+                        traverser.path(this.sideEffectKeyOrPathLabel);
+                return except instanceof Collection ?
+                        !((Collection) except).contains(traverser.get()) :
+                        !except.equals(traverser.get());
+            }
+            case 1:
+                return !this.exceptCollection.contains(traverser.get());
+            default:
+                return !this.exceptObject.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());
+    }
+}