You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tinkerpop.apache.org by GitBox <gi...@apache.org> on 2022/01/11 02:25:53 UTC

[GitHub] [tinkerpop] mikepersonick opened a new pull request #1543: Orderability Semantics

mikepersonick opened a new pull request #1543:
URL: https://github.com/apache/tinkerpop/pull/1543


   Implementation of total orderabillity semantics including across types.
   
   https://issues.apache.org/jira/browse/TINKERPOP-2641
   
   https://tinkerpop.apache.org/docs/3.6.0-SNAPSHOT/dev/provider/#_composite_types_3


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@tinkerpop.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [tinkerpop] mikepersonick commented on a change in pull request #1543: Orderability Semantics

Posted by GitBox <gi...@apache.org>.
mikepersonick commented on a change in pull request #1543:
URL: https://github.com/apache/tinkerpop/pull/1543#discussion_r782307310



##########
File path: gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/GherkinTestRunner.cs
##########
@@ -85,6 +85,7 @@ public class GherkinTestRunner
                     "g_V_hasXperson_name_markoX_bothXknowsX_groupCount_byXvaluesXnameX_foldX",
                     IgnoreReason.ArrayKeysInMapNotAssertingInGherkin
                 },
+                {"g_V_properties_order_id", IgnoreReason.NoReason},

Review comment:
       @spmallette 




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@tinkerpop.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [tinkerpop] mikepersonick commented on a change in pull request #1543: Orderability Semantics

Posted by GitBox <gi...@apache.org>.
mikepersonick commented on a change in pull request #1543:
URL: https://github.com/apache/tinkerpop/pull/1543#discussion_r782203759



##########
File path: gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/OrderabilityComparator.java
##########
@@ -0,0 +1,234 @@
+/*
+ * 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.util;
+
+import org.apache.tinkerpop.gremlin.process.traversal.Path;
+import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
+import org.apache.tinkerpop.gremlin.structure.Edge;
+import org.apache.tinkerpop.gremlin.structure.Element;
+import org.apache.tinkerpop.gremlin.structure.Property;
+import org.apache.tinkerpop.gremlin.structure.Vertex;
+import org.apache.tinkerpop.gremlin.structure.VertexProperty;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.Comparator;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
+
+/**
+ * An implementation of the Comparability/Orderability semantics as defined in the Apache TinkerPop Provider
+ * documentation.
+ *
+ * @author Mike Personick
+ */
+public class OrderabilityComparator implements Comparator<Object> {
+
+    public static final Comparator<Object> INSTANCE = Comparator.comparing(
+            // first transform (strip Traverser layer)
+            OrderabilityComparator::transform,
+                    // then handle nulls
+                    Comparator.nullsFirst(
+                            // then consider orderability
+                            new OrderabilityComparator()));
+
+    /**
+     * The order of this array determines the sort order across types.The index in this array corresponds directly to a
+     * Comparator in the {@link #comparators} array below, so be sure to keep them in sync.
+     */
+    private static final Class[] types = new Class[] {
+            Boolean.class,
+            Number.class,
+            Date.class,
+            String.class,
+            UUID.class,
+            Vertex.class,
+            Edge.class,
+            VertexProperty.class,
+            Property.class,
+            Path.class,
+            Set.class,
+            List.class,
+            Map.class,
+            Map.Entry.class,
+    };
+
+    /**
+     * The stable ordering for numeric types, should we choose to support stable ordering for numeric types.
+     */
+    private static final Class[] numerics = new Class[] {
+            Byte.class,
+            Short.class,
+            Integer.class,
+            Long.class,
+            BigInteger.class,
+            Float.class,
+            Double.class,
+            BigDecimal.class
+    };
+
+    private static final Comparator<Comparable> naturalOrderComparator = Comparator.naturalOrder();
+
+    /**
+     * This comparator does not provide a stable order for numerics because of type promotion equivalence semantics.
+     */
+    private static final Comparator<Number> numberComparator = (f,s) -> NumberHelper.compare(f, s);
+
+    /**
+     * This alternative numeric comparator will sort by numeric type in the case of type promotion equivalence.
+     * Currently unused.
+     */
+    private static final Comparator<Number> stableOrderNumberComparator = (f,s) -> {
+        final int i = NumberHelper.compare(f, s);
+        if (i != 0 || f.getClass().equals(s.getClass())) {
+            // they're not equal, or they are of the same numeric type
+            return i;
+        }
+        // if they are equal but of different types, order by type
+        final int ft = type(numerics, f);
+        final int st = type(numerics, s);
+        return ft - st;
+    };
+
+    /**
+     * Sort Vertex, Edge, VertexProperty by id.
+     */
+    private static final Comparator<Element> elementComparator =
+            Comparator.comparing(Element::id, INSTANCE);
+
+    /**
+     * Sort Property first by key, then by value.
+     */
+    private static final Comparator<Property> propertyComparator =
+            Comparator.<Property,Object>comparing(Property::key, INSTANCE).thenComparing(Property::value, INSTANCE);
+
+    /**
+     * Sort List, Set, Path, and Map element-by-element in the order presented by their natural iterator.
+     */
+    private static final Comparator<Iterable> iteratableComparator = (f, s) -> {
+        final Iterator fi = f.iterator();
+        final Iterator si = s.iterator();
+
+        while (fi.hasNext() && si.hasNext()) {
+            final int i = INSTANCE.compare(fi.next(), si.next());
+            if (i != 0) {
+                return i;
+            }
+        }
+
+        return fi.hasNext() ? 1 : si.hasNext() ? -1 : 0;
+    };
+
+    /**
+     * Sort Map by entry-set.
+     */
+    private static final Comparator<Map> mapComparator =
+            Comparator.comparing(Map::entrySet, iteratableComparator);
+
+    /**
+     * Sort Map.Entry first by key, then by value.
+     */
+    private static final Comparator<Map.Entry> entryComparator =
+            Comparator.<Map.Entry,Object>comparing(Map.Entry::getKey, INSTANCE).thenComparing(Map.Entry::getValue, INSTANCE);
+
+    /**
+     * Sort unknown types first by classname, then by natural toString().
+     */
+    private static final Comparator<Object> unknownTypeComparator =
+            Comparator.comparing(f -> f.getClass().getName()).thenComparing(Object::toString);
+
+    /**
+     * The comparators that will be used for the types defined above in the {@link #types} array. Be sure to keep them
+     * in sync.
+     */
+    private static final Comparator[] comparators = new Comparator[] {
+        naturalOrderComparator,          // Boolean.class,
+        numberComparator,                // Number.class,
+        naturalOrderComparator,          // Date.class,
+        naturalOrderComparator,          // String.class,
+        naturalOrderComparator,          // UUID.class,
+        elementComparator,               // Vertex.class,
+        elementComparator,               // Edge.class,
+        elementComparator,               // VertexProperty.class,
+        propertyComparator,              // Property.class,
+        iteratableComparator,            // Path.class,
+        iteratableComparator,            // Set.class,
+        iteratableComparator,            // List.class,
+        mapComparator,                   // Map.class,
+        entryComparator,                 // Map.Entry.class,
+    };
+
+    /**
+     * Marker priority for unknown types. A large number means they will appear after known types. Use -1 if you want
+     * them to appear first.
+     */
+    private static final int UNKNOWN_TYPE = 0xffff;
+
+    /**
+     * Return the first index of the Class array for which the supplied object is an instance. Returns
+     * {@link #UNKNOWN_TYPE} if not an instance of any of the supplied classes.
+     */
+    private static final int type(final Class[] types, final Object o) {
+        for (int i = 0; i < types.length; i++) {
+            if (types[i].isInstance(o)) {
+                return i;
+            }
+        }
+        return UNKNOWN_TYPE;

Review comment:
       g.inject on a local tinkergraph? lambdas? maybe others. Probably would never happen over a remote connection. Part of Orderability semantics is no exceptions thrown - total universal order. I will update the semantics documentation if it's not in there already.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@tinkerpop.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [tinkerpop] mikepersonick closed pull request #1543: Orderability Semantics

Posted by GitBox <gi...@apache.org>.
mikepersonick closed pull request #1543:
URL: https://github.com/apache/tinkerpop/pull/1543


   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@tinkerpop.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [tinkerpop] mikepersonick commented on a change in pull request #1543: Orderability Semantics

Posted by GitBox <gi...@apache.org>.
mikepersonick commented on a change in pull request #1543:
URL: https://github.com/apache/tinkerpop/pull/1543#discussion_r782264546



##########
File path: gremlin-test/features/semantics/Orderability.feature
##########
@@ -0,0 +1,354 @@
+# 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.
+
+@OrderabilitySemantics
+Feature: Orderability
+
+  Scenario: g_V_values_order
+    Given the modern graph
+    And the traversal of
+      """
+      g.V().values().order()
+      """
+    When iterated to list
+    Then the result should be ordered
+      | result |
+      | d[27].i |
+      | d[29].i |
+      | d[32].i |
+      | d[35].i |
+      | java |
+      | java |
+      | josh |
+      | lop  |
+      | marko |
+      | peter |
+      | ripple |
+      | vadas  |
+
+# This exposes an underlying problem where .value() does not preserve the order (should it?). This will be
+# fixed under separate cover.
+#
+#  @UserSuppliedVertexPropertyIds
+#  Scenario: g_V_properties_order_value
+#    Given the modern graph
+#    And the traversal of
+#      """
+#      g.V().properties().order().value()
+#      """
+#    When iterated to list
+#    Then the result should be ordered
+#      | result |
+#      | marko |
+#      | d[29].i |
+#      | vadas  |
+#      | d[27].i |
+#      | lop  |
+#      | java |
+#      | josh |
+#      | d[32].i |
+#      | ripple |
+#      | java |
+#      | peter |
+#      | d[35].i |
+
+  @UserSuppliedVertexPropertyIds
+  Scenario: g_V_properties_order_id
+    Given the modern graph
+    And the traversal of
+      """
+      g.V().properties().order().id()
+      """
+    When iterated to list
+    Then the result should be ordered
+      | result |
+      | d[0].l |
+      | d[1].l |
+      | d[2].l |
+      | d[3].l |
+      | d[4].l |
+      | d[5].l |
+      | d[6].l |
+      | d[7].l |
+      | d[8].l |
+      | d[9].l |
+      | d[10].l |
+      | d[11].l |
+
+  Scenario: g_E_properties_order_value
+    Given the modern graph
+    And the traversal of
+      """
+      g.E().properties().order().value()
+      """
+    When iterated to list
+    Then the result should be ordered
+      | result |
+      | d[0.2].d |
+      | d[0.4].d |
+      | d[0.4].d |
+      | d[0.5].d |
+      | d[1.0].d |
+      | d[1.0].d |
+
+  Scenario: g_E_properties_order_byXdescX_value
+    Given the modern graph
+    And the traversal of
+      """
+      g.E().properties().order().by(desc).value()
+      """
+    When iterated to list
+    Then the result should be ordered
+      | result |
+      | d[1.0].d |
+      | d[1.0].d |
+      | d[0.5].d |
+      | d[0.4].d |
+      | d[0.4].d |
+      | d[0.2].d |
+
+  Scenario: g_inject_order
+    Given the empty graph
+    And using the parameter xx1 defined as "null"
+    And using the parameter xx2 defined as "false"
+    And using the parameter xx3 defined as "true"
+    And using the parameter xx4 defined as "d[1].i"
+    And using the parameter xx5 defined as "d[2.0].d"
+    And using the parameter xx6 defined as "bar"
+    And using the parameter xx7 defined as "foo"
+    And using the parameter xx8 defined as "zzz"
+    And using the parameter xx9 defined as "l[a,b,c]"
+    And using the parameter xx10 defined as "l[a,b,c,d]"
+    And using the parameter xx11 defined as "m[{\"a\":\"a\", \"b\":false, \"c\":\"c\"}]"
+    And using the parameter xx12 defined as "m[{\"a\":\"a\", \"b\":\"b\"}]"
+    # TODO add support for Set, UUID, Date once the framework supports it
+    And the traversal of
+      """
+      g.inject(xx8,xx7,xx10,xx4,xx9,xx12,xx1,xx5,xx11,xx6,xx3,xx2).order()
+      """
+    When iterated to list
+    Then the result should be ordered
+      | result |
+      | null |
+      | false |
+      | true |
+      | d[1].i |
+      | d[2.0].d |
+      | bar |
+      | foo |
+      | zzz |
+      | l[a,b,c] |
+      | l[a,b,c,d] |
+      | m[{"a":"a", "b":false, "c":"c"}] |
+      | m[{"a":"a", "b":"b"}] |
+
+  Scenario: g_inject_order_byXdescX
+    Given the empty graph
+    And using the parameter xx1 defined as "null"
+    And using the parameter xx2 defined as "false"
+    And using the parameter xx3 defined as "true"
+    And using the parameter xx4 defined as "d[1].i"
+    And using the parameter xx5 defined as "d[2.0].d"
+    And using the parameter xx6 defined as "bar"
+    And using the parameter xx7 defined as "foo"
+    And using the parameter xx8 defined as "zzz"
+    And using the parameter xx9 defined as "l[a,b,c]"
+    And using the parameter xx10 defined as "l[a,b,c,d]"
+    And using the parameter xx11 defined as "m[{\"a\":\"a\", \"b\":false, \"c\":\"c\"}]"
+    And using the parameter xx12 defined as "m[{\"a\":\"a\", \"b\":\"b\"}]"
+    # TODO add support for Set, UUID, Date once the framework supports it
+    And the traversal of
+      """
+      g.inject(xx8,xx7,xx10,xx4,xx9,xx12,xx1,xx5,xx11,xx6,xx3,xx2).order().by(desc)
+      """
+    When iterated to list
+    Then the result should be ordered
+      | result |
+      | m[{"a":"a", "b":"b"}] |
+      | m[{"a":"a", "b":false, "c":"c"}] |
+      | l[a,b,c,d] |
+      | l[a,b,c] |
+      | zzz |
+      | foo |
+      | bar |
+      | d[2.0].d |
+      | d[1].i |
+      | true |
+      | false |
+      | null |
+
+  @UserSuppliedVertexIds
+  Scenario: g_V_out_out_order_byXascX
+    Given the modern graph
+    And the traversal of
+      """
+      g.V().out().out().order().by(asc)
+      """
+    When iterated to list
+    Then the result should be ordered
+      | result |
+      | v[lop] |
+      | v[ripple] |
+
+  @UserSuppliedVertexIds
+  Scenario: g_V_out_out_order_byXdescX
+    Given the modern graph
+    And the traversal of
+      """
+      g.V().out().out().order().by(desc)
+      """
+    When iterated to list
+    Then the result should be ordered
+      | result |
+      | v[ripple] |
+      | v[lop] |
+
+  @UserSuppliedVertexIds
+  Scenario: g_V_out_out_asXheadX_path_order_byXascX_selectXheadX
+    Given the modern graph
+    And the traversal of
+      """
+      g.V().out().out().as("head").path().order().by(asc).select("head")
+      """
+    When iterated to list
+    Then the result should be ordered
+      | result |
+      | v[lop] |
+      | v[ripple] |
+
+  @UserSuppliedVertexIds
+  Scenario: g_V_out_out_asXheadX_path_order_byXdescX_selectXheadX
+    Given the modern graph
+    And the traversal of
+      """
+      g.V().out().out().as("head").path().order().by(desc).select("head")
+      """
+    When iterated to list
+    Then the result should be ordered
+      | result |
+      | v[ripple] |
+      | v[lop] |
+
+  @UserSuppliedEdgeIds
+  Scenario: g_V_out_outE_order_byXascX
+    Given the modern graph
+    And the traversal of
+      """
+      g.V().out().outE().order().by(asc)
+      """
+    When iterated to list
+    Then the result should be ordered
+      | result |
+      | e[josh-created->ripple] |
+      | e[josh-created->lop] |
+
+  @UserSuppliedEdgeIds
+  Scenario: g_V_out_outE_order_byXdescX
+    Given the modern graph
+    And the traversal of
+      """
+      g.V().out().outE().order().by(desc)
+      """
+    When iterated to list
+    Then the result should be ordered
+      | result |
+      | e[josh-created->lop] |
+      | e[josh-created->ripple] |
+
+  @UserSuppliedEdgeIds
+  Scenario: g_V_out_outE_asXheadX_path_order_byXascX_selectXheadX
+    Given the modern graph
+    And the traversal of
+      """
+      g.V().out().outE().as("head").path().order().by(asc).select("head")
+      """
+    When iterated to list
+    Then the result should be ordered
+      | result |
+      | e[josh-created->ripple] |
+      | e[josh-created->lop] |
+
+  @UserSuppliedEdgeIds
+  Scenario: g_V_out_outE_asXheadX_path_order_byXdescX_selectXheadX
+    Given the modern graph
+    And the traversal of
+      """
+      g.V().out().outE().as("head").path().order().by(desc).select("head")
+      """
+    When iterated to list
+    Then the result should be ordered
+      | result |
+      | e[josh-created->lop] |
+      | e[josh-created->ripple] |
+
+  @UserSuppliedVertexPropertyIds
+  Scenario: g_V_out_out_properties_asXheadX_path_order_byXascX_selectXheadX_value
+    Given the modern graph
+    And the traversal of
+      """
+      g.V().out().out().properties().as("head").path().order().by(asc).select("head").value()
+      """
+    When iterated to list
+    Then the result should be ordered
+      | result |
+      | lop |
+      | java |
+      | ripple |
+      | java |
+
+  @UserSuppliedVertexPropertyIds
+  Scenario: g_V_out_out_properties_asXheadX_path_order_byXdescX_selectXheadX_value
+    Given the modern graph
+    And the traversal of
+      """
+      g.V().out().out().properties().as("head").path().order().by(desc).select("head").value()
+      """
+    When iterated to list
+    Then the result should be ordered
+      | result |
+      | java |
+      | ripple |
+      | java |
+      | lop |
+
+  Scenario: g_V_out_out_values_asXheadX_path_order_byXascX_selectXheadX

Review comment:
       "@UserSuppliedVertexIds"




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@tinkerpop.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [tinkerpop] divijvaidya commented on a change in pull request #1543: Orderability Semantics

Posted by GitBox <gi...@apache.org>.
divijvaidya commented on a change in pull request #1543:
URL: https://github.com/apache/tinkerpop/pull/1543#discussion_r782089506



##########
File path: gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/OrderabilityComparator.java
##########
@@ -0,0 +1,234 @@
+/*
+ * 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.util;
+
+import org.apache.tinkerpop.gremlin.process.traversal.Path;
+import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
+import org.apache.tinkerpop.gremlin.structure.Edge;
+import org.apache.tinkerpop.gremlin.structure.Element;
+import org.apache.tinkerpop.gremlin.structure.Property;
+import org.apache.tinkerpop.gremlin.structure.Vertex;
+import org.apache.tinkerpop.gremlin.structure.VertexProperty;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.Comparator;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
+
+/**
+ * An implementation of the Comparability/Orderability semantics as defined in the Apache TinkerPop Provider
+ * documentation.
+ *
+ * @author Mike Personick
+ */
+public class OrderabilityComparator implements Comparator<Object> {
+
+    public static final Comparator<Object> INSTANCE = Comparator.comparing(
+            // first transform (strip Traverser layer)
+            OrderabilityComparator::transform,
+                    // then handle nulls
+                    Comparator.nullsFirst(
+                            // then consider orderability
+                            new OrderabilityComparator()));
+
+    /**
+     * The order of this array determines the sort order across types.The index in this array corresponds directly to a
+     * Comparator in the {@link #comparators} array below, so be sure to keep them in sync.
+     */
+    private static final Class[] types = new Class[] {
+            Boolean.class,
+            Number.class,
+            Date.class,
+            String.class,
+            UUID.class,
+            Vertex.class,
+            Edge.class,
+            VertexProperty.class,
+            Property.class,
+            Path.class,
+            Set.class,
+            List.class,
+            Map.class,
+            Map.Entry.class,
+    };
+
+    /**
+     * The stable ordering for numeric types, should we choose to support stable ordering for numeric types.
+     */
+    private static final Class[] numerics = new Class[] {
+            Byte.class,
+            Short.class,
+            Integer.class,
+            Long.class,
+            BigInteger.class,
+            Float.class,
+            Double.class,
+            BigDecimal.class
+    };
+
+    private static final Comparator<Comparable> naturalOrderComparator = Comparator.naturalOrder();
+
+    /**
+     * This comparator does not provide a stable order for numerics because of type promotion equivalence semantics.
+     */
+    private static final Comparator<Number> numberComparator = (f,s) -> NumberHelper.compare(f, s);
+
+    /**
+     * This alternative numeric comparator will sort by numeric type in the case of type promotion equivalence.
+     * Currently unused.
+     */
+    private static final Comparator<Number> stableOrderNumberComparator = (f,s) -> {
+        final int i = NumberHelper.compare(f, s);
+        if (i != 0 || f.getClass().equals(s.getClass())) {
+            // they're not equal, or they are of the same numeric type
+            return i;
+        }
+        // if they are equal but of different types, order by type
+        final int ft = type(numerics, f);
+        final int st = type(numerics, s);
+        return ft - st;
+    };
+
+    /**
+     * Sort Vertex, Edge, VertexProperty by id.
+     */
+    private static final Comparator<Element> elementComparator =
+            Comparator.comparing(Element::id, INSTANCE);
+
+    /**
+     * Sort Property first by key, then by value.
+     */
+    private static final Comparator<Property> propertyComparator =
+            Comparator.<Property,Object>comparing(Property::key, INSTANCE).thenComparing(Property::value, INSTANCE);
+
+    /**
+     * Sort List, Set, Path, and Map element-by-element in the order presented by their natural iterator.
+     */
+    private static final Comparator<Iterable> iteratableComparator = (f, s) -> {
+        final Iterator fi = f.iterator();
+        final Iterator si = s.iterator();
+
+        while (fi.hasNext() && si.hasNext()) {
+            final int i = INSTANCE.compare(fi.next(), si.next());
+            if (i != 0) {
+                return i;
+            }
+        }
+
+        return fi.hasNext() ? 1 : si.hasNext() ? -1 : 0;
+    };
+
+    /**
+     * Sort Map by entry-set.
+     */
+    private static final Comparator<Map> mapComparator =
+            Comparator.comparing(Map::entrySet, iteratableComparator);
+
+    /**
+     * Sort Map.Entry first by key, then by value.
+     */
+    private static final Comparator<Map.Entry> entryComparator =
+            Comparator.<Map.Entry,Object>comparing(Map.Entry::getKey, INSTANCE).thenComparing(Map.Entry::getValue, INSTANCE);
+
+    /**
+     * Sort unknown types first by classname, then by natural toString().
+     */
+    private static final Comparator<Object> unknownTypeComparator =
+            Comparator.comparing(f -> f.getClass().getName()).thenComparing(Object::toString);
+
+    /**
+     * The comparators that will be used for the types defined above in the {@link #types} array. Be sure to keep them

Review comment:
       optional suggestion:
   We can avoid potential bugs due to out of sync arrays by storing the mapping btw types and comparators in a LinkedHashMap<Class, Comparator>.

##########
File path: gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/OrderabilityComparator.java
##########
@@ -0,0 +1,234 @@
+/*
+ * 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.util;
+
+import org.apache.tinkerpop.gremlin.process.traversal.Path;
+import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
+import org.apache.tinkerpop.gremlin.structure.Edge;
+import org.apache.tinkerpop.gremlin.structure.Element;
+import org.apache.tinkerpop.gremlin.structure.Property;
+import org.apache.tinkerpop.gremlin.structure.Vertex;
+import org.apache.tinkerpop.gremlin.structure.VertexProperty;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.Comparator;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
+
+/**
+ * An implementation of the Comparability/Orderability semantics as defined in the Apache TinkerPop Provider
+ * documentation.
+ *
+ * @author Mike Personick
+ */
+public class OrderabilityComparator implements Comparator<Object> {
+
+    public static final Comparator<Object> INSTANCE = Comparator.comparing(
+            // first transform (strip Traverser layer)
+            OrderabilityComparator::transform,
+                    // then handle nulls
+                    Comparator.nullsFirst(
+                            // then consider orderability
+                            new OrderabilityComparator()));
+
+    /**
+     * The order of this array determines the sort order across types.The index in this array corresponds directly to a
+     * Comparator in the {@link #comparators} array below, so be sure to keep them in sync.
+     */
+    private static final Class[] types = new Class[] {
+            Boolean.class,
+            Number.class,
+            Date.class,
+            String.class,
+            UUID.class,
+            Vertex.class,
+            Edge.class,
+            VertexProperty.class,
+            Property.class,
+            Path.class,
+            Set.class,
+            List.class,
+            Map.class,
+            Map.Entry.class,
+    };
+
+    /**
+     * The stable ordering for numeric types, should we choose to support stable ordering for numeric types.
+     */
+    private static final Class[] numerics = new Class[] {
+            Byte.class,
+            Short.class,
+            Integer.class,
+            Long.class,
+            BigInteger.class,
+            Float.class,
+            Double.class,
+            BigDecimal.class
+    };
+
+    private static final Comparator<Comparable> naturalOrderComparator = Comparator.naturalOrder();
+
+    /**
+     * This comparator does not provide a stable order for numerics because of type promotion equivalence semantics.
+     */
+    private static final Comparator<Number> numberComparator = (f,s) -> NumberHelper.compare(f, s);
+
+    /**
+     * This alternative numeric comparator will sort by numeric type in the case of type promotion equivalence.
+     * Currently unused.
+     */
+    private static final Comparator<Number> stableOrderNumberComparator = (f,s) -> {
+        final int i = NumberHelper.compare(f, s);
+        if (i != 0 || f.getClass().equals(s.getClass())) {
+            // they're not equal, or they are of the same numeric type
+            return i;
+        }
+        // if they are equal but of different types, order by type
+        final int ft = type(numerics, f);
+        final int st = type(numerics, s);
+        return ft - st;
+    };
+
+    /**
+     * Sort Vertex, Edge, VertexProperty by id.
+     */
+    private static final Comparator<Element> elementComparator =
+            Comparator.comparing(Element::id, INSTANCE);
+
+    /**
+     * Sort Property first by key, then by value.
+     */
+    private static final Comparator<Property> propertyComparator =
+            Comparator.<Property,Object>comparing(Property::key, INSTANCE).thenComparing(Property::value, INSTANCE);
+
+    /**
+     * Sort List, Set, Path, and Map element-by-element in the order presented by their natural iterator.
+     */
+    private static final Comparator<Iterable> iteratableComparator = (f, s) -> {
+        final Iterator fi = f.iterator();
+        final Iterator si = s.iterator();
+
+        while (fi.hasNext() && si.hasNext()) {
+            final int i = INSTANCE.compare(fi.next(), si.next());
+            if (i != 0) {
+                return i;
+            }
+        }
+
+        return fi.hasNext() ? 1 : si.hasNext() ? -1 : 0;
+    };
+
+    /**
+     * Sort Map by entry-set.
+     */
+    private static final Comparator<Map> mapComparator =
+            Comparator.comparing(Map::entrySet, iteratableComparator);
+
+    /**
+     * Sort Map.Entry first by key, then by value.
+     */
+    private static final Comparator<Map.Entry> entryComparator =
+            Comparator.<Map.Entry,Object>comparing(Map.Entry::getKey, INSTANCE).thenComparing(Map.Entry::getValue, INSTANCE);
+
+    /**
+     * Sort unknown types first by classname, then by natural toString().
+     */
+    private static final Comparator<Object> unknownTypeComparator =
+            Comparator.comparing(f -> f.getClass().getName()).thenComparing(Object::toString);
+
+    /**
+     * The comparators that will be used for the types defined above in the {@link #types} array. Be sure to keep them
+     * in sync.
+     */
+    private static final Comparator[] comparators = new Comparator[] {
+        naturalOrderComparator,          // Boolean.class,
+        numberComparator,                // Number.class,
+        naturalOrderComparator,          // Date.class,
+        naturalOrderComparator,          // String.class,
+        naturalOrderComparator,          // UUID.class,
+        elementComparator,               // Vertex.class,
+        elementComparator,               // Edge.class,
+        elementComparator,               // VertexProperty.class,
+        propertyComparator,              // Property.class,
+        iteratableComparator,            // Path.class,
+        iteratableComparator,            // Set.class,
+        iteratableComparator,            // List.class,
+        mapComparator,                   // Map.class,
+        entryComparator,                 // Map.Entry.class,
+    };
+
+    /**
+     * Marker priority for unknown types. A large number means they will appear after known types. Use -1 if you want
+     * them to appear first.
+     */
+    private static final int UNKNOWN_TYPE = 0xffff;
+
+    /**
+     * Return the first index of the Class array for which the supplied object is an instance. Returns
+     * {@link #UNKNOWN_TYPE} if not an instance of any of the supplied classes.
+     */
+    private static final int type(final Class[] types, final Object o) {
+        for (int i = 0; i < types.length; i++) {
+            if (types[i].isInstance(o)) {
+                return i;
+            }
+        }
+        return UNKNOWN_TYPE;

Review comment:
       What are the cases where we legitimately expect an unknown type? It should probably be an exception if we are dealing with a type not defined in the semantics. 

##########
File path: gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/OrderabilityTest.java
##########
@@ -0,0 +1,537 @@
+/*
+ * 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.LoadGraphWith;
+import org.apache.tinkerpop.gremlin.process.AbstractGremlinProcessTest;
+import org.apache.tinkerpop.gremlin.process.GremlinProcessRunner;
+import org.apache.tinkerpop.gremlin.process.traversal.Order;
+import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
+import org.apache.tinkerpop.gremlin.structure.Edge;
+import org.apache.tinkerpop.gremlin.structure.Property;
+import org.apache.tinkerpop.gremlin.structure.Vertex;
+import org.junit.Assert;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.apache.tinkerpop.gremlin.LoadGraphWith.GraphData.MODERN;
+
+import java.util.Arrays;
+import java.util.Date;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.stream.Collectors;
+
+@RunWith(GremlinProcessRunner.class)
+public abstract class OrderabilityTest extends AbstractGremlinProcessTest {
+
+    private interface Constants {
+        UUID uuid = UUID.randomUUID();
+        Date date = new Date();
+        List list1 = Arrays.asList(1, 2, 3);
+        List list2 = Arrays.asList(1, 2, 3, 4);
+        Set set1 = new LinkedHashSet(list1);
+        Set set2 = new LinkedHashSet(list2);
+        Map map1 = new LinkedHashMap() {{
+            put(1, 11);
+            put(2, 22);
+            put(3, false);
+            put(4, 44);
+        }};
+        Map map2 = new LinkedHashMap() {{
+            put(1, 11);
+            put(2, 22);
+            put(3, 33);
+        }};
+
+        Object[] unordered = { map2, 1, map1, "foo", null, list1, date, set1, list2, true, uuid, "bar", 2.0, false, set2 };
+    }
+
+    public abstract Traversal<Vertex, Object> get_g_V_values_order();
+
+    public abstract Traversal<Vertex, ? extends Property> get_g_V_properties_order();
+
+    public abstract Traversal<Edge, Object> get_g_E_properties_order_value();
+
+    public abstract Traversal<Edge, Object> get_g_E_properties_order_byXdescX_value();
+
+    public abstract Traversal<Object, Object> get_g_inject_order();
+
+    // order asc by vertex: v[3], v[5]
+    public abstract Traversal<Vertex, Vertex> get_g_V_out_out_order_byXascX();
+
+    // order asc by vertex in path: v[3], v[5]
+    public abstract Traversal<Vertex, Vertex> get_g_V_out_out_asXheadX_path_order_byXascX_selectXheadX();
+
+    // order asc by edge: e[10], v[e11]
+    public abstract Traversal<Vertex, Edge> get_g_V_out_outE_order_byXascX();
+
+    // order asc by edge in path: e[10], e[11]
+    public abstract Traversal<Vertex, Edge> get_g_V_out_outE_asXheadX_path_order_byXascX_selectXheadX();
+
+    // order asc by vertex and then vertex property id in path.
+    public abstract Traversal<Vertex, Object> get_g_V_out_out_properties_asXheadX_path_order_byXascX_selectXheadX_value();
+
+    // order asc by vertex and then vertex property value in path.
+    public abstract Traversal<Vertex, Object> get_g_V_out_out_values_asXheadX_path_order_byXascX_selectXheadX();
+
+    // order desc by vertex: v[3], v[5]
+    public abstract Traversal<Vertex, Vertex> get_g_V_out_out_order_byXdescX();
+
+    // order desc by vertex in path: v[3], v[5]
+    public abstract Traversal<Vertex, Vertex> get_g_V_out_out_asXheadX_path_order_byXdescX_selectXheadX();
+
+    // order desc by edge: e[10], v[e11]
+    public abstract Traversal<Vertex, Edge> get_g_V_out_outE_order_byXdescX();
+
+    // order desc by edge in path: e[10], e[11]
+    public abstract Traversal<Vertex, Edge> get_g_V_out_outE_asXheadX_path_order_byXdescX_selectXheadX();
+
+    // order desc by vertex and then vertex property id in path.
+    public abstract Traversal<Vertex, Object> get_g_V_out_out_properties_asXheadX_path_order_byXdescX_selectXheadX_value();
+
+    // order desc by vertex and then vertex property value in path.
+    public abstract Traversal<Vertex, Object> get_g_V_out_out_values_asXheadX_path_order_byXdescX_selectXheadX();
+
+    /**
+     * Order by property value (mixed types).
+     */
+    @Test
+    @LoadGraphWith(MODERN)
+    public void g_V_values_order() {
+        final Traversal<Vertex, Object> traversal = get_g_V_values_order();
+        printTraversalForm(traversal);
+        checkOrderedResults(Arrays.asList(
+                27, 29, 32, 35, "java", "java", "josh", "lop", "marko", "peter", "ripple", "vadas"
+        ), traversal);
+    }
+
+    /**
+     * Order by vertex property (orders by id).
+     */
+    @Test
+    @LoadGraphWith(MODERN)
+    public void g_V_properties_order() {
+        final Traversal traversal = get_g_V_properties_order();
+        printTraversalForm(traversal);
+        checkOrderedResults(Arrays.asList(
+                convertToVertexProperty("marko", "name", "marko"),    // vpid = 0
+                convertToVertexProperty("marko", "age", 29),          // vpid = 1
+                convertToVertexProperty("vadas", "name", "vadas"),    // vpid = 2
+                convertToVertexProperty("vadas", "age", 27),          // vpid = 3
+                convertToVertexProperty("lop", "name", "lop"),        // vpid = 4
+                convertToVertexProperty("lop", "lang", "java"),       // vpid = 5
+                convertToVertexProperty("josh", "name", "josh"),      // vpid = 6
+                convertToVertexProperty("josh", "age", 32),           // vpid = 7
+                convertToVertexProperty("ripple", "name", "ripple"),  // vpid = 8
+                convertToVertexProperty("ripple", "lang", "java"),    // vpid = 9
+                convertToVertexProperty("peter", "name", "peter"),    // vpid = 10
+                convertToVertexProperty("peter", "age", 35)           // vpid = 11
+        ), traversal);
+    }
+
+    /**
+     * Order by edge property (orders by key, then value).
+     */
+    @Test
+    @LoadGraphWith(MODERN)
+    public void g_E_properties_order_value() {
+        { // add some more edge properties
+            final AtomicInteger a = new AtomicInteger();
+            g.E().forEachRemaining(e -> e.property("a", a.getAndIncrement()));
+        }
+
+        final Traversal asc = get_g_E_properties_order_value();
+        printTraversalForm(asc);
+        checkOrderedResults(Arrays.asList(
+                0, 1, 2, 3, 4, 5, 0.2, 0.4, 0.4, 0.5, 1.0, 1.0
+        ), asc);
+
+        final Traversal desc = get_g_E_properties_order_byXdescX_value();
+        printTraversalForm(desc);
+        checkOrderedResults(Arrays.asList(
+                1.0, 1.0, 0.5, 0.4, 0.4, 0.2, 5, 4, 3, 2, 1, 0
+        ), desc);
+    }
+
+    /**
+     * Mixed type values including list, set, map, uuid, date, boolean, numeric, string, null.
+     */
+    @Test
+    public void g_inject_order() {
+        final Traversal traversal = get_g_inject_order();
+        printTraversalForm(traversal);
+        checkOrderedResults(Arrays.asList(
+                null,
+                false, true,
+                1, 2.0,
+                Constants.date,
+                "bar", "foo",
+                Constants.uuid,
+                Constants.set1, Constants.set2,
+                Constants.list1, Constants.list2,
+                Constants.map1, Constants.map2
+        ), traversal);
+    }
+
+    /**
+     * More mixed type values including a Java Object (unknown type).
+     */
+    @Test
+    public void g_inject_order_with_unknown_type() {
+        final Object unknown = new Object();
+        final Object[] unordered = new Object[Constants.unordered.length+1];
+        unordered[0] = unknown;
+        System.arraycopy(Constants.unordered, 0, unordered, 1, Constants.unordered.length);
+
+        final Traversal traversal = g.inject(unordered).order();
+        printTraversalForm(traversal);
+        checkOrderedResults(Arrays.asList(
+                null,
+                false, true,
+                1, 2.0,
+                Constants.date,
+                "bar", "foo",
+                Constants.uuid,
+                Constants.set1, Constants.set2,
+                Constants.list1, Constants.list2,
+                Constants.map1, Constants.map2,
+                unknown
+        ), traversal);
+    }
+
+    /**
+     * Order asc by vertex: v[3], v[5]
+     *
+     * Note to graph providers: if your graph does not support user-assigned vertex ids you may need to
+     * skip this test.
+     */
+    @Test
+    @LoadGraphWith(MODERN)
+    public void g_V_out_out_order_byXascX() {
+        final Traversal traversal = get_g_V_out_out_order_byXascX();
+        printTraversalForm(traversal);
+        checkOrderedResults(Arrays.asList(
+                convertToVertex("lop"),         // vid = 3
+                convertToVertex("ripple")       // vid = 5
+        ), traversal);
+    }
+
+    /**
+     * Order asc by vertex in path: v[3], v[5]
+     *
+     * Note to graph providers: if your graph does not support user-assigned vertex ids you may need to
+     * skip this test.
+     */
+    @Test
+    @LoadGraphWith(MODERN)
+    public void g_V_out_out_asXheadX_path_order_byXascX_selectXheadX() {
+        final Traversal traversal = get_g_V_out_out_asXheadX_path_order_byXascX_selectXheadX();
+        printTraversalForm(traversal);
+        checkOrderedResults(Arrays.asList(
+                convertToVertex("lop"),         // vid = 3
+                convertToVertex("ripple")       // vid = 5
+        ), traversal);
+    }
+
+    /**
+     * Order asc by edge: e[10], v[e11]
+     *
+     * Note to graph providers: if your graph does not support user-assigned edge ids you may need to
+     * skip this test.
+     */
+    @Test
+    @LoadGraphWith(MODERN)
+    public void g_V_out_outE_order_byXascX() {
+        final Traversal traversal = get_g_V_out_outE_order_byXascX();
+        printTraversalForm(traversal);
+        checkOrderedResults(Arrays.asList(
+                convertToEdge("josh", "created", "ripple"),      // eid = 10
+                convertToEdge("josh", "created", "lop")          // eid = 11
+        ), traversal);
+    }
+
+    /**
+     * Order asc by edge in path: e[10], e[11]
+     *
+     * Note to graph providers: if your graph does not support user-assigned edge ids you may need to
+     * skip this test.
+     */
+    @Test
+    @LoadGraphWith(MODERN)
+    public void g_V_out_outE_asXheadX_path_order_byXascX_selectXheadX() {
+        final Traversal traversal = get_g_V_out_outE_asXheadX_path_order_byXascX_selectXheadX();
+        printTraversalForm(traversal);
+        checkOrderedResults(Arrays.asList(
+                convertToEdge("josh", "created", "ripple"),      // eid = 10
+                convertToEdge("josh", "created", "lop")          // eid = 11
+        ), traversal);
+    }
+
+    /**
+     * Order asc by vertex and then vertex property id in path.
+     *
+     * Note to graph providers: if your graph does not support user-assigned vertex ids and vertex property ids you 
+     * may need to skip this test.
+     */
+    @Test
+    @LoadGraphWith(MODERN)
+    public void g_V_out_out_properties_asXheadX_path_order_byXascX_selectXheadX_value() {
+        final Traversal traversal = get_g_V_out_out_properties_asXheadX_path_order_byXascX_selectXheadX_value();
+        printTraversalForm(traversal);
+        checkOrderedResults(Arrays.asList(
+                "lop",      // vid = 3, vpid = 4
+                "java",     // vid = 3, vpid = 5
+                "ripple",   // vid = 5, vpid = 8
+                "java"      // vid = 5, vpid = 9
+        ), traversal);
+    }
+
+    /**
+     * Order asc by vertex and then vertex property value in path.
+     *
+     * Note to graph providers: if your graph does not support user-assigned vertex ids you may need to
+     * skip this test.
+     */
+    @Test
+    @LoadGraphWith(MODERN)
+    public void g_V_out_out_values_asXheadX_path_order_byXascX_selectXheadX() {
+        final Traversal traversal = get_g_V_out_out_values_asXheadX_path_order_byXascX_selectXheadX();
+        printTraversalForm(traversal);
+        checkOrderedResults(Arrays.asList(
+                "java",     // vid = 3, val = "java"
+                "lop",      // vid = 3, val = "lop"
+                "java",     // vid = 5, val = "java"
+                "ripple"    // vid = 5, val = "ripple"
+        ), traversal);
+    }
+
+    /**
+     * Order desc by vertex: v[5], v[3]
+     *
+     * Note to graph providers: if your graph does not support user-assigned vertex ids you may need to
+     * skip this test.
+     */
+    @Test
+    @LoadGraphWith(MODERN)
+    public void g_V_out_out_order_byXdescX() {
+        final Traversal traversal = get_g_V_out_out_order_byXdescX();
+        printTraversalForm(traversal);
+        checkOrderedResults(Arrays.asList(
+                convertToVertex("ripple"),     // vid = 5
+                convertToVertex("lop")         // vid = 3
+        ), traversal);
+    }
+
+    /**
+     * Order desc by vertex in path: v[5], v[3]
+     *
+     * Note to graph providers: if your graph does not support user-assigned vertex ids you may need to
+     * skip this test.
+     */
+    @Test
+    @LoadGraphWith(MODERN)
+    public void g_V_out_out_asXheadX_path_order_byXdescX_selectXheadX() {
+        final Traversal traversal = get_g_V_out_out_asXheadX_path_order_byXdescX_selectXheadX();
+        printTraversalForm(traversal);
+        checkOrderedResults(Arrays.asList(
+                convertToVertex("ripple"),     // vid = 5
+                convertToVertex("lop")         // vid = 3
+        ), traversal);
+    }
+
+    /**
+     * Order desc by edge: e[11], v[e10]
+     *
+     * Note to graph providers: if your graph does not support user-assigned edge ids you may need to
+     * skip this test.
+     */
+    @Test
+    @LoadGraphWith(MODERN)
+    public void g_V_out_outE_order_byXdescX() {
+        final Traversal traversal = get_g_V_out_outE_order_byXdescX();
+        printTraversalForm(traversal);
+        checkOrderedResults(Arrays.asList(
+                convertToEdge("josh", "created", "lop"),        // eid = 11
+                convertToEdge("josh", "created", "ripple")      // eid = 10
+        ), traversal);
+    }
+
+    /**
+     * Order desc by edge in path: e[11], e[10]
+     *
+     * Note to graph providers: if your graph does not support user-assigned edge ids you may need to
+     * skip this test.
+     */
+    @Test
+    @LoadGraphWith(MODERN)
+    public void g_V_out_outE_asXheadX_path_order_byXdescX_selectXheadX() {
+        final Traversal traversal = get_g_V_out_outE_asXheadX_path_order_byXdescX_selectXheadX();
+        printTraversalForm(traversal);
+        checkOrderedResults(Arrays.asList(
+                convertToEdge("josh", "created", "lop"),        // eid = 11
+                convertToEdge("josh", "created", "ripple")      // eid = 10
+        ), traversal);
+    }
+
+    /**
+     * Order desc by vertex and then vertex property id in path.
+     *
+     * Note to graph providers: if your graph does not support user-assigned vertex ids and vertex property ids you 

Review comment:
       you can already check the feature support in the tests using `@FeatureRequirement` annotation.
   
   ```
   @FeatureRequirement(featureClass = ElementFeatures.class, feature = FEATURE_USER_SUPPLIED_IDS)
   ```

##########
File path: gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/OrderabilityComparator.java
##########
@@ -0,0 +1,234 @@
+/*
+ * 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.util;
+
+import org.apache.tinkerpop.gremlin.process.traversal.Path;
+import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
+import org.apache.tinkerpop.gremlin.structure.Edge;
+import org.apache.tinkerpop.gremlin.structure.Element;
+import org.apache.tinkerpop.gremlin.structure.Property;
+import org.apache.tinkerpop.gremlin.structure.Vertex;
+import org.apache.tinkerpop.gremlin.structure.VertexProperty;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.Comparator;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
+
+/**
+ * An implementation of the Comparability/Orderability semantics as defined in the Apache TinkerPop Provider
+ * documentation.
+ *
+ * @author Mike Personick
+ */
+public class OrderabilityComparator implements Comparator<Object> {
+
+    public static final Comparator<Object> INSTANCE = Comparator.comparing(
+            // first transform (strip Traverser layer)
+            OrderabilityComparator::transform,
+                    // then handle nulls
+                    Comparator.nullsFirst(

Review comment:
       nulls go last for desc. Please add a unit test if not already present.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@tinkerpop.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [tinkerpop] mikepersonick commented on a change in pull request #1543: Orderability Semantics

Posted by GitBox <gi...@apache.org>.
mikepersonick commented on a change in pull request #1543:
URL: https://github.com/apache/tinkerpop/pull/1543#discussion_r782200455



##########
File path: gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/OrderabilityComparator.java
##########
@@ -0,0 +1,234 @@
+/*
+ * 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.util;
+
+import org.apache.tinkerpop.gremlin.process.traversal.Path;
+import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
+import org.apache.tinkerpop.gremlin.structure.Edge;
+import org.apache.tinkerpop.gremlin.structure.Element;
+import org.apache.tinkerpop.gremlin.structure.Property;
+import org.apache.tinkerpop.gremlin.structure.Vertex;
+import org.apache.tinkerpop.gremlin.structure.VertexProperty;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.Comparator;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
+
+/**
+ * An implementation of the Comparability/Orderability semantics as defined in the Apache TinkerPop Provider
+ * documentation.
+ *
+ * @author Mike Personick
+ */
+public class OrderabilityComparator implements Comparator<Object> {
+
+    public static final Comparator<Object> INSTANCE = Comparator.comparing(
+            // first transform (strip Traverser layer)
+            OrderabilityComparator::transform,
+                    // then handle nulls
+                    Comparator.nullsFirst(

Review comment:
       It is handled in Order.desc. Added a test.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@tinkerpop.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [tinkerpop] mikepersonick commented on a change in pull request #1543: Orderability Semantics

Posted by GitBox <gi...@apache.org>.
mikepersonick commented on a change in pull request #1543:
URL: https://github.com/apache/tinkerpop/pull/1543#discussion_r782257294



##########
File path: gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/OrderabilityTest.java
##########
@@ -0,0 +1,537 @@
+/*
+ * 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.LoadGraphWith;
+import org.apache.tinkerpop.gremlin.process.AbstractGremlinProcessTest;
+import org.apache.tinkerpop.gremlin.process.GremlinProcessRunner;
+import org.apache.tinkerpop.gremlin.process.traversal.Order;
+import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
+import org.apache.tinkerpop.gremlin.structure.Edge;
+import org.apache.tinkerpop.gremlin.structure.Property;
+import org.apache.tinkerpop.gremlin.structure.Vertex;
+import org.junit.Assert;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.apache.tinkerpop.gremlin.LoadGraphWith.GraphData.MODERN;
+
+import java.util.Arrays;
+import java.util.Date;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.stream.Collectors;
+
+@RunWith(GremlinProcessRunner.class)
+public abstract class OrderabilityTest extends AbstractGremlinProcessTest {
+
+    private interface Constants {
+        UUID uuid = UUID.randomUUID();
+        Date date = new Date();
+        List list1 = Arrays.asList(1, 2, 3);
+        List list2 = Arrays.asList(1, 2, 3, 4);
+        Set set1 = new LinkedHashSet(list1);
+        Set set2 = new LinkedHashSet(list2);
+        Map map1 = new LinkedHashMap() {{
+            put(1, 11);
+            put(2, 22);
+            put(3, false);
+            put(4, 44);
+        }};
+        Map map2 = new LinkedHashMap() {{
+            put(1, 11);
+            put(2, 22);
+            put(3, 33);
+        }};
+
+        Object[] unordered = { map2, 1, map1, "foo", null, list1, date, set1, list2, true, uuid, "bar", 2.0, false, set2 };
+    }
+
+    public abstract Traversal<Vertex, Object> get_g_V_values_order();
+
+    public abstract Traversal<Vertex, ? extends Property> get_g_V_properties_order();
+
+    public abstract Traversal<Edge, Object> get_g_E_properties_order_value();
+
+    public abstract Traversal<Edge, Object> get_g_E_properties_order_byXdescX_value();
+
+    public abstract Traversal<Object, Object> get_g_inject_order();
+
+    // order asc by vertex: v[3], v[5]
+    public abstract Traversal<Vertex, Vertex> get_g_V_out_out_order_byXascX();
+
+    // order asc by vertex in path: v[3], v[5]
+    public abstract Traversal<Vertex, Vertex> get_g_V_out_out_asXheadX_path_order_byXascX_selectXheadX();
+
+    // order asc by edge: e[10], v[e11]
+    public abstract Traversal<Vertex, Edge> get_g_V_out_outE_order_byXascX();
+
+    // order asc by edge in path: e[10], e[11]
+    public abstract Traversal<Vertex, Edge> get_g_V_out_outE_asXheadX_path_order_byXascX_selectXheadX();
+
+    // order asc by vertex and then vertex property id in path.
+    public abstract Traversal<Vertex, Object> get_g_V_out_out_properties_asXheadX_path_order_byXascX_selectXheadX_value();
+
+    // order asc by vertex and then vertex property value in path.
+    public abstract Traversal<Vertex, Object> get_g_V_out_out_values_asXheadX_path_order_byXascX_selectXheadX();
+
+    // order desc by vertex: v[3], v[5]
+    public abstract Traversal<Vertex, Vertex> get_g_V_out_out_order_byXdescX();
+
+    // order desc by vertex in path: v[3], v[5]
+    public abstract Traversal<Vertex, Vertex> get_g_V_out_out_asXheadX_path_order_byXdescX_selectXheadX();
+
+    // order desc by edge: e[10], v[e11]
+    public abstract Traversal<Vertex, Edge> get_g_V_out_outE_order_byXdescX();
+
+    // order desc by edge in path: e[10], e[11]
+    public abstract Traversal<Vertex, Edge> get_g_V_out_outE_asXheadX_path_order_byXdescX_selectXheadX();
+
+    // order desc by vertex and then vertex property id in path.
+    public abstract Traversal<Vertex, Object> get_g_V_out_out_properties_asXheadX_path_order_byXdescX_selectXheadX_value();
+
+    // order desc by vertex and then vertex property value in path.
+    public abstract Traversal<Vertex, Object> get_g_V_out_out_values_asXheadX_path_order_byXdescX_selectXheadX();
+
+    /**
+     * Order by property value (mixed types).
+     */
+    @Test
+    @LoadGraphWith(MODERN)
+    public void g_V_values_order() {
+        final Traversal<Vertex, Object> traversal = get_g_V_values_order();
+        printTraversalForm(traversal);
+        checkOrderedResults(Arrays.asList(
+                27, 29, 32, 35, "java", "java", "josh", "lop", "marko", "peter", "ripple", "vadas"
+        ), traversal);
+    }
+
+    /**
+     * Order by vertex property (orders by id).
+     */
+    @Test
+    @LoadGraphWith(MODERN)
+    public void g_V_properties_order() {
+        final Traversal traversal = get_g_V_properties_order();
+        printTraversalForm(traversal);
+        checkOrderedResults(Arrays.asList(
+                convertToVertexProperty("marko", "name", "marko"),    // vpid = 0
+                convertToVertexProperty("marko", "age", 29),          // vpid = 1
+                convertToVertexProperty("vadas", "name", "vadas"),    // vpid = 2
+                convertToVertexProperty("vadas", "age", 27),          // vpid = 3
+                convertToVertexProperty("lop", "name", "lop"),        // vpid = 4
+                convertToVertexProperty("lop", "lang", "java"),       // vpid = 5
+                convertToVertexProperty("josh", "name", "josh"),      // vpid = 6
+                convertToVertexProperty("josh", "age", 32),           // vpid = 7
+                convertToVertexProperty("ripple", "name", "ripple"),  // vpid = 8
+                convertToVertexProperty("ripple", "lang", "java"),    // vpid = 9
+                convertToVertexProperty("peter", "name", "peter"),    // vpid = 10
+                convertToVertexProperty("peter", "age", 35)           // vpid = 11
+        ), traversal);
+    }
+
+    /**
+     * Order by edge property (orders by key, then value).
+     */
+    @Test
+    @LoadGraphWith(MODERN)
+    public void g_E_properties_order_value() {
+        { // add some more edge properties
+            final AtomicInteger a = new AtomicInteger();
+            g.E().forEachRemaining(e -> e.property("a", a.getAndIncrement()));
+        }
+
+        final Traversal asc = get_g_E_properties_order_value();
+        printTraversalForm(asc);
+        checkOrderedResults(Arrays.asList(
+                0, 1, 2, 3, 4, 5, 0.2, 0.4, 0.4, 0.5, 1.0, 1.0
+        ), asc);
+
+        final Traversal desc = get_g_E_properties_order_byXdescX_value();
+        printTraversalForm(desc);
+        checkOrderedResults(Arrays.asList(
+                1.0, 1.0, 0.5, 0.4, 0.4, 0.2, 5, 4, 3, 2, 1, 0
+        ), desc);
+    }
+
+    /**
+     * Mixed type values including list, set, map, uuid, date, boolean, numeric, string, null.
+     */
+    @Test
+    public void g_inject_order() {
+        final Traversal traversal = get_g_inject_order();
+        printTraversalForm(traversal);
+        checkOrderedResults(Arrays.asList(
+                null,
+                false, true,
+                1, 2.0,
+                Constants.date,
+                "bar", "foo",
+                Constants.uuid,
+                Constants.set1, Constants.set2,
+                Constants.list1, Constants.list2,
+                Constants.map1, Constants.map2
+        ), traversal);
+    }
+
+    /**
+     * More mixed type values including a Java Object (unknown type).
+     */
+    @Test
+    public void g_inject_order_with_unknown_type() {
+        final Object unknown = new Object();
+        final Object[] unordered = new Object[Constants.unordered.length+1];
+        unordered[0] = unknown;
+        System.arraycopy(Constants.unordered, 0, unordered, 1, Constants.unordered.length);
+
+        final Traversal traversal = g.inject(unordered).order();
+        printTraversalForm(traversal);
+        checkOrderedResults(Arrays.asList(
+                null,
+                false, true,
+                1, 2.0,
+                Constants.date,
+                "bar", "foo",
+                Constants.uuid,
+                Constants.set1, Constants.set2,
+                Constants.list1, Constants.list2,
+                Constants.map1, Constants.map2,
+                unknown
+        ), traversal);
+    }
+
+    /**
+     * Order asc by vertex: v[3], v[5]
+     *
+     * Note to graph providers: if your graph does not support user-assigned vertex ids you may need to
+     * skip this test.
+     */
+    @Test
+    @LoadGraphWith(MODERN)
+    public void g_V_out_out_order_byXascX() {
+        final Traversal traversal = get_g_V_out_out_order_byXascX();
+        printTraversalForm(traversal);
+        checkOrderedResults(Arrays.asList(
+                convertToVertex("lop"),         // vid = 3
+                convertToVertex("ripple")       // vid = 5
+        ), traversal);
+    }
+
+    /**
+     * Order asc by vertex in path: v[3], v[5]
+     *
+     * Note to graph providers: if your graph does not support user-assigned vertex ids you may need to
+     * skip this test.
+     */
+    @Test
+    @LoadGraphWith(MODERN)
+    public void g_V_out_out_asXheadX_path_order_byXascX_selectXheadX() {
+        final Traversal traversal = get_g_V_out_out_asXheadX_path_order_byXascX_selectXheadX();
+        printTraversalForm(traversal);
+        checkOrderedResults(Arrays.asList(
+                convertToVertex("lop"),         // vid = 3
+                convertToVertex("ripple")       // vid = 5
+        ), traversal);
+    }
+
+    /**
+     * Order asc by edge: e[10], v[e11]
+     *
+     * Note to graph providers: if your graph does not support user-assigned edge ids you may need to
+     * skip this test.
+     */
+    @Test
+    @LoadGraphWith(MODERN)
+    public void g_V_out_outE_order_byXascX() {
+        final Traversal traversal = get_g_V_out_outE_order_byXascX();
+        printTraversalForm(traversal);
+        checkOrderedResults(Arrays.asList(
+                convertToEdge("josh", "created", "ripple"),      // eid = 10
+                convertToEdge("josh", "created", "lop")          // eid = 11
+        ), traversal);
+    }
+
+    /**
+     * Order asc by edge in path: e[10], e[11]
+     *
+     * Note to graph providers: if your graph does not support user-assigned edge ids you may need to
+     * skip this test.
+     */
+    @Test
+    @LoadGraphWith(MODERN)
+    public void g_V_out_outE_asXheadX_path_order_byXascX_selectXheadX() {
+        final Traversal traversal = get_g_V_out_outE_asXheadX_path_order_byXascX_selectXheadX();
+        printTraversalForm(traversal);
+        checkOrderedResults(Arrays.asList(
+                convertToEdge("josh", "created", "ripple"),      // eid = 10
+                convertToEdge("josh", "created", "lop")          // eid = 11
+        ), traversal);
+    }
+
+    /**
+     * Order asc by vertex and then vertex property id in path.
+     *
+     * Note to graph providers: if your graph does not support user-assigned vertex ids and vertex property ids you 
+     * may need to skip this test.
+     */
+    @Test
+    @LoadGraphWith(MODERN)
+    public void g_V_out_out_properties_asXheadX_path_order_byXascX_selectXheadX_value() {
+        final Traversal traversal = get_g_V_out_out_properties_asXheadX_path_order_byXascX_selectXheadX_value();
+        printTraversalForm(traversal);
+        checkOrderedResults(Arrays.asList(
+                "lop",      // vid = 3, vpid = 4
+                "java",     // vid = 3, vpid = 5
+                "ripple",   // vid = 5, vpid = 8
+                "java"      // vid = 5, vpid = 9
+        ), traversal);
+    }
+
+    /**
+     * Order asc by vertex and then vertex property value in path.
+     *
+     * Note to graph providers: if your graph does not support user-assigned vertex ids you may need to
+     * skip this test.
+     */
+    @Test
+    @LoadGraphWith(MODERN)
+    public void g_V_out_out_values_asXheadX_path_order_byXascX_selectXheadX() {
+        final Traversal traversal = get_g_V_out_out_values_asXheadX_path_order_byXascX_selectXheadX();
+        printTraversalForm(traversal);
+        checkOrderedResults(Arrays.asList(
+                "java",     // vid = 3, val = "java"
+                "lop",      // vid = 3, val = "lop"
+                "java",     // vid = 5, val = "java"
+                "ripple"    // vid = 5, val = "ripple"
+        ), traversal);
+    }
+
+    /**
+     * Order desc by vertex: v[5], v[3]
+     *
+     * Note to graph providers: if your graph does not support user-assigned vertex ids you may need to
+     * skip this test.
+     */
+    @Test
+    @LoadGraphWith(MODERN)
+    public void g_V_out_out_order_byXdescX() {
+        final Traversal traversal = get_g_V_out_out_order_byXdescX();
+        printTraversalForm(traversal);
+        checkOrderedResults(Arrays.asList(
+                convertToVertex("ripple"),     // vid = 5
+                convertToVertex("lop")         // vid = 3
+        ), traversal);
+    }
+
+    /**
+     * Order desc by vertex in path: v[5], v[3]
+     *
+     * Note to graph providers: if your graph does not support user-assigned vertex ids you may need to
+     * skip this test.
+     */
+    @Test
+    @LoadGraphWith(MODERN)
+    public void g_V_out_out_asXheadX_path_order_byXdescX_selectXheadX() {
+        final Traversal traversal = get_g_V_out_out_asXheadX_path_order_byXdescX_selectXheadX();
+        printTraversalForm(traversal);
+        checkOrderedResults(Arrays.asList(
+                convertToVertex("ripple"),     // vid = 5
+                convertToVertex("lop")         // vid = 3
+        ), traversal);
+    }
+
+    /**
+     * Order desc by edge: e[11], v[e10]
+     *
+     * Note to graph providers: if your graph does not support user-assigned edge ids you may need to
+     * skip this test.
+     */
+    @Test
+    @LoadGraphWith(MODERN)
+    public void g_V_out_outE_order_byXdescX() {
+        final Traversal traversal = get_g_V_out_outE_order_byXdescX();
+        printTraversalForm(traversal);
+        checkOrderedResults(Arrays.asList(
+                convertToEdge("josh", "created", "lop"),        // eid = 11
+                convertToEdge("josh", "created", "ripple")      // eid = 10
+        ), traversal);
+    }
+
+    /**
+     * Order desc by edge in path: e[11], e[10]
+     *
+     * Note to graph providers: if your graph does not support user-assigned edge ids you may need to
+     * skip this test.
+     */
+    @Test
+    @LoadGraphWith(MODERN)
+    public void g_V_out_outE_asXheadX_path_order_byXdescX_selectXheadX() {
+        final Traversal traversal = get_g_V_out_outE_asXheadX_path_order_byXdescX_selectXheadX();
+        printTraversalForm(traversal);
+        checkOrderedResults(Arrays.asList(
+                convertToEdge("josh", "created", "lop"),        // eid = 11
+                convertToEdge("josh", "created", "ripple")      // eid = 10
+        ), traversal);
+    }
+
+    /**
+     * Order desc by vertex and then vertex property id in path.
+     *
+     * Note to graph providers: if your graph does not support user-assigned vertex ids and vertex property ids you 

Review comment:
       done




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@tinkerpop.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [tinkerpop] mikepersonick commented on a change in pull request #1543: Orderability Semantics

Posted by GitBox <gi...@apache.org>.
mikepersonick commented on a change in pull request #1543:
URL: https://github.com/apache/tinkerpop/pull/1543#discussion_r782259532



##########
File path: gremlin-test/features/semantics/Orderability.feature
##########
@@ -0,0 +1,354 @@
+# 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.
+
+@OrderabilitySemantics
+Feature: Orderability
+
+  Scenario: g_V_values_order
+    Given the modern graph
+    And the traversal of
+      """
+      g.V().values().order()
+      """
+    When iterated to list
+    Then the result should be ordered
+      | result |
+      | d[27].i |
+      | d[29].i |
+      | d[32].i |
+      | d[35].i |
+      | java |
+      | java |
+      | josh |
+      | lop  |
+      | marko |
+      | peter |
+      | ripple |
+      | vadas  |
+
+# This exposes an underlying problem where .value() does not preserve the order (should it?). This will be

Review comment:
       Remove this




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@tinkerpop.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org