DATAMONGO-1466 - Add embedded typeinformation-based reading GeoJSON converter.
Original pull request: #561.
This commit is contained in:
committed by
Mark Paluch
parent
489d637a00
commit
ae18958955
@@ -41,6 +41,7 @@ import org.springframework.data.mongodb.core.geo.GeoJsonPoint;
|
|||||||
import org.springframework.data.mongodb.core.geo.GeoJsonPolygon;
|
import org.springframework.data.mongodb.core.geo.GeoJsonPolygon;
|
||||||
import org.springframework.data.mongodb.core.geo.Sphere;
|
import org.springframework.data.mongodb.core.geo.Sphere;
|
||||||
import org.springframework.data.mongodb.core.query.GeoCommand;
|
import org.springframework.data.mongodb.core.query.GeoCommand;
|
||||||
|
import org.springframework.lang.Nullable;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
import org.springframework.util.NumberUtils;
|
import org.springframework.util.NumberUtils;
|
||||||
import org.springframework.util.ObjectUtils;
|
import org.springframework.util.ObjectUtils;
|
||||||
@@ -91,7 +92,8 @@ abstract class GeoConverters {
|
|||||||
, DocumentToGeoJsonMultiLineStringConverter.INSTANCE //
|
, DocumentToGeoJsonMultiLineStringConverter.INSTANCE //
|
||||||
, DocumentToGeoJsonMultiPointConverter.INSTANCE //
|
, DocumentToGeoJsonMultiPointConverter.INSTANCE //
|
||||||
, DocumentToGeoJsonMultiPolygonConverter.INSTANCE //
|
, DocumentToGeoJsonMultiPolygonConverter.INSTANCE //
|
||||||
, DocumentToGeoJsonGeometryCollectionConverter.INSTANCE);
|
, DocumentToGeoJsonGeometryCollectionConverter.INSTANCE //
|
||||||
|
, DocumentToGeoJsonConverter.INSTANCE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -756,7 +758,7 @@ abstract class GeoConverters {
|
|||||||
* @author Christoph Strobl
|
* @author Christoph Strobl
|
||||||
* @since 1.7
|
* @since 1.7
|
||||||
*/
|
*/
|
||||||
static enum DocumentToGeoJsonGeometryCollectionConverter implements Converter<Document, GeoJsonGeometryCollection> {
|
enum DocumentToGeoJsonGeometryCollectionConverter implements Converter<Document, GeoJsonGeometryCollection> {
|
||||||
|
|
||||||
INSTANCE;
|
INSTANCE;
|
||||||
|
|
||||||
@@ -775,41 +777,12 @@ abstract class GeoConverters {
|
|||||||
Assert.isTrue(ObjectUtils.nullSafeEquals(source.get("type"), "GeometryCollection"),
|
Assert.isTrue(ObjectUtils.nullSafeEquals(source.get("type"), "GeometryCollection"),
|
||||||
String.format("Cannot convert type '%s' to GeometryCollection.", source.get("type")));
|
String.format("Cannot convert type '%s' to GeometryCollection.", source.get("type")));
|
||||||
|
|
||||||
List<GeoJson<?>> geometries = new ArrayList<GeoJson<?>>();
|
List<GeoJson<?>> geometries = new ArrayList<>();
|
||||||
for (Object o : (List) source.get("geometries")) {
|
for (Object o : (List) source.get("geometries")) {
|
||||||
geometries.add(convertGeometries((Document) o));
|
geometries.add(toGenericGeoJson((Document) o));
|
||||||
}
|
}
|
||||||
|
|
||||||
return new GeoJsonGeometryCollection(geometries);
|
return new GeoJsonGeometryCollection(geometries);
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private static GeoJson<?> convertGeometries(Document source) {
|
|
||||||
|
|
||||||
Object type = source.get("type");
|
|
||||||
if (ObjectUtils.nullSafeEquals(type, "Point")) {
|
|
||||||
return DocumentToGeoJsonPointConverter.INSTANCE.convert(source);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ObjectUtils.nullSafeEquals(type, "MultiPoint")) {
|
|
||||||
return DocumentToGeoJsonMultiPointConverter.INSTANCE.convert(source);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ObjectUtils.nullSafeEquals(type, "LineString")) {
|
|
||||||
return DocumentToGeoJsonLineStringConverter.INSTANCE.convert(source);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ObjectUtils.nullSafeEquals(type, "MultiLineString")) {
|
|
||||||
return DocumentToGeoJsonMultiLineStringConverter.INSTANCE.convert(source);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ObjectUtils.nullSafeEquals(type, "Polygon")) {
|
|
||||||
return DocumentToGeoJsonPolygonConverter.INSTANCE.convert(source);
|
|
||||||
}
|
|
||||||
if (ObjectUtils.nullSafeEquals(type, "MultiPolygon")) {
|
|
||||||
return DocumentToGeoJsonMultiPolygonConverter.INSTANCE.convert(source);
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new IllegalArgumentException(String.format("Cannot convert unknown GeoJson type %s", type));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -852,6 +825,64 @@ abstract class GeoConverters {
|
|||||||
return new GeoJsonPolygon(toListOfPoint((List) dbList.get(0)));
|
return new GeoJsonPolygon(toListOfPoint((List) dbList.get(0)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converter implementation transforming a {@link Document} into a concrete {@link GeoJson} based on the embedded
|
||||||
|
* {@literal type} information.
|
||||||
|
*
|
||||||
|
* @since 2.1
|
||||||
|
* @author Christoph Strobl
|
||||||
|
*/
|
||||||
|
@ReadingConverter
|
||||||
|
enum DocumentToGeoJsonConverter implements Converter<Document, GeoJson> {
|
||||||
|
INSTANCE;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
* @see org.springframework.core.convert.converter.Converter#convert(java.lang.Object)
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public GeoJson convert(Document source) {
|
||||||
|
return toGenericGeoJson(source);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static GeoJson<?> toGenericGeoJson(Document source) {
|
||||||
|
|
||||||
|
String type = source.get("type", String.class);
|
||||||
|
|
||||||
|
if ("point".equalsIgnoreCase(type)) {
|
||||||
|
return DocumentToGeoJsonPointConverter.INSTANCE.convert(source);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ("multipoint".equalsIgnoreCase(type)) {
|
||||||
|
return DocumentToGeoJsonMultiPointConverter.INSTANCE.convert(source);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ("linestring".equalsIgnoreCase(type)) {
|
||||||
|
return DocumentToGeoJsonLineStringConverter.INSTANCE.convert(source);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ("multilinestring".equalsIgnoreCase(type)) {
|
||||||
|
return DocumentToGeoJsonMultiLineStringConverter.INSTANCE.convert(source);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ("polygon".equalsIgnoreCase(type)) {
|
||||||
|
return DocumentToGeoJsonPolygonConverter.INSTANCE.convert(source);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ("multipolygon".equalsIgnoreCase(type)) {
|
||||||
|
return DocumentToGeoJsonMultiPolygonConverter.INSTANCE.convert(source);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ("geometrycollection".equalsIgnoreCase(type)) {
|
||||||
|
return DocumentToGeoJsonGeometryCollectionConverter.INSTANCE.convert(source);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
String.format("No converter found capable of converting GeoJson type " + "%s.", type));
|
||||||
|
}
|
||||||
|
|
||||||
private static double toPrimitiveDoubleValue(Object value) {
|
private static double toPrimitiveDoubleValue(Object value) {
|
||||||
|
|
||||||
Assert.isInstanceOf(Number.class, value, "Argument must be a Number.");
|
Assert.isInstanceOf(Number.class, value, "Argument must be a Number.");
|
||||||
|
|||||||
@@ -20,10 +20,11 @@ import static org.junit.Assert.*;
|
|||||||
import static org.springframework.data.mongodb.core.query.Criteria.*;
|
import static org.springframework.data.mongodb.core.query.Criteria.*;
|
||||||
import static org.springframework.data.mongodb.core.query.Query.*;
|
import static org.springframework.data.mongodb.core.query.Query.*;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import com.mongodb.client.MongoCollection;
|
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
@@ -43,16 +44,17 @@ import org.springframework.data.mongodb.core.MongoTemplate;
|
|||||||
import org.springframework.data.mongodb.core.index.GeoSpatialIndexType;
|
import org.springframework.data.mongodb.core.index.GeoSpatialIndexType;
|
||||||
import org.springframework.data.mongodb.core.index.GeoSpatialIndexed;
|
import org.springframework.data.mongodb.core.index.GeoSpatialIndexed;
|
||||||
import org.springframework.data.mongodb.core.index.GeospatialIndex;
|
import org.springframework.data.mongodb.core.index.GeospatialIndex;
|
||||||
|
import org.springframework.data.mongodb.core.mapping.Document;
|
||||||
import org.springframework.data.mongodb.core.query.NearQuery;
|
import org.springframework.data.mongodb.core.query.NearQuery;
|
||||||
import org.springframework.data.mongodb.core.query.Query;
|
import org.springframework.data.mongodb.core.query.Query;
|
||||||
import org.springframework.data.mongodb.test.util.BasicDbListBuilder;
|
import org.springframework.data.mongodb.test.util.BasicDbListBuilder;
|
||||||
import org.springframework.test.context.ContextConfiguration;
|
import org.springframework.test.context.ContextConfiguration;
|
||||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||||
|
|
||||||
import com.mongodb.Mongo;
|
|
||||||
import com.mongodb.MongoClient;
|
import com.mongodb.MongoClient;
|
||||||
import com.mongodb.MongoException;
|
import com.mongodb.MongoException;
|
||||||
import com.mongodb.WriteConcern;
|
import com.mongodb.WriteConcern;
|
||||||
|
import com.mongodb.client.MongoCollection;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Christoph Strobl
|
* @author Christoph Strobl
|
||||||
@@ -190,8 +192,9 @@ public class GeoJsonTests {
|
|||||||
|
|
||||||
DocumentWithPropertyUsingGeoJsonType obj = new DocumentWithPropertyUsingGeoJsonType();
|
DocumentWithPropertyUsingGeoJsonType obj = new DocumentWithPropertyUsingGeoJsonType();
|
||||||
obj.id = "geoJsonMultiLineString";
|
obj.id = "geoJsonMultiLineString";
|
||||||
obj.geoJsonMultiLineString = new GeoJsonMultiLineString(Arrays.asList(new GeoJsonLineString(new Point(0, 0),
|
obj.geoJsonMultiLineString = new GeoJsonMultiLineString(
|
||||||
new Point(0, 1), new Point(1, 1)), new GeoJsonLineString(new Point(199, 0), new Point(2, 3))));
|
Arrays.asList(new GeoJsonLineString(new Point(0, 0), new Point(0, 1), new Point(1, 1)),
|
||||||
|
new GeoJsonLineString(new Point(199, 0), new Point(2, 3))));
|
||||||
|
|
||||||
template.save(obj);
|
template.save(obj);
|
||||||
|
|
||||||
@@ -221,8 +224,8 @@ public class GeoJsonTests {
|
|||||||
|
|
||||||
DocumentWithPropertyUsingGeoJsonType obj = new DocumentWithPropertyUsingGeoJsonType();
|
DocumentWithPropertyUsingGeoJsonType obj = new DocumentWithPropertyUsingGeoJsonType();
|
||||||
obj.id = "geoJsonMultiPolygon";
|
obj.id = "geoJsonMultiPolygon";
|
||||||
obj.geoJsonMultiPolygon = new GeoJsonMultiPolygon(Arrays.asList(new GeoJsonPolygon(new Point(0, 0),
|
obj.geoJsonMultiPolygon = new GeoJsonMultiPolygon(
|
||||||
new Point(0, 1), new Point(1, 1), new Point(0, 0))));
|
Arrays.asList(new GeoJsonPolygon(new Point(0, 0), new Point(0, 1), new Point(1, 1), new Point(0, 0))));
|
||||||
|
|
||||||
template.save(obj);
|
template.save(obj);
|
||||||
|
|
||||||
@@ -237,9 +240,8 @@ public class GeoJsonTests {
|
|||||||
|
|
||||||
DocumentWithPropertyUsingGeoJsonType obj = new DocumentWithPropertyUsingGeoJsonType();
|
DocumentWithPropertyUsingGeoJsonType obj = new DocumentWithPropertyUsingGeoJsonType();
|
||||||
obj.id = "geoJsonGeometryCollection";
|
obj.id = "geoJsonGeometryCollection";
|
||||||
obj.geoJsonGeometryCollection = new GeoJsonGeometryCollection(Arrays.<GeoJson<?>> asList(
|
obj.geoJsonGeometryCollection = new GeoJsonGeometryCollection(Arrays.<GeoJson<?>> asList(new GeoJsonPoint(100, 200),
|
||||||
new GeoJsonPoint(100, 200), new GeoJsonPolygon(new Point(0, 0), new Point(0, 1), new Point(1, 1), new Point(1,
|
new GeoJsonPolygon(new Point(0, 0), new Point(0, 1), new Point(1, 1), new Point(1, 0), new Point(0, 0))));
|
||||||
0), new Point(0, 0))));
|
|
||||||
|
|
||||||
template.save(obj);
|
template.save(obj);
|
||||||
|
|
||||||
@@ -286,7 +288,8 @@ public class GeoJsonTests {
|
|||||||
new CollectionCallback<Object>() {
|
new CollectionCallback<Object>() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object doInCollection(MongoCollection<org.bson.Document> collection) throws MongoException, DataAccessException {
|
public Object doInCollection(MongoCollection<org.bson.Document> collection)
|
||||||
|
throws MongoException, DataAccessException {
|
||||||
|
|
||||||
org.bson.Document pointRepresentation = new org.bson.Document();
|
org.bson.Document pointRepresentation = new org.bson.Document();
|
||||||
pointRepresentation.put("type", "Point");
|
pointRepresentation.put("type", "Point");
|
||||||
@@ -313,7 +316,8 @@ public class GeoJsonTests {
|
|||||||
new CollectionCallback<Object>() {
|
new CollectionCallback<Object>() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object doInCollection(MongoCollection<org.bson.Document> collection) throws MongoException, DataAccessException {
|
public Object doInCollection(MongoCollection<org.bson.Document> collection)
|
||||||
|
throws MongoException, DataAccessException {
|
||||||
|
|
||||||
org.bson.Document lineStringRepresentation = new org.bson.Document();
|
org.bson.Document lineStringRepresentation = new org.bson.Document();
|
||||||
lineStringRepresentation.put("type", "LineString");
|
lineStringRepresentation.put("type", "LineString");
|
||||||
@@ -337,6 +341,27 @@ public class GeoJsonTests {
|
|||||||
is(equalTo(new GeoJsonLineString(new Point(0D, 0D), new Point(1, 1)))));
|
is(equalTo(new GeoJsonLineString(new Point(0D, 0D), new Point(1, 1)))));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test // DATAMONGO-1466
|
||||||
|
public void readGeoJsonBasedOnEmbeddedTypeInformation() {
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
GeoJsonPolygon polygon = new GeoJsonPolygon(first, second, third, fourth, first);
|
||||||
|
|
||||||
|
ConcreteGeoJson source = new ConcreteGeoJson();
|
||||||
|
source.shape = polygon;
|
||||||
|
source.id = "id-1";
|
||||||
|
|
||||||
|
template.save(source);
|
||||||
|
|
||||||
|
OpenGeoJson target = template.findOne(query(where("id").is(source.id)), OpenGeoJson.class);
|
||||||
|
|
||||||
|
assertThat(target.shape, is(equalTo(source.shape)));
|
||||||
|
}
|
||||||
|
|
||||||
private void addVenues() {
|
private void addVenues() {
|
||||||
|
|
||||||
template.insert(new Venue2DSphere("Penn Station", -73.99408, 40.75057));
|
template.insert(new Venue2DSphere("Penn Station", -73.99408, 40.75057));
|
||||||
@@ -355,8 +380,8 @@ public class GeoJsonTests {
|
|||||||
|
|
||||||
protected void createIndex() {
|
protected void createIndex() {
|
||||||
dropIndex();
|
dropIndex();
|
||||||
template.indexOps(Venue2DSphere.class).ensureIndex(
|
template.indexOps(Venue2DSphere.class)
|
||||||
new GeospatialIndex("location").typed(GeoSpatialIndexType.GEO_2DSPHERE));
|
.ensureIndex(new GeospatialIndex("location").typed(GeoSpatialIndexType.GEO_2DSPHERE));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void dropIndex() {
|
protected void dropIndex() {
|
||||||
@@ -416,4 +441,18 @@ public class GeoJsonTests {
|
|||||||
GeoJsonGeometryCollection geoJsonGeometryCollection;
|
GeoJsonGeometryCollection geoJsonGeometryCollection;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@Document(collection = "geo-json-shapes")
|
||||||
|
static class ConcreteGeoJson {
|
||||||
|
String id;
|
||||||
|
GeoJsonPolygon shape;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@Document(collection = "geo-json-shapes")
|
||||||
|
static class OpenGeoJson {
|
||||||
|
String id;
|
||||||
|
GeoJson shape;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user