DATAMONGO-858 - Revised rendering of geo spatial structures.

Switched back to the old style of rendering (as in 1.4.x) of DBObjects when they are used as values in persistent domain objects, adjusted the GeoConverters accordingly. In order to render geo structures correctly when they are used within a query we now wrap them in a GeoCommand that triggers a different Shape rendering.

We now render the metric that was used in the Distance definition of the radius of a Circle or Sphere.
This commit is contained in:
Thomas Darimont
2014-03-20 21:13:29 +01:00
committed by Oliver Gierke
parent ed55d48a53
commit d7b03915a7
8 changed files with 639 additions and 419 deletions

View File

@@ -25,17 +25,24 @@ import org.springframework.data.convert.ReadingConverter;
import org.springframework.data.convert.WritingConverter;
import org.springframework.data.geo.Box;
import org.springframework.data.geo.Circle;
import org.springframework.data.geo.Distance;
import org.springframework.data.geo.Metrics;
import org.springframework.data.geo.Point;
import org.springframework.data.geo.Polygon;
import org.springframework.data.geo.Shape;
import org.springframework.data.mongodb.core.geo.Sphere;
import org.springframework.data.mongodb.core.query.GeoCommand;
import org.springframework.util.Assert;
import com.mongodb.BasicDBList;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
/**
* Wrapper class to contain useful geo structure converters for the usage with Mongo.
*
* @author Thomas Darimont
* @author Oliver Gierke
* @since 1.5
*/
abstract class GeoConverters {
@@ -45,318 +52,6 @@ abstract class GeoConverters {
*/
private GeoConverters() {}
/**
* Converts a {@link List} of {@link Double}s into a {@link Point}.
*
* @author Thomas Darimont
* @since 1.5
*/
@ReadingConverter
public static enum ListToPointConverter implements Converter<List<Double>, Point> {
INSTANCE;
@SuppressWarnings("deprecation")
public Point convert(List<Double> source) {
Assert.notEmpty(source, "Source must not be empty!");
Assert.isTrue(source.size() == 2, "Source must contain 2 elements");
return source == null ? null : new org.springframework.data.mongodb.core.geo.Point(source.get(0), source.get(1));
}
}
/**
* Converts a {@link Point} into a {@link List} of {@link Double}s.
*
* @author Thomas Darimont
* @since 1.5
*/
public static enum PointToListConverter implements Converter<Point, List<Double>> {
INSTANCE;
@Override
public List<Double> convert(Point source) {
return source == null ? null : Arrays.asList(source.getX(), source.getY());
}
}
/**
* Converts a {@link Box} into a {@link BasicDBList}.
*
* @author Thomas Darimont
* @since 1.5
*/
@WritingConverter
public static enum BoxToDbObjectConverter implements Converter<Box, BasicDBList> {
INSTANCE;
@Override
public BasicDBList convert(Box source) {
if (source == null) {
return null;
}
BasicDBList result = new BasicDBList();
result.add(toList(source.getFirst()));
result.add(toList(source.getSecond()));
return result;
}
}
/**
* Converts a {@link BasicDBList} into a {@link org.springframework.data.mongodb.core.geo.Box}.
*
* @author Thomas Darimont
* @since 1.5
*/
@ReadingConverter
public static enum DbObjectToBoxConverter implements Converter<BasicDBList, Box> {
INSTANCE;
@SuppressWarnings("deprecation")
@Override
public Box convert(BasicDBList source) {
if (source == null) {
return null;
}
return new org.springframework.data.mongodb.core.geo.Box(toPoint(source.get(0)), toPoint(source.get(1)));
}
}
/**
* Converts a {@link Circle} into a {@link BasicDBList}.
*
* @author Thomas Darimont
* @since 1.5
*/
public static enum CircleToDbObjectConverter implements Converter<Circle, BasicDBList> {
INSTANCE;
@Override
public BasicDBList convert(Circle source) {
if (source == null) {
return null;
}
BasicDBList result = new BasicDBList();
result.add(toList(source.getCenter()));
result.add(source.getRadius().getNormalizedValue());
return result;
}
}
/**
* Converts a {@link BasicDBList} into a {@link org.springframework.data.mongodb.core.geo.Circle}.
*
* @author Thomas Darimont
* @since 1.5
*/
@ReadingConverter
public static enum DbObjectToCircleConverter implements Converter<BasicDBList, Circle> {
INSTANCE;
@Override
public Circle convert(BasicDBList source) {
if (source == null) {
return null;
}
return new Circle(toPoint(source.get(0)), (Double) source.get(1));
}
}
/**
* Converts a {@link Circle} into a {@link BasicDBList}.
*
* @author Thomas Darimont
* @since 1.5
*/
@SuppressWarnings("deprecation")
public static enum LegacyCircleToDbObjectConverter implements
Converter<org.springframework.data.mongodb.core.geo.Circle, BasicDBList> {
INSTANCE;
@Override
public BasicDBList convert(org.springframework.data.mongodb.core.geo.Circle source) {
if (source == null) {
return null;
}
BasicDBList result = new BasicDBList();
result.add(toList(source.getCenter()));
result.add(source.getRadius());
return result;
}
}
/**
* Converts a {@link BasicDBList} into a {@link org.springframework.data.mongodb.core.geo.Circle}.
*
* @author Thomas Darimont
* @since 1.5
*/
@ReadingConverter
@SuppressWarnings("deprecation")
public static enum DbObjectToLegacyCircleConverter implements
Converter<BasicDBList, org.springframework.data.mongodb.core.geo.Circle> {
INSTANCE;
@Override
public org.springframework.data.mongodb.core.geo.Circle convert(BasicDBList source) {
if (source == null) {
return null;
}
return new org.springframework.data.mongodb.core.geo.Circle(toPoint(source.get(0)), (Double) source.get(1));
}
}
/**
* Converts a {@link Sphere} into a {@link BasicDBList}.
*
* @author Thomas Darimont
* @since 1.5
*/
public static enum SphereToDbObjectConverter implements Converter<Sphere, BasicDBList> {
INSTANCE;
@Override
public BasicDBList convert(Sphere source) {
if (source == null) {
return null;
}
BasicDBList result = new BasicDBList();
result.add(toList(source.getCenter()));
result.add(source.getRadius().getNormalizedValue());
return result;
}
}
/**
* Converts a {@link BasicDBList} into a {@link Sphere}.
*
* @author Thomas Darimont
* @since 1.5
*/
@ReadingConverter
public static enum DbObjectToSphereConverter implements Converter<BasicDBList, Sphere> {
INSTANCE;
@Override
public Sphere convert(BasicDBList source) {
if (source == null) {
return null;
}
return new Sphere(toPoint(source.get(0)), (Double) source.get(1));
}
}
/**
* Converts a {@link Polygon} into a {@link BasicDBList}.
*
* @author Thomas Darimont
* @since 1.5
*/
public static enum PolygonToDbObjectConverter implements Converter<Polygon, BasicDBList> {
INSTANCE;
@Override
public BasicDBList convert(Polygon source) {
if (source == null) {
return null;
}
List<Point> points = source.getPoints();
List<List<Double>> pointTuples = new ArrayList<List<Double>>(points.size());
for (Point point : points) {
pointTuples.add(toList(point));
}
BasicDBList result = new BasicDBList();
result.addAll(pointTuples);
return result;
}
}
/**
* Converts a {@link BasicDBList} into a {@link org.springframework.data.mongodb.core.geo.Polygon}.
*
* @author Thomas Darimont
* @since 1.5
*/
@ReadingConverter
public static enum DbObjectToPolygonConverter implements Converter<BasicDBList, Polygon> {
INSTANCE;
@SuppressWarnings("deprecation")
@Override
public Polygon convert(BasicDBList source) {
if (source == null) {
return null;
}
List<Point> points = new ArrayList<Point>(source.size());
for (Object element : source) {
Assert.notNull(element, "point elements of polygon must not be null!");
points.add(toPoint(element));
}
return new org.springframework.data.mongodb.core.geo.Polygon(points);
}
}
/**
* Converts the given item into a {@link Point}.
*
* @param item
* @return
*/
@SuppressWarnings("unchecked")
private static Point toPoint(Object item) {
Assert.isInstanceOf(List.class, item);
return ListToPointConverter.INSTANCE.convert((List<Double>) item);
}
/**
* Converts the given {@link Point} into a {@link List} representation with X,Y coordinates as {@link Double}s.
*
* @param point
* @return
*/
private static List<Double> toList(Point point) {
return PointToListConverter.INSTANCE.convert(point);
}
/**
* Returns the geo converters to be registered.
*
@@ -375,8 +70,451 @@ abstract class GeoConverters {
, DbObjectToCircleConverter.INSTANCE //
, DbObjectToLegacyCircleConverter.INSTANCE //
, DbObjectToSphereConverter.INSTANCE //
, ListToPointConverter.INSTANCE //
, PointToListConverter.INSTANCE //
);
, DbObjectToPointConverter.INSTANCE //
, PointToDbObjectConverter.INSTANCE //
, GeoCommandToDbObjectConverter.INSTANCE);
}
/**
* Converts a {@link List} of {@link Double}s into a {@link Point}.
*
* @author Thomas Darimont
* @since 1.5
*/
@ReadingConverter
public static enum DbObjectToPointConverter implements Converter<DBObject, Point> {
INSTANCE;
/*
* (non-Javadoc)
* @see org.springframework.core.convert.converter.Converter#convert(java.lang.Object)
*/
@Override
@SuppressWarnings("deprecation")
public Point convert(DBObject source) {
Assert.isTrue(source.keySet().size() == 2, "Source must contain 2 elements");
return source == null ? null : new org.springframework.data.mongodb.core.geo.Point((Double) source.get("x"),
(Double) source.get("y"));
}
}
/**
* Converts a {@link Point} into a {@link List} of {@link Double}s.
*
* @author Thomas Darimont
* @since 1.5
*/
public static enum PointToDbObjectConverter implements Converter<Point, DBObject> {
INSTANCE;
/*
* (non-Javadoc)
* @see org.springframework.core.convert.converter.Converter#convert(java.lang.Object)
*/
@Override
public DBObject convert(Point source) {
return source == null ? null : new BasicDBObject("x", source.getX()).append("y", source.getY());
}
}
/**
* Converts a {@link Box} into a {@link BasicDBList}.
*
* @author Thomas Darimont
* @since 1.5
*/
@WritingConverter
public static enum BoxToDbObjectConverter implements Converter<Box, DBObject> {
INSTANCE;
/*
* (non-Javadoc)
* @see org.springframework.core.convert.converter.Converter#convert(java.lang.Object)
*/
@Override
public DBObject convert(Box source) {
if (source == null) {
return null;
}
BasicDBObject result = new BasicDBObject();
result.put("first", PointToDbObjectConverter.INSTANCE.convert(source.getFirst()));
result.put("second", PointToDbObjectConverter.INSTANCE.convert(source.getSecond()));
return result;
}
}
/**
* Converts a {@link BasicDBList} into a {@link org.springframework.data.mongodb.core.geo.Box}.
*
* @author Thomas Darimont
* @since 1.5
*/
@ReadingConverter
public static enum DbObjectToBoxConverter implements Converter<DBObject, Box> {
INSTANCE;
/*
* (non-Javadoc)
* @see org.springframework.core.convert.converter.Converter#convert(java.lang.Object)
*/
@Override
@SuppressWarnings("deprecation")
public Box convert(DBObject source) {
if (source == null) {
return null;
}
Point first = DbObjectToPointConverter.INSTANCE.convert((DBObject) source.get("first"));
Point second = DbObjectToPointConverter.INSTANCE.convert((DBObject) source.get("second"));
return new org.springframework.data.mongodb.core.geo.Box(first, second);
}
}
/**
* Converts a {@link Circle} into a {@link BasicDBList}.
*
* @author Thomas Darimont
* @since 1.5
*/
public static enum CircleToDbObjectConverter implements Converter<Circle, DBObject> {
INSTANCE;
/*
* (non-Javadoc)
* @see org.springframework.core.convert.converter.Converter#convert(java.lang.Object)
*/
@Override
public DBObject convert(Circle source) {
if (source == null) {
return null;
}
DBObject result = new BasicDBObject();
result.put("center", PointToDbObjectConverter.INSTANCE.convert(source.getCenter()));
result.put("radius", source.getRadius().getNormalizedValue());
result.put("metric", source.getRadius().getMetric().toString());
return result;
}
}
/**
* Converts a {@link DBObject} into a {@link org.springframework.data.mongodb.core.geo.Circle}.
*
* @author Thomas Darimont
* @since 1.5
*/
@ReadingConverter
public static enum DbObjectToCircleConverter implements Converter<DBObject, Circle> {
INSTANCE;
/*
* (non-Javadoc)
* @see org.springframework.core.convert.converter.Converter#convert(java.lang.Object)
*/
@Override
public Circle convert(DBObject source) {
if (source == null) {
return null;
}
DBObject center = (DBObject) source.get("center");
Double radius = (Double) source.get("radius");
Distance distance = new Distance(radius);
if (source.containsField("metric")) {
String metricString = (String) source.get("metric");
Assert.notNull(metricString, "Metric must not be null!");
distance = distance.in(Metrics.valueOf(metricString));
}
Assert.notNull(center, "Center must not be null!");
Assert.notNull(radius, "Radius must not be null!");
return new Circle(DbObjectToPointConverter.INSTANCE.convert(center), distance);
}
}
/**
* Converts a {@link Circle} into a {@link BasicDBList}.
*
* @author Thomas Darimont
* @since 1.5
*/
@SuppressWarnings("deprecation")
public static enum LegacyCircleToDbObjectConverter implements
Converter<org.springframework.data.mongodb.core.geo.Circle, DBObject> {
INSTANCE;
/*
* (non-Javadoc)
* @see org.springframework.core.convert.converter.Converter#convert(java.lang.Object)
*/
@Override
public DBObject convert(org.springframework.data.mongodb.core.geo.Circle source) {
if (source == null) {
return null;
}
DBObject result = new BasicDBObject();
result.put("center", PointToDbObjectConverter.INSTANCE.convert(source.getCenter()));
result.put("radius", source.getRadius());
return result;
}
}
/**
* Converts a {@link BasicDBList} into a {@link org.springframework.data.mongodb.core.geo.Circle}.
*
* @author Thomas Darimont
* @since 1.5
*/
@ReadingConverter
@SuppressWarnings("deprecation")
public static enum DbObjectToLegacyCircleConverter implements
Converter<DBObject, org.springframework.data.mongodb.core.geo.Circle> {
INSTANCE;
/*
* (non-Javadoc)
* @see org.springframework.core.convert.converter.Converter#convert(java.lang.Object)
*/
@Override
public org.springframework.data.mongodb.core.geo.Circle convert(DBObject source) {
if (source == null) {
return null;
}
DBObject centerSource = (DBObject) source.get("center");
Double radius = (Double) source.get("radius");
Assert.notNull(centerSource, "Center must not be null!");
Assert.notNull(radius, "Radius must not be null!");
Point center = DbObjectToPointConverter.INSTANCE.convert(centerSource);
return new org.springframework.data.mongodb.core.geo.Circle(center, radius);
}
}
/**
* Converts a {@link Sphere} into a {@link BasicDBList}.
*
* @author Thomas Darimont
* @since 1.5
*/
public static enum SphereToDbObjectConverter implements Converter<Sphere, DBObject> {
INSTANCE;
/*
* (non-Javadoc)
* @see org.springframework.core.convert.converter.Converter#convert(java.lang.Object)
*/
@Override
public DBObject convert(Sphere source) {
if (source == null) {
return null;
}
DBObject result = new BasicDBObject();
result.put("center", PointToDbObjectConverter.INSTANCE.convert(source.getCenter()));
result.put("radius", source.getRadius().getNormalizedValue());
result.put("metric", source.getRadius().getMetric().toString());
return result;
}
}
/**
* Converts a {@link BasicDBList} into a {@link Sphere}.
*
* @author Thomas Darimont
* @since 1.5
*/
@ReadingConverter
public static enum DbObjectToSphereConverter implements Converter<DBObject, Sphere> {
INSTANCE;
/*
* (non-Javadoc)
* @see org.springframework.core.convert.converter.Converter#convert(java.lang.Object)
*/
@Override
public Sphere convert(DBObject source) {
if (source == null) {
return null;
}
DBObject center = (DBObject) source.get("center");
Double radius = (Double) source.get("radius");
Distance distance = new Distance(radius);
if (source.containsField("metric")) {
String metricString = (String) source.get("metric");
Assert.notNull(metricString, "Metric must not be null!");
distance = distance.in(Metrics.valueOf(metricString));
}
Assert.notNull(center, "Center must not be null!");
Assert.notNull(radius, "Radius must not be null!");
return new Sphere(DbObjectToPointConverter.INSTANCE.convert(center), distance);
}
}
/**
* Converts a {@link Polygon} into a {@link BasicDBList}.
*
* @author Thomas Darimont
* @since 1.5
*/
public static enum PolygonToDbObjectConverter implements Converter<Polygon, DBObject> {
INSTANCE;
/*
* (non-Javadoc)
* @see org.springframework.core.convert.converter.Converter#convert(java.lang.Object)
*/
@Override
public DBObject convert(Polygon source) {
if (source == null) {
return null;
}
List<Point> points = source.getPoints();
List<DBObject> pointTuples = new ArrayList<DBObject>(points.size());
for (Point point : points) {
pointTuples.add(PointToDbObjectConverter.INSTANCE.convert(point));
}
DBObject result = new BasicDBObject();
result.put("points", pointTuples);
return result;
}
}
/**
* Converts a {@link BasicDBList} into a {@link org.springframework.data.mongodb.core.geo.Polygon}.
*
* @author Thomas Darimont
* @since 1.5
*/
@ReadingConverter
public static enum DbObjectToPolygonConverter implements Converter<DBObject, Polygon> {
INSTANCE;
/*
* (non-Javadoc)
* @see org.springframework.core.convert.converter.Converter#convert(java.lang.Object)
*/
@Override
@SuppressWarnings({ "deprecation", "unchecked" })
public Polygon convert(DBObject source) {
if (source == null) {
return null;
}
List<DBObject> points = (List<DBObject>) source.get("points");
List<Point> newPoints = new ArrayList<Point>(points.size());
for (DBObject element : points) {
Assert.notNull(element, "Point elements of polygon must not be null!");
newPoints.add(DbObjectToPointConverter.INSTANCE.convert(element));
}
return new org.springframework.data.mongodb.core.geo.Polygon(newPoints);
}
}
/**
* Converts a {@link Sphere} into a {@link BasicDBList}.
*
* @author Thomas Darimont
* @since 1.5
*/
public static enum GeoCommandToDbObjectConverter implements Converter<GeoCommand, DBObject> {
INSTANCE;
/*
* (non-Javadoc)
* @see org.springframework.core.convert.converter.Converter#convert(java.lang.Object)
*/
@Override
@SuppressWarnings("deprecation")
public DBObject convert(GeoCommand source) {
if (source == null) {
return null;
}
BasicDBList argument = new BasicDBList();
Shape shape = source.getShape();
if (shape instanceof Box) {
argument.add(toList(((Box) shape).getFirst()));
argument.add(toList(((Box) shape).getSecond()));
} else if (shape instanceof Circle) {
argument.add(toList(((Circle) shape).getCenter()));
argument.add(((Circle) shape).getRadius().getNormalizedValue());
} else if (shape instanceof org.springframework.data.mongodb.core.geo.Circle) {
argument.add(toList(((org.springframework.data.mongodb.core.geo.Circle) shape).getCenter()));
argument.add(((org.springframework.data.mongodb.core.geo.Circle) shape).getRadius());
} else if (shape instanceof Polygon) {
for (Point point : ((Polygon) shape).getPoints()) {
argument.add(toList(point));
}
} else if (shape instanceof Sphere) {
argument.add(toList(((Sphere) shape).getCenter()));
argument.add(((Sphere) shape).getRadius().getNormalizedValue());
}
return new BasicDBObject(source.getCommand(), argument);
}
}
static List<Double> toList(Point point) {
return Arrays.asList(point.getX(), point.getY());
}
}

View File

@@ -25,10 +25,8 @@ import java.util.List;
import java.util.regex.Pattern;
import org.bson.BSON;
import org.springframework.data.geo.Box;
import org.springframework.data.geo.Circle;
import org.springframework.data.geo.Point;
import org.springframework.data.geo.Polygon;
import org.springframework.data.geo.Shape;
import org.springframework.data.mongodb.InvalidMongoDbApiUsageException;
import org.springframework.data.mongodb.core.geo.Sphere;
@@ -386,7 +384,7 @@ public class Criteria implements CriteriaDefinition {
*/
public Criteria withinSphere(Circle circle) {
Assert.notNull(circle);
criteria.put("$within", wrapInCommand(new Sphere(circle)));
criteria.put("$within", new GeoCommand(new Sphere(circle)));
return this;
}
@@ -400,7 +398,7 @@ public class Criteria implements CriteriaDefinition {
@Deprecated
public Criteria withinSphere(org.springframework.data.mongodb.core.geo.Circle circle) {
Assert.notNull(circle);
criteria.put("$within", wrapInCommand(new Sphere(circle)));
criteria.put("$within", new GeoCommand(new Sphere(circle)));
return this;
}
@@ -414,7 +412,7 @@ public class Criteria implements CriteriaDefinition {
public Criteria within(Shape shape) {
Assert.notNull(shape);
criteria.put("$within", wrapInCommand(shape));
criteria.put("$within", new GeoCommand(shape));
return this;
}
@@ -660,43 +658,6 @@ public class Criteria implements CriteriaDefinition {
return ObjectUtils.nullSafeEquals(left, right);
}
/**
* Wraps the given {@link Shape} in an appropriate MongoDB command.
*
* @param shape must not be {@literal null}.
* @return
*/
private DBObject wrapInCommand(Shape shape) {
Assert.notNull(shape, "Shape must not be null!");
return new BasicDBObject(getCommand(shape), shape);
}
/**
* Returns the MongoDB command for the given {@link Shape}.
*
* @param shape must not be {@literal null}.
* @return
*/
@SuppressWarnings("deprecation")
private String getCommand(Shape shape) {
Assert.notNull(shape, "Shape must not be null!");
if (shape instanceof Box) {
return org.springframework.data.mongodb.core.geo.Box.COMMAND;
} else if (shape instanceof Circle || shape instanceof org.springframework.data.mongodb.core.geo.Circle) {
return org.springframework.data.mongodb.core.geo.Circle.COMMAND;
} else if (shape instanceof Polygon) {
return org.springframework.data.mongodb.core.geo.Polygon.COMMAND;
} else if (shape instanceof Sphere) {
return org.springframework.data.mongodb.core.geo.Sphere.COMMAND;
}
throw new IllegalArgumentException("Unknown shape: " + shape);
}
/*
* (non-Javadoc)
* @see java.lang.Object#hashCode()

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.mongodb.core.convert;
package org.springframework.data.mongodb.core.query;
import org.springframework.data.geo.Box;
import org.springframework.data.geo.Circle;
@@ -22,27 +22,42 @@ import org.springframework.data.geo.Shape;
import org.springframework.data.mongodb.core.geo.Sphere;
import org.springframework.util.Assert;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
/**
* Wrapper around a {@link Shape} to allow appropriate query rendering.
*
* @author Thomas Darimont
* @since 1.5
*/
public enum GeoCommandUtils {
public class GeoCommand {
INSTANCE;
private final Shape shape;
private final String command;
/**
* Wraps the given {@link Shape} in an appropriate MongoDB command.
* Creates a new {@link GeoCommand}.
*
* @param shape must not be {@literal null}.
* @return
*/
public DBObject wrapInCommand(Shape shape) {
public GeoCommand(Shape shape) {
Assert.notNull(shape, "Shape must not be null!");
return new BasicDBObject(getCommand(shape), shape);
this.shape = shape;
this.command = getCommand(shape);
}
/**
* @return the shape
*/
public Shape getShape() {
return shape;
}
/**
* @return the command
*/
public String getCommand() {
return command;
}
/**
@@ -51,6 +66,7 @@ public enum GeoCommandUtils {
* @param shape must not be {@literal null}.
* @return
*/
@SuppressWarnings("deprecation")
private String getCommand(Shape shape) {
Assert.notNull(shape, "Shape must not be null!");

View File

@@ -18,11 +18,13 @@ package org.springframework.data.mongodb.core.convert;
import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;
import java.util.List;
import java.util.Arrays;
import org.junit.Test;
import org.springframework.data.geo.Box;
import org.springframework.data.geo.Circle;
import org.springframework.data.geo.Distance;
import org.springframework.data.geo.Metrics;
import org.springframework.data.geo.Point;
import org.springframework.data.geo.Polygon;
import org.springframework.data.mongodb.core.convert.GeoConverters.BoxToDbObjectConverter;
@@ -30,21 +32,24 @@ import org.springframework.data.mongodb.core.convert.GeoConverters.CircleToDbObj
import org.springframework.data.mongodb.core.convert.GeoConverters.DbObjectToBoxConverter;
import org.springframework.data.mongodb.core.convert.GeoConverters.DbObjectToCircleConverter;
import org.springframework.data.mongodb.core.convert.GeoConverters.DbObjectToLegacyCircleConverter;
import org.springframework.data.mongodb.core.convert.GeoConverters.DbObjectToPointConverter;
import org.springframework.data.mongodb.core.convert.GeoConverters.DbObjectToPolygonConverter;
import org.springframework.data.mongodb.core.convert.GeoConverters.DbObjectToSphereConverter;
import org.springframework.data.mongodb.core.convert.GeoConverters.GeoCommandToDbObjectConverter;
import org.springframework.data.mongodb.core.convert.GeoConverters.LegacyCircleToDbObjectConverter;
import org.springframework.data.mongodb.core.convert.GeoConverters.ListToPointConverter;
import org.springframework.data.mongodb.core.convert.GeoConverters.PointToListConverter;
import org.springframework.data.mongodb.core.convert.GeoConverters.PointToDbObjectConverter;
import org.springframework.data.mongodb.core.convert.GeoConverters.PolygonToDbObjectConverter;
import org.springframework.data.mongodb.core.convert.GeoConverters.SphereToDbObjectConverter;
import org.springframework.data.mongodb.core.geo.Sphere;
import org.springframework.data.mongodb.core.query.GeoCommand;
import com.mongodb.BasicDBList;
import com.mongodb.DBObject;
/**
* Unit tests for {@link GeoConverters}.
*
* @author Thomas Darimont
* @author Oliver Gierke
* @since 1.5
*/
@SuppressWarnings("deprecation")
@@ -58,7 +63,7 @@ public class GeoConvertersUnitTests {
Box box = new Box(new Point(1, 2), new Point(3, 4));
BasicDBList dbo = BoxToDbObjectConverter.INSTANCE.convert(box);
DBObject dbo = BoxToDbObjectConverter.INSTANCE.convert(box);
Box result = DbObjectToBoxConverter.INSTANCE.convert(dbo);
assertThat(result, is(box));
@@ -69,16 +74,32 @@ public class GeoConvertersUnitTests {
* @see DATAMONGO-858
*/
@Test
public void convertsCircleToDbObjectAndBackCorrectly() {
public void convertsCircleToDbObjectAndBackCorrectlyNeutralDistance() {
Circle circle = new Circle(new Point(1, 2), 3);
BasicDBList dbo = CircleToDbObjectConverter.INSTANCE.convert(circle);
DBObject dbo = CircleToDbObjectConverter.INSTANCE.convert(circle);
Circle result = DbObjectToCircleConverter.INSTANCE.convert(dbo);
assertThat(result, is(circle));
}
/**
* @see DATAMONGO-858
*/
@Test
public void convertsCircleToDbObjectAndBackCorrectlyMilesDistance() {
Distance radius = new Distance(3, Metrics.MILES);
Circle circle = new Circle(new Point(1, 2), radius);
DBObject dbo = CircleToDbObjectConverter.INSTANCE.convert(circle);
Circle result = DbObjectToCircleConverter.INSTANCE.convert(dbo);
assertThat(result, is(circle));
assertThat(result.getRadius(), is(radius));
}
/**
* @see DATAMONGO-858
*/
@@ -88,7 +109,7 @@ public class GeoConvertersUnitTests {
org.springframework.data.mongodb.core.geo.Circle circle = new org.springframework.data.mongodb.core.geo.Circle(
new Point(1, 2), 3);
BasicDBList dbo = LegacyCircleToDbObjectConverter.INSTANCE.convert(circle);
DBObject dbo = LegacyCircleToDbObjectConverter.INSTANCE.convert(circle);
org.springframework.data.mongodb.core.geo.Circle result = DbObjectToLegacyCircleConverter.INSTANCE.convert(dbo);
assertThat(result, is(circle));
@@ -102,7 +123,7 @@ public class GeoConvertersUnitTests {
Polygon polygon = new Polygon(new Point(1, 2), new Point(2, 3), new Point(3, 4), new Point(5, 6));
BasicDBList dbo = PolygonToDbObjectConverter.INSTANCE.convert(polygon);
DBObject dbo = PolygonToDbObjectConverter.INSTANCE.convert(polygon);
Polygon result = DbObjectToPolygonConverter.INSTANCE.convert(dbo);
assertThat(result, is(polygon));
@@ -113,17 +134,34 @@ public class GeoConvertersUnitTests {
* @see DATAMONGO-858
*/
@Test
public void convertsSphereToDbObjectAndBackCorrectly() {
public void convertsSphereToDbObjectAndBackCorrectlyWithNeutralDistance() {
Sphere sphere = new Sphere(new Point(1, 2), 3);
BasicDBList dbo = SphereToDbObjectConverter.INSTANCE.convert(sphere);
DBObject dbo = SphereToDbObjectConverter.INSTANCE.convert(sphere);
Sphere result = DbObjectToSphereConverter.INSTANCE.convert(dbo);
assertThat(result, is(sphere));
assertThat(result.getClass().equals(org.springframework.data.mongodb.core.geo.Sphere.class), is(true));
}
/**
* @see DATAMONGO-858
*/
@Test
public void convertsSphereToDbObjectAndBackCorrectlyWithKilometerDistance() {
Distance radius = new Distance(3, Metrics.KILOMETERS);
Sphere sphere = new Sphere(new Point(1, 2), radius);
DBObject dbo = SphereToDbObjectConverter.INSTANCE.convert(sphere);
Sphere result = DbObjectToSphereConverter.INSTANCE.convert(dbo);
assertThat(result, is(sphere));
assertThat(result.getRadius(), is(radius));
assertThat(result.getClass().equals(org.springframework.data.mongodb.core.geo.Sphere.class), is(true));
}
/**
* @see DATAMONGO-858
*/
@@ -132,10 +170,30 @@ public class GeoConvertersUnitTests {
Point point = new Point(1, 2);
List<Double> list = PointToListConverter.INSTANCE.convert(point);
Point result = ListToPointConverter.INSTANCE.convert(list);
DBObject dbo = PointToDbObjectConverter.INSTANCE.convert(point);
Point result = DbObjectToPointConverter.INSTANCE.convert(dbo);
assertThat(result, is(point));
assertThat(result.getClass().equals(org.springframework.data.mongodb.core.geo.Point.class), is(true));
}
/**
* @see DATAMONGO-858
*/
@Test
@SuppressWarnings("unchecked")
public void convertsGeoCommandToDbObjectCorrectly() {
Box box = new Box(new double[] { 1, 2 }, new double[] { 3, 4 });
GeoCommand cmd = new GeoCommand(box);
DBObject dbo = GeoCommandToDbObjectConverter.INSTANCE.convert(cmd);
assertThat(dbo, is(notNullValue()));
DBObject boxObject = (DBObject) dbo.get("$box");
assertThat(boxObject,
is((Object) Arrays.asList(GeoConverters.toList(box.getFirst()), GeoConverters.toList(box.getSecond()))));
}
}

View File

@@ -57,6 +57,8 @@ import org.springframework.data.annotation.PersistenceConstructor;
import org.springframework.data.annotation.TypeAlias;
import org.springframework.data.geo.Box;
import org.springframework.data.geo.Circle;
import org.springframework.data.geo.Distance;
import org.springframework.data.geo.Metrics;
import org.springframework.data.geo.Point;
import org.springframework.data.geo.Polygon;
import org.springframework.data.geo.Shape;
@@ -1493,7 +1495,7 @@ public class MappingMongoConverterUnitTests {
assertThat(result.enumMap.size(), is(1));
assertThat(result.enumMap.get(SampleEnum.FIRST), is("Dave"));
}
/**
* @see DATAMONGO-887
*/
@@ -1532,13 +1534,11 @@ public class MappingMongoConverterUnitTests {
DBObject entry = getAsDBObject(map, "key");
assertThat(entry.get("foo"), is((Object) "Dave"));
}
/**
* @DATAMONGO-858
*/
@Test
@SuppressWarnings({ "deprecation", "unchecked" })
public void shouldWriteEntityWithGeoBoxCorrectly() {
ClassWithGeoBox object = new ClassWithGeoBox();
@@ -1548,10 +1548,13 @@ public class MappingMongoConverterUnitTests {
converter.write(object, dbo);
assertThat(dbo, is(notNullValue()));
assertThat(dbo.get("box"), is(instanceOf(List.class)));
assertThat(dbo.get("box"), is((Object) Arrays.asList(
org.springframework.data.mongodb.core.geo.Point.asList(object.box.getFirst()),
org.springframework.data.mongodb.core.geo.Point.asList(object.box.getSecond()))));
assertThat(dbo.get("box"), is(instanceOf(DBObject.class)));
assertThat(dbo.get("box"), is((Object) new BasicDBObject().append("first", toDbObject(object.box.getFirst()))
.append("second", toDbObject(object.box.getSecond()))));
}
private static DBObject toDbObject(Point point) {
return new BasicDBObject("x", point.getX()).append("y", point.getY());
}
/**
@@ -1586,10 +1589,15 @@ public class MappingMongoConverterUnitTests {
assertThat(dbo, is(notNullValue()));
BasicDBList polygon = getAsDBList(dbo, "polygon");
assertThat(dbo.get("polygon"), is(instanceOf(DBObject.class)));
DBObject polygonDbo = (DBObject) dbo.get("polygon");
assertThat(polygon, hasSize(3));
assertThat(polygon, Matchers.<Object> hasItems(Arrays.asList(1d, 2d), Arrays.asList(3d, 4d), Arrays.asList(4d, 5d)));
@SuppressWarnings("unchecked")
List<DBObject> points = (List<DBObject>) polygonDbo.get("points");
assertThat(points, hasSize(3));
assertThat(points, Matchers.<DBObject> hasItems(toDbObject(object.polygon.getPoints().get(0)),
toDbObject(object.polygon.getPoints().get(1)), toDbObject(object.polygon.getPoints().get(2))));
}
/**
@@ -1614,19 +1622,23 @@ public class MappingMongoConverterUnitTests {
* @DATAMONGO-858
*/
@Test
@SuppressWarnings("deprecation")
public void shouldWriteEntityWithGeoCircleCorrectly() {
ClassWithGeoCircle object = new ClassWithGeoCircle();
object.circle = new Circle(new Point(1, 2), 3);
Circle circle = new Circle(new Point(1, 2), 3);
Distance radius = circle.getRadius();
object.circle = circle;
DBObject dbo = new BasicDBObject();
converter.write(object, dbo);
assertThat(dbo, is(notNullValue()));
assertThat(dbo.get("circle"), is(instanceOf(List.class)));
assertThat(dbo.get("circle"), is((Object) Arrays.asList(org.springframework.data.mongodb.core.geo.Point
.asList(object.circle.getCenter()), object.circle.getRadius().getNormalizedValue())));
assertThat(dbo.get("circle"), is(instanceOf(DBObject.class)));
assertThat(
dbo.get("circle"),
is((Object) new BasicDBObject("center", new BasicDBObject("x", circle.getCenter().getX()).append("y", circle
.getCenter().getY())).append("radius", radius.getNormalizedValue()).append("metric",
radius.getMetric().toString())));
}
/**
@@ -1655,15 +1667,17 @@ public class MappingMongoConverterUnitTests {
public void shouldWriteEntityWithGeoLegacyCircleCorrectly() {
ClassWithGeoLegacyCircle object = new ClassWithGeoLegacyCircle();
object.circle = new org.springframework.data.mongodb.core.geo.Circle(new Point(1, 2), 3);
org.springframework.data.mongodb.core.geo.Circle circle = new org.springframework.data.mongodb.core.geo.Circle(
new Point(1, 2), 3);
object.circle = circle;
DBObject dbo = new BasicDBObject();
converter.write(object, dbo);
assertThat(dbo, is(notNullValue()));
assertThat(dbo.get("circle"), is(instanceOf(List.class)));
assertThat(dbo.get("circle"), is((Object) Arrays.asList(
org.springframework.data.mongodb.core.geo.Point.asList(object.circle.getCenter()), object.circle.getRadius())));
assertThat(dbo.get("circle"), is(instanceOf(DBObject.class)));
assertThat(dbo.get("circle"), is((Object) new BasicDBObject("center", new BasicDBObject("x", circle.getCenter()
.getX()).append("y", circle.getCenter().getY())).append("radius", circle.getRadius())));
}
/**
@@ -1689,19 +1703,46 @@ public class MappingMongoConverterUnitTests {
* @DATAMONGO-858
*/
@Test
@SuppressWarnings("deprecation")
public void shouldWriteEntityWithGeoSphereCorrectly() {
ClassWithGeoSphere object = new ClassWithGeoSphere();
object.sphere = new Sphere(new Point(1, 2), 3);
Sphere sphere = new Sphere(new Point(1, 2), 3);
Distance radius = sphere.getRadius();
object.sphere = sphere;
DBObject dbo = new BasicDBObject();
converter.write(object, dbo);
assertThat(dbo, is(notNullValue()));
assertThat(dbo.get("sphere"), is(instanceOf(List.class)));
assertThat(dbo.get("sphere"), is((Object) Arrays.asList(org.springframework.data.mongodb.core.geo.Point
.asList(object.sphere.getCenter()), object.sphere.getRadius().getNormalizedValue())));
assertThat(dbo.get("sphere"), is(instanceOf(DBObject.class)));
assertThat(
dbo.get("sphere"),
is((Object) new BasicDBObject("center", new BasicDBObject("x", sphere.getCenter().getX()).append("y", sphere
.getCenter().getY())).append("radius", radius.getNormalizedValue()).append("metric",
radius.getMetric().toString())));
}
/**
* @DATAMONGO-858
*/
@Test
public void shouldWriteEntityWithGeoSphereWithMetricDistanceCorrectly() {
ClassWithGeoSphere object = new ClassWithGeoSphere();
Sphere sphere = new Sphere(new Point(1, 2), new Distance(3, Metrics.KILOMETERS));
Distance radius = sphere.getRadius();
object.sphere = sphere;
DBObject dbo = new BasicDBObject();
converter.write(object, dbo);
assertThat(dbo, is(notNullValue()));
assertThat(dbo.get("sphere"), is(instanceOf(DBObject.class)));
assertThat(
dbo.get("sphere"),
is((Object) new BasicDBObject("center", new BasicDBObject("x", sphere.getCenter().getX()).append("y", sphere
.getCenter().getY())).append("radius", radius.getNormalizedValue()).append("metric",
radius.getMetric().toString())));
}
/**
@@ -1726,20 +1767,23 @@ public class MappingMongoConverterUnitTests {
* @DATAMONGO-858
*/
@Test
@SuppressWarnings("deprecation")
public void shouldWriteEntityWithGeoShapeCorrectly() {
ClassWithGeoShape object = new ClassWithGeoShape();
Sphere sphere = new Sphere(new Point(1, 2), 3);
Distance radius = sphere.getRadius();
object.shape = sphere;
DBObject dbo = new BasicDBObject();
converter.write(object, dbo);
assertThat(dbo, is(notNullValue()));
assertThat(dbo.get("shape"), is(instanceOf(List.class)));
assertThat(dbo.get("shape"), is((Object) Arrays.asList(org.springframework.data.mongodb.core.geo.Point
.asList(sphere.getCenter()), sphere.getRadius().getNormalizedValue())));
assertThat(dbo.get("shape"), is(instanceOf(DBObject.class)));
assertThat(
dbo.get("shape"),
is((Object) new BasicDBObject("center", new BasicDBObject("x", sphere.getCenter().getX()).append("y", sphere
.getCenter().getY())).append("radius", radius.getNormalizedValue()).append("metric",
radius.getMetric().toString())));
}
/**

View File

@@ -19,7 +19,6 @@ import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;
import java.math.BigDecimal;
import java.util.List;
import org.junit.Test;
import org.springframework.data.geo.Box;
@@ -31,7 +30,7 @@ import org.springframework.data.mongodb.core.convert.MongoConverters.BigDecimalT
import org.springframework.data.mongodb.core.convert.MongoConverters.StringToBigDecimalConverter;
import org.springframework.data.mongodb.core.geo.Sphere;
import com.mongodb.BasicDBList;
import com.mongodb.DBObject;
/**
* Unit tests for {@link MongoConverters}.
@@ -60,7 +59,7 @@ public class MongoConvertersUnitTests {
Box box = new Box(new Point(1, 2), new Point(3, 4));
BasicDBList dbo = GeoConverters.BoxToDbObjectConverter.INSTANCE.convert(box);
DBObject dbo = GeoConverters.BoxToDbObjectConverter.INSTANCE.convert(box);
Shape shape = GeoConverters.DbObjectToBoxConverter.INSTANCE.convert(dbo);
assertThat(shape, is((org.springframework.data.geo.Shape) box));
@@ -74,7 +73,7 @@ public class MongoConvertersUnitTests {
Circle circle = new Circle(new Point(1, 2), 3);
BasicDBList dbo = GeoConverters.CircleToDbObjectConverter.INSTANCE.convert(circle);
DBObject dbo = GeoConverters.CircleToDbObjectConverter.INSTANCE.convert(circle);
Shape shape = GeoConverters.DbObjectToCircleConverter.INSTANCE.convert(dbo);
assertThat(shape, is((org.springframework.data.geo.Shape) circle));
@@ -88,7 +87,7 @@ public class MongoConvertersUnitTests {
Polygon polygon = new Polygon(new Point(1, 2), new Point(2, 3), new Point(3, 4), new Point(5, 6));
BasicDBList dbo = GeoConverters.PolygonToDbObjectConverter.INSTANCE.convert(polygon);
DBObject dbo = GeoConverters.PolygonToDbObjectConverter.INSTANCE.convert(polygon);
Shape shape = GeoConverters.DbObjectToPolygonConverter.INSTANCE.convert(dbo);
assertThat(shape, is((org.springframework.data.geo.Shape) polygon));
@@ -102,7 +101,7 @@ public class MongoConvertersUnitTests {
Sphere sphere = new Sphere(new Point(1, 2), 3);
BasicDBList dbo = GeoConverters.SphereToDbObjectConverter.INSTANCE.convert(sphere);
DBObject dbo = GeoConverters.SphereToDbObjectConverter.INSTANCE.convert(sphere);
org.springframework.data.geo.Shape shape = GeoConverters.DbObjectToSphereConverter.INSTANCE.convert(dbo);
assertThat(shape, is((org.springframework.data.geo.Shape) sphere));
@@ -116,8 +115,8 @@ public class MongoConvertersUnitTests {
Point point = new Point(1, 2);
List<Double> list = GeoConverters.PointToListConverter.INSTANCE.convert(point);
org.springframework.data.geo.Point converted = GeoConverters.ListToPointConverter.INSTANCE.convert(list);
DBObject dbo = GeoConverters.PointToDbObjectConverter.INSTANCE.convert(point);
org.springframework.data.geo.Point converted = GeoConverters.DbObjectToPointConverter.INSTANCE.convert(dbo);
assertThat(converted, is((org.springframework.data.geo.Point) point));
}

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.mongodb.core.index;
package org.springframework.data.mongodb.core.geo;
import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;
@@ -29,6 +29,8 @@ import org.springframework.data.mongodb.config.AbstractIntegrationTests;
import org.springframework.data.mongodb.core.CollectionCallback;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.WriteResultChecking;
import org.springframework.data.mongodb.core.index.GeoSpatialIndexType;
import org.springframework.data.mongodb.core.index.GeoSpatialIndexed;
import com.mongodb.DBCollection;
import com.mongodb.DBObject;
@@ -40,6 +42,7 @@ import com.mongodb.WriteConcern;
*
* @author Laurent Canet
* @author Oliver Gierke
* @author Thomas Darimont
*/
public class GeoSpatialIndexTests extends AbstractIntegrationTests {

View File

@@ -43,6 +43,7 @@ import org.springframework.data.geo.Metrics;
import org.springframework.data.geo.Point;
import org.springframework.data.geo.Polygon;
import org.springframework.data.mongodb.core.MongoOperations;
import org.springframework.data.mongodb.core.query.BasicQuery;
import org.springframework.data.mongodb.repository.Person.Sex;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@@ -763,7 +764,7 @@ public abstract class AbstractPersonRepositoryIntegrationTests {
assertThat(result, is(arrayWithSize(1)));
assertThat(result, is(arrayContaining(leroi)));
}
/**
* @see DATAMONGO-821
*/