DATAMONGO-1565 - Polishing.
Consider quoted/unquoted parameter use with the same parameter reference. Extend date range in license headers.
This commit is contained in:
committed by
Oliver Gierke
parent
14e326dc09
commit
1a105333aa
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2015 the original author or authors.
|
||||
* Copyright 2015-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -15,6 +15,9 @@
|
||||
*/
|
||||
package org.springframework.data.mongodb.repository.query;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
@@ -44,6 +47,7 @@ import com.mongodb.util.JSON;
|
||||
* @author Christoph Strobl
|
||||
* @author Thomas Darimont
|
||||
* @author Oliver Gierke
|
||||
* @author Mark Paluch
|
||||
* @since 1.9
|
||||
*/
|
||||
class ExpressionEvaluatingParameterBinder {
|
||||
@@ -90,7 +94,7 @@ class ExpressionEvaluatingParameterBinder {
|
||||
*
|
||||
* @param input must not be {@literal null} or empty.
|
||||
* @param accessor must not be {@literal null}.
|
||||
* @param bindings must not be {@literal null}.
|
||||
* @param bindingContext must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
private String replacePlaceholders(String input, MongoParameterAccessor accessor, BindingContext bindingContext) {
|
||||
@@ -232,22 +236,23 @@ class ExpressionEvaluatingParameterBinder {
|
||||
* @param groupName The actual {@link Matcher#group() group}.
|
||||
* @return
|
||||
*/
|
||||
private String extractPlaceholder(String groupName) {
|
||||
private Placeholder extractPlaceholder(String groupName) {
|
||||
|
||||
if (!groupName.endsWith("'") && !groupName.endsWith("\"")) {
|
||||
return groupName;
|
||||
return new Placeholder(groupName, false);
|
||||
}
|
||||
return groupName.substring(0, groupName.length() - 1);
|
||||
return new Placeholder(groupName.substring(0, groupName.length() - 1), true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
* @author Mark Paluch
|
||||
* @since 1.9
|
||||
*/
|
||||
static class BindingContext {
|
||||
|
||||
final MongoParameters parameters;
|
||||
final Map<String, ParameterBinding> bindings;
|
||||
final Map<Placeholder, ParameterBinding> bindings;
|
||||
|
||||
/**
|
||||
* Creates new {@link BindingContext}.
|
||||
@@ -279,13 +284,13 @@ class ExpressionEvaluatingParameterBinder {
|
||||
|
||||
/**
|
||||
* Get the concrete {@link ParameterBinding} for a given {@literal placeholder}.
|
||||
*
|
||||
*
|
||||
* @param placeholder must not be {@literal null}.
|
||||
* @return
|
||||
* @throws java.util.NoSuchElementException
|
||||
* @since 1.10
|
||||
*/
|
||||
ParameterBinding getBindingFor(String placeholder) {
|
||||
ParameterBinding getBindingFor(Placeholder placeholder) {
|
||||
|
||||
if (!bindings.containsKey(placeholder)) {
|
||||
throw new NoSuchElementException(String.format("Could not to find binding for placeholder '%s'.", placeholder));
|
||||
@@ -296,20 +301,43 @@ class ExpressionEvaluatingParameterBinder {
|
||||
|
||||
/**
|
||||
* Get the associated {@link MongoParameters}.
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public MongoParameters getParameters() {
|
||||
return parameters;
|
||||
}
|
||||
|
||||
private static Map<String, ParameterBinding> mapBindings(List<ParameterBinding> bindings) {
|
||||
private static Map<Placeholder, ParameterBinding> mapBindings(List<ParameterBinding> bindings) {
|
||||
|
||||
Map<String, ParameterBinding> map = new LinkedHashMap<String, ParameterBinding>(bindings.size(), 1);
|
||||
Map<Placeholder, ParameterBinding> map = new LinkedHashMap<Placeholder, ParameterBinding>(bindings.size(), 1);
|
||||
for (ParameterBinding binding : bindings) {
|
||||
map.put(binding.getParameter(), binding);
|
||||
map.put(new Placeholder(binding.getParameter(), binding.isQuoted()), binding);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Encapsulates a quoted/unquoted parameter placeholder.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @since 1.9
|
||||
*/
|
||||
@Data
|
||||
@RequiredArgsConstructor
|
||||
static class Placeholder {
|
||||
|
||||
private final String parameter;
|
||||
private final boolean quoted;
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return quoted ? String.format("'%s'", parameter) : parameter;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2011-2015 the original author or authors.
|
||||
* Copyright 2011-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -50,6 +50,7 @@ import org.springframework.data.repository.core.support.DefaultRepositoryMetadat
|
||||
import org.springframework.data.repository.query.DefaultEvaluationContextProvider;
|
||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||
|
||||
import com.mongodb.BasicDBList;
|
||||
import com.mongodb.BasicDBObject;
|
||||
import com.mongodb.BasicDBObjectBuilder;
|
||||
import com.mongodb.DBObject;
|
||||
@@ -86,9 +87,9 @@ public class StringBasedMongoQueryUnitTests {
|
||||
public void bindsSimplePropertyCorrectly() throws Exception {
|
||||
|
||||
StringBasedMongoQuery mongoQuery = createQueryForMethod("findByLastname", String.class);
|
||||
ConvertingParameterAccessor accesor = StubParameterAccessor.getAccessor(converter, "Matthews");
|
||||
ConvertingParameterAccessor accessor = StubParameterAccessor.getAccessor(converter, "Matthews");
|
||||
|
||||
org.springframework.data.mongodb.core.query.Query query = mongoQuery.createQuery(accesor);
|
||||
org.springframework.data.mongodb.core.query.Query query = mongoQuery.createQuery(accessor);
|
||||
org.springframework.data.mongodb.core.query.Query reference = new BasicQuery("{'lastname' : 'Matthews'}");
|
||||
|
||||
assertThat(query.getQueryObject(), is(reference.getQueryObject()));
|
||||
@@ -100,13 +101,13 @@ public class StringBasedMongoQueryUnitTests {
|
||||
StringBasedMongoQuery mongoQuery = createQueryForMethod("findByAddress", Address.class);
|
||||
|
||||
Address address = new Address("Foo", "0123", "Bar");
|
||||
ConvertingParameterAccessor accesor = StubParameterAccessor.getAccessor(converter, address);
|
||||
ConvertingParameterAccessor accessor = StubParameterAccessor.getAccessor(converter, address);
|
||||
|
||||
DBObject dbObject = new BasicDBObject();
|
||||
converter.write(address, dbObject);
|
||||
dbObject.removeField(DefaultMongoTypeMapper.DEFAULT_TYPE_KEY);
|
||||
|
||||
org.springframework.data.mongodb.core.query.Query query = mongoQuery.createQuery(accesor);
|
||||
org.springframework.data.mongodb.core.query.Query query = mongoQuery.createQuery(accessor);
|
||||
BasicDBObject queryObject = new BasicDBObject("address", dbObject);
|
||||
org.springframework.data.mongodb.core.query.Query reference = new BasicQuery(queryObject);
|
||||
|
||||
@@ -119,7 +120,7 @@ public class StringBasedMongoQueryUnitTests {
|
||||
StringBasedMongoQuery mongoQuery = createQueryForMethod("findByLastnameAndAddress", String.class, Address.class);
|
||||
|
||||
Address address = new Address("Foo", "0123", "Bar");
|
||||
ConvertingParameterAccessor accesor = StubParameterAccessor.getAccessor(converter, "Matthews", address);
|
||||
ConvertingParameterAccessor accessor = StubParameterAccessor.getAccessor(converter, "Matthews", address);
|
||||
|
||||
DBObject addressDbObject = new BasicDBObject();
|
||||
converter.write(address, addressDbObject);
|
||||
@@ -128,7 +129,7 @@ public class StringBasedMongoQueryUnitTests {
|
||||
DBObject reference = new BasicDBObject("address", addressDbObject);
|
||||
reference.put("lastname", "Matthews");
|
||||
|
||||
org.springframework.data.mongodb.core.query.Query query = mongoQuery.createQuery(accesor);
|
||||
org.springframework.data.mongodb.core.query.Query query = mongoQuery.createQuery(accessor);
|
||||
assertThat(query.getQueryObject(), is(reference));
|
||||
}
|
||||
|
||||
@@ -229,10 +230,10 @@ public class StringBasedMongoQueryUnitTests {
|
||||
@Test
|
||||
public void bindsSimplePropertyAlreadyQuotedCorrectly() throws Exception {
|
||||
|
||||
ConvertingParameterAccessor accesor = StubParameterAccessor.getAccessor(converter, "Matthews");
|
||||
ConvertingParameterAccessor accessor = StubParameterAccessor.getAccessor(converter, "Matthews");
|
||||
StringBasedMongoQuery mongoQuery = createQueryForMethod("findByLastnameQuoted", String.class);
|
||||
|
||||
org.springframework.data.mongodb.core.query.Query query = mongoQuery.createQuery(accesor);
|
||||
org.springframework.data.mongodb.core.query.Query query = mongoQuery.createQuery(accessor);
|
||||
org.springframework.data.mongodb.core.query.Query reference = new BasicQuery("{'lastname' : 'Matthews'}");
|
||||
|
||||
assertThat(query.getQueryObject(), is(reference.getQueryObject()));
|
||||
@@ -244,10 +245,10 @@ public class StringBasedMongoQueryUnitTests {
|
||||
@Test
|
||||
public void bindsSimplePropertyAlreadyQuotedWithRegexCorrectly() throws Exception {
|
||||
|
||||
ConvertingParameterAccessor accesor = StubParameterAccessor.getAccessor(converter, "^Mat.*");
|
||||
ConvertingParameterAccessor accessor = StubParameterAccessor.getAccessor(converter, "^Mat.*");
|
||||
StringBasedMongoQuery mongoQuery = createQueryForMethod("findByLastnameQuoted", String.class);
|
||||
|
||||
org.springframework.data.mongodb.core.query.Query query = mongoQuery.createQuery(accesor);
|
||||
org.springframework.data.mongodb.core.query.Query query = mongoQuery.createQuery(accessor);
|
||||
org.springframework.data.mongodb.core.query.Query reference = new BasicQuery("{'lastname' : '^Mat.*'}");
|
||||
|
||||
assertThat(query.getQueryObject(), is(reference.getQueryObject()));
|
||||
@@ -260,9 +261,9 @@ public class StringBasedMongoQueryUnitTests {
|
||||
public void bindsSimplePropertyWithRegexCorrectly() throws Exception {
|
||||
|
||||
StringBasedMongoQuery mongoQuery = createQueryForMethod("findByLastname", String.class);
|
||||
ConvertingParameterAccessor accesor = StubParameterAccessor.getAccessor(converter, "^Mat.*");
|
||||
ConvertingParameterAccessor accessor = StubParameterAccessor.getAccessor(converter, "^Mat.*");
|
||||
|
||||
org.springframework.data.mongodb.core.query.Query query = mongoQuery.createQuery(accesor);
|
||||
org.springframework.data.mongodb.core.query.Query query = mongoQuery.createQuery(accessor);
|
||||
org.springframework.data.mongodb.core.query.Query reference = new BasicQuery("{'lastname' : '^Mat.*'}");
|
||||
|
||||
assertThat(query.getQueryObject(), is(reference.getQueryObject()));
|
||||
@@ -305,10 +306,10 @@ public class StringBasedMongoQueryUnitTests {
|
||||
@Test
|
||||
public void shouldSupportExpressionsInCustomQueries() throws Exception {
|
||||
|
||||
ConvertingParameterAccessor accesor = StubParameterAccessor.getAccessor(converter, "Matthews");
|
||||
ConvertingParameterAccessor accessor = StubParameterAccessor.getAccessor(converter, "Matthews");
|
||||
StringBasedMongoQuery mongoQuery = createQueryForMethod("findByQueryWithExpression", String.class);
|
||||
|
||||
org.springframework.data.mongodb.core.query.Query query = mongoQuery.createQuery(accesor);
|
||||
org.springframework.data.mongodb.core.query.Query query = mongoQuery.createQuery(accessor);
|
||||
org.springframework.data.mongodb.core.query.Query reference = new BasicQuery("{'lastname' : 'Matthews'}");
|
||||
|
||||
assertThat(query.getQueryObject(), is(reference.getQueryObject()));
|
||||
@@ -320,11 +321,11 @@ public class StringBasedMongoQueryUnitTests {
|
||||
@Test
|
||||
public void shouldSupportExpressionsInCustomQueriesWithNestedObject() throws Exception {
|
||||
|
||||
ConvertingParameterAccessor accesor = StubParameterAccessor.getAccessor(converter, true, "param1", "param2");
|
||||
ConvertingParameterAccessor accessor = StubParameterAccessor.getAccessor(converter, true, "param1", "param2");
|
||||
StringBasedMongoQuery mongoQuery = createQueryForMethod("findByQueryWithExpressionAndNestedObject", boolean.class,
|
||||
String.class);
|
||||
|
||||
org.springframework.data.mongodb.core.query.Query query = mongoQuery.createQuery(accesor);
|
||||
org.springframework.data.mongodb.core.query.Query query = mongoQuery.createQuery(accessor);
|
||||
org.springframework.data.mongodb.core.query.Query reference = new BasicQuery("{ \"id\" : { \"$exists\" : true}}");
|
||||
|
||||
assertThat(query.getQueryObject(), is(reference.getQueryObject()));
|
||||
@@ -336,11 +337,11 @@ public class StringBasedMongoQueryUnitTests {
|
||||
@Test
|
||||
public void shouldSupportExpressionsInCustomQueriesWithMultipleNestedObjects() throws Exception {
|
||||
|
||||
ConvertingParameterAccessor accesor = StubParameterAccessor.getAccessor(converter, true, "param1", "param2");
|
||||
ConvertingParameterAccessor accessor = StubParameterAccessor.getAccessor(converter, true, "param1", "param2");
|
||||
StringBasedMongoQuery mongoQuery = createQueryForMethod("findByQueryWithExpressionAndMultipleNestedObjects",
|
||||
boolean.class, String.class, String.class);
|
||||
|
||||
org.springframework.data.mongodb.core.query.Query query = mongoQuery.createQuery(accesor);
|
||||
org.springframework.data.mongodb.core.query.Query query = mongoQuery.createQuery(accessor);
|
||||
org.springframework.data.mongodb.core.query.Query reference = new BasicQuery(
|
||||
"{ \"id\" : { \"$exists\" : true} , \"foo\" : 42 , \"bar\" : { \"$exists\" : false}}");
|
||||
|
||||
@@ -354,16 +355,36 @@ public class StringBasedMongoQueryUnitTests {
|
||||
public void shouldSupportNonQuotedBinaryDataReplacement() throws Exception {
|
||||
|
||||
byte[] binaryData = "Matthews".getBytes("UTF-8");
|
||||
ConvertingParameterAccessor accesor = StubParameterAccessor.getAccessor(converter, binaryData);
|
||||
ConvertingParameterAccessor accessor = StubParameterAccessor.getAccessor(converter, binaryData);
|
||||
StringBasedMongoQuery mongoQuery = createQueryForMethod("findByLastnameAsBinary", byte[].class);
|
||||
|
||||
org.springframework.data.mongodb.core.query.Query query = mongoQuery.createQuery(accesor);
|
||||
org.springframework.data.mongodb.core.query.Query query = mongoQuery.createQuery(accessor);
|
||||
org.springframework.data.mongodb.core.query.Query reference = new BasicQuery("{'lastname' : { '$binary' : '"
|
||||
+ DatatypeConverter.printBase64Binary(binaryData) + "', '$type' : " + BSON.B_GENERAL + "}}");
|
||||
|
||||
assertThat(query.getQueryObject(), is(reference.getQueryObject()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1565
|
||||
*/
|
||||
@Test
|
||||
public void bindsPropertyReferenceMultipleTimesCorrectly() throws Exception {
|
||||
|
||||
StringBasedMongoQuery mongoQuery = createQueryForMethod("findByAgeQuotedAndUnquoted", Integer.TYPE);
|
||||
|
||||
ConvertingParameterAccessor accessor = StubParameterAccessor.getAccessor(converter, 3);
|
||||
|
||||
org.springframework.data.mongodb.core.query.Query query = mongoQuery.createQuery(accessor);
|
||||
BasicDBList or = new BasicDBList();
|
||||
or.add(new BasicDBObject("age", 3));
|
||||
or.add(new BasicDBObject("displayAge", "3"));
|
||||
BasicDBObject queryObject = new BasicDBObject("$or", or);
|
||||
org.springframework.data.mongodb.core.query.Query reference = new BasicQuery(queryObject);
|
||||
|
||||
assertThat(query.getQueryObject(), is(reference.getQueryObject()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1454
|
||||
*/
|
||||
@@ -381,12 +402,12 @@ public class StringBasedMongoQueryUnitTests {
|
||||
@Test
|
||||
public void shouldIgnorePlaceholderPatternInReplacementValue() throws Exception {
|
||||
|
||||
ConvertingParameterAccessor accesor = StubParameterAccessor.getAccessor(converter, "argWith?1andText",
|
||||
ConvertingParameterAccessor accessor = StubParameterAccessor.getAccessor(converter, "argWith?1andText",
|
||||
"nothing-special");
|
||||
|
||||
StringBasedMongoQuery mongoQuery = createQueryForMethod("findByStringWithWildcardChar", String.class, String.class);
|
||||
|
||||
org.springframework.data.mongodb.core.query.Query query = mongoQuery.createQuery(accesor);
|
||||
org.springframework.data.mongodb.core.query.Query query = mongoQuery.createQuery(accessor);
|
||||
assertThat(query.getQueryObject(),
|
||||
is(JSON.parse("{ \"arg0\" : \"argWith?1andText\" , \"arg1\" : \"nothing-special\"}")));
|
||||
}
|
||||
@@ -524,6 +545,9 @@ public class StringBasedMongoQueryUnitTests {
|
||||
@Query("{'id':?#{ [0] ? { $exists :true} : [1] }, 'foo':42, 'bar': ?#{ [0] ? { $exists :false} : [1] }}")
|
||||
List<Person> findByQueryWithExpressionAndMultipleNestedObjects(boolean param0, String param1, String param2);
|
||||
|
||||
@Query(value = "{ $or : [{'age' : ?0 }, {'displayAge' : '?0'}] }")
|
||||
boolean findByAgeQuotedAndUnquoted(int age);
|
||||
|
||||
@Query(value = "{ 'lastname' : ?0 }", exists = true)
|
||||
boolean existsByLastname(String lastname);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user