TINKERPOP-2058 Use `Compare.eq` in `Contains.within` to ensure equal filter behaviors.
If the object to be filtered is a number, `Contains` predicates will now scan the provided collection, comparing each element using `Compare.eq`. For non-numeric values `Contains.within` will still use `collection.contains()` in order to make use of search-optimized data types (e.g. `Set`). Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/e900cfc5 Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/e900cfc5 Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/e900cfc5 Branch: refs/heads/TINKERPOP-2058 Commit: e900cfc56451b90ef7efca9e73b6ddb05f6cc308 Parents: 5756c0c Author: Daniel Kuppitz <daniel_kupp...@hotmail.com> Authored: Thu Oct 4 07:15:09 2018 -0700 Committer: Daniel Kuppitz <daniel_kupp...@hotmail.com> Committed: Fri Oct 5 10:44:29 2018 -0700 ---------------------------------------------------------------------- CHANGELOG.asciidoc | 1 + .../gremlin/process/traversal/Contains.java | 16 +++++++++++++--- .../gremlin/process/traversal/ContainsTest.java | 2 +- .../tinkerpop/gremlin/process/traversal/PTest.java | 2 +- 4 files changed, 16 insertions(+), 5 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/e900cfc5/CHANGELOG.asciidoc ---------------------------------------------------------------------- diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc index 14d79aa..739737e 100644 --- a/CHANGELOG.asciidoc +++ b/CHANGELOG.asciidoc @@ -25,6 +25,7 @@ image::https://raw.githubusercontent.com/apache/tinkerpop/master/docs/static/ima This release also includes changes from <<release-3-3-3, 3.3.3>>. +* Use `Compare.eq` in `Contains` predicates to ensure the same filter behavior for numberic values. * Added text predicates. * Rewrote `ConnectiveStrategy` to support an arbitrary number of infix notations in a single traversal. * GraphSON `MessageSerializer`s will automatically register the GremlinServerModule to a provided GraphSONMapper. http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/e900cfc5/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Contains.java ---------------------------------------------------------------------- diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Contains.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Contains.java index da46d0b..35a8ca7 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Contains.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Contains.java @@ -18,19 +18,27 @@ */ package org.apache.tinkerpop.gremlin.process.traversal; +import org.apache.tinkerpop.gremlin.util.iterator.IteratorUtils; + import java.util.Collection; import java.util.function.BiPredicate; /** * {@link Contains} is a {@link BiPredicate} that evaluates whether the first object is contained within (or not - * within) the second collection object. For example: + * within) the second collection object. If the first object is a number, each element in the second collection + * will be compared to the first object using {@link Compare}'s {@code eq} predicate. This will ensure, that numbers + * are matched by their value only, ignoring the number type. For example: * <p/> * <pre> * gremlin Contains.within [gremlin, blueprints, furnace] == true * gremlin Contains.without [gremlin, rexster] == false * rexster Contains.without [gremlin, blueprints, furnace] == true + * 123 Contains.within [1, 2, 3] == false + * 100 Contains.within [1L, 10L, 100L] == true * </pre> * + * + * * @author Pierre De Wilde * @author Marko A. Rodriguez (http://markorodriguez.com) */ @@ -44,7 +52,9 @@ public enum Contains implements BiPredicate<Object, Collection> { within { @Override public boolean test(final Object first, final Collection second) { - return second.contains(first); + return first instanceof Number + ? IteratorUtils.anyMatch(second.iterator(), o -> Compare.eq.test(first, o)) + : second.contains(first); } }, @@ -56,7 +66,7 @@ public enum Contains implements BiPredicate<Object, Collection> { without { @Override public boolean test(final Object first, final Collection second) { - return !second.contains(first); + return !within.test(first, second); } }; http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/e900cfc5/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/ContainsTest.java ---------------------------------------------------------------------- diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/ContainsTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/ContainsTest.java index 6d9ea38..2ea635d 100644 --- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/ContainsTest.java +++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/ContainsTest.java @@ -43,7 +43,7 @@ public class ContainsTest { {Contains.within, 10, Collections.emptyList(), false}, {Contains.without, 10, Collections.emptyList(), true}, {Contains.within, 100, Arrays.asList(1, 2, 3, 4, 10), false}, - {Contains.without, 10l, Arrays.asList(1, 2, 3, 4, 10), true}, // no forgiveness + {Contains.without, 10L, Arrays.asList(1, 2, 3, 4, 10), false}, {Contains.within, "test", Arrays.asList(1, 2, 3, "test", 10), true}, {Contains.without, "testing", Arrays.asList(1, 2, 3, "test", 10), true} })); http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/e900cfc5/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/PTest.java ---------------------------------------------------------------------- diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/PTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/PTest.java index 3494e32..f2e0868 100644 --- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/PTest.java +++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/PTest.java @@ -127,7 +127,7 @@ public class PTest { assertEquals(expected, predicate.test(value)); assertNotEquals(expected, predicate.clone().negate().test(value)); assertNotEquals(expected, P.not(predicate.clone()).test(value)); - if (value instanceof Number && !(predicate.biPredicate instanceof Contains)) { + if (value instanceof Number) { assertEquals(expected, predicate.test(((Number) value).longValue())); assertNotEquals(expected, predicate.clone().negate().test(((Number) value).longValue())); assertNotEquals(expected, P.not(predicate).test(((Number) value).longValue()));