From a483d95cde87111ab7afda899b25cc5cf54eeec5 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Tue, 20 Nov 2018 14:30:58 +0100 Subject: [PATCH] DATAMONGO-2119 - Allow SpEL usage for annotated $regex query. Original pull request: #621. --- .../query/StringBasedMongoQuery.java | 34 ++++++++++++++++++- .../query/StringBasedMongoQueryUnitTests.java | 19 ++++++++++- 2 files changed, 51 insertions(+), 2 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/StringBasedMongoQuery.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/StringBasedMongoQuery.java index 56153776c..57d9d84e0 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/StringBasedMongoQuery.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/StringBasedMongoQuery.java @@ -20,7 +20,9 @@ import java.util.Collections; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; +import java.util.regex.PatternSyntaxException; +import org.bson.BSON; import org.bson.Document; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -37,6 +39,7 @@ import org.springframework.util.StringUtils; import com.mongodb.DBObject; import com.mongodb.DBRef; import com.mongodb.util.JSON; +import com.mongodb.util.JSONCallback; /** * Query to use a plain JSON String to create the {@link Query} to actually execute. @@ -224,7 +227,36 @@ public class StringBasedMongoQuery extends AbstractMongoQuery { String transformedInput = transformQueryAndCollectExpressionParametersIntoBindings(input, bindings); String parseableInput = makeParameterReferencesParseable(transformedInput); - collectParameterReferencesIntoBindings(bindings, JSON.parse(parseableInput)); + collectParameterReferencesIntoBindings(bindings, JSON.parse(parseableInput, new JSONCallback() { + + /* + * (non-Javadoc) + * @see com.mongodb.util.JSONCallback#objectDone() + */ + @Override + public Object objectDone() { + return exceptionSwallowingStackReducingObjectDone(); + } + + private Object exceptionSwallowingStackReducingObjectDone/*CauseWeJustNeedTheStructureNotTheActualValue*/() { + + Object value; + + try { + return super.objectDone(); + } catch (PatternSyntaxException e) { + value = Pattern.compile(""); + } + + if (!isStackEmpty()) { + _put(curName(), value); + } else { + value = !BSON.hasDecodeHooks() ? value : BSON.applyDecodingHooks(value); + setRoot(value); + } + return value; + } + })); return transformedInput; } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/StringBasedMongoQueryUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/StringBasedMongoQueryUnitTests.java index 742985af5..85a691f65 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/StringBasedMongoQueryUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/StringBasedMongoQueryUnitTests.java @@ -590,6 +590,19 @@ public class StringBasedMongoQueryUnitTests { assertThat(query.getQueryObject(), is(new Document("arg0", null))); } + @Test // DATAMONGO-2119 + public void spelShouldIgnoreJsonParseErrorsForRegex() { + + StringBasedMongoQuery mongoQuery = createQueryForMethod("findByPersonLastnameRegex", Person.class); + ConvertingParameterAccessor accessor = StubParameterAccessor.getAccessor(converter, + new Person("Molly", "Chandler")); + + org.springframework.data.mongodb.core.query.Query query = mongoQuery.createQuery(accessor); + + assertThat(query.getQueryObject().toJson(), + is(new BasicQuery("{lastname: {$regex: 'Chandler'}}").getQueryObject().toJson())); + } + private StringBasedMongoQuery createQueryForMethod(String name, Class... parameters) { try { @@ -697,10 +710,14 @@ public class StringBasedMongoQueryUnitTests { @Query("{ 'arg0' : '?0', 'arg1' : '?1s' }") List findByWhenQuotedAndSomeStuffAppended(String arg0, String arg1); - @Query("{ 'lastname' : { '$regex' : '^(?0|John ?1|?1)'} }") // use spel or some regex string this is fucking bad + @Query("{ 'lastname' : { '$regex' : '^(?0|John ?1|?1)'} }") // use spel or some regex string this is bad Person findByLastnameRegex(String lastname, String alternative); @Query("{ arg0 : ?#{[0]} }") List findByUsingSpel(Object arg0); + + @Query("{ 'lastname' : { '$regex' : ?#{[0].lastname} } }") + Person findByPersonLastnameRegex(Person key); } + }