From fe9b3a4ca3db7426ca9c82c814553e17fa8aa27b Mon Sep 17 00:00:00 2001 From: Michael Simons Date: Tue, 12 Jan 2021 19:14:38 +0100 Subject: [PATCH] GH-1862 - Support combining startingWith and endingWith with IgnoreCase in derived queries. This closes #1862 --- .../filter/PropertyComparisonBuilder.java | 17 ++++- .../examples/restaurants/RestaurantTests.java | 70 +++++++------------ .../repo/RestaurantRepository.java | 4 ++ 3 files changed, 43 insertions(+), 48 deletions(-) diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/repository/query/filter/PropertyComparisonBuilder.java b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/repository/query/filter/PropertyComparisonBuilder.java index 518c83531..46c5fb1db 100644 --- a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/repository/query/filter/PropertyComparisonBuilder.java +++ b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/repository/query/filter/PropertyComparisonBuilder.java @@ -17,8 +17,11 @@ package org.springframework.data.neo4j.repository.query.filter; import static org.springframework.data.repository.query.parser.Part.Type.*; +import java.util.Arrays; import java.util.Collections; +import java.util.HashSet; import java.util.List; +import java.util.Set; import java.util.Stack; import org.neo4j.ogm.cypher.BooleanOperator; @@ -34,6 +37,17 @@ import org.springframework.util.Assert; */ class PropertyComparisonBuilder extends FilterBuilder { + private static final Set TYPES_SUPPORTING_IGNORE_CASE; + + static { + Set typesSupportingIgnoreCase = new HashSet<>(); + typesSupportingIgnoreCase.add(SIMPLE_PROPERTY); + typesSupportingIgnoreCase.add(CONTAINING); + typesSupportingIgnoreCase.add(STARTING_WITH); + typesSupportingIgnoreCase.add(ENDING_WITH); + TYPES_SUPPORTING_IGNORE_CASE = Collections.unmodifiableSet(typesSupportingIgnoreCase); + } + PropertyComparisonBuilder(Part part, BooleanOperator booleanOperator, Class entityType) { super(part, booleanOperator, entityType); } @@ -128,7 +142,6 @@ class PropertyComparisonBuilder extends FilterBuilder { } private boolean isSupportedIgnoreKeyword(Part part) { - Part.Type type = part.getType(); - return type == SIMPLE_PROPERTY || type == CONTAINING; + return TYPES_SUPPORTING_IGNORE_CASE.contains(part.getType()); } } diff --git a/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/examples/restaurants/RestaurantTests.java b/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/examples/restaurants/RestaurantTests.java index 91e4d31a6..a8174f745 100644 --- a/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/examples/restaurants/RestaurantTests.java +++ b/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/examples/restaurants/RestaurantTests.java @@ -22,6 +22,8 @@ import java.util.Arrays; import java.util.Collections; import java.util.Date; import java.util.List; +import java.util.Locale; +import java.util.function.Supplier; import org.junit.After; import org.junit.Test; @@ -370,23 +372,26 @@ public class RestaurantTests { assertEquals(0, results.size()); } - /** - * All findByPropertyLike does currently is to require an exact match, ignoring case. - */ - @Test // DATAGRAPH-904 - public void shouldFindByNameNotLike() { - + void runTestThatShouldReturnOnlySFO(Supplier> restaurantSupplier) { Restaurant restaurant = new Restaurant("San Francisco International Airport (SFO)", 68.0); restaurantRepository.save(restaurant); Restaurant kuroda = new Restaurant("Kuroda", 72.4); restaurantRepository.save(kuroda); - List results = restaurantRepository.findByNameNotLike("kuroda"); + List results = restaurantSupplier.get(); assertNotNull(results); assertEquals(1, results.size()); assertEquals("San Francisco International Airport (SFO)", results.get(0).getName()); + } + /** + * All findByPropertyLike does currently is to require an exact match, ignoring case. + */ + @Test // DATAGRAPH-904 + public void shouldFindByNameNotLike() { + + runTestThatShouldReturnOnlySFO(() -> restaurantRepository.findByNameNotLike("kuroda")); } /** @@ -395,49 +400,32 @@ public class RestaurantTests { @Test // DATAGRAPH-904 public void shouldFindByNameLike() { - Restaurant restaurant = new Restaurant("San Francisco International Airport (SFO)", 68.0); - restaurantRepository.save(restaurant); - - Restaurant kuroda = new Restaurant("Kuroda", 72.4); - restaurantRepository.save(kuroda); - - List results = restaurantRepository.findByNameLike("*san francisco international*"); - assertNotNull(results); - assertEquals(1, results.size()); - assertEquals("San Francisco International Airport (SFO)", results.get(0).getName()); - + runTestThatShouldReturnOnlySFO(() -> restaurantRepository.findByNameLike("*san francisco international*")); } @Test // DATAGRAPH-904 public void shouldFindByNameStartingWith() { - Restaurant restaurant = new Restaurant("San Francisco International Airport (SFO)", 68.0); - restaurantRepository.save(restaurant); + runTestThatShouldReturnOnlySFO(() -> restaurantRepository.findByNameStartingWith("San Francisco")); - Restaurant kuroda = new Restaurant("Kuroda", 72.4); - restaurantRepository.save(kuroda); + } - List results = restaurantRepository.findByNameStartingWith("San Francisco"); - assertNotNull(results); - assertEquals(1, results.size()); - assertEquals("San Francisco International Airport (SFO)", results.get(0).getName()); + @Test // DATAGRAPH-1862 + public void shouldFindByNameStartingWithIgnoringCase() { + runTestThatShouldReturnOnlySFO(() -> restaurantRepository.findByNameStartingWithIgnoreCase("San Francisco".toLowerCase(Locale.ROOT))); } @Test // DATAGRAPH-904 public void shouldFindByNameEndingWith() { - Restaurant restaurant = new Restaurant("San Francisco International Airport (SFO)", 68.0); - restaurantRepository.save(restaurant); + runTestThatShouldReturnOnlySFO(() -> restaurantRepository.findByNameEndingWith("Airport (SFO)")); + } - Restaurant kuroda = new Restaurant("Kuroda", 72.4); - restaurantRepository.save(kuroda); - - List results = restaurantRepository.findByNameEndingWith("Airport (SFO)"); - assertNotNull(results); - assertEquals(1, results.size()); - assertEquals("San Francisco International Airport (SFO)", results.get(0).getName()); + @Test // DATAGRAPH-1862 + public void shouldFindByNameEndingWithIgnoringCase() { + runTestThatShouldReturnOnlySFO(() -> restaurantRepository.findByNameEndingWithIgnoreCase("Airport (SFO)".toLowerCase(Locale.ROOT))); } @Test // DATAGRAPH-904 @@ -510,17 +498,7 @@ public class RestaurantTests { @Test // DATAGRAPH-904 public void shouldFindByNameMatchesRegEx() { - Restaurant restaurant = new Restaurant("San Francisco International Airport (SFO)", 68.0); - restaurantRepository.save(restaurant); - - Restaurant kuroda = new Restaurant("Kuroda", 72.4); - restaurantRepository.save(kuroda); - - List results = restaurantRepository.findByNameMatchesRegex("(?i)san francisco.*"); - assertNotNull(results); - assertEquals(1, results.size()); - assertEquals("San Francisco International Airport (SFO)", results.get(0).getName()); - + runTestThatShouldReturnOnlySFO(() -> restaurantRepository.findByNameMatchesRegex("(?i)san francisco.*")); } @Test // DATAGRAPH-904 diff --git a/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/examples/restaurants/repo/RestaurantRepository.java b/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/examples/restaurants/repo/RestaurantRepository.java index 1cdbecb56..058ccb7ea 100644 --- a/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/examples/restaurants/repo/RestaurantRepository.java +++ b/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/examples/restaurants/repo/RestaurantRepository.java @@ -61,8 +61,12 @@ public interface RestaurantRepository extends Neo4jRepository List findByNameStartingWith(String string); + List findByNameStartingWithIgnoreCase(String string); + List findByNameEndingWith(String string); + List findByNameEndingWithIgnoreCase(String string); + List findByNameContaining(String string); List findByNameNotContaining(String string);