Browse Source
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-416pull/1/head
14 changed files with 405 additions and 33 deletions
@ -0,0 +1,35 @@
@@ -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 @@
@@ -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 @@
@@ -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); |
||||
} |
||||
} |
||||
@ -0,0 +1,66 @@
@@ -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 @@
@@ -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); |
||||
} |
||||
} |
||||
Loading…
Reference in new issue