in gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/GremlinValueComparator.java [315:364]
public static boolean comparable(final Object f, final Object s) {
if (f == null || s == null)
return f == s; // true iff both in the null space
if (eitherAreNaN(f, s))
return false;
final Type ft = Type.type(f);
final Type st = Type.type(s);
// if objects are collections or composites, their contents must be mutually comparable
if (ft == Type.List && st == Type.List) {
return contentsComparable(IteratorUtils.asIterator(f), IteratorUtils.asIterator(s));
}
else if (ft == Type.Path && st == Type.Path) {
return contentsComparable(((Path) f).iterator(), ((Path) s).iterator());
}
else if (ft == Type.Set && st == Type.Set) {
final List l1 = new ArrayList((Set) f);
final List l2 = new ArrayList((Set) s);
Collections.sort(l1, ORDERABILITY);
Collections.sort(l2, ORDERABILITY);
return contentsComparable(l1.iterator(), l2.iterator());
}
else if (ft == Type.Map && st == Type.Map) {
final List l1 = new ArrayList(((Map) f).entrySet());
final List l2 = new ArrayList(((Map) s).entrySet());
Collections.sort(l1, ORDERABILITY);
Collections.sort(l2, ORDERABILITY);
return contentsComparable(l1.iterator(), l2.iterator());
}
else if (ft == Type.MapEntry && st == Type.MapEntry) {
return comparable(((Map.Entry) f).getKey(), ((Map.Entry) s).getKey()) &&
comparable(((Map.Entry) f).getValue(), ((Map.Entry) s).getValue());
}
else if (ft == Type.Vertex && st == Type.Vertex ||
ft == Type.Edge && st == Type.Edge ||
ft == Type.VertexProperty && st == Type.VertexProperty) {
return comparable(((Element) f).id(), ((Element) s).id());
}
else if (ft == Type.Property && st == Type.Property) {
return comparable(((Property) f).key(), ((Property) s).key()) &&
comparable(((Property) f).value(), ((Property) s).value());
}
// Check for same type. If they're both the unknown type then return true iff they are naturally Comparable
return ft == Type.Unknown && st == Type.Unknown ? naturallyComparable(f, s) : ft == st;
}