From e01c7458844de4c40a304a8431fb92cdd9d91063 Mon Sep 17 00:00:00 2001 From: Oliver Gierke Date: Wed, 26 Apr 2017 17:32:27 +0200 Subject: [PATCH] DATAMONGO-1674 - Adapted to Range API changes. --- .../core/aggregation/AggregationUtils.java | 48 +++++++++++++++++++ .../core/aggregation/ArrayOperators.java | 11 +---- .../core/aggregation/StringOperators.java | 23 +-------- .../repository/query/MongoQueryCreator.java | 33 +++++++------ .../repository/query/MongoQueryExecution.java | 30 ++++-------- .../query/ReactiveMongoQueryExecution.java | 29 ++++------- ...oParametersParameterAccessorUnitTests.java | 14 +++--- 7 files changed, 94 insertions(+), 94 deletions(-) create mode 100644 spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationUtils.java diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationUtils.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationUtils.java new file mode 100644 index 000000000..2962993c4 --- /dev/null +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationUtils.java @@ -0,0 +1,48 @@ +/* + * Copyright 2017 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.core.aggregation; + +import java.util.ArrayList; +import java.util.List; + +import org.springframework.data.domain.Range; +import org.springframework.util.Assert; + +/** + * Utility methods for aggregation ooperation implementations. + * + * @author Oliver Gierke + */ +interface AggregationUtils { + + /** + * Converts the given {@link Range} into an array of values. + * + * @param range must not be {@literal null}. + * @return + */ + public static List toRangeValues(Range range) { + + Assert.notNull(range, "Range must not be null!"); + + List result = new ArrayList(2); + result.add(range.getLowerBound().getValue() + .orElseThrow(() -> new IllegalArgumentException("Lower bound of range must be bounded!"))); + range.getUpperBound().getValue().ifPresent(it -> result.add(it)); + + return result; + } +} diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ArrayOperators.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ArrayOperators.java index 0d3d7399e..fc61f4372 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ArrayOperators.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ArrayOperators.java @@ -849,16 +849,7 @@ public class ArrayOperators { } public IndexOfArray within(Range range) { - - Assert.notNull(range, "Range must not be null!"); - - List rangeValues = new ArrayList(2); - rangeValues.add(range.getLowerBound()); - if (range.getUpperBound() != null) { - rangeValues.add(range.getUpperBound()); - } - - return new IndexOfArray(append(rangeValues)); + return new IndexOfArray(append(AggregationUtils.toRangeValues(range))); } /** diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/StringOperators.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/StringOperators.java index eed2ac8d3..2f6188d58 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/StringOperators.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/StringOperators.java @@ -15,7 +15,6 @@ */ package org.springframework.data.mongodb.core.aggregation; -import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; @@ -732,16 +731,7 @@ public class StringOperators { * @return */ public IndexOfBytes within(Range range) { - - Assert.notNull(range, "Range must not be null!"); - - List rangeValues = new ArrayList(2); - rangeValues.add(range.getLowerBound()); - if (range.getUpperBound() != null) { - rangeValues.add(range.getUpperBound()); - } - - return new IndexOfBytes(append(rangeValues)); + return new IndexOfBytes(append(AggregationUtils.toRangeValues(range))); } public static class SubstringBuilder { @@ -831,16 +821,7 @@ public class StringOperators { * @return */ public IndexOfCP within(Range range) { - - Assert.notNull(range, "Range must not be null!"); - - List rangeValues = new ArrayList(2); - rangeValues.add(range.getLowerBound()); - if (range.getUpperBound() != null) { - rangeValues.add(range.getUpperBound()); - } - - return new IndexOfCP(append(rangeValues)); + return new IndexOfCP(append(AggregationUtils.toRangeValues(range))); } public static class SubstringBuilder { 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 401f306c9..69c1c2572 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,7 +21,6 @@ import java.util.Arrays; import java.util.Collection; import java.util.Iterator; import java.util.Optional; -import java.util.regex.Pattern; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -61,7 +60,6 @@ import org.springframework.util.ClassUtils; class MongoQueryCreator extends AbstractQueryCreator { private static final Logger LOG = LoggerFactory.getLogger(MongoQueryCreator.class); - private static final Pattern PUNCTATION_PATTERN = Pattern.compile("\\p{Punct}"); private final MongoParameterAccessor accessor; private final boolean isGeoNearQuery; @@ -217,28 +215,29 @@ class MongoQueryCreator extends AbstractQueryCreator { case NEAR: Range range = accessor.getDistanceRange(); - Distance distance = range.getUpperBound(); - Distance minDistance = range.getLowerBound(); + Optional distance = range.getUpperBound().getValue(); + Optional minDistance = range.getLowerBound().getValue(); Point point = accessor.getGeoNearLocation(); - point = point == null ? nextAs(parameters, Point.class) : point; + Point pointToUse = point == null ? nextAs(parameters, Point.class) : point; boolean isSpherical = isSpherical(property); - if (distance == null) { - return isSpherical ? criteria.nearSphere(point) : criteria.near(point); - } else { - if (isSpherical || !Metrics.NEUTRAL.equals(distance.getMetric())) { - criteria.nearSphere(point); + return distance.map(it -> { + + if (isSpherical || !Metrics.NEUTRAL.equals(it.getMetric())) { + criteria.nearSphere(pointToUse); } else { - criteria.near(point); + criteria.near(pointToUse); } - criteria.maxDistance(distance.getNormalizedValue()); - if (minDistance != null) { - criteria.minDistance(minDistance.getNormalizedValue()); - } - } - return criteria; + + criteria.maxDistance(it.getNormalizedValue()); + minDistance.ifPresent(min -> criteria.minDistance(min.getNormalizedValue())); + + return criteria; + + }).orElseGet(() -> isSpherical ? criteria.nearSphere(pointToUse) : criteria.near(pointToUse)); + case WITHIN: Object parameter = parameters.next(); diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoQueryExecution.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoQueryExecution.java index adca90606..401bcd162 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoQueryExecution.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoQueryExecution.java @@ -140,13 +140,13 @@ interface MongoQueryExecution { // Adjust limit if page would exceed the overall limit if (overallLimit != 0 && pageable.getOffset() + pageable.getPageSize() > overallLimit) { - query.limit((int)(overallLimit - pageable.getOffset())); + query.limit((int) (overallLimit - pageable.getOffset())); } return PageableExecutionUtils.getPage(operations.find(query, type, collection), pageable, () -> { - long count = operations.count(query, type, collection); - return overallLimit != 0 ? Math.min(count, overallLimit) : count; + long count = operations.count(query, type, collection); + return overallLimit != 0 ? Math.min(count, overallLimit) : count; }); } @@ -249,17 +249,8 @@ interface MongoQueryExecution { } Range distances = accessor.getDistanceRange(); - Distance maxDistance = distances.getUpperBound(); - - if (maxDistance != null) { - nearQuery.maxDistance(maxDistance).in(maxDistance.getMetric()); - } - - Distance minDistance = distances.getLowerBound(); - - if (minDistance != null) { - nearQuery.minDistance(minDistance).in(minDistance.getMetric()); - } + distances.getLowerBound().getValue().ifPresent(it -> nearQuery.minDistance(it).in(it.getMetric())); + distances.getUpperBound().getValue().ifPresent(it -> nearQuery.maxDistance(it).in(it.getMetric())); Pageable pageable = accessor.getPageable(); @@ -315,13 +306,12 @@ interface MongoQueryExecution { Page> page = PageableExecutionUtils.getPage(geoResults.getContent(), accessor.getPageable(), () -> { + ConvertingParameterAccessor parameterAccessor = new ConvertingParameterAccessor(operations.getConverter(), + accessor); + Query countQuery = mongoQuery + .applyQueryMetaAttributesWhenPresent(mongoQuery.createCountQuery(parameterAccessor)); - ConvertingParameterAccessor parameterAccessor = new ConvertingParameterAccessor(operations.getConverter(), - accessor); - Query countQuery = mongoQuery - .applyQueryMetaAttributesWhenPresent(mongoQuery.createCountQuery(parameterAccessor)); - - return operations.count(countQuery, collection); + return operations.count(countQuery, collection); }); diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveMongoQueryExecution.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveMongoQueryExecution.java index 03da22d14..cc7baeb3d 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveMongoQueryExecution.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveMongoQueryExecution.java @@ -15,13 +15,16 @@ */ package org.springframework.data.mongodb.repository.query; +import lombok.NonNull; +import lombok.RequiredArgsConstructor; +import reactor.core.publisher.Flux; + import java.util.Optional; import org.springframework.core.convert.converter.Converter; import org.springframework.data.convert.EntityInstantiators; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Range; -import org.springframework.data.domain.Slice; import org.springframework.data.geo.Distance; import org.springframework.data.geo.GeoResult; import org.springframework.data.geo.Point; @@ -34,17 +37,12 @@ import org.springframework.data.repository.util.ReactiveWrappers; import org.springframework.data.util.TypeInformation; import org.springframework.util.ClassUtils; -import lombok.NonNull; -import lombok.RequiredArgsConstructor; -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; - import com.mongodb.client.result.DeleteResult; /** * Set of classes to contain query execution strategies. Depending (mostly) on the return type of a - * {@link org.springframework.data.repository.query.QueryMethod} a {@link AbstractReactiveMongoQuery} can be executed in various - * flavors. + * {@link org.springframework.data.repository.query.QueryMethod} a {@link AbstractReactiveMongoQuery} can be executed in + * various flavors. * * @author Mark Paluch * @since 2.0 @@ -127,7 +125,7 @@ interface ReactiveMongoQueryExecution { return isStreamOfGeoResult() ? results : results.map(GeoResult::getContent); } - @SuppressWarnings("unchecked") + @SuppressWarnings({ "unchecked", "rawtypes" }) protected Flux> doExecuteQuery(Query query, Class type, String collection) { Point nearLocation = accessor.getGeoNearLocation(); @@ -138,17 +136,8 @@ interface ReactiveMongoQueryExecution { } Range distances = accessor.getDistanceRange(); - Distance maxDistance = distances.getUpperBound(); - - if (maxDistance != null) { - nearQuery.maxDistance(maxDistance).in(maxDistance.getMetric()); - } - - Distance minDistance = distances.getLowerBound(); - - if (minDistance != null) { - nearQuery.minDistance(minDistance).in(minDistance.getMetric()); - } + distances.getUpperBound().getValue().ifPresent(it -> nearQuery.maxDistance(it).in(it.getMetric())); + distances.getLowerBound().getValue().ifPresent(it -> nearQuery.minDistance(it).in(it.getMetric())); Pageable pageable = accessor.getPageable(); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/MongoParametersParameterAccessorUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/MongoParametersParameterAccessorUnitTests.java index 0ba05dc3b..4cbe24af7 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/MongoParametersParameterAccessorUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/MongoParametersParameterAccessorUnitTests.java @@ -15,8 +15,9 @@ */ package org.springframework.data.mongodb.repository.query; +import static org.assertj.core.api.Assertions.assertThat; import static org.hamcrest.CoreMatchers.*; -import static org.junit.Assert.*; +import static org.junit.Assert.assertThat; import java.lang.reflect.Method; import java.util.List; @@ -25,6 +26,7 @@ import org.bson.Document; import org.hamcrest.core.IsNull; import org.junit.Test; import org.springframework.data.domain.Range; +import org.springframework.data.domain.Range.Bound; import org.springframework.data.geo.Distance; import org.springframework.data.geo.Metrics; import org.springframework.data.geo.Point; @@ -51,14 +53,14 @@ public class MongoParametersParameterAccessorUnitTests { ProjectionFactory factory = new SpelAwareProxyProjectionFactory(); @Test - public void returnsNullForDistanceIfNoneAvailable() throws NoSuchMethodException, SecurityException { + public void returnsUnboundedForDistanceIfNoneAvailable() throws NoSuchMethodException, SecurityException { Method method = PersonRepository.class.getMethod("findByLocationNear", Point.class); MongoQueryMethod queryMethod = new MongoQueryMethod(method, metadata, factory, context); MongoParameterAccessor accessor = new MongoParametersParameterAccessor(queryMethod, new Object[] { new Point(10, 20) }); - assertThat(accessor.getDistanceRange().getUpperBound(), is(nullValue())); + assertThat(accessor.getDistanceRange().getUpperBound().isBounded()).isFalse(); } @Test @@ -69,7 +71,7 @@ public class MongoParametersParameterAccessorUnitTests { MongoParameterAccessor accessor = new MongoParametersParameterAccessor(queryMethod, new Object[] { new Point(10, 20), DISTANCE }); - assertThat(accessor.getDistanceRange().getUpperBound(), is(DISTANCE)); + assertThat(accessor.getDistanceRange().getUpperBound()).isEqualTo(Bound.inclusive(DISTANCE)); } @Test // DATAMONGO-973 @@ -109,8 +111,8 @@ public class MongoParametersParameterAccessorUnitTests { Range range = accessor.getDistanceRange(); - assertThat(range.getLowerBound(), is(min)); - assertThat(range.getUpperBound(), is(max)); + assertThat(range.getLowerBound(), is(Bound.inclusive(min))); + assertThat(range.getUpperBound(), is(Bound.inclusive(max))); } interface PersonRepository extends Repository {