diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/GeoConverters.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/GeoConverters.java index 8b7f0f1b4..038f72e23 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/GeoConverters.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/GeoConverters.java @@ -67,6 +67,7 @@ abstract class GeoConverters { * * @return */ + @SuppressWarnings("unchecked") public static Collection getConvertersToRegister() { return Arrays.asList( // BoxToDbObjectConverter.INSTANCE // @@ -421,6 +422,7 @@ abstract class GeoConverters { * @see org.springframework.core.convert.converter.Converter#convert(java.lang.Object) */ @Override + @SuppressWarnings("rawtypes") public DBObject convert(GeoCommand source) { if (source == null) { @@ -472,8 +474,13 @@ abstract class GeoConverters { */ @SuppressWarnings("rawtypes") static enum GeoJsonToDbObjectConverter implements Converter { + INSTANCE; + /* + * (non-Javadoc) + * @see org.springframework.core.convert.converter.Converter#convert(java.lang.Object) + */ @Override public DBObject convert(GeoJson source) { @@ -484,11 +491,15 @@ abstract class GeoConverters { DBObject dbo = new BasicDBObject("type", source.getType()); if (source instanceof GeoJsonGeometryCollection) { + BasicDBList dbl = new BasicDBList(); + for (GeoJson geometry : ((GeoJsonGeometryCollection) source).getCoordinates()) { dbl.add(convert(geometry)); } + dbo.put("geometries", dbl); + } else { dbo.put("coordinates", convertIfNecessarry(source.getCoordinates())); } @@ -503,10 +514,13 @@ abstract class GeoConverters { } if (candidate instanceof Iterable) { + BasicDBList dbl = new BasicDBList(); + for (Object element : (Iterable) candidate) { dbl.add(convertIfNecessarry(element)); } + return dbl; } @@ -523,8 +537,13 @@ abstract class GeoConverters { * @since 1.7 */ static enum GeoJsonPointToDbObjectConverter implements Converter { + INSTANCE; + /* + * (non-Javadoc) + * @see org.springframework.core.convert.converter.Converter#convert(java.lang.Object) + */ @Override public DBObject convert(GeoJsonPoint source) { return GeoJsonToDbObjectConverter.INSTANCE.convert(source); @@ -536,13 +555,17 @@ abstract class GeoConverters { * @since 1.7 */ static enum GeoJsonPolygonToDbObjectConverter implements Converter { + INSTANCE; + /* + * (non-Javadoc) + * @see org.springframework.core.convert.converter.Converter#convert(java.lang.Object) + */ @Override public DBObject convert(GeoJsonPolygon source) { return GeoJsonToDbObjectConverter.INSTANCE.convert(source); } - } /** @@ -550,9 +573,15 @@ abstract class GeoConverters { * @since 1.7 */ static enum DbObjectToGeoJsonPointConverter implements Converter { + INSTANCE; + /* + * (non-Javadoc) + * @see org.springframework.core.convert.converter.Converter#convert(java.lang.Object) + */ @Override + @SuppressWarnings("unchecked") public GeoJsonPoint convert(DBObject source) { if (source == null) { @@ -572,9 +601,13 @@ abstract class GeoConverters { * @since 1.7 */ static enum DbObjectToGeoJsonPolygonConverter implements Converter { + INSTANCE; - @SuppressWarnings("rawtypes") + /* + * (non-Javadoc) + * @see org.springframework.core.convert.converter.Converter#convert(java.lang.Object) + */ @Override public GeoJsonPolygon convert(DBObject source) { @@ -594,8 +627,13 @@ abstract class GeoConverters { * @since 1.7 */ static enum DbObjectToGeoJsonMultiPolygonConverter implements Converter { + INSTANCE; + /* + * (non-Javadoc) + * @see org.springframework.core.convert.converter.Converter#convert(java.lang.Object) + */ @Override public GeoJsonMultiPolygon convert(DBObject source) { @@ -608,11 +646,12 @@ abstract class GeoConverters { BasicDBList dbl = (BasicDBList) source.get("coordinates"); List polygones = new ArrayList(); + for (Object polygon : dbl) { polygones.add(toGeoJsonPolygon((BasicDBList) polygon)); } - return new GeoJsonMultiPolygon(polygones); + return new GeoJsonMultiPolygon(polygones); } } @@ -621,8 +660,13 @@ abstract class GeoConverters { * @since 1.7 */ static enum DbObjectToGeoJsonLineStringConverter implements Converter { + INSTANCE; + /* + * (non-Javadoc) + * @see org.springframework.core.convert.converter.Converter#convert(java.lang.Object) + */ @Override public GeoJsonLineString convert(DBObject source) { @@ -634,6 +678,7 @@ abstract class GeoConverters { String.format("Cannot convert type '%s' to LineString.", source.get("type"))); BasicDBList cords = (BasicDBList) source.get("coordinates"); + return new GeoJsonLineString(toListOfPoint(cords)); } } @@ -643,8 +688,13 @@ abstract class GeoConverters { * @since 1.7 */ static enum DbObjectToGeoJsonMultiPointConverter implements Converter { + INSTANCE; + /* + * (non-Javadoc) + * @see org.springframework.core.convert.converter.Converter#convert(java.lang.Object) + */ @Override public GeoJsonMultiPoint convert(DBObject source) { @@ -656,6 +706,7 @@ abstract class GeoConverters { String.format("Cannot convert type '%s' to MultiPoint.", source.get("type"))); BasicDBList cords = (BasicDBList) source.get("coordinates"); + return new GeoJsonMultiPoint(toListOfPoint(cords)); } } @@ -665,8 +716,13 @@ abstract class GeoConverters { * @since 1.7 */ static enum DbObjectToGeoJsonMultiLineStringConverter implements Converter { + INSTANCE; + /* + * (non-Javadoc) + * @see org.springframework.core.convert.converter.Converter#convert(java.lang.Object) + */ @Override public GeoJsonMultiLineString convert(DBObject source) { @@ -679,6 +735,7 @@ abstract class GeoConverters { List lines = new ArrayList(); BasicDBList cords = (BasicDBList) source.get("coordinates"); + for (Object line : cords) { lines.add(new GeoJsonLineString(toListOfPoint((BasicDBList) line))); } @@ -691,8 +748,14 @@ abstract class GeoConverters { * @since 1.7 */ static enum DbObjectToGeoJsonGeometryCollectionConverter implements Converter { + INSTANCE; + /* + * (non-Javadoc) + * @see org.springframework.core.convert.converter.Converter#convert(java.lang.Object) + */ + @SuppressWarnings("rawtypes") @Override public GeoJsonGeometryCollection convert(DBObject source) { @@ -711,7 +774,7 @@ abstract class GeoConverters { } - private GeoJson convertGeometries(DBObject source) { + private static GeoJson convertGeometries(DBObject source) { Object type = source.get("type"); if (ObjectUtils.nullSafeEquals(type, "Point")) { @@ -756,11 +819,13 @@ abstract class GeoConverters { static List toListOfPoint(BasicDBList listOfCoordinatePairs) { List points = new ArrayList(); + for (Object point : listOfCoordinatePairs) { Assert.isInstanceOf(List.class, point); List coordinatesList = (List) point; + points.add(new GeoJsonPoint(coordinatesList.get(0).doubleValue(), coordinatesList.get(1).doubleValue())); } return points; @@ -769,14 +834,11 @@ abstract class GeoConverters { /** * Converts a coordinate pairs nested in in {@link BasicDBList} into {@link GeoJsonPolygon}. * - * @param dbl + * @param dbList * @return * @since 1.7 */ - static GeoJsonPolygon toGeoJsonPolygon(BasicDBList dbl) { - - List outer = toListOfPoint((BasicDBList) dbl.get(0)); - - return new GeoJsonPolygon(outer); + static GeoJsonPolygon toGeoJsonPolygon(BasicDBList dbList) { + return new GeoJsonPolygon(toListOfPoint((BasicDBList) dbList.get(0))); } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJson.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJson.java index 92e4ae2ef..91f48672a 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJson.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJson.java @@ -26,7 +26,7 @@ public interface GeoJson> { /** * String value representing the type of the {@link GeoJson} object. * - * @return never {@literal null}. + * @return will never be {@literal null}. * @see http://geojson.org/geojson-spec.html#geojson-objects */ String getType(); @@ -35,7 +35,7 @@ public interface GeoJson> { * The value of the coordinates member is always an {@link Iterable}. The structure for the elements within is * determined by {@link #getType()} of geometry. * - * @return never {@literal null}. + * @return will never be {@literal null}. * @see http://geojson.org/geojson-spec.html#geometry-objects */ T getCoordinates(); diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJsonGeometryCollection.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJsonGeometryCollection.java index 1b98f312b..96cc28cae 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJsonGeometryCollection.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJsonGeometryCollection.java @@ -32,14 +32,18 @@ import org.springframework.util.ObjectUtils; public class GeoJsonGeometryCollection implements GeoJson>> { private static final String TYPE = "GeometryCollection"; + private final List> geometries = new ArrayList>(); /** + * Creates a new {@link GeoJsonGeometryCollection} for the given {@link GeoJson} instances. + * * @param geometries */ public GeoJsonGeometryCollection(List> geometries) { - Assert.notNull(geometries); + Assert.notNull(geometries, "Geometries must not be null!"); + this.geometries.addAll(geometries); } @@ -76,17 +80,17 @@ public class GeoJsonGeometryCollection implements GeoJson>> */ @Override public boolean equals(Object obj) { + if (this == obj) { return true; } - if (obj == null) { - return false; - } + if (!(obj instanceof GeoJsonGeometryCollection)) { return false; } + GeoJsonGeometryCollection other = (GeoJsonGeometryCollection) obj; + return ObjectUtils.nullSafeEquals(this.geometries, other.geometries); } - } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJsonLineString.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJsonLineString.java index 98a8b9901..921a8dbf8 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJsonLineString.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJsonLineString.java @@ -31,6 +31,8 @@ public class GeoJsonLineString extends GeoJsonMultiPoint { private static final String TYPE = "LineString"; /** + * Creates a new {@link GeoJsonLineString} for the given {@link Point}s. + * * @param points must not be {@literal null} and have at least 2 entries. */ public GeoJsonLineString(List points) { @@ -38,12 +40,14 @@ public class GeoJsonLineString extends GeoJsonMultiPoint { } /** - * @param p0 must not be {@literal null} - * @param p1 must not be {@literal null} + * Creates a new {@link GeoJsonLineString} for the given {@link Point}s. + * + * @param first must not be {@literal null} + * @param second must not be {@literal null} * @param others can be {@literal null} */ - public GeoJsonLineString(Point p0, Point p1, Point... others) { - super(p0, p1, others); + public GeoJsonLineString(Point first, Point second, Point... others) { + super(first, second, others); } /* @@ -54,5 +58,4 @@ public class GeoJsonLineString extends GeoJsonMultiPoint { public String getType() { return TYPE; } - } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJsonMultiLineString.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJsonMultiLineString.java index 1bc11d4c2..90b046ccc 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJsonMultiLineString.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJsonMultiLineString.java @@ -33,28 +33,32 @@ import org.springframework.util.ObjectUtils; public class GeoJsonMultiLineString implements GeoJson> { private static final String TYPE = "MultiLineString"; + private List coordinates = new ArrayList(); /** - * Creates new {@link GeoJsonMultiLineString}. + * Creates new {@link GeoJsonMultiLineString} for the given {@link Point}s. * * @param lines must not be {@literal null}. */ - @SuppressWarnings("unchecked") public GeoJsonMultiLineString(List... lines) { - Assert.notEmpty(lines, "Lines for MultiLineString must not be null!"); + Assert.notEmpty(lines, "Points for MultiLineString must not be null!"); + for (List line : lines) { this.coordinates.add(new GeoJsonLineString(line)); } } /** + * Creates new {@link GeoJsonMultiLineString} for the given {@link GeoJsonLineString}s. + * * @param lines must not be {@literal null}. */ public GeoJsonMultiLineString(List lines) { Assert.notNull(lines, "Lines for MultiLineString must not be null!"); + this.coordinates.addAll(lines); } @@ -91,16 +95,15 @@ public class GeoJsonMultiLineString implements GeoJson> { private static final String TYPE = "MultiPoint"; + private final List points; /** + * Creates a new {@link GeoJsonMultiPoint} for the given {@link Point}s. + * * @param points points must not be {@literal null} and have at least 2 entries. */ public GeoJsonMultiPoint(List points) { @@ -47,14 +50,23 @@ public class GeoJsonMultiPoint implements GeoJson> { this.points = new ArrayList(points); } - public GeoJsonMultiPoint(Point p0, Point p1, Point... others) { + /** + * Creates a new {@link GeoJsonMultiPoint} for the given {@link Point}s. + * + * @param first must not be {@literal null}. + * @param second must not be {@literal null}. + * @param others must not be {@literal null}. + */ + public GeoJsonMultiPoint(Point first, Point second, Point... others) { + + Assert.notNull(first, "First point must not be null!"); + Assert.notNull(second, "Second point must not be null!"); + Assert.notNull(others, "Additional points must not be null!"); this.points = new ArrayList(); - this.points.add(p0); - this.points.add(p1); - if (!ObjectUtils.isEmpty(others)) { - this.points.addAll(Arrays.asList(others)); - } + this.points.add(first); + this.points.add(second); + this.points.addAll(Arrays.asList(others)); } /* @@ -90,16 +102,15 @@ public class GeoJsonMultiPoint implements GeoJson> { */ @Override public boolean equals(Object obj) { + if (this == obj) { return true; } - if (obj == null) { - return false; - } + if (!(obj instanceof GeoJsonMultiPoint)) { return false; } + return ObjectUtils.nullSafeEquals(this.points, ((GeoJsonMultiPoint) obj).points); } - } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJsonMultiPolygon.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJsonMultiPolygon.java index f0254394c..da4a1be17 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJsonMultiPolygon.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJsonMultiPolygon.java @@ -31,14 +31,18 @@ import org.springframework.util.ObjectUtils; public class GeoJsonMultiPolygon implements GeoJson> { private static final String TYPE = "MultiPolygon"; + private List coordinates = new ArrayList(); /** + * Creates a new {@link GeoJsonMultiPolygon} for the given {@link GeoJsonPolygon}s. + * * @param polygons must not be {@literal null}. */ public GeoJsonMultiPolygon(List polygons) { Assert.notNull(polygons, "Polygons for MultiPolygon must not be null!"); + this.coordinates.addAll(polygons); } @@ -75,16 +79,15 @@ public class GeoJsonMultiPolygon implements GeoJson> { */ @Override public boolean equals(Object obj) { + if (this == obj) { return true; } - if (obj == null) { - return false; - } + if (!(obj instanceof GeoJsonMultiPolygon)) { return false; } + return ObjectUtils.nullSafeEquals(this.coordinates, ((GeoJsonMultiPolygon) obj).coordinates); } - } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJsonPoint.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJsonPoint.java index ab83adb3a..a44aa856c 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJsonPoint.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJsonPoint.java @@ -30,6 +30,7 @@ import org.springframework.data.geo.Point; public class GeoJsonPoint extends Point implements GeoJson> { private static final long serialVersionUID = -8026303425147474002L; + private static final String TYPE = "Point"; /** @@ -68,5 +69,4 @@ public class GeoJsonPoint extends Point implements GeoJson> { public List getCoordinates() { return Arrays.asList(Double.valueOf(getX()), Double.valueOf(getY())); } - } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJsonPolygon.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJsonPolygon.java index 5738efc4f..0963e1808 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJsonPolygon.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJsonPolygon.java @@ -22,7 +22,6 @@ import java.util.List; import org.springframework.data.geo.Point; import org.springframework.data.geo.Polygon; -import org.springframework.util.ObjectUtils; /** * {@link GeoJson} representation of {@link Polygon}. Unlike {@link Polygon} the {@link GeoJsonPolygon} requires a @@ -36,34 +35,24 @@ public class GeoJsonPolygon extends Polygon implements GeoJson coordinates = new ArrayList(); /** - * Creates new {@link GeoJsonPolygon}. + * Creates new {@link GeoJsonPolygon} from the given {@link Point}s. * - * @param p0 must not be {@literal null}. - * @param p1 must not be {@literal null}. - * @param p2 must not be {@literal null}. - * @param p3 must not be {@literal null}. + * @param first must not be {@literal null}. + * @param second must not be {@literal null}. + * @param third must not be {@literal null}. + * @param fourth must not be {@literal null}. * @param others can be {@literal null}. */ - public GeoJsonPolygon(Point p0, Point p1, Point p2, Point p3, final Point... others) { - - this(new ArrayList(Arrays.asList(p0, p1, p2, p3)) { - private static final long serialVersionUID = 3143657022446395361L; - - { - if (!ObjectUtils.isEmpty(others)) { - for (Point p : others) { - add(p); - } - } - } - }); + public GeoJsonPolygon(Point first, Point second, Point third, Point fourth, final Point... others) { + this(asList(first, second, third, fourth, others)); } /** - * Creates new {@link GeoJsonPolygon}. + * Creates new {@link GeoJsonPolygon} from the given {@link Point}s. * * @param points must not be {@literal null}. */ @@ -90,4 +79,17 @@ public class GeoJsonPolygon extends Polygon implements GeoJson getCoordinates() { return Collections.unmodifiableList(this.coordinates); } + + private static List asList(Point first, Point second, Point third, Point fourth, final Point... others) { + + ArrayList result = new ArrayList(3 + others.length); + + result.add(first); + result.add(second); + result.add(third); + result.add(fourth); + result.addAll(Arrays.asList(others)); + + return result; + } } 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 a0066a34f..38725ff4f 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 @@ -605,11 +605,6 @@ public class Criteria implements CriteriaDefinition { } } - private boolean requiresGeoJsonFormat(Object value) { - return value instanceof GeoJson - || (value instanceof GeoCommand && ((GeoCommand) value).getShape() instanceof GeoJson); - } - private boolean createNearCriteriaForCommand(String command, double maxDistance) { if (!criteria.containsKey(command)) { @@ -617,16 +612,22 @@ public class Criteria implements CriteriaDefinition { } Object existingNearOperationValue = criteria.get(command); + if (existingNearOperationValue instanceof DBObject) { + ((DBObject) existingNearOperationValue).put("$maxDistance", maxDistance); + return true; + } else if (existingNearOperationValue instanceof GeoJson) { - BasicDBObject dbo = new BasicDBObject("$geometry", existingNearOperationValue); - dbo.put("$maxDistance", maxDistance); + BasicDBObject dbo = new BasicDBObject("$geometry", existingNearOperationValue) + .append("$maxDistance", maxDistance); criteria.put(command, dbo); + return true; } + return false; } @@ -708,4 +709,9 @@ public class Criteria implements CriteriaDefinition { return result; } + + private static boolean requiresGeoJsonFormat(Object value) { + return value instanceof GeoJson + || (value instanceof GeoCommand && ((GeoCommand) value).getShape() instanceof GeoJson); + } }