From 626dfa4f9a0c34ba502ff36a03f42d6dd2e7a118 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Mon, 11 Jun 2018 10:26:30 +0200 Subject: [PATCH] DATAMONGO-2003 - Fix derived query using regex pattern with options. We now consider regex pattern options when using the pattern as a derived finder argument. Original pull request: #570. --- .../repository/query/MongoQueryCreator.java | 21 +++++++++------- ...tractPersonRepositoryIntegrationTests.java | 17 ++++++++++++- .../mongodb/repository/PersonRepository.java | 25 +++++++++++-------- .../query/MongoQueryCreatorUnitTests.java | 23 ++++++++++++++++- 4 files changed, 64 insertions(+), 22 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoQueryCreator.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoQueryCreator.java index 769b2da37..9d816441d 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoQueryCreator.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoQueryCreator.java @@ -21,6 +21,7 @@ import java.util.Arrays; import java.util.Collection; import java.util.Iterator; import java.util.regex.Pattern; +import java.util.regex.Pattern; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -51,7 +52,7 @@ import org.springframework.util.ClassUtils; /** * Custom query creator to create Mongo criterias. - * + * * @author Oliver Gierke * @author Thomas Darimont * @author Christoph Strobl @@ -69,7 +70,7 @@ class MongoQueryCreator extends AbstractQueryCreator { /** * Creates a new {@link MongoQueryCreator} from the given {@link PartTree}, {@link ConvertingParameterAccessor} and * {@link MappingContext}. - * + * * @param tree * @param accessor * @param context @@ -82,7 +83,7 @@ class MongoQueryCreator extends AbstractQueryCreator { /** * Creates a new {@link MongoQueryCreator} from the given {@link PartTree}, {@link ConvertingParameterAccessor} and * {@link MappingContext}. - * + * * @param tree * @param accessor * @param context @@ -164,7 +165,7 @@ class MongoQueryCreator extends AbstractQueryCreator { /** * Populates the given {@link CriteriaDefinition} depending on the {@link Part} given. - * + * * @param part * @param property * @param criteria @@ -206,7 +207,9 @@ class MongoQueryCreator extends AbstractQueryCreator { case NOT_CONTAINING: return createContainingCriteria(part, property, criteria.not(), parameters); case REGEX: - return criteria.regex(parameters.next().toString()); + + Object param = parameters.next(); + return param instanceof Pattern ? criteria.regex((Pattern) param) : criteria.regex(param.toString()); case EXISTS: return criteria.exists((Boolean) parameters.next()); case TRUE: @@ -272,7 +275,7 @@ class MongoQueryCreator extends AbstractQueryCreator { /** * Creates and extends the given criteria with a like-regex if necessary. - * + * * @param part * @param property * @param criteria @@ -314,7 +317,7 @@ class MongoQueryCreator extends AbstractQueryCreator { * If the target property of the comparison is of type String, then the operator checks for match using regular * expression. If the target property of the comparison is a {@link Collection} then the operator evaluates to true if * it finds an exact match within any member of the {@link Collection}. - * + * * @param part * @param property * @param criteria @@ -333,7 +336,7 @@ class MongoQueryCreator extends AbstractQueryCreator { /** * Creates an appropriate like-regex and appends it to the given criteria. - * + * * @param criteria * @param part * @param value @@ -368,7 +371,7 @@ class MongoQueryCreator extends AbstractQueryCreator { /** * Returns the next element from the given {@link Iterator} expecting it to be of a certain type. - * + * * @param * @param iterator * @param type diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/AbstractPersonRepositoryIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/AbstractPersonRepositoryIntegrationTests.java index 319f2aa47..96786dcc9 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/AbstractPersonRepositoryIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/AbstractPersonRepositoryIntegrationTests.java @@ -24,6 +24,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; import java.util.List; +import java.util.regex.Pattern; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -63,7 +64,7 @@ import org.springframework.test.util.ReflectionTestUtils; /** * Base class for tests for {@link PersonRepository}. - * + * * @author Oliver Gierke * @author Thomas Darimont * @author Christoph Strobl @@ -1166,4 +1167,18 @@ public abstract class AbstractPersonRepositoryIntegrationTests { assertThat(repository.countByThePersonsFirstname("Dave"), is(0L)); } + + @Test // DATAMONGO-2003 + public void findByRegexWithPattern() { + assertThat(repository.findByFirstnameRegex(Pattern.compile(alicia.getFirstname())), hasSize(1)); + } + + @Test // DATAMONGO-2003 + public void findByRegexWithPatternAndOptions() { + + String fn = alicia.getFirstname().toUpperCase(); + + assertThat(repository.findByFirstnameRegex(Pattern.compile(fn)), hasSize(0)); + assertThat(repository.findByFirstnameRegex(Pattern.compile(fn, Pattern.CASE_INSENSITIVE)), hasSize(1)); + } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonRepository.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonRepository.java index 42beb55ed..ec391804f 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonRepository.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonRepository.java @@ -18,6 +18,7 @@ package org.springframework.data.mongodb.repository; import java.util.Collection; import java.util.Date; import java.util.List; +import java.util.regex.Pattern; import java.util.stream.Stream; import org.springframework.data.domain.Page; @@ -38,7 +39,7 @@ import org.springframework.data.repository.query.Param; /** * Sample repository managing {@link Person} entities. - * + * * @author Oliver Gierke * @author Thomas Darimont * @author Christoph Strobl @@ -49,7 +50,7 @@ public interface PersonRepository extends MongoRepository, Query /** * Returns all {@link Person}s with the given lastname. - * + * * @param lastname * @return */ @@ -61,7 +62,7 @@ public interface PersonRepository extends MongoRepository, Query /** * Returns all {@link Person}s with the given lastname ordered by their firstname. - * + * * @param lastname * @return */ @@ -70,7 +71,7 @@ public interface PersonRepository extends MongoRepository, Query /** * Returns the {@link Person}s with the given firstname. Uses {@link Query} annotation to define the query to be * executed. - * + * * @param firstname * @return */ @@ -83,7 +84,7 @@ public interface PersonRepository extends MongoRepository, Query /** * Returns all {@link Person}s with a firstname matching the given one (*-wildcard supported). - * + * * @param firstname * @return */ @@ -110,7 +111,7 @@ public interface PersonRepository extends MongoRepository, Query /** * Returns a page of {@link Person}s with a lastname mathing the given one (*-wildcards supported). - * + * * @param lastname * @param pageable * @return @@ -122,7 +123,7 @@ public interface PersonRepository extends MongoRepository, Query /** * Returns all {@link Person}s with a firstname contained in the given varargs. - * + * * @param firstnames * @return */ @@ -130,7 +131,7 @@ public interface PersonRepository extends MongoRepository, Query /** * Returns all {@link Person}s with a firstname not contained in the given collection. - * + * * @param firstnames * @return */ @@ -140,7 +141,7 @@ public interface PersonRepository extends MongoRepository, Query /** * Returns all {@link Person}s with an age between the two given values. - * + * * @param from * @param to * @return @@ -149,7 +150,7 @@ public interface PersonRepository extends MongoRepository, Query /** * Returns the {@link Person} with the given {@link Address} as shipping address. - * + * * @param address * @return */ @@ -157,7 +158,7 @@ public interface PersonRepository extends MongoRepository, Query /** * Returns all {@link Person}s with the given {@link Address}. - * + * * @param address * @return */ @@ -325,4 +326,6 @@ public interface PersonRepository extends MongoRepository, Query */ @DeleteQuery("{ 'firstname' : ?0 }") // DATAMONGO-1539 void deleteByThePersonsFirstname(String firstname); + + List findByFirstnameRegex(Pattern pattern); } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/MongoQueryCreatorUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/MongoQueryCreatorUnitTests.java index 567d5b9b1..54e18385a 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/MongoQueryCreatorUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/MongoQueryCreatorUnitTests.java @@ -24,7 +24,9 @@ import static org.springframework.data.mongodb.repository.query.StubParameterAcc import java.lang.reflect.Method; import java.util.List; +import java.util.regex.Pattern; +import org.bson.Document; import org.bson.types.ObjectId; import org.junit.Before; import org.junit.Rule; @@ -64,7 +66,7 @@ import com.mongodb.DBObject; /** * Unit test for {@link MongoQueryCreator}. - * + * * @author Oliver Gierke * @author Thomas Darimont * @author Christoph Strobl @@ -627,6 +629,25 @@ public class MongoQueryCreatorUnitTests { new MongoQueryCreator(tree, accessor, context).createQuery(); } + @Test // DATAMONGO-2003 + public void createsRegexQueryForPatternCorrectly() throws Exception { + + PartTree tree = new PartTree("findByFirstNameRegex", Person.class); + MongoQueryCreator creator = new MongoQueryCreator(tree, getAccessor(converter, Pattern.compile(".*")), context); + + assertThat(creator.createQuery(), is(query(where("firstName").regex(".*")))); + } + + @Test // DATAMONGO-2003 + public void createsRegexQueryForPatternWithOptionsCorrectly() throws Exception { + + Pattern pattern = Pattern.compile(".*", Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE); + + PartTree tree = new PartTree("findByFirstNameRegex", Person.class); + MongoQueryCreator creator = new MongoQueryCreator(tree, getAccessor(converter, pattern), context); + assertThat(creator.createQuery(), is(query(where("firstName").regex(".*", "iu")))); + } + interface PersonRepository extends Repository { List findByLocationNearAndFirstname(Point location, Distance maxDistance, String firstname);