You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tinkerpop.apache.org by sp...@apache.org on 2015/08/25 15:06:11 UTC

[14/17] incubator-tinkerpop git commit: Revert "Revert "Merge remote-tracking branch 'origin' into tp30""

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/ae644951/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/RangeLocalStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/RangeLocalStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/RangeLocalStep.java
index 773a48b..26e7264 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/RangeLocalStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/RangeLocalStep.java
@@ -68,13 +68,15 @@ public final class RangeLocalStep<S> extends MapStep<S, S> {
     static <S> S applyRange(final S start, final long low, final long high) {
         if (start instanceof Map) {
             return (S) applyRangeMap((Map) start, low, high);
-        } else if (start instanceof Collection) {
-            return (S) applyRangeCollection((Collection) start, low, high);
+        } else if (start instanceof Iterable) {
+            return (S) applyRangeIterable((Iterable) start, low, high);
         }
         return start;
     }
 
-    /** Extracts specified range of elements from a Map. */
+    /**
+     * Extracts specified range of elements from a Map.
+     */
     private static Map applyRangeMap(final Map map, final long low, final long high) {
         final long capacity = (high != -1 ? high : map.size()) - low;
         final Map result = new LinkedHashMap((int) Math.min(capacity, map.size()));
@@ -91,8 +93,10 @@ public final class RangeLocalStep<S> extends MapStep<S, S> {
         return result;
     }
 
-    /** Extracts specified range of elements from a Collection. */
-    private static Object applyRangeCollection(final Collection collection, final long low, final long high) {
+    /**
+     * Extracts specified range of elements from a Collection.
+     */
+    private static Object applyRangeIterable(final Iterable<Object> iterable, final long low, final long high) {
         // See if we only want a single item.  It is also possible that we will allow more than one item, but that the
         // incoming container is only capable of producing a single item.  In that case, we will still emit a
         // container.  This allows the result type to be predictable based on the step arguments.  It also allows us to
@@ -100,10 +104,10 @@ public final class RangeLocalStep<S> extends MapStep<S, S> {
         boolean single = high != -1 ? (high - low == 1) : false;
 
         final Collection resultCollection =
-            single ? null : (collection instanceof Set) ? new LinkedHashSet() : new LinkedList();
+                single ? null : (iterable instanceof Set) ? new LinkedHashSet() : new LinkedList();
         Object result = single ? null : resultCollection;
         long c = 0L;
-        for (final Object item : collection) {
+        for (final Object item : iterable) {
             if (c >= low) {
                 if (c < high || high == -1) {
                     if (single) {

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/ae644951/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/TailLocalStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/TailLocalStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/TailLocalStep.java
index 43f6d9d..ea678a5 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/TailLocalStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/TailLocalStep.java
@@ -19,10 +19,12 @@
 
 package org.apache.tinkerpop.gremlin.process.traversal.step.map;
 
+import org.apache.tinkerpop.gremlin.process.traversal.Path;
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
 import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
+import org.apache.tinkerpop.gremlin.util.iterator.IteratorUtils;
 
 import java.util.Collection;
 import java.util.Collections;
@@ -50,7 +52,9 @@ public final class TailLocalStep<S> extends MapStep<S, S> {
         final long high =
                 start instanceof Map ? ((Map) start).size() :
                         start instanceof Collection ? ((Collection) start).size() :
-                                this.limit;
+                                start instanceof Path ? ((Path) start).size() :
+                                        start instanceof Iterable ? IteratorUtils.count((Iterable) start) :
+                                                this.limit;
         final long low = high - this.limit;
         final S result = RangeLocalStep.applyRange(start, low, high);
         return result;

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/ae644951/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GraphStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GraphStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GraphStep.java
index 1cfdbee..b0472b2 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GraphStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GraphStep.java
@@ -29,6 +29,7 @@ import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
 import org.apache.tinkerpop.gremlin.util.iterator.EmptyIterator;
 
 import java.util.Arrays;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.Iterator;
 import java.util.function.Supplier;
@@ -46,11 +47,10 @@ public class GraphStep<S extends Element> extends StartStep<S> implements Engine
     public GraphStep(final Traversal.Admin traversal, final Class<S> returnClass, final Object... ids) {
         super(traversal);
         this.returnClass = returnClass;
-        this.ids = ids;
-
+        this.ids = (ids.length == 1 && ids[0] instanceof Collection) ? ((Collection) ids[0]).toArray(new Object[((Collection) ids[0]).size()]) : ids;
         this.iteratorSupplier = () -> (Iterator<S>) (Vertex.class.isAssignableFrom(this.returnClass) ?
-                    this.getTraversal().getGraph().get().vertices(this.ids) :
-                    this.getTraversal().getGraph().get().edges(this.ids));
+                this.getTraversal().getGraph().get().vertices(this.ids) :
+                this.getTraversal().getGraph().get().edges(this.ids));
     }
 
     public String toString() {
@@ -85,6 +85,10 @@ public class GraphStep<S extends Element> extends StartStep<S> implements Engine
     public void onEngine(final TraversalEngine traversalEngine) {
         if (traversalEngine.isComputer()) {
             this.iteratorSupplier = Collections::emptyIterator;
+            for(int i=0; i<this.ids.length; i++) {    // if this is going to OLAP, convert to ids so you don't serialize elements
+                if(this.ids[i] instanceof Element)
+                    this.ids[i] = ((Element)this.ids[i]).id();
+            }
         }
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/ae644951/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/AbstractStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/AbstractStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/AbstractStep.java
index e141e61..4d9b7d2 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/AbstractStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/AbstractStep.java
@@ -40,8 +40,8 @@ public abstract class AbstractStep<S, E> implements Step<S, E> {
     protected String id = Traverser.Admin.HALT;
     protected Traversal.Admin traversal;
     protected ExpandableStepIterator<S> starts;
-    protected Traverser<E> nextEnd = null;
-    protected boolean traverserStepIdSetByChild = false;
+    protected Traverser.Admin<E> nextEnd = null;
+    protected boolean traverserStepIdAndLabelsSetByChild = false;
 
     protected Step<?, S> previousStep = EmptyStep.instance();
     protected Step<E, ?> nextStep = EmptyStep.instance();
@@ -123,7 +123,7 @@ public abstract class AbstractStep<S, E> implements Step<S, E> {
             }
         } else {
             while (true) {
-                final Traverser<E> traverser = this.processNextStart();
+                final Traverser.Admin<E> traverser = (Traverser.Admin<E>) this.processNextStart();
                 if (null != traverser.get() && 0 != traverser.bulk())
                     return this.prepareTraversalForNextStep(traverser);
             }
@@ -137,7 +137,7 @@ public abstract class AbstractStep<S, E> implements Step<S, E> {
         else {
             try {
                 while (true) {
-                    this.nextEnd = this.processNextStart();
+                    this.nextEnd = (Traverser.Admin<E>) this.processNextStart();
                     if (null != this.nextEnd.get() && 0 != this.nextEnd.bulk())
                         return true;
                     else
@@ -197,9 +197,11 @@ public abstract class AbstractStep<S, E> implements Step<S, E> {
         return result;
     }
 
-    private final Traverser<E> prepareTraversalForNextStep(final Traverser<E> traverser) {
-        if (!this.traverserStepIdSetByChild) ((Traverser.Admin<E>) traverser).setStepId(this.nextStep.getId());
-        if (!this.labels.isEmpty()) this.labels.forEach(label -> traverser.path().addLabel(label));
+    private final Traverser.Admin<E> prepareTraversalForNextStep(final Traverser.Admin<E> traverser) {
+        if (!this.traverserStepIdAndLabelsSetByChild) {
+            traverser.setStepId(this.nextStep.getId());
+            traverser.addLabels(this.labels);
+        }
         return traverser;
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/ae644951/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/ComputerAwareStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/ComputerAwareStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/ComputerAwareStep.java
index a8cc2d3..2c7ecc5 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/ComputerAwareStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/ComputerAwareStep.java
@@ -44,13 +44,13 @@ public abstract class ComputerAwareStep<S, E> extends AbstractStep<S, E> impleme
         while (true) {
             if (this.previousIterator.hasNext())
                 return this.previousIterator.next();
-            this.previousIterator = this.traverserStepIdSetByChild ? this.computerAlgorithm() : this.standardAlgorithm();
+            this.previousIterator = this.traverserStepIdAndLabelsSetByChild ? this.computerAlgorithm() : this.standardAlgorithm();
         }
     }
 
     @Override
     public void onEngine(final TraversalEngine engine) {
-        this.traverserStepIdSetByChild = engine.isComputer();
+        this.traverserStepIdAndLabelsSetByChild = engine.isComputer();
     }
 
     @Override
@@ -75,8 +75,10 @@ public abstract class ComputerAwareStep<S, E> extends AbstractStep<S, E> impleme
         @Override
         protected Traverser<S> processNextStart() throws NoSuchElementException {
             final Traverser.Admin<S> start = this.starts.next();
-            if (this.traverserStepIdSetByChild)
-                start.setStepId(((ComputerAwareStep)this.getTraversal().getParent()).getNextStep().getId());
+            if (this.traverserStepIdAndLabelsSetByChild) {
+                start.setStepId(((ComputerAwareStep<?, ?>) this.getTraversal().getParent()).getNextStep().getId());
+                start.addLabels(((ComputerAwareStep<?, ?>) this.getTraversal().getParent()).getLabels());
+            }
             return start;
         }
 
@@ -87,7 +89,7 @@ public abstract class ComputerAwareStep<S, E> extends AbstractStep<S, E> impleme
 
         @Override
         public void onEngine(final TraversalEngine engine) {
-            this.traverserStepIdSetByChild = engine.isComputer();
+            this.traverserStepIdAndLabelsSetByChild = engine.isComputer();
         }
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/ae644951/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/EmptyPath.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/EmptyPath.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/EmptyPath.java
index 72d8c01..c40f228 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/EmptyPath.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/EmptyPath.java
@@ -47,6 +47,11 @@ public final class EmptyPath implements Path, Serializable {
     }
 
     @Override
+    public Path extend(final Set<String> labels) {
+        return this;
+    }
+
+    @Override
     public <A> A get(final String label) {
         throw Path.Exceptions.stepWithProvidedLabelDoesNotExist(label);
     }
@@ -62,11 +67,6 @@ public final class EmptyPath implements Path, Serializable {
     }
 
     @Override
-    public void addLabel(final String label) {
-
-    }
-
-    @Override
     public List<Object> objects() {
         return Collections.emptyList();
     }

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/ae644951/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/ImmutablePath.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/ImmutablePath.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/ImmutablePath.java
index 93f7623..1a916ca 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/ImmutablePath.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/ImmutablePath.java
@@ -20,6 +20,7 @@ package org.apache.tinkerpop.gremlin.process.traversal.step.util;
 
 import org.apache.tinkerpop.gremlin.process.traversal.Path;
 import org.apache.tinkerpop.gremlin.process.traversal.Pop;
+import org.apache.tinkerpop.gremlin.structure.Element;
 
 import java.io.Serializable;
 import java.util.ArrayList;
@@ -51,10 +52,6 @@ public class ImmutablePath implements Path, ImmutablePathImpl, Serializable, Clo
         return this;
     }
 
-    private ImmutablePath(final Object currentObject, final Set<String> currentLabels) {
-        this(TailPath.instance(), currentObject, currentLabels);
-    }
-
     private ImmutablePath(final ImmutablePathImpl previousPath, final Object currentObject, final Set<String> currentLabels) {
         this.previousPath = previousPath;
         this.currentObject = currentObject;
@@ -72,6 +69,14 @@ public class ImmutablePath implements Path, ImmutablePathImpl, Serializable, Clo
     }
 
     @Override
+    public Path extend(final Set<String> labels) {
+        final Set<String> temp = new LinkedHashSet<>();
+        temp.addAll(this.currentLabels);
+        temp.addAll(labels);
+        return new ImmutablePath(this.previousPath, this.currentObject, temp);
+    }
+
+    @Override
     public <A> A get(final int index) {
         return (this.size() - 1) == index ? (A) this.currentObject : this.previousPath.get(index);
     }
@@ -130,13 +135,8 @@ public class ImmutablePath implements Path, ImmutablePathImpl, Serializable, Clo
     }
 
     @Override
-    public void addLabel(final String label) {
-        this.currentLabels.add(label);
-    }
-
-    @Override
     public List<Object> objects() {
-        final List<Object> objectPath = new ArrayList<>();
+        final List<Object> objectPath = new ArrayList<>();    // TODO: optimize
         objectPath.addAll(this.previousPath.objects());
         objectPath.add(this.currentObject);
         return Collections.unmodifiableList(objectPath);
@@ -144,7 +144,7 @@ public class ImmutablePath implements Path, ImmutablePathImpl, Serializable, Clo
 
     @Override
     public List<Set<String>> labels() {
-        final List<Set<String>> labelPath = new ArrayList<>();
+        final List<Set<String>> labelPath = new ArrayList<>();   // TODO: optimize
         labelPath.addAll(this.previousPath.labels());
         labelPath.add(this.currentLabels);
         return Collections.unmodifiableList(labelPath);
@@ -155,6 +155,28 @@ public class ImmutablePath implements Path, ImmutablePathImpl, Serializable, Clo
         return this.objects().toString();
     }
 
+    @Override
+    public int hashCode() {
+        return this.objects().hashCode();
+    }
+
+    @Override
+    public boolean equals(final Object other) {
+        if (!(other instanceof Path))
+            return false;
+        final Path otherPath = (Path) other;
+        if (otherPath.size() != this.size())
+            return false;
+        for (int i = this.size() - 1; i >= 0; i--) {
+            if (!this.get(i).equals(otherPath.get(i)))
+                return false;
+            if (!this.labels().get(i).equals(otherPath.labels().get(i)))
+                return false;
+        }
+        return true;
+    }
+
+
     private static class TailPath implements Path, ImmutablePathImpl {
         private static final TailPath INSTANCE = new TailPath();
 
@@ -169,7 +191,12 @@ public class ImmutablePath implements Path, ImmutablePathImpl, Serializable, Clo
 
         @Override
         public Path extend(final Object object, final Set<String> labels) {
-            return new ImmutablePath(object, labels);
+            return new ImmutablePath(TailPath.instance(), object, labels);
+        }
+
+        @Override
+        public Path extend(final Set<String> labels) {
+            throw new UnsupportedOperationException("A head path can not have labels added to it");
         }
 
         @Override
@@ -206,11 +233,6 @@ public class ImmutablePath implements Path, ImmutablePathImpl, Serializable, Clo
         }
 
         @Override
-        public void addLabel(final String label) {
-            throw new UnsupportedOperationException("A head path can not have labels added to it");
-        }
-
-        @Override
         public List<Object> objects() {
             return Collections.emptyList();
         }
@@ -225,6 +247,7 @@ public class ImmutablePath implements Path, ImmutablePathImpl, Serializable, Clo
             return true;
         }
 
+        @SuppressWarnings("CloneDoesntCallSuperClone,CloneDoesntDeclareCloneNotSupportedException")
         @Override
         public TailPath clone() {
             return this;
@@ -235,13 +258,18 @@ public class ImmutablePath implements Path, ImmutablePathImpl, Serializable, Clo
         }
 
         @Override
-        public boolean equals(final Object object) {
-            return object instanceof TailPath;
+        public String toString() {
+            return Collections.emptyList().toString();
         }
 
         @Override
-        public String toString() {
-            return Collections.emptyList().toString();
+        public int hashCode() {
+            return Collections.emptyList().hashCode();
+        }
+
+        @Override
+        public boolean equals(final Object other) {
+            return other instanceof Path && ((Path) other).size() == 0;
         }
     }
 }

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/ae644951/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/MutablePath.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/MutablePath.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/MutablePath.java
index 67f9d57..0a35f90 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/MutablePath.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/MutablePath.java
@@ -24,6 +24,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.Pop;
 import java.io.Serializable;
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.Iterator;
 import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Set;
@@ -58,7 +59,9 @@ public class MutablePath implements Path, Serializable {
         clone.objects = new ArrayList<>();
         clone.labels = new ArrayList<>();*/
         clone.objects.addAll(this.objects);
-        clone.labels.addAll(this.labels);
+        for (final Set<String> labels : this.labels) {
+            clone.labels.add(new LinkedHashSet<>(labels));
+        }
         return clone;
     }
 
@@ -76,13 +79,19 @@ public class MutablePath implements Path, Serializable {
     }
 
     @Override
+    public Path extend(final Set<String> labels) {
+        this.labels.get(this.labels.size() - 1).addAll(labels);
+        return this;
+    }
+
+    @Override
     public <A> A get(int index) {
         return (A) this.objects.get(index);
     }
 
     @Override
     public <A> A get(final Pop pop, final String label) {
-        if(Pop.all == pop) {
+        if (Pop.all == pop) {
             if (this.hasLabel(label)) {
                 final Object object = this.get(label);
                 if (object instanceof List)
@@ -92,7 +101,7 @@ public class MutablePath implements Path, Serializable {
             } else {
                 return (A) Collections.emptyList();
             }
-        }  else {
+        } else {
             // Override default to avoid building temporary list, and to stop looking when we find the label.
             if (Pop.last == pop) {
                 for (int i = this.labels.size() - 1; i >= 0; i--) {
@@ -115,11 +124,6 @@ public class MutablePath implements Path, Serializable {
     }
 
     @Override
-    public void addLabel(final String label) {
-        this.labels.get(this.labels.size() - 1).add(label);
-    }
-
-    @Override
     public List<Object> objects() {
         return Collections.unmodifiableList(this.objects);
     }
@@ -130,7 +134,33 @@ public class MutablePath implements Path, Serializable {
     }
 
     @Override
+    public Iterator<Object> iterator() {
+        return this.objects.iterator();
+    }
+
+    @Override
     public String toString() {
         return this.objects.toString();
     }
+
+    @Override
+    public int hashCode() {
+        return this.objects.hashCode();
+    }
+
+    @Override
+    public boolean equals(final Object other) {
+        if (!(other instanceof Path))
+            return false;
+        final Path otherPath = (Path) other;
+        if (otherPath.size() != this.size())
+            return false;
+        for (int i = this.size() - 1; i >= 0; i--) {
+            if (!this.objects.get(i).equals(otherPath.get(i)))
+                return false;
+            if (!this.labels.get(i).equals(otherPath.labels().get(i)))
+                return false;
+        }
+        return true;
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/ae644951/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/DedupBijectionStrategy.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/DedupBijectionStrategy.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/DedupBijectionStrategy.java
deleted file mode 100644
index 712184d..0000000
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/DedupBijectionStrategy.java
+++ /dev/null
@@ -1,90 +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.strategy.optimization;
-
-import org.apache.tinkerpop.gremlin.process.traversal.Step;
-import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
-import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategy;
-import org.apache.tinkerpop.gremlin.process.traversal.step.filter.DedupGlobalStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.map.OrderGlobalStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.IdentityStep;
-import org.apache.tinkerpop.gremlin.process.traversal.strategy.AbstractTraversalStrategy;
-import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper;
-
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-/**
- * {@code DedupBijectionStrategy} does deduplication prior to a non-mutating bijective step if there is no
- * {@code by()}-modulation on {@code dedup()}. Given that {@link DedupGlobalStep} reduces the number of
- * objects in the stream, it is cheaper to dedup prior.
- * <p/>
- *
- * @author Marko A. Rodriguez (http://markorodriguez.com)
- * @author Daniel Kuppitz (http://gremlin.guru)
- * @example <pre>
- * __.order().dedup()            // is replaced by __.dedup().order()
- * </pre>
- */
-public final class DedupBijectionStrategy extends AbstractTraversalStrategy<TraversalStrategy.OptimizationStrategy> implements TraversalStrategy.OptimizationStrategy {
-
-    private static final DedupBijectionStrategy INSTANCE = new DedupBijectionStrategy();
-    private static final Set<Class<? extends OptimizationStrategy>> PRIORS = new HashSet<>();
-
-    static {
-        PRIORS.add(IdentityRemovalStrategy.class);
-    }
-
-
-    private DedupBijectionStrategy() {
-    }
-
-
-    @Override
-    public void apply(final Traversal.Admin<?, ?> traversal) {
-        if (!TraversalHelper.hasStepOfClass(DedupGlobalStep.class, traversal))
-            return;
-
-        final List<Step> steps = traversal.getSteps();
-        boolean exchangeable = false;
-        for (int i = steps.size() - 1; i >= 0; i--) {
-            final Step curr = steps.get(i);
-            if (exchangeable) {
-                if (curr instanceof OrderGlobalStep) {
-                    final Step next = curr.getNextStep();
-                    traversal.removeStep(next);
-                    traversal.addStep(i, next);
-                }
-                exchangeable = curr instanceof IdentityStep;
-            } else {
-                exchangeable = curr instanceof DedupGlobalStep && ((DedupGlobalStep) curr).getLocalChildren().isEmpty();
-            }
-        }
-    }
-
-    @Override
-    public Set<Class<? extends OptimizationStrategy>> applyPrior() {
-        return PRIORS;
-    }
-
-    public static DedupBijectionStrategy instance() {
-        return INSTANCE;
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/ae644951/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/FilterRankingStrategy.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/FilterRankingStrategy.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/FilterRankingStrategy.java
new file mode 100644
index 0000000..eaa69bc
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/FilterRankingStrategy.java
@@ -0,0 +1,176 @@
+/*
+ * 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.strategy.optimization;
+
+import org.apache.tinkerpop.gremlin.process.traversal.Step;
+import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
+import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.step.LambdaHolder;
+import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent;
+import org.apache.tinkerpop.gremlin.process.traversal.step.filter.*;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.OrderGlobalStep;
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.AbstractTraversalStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper;
+import org.apache.tinkerpop.gremlin.util.iterator.IteratorUtils;
+
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * FilterRankingStrategy reorders filter- and order-steps according to their rank. Labeled steps or lambda holders or
+ * steps that contain child traversals, that have labeled steps or lambda holders, will not be reordered.
+ * <p/>
+ * <table>
+ * <thead>
+ * <tr><th>Step</th><th>Rank</th></tr>
+ * </thead>
+ * <tbody>
+ * <tr><td>is(predicate)</td><td>1</td></tr>
+ * <tr><td>has(predicate)</td><td>2</td></tr>
+ * <tr><td>where(predicate)</td><td>3</td></tr>
+ * <tr><td>simplePath()</td><td>4</td></tr>
+ * <tr><td>cyclicPath()</td><td>4</td></tr>
+ * <tr><td>filter(traversal)</td><td>5</td></tr>
+ * <tr><td>where(traversal)</td><td>6</td></tr>
+ * <tr><td>or(...)</td><td>7</td></tr>
+ * <tr><td>and(...)</td><td>8</td></tr>
+ * <tr><td>dedup()</td><td>9</td></tr>
+ * <tr><td>order()</td><td>10</td></tr>
+ * </tbody>
+ * </table>
+ *
+ * @author Daniel Kuppitz (http://gremlin.guru)
+ * @author Marko A. Rodriguez (http://markorodriguez.com)
+ * @example <pre>
+ * __.order().dedup()                        // is replaced by __.dedup().order()
+ * __.dedup().filter(out()).has("value", 0)  // is replaced by __.has("value", 0).filter(out()).dedup()
+ * </pre>
+ */
+public final class FilterRankingStrategy extends AbstractTraversalStrategy<TraversalStrategy.OptimizationStrategy> implements TraversalStrategy.OptimizationStrategy {
+
+    private static final FilterRankingStrategy INSTANCE = new FilterRankingStrategy();
+    private static final Set<Class<? extends OptimizationStrategy>> PRIORS = new HashSet<>();
+
+    static {
+        PRIORS.add(IdentityRemovalStrategy.class);
+    }
+
+    private FilterRankingStrategy() {
+    }
+
+    @Override
+    public void apply(final Traversal.Admin<?, ?> traversal) {
+        boolean modified;
+        do {
+            modified = false;
+            final List<Step> steps = traversal.getSteps();
+            int prevRank = 0;
+            for (int i = steps.size() - 1; i >= 0; i--) {
+                final Step curr = steps.get(i);
+                final int rank = rank(curr);
+                if (prevRank > 0 && rank > prevRank) {
+                    final Step next = curr.getNextStep();
+                    traversal.removeStep(next);
+                    traversal.addStep(i, next);
+                    modified = true;
+                }
+                prevRank = rank;
+            }
+        } while (modified);
+    }
+
+    @Override
+    public Set<Class<? extends OptimizationStrategy>> applyPrior() {
+        return PRIORS;
+    }
+
+    public static FilterRankingStrategy instance() {
+        return INSTANCE;
+    }
+
+    /**
+     * Ranks the given step. Steps with lower ranks can be moved in front of steps with higher ranks. 0 means that
+     * the step has no rank and thus is not exchangeable with its neighbors.
+     *
+     * @param step
+     * @return The rank of the given step.
+     */
+    private static int getStepRank(final Step step) {
+        if (step instanceof IsStep) {
+            return 1;
+        } else if (step instanceof HasStep) {
+            return 2;
+        } else if (step instanceof WherePredicateStep) {
+            return 3;
+        } else if (step instanceof SimplePathStep || step instanceof CyclicPathStep) {
+            return 4;
+        } else if (step instanceof TraversalFilterStep) {
+            return 5;
+        } else if (step instanceof WhereTraversalStep) {
+            return 6;
+        } else if (step instanceof OrStep) {
+            return 7;
+        } else if (step instanceof AndStep) {
+            return 8;
+        } else if (step instanceof DedupGlobalStep) {
+            return 9;
+        } else if (step instanceof OrderGlobalStep) {
+            return 10;
+        }
+        return 0;
+    }
+
+    /**
+     * If the given step has no child traversal that holds a lambda, then the actual rank determined by
+     * {@link #getStepRank(Step)} is returned, otherwise 0.
+     *
+     * @param step
+     * @return The rank of the given step.
+     */
+    private static int rank(final Step step) {
+        if (isNotOptimizableStep(step)) {
+            return 0;
+        }
+        final int rank = getStepRank(step);
+        if (rank > 0 && step instanceof TraversalParent) {
+            final TraversalParent tp = (TraversalParent) step;
+            final Iterator<Traversal.Admin<Object, Object>> childTraversalIterator = IteratorUtils.concat(
+                    tp.getLocalChildren().iterator(), tp.getGlobalChildren().iterator());
+            while (childTraversalIterator.hasNext()) {
+                if (TraversalHelper.anyStepRecursively(FilterRankingStrategy::isNotOptimizableStep, childTraversalIterator.next())) {
+                    return 0;
+                }
+            }
+        }
+        return rank;
+    }
+
+    /**
+     * Returns true if the step is not optimizable, otherwise false. A step is not optimizable if it (or any of its
+     * child traversals) is a lambda holder or has a label.
+     *
+     * @param step
+     * @return true if the given step is optimizable, otherwise false.
+     */
+    private static boolean isNotOptimizableStep(final Step step) {
+        return step instanceof LambdaHolder || !step.getLabels().isEmpty();
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/ae644951/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_LP_O_P_S_SE_SL_Traverser.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_LP_O_P_S_SE_SL_Traverser.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_LP_O_P_S_SE_SL_Traverser.java
new file mode 100644
index 0000000..c282d30
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_LP_O_P_S_SE_SL_Traverser.java
@@ -0,0 +1,99 @@
+/*
+ * 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.traverser;
+
+import org.apache.tinkerpop.gremlin.process.traversal.Path;
+import org.apache.tinkerpop.gremlin.process.traversal.Step;
+import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.ImmutablePath;
+import org.apache.tinkerpop.gremlin.structure.util.Attachable;
+import org.apache.tinkerpop.gremlin.structure.util.reference.ReferenceFactory;
+
+import java.util.Set;
+import java.util.function.Function;
+
+/**
+ * @author Marko A. Rodriguez (http://markorodriguez.com)
+ */
+public class B_LP_O_P_S_SE_SL_Traverser<T> extends B_O_S_SE_SL_Traverser<T> {
+
+    protected Path path;
+
+    protected B_LP_O_P_S_SE_SL_Traverser() {
+    }
+
+    public B_LP_O_P_S_SE_SL_Traverser(final T t, final Step<T, ?> step, final long initialBulk) {
+        super(t, step, initialBulk);
+        this.path = ImmutablePath.make().extend(t, step.getLabels());
+    }
+
+    /////////////////
+
+    @Override
+    public Path path() {
+        return this.path;
+    }
+
+    /////////////////
+
+    @Override
+    public Traverser.Admin<T> detach() {
+        super.detach();
+        this.path = ReferenceFactory.detach(this.path);
+        return this;
+    }
+
+    /////////////////
+
+    @Override
+    public <R> Traverser.Admin<R> split(final R r, final Step<T, R> step) {
+        final B_LP_O_P_S_SE_SL_Traverser<R> clone = (B_LP_O_P_S_SE_SL_Traverser<R>) super.split(r, step);
+        clone.path = clone.path.clone().extend(r, step.getLabels());
+        return clone;
+    }
+
+    @Override
+    public Traverser.Admin<T> split() {
+        final B_LP_O_P_S_SE_SL_Traverser<T> clone = (B_LP_O_P_S_SE_SL_Traverser<T>) super.split();
+        clone.path = clone.path.clone();
+        return clone;
+    }
+
+    @Override
+    public void addLabels(final Set<String> labels) {
+        if (!labels.isEmpty())
+            this.path = this.path.extend(labels);
+    }
+
+    @Override
+    public int hashCode() {
+        return super.hashCode() + this.path.hashCode();
+    }
+
+    @Override
+    public boolean equals(final Object object) {
+        return (object instanceof B_LP_O_P_S_SE_SL_Traverser)
+                && ((B_LP_O_P_S_SE_SL_Traverser) object).get().equals(this.t)
+                && ((B_LP_O_P_S_SE_SL_Traverser) object).getStepId().equals(this.getStepId())
+                && ((B_LP_O_P_S_SE_SL_Traverser) object).loops() == this.loops()
+                && (null == this.sack)
+                && ((B_LP_O_P_S_SE_SL_Traverser) object).path().equals(this.path);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/ae644951/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_LP_O_P_S_SE_SL_TraverserGenerator.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_LP_O_P_S_SE_SL_TraverserGenerator.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_LP_O_P_S_SE_SL_TraverserGenerator.java
new file mode 100644
index 0000000..0ba86f5
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_LP_O_P_S_SE_SL_TraverserGenerator.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.traverser;
+
+import org.apache.tinkerpop.gremlin.process.traversal.Step;
+import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
+import org.apache.tinkerpop.gremlin.process.traversal.TraverserGenerator;
+
+import java.util.EnumSet;
+import java.util.Set;
+
+/**
+ * @author Marko A. Rodriguez (http://markorodriguez.com)
+ */
+public class B_LP_O_P_S_SE_SL_TraverserGenerator implements TraverserGenerator {
+
+    private static final B_LP_O_P_S_SE_SL_TraverserGenerator INSTANCE = new B_LP_O_P_S_SE_SL_TraverserGenerator();
+    private static final Set<TraverserRequirement> REQUIREMENTS = EnumSet.of(
+            TraverserRequirement.OBJECT,
+            TraverserRequirement.BULK,
+            TraverserRequirement.SINGLE_LOOP,
+            TraverserRequirement.LABELED_PATH,
+            TraverserRequirement.PATH,
+            TraverserRequirement.SACK,
+            TraverserRequirement.SIDE_EFFECTS);
+
+    private B_LP_O_P_S_SE_SL_TraverserGenerator() {
+    }
+
+    @Override
+    public <S> Traverser.Admin<S> generate(final S start, final Step<S, ?> startStep, final long initialBulk) {
+        return new B_LP_O_P_S_SE_SL_Traverser<>(start, startStep, initialBulk);
+    }
+
+    @Override
+    public Set<TraverserRequirement> getProvidedRequirements() {
+        return REQUIREMENTS;
+    }
+
+    public static B_LP_O_P_S_SE_SL_TraverserGenerator instance() {
+        return INSTANCE;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/ae644951/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_LP_O_S_SE_SL_Traverser.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_LP_O_S_SE_SL_Traverser.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_LP_O_S_SE_SL_Traverser.java
new file mode 100644
index 0000000..61683c9
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_LP_O_S_SE_SL_Traverser.java
@@ -0,0 +1,106 @@
+/*
+ *
+ *  * 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.traverser;
+
+import org.apache.tinkerpop.gremlin.process.traversal.Path;
+import org.apache.tinkerpop.gremlin.process.traversal.Step;
+import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.ImmutablePath;
+import org.apache.tinkerpop.gremlin.structure.util.Attachable;
+import org.apache.tinkerpop.gremlin.structure.util.reference.ReferenceFactory;
+
+import java.util.Set;
+import java.util.function.Function;
+
+/**
+ * @author Marko A. Rodriguez (http://markorodriguez.com)
+ */
+public class B_LP_O_S_SE_SL_Traverser<T> extends B_O_S_SE_SL_Traverser<T> {
+
+    protected Path path;
+
+    protected B_LP_O_S_SE_SL_Traverser() {
+    }
+
+    public B_LP_O_S_SE_SL_Traverser(final T t, final Step<T, ?> step, final long initialBulk) {
+        super(t, step, initialBulk);
+        this.path = ImmutablePath.make();
+        if (!step.getLabels().isEmpty()) this.path = this.path.extend(t, step.getLabels());
+    }
+
+    /////////////////
+
+    @Override
+    public Path path() {
+        return this.path;
+    }
+
+    /////////////////
+
+    @Override
+    public Traverser.Admin<T> detach() {
+        super.detach();
+        this.path = ReferenceFactory.detach(this.path);
+        return this;
+    }
+
+    /////////////////
+
+    @Override
+    public <R> Traverser.Admin<R> split(final R r, final Step<T, R> step) {
+        final B_LP_O_S_SE_SL_Traverser<R> clone = (B_LP_O_S_SE_SL_Traverser<R>) super.split(r, step);
+        clone.path = clone.path.clone();
+        if (!step.getLabels().isEmpty()) clone.path = clone.path.extend(r, step.getLabels());
+        return clone;
+    }
+
+    @Override
+    public Traverser.Admin<T> split() {
+        final B_LP_O_S_SE_SL_Traverser<T> clone = (B_LP_O_S_SE_SL_Traverser<T>) super.split();
+        clone.path = clone.path.clone();
+        return clone;
+    }
+
+    @Override
+    public void addLabels(final Set<String> labels) {
+        if (!labels.isEmpty())
+            this.path = this.path.size() == 0 || !this.path.get(this.path.size() - 1).equals(this.t) ?
+                    this.path.extend(this.t, labels) :
+                    this.path.extend(labels);
+    }
+
+    @Override
+    public int hashCode() {
+        return super.hashCode() + this.path.hashCode();
+    }
+
+    @Override
+    public boolean equals(final Object object) {
+        return (object instanceof B_LP_O_S_SE_SL_Traverser)
+                && ((B_LP_O_S_SE_SL_Traverser) object).get().equals(this.t)
+                && ((B_LP_O_S_SE_SL_Traverser) object).getStepId().equals(this.getStepId())
+                && ((B_LP_O_S_SE_SL_Traverser) object).loops() == this.loops()
+                && (null == this.sack)
+                && ((B_LP_O_S_SE_SL_Traverser) object).path().equals(this.path);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/ae644951/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_LP_O_S_SE_SL_TraverserGenerator.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_LP_O_S_SE_SL_TraverserGenerator.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_LP_O_S_SE_SL_TraverserGenerator.java
new file mode 100644
index 0000000..4789056
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_LP_O_S_SE_SL_TraverserGenerator.java
@@ -0,0 +1,61 @@
+/*
+ *
+ *  * 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.traverser;
+
+import org.apache.tinkerpop.gremlin.process.traversal.Step;
+import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
+import org.apache.tinkerpop.gremlin.process.traversal.TraverserGenerator;
+
+import java.util.EnumSet;
+import java.util.Set;
+
+/**
+ * @author Marko A. Rodriguez (http://markorodriguez.com)
+ */
+public class B_LP_O_S_SE_SL_TraverserGenerator implements TraverserGenerator {
+
+    private static final B_LP_O_S_SE_SL_TraverserGenerator INSTANCE = new B_LP_O_S_SE_SL_TraverserGenerator();
+    private static final Set<TraverserRequirement> REQUIREMENTS = EnumSet.of(
+            TraverserRequirement.OBJECT,
+            TraverserRequirement.BULK,
+            TraverserRequirement.SINGLE_LOOP,
+            TraverserRequirement.LABELED_PATH,
+            TraverserRequirement.SACK,
+            TraverserRequirement.SIDE_EFFECTS);
+
+    private B_LP_O_S_SE_SL_TraverserGenerator() {
+    }
+
+    @Override
+    public <S> Traverser.Admin<S> generate(final S start, final Step<S, ?> startStep, final long initialBulk) {
+        return new B_LP_O_S_SE_SL_Traverser<>(start, startStep, initialBulk);
+    }
+
+    @Override
+    public Set<TraverserRequirement> getProvidedRequirements() {
+        return REQUIREMENTS;
+    }
+
+    public static B_LP_O_S_SE_SL_TraverserGenerator instance() {
+        return INSTANCE;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/ae644951/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_O_P_S_SE_SL_Traverser.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_O_P_S_SE_SL_Traverser.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_O_P_S_SE_SL_Traverser.java
deleted file mode 100644
index 7b77843..0000000
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_O_P_S_SE_SL_Traverser.java
+++ /dev/null
@@ -1,100 +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.traverser;
-
-import org.apache.tinkerpop.gremlin.process.traversal.Path;
-import org.apache.tinkerpop.gremlin.process.traversal.Step;
-import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
-import org.apache.tinkerpop.gremlin.process.traversal.step.util.ImmutablePath;
-import org.apache.tinkerpop.gremlin.structure.util.Attachable;
-import org.apache.tinkerpop.gremlin.structure.util.detached.DetachedFactory;
-import org.apache.tinkerpop.gremlin.structure.util.reference.ReferenceFactory;
-
-import java.util.function.Function;
-
-/**
- * @author Marko A. Rodriguez (http://markorodriguez.com)
- */
-public class B_O_P_S_SE_SL_Traverser<T> extends B_O_S_SE_SL_Traverser<T> {
-
-    protected Path path;
-
-    protected B_O_P_S_SE_SL_Traverser() {
-    }
-
-    public B_O_P_S_SE_SL_Traverser(final T t, final Step<T, ?> step, final long initialBulk) {
-        super(t, step, initialBulk);
-        this.path = ImmutablePath.make().extend(t, step.getLabels());
-    }
-
-    /////////////////
-
-    @Override
-    public Path path() {
-        return this.path;
-    }
-
-    /////////////////
-
-    @Override
-    public Traverser.Admin<T> detach() {
-        super.detach();
-        this.path = ReferenceFactory.detach(this.path);
-        return this;
-    }
-
-    @Override
-    public T attach(final Function<Attachable<T>, T> method) {
-        // you do not want to attach a path because it will reference graph objects not at the current vertex
-        if (this.t instanceof Attachable && !(((Attachable) this.t).get() instanceof Path))
-            this.t = ((Attachable<T>) this.t).attach(method);
-        return this.t;
-    }
-
-    /////////////////
-
-    @Override
-    public void merge(final Traverser.Admin<?> other) {
-        this.bulk = this.bulk + other.bulk();
-    }
-
-    @Override
-    public <R> Traverser.Admin<R> split(final R r, final Step<T, R> step) {
-        final B_O_P_S_SE_SL_Traverser<R> clone = (B_O_P_S_SE_SL_Traverser<R>) super.split(r, step);
-        clone.path = clone.path.clone().extend(r, step.getLabels());
-        return clone;
-
-    }
-
-    @Override
-    public int hashCode() {
-        return super.hashCode() + this.path.hashCode();
-    }
-
-    @Override
-    public boolean equals(final Object object) {
-        return (object instanceof B_O_P_S_SE_SL_Traverser)
-                && ((B_O_P_S_SE_SL_Traverser) object).path().equals(this.path)
-                && ((B_O_P_S_SE_SL_Traverser) object).get().equals(this.t)
-                && ((B_O_P_S_SE_SL_Traverser) object).getStepId().equals(this.getStepId())
-                && ((B_O_P_S_SE_SL_Traverser) object).loops() == this.loops()
-                && (null == this.sack);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/ae644951/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_O_P_S_SE_SL_TraverserGenerator.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_O_P_S_SE_SL_TraverserGenerator.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_O_P_S_SE_SL_TraverserGenerator.java
deleted file mode 100644
index 9915740..0000000
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/B_O_P_S_SE_SL_TraverserGenerator.java
+++ /dev/null
@@ -1,58 +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.traverser;
-
-import org.apache.tinkerpop.gremlin.process.traversal.Step;
-import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
-import org.apache.tinkerpop.gremlin.process.traversal.TraverserGenerator;
-
-import java.util.EnumSet;
-import java.util.Set;
-
-/**
- * @author Marko A. Rodriguez (http://markorodriguez.com)
- */
-public class B_O_P_S_SE_SL_TraverserGenerator implements TraverserGenerator {
-
-    private static final B_O_P_S_SE_SL_TraverserGenerator INSTANCE = new B_O_P_S_SE_SL_TraverserGenerator();
-    private static final Set<TraverserRequirement> REQUIREMENTS = EnumSet.of(
-            TraverserRequirement.OBJECT,
-            TraverserRequirement.BULK,
-            TraverserRequirement.SINGLE_LOOP,
-            TraverserRequirement.PATH,
-            TraverserRequirement.SACK,
-            TraverserRequirement.SIDE_EFFECTS);
-
-    private B_O_P_S_SE_SL_TraverserGenerator() {
-    }
-
-    @Override
-    public <S> Traverser.Admin<S> generate(final S start, final Step<S, ?> startStep, final long initialBulk) {
-        return new B_O_P_S_SE_SL_Traverser<>(start, startStep, initialBulk);
-    }
-
-    @Override
-    public Set<TraverserRequirement> getProvidedRequirements() {
-        return REQUIREMENTS;
-    }
-
-    public static B_O_P_S_SE_SL_TraverserGenerator instance() {
-        return INSTANCE;
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/ae644951/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/TraverserRequirement.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/TraverserRequirement.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/TraverserRequirement.java
index 8d6c7c8..b81469b 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/TraverserRequirement.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/TraverserRequirement.java
@@ -35,6 +35,7 @@ public enum TraverserRequirement {
     BULK,
     SINGLE_LOOP,
     NESTED_LOOP,
+    LABELED_PATH,
     PATH,
     SACK,
     SIDE_EFFECTS,

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/ae644951/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/util/AbstractTraverser.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/util/AbstractTraverser.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/util/AbstractTraverser.java
index 3284394..1ced9ef 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/util/AbstractTraverser.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/util/AbstractTraverser.java
@@ -27,6 +27,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.util.EmptyTraversalSideEff
 import org.apache.tinkerpop.gremlin.structure.util.Attachable;
 import org.apache.tinkerpop.gremlin.structure.util.reference.ReferenceFactory;
 
+import java.util.Set;
 import java.util.function.Function;
 
 /**
@@ -72,6 +73,11 @@ public abstract class AbstractTraverser<T> implements Traverser<T>, Traverser.Ad
     }
 
     @Override
+    public void addLabels(final Set<String> labels) {
+
+    }
+
+    @Override
     public void set(final T t) {
         this.t = t;
     }

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/ae644951/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/util/DefaultTraverserGeneratorFactory.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/util/DefaultTraverserGeneratorFactory.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/util/DefaultTraverserGeneratorFactory.java
index f473cbb..d94e531 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/util/DefaultTraverserGeneratorFactory.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/util/DefaultTraverserGeneratorFactory.java
@@ -20,8 +20,9 @@ package org.apache.tinkerpop.gremlin.process.traversal.traverser.util;
 
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.TraverserGenerator;
+import org.apache.tinkerpop.gremlin.process.traversal.traverser.B_LP_O_P_S_SE_SL_TraverserGenerator;
+import org.apache.tinkerpop.gremlin.process.traversal.traverser.B_LP_O_S_SE_SL_TraverserGenerator;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.B_O_S_SE_SL_TraverserGenerator;
-import org.apache.tinkerpop.gremlin.process.traversal.traverser.B_O_P_S_SE_SL_TraverserGenerator;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.B_O_TraverserGenerator;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.O_TraverserGenerator;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserGeneratorFactory;
@@ -44,7 +45,7 @@ public class DefaultTraverserGeneratorFactory implements TraverserGeneratorFacto
     }
 
     @Override
-    public TraverserGenerator getTraverserGenerator(final Traversal.Admin<?,?> traversal) {
+    public TraverserGenerator getTraverserGenerator(final Traversal.Admin<?, ?> traversal) {
         final Set<TraverserRequirement> requirements = traversal.getTraverserRequirements();
 
         if (O_TraverserGenerator.instance().getProvidedRequirements().containsAll(requirements))
@@ -56,8 +57,11 @@ public class DefaultTraverserGeneratorFactory implements TraverserGeneratorFacto
         if (B_O_S_SE_SL_TraverserGenerator.instance().getProvidedRequirements().containsAll(requirements))
             return B_O_S_SE_SL_TraverserGenerator.instance();
 
-        if (B_O_P_S_SE_SL_TraverserGenerator.instance().getProvidedRequirements().containsAll(requirements))
-            return B_O_P_S_SE_SL_TraverserGenerator.instance();
+        if (B_LP_O_S_SE_SL_TraverserGenerator.instance().getProvidedRequirements().containsAll(requirements))
+            return B_LP_O_S_SE_SL_TraverserGenerator.instance();
+
+        if (B_LP_O_P_S_SE_SL_TraverserGenerator.instance().getProvidedRequirements().containsAll(requirements))
+            return B_LP_O_P_S_SE_SL_TraverserGenerator.instance();
 
         throw new IllegalStateException("The provided traverser generator factory does not support the requirements of the traversal: " + this.getClass().getCanonicalName() + requirements);
     }

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/ae644951/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/util/EmptyTraverser.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/util/EmptyTraverser.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/util/EmptyTraverser.java
index 11d19bc..a099505 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/util/EmptyTraverser.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/util/EmptyTraverser.java
@@ -25,6 +25,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
 import org.apache.tinkerpop.gremlin.process.traversal.step.util.EmptyPath;
 import org.apache.tinkerpop.gremlin.structure.util.Attachable;
 
+import java.util.Set;
 import java.util.function.Function;
 
 /**
@@ -43,6 +44,11 @@ public final class EmptyTraverser<T> implements Traverser<T>, Traverser.Admin<T>
     }
 
     @Override
+    public void addLabels(final Set<String> labels) {
+
+    }
+
+    @Override
     public void set(final T t) {
 
     }

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/ae644951/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalHelper.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalHelper.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalHelper.java
index eb2444c..5e025b1 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalHelper.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalHelper.java
@@ -38,13 +38,8 @@ import org.apache.tinkerpop.gremlin.process.traversal.step.util.EmptyStep;
 import org.apache.tinkerpop.gremlin.structure.T;
 import org.apache.tinkerpop.gremlin.util.iterator.IteratorUtils;
 
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Optional;
-import java.util.Set;
+import java.util.*;
+import java.util.function.Predicate;
 import java.util.stream.Collectors;
 
 /**
@@ -216,6 +211,22 @@ public final class TraversalHelper {
         return false;
     }
 
+    public static boolean anyStepRecursively(final Predicate<Step> predicate, final Traversal.Admin<?, ?> traversal) {
+        for (final Step<?, ?> step : traversal.getSteps()) {
+            if (predicate.test(step)) {
+                return true;
+            }
+            if (step instanceof TraversalParent) {
+                for (final Traversal.Admin<?, ?> globalChild : ((TraversalParent) step).getGlobalChildren()) {
+                    if (anyStepRecursively(predicate, globalChild)) {
+                        return true;
+                    }
+                }
+            }
+        }
+        return false;
+    }
+
     /**
      * @param stepClasses the step classes to look for
      * @param traversal   the traversal in which to look for the given step classes

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/ae644951/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/Transaction.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/Transaction.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/Transaction.java
index 56b22e0..03bd8cc 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/Transaction.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/Transaction.java
@@ -20,7 +20,6 @@ package org.apache.tinkerpop.gremlin.structure;
 
 import org.apache.tinkerpop.gremlin.structure.util.AbstractTransaction;
 
-import java.io.Closeable;
 import java.util.Collections;
 import java.util.Set;
 import java.util.function.BiFunction;

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/ae644951/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphml/GraphMLReader.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphml/GraphMLReader.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphml/GraphMLReader.java
index d2fdb39..d45d411 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphml/GraphMLReader.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphml/GraphMLReader.java
@@ -61,12 +61,13 @@ public final class GraphMLReader implements GraphReader {
     private final String edgeLabelKey;
     private final String vertexLabelKey;
     private final long batchSize;
+    private final boolean strict;
 
-    private GraphMLReader(final String edgeLabelKey, final String vertexLabelKey,
-                          final long batchSize) {
-        this.edgeLabelKey = edgeLabelKey;
-        this.batchSize = batchSize;
-        this.vertexLabelKey = vertexLabelKey;
+    private GraphMLReader(final Builder builder) {
+        this.edgeLabelKey = builder.edgeLabelKey;
+        this.batchSize = builder.batchSize;
+        this.vertexLabelKey = builder.vertexLabelKey;
+        this.strict = builder.strict;
     }
 
     @Override
@@ -143,13 +144,23 @@ public final class GraphMLReader implements GraphReader {
                                 if (isInVertex) {
                                     if (key.equals(vertexLabelKey))
                                         vertexLabel = value;
-                                    else
-                                        vertexProps.put(dataAttributeName, typeCastValue(key, value, keyTypesMaps));
+                                    else {
+                                        try {
+                                            vertexProps.put(dataAttributeName, typeCastValue(key, value, keyTypesMaps));
+                                        } catch (NumberFormatException nfe) {
+                                            if (strict) throw nfe;
+                                        }
+                                    }
                                 } else if (isInEdge) {
                                     if (key.equals(edgeLabelKey))
                                         edgeLabel = value;
-                                    else
-                                        edgeProps.put(dataAttributeName, typeCastValue(key, value, keyTypesMaps));
+                                    else {
+                                        try {
+                                            edgeProps.put(dataAttributeName, typeCastValue(key, value, keyTypesMaps));
+                                        } catch (NumberFormatException nfe) {
+                                            if (strict) throw nfe;
+                                        }
+                                    }
                                 }
                             }
 
@@ -329,9 +340,19 @@ public final class GraphMLReader implements GraphReader {
     public static final class Builder implements ReaderBuilder<GraphMLReader> {
         private String edgeLabelKey = GraphMLTokens.LABEL_E;
         private String vertexLabelKey = GraphMLTokens.LABEL_V;
+        private boolean strict = true;
         private long batchSize = 10000;
 
-        private Builder() {
+        private Builder() { }
+
+        /**
+         * When set to true, exceptions will be thrown if a property value cannot be coerced to the expected data
+         * type. If set to false, then the reader will continue with the import but ignore the failed property key.
+         * By default this value is "true".
+         */
+        public Builder strict(final boolean strict) {
+            this.strict = strict;
+            return this;
         }
 
         /**
@@ -359,7 +380,7 @@ public final class GraphMLReader implements GraphReader {
         }
 
         public GraphMLReader create() {
-            return new GraphMLReader(edgeLabelKey, vertexLabelKey, batchSize);
+            return new GraphMLReader(this);
         }
     }
 }

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/ae644951/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoMapper.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoMapper.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoMapper.java
index 8b96052..b77f3ec 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoMapper.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoMapper.java
@@ -20,10 +20,12 @@ package org.apache.tinkerpop.gremlin.structure.io.gryo;
 
 import org.apache.tinkerpop.gremlin.process.computer.MapReduce;
 import org.apache.tinkerpop.gremlin.process.computer.util.MapMemory;
+import org.apache.tinkerpop.gremlin.process.traversal.Contains;
 import org.apache.tinkerpop.gremlin.process.traversal.Path;
 import org.apache.tinkerpop.gremlin.process.traversal.step.util.BulkSet;
 import org.apache.tinkerpop.gremlin.process.traversal.step.util.Tree;
-import org.apache.tinkerpop.gremlin.process.traversal.traverser.B_O_P_S_SE_SL_Traverser;
+import org.apache.tinkerpop.gremlin.process.traversal.traverser.B_LP_O_P_S_SE_SL_Traverser;
+import org.apache.tinkerpop.gremlin.process.traversal.traverser.B_LP_O_S_SE_SL_Traverser;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.B_O_S_SE_SL_Traverser;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.B_O_Traverser;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.O_Traverser;
@@ -31,7 +33,6 @@ import org.apache.tinkerpop.gremlin.process.traversal.traverser.util.TraverserSe
 import org.apache.tinkerpop.gremlin.process.traversal.util.DependantMutableMetrics;
 import org.apache.tinkerpop.gremlin.process.traversal.util.MutableMetrics;
 import org.apache.tinkerpop.gremlin.process.traversal.util.StandardTraversalMetrics;
-import org.apache.tinkerpop.gremlin.process.traversal.Contains;
 import org.apache.tinkerpop.gremlin.structure.Direction;
 import org.apache.tinkerpop.gremlin.structure.Edge;
 import org.apache.tinkerpop.gremlin.structure.Graph;
@@ -96,12 +97,12 @@ import java.util.stream.Collectors;
  * serializers in one of three ways:
  * <p/>
  * <ol>
- *     <li>Register just the custom class with a {@code null} {@link Serializer} implementation</li>
- *     <li>Register the custom class with a {@link Serializer} implementation</li>
- *     <li>
- *         Register the custom class with a {@code Function<Kryo, Serializer>} for those cases where the
- *         {@link Serializer} requires the {@link Kryo} instance to get constructed.
- *     </li>
+ * <li>Register just the custom class with a {@code null} {@link Serializer} implementation</li>
+ * <li>Register the custom class with a {@link Serializer} implementation</li>
+ * <li>
+ * Register the custom class with a {@code Function<Kryo, Serializer>} for those cases where the
+ * {@link Serializer} requires the {@link Kryo} instance to get constructed.
+ * </li>
  * </ol>
  * <p/>
  * For example:
@@ -223,7 +224,7 @@ public final class GryoMapper implements Mapper<Kryo> {
             add(Triplet.<Class, Function<Kryo, Serializer>, Integer>with(ReferenceVertex.class, null, 84));
             add(Triplet.<Class, Function<Kryo, Serializer>, Integer>with(ReferencePath.class, null, 85));
 
-            add(Triplet.<Class, Function<Kryo, Serializer>, Integer>with(StarGraph.class, kryo -> StarGraphGryoSerializer.with(Direction.BOTH), 86)); // ***LAST ID**
+            add(Triplet.<Class, Function<Kryo, Serializer>, Integer>with(StarGraph.class, kryo -> StarGraphGryoSerializer.with(Direction.BOTH), 86));
 
             add(Triplet.<Class, Function<Kryo, Serializer>, Integer>with(Edge.class, kryo -> new GryoSerializers.EdgeSerializer(), 65));
             add(Triplet.<Class, Function<Kryo, Serializer>, Integer>with(Vertex.class, kryo -> new GryoSerializers.VertexSerializer(), 66));
@@ -233,8 +234,9 @@ public final class GryoMapper implements Mapper<Kryo> {
             // skip 55
             add(Triplet.<Class, Function<Kryo, Serializer>, Integer>with(B_O_Traverser.class, null, 75));
             add(Triplet.<Class, Function<Kryo, Serializer>, Integer>with(O_Traverser.class, null, 76));
-            add(Triplet.<Class, Function<Kryo, Serializer>, Integer>with(B_O_P_S_SE_SL_Traverser.class, null, 77));
+            add(Triplet.<Class, Function<Kryo, Serializer>, Integer>with(B_LP_O_P_S_SE_SL_Traverser.class, null, 77));
             add(Triplet.<Class, Function<Kryo, Serializer>, Integer>with(B_O_S_SE_SL_Traverser.class, null, 78));
+            add(Triplet.<Class, Function<Kryo, Serializer>, Integer>with(B_LP_O_S_SE_SL_Traverser.class, null, 87));  // ***LAST ID**
 
             add(Triplet.<Class, Function<Kryo, Serializer>, Integer>with(TraverserSet.class, null, 58));
             add(Triplet.<Class, Function<Kryo, Serializer>, Integer>with(Tree.class, null, 61));

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/ae644951/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/util/AbstractThreadLocalTransaction.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/util/AbstractThreadLocalTransaction.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/util/AbstractThreadLocalTransaction.java
new file mode 100644
index 0000000..b47eb79
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/util/AbstractThreadLocalTransaction.java
@@ -0,0 +1,75 @@
+/*
+ * 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.structure.util;
+
+import org.apache.tinkerpop.gremlin.structure.Graph;
+import org.apache.tinkerpop.gremlin.structure.Transaction;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.function.Consumer;
+
+/**
+ * A base implementation of {@link Transaction} that provides core functionality for transaction listeners using
+ * {@link ThreadLocal}.  In this implementation, the listeners are bound to the current thread of execution (usually
+ * the same as the transaction for most graph database implementations).  Therefore, when {@link #commit()} is
+ * called on a particular thread, the only listeners that get notified are those bound to that thread.
+ *
+ * @see AbstractThreadedTransaction
+ *
+ * @author Stephen Mallette (http://stephen.genoprime.com)
+ */
+public abstract class AbstractThreadLocalTransaction extends AbstractTransaction {
+
+    protected final ThreadLocal<List<Consumer<Transaction.Status>>> transactionListeners = new ThreadLocal<List<Consumer<Transaction.Status>>>() {
+        @Override
+        protected List<Consumer<Transaction.Status>> initialValue() {
+            return new ArrayList<>();
+        }
+    };
+
+    public AbstractThreadLocalTransaction(final Graph g) {
+        super(g);
+    }
+
+    @Override
+    protected void fireOnCommit() {
+        transactionListeners.get().forEach(c -> c.accept(Status.COMMIT));
+    }
+
+    @Override
+    protected void fireOnRollback() {
+        transactionListeners.get().forEach(c -> c.accept(Status.ROLLBACK));
+    }
+
+    @Override
+    public void addTransactionListener(final Consumer<Status> listener) {
+        transactionListeners.get().add(listener);
+    }
+
+    @Override
+    public void removeTransactionListener(final Consumer<Status> listener) {
+        transactionListeners.get().remove(listener);
+    }
+
+    @Override
+    public void clearTransactionListeners() {
+        transactionListeners.get().clear();
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/ae644951/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/util/AbstractThreadedTransaction.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/util/AbstractThreadedTransaction.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/util/AbstractThreadedTransaction.java
new file mode 100644
index 0000000..57f8ec0
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/util/AbstractThreadedTransaction.java
@@ -0,0 +1,70 @@
+/*
+ * 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.structure.util;
+
+import org.apache.tinkerpop.gremlin.structure.Graph;
+import org.apache.tinkerpop.gremlin.structure.Transaction;
+
+import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.function.Consumer;
+
+/**
+ * A base implementation of {@link Transaction} that provides core functionality for transaction listeners using a
+ * shared set of transaction listeners.  Therefore, when {@link #commit()} is called from any thread, all listeners
+ * get notified.  This implementation would be useful for graph implementations that support threaded transactions,
+ * specifically in the {@link Graph} instance returned from {@link Transaction#createThreadedTx()}.
+ *
+ * @see AbstractThreadLocalTransaction
+ *
+ * @author Stephen Mallette (http://stephen.genoprime.com)
+ */
+public abstract class AbstractThreadedTransaction extends AbstractTransaction {
+
+    protected final List<Consumer<Status>> transactionListeners = new CopyOnWriteArrayList<>();
+
+    public AbstractThreadedTransaction(final Graph g) {
+        super(g);
+    }
+
+    @Override
+    protected void fireOnCommit() {
+        transactionListeners.forEach(c -> c.accept(Status.COMMIT));
+    }
+
+    @Override
+    protected void fireOnRollback() {
+        transactionListeners.forEach(c -> c.accept(Status.ROLLBACK));
+    }
+
+    @Override
+    public void addTransactionListener(final Consumer<Status> listener) {
+        transactionListeners.add(listener);
+    }
+
+    @Override
+    public void removeTransactionListener(final Consumer<Status> listener) {
+        transactionListeners.remove(listener);
+    }
+
+    @Override
+    public void clearTransactionListeners() {
+        transactionListeners.clear();
+    }
+}