From 80641a0943231d57847322892f6ffff941281691 Mon Sep 17 00:00:00 2001 From: Oliver Gierke Date: Tue, 11 Oct 2011 12:29:54 +0200 Subject: [PATCH] DATADOC-293 - Added Polygon abstraction to Criteria. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Introduced Polygon value object to capture a list of Points. Polished implementation of Circle (equals(…) and hashCode()) and API of Criteria. Added some additional unit tests. Introduced Shape interface to allow streamling the implementation of building within-Criterias. Ignoring the tests for polygons right now until we have updated the Mongo instance on the CI server to 2.0. --- .../data/mongodb/core/geo/Box.java | 24 +++- .../data/mongodb/core/geo/Circle.java | 88 +++++++++++++- .../data/mongodb/core/geo/Polygon.java | 113 ++++++++++++++++++ .../data/mongodb/core/geo/Shape.java | 41 +++++++ .../data/mongodb/core/query/Criteria.java | 46 ++----- .../repository/query/MongoQueryCreator.java | 11 +- .../mongodb/core/geo/CircleUnitTests.java | 54 +++++++++ .../mongodb/core/geo/GeoSpatialTests.java | 70 +++++++---- .../mongodb/core/geo/PolygonUnitTests.java | 54 +++++++++ ...tractPersonRepositoryIntegrationTests.java | 52 +++++--- .../mongodb/repository/PersonRepository.java | 5 +- 11 files changed, 467 insertions(+), 91 deletions(-) create mode 100644 spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/Polygon.java create mode 100644 spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/Shape.java create mode 100644 spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/geo/CircleUnitTests.java create mode 100644 spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/geo/PolygonUnitTests.java diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/Box.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/Box.java index 6a3543ce8..5ce940ecb 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/Box.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/Box.java @@ -15,6 +15,9 @@ */ package org.springframework.data.mongodb.core.geo; +import java.util.ArrayList; +import java.util.List; + import org.springframework.data.mongodb.core.mapping.Field; import org.springframework.util.Assert; @@ -24,7 +27,7 @@ import org.springframework.util.Assert; * @author Mark Pollack * @author Oliver Gierke */ -public class Box { +public class Box implements Shape { @Field(order = 10) private final Point first; @@ -53,6 +56,25 @@ public class Box { return second; } + /* + * (non-Javadoc) + * @see org.springframework.data.mongodb.core.geo.Shape#asList() + */ + public List asList() { + List> list = new ArrayList>(); + list.add(getLowerLeft().asList()); + list.add(getUpperRight().asList()); + return list; + } + + /* + * (non-Javadoc) + * @see org.springframework.data.mongodb.core.geo.Shape#getCommand() + */ + public String getCommand() { + return "$box"; + } + @Override public String toString() { return String.format("Box [%s, %s]", first, second); diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/Circle.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/Circle.java index a590c11cb..e580ba5e8 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/Circle.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/Circle.java @@ -15,6 +15,9 @@ */ package org.springframework.data.mongodb.core.geo; +import java.util.ArrayList; +import java.util.List; + import org.springframework.data.annotation.PersistenceConstructor; import org.springframework.util.Assert; @@ -24,33 +27,112 @@ import org.springframework.util.Assert; * @author Mark Pollack * @author Oliver Gierke */ -public class Circle { +public class Circle implements Shape { - private Point center; - private double radius; + private final Point center; + private final double radius; + /** + * Creates a new {@link Circle} from the given {@link Point} and radius. + * + * @param center must not be {@literal null}. + * @param radius must be greater or equal to zero. + */ @PersistenceConstructor public Circle(Point center, double radius) { + Assert.notNull(center); Assert.isTrue(radius >= 0, "Radius must not be negative!"); + this.center = center; this.radius = radius; } + /** + * Creates a new {@link Circle} from the given coordinates and radius. + * + * @param centerX + * @param centerY + * @param radius must be greater or equal to zero. + */ public Circle(double centerX, double centerY, double radius) { this(new Point(centerX, centerY), radius); } + /** + * Returns the center of the {@link Circle}. + * + * @return will never be {@literal null}. + */ public Point getCenter() { return center; } + /** + * Returns the radius of the {@link Circle}. + * + * @return + */ public double getRadius() { return radius; } + + /* + * (non-Javadoc) + * @see org.springframework.data.mongodb.core.geo.Shape#asList() + */ + public List asList() { + List result = new ArrayList(); + result.add(getCenter().asList()); + result.add(getRadius()); + return result; + } + + /* + * (non-Javadoc) + * @see org.springframework.data.mongodb.core.geo.Shape#getCommand() + */ + public String getCommand() { + return "$center"; + } + /* + * (non-Javadoc) + * @see java.lang.Object#toString() + */ @Override public String toString() { return String.format("Circle [center=%s, radius=%f]", center, radius); } + + /* (non-Javadoc) + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override + public boolean equals(Object obj) { + + if (this == obj) { + return true; + } + + if (obj == null || !getClass().equals(obj.getClass())) { + return false; + } + + Circle that = (Circle) obj; + + return this.center.equals(that.center) && this.radius == that.radius; + } + + /* + * (non-Javadoc) + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() { + int result = 17; + result += 31 * center.hashCode(); + result += 31 * radius; + return result; + } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/Polygon.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/Polygon.java new file mode 100644 index 000000000..7325c311b --- /dev/null +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/Polygon.java @@ -0,0 +1,113 @@ +/* + * 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.core.geo; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; + +import org.springframework.util.Assert; + +/** + * Simple value object to represent a {@link Polygon}. + * + * @author Oliver Gierke + */ +public class Polygon implements Shape, Iterable { + + private final List points; + + /** + * Creates a new {@link Polygon} for the given Points. + * + * @param x + * @param y + * @param z + * @param others + */ + public Polygon(Point x, Point y, Point z, Point... others) { + + Assert.notNull(x); + Assert.notNull(y); + Assert.notNull(z); + Assert.notNull(others); + + this.points = new ArrayList(3 + others.length); + this.points.addAll(Arrays.asList(x, y, z)); + this.points.addAll(Arrays.asList(others)); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.mongodb.core.geo.Shape#asList() + */ + public List> asList() { + + List> result = new ArrayList>(); + + for (Point point : points) { + result.add(point.asList()); + } + + return result; + } + + /* + * (non-Javadoc) + * @see org.springframework.data.mongodb.core.geo.Shape#getCommand() + */ + public String getCommand() { + return "$polygon"; + } + + /* + * (non-Javadoc) + * @see java.lang.Iterable#iterator() + */ + public Iterator iterator() { + return this.points.iterator(); + } + + /* + * (non-Javadoc) + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override + public boolean equals(Object obj) { + + if (this == obj) { + return true; + } + + if (obj == null || !getClass().equals(obj.getClass())) { + return false; + } + + Polygon that = (Polygon) obj; + + return this.points.equals(that.points); + } + + /* + * (non-Javadoc) + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() { + return points.hashCode(); + } +} diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/Shape.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/Shape.java new file mode 100644 index 000000000..926b85a3b --- /dev/null +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/Shape.java @@ -0,0 +1,41 @@ +/* + * 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.core.geo; + +import java.util.List; + +/** + * Common interface for all shapes. Allows building MongoDB representations of them. + * + * @author Oliver Gierke + */ +public interface Shape { + + /** + * Returns the {@link Shape} as a list of usually {@link Double} or {@link List}s of {@link Double}s. Wildcard bound + * to allow implementations to return a more concrete element type. + * + * @return + */ + List asList(); + + /** + * Returns the command to be used to create the {@literal $within} criterion. + * + * @return + */ + String getCommand(); +} diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Criteria.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Criteria.java index 2e4c538b0..8debe3670 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Criteria.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Criteria.java @@ -20,16 +20,16 @@ import java.util.Collection; import java.util.LinkedHashMap; import java.util.List; -import com.mongodb.BasicDBObject; -import com.mongodb.DBObject; - import org.springframework.data.mongodb.InvalidMongoDbApiUsageException; -import org.springframework.data.mongodb.core.geo.Box; import org.springframework.data.mongodb.core.geo.Circle; import org.springframework.data.mongodb.core.geo.Point; +import org.springframework.data.mongodb.core.geo.Shape; import org.springframework.util.Assert; import org.springframework.util.StringUtils; +import com.mongodb.BasicDBObject; +import com.mongodb.DBObject; + public class Criteria implements CriteriaDefinition { /** @@ -282,48 +282,22 @@ public class Criteria implements CriteriaDefinition { return this; } - /** - * Creates a geospatial criterion using a $within $center operation - * - * @param circle must not be {@literal null} - * @return - */ - public Criteria withinCenter(Circle circle) { - Assert.notNull(circle); - List list = new ArrayList(); - list.add(circle.getCenter().asList()); - list.add(circle.getRadius()); - criteria.put("$within", new BasicDBObject("$center", list)); - return this; - } - /** * Creates a geospatial criterion using a $within $center operation. This is only available for Mongo 1.7 and higher. * * @param circle must not be {@literal null} * @return */ - public Criteria withinCenterSphere(Circle circle) { + public Criteria withinSphere(Circle circle) { Assert.notNull(circle); - List list = new ArrayList(); - list.add(circle.getCenter().asList()); - list.add(circle.getRadius()); - criteria.put("$within", new BasicDBObject("$centerSphere", list)); + criteria.put("$within", new BasicDBObject("$centerSphere", circle.asList())); return this; } - /** - * Creates a geospatial criterion using a $within $box operation - * - * @param box - * @return - */ - public Criteria withinBox(Box box) { - Assert.notNull(box); - List> list = new ArrayList>(); - list.add(box.getLowerLeft().asList()); - list.add(box.getUpperRight().asList()); - criteria.put("$within", new BasicDBObject("$box", list)); + public Criteria within(Shape shape) { + + Assert.notNull(shape); + criteria.put("$within", new BasicDBObject(shape.getCommand(), shape.asList())); return this; } 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 d36213c74..7c1149dd2 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 @@ -19,15 +19,15 @@ import static org.springframework.data.mongodb.core.query.Criteria.*; import java.util.Collection; import java.util.Iterator; + import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.data.domain.Sort; import org.springframework.data.mapping.context.MappingContext; import org.springframework.data.mapping.context.PersistentPropertyPath; -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.geo.Shape; import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty; import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.core.query.CriteriaDefinition; @@ -211,12 +211,7 @@ class MongoQueryCreator extends AbstractQueryCreator { case WITHIN: Object parameter = parameters.next(); - if (parameter instanceof Box) { - return criteria.withinBox((Box) parameter); - } else if (parameter instanceof Circle) { - return criteria.withinCenter((Circle) parameter); - } - throw new IllegalArgumentException("Parameter has to be either Box or Circle!"); + return criteria.within((Shape) parameter); case SIMPLE_PROPERTY: return criteria.is(parameters.nextConverted()); case NEGATING_SIMPLE_PROPERTY: diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/geo/CircleUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/geo/CircleUnitTests.java new file mode 100644 index 000000000..fb99ce7c4 --- /dev/null +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/geo/CircleUnitTests.java @@ -0,0 +1,54 @@ +/* + * 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.core.geo; + +import static org.hamcrest.CoreMatchers.*; +import static org.junit.Assert.*; + +import org.junit.Test; + +/** + * Unit tests for {@link Circle}. + * + * @author Oliver Gierke + */ +public class CircleUnitTests { + + @Test(expected = IllegalArgumentException.class) + public void rejectsNullOrigin() { + new Circle(null, 0); + } + + @Test(expected = IllegalArgumentException.class) + public void rejectsNegativeRadius() { + new Circle(1, 1, -1); + } + + @Test + public void considersTwoCirclesEqualCorrectly() { + + Circle left = new Circle(1, 1, 1); + Circle right = new Circle(1, 1, 1); + + assertThat(left, is(right)); + assertThat(right, is(left)); + + right = new Circle(new Point(1,1), 1); + + assertThat(left, is(right)); + assertThat(right, is(left)); + } +} diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/geo/GeoSpatialTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/geo/GeoSpatialTests.java index f55ce95c7..e56a53ee5 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/geo/GeoSpatialTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/geo/GeoSpatialTests.java @@ -18,6 +18,8 @@ package org.springframework.data.mongodb.core.geo; import static org.hamcrest.Matchers.*; import static org.junit.Assert.*; +import static org.springframework.data.mongodb.core.query.Query.*; +import static org.springframework.data.mongodb.core.query.Criteria.*; import java.net.UnknownHostException; import java.util.Collection; @@ -27,6 +29,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.junit.After; import org.junit.Before; +import org.junit.Ignore; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; @@ -35,7 +38,6 @@ import org.springframework.data.mongodb.core.CollectionCallback; import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.Venue; import org.springframework.data.mongodb.core.index.GeospatialIndex; -import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.core.query.NearQuery; import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.mongodb.monitor.ServerInfo; @@ -111,70 +113,86 @@ public class GeoSpatialTests { @Test public void geoNear() { - NearQuery geoNear = NearQuery.near(-73,40, Metrics.KILOMETERS).num(10).maxDistance(150); + NearQuery geoNear = NearQuery.near(-73, 40, Metrics.KILOMETERS).num(10).maxDistance(150); GeoResults geoNearResult = template.geoNear(geoNear, Venue.class); - + assertThat(geoNearResult.getContent().size(), is(not(0))); } @Test public void withinCenter() { - Circle circle = new Circle(-73.99171, 40.738868, 0.01); - List venues = template.find(new Query(Criteria.where("location").withinCenter(circle)), Venue.class); - assertThat(venues.size(), equalTo(7)); + List venues = template.find(query(where("location").within(circle)), Venue.class); + assertThat(venues.size(), is(7)); } @Test public void withinCenterSphere() { Circle circle = new Circle(-73.99171, 40.738868, 0.003712240453784); - List venues = template.find(new Query(Criteria.where("location").withinCenterSphere(circle)), Venue.class); - assertThat(venues.size(), equalTo(11)); + List venues = template.find(query(where("location").withinSphere(circle)), Venue.class); + assertThat(venues.size(), is(11)); } @Test public void withinBox() { + Box box = new Box(new Point(-73.99756, 40.73083), new Point(-73.988135, 40.741404)); - // Box box = newBox.lowerLeft(x,y).upperRight(x,y); - List venues = template.find(new Query(Criteria.where("location").withinBox(box)), Venue.class); - assertThat(venues.size(), equalTo(4)); + List venues = template.find(query(where("location").within(box)), Venue.class); + assertThat(venues.size(), is(4)); + } + + @Test + @Ignore + public void withinPolygon() { + + Point first = new Point(-73.99756, 40.73083); + Point second = new Point(-73.99756, 40.741404); + Point third = new Point(-73.988135, 40.741404); + Point fourth = new Point(-73.988135, 40.73083); + + Polygon polygon = new Polygon(first, second, third, fourth); + + List venues = template.find(query(where("location").within(polygon)), Venue.class); + assertThat(venues.size(), is(4)); } @Test public void nearPoint() { Point point = new Point(-73.99171, 40.738868); - List venues = template - .find(new Query(Criteria.where("location").near(point).maxDistance(0.01)), Venue.class); - assertThat(venues.size(), equalTo(7)); + List venues = template.find(query(where("location").near(point).maxDistance(0.01)), Venue.class); + assertThat(venues.size(), is(7)); } @Test public void nearSphere() { Point point = new Point(-73.99171, 40.738868); - List venues = template.find( - new Query(Criteria.where("location").nearSphere(point).maxDistance(0.003712240453784)), Venue.class); - assertThat(venues.size(), equalTo(11)); + Query query = query(where("location").nearSphere(point).maxDistance(0.003712240453784)); + List venues = template.find(query, Venue.class); + assertThat(venues.size(), is(11)); } @Test public void searchAllData() { - assertThat(template, notNullValue()); - Venue foundVenue = template.findOne(new Query(Criteria.where("name").is("Penn Station")), Venue.class); - assertThat(foundVenue, notNullValue()); + + Venue foundVenue = template.findOne(query(where("name").is("Penn Station")), Venue.class); + assertThat(foundVenue, is(notNullValue())); + List venues = template.findAll(Venue.class); - assertThat(venues.size(), equalTo(12)); + assertThat(venues.size(), is(12)); + Collection names = (Collection) parser.parseExpression("![name]").getValue(venues); - assertThat(names.size(), equalTo(12)); - org.springframework.util.Assert.notEmpty(names); + assertThat(names.size(), is(12)); } public void indexCreated() { + List indexInfo = getIndexInfo(Venue.class); LOGGER.debug(indexInfo); - assertThat(indexInfo.size(), equalTo(2)); - assertThat(indexInfo.get(1).get("name").toString(), equalTo("location_2d")); - assertThat(indexInfo.get(1).get("ns").toString(), equalTo("database.newyork")); + + assertThat(indexInfo.size(), is(2)); + assertThat(indexInfo.get(1).get("name").toString(), is("location_2d")); + assertThat(indexInfo.get(1).get("ns").toString(), is("database.newyork")); } // TODO move to MongoAdmin diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/geo/PolygonUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/geo/PolygonUnitTests.java new file mode 100644 index 000000000..01ca9985a --- /dev/null +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/geo/PolygonUnitTests.java @@ -0,0 +1,54 @@ +/* + * Copyright 2010-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.core.geo; + +import static org.hamcrest.CoreMatchers.*; +import static org.junit.Assert.*; + +import org.junit.Test; + +/** + * Unit tests for {@link Polygon}. + * + * @author Oliver Gierke + */ +public class PolygonUnitTests { + + Point first = new Point(1, 1); + Point second = new Point(2, 2); + Point third = new Point(3, 3); + + @Test(expected = IllegalArgumentException.class) + public void rejectsNullPoints() { + new Polygon(null, null, null); + } + + @Test + public void createsSimplePolygon() { + Polygon polygon = new Polygon(third, second, first); + assertThat(polygon, is(notNullValue())); + } + + @Test + public void isEqualForSamePoints() { + + Polygon left = new Polygon(third, second, first); + Polygon right = new Polygon(third, second, first); + + assertThat(left, is(right)); + assertThat(right, is(left)); + } +} diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/AbstractPersonRepositoryIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/AbstractPersonRepositoryIntegrationTests.java index 468b30ba8..2c11ffa40 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/AbstractPersonRepositoryIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/AbstractPersonRepositoryIntegrationTests.java @@ -24,6 +24,7 @@ import java.util.HashSet; import java.util.List; import org.junit.Before; +import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; @@ -38,6 +39,7 @@ import org.springframework.data.mongodb.core.geo.Distance; import org.springframework.data.mongodb.core.geo.GeoResults; import org.springframework.data.mongodb.core.geo.Metrics; import org.springframework.data.mongodb.core.geo.Point; +import org.springframework.data.mongodb.core.geo.Polygon; import org.springframework.data.mongodb.repository.Person.Sex; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @@ -53,7 +55,7 @@ public abstract class AbstractPersonRepositoryIntegrationTests { protected PersonRepository repository; Person dave, oliver, carter, boyd, stefan, leroi, alicia; QPerson person; - + List all; @Before @@ -67,7 +69,7 @@ public abstract class AbstractPersonRepositoryIntegrationTests { boyd = new Person("Boyd", "Tinsley", 45); stefan = new Person("Stefan", "Lessard", 34); leroi = new Person("Leroi", "Moore", 41); - + alicia = new Person("Alicia", "Keys", 30, Sex.FEMALE); person = new QPerson("person"); @@ -147,17 +149,19 @@ public abstract class AbstractPersonRepositoryIntegrationTests { @Test public void executesPagedFinderCorrectly() throws Exception { - Page page = repository.findByLastnameLike("*a*", new PageRequest(0, 2, Direction.ASC, "lastname", "firstname")); + Page page = repository.findByLastnameLike("*a*", new PageRequest(0, 2, Direction.ASC, "lastname", + "firstname")); assertThat(page.isFirstPage(), is(true)); assertThat(page.isLastPage(), is(false)); assertThat(page.getNumberOfElements(), is(2)); assertThat(page, hasItems(carter, stefan)); } - + @Test public void executesPagedFinderWithAnnotatedQueryCorrectly() throws Exception { - Page page = repository.findByLastnameLikeWithPageable(".*a.*", new PageRequest(0, 2, Direction.ASC, "lastname", "firstname")); + Page page = repository.findByLastnameLikeWithPageable(".*a.*", new PageRequest(0, 2, Direction.ASC, + "lastname", "firstname")); assertThat(page.isFirstPage(), is(true)); assertThat(page.isLastPage(), is(false)); assertThat(page.getNumberOfElements(), is(2)); @@ -261,6 +265,24 @@ public abstract class AbstractPersonRepositoryIntegrationTests { assertThat(result, hasItem(dave)); } + @Test + @Ignore + public void findsPeopleByLocationWithinPolygon() { + + Point point = new Point(-73.99171, 40.738868); + dave.setLocation(point); + repository.save(dave); + + Point first = new Point(-78.99171, 35.738868); + Point second = new Point(-78.99171, 45.738868); + Point third = new Point(-68.99171, 45.738868); + Point fourth = new Point(-68.99171, 35.738868); + + List result = repository.findByLocationWithin(new Polygon(first, second, third, fourth)); + assertThat(result.size(), is(1)); + assertThat(result, hasItem(dave)); + } + @Test public void findsPagedPeopleByPredicate() throws Exception { @@ -277,7 +299,7 @@ public abstract class AbstractPersonRepositoryIntegrationTests { */ @Test public void findsPeopleBySexCorrectly() { - + List females = repository.findBySex(Sex.FEMALE); assertThat(females.size(), is(1)); assertThat(females.get(0), is(alicia)); @@ -300,12 +322,12 @@ public abstract class AbstractPersonRepositoryIntegrationTests { @Test(expected = DuplicateKeyException.class) public void rejectsDuplicateEmailAddressOnSave() { - + assertThat(dave.getEmail(), is("dave@dmband.com")); - + Person daveSyer = new Person("Dave", "Syer"); assertThat(daveSyer.getEmail(), is("dave@dmband.com")); - + repository.save(daveSyer); } @@ -319,7 +341,7 @@ public abstract class AbstractPersonRepositoryIntegrationTests { assertThat(result.get(0), is(dave)); assertThat(result.get(1), is(oliver)); } - + /** * @see DATADOC-236 */ @@ -333,16 +355,16 @@ public abstract class AbstractPersonRepositoryIntegrationTests { assertThat(result.get(3), is(dave)); assertThat(result.get(4), is(leroi)); } - - + @Test public void executesGeoNearQueryForResultsCorrectly() { - + Point point = new Point(-73.99171, 40.738868); dave.setLocation(point); repository.save(dave); - - GeoResults results = repository.findByLocationNear(new Point(-73.99, 40.73), new Distance(2000, Metrics.KILOMETERS)); + + GeoResults results = repository.findByLocationNear(new Point(-73.99, 40.73), new Distance(2000, + Metrics.KILOMETERS)); assertThat(results.getContent().isEmpty(), is(false)); } } \ No newline at end of file diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonRepository.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonRepository.java index 0edfd0882..8fcd211a2 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonRepository.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonRepository.java @@ -26,8 +26,7 @@ import org.springframework.data.mongodb.core.geo.Circle; import org.springframework.data.mongodb.core.geo.Distance; import org.springframework.data.mongodb.core.geo.GeoResults; import org.springframework.data.mongodb.core.geo.Point; -import org.springframework.data.mongodb.repository.MongoRepository; -import org.springframework.data.mongodb.repository.Query; +import org.springframework.data.mongodb.core.geo.Polygon; import org.springframework.data.mongodb.repository.Person.Sex; import org.springframework.data.querydsl.QueryDslPredicateExecutor; @@ -139,6 +138,8 @@ public interface PersonRepository extends MongoRepository, Query List findByLocationWithin(Box box); + List findByLocationWithin(Polygon polygon); + List findBySex(Sex sex); List findByNamedQuery(String firstname);