DATACMNS-61 - Adapted changes in Spring Data Commons.
Use QueryMethod accessor methods instead of dropped Type enum to determine query execution. Added custom MongoParameters and MongoParameter to allow discovering a Distance parameter for repository queries which will transparently add a 'maxDistance' clause for *Near criterias in query methods. If the given Distance is equipped with a Metric we will rather use $nearSphere over $near. Added asList() to Point class to circumvent bug in BasicBSONObject.equals(…) which breaks equals(…) comparisons of DBObjects in case they use arrays as values. See [0] for details. Adapted usage of Point objects to use asList() over asArray(). [0] https://jira.mongodb.org/browse/JAVA-416
This commit is contained in:
@@ -15,6 +15,9 @@
|
||||
*/
|
||||
package org.springframework.data.mongodb.core.geo;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.data.annotation.PersistenceConstructor;
|
||||
import org.springframework.data.mongodb.core.mapping.Field;
|
||||
import org.springframework.util.Assert;
|
||||
@@ -55,6 +58,10 @@ public class Point {
|
||||
public double[] asArray() {
|
||||
return new double[] { x, y };
|
||||
}
|
||||
|
||||
public List<Double> asList() {
|
||||
return Arrays.asList(x, y);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
|
||||
@@ -18,7 +18,6 @@ package org.springframework.data.mongodb.core.query;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import com.mongodb.BasicDBObject;
|
||||
@@ -295,8 +294,8 @@ public class Criteria implements CriteriaDefinition {
|
||||
*/
|
||||
public Criteria withinCenter(Circle circle) {
|
||||
Assert.notNull(circle);
|
||||
LinkedList<Object> list = new LinkedList<Object>();
|
||||
list.addLast(circle.getCenter().asArray());
|
||||
List<Object> list = new ArrayList<Object>();
|
||||
list.add(circle.getCenter().asList());
|
||||
list.add(circle.getRadius());
|
||||
criteria.put("$within", new BasicDBObject("$center", list));
|
||||
return this;
|
||||
@@ -311,8 +310,8 @@ public class Criteria implements CriteriaDefinition {
|
||||
*/
|
||||
public Criteria withinCenterSphere(Circle circle) {
|
||||
Assert.notNull(circle);
|
||||
LinkedList<Object> list = new LinkedList<Object>();
|
||||
list.addLast(circle.getCenter().asArray());
|
||||
List<Object> list = new ArrayList<Object>();
|
||||
list.add(circle.getCenter().asList());
|
||||
list.add(circle.getRadius());
|
||||
criteria.put("$within", new BasicDBObject("$centerSphere", list));
|
||||
return this;
|
||||
@@ -326,9 +325,9 @@ public class Criteria implements CriteriaDefinition {
|
||||
*/
|
||||
public Criteria withinBox(Box box) {
|
||||
Assert.notNull(box);
|
||||
LinkedList<double[]> list = new LinkedList<double[]>();
|
||||
list.addLast(box.getLowerLeft().asArray());
|
||||
list.addLast(box.getUpperRight().asArray());
|
||||
List<List<Double>> list = new ArrayList<List<Double>>();
|
||||
list.add(box.getLowerLeft().asList());
|
||||
list.add(box.getUpperRight().asList());
|
||||
criteria.put("$within", new BasicDBObject("$box", list));
|
||||
return this;
|
||||
}
|
||||
@@ -342,7 +341,7 @@ public class Criteria implements CriteriaDefinition {
|
||||
*/
|
||||
public Criteria near(Point point) {
|
||||
Assert.notNull(point);
|
||||
criteria.put("$near", point.asArray());
|
||||
criteria.put("$near", point.asList());
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -355,7 +354,7 @@ public class Criteria implements CriteriaDefinition {
|
||||
*/
|
||||
public Criteria nearSphere(Point point) {
|
||||
Assert.notNull(point);
|
||||
criteria.put("$nearSphere", point.asArray());
|
||||
criteria.put("$nearSphere", point.asList());
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ public class NearQuery {
|
||||
Assert.notNull(point);
|
||||
|
||||
this.criteria = new BasicDBObject();
|
||||
this.criteria.put("near", point.asArray());
|
||||
this.criteria.put("near", point.asList());
|
||||
|
||||
this.metric = metric;
|
||||
if (metric != null) {
|
||||
|
||||
@@ -19,19 +19,19 @@ import static org.springframework.data.mongodb.repository.QueryUtils.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.mongodb.DBCollection;
|
||||
import com.mongodb.DBCursor;
|
||||
import com.mongodb.DBObject;
|
||||
import org.springframework.data.domain.PageImpl;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.mongodb.core.CollectionCallback;
|
||||
import org.springframework.data.mongodb.core.MongoTemplate;
|
||||
import org.springframework.data.mongodb.core.query.Query;
|
||||
import org.springframework.data.repository.query.ParameterAccessor;
|
||||
import org.springframework.data.repository.query.ParametersParameterAccessor;
|
||||
import org.springframework.data.repository.query.RepositoryQuery;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import com.mongodb.DBCollection;
|
||||
import com.mongodb.DBCursor;
|
||||
import com.mongodb.DBObject;
|
||||
|
||||
/**
|
||||
* Base class for {@link RepositoryQuery} implementations for Mongo.
|
||||
*
|
||||
@@ -72,15 +72,14 @@ public abstract class AbstractMongoQuery implements RepositoryQuery {
|
||||
*/
|
||||
public Object execute(Object[] parameters) {
|
||||
|
||||
ParameterAccessor accessor = new ParametersParameterAccessor(method.getParameters(), parameters);
|
||||
MongoParameterAccessor accessor = new MongoParametersParameterAccessor(method.getParameters(), parameters);
|
||||
Query query = createQuery(new ConvertingParameterAccessor(template.getConverter(), accessor));
|
||||
|
||||
switch (method.getType()) {
|
||||
case COLLECTION:
|
||||
if (method.isCollectionQuery()) {
|
||||
return new CollectionExecution().execute(query);
|
||||
case PAGING:
|
||||
} else if (method.isPageQuery()) {
|
||||
return new PagedExecution(accessor.getPageable()).execute(query);
|
||||
default:
|
||||
} else {
|
||||
return new SingleEntityExecution().execute(query);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.mongodb.core.convert.MappingMongoConverter;
|
||||
import org.springframework.data.mongodb.core.convert.MongoWriter;
|
||||
import org.springframework.data.mongodb.core.geo.Distance;
|
||||
import org.springframework.data.repository.query.ParameterAccessor;
|
||||
|
||||
import com.mongodb.BasicDBList;
|
||||
@@ -31,17 +32,17 @@ import com.mongodb.DBObject;
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class ConvertingParameterAccessor implements ParameterAccessor {
|
||||
public class ConvertingParameterAccessor implements MongoParameterAccessor {
|
||||
|
||||
private final MongoWriter<Object> writer;
|
||||
private final ParameterAccessor delegate;
|
||||
private final MongoParameterAccessor delegate;
|
||||
|
||||
/**
|
||||
* Creates a new {@link ConvertingParameterAccessor} with the given {@link MongoWriter} and delegate.
|
||||
*
|
||||
* @param writer
|
||||
*/
|
||||
public ConvertingParameterAccessor(MongoWriter<Object> writer, ParameterAccessor delegate) {
|
||||
public ConvertingParameterAccessor(MongoWriter<Object> writer, MongoParameterAccessor delegate) {
|
||||
this.writer = writer;
|
||||
this.delegate = delegate;
|
||||
}
|
||||
@@ -51,7 +52,7 @@ public class ConvertingParameterAccessor implements ParameterAccessor {
|
||||
*
|
||||
* @see java.lang.Iterable#iterator()
|
||||
*/
|
||||
public Iterator<Object> iterator() {
|
||||
public PotentiallyConvertingIterator iterator() {
|
||||
return new ConvertingIterator(delegate.iterator());
|
||||
}
|
||||
|
||||
@@ -80,6 +81,14 @@ public class ConvertingParameterAccessor implements ParameterAccessor {
|
||||
|
||||
return getConvertedValue(delegate.getBindableValue(index));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.repository.MongoParameterAccessor#getMaxDistance()
|
||||
*/
|
||||
public Distance getMaxDistance() {
|
||||
return delegate.getMaxDistance();
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the given value with the underlying {@link MongoWriter}.
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright 2011 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.mongodb.repository;
|
||||
|
||||
import org.springframework.data.mongodb.core.geo.Distance;
|
||||
import org.springframework.data.repository.query.ParameterAccessor;
|
||||
|
||||
/**
|
||||
* Mongo-specific {@link ParameterAccessor} exposing a maximum distance parameter.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public interface MongoParameterAccessor extends ParameterAccessor {
|
||||
|
||||
/**
|
||||
* Returns a {@link Distance} to be applied to Mongo geo queries.
|
||||
*
|
||||
* @return the maximum distance to apply to the geo query or {@literal null} if there's no {@link Distance} parameter
|
||||
* at all or the given value for it was {@literal null}.
|
||||
*/
|
||||
Distance getMaxDistance();
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
package org.springframework.data.mongodb.repository;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.data.mongodb.core.geo.Distance;
|
||||
import org.springframework.data.repository.query.Parameter;
|
||||
import org.springframework.data.repository.query.Parameters;
|
||||
|
||||
/**
|
||||
* Custom extension of {@link Parameters} discovering additional
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class MongoParameters extends Parameters {
|
||||
|
||||
private int distanceIndex = -1;
|
||||
|
||||
public MongoParameters(Method method) {
|
||||
|
||||
super(method);
|
||||
this.distanceIndex = Arrays.asList(method.getParameterTypes()).indexOf(Distance.class);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.data.repository.query.Parameters#createParameter(org.springframework.core.MethodParameter)
|
||||
*/
|
||||
@Override
|
||||
protected Parameter createParameter(MethodParameter parameter) {
|
||||
return new MongoParameter(parameter, this);
|
||||
}
|
||||
|
||||
public int getDistanceIndex() {
|
||||
return distanceIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom {@link Parameter} implementation adding parameters of type {@link Distance} to the special ones.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
static class MongoParameter extends Parameter {
|
||||
|
||||
/**
|
||||
*
|
||||
* @param parameter
|
||||
* @param parameters
|
||||
*/
|
||||
MongoParameter(MethodParameter parameter, Parameters parameters) {
|
||||
super(parameter, parameters);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.repository.query.Parameter#isSpecialParameter()
|
||||
*/
|
||||
@Override
|
||||
public boolean isSpecialParameter() {
|
||||
return super.isSpecialParameter() || getType().equals(Distance.class);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright 2011 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.mongodb.repository;
|
||||
|
||||
import org.springframework.data.mongodb.core.geo.Distance;
|
||||
import org.springframework.data.repository.query.ParametersParameterAccessor;
|
||||
|
||||
/**
|
||||
* Mongo-specific {@link ParametersParameterAccessor} to allow access to the {@link Distance} parameter.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class MongoParametersParameterAccessor extends ParametersParameterAccessor implements MongoParameterAccessor {
|
||||
|
||||
private final MongoParameters parameters;
|
||||
|
||||
/**
|
||||
* @param parameters
|
||||
* @param values
|
||||
*/
|
||||
public MongoParametersParameterAccessor(MongoParameters parameters, Object[] values) {
|
||||
super(parameters, values);
|
||||
this.parameters = parameters;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.repository.MongoParameterAccessor#getMaxDistance()
|
||||
*/
|
||||
public Distance getMaxDistance() {
|
||||
int index = parameters.getDistanceIndex();
|
||||
return index == -1 ? null : (Distance) getValue(index);
|
||||
}
|
||||
}
|
||||
@@ -26,12 +26,12 @@ import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.mongodb.core.geo.Box;
|
||||
import org.springframework.data.mongodb.core.geo.Circle;
|
||||
import org.springframework.data.mongodb.core.geo.Distance;
|
||||
import org.springframework.data.mongodb.core.geo.Point;
|
||||
import org.springframework.data.mongodb.core.query.Criteria;
|
||||
import org.springframework.data.mongodb.core.query.CriteriaDefinition;
|
||||
import org.springframework.data.mongodb.core.query.Query;
|
||||
import org.springframework.data.mongodb.repository.ConvertingParameterAccessor.PotentiallyConvertingIterator;
|
||||
import org.springframework.data.repository.query.ParameterAccessor;
|
||||
import org.springframework.data.repository.query.ParametersParameterAccessor;
|
||||
import org.springframework.data.repository.query.parser.AbstractQueryCreator;
|
||||
import org.springframework.data.repository.query.parser.Part;
|
||||
@@ -46,6 +46,7 @@ import org.springframework.data.repository.query.parser.PartTree;
|
||||
class MongoQueryCreator extends AbstractQueryCreator<Query, Query> {
|
||||
|
||||
private static final Log LOG = LogFactory.getLog(MongoQueryCreator.class);
|
||||
private final MongoParameterAccessor accessor;
|
||||
|
||||
/**
|
||||
* Creates a new {@link MongoQueryCreator} from the given {@link PartTree} and {@link ParametersParameterAccessor}.
|
||||
@@ -53,9 +54,10 @@ class MongoQueryCreator extends AbstractQueryCreator<Query, Query> {
|
||||
* @param tree
|
||||
* @param accessor
|
||||
*/
|
||||
public MongoQueryCreator(PartTree tree, ParameterAccessor accessor) {
|
||||
public MongoQueryCreator(PartTree tree, ConvertingParameterAccessor accessor) {
|
||||
|
||||
super(tree, accessor);
|
||||
this.accessor = accessor;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -144,9 +146,23 @@ class MongoQueryCreator extends AbstractQueryCreator<Query, Query> {
|
||||
String value = parameters.next().toString();
|
||||
return criteria.is(toLikeRegex(value));
|
||||
case NEAR:
|
||||
return criteria.near(nextAs(parameters, Point.class));
|
||||
|
||||
Distance distance = accessor.getMaxDistance();
|
||||
Point point = nextAs(parameters, Point.class);
|
||||
|
||||
if (distance == null) {
|
||||
return criteria.near(point);
|
||||
} else {
|
||||
if (distance.getMetric() != null) {
|
||||
criteria.nearSphere(point);
|
||||
} else {
|
||||
criteria.near(point);
|
||||
}
|
||||
criteria.maxDistance(distance.getNormalizedValue());
|
||||
}
|
||||
return criteria;
|
||||
|
||||
case WITHIN:
|
||||
|
||||
Object parameter = parameters.next();
|
||||
if (parameter instanceof Box) {
|
||||
return criteria.withinBox((Box) parameter);
|
||||
|
||||
@@ -20,6 +20,7 @@ import java.lang.reflect.Method;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.data.mongodb.repository.MongoRepositoryFactoryBean.EntityInformationCreator;
|
||||
import org.springframework.data.repository.core.RepositoryMetadata;
|
||||
import org.springframework.data.repository.query.Parameters;
|
||||
import org.springframework.data.repository.query.QueryMethod;
|
||||
import org.springframework.data.repository.util.ClassUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
@@ -45,6 +46,15 @@ class MongoQueryMethod extends QueryMethod {
|
||||
this.method = method;
|
||||
this.entityInformation = entityInformationCreator.getEntityInformation(ClassUtils.getReturnedDomainClass(method));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.repository.query.QueryMethod#getParameters(java.lang.reflect.Method)
|
||||
*/
|
||||
@Override
|
||||
protected Parameters createParameters(Method method) {
|
||||
return new MongoParameters(method);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the method has an annotated query.
|
||||
@@ -78,14 +88,24 @@ class MongoQueryMethod extends QueryMethod {
|
||||
return StringUtils.hasText(value) ? value : null;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.data.repository.query.QueryMethod#getEntityMetadata()
|
||||
*/
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.repository.query.QueryMethod#getEntityInformation()
|
||||
*/
|
||||
@Override
|
||||
public MongoEntityInformation<?, ?> getEntityInformation() {
|
||||
|
||||
return entityInformation;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.repository.query.QueryMethod#getParameters()
|
||||
*/
|
||||
@Override
|
||||
public MongoParameters getParameters() {
|
||||
return (MongoParameters) super.getParameters();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link Query} annotation that is applied to the method or {@code null} if none available.
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright 2011 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.mongodb.repository;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.data.mongodb.core.geo.Distance;
|
||||
import org.springframework.data.mongodb.core.geo.Metrics;
|
||||
import org.springframework.data.mongodb.core.geo.Point;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link MongoParametersParameterAccessor}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class MongoParametersParameterAccessorUnitTests {
|
||||
|
||||
private static final Distance DISTANCE = new Distance(2.5, Metrics.KILOMETERS);
|
||||
|
||||
@Test
|
||||
public void returnsNullForDistanceIfNoneAvailable() throws NoSuchMethodException, SecurityException {
|
||||
|
||||
Method method = PersonRepository.class.getMethod("findByLocationNear", Point.class);
|
||||
MongoParameters parameters = new MongoParameters(method);
|
||||
|
||||
MongoParameterAccessor accessor = new MongoParametersParameterAccessor(parameters,
|
||||
new Object[] { new Point(10, 20) });
|
||||
assertThat(accessor.getMaxDistance(), is(nullValue()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void returnsDistanceIfAvailable() throws NoSuchMethodException, SecurityException {
|
||||
|
||||
Method method = PersonRepository.class.getMethod("findByLocationNear", Point.class, Distance.class);
|
||||
MongoParameters parameters = new MongoParameters(method);
|
||||
|
||||
MongoParameterAccessor accessor = new MongoParametersParameterAccessor(parameters, new Object[] {
|
||||
new Point(10, 20), DISTANCE });
|
||||
assertThat(accessor.getMaxDistance(), is(DISTANCE));
|
||||
}
|
||||
|
||||
interface PersonRepository {
|
||||
|
||||
List<Person> findByLocationNear(Point point);
|
||||
|
||||
List<Person> findByLocationNear(Point point, Distance distance);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright 2011 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.mongodb.repository;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.data.mongodb.core.geo.Distance;
|
||||
import org.springframework.data.mongodb.core.geo.Point;
|
||||
import org.springframework.data.mongodb.repository.MongoParameters.MongoParameter;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link MongoParameters}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class MongoParametersUnitTests {
|
||||
|
||||
@Test
|
||||
public void discoversDistanceParameter() throws NoSuchMethodException, SecurityException {
|
||||
Method method = PersonRepository.class.getMethod("findByLocationNear", Point.class, Distance.class);
|
||||
MongoParameters parameters = new MongoParameters(method);
|
||||
|
||||
assertThat(parameters.getNumberOfParameters(), is(2));
|
||||
assertThat(parameters.getDistanceIndex(), is(1));
|
||||
assertThat(parameters.getBindableParameters().getNumberOfParameters(), is(1));
|
||||
|
||||
MongoParameter parameter = new MongoParameters.MongoParameter(new MethodParameter(method,
|
||||
parameters.getDistanceIndex()), parameters);
|
||||
|
||||
assertThat(parameter.isSpecialParameter(), is(true));
|
||||
assertThat(parameter.isBindable(), is(false));
|
||||
}
|
||||
|
||||
interface PersonRepository {
|
||||
|
||||
List<Person> findByLocationNear(Point point, Distance distance);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
* Copyright 2011 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.
|
||||
@@ -19,8 +19,12 @@ import static org.junit.Assert.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
import static org.hamcrest.CoreMatchers.*;
|
||||
import static org.springframework.data.mongodb.repository.StubParameterAccessor.*;
|
||||
import static org.springframework.data.mongodb.core.query.Query.*;
|
||||
import static org.springframework.data.mongodb.core.query.Criteria.*;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
@@ -31,6 +35,9 @@ import org.mockito.runners.MockitoJUnitRunner;
|
||||
import org.mockito.stubbing.Answer;
|
||||
import org.springframework.data.mongodb.core.Person;
|
||||
import org.springframework.data.mongodb.core.convert.MongoConverter;
|
||||
import org.springframework.data.mongodb.core.geo.Distance;
|
||||
import org.springframework.data.mongodb.core.geo.Metrics;
|
||||
import org.springframework.data.mongodb.core.geo.Point;
|
||||
import org.springframework.data.mongodb.core.query.Criteria;
|
||||
import org.springframework.data.mongodb.core.query.Query;
|
||||
import org.springframework.data.mongodb.repository.MongoQueryCreator;
|
||||
@@ -96,4 +103,42 @@ public class MongoQueryCreatorUnitTests {
|
||||
|
||||
assertThat(query.getQueryObject(), is(new Query(Criteria.where("firstName").is(null)).getQueryObject()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void bindsMetricDistanceParameterToNearSphereCorrectly() throws Exception {
|
||||
|
||||
Point point = new Point(10, 20);
|
||||
Distance distance = new Distance(2.5, Metrics.KILOMETERS);
|
||||
|
||||
Query query = query(where("location").nearSphere(point).maxDistance(distance.getNormalizedValue()).and("firstname").is("Dave"));
|
||||
assertBindsDistanceToQuery(point, distance, query);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void bindsDistanceParameterToNearCorrectly() throws Exception {
|
||||
|
||||
Point point = new Point(10, 20);
|
||||
Distance distance = new Distance(2.5);
|
||||
|
||||
Query query = query(where("location").near(point).maxDistance(distance.getNormalizedValue()).and("firstname").is("Dave"));
|
||||
assertBindsDistanceToQuery(point, distance, query);
|
||||
}
|
||||
|
||||
private void assertBindsDistanceToQuery(Point point, Distance distance, Query reference) throws Exception {
|
||||
|
||||
when(converter.convertToMongoType("Dave")).thenReturn("Dave");
|
||||
|
||||
PartTree tree = new PartTree("findByLocationNearAndFirstname", org.springframework.data.mongodb.repository.Person.class);
|
||||
MongoParameters parameters = new MongoParameters(PersonRepository.class.getMethod("findByLocationNearAndFirstname", Point.class, Distance.class, String.class));
|
||||
MongoParameterAccessor accessor = new MongoParametersParameterAccessor(parameters, new Object[] { point, distance, "Dave" });
|
||||
|
||||
Query query = new MongoQueryCreator(tree, new ConvertingParameterAccessor(converter, accessor)).createQuery();
|
||||
assertThat(query.getQueryObject(), is(query.getQueryObject()));
|
||||
|
||||
}
|
||||
|
||||
interface PersonRepository {
|
||||
|
||||
List<Person> findByLocationNearAndFirstname(Point location, Distance maxDistance, String firstname);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import java.util.Iterator;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.mongodb.core.convert.MongoWriter;
|
||||
import org.springframework.data.mongodb.core.geo.Distance;
|
||||
import org.springframework.data.mongodb.repository.ConvertingParameterAccessor;
|
||||
import org.springframework.data.repository.query.ParameterAccessor;
|
||||
|
||||
@@ -29,7 +30,7 @@ import org.springframework.data.repository.query.ParameterAccessor;
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
class StubParameterAccessor implements ParameterAccessor {
|
||||
class StubParameterAccessor implements MongoParameterAccessor {
|
||||
|
||||
private final Object[] values;
|
||||
|
||||
@@ -74,6 +75,14 @@ class StubParameterAccessor implements ParameterAccessor {
|
||||
public Sort getSort() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.repository.MongoParameterAccessor#getMaxDistance()
|
||||
*/
|
||||
public Distance getMaxDistance() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
|
||||
Reference in New Issue
Block a user