-
Notifications
You must be signed in to change notification settings - Fork 455
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
b4a6b3e
commit 396a9b5
Showing
30 changed files
with
435 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
127 changes: 127 additions & 0 deletions
127
core/src/main/java/dev/morphia/mapping/codec/PolygonCoordinatesCodec.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,127 @@ | ||
package dev.morphia.mapping.codec; | ||
|
||
import java.util.ArrayList; | ||
import java.util.List; | ||
|
||
import com.mongodb.client.model.geojson.PolygonCoordinates; | ||
import com.mongodb.client.model.geojson.Position; | ||
|
||
import org.bson.BsonReader; | ||
import org.bson.BsonType; | ||
import org.bson.BsonWriter; | ||
import org.bson.codecs.Codec; | ||
import org.bson.codecs.DecoderContext; | ||
import org.bson.codecs.EncoderContext; | ||
import org.bson.codecs.configuration.CodecConfigurationException; | ||
|
||
import static java.lang.String.format; | ||
|
||
/** | ||
* This codec has been cobbled together via sources from com.mongodb.client.model.geojson.codecs.GeometryDecoderHelper | ||
* and com.mongodb.client.model.geojson.codecs.GeometryEncoderHelper | ||
*/ | ||
public class PolygonCoordinatesCodec implements Codec<PolygonCoordinates> { | ||
|
||
@Override | ||
public PolygonCoordinates decode(BsonReader reader, DecoderContext decoderContext) { | ||
reader.readStartArray(); | ||
List<List<Position>> values = new ArrayList<>(); | ||
while (reader.readBsonType() != BsonType.END_OF_DOCUMENT) { | ||
values.add(decodeCoordinates(reader)); | ||
} | ||
reader.readEndArray(); | ||
|
||
if (values.isEmpty()) { | ||
throw new CodecConfigurationException("Invalid Polygon no coordinates."); | ||
} | ||
|
||
List<Position> exterior = values.remove(0); | ||
|
||
try { | ||
return new PolygonCoordinates(exterior, values); | ||
} catch (IllegalArgumentException e) { | ||
throw new CodecConfigurationException(format("Invalid Polygon: %s", e.getMessage())); | ||
} | ||
|
||
} | ||
|
||
@Override | ||
public void encode(BsonWriter writer, PolygonCoordinates polygonCoordinates, EncoderContext encoderContext) { | ||
writer.writeStartArray(); | ||
encodeLinearRing(polygonCoordinates.getExterior(), writer); | ||
for (List<Position> ring : polygonCoordinates.getHoles()) { | ||
encodeLinearRing(ring, writer); | ||
} | ||
writer.writeEndArray(); | ||
} | ||
|
||
@Override | ||
public Class<PolygonCoordinates> getEncoderClass() { | ||
return PolygonCoordinates.class; | ||
} | ||
|
||
private static List<Position> decodeCoordinates(final BsonReader reader) { | ||
validateIsArray(reader); | ||
reader.readStartArray(); | ||
List<Position> values = new ArrayList<>(); | ||
while (reader.readBsonType() != BsonType.END_OF_DOCUMENT) { | ||
values.add(decodePosition(reader)); | ||
} | ||
reader.readEndArray(); | ||
return values; | ||
} | ||
|
||
private static Position decodePosition(final BsonReader reader) { | ||
validateIsArray(reader); | ||
reader.readStartArray(); | ||
List<Double> values = new ArrayList<>(); | ||
while (reader.readBsonType() != BsonType.END_OF_DOCUMENT) { | ||
values.add(readAsDouble(reader)); | ||
} | ||
reader.readEndArray(); | ||
|
||
try { | ||
return new Position(values); | ||
} catch (IllegalArgumentException e) { | ||
throw new CodecConfigurationException(format("Invalid Position: %s", e.getMessage())); | ||
} | ||
} | ||
|
||
private static double readAsDouble(final BsonReader reader) { | ||
if (reader.getCurrentBsonType() == BsonType.DOUBLE) { | ||
return reader.readDouble(); | ||
} else if (reader.getCurrentBsonType() == BsonType.INT32) { | ||
return reader.readInt32(); | ||
} else if (reader.getCurrentBsonType() == BsonType.INT64) { | ||
return reader.readInt64(); | ||
} | ||
|
||
throw new CodecConfigurationException("A GeoJSON position value must be a numerical type, but the value is of type " | ||
+ reader.getCurrentBsonType()); | ||
} | ||
|
||
private void encodeLinearRing(final List<Position> ring, final BsonWriter writer) { | ||
writer.writeStartArray(); | ||
for (Position position : ring) { | ||
encodePosition(writer, position); | ||
} | ||
writer.writeEndArray(); | ||
} | ||
|
||
private void encodePosition(final BsonWriter writer, final Position value) { | ||
writer.writeStartArray(); | ||
|
||
for (double number : value.getValues()) { | ||
writer.writeDouble(number); | ||
} | ||
|
||
writer.writeEndArray(); | ||
} | ||
|
||
private static void validateIsArray(final BsonReader reader) { | ||
if (reader.getCurrentBsonType() != BsonType.ARRAY) { | ||
throw new CodecConfigurationException("Invalid BsonType expecting an Array"); | ||
} | ||
} | ||
|
||
} |
62 changes: 62 additions & 0 deletions
62
core/src/main/java/dev/morphia/mapping/codec/filters/GeoWithinFilterCodec.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
package dev.morphia.mapping.codec.filters; | ||
|
||
import com.mongodb.client.model.geojson.CoordinateReferenceSystem; | ||
import com.mongodb.client.model.geojson.GeoJsonObjectType; | ||
import com.mongodb.client.model.geojson.Geometry; | ||
import com.mongodb.client.model.geojson.MultiPolygon; | ||
import com.mongodb.client.model.geojson.Polygon; | ||
|
||
import dev.morphia.MorphiaDatastore; | ||
import dev.morphia.query.filters.GeoWithinFilter; | ||
|
||
import org.bson.BsonWriter; | ||
import org.bson.codecs.EncoderContext; | ||
|
||
import static dev.morphia.mapping.codec.CodecHelper.document; | ||
import static dev.morphia.mapping.codec.CodecHelper.value; | ||
|
||
public class GeoWithinFilterCodec extends BaseFilterCodec<GeoWithinFilter> { | ||
public GeoWithinFilterCodec(MorphiaDatastore datastore) { | ||
super(datastore); | ||
} | ||
|
||
@Override | ||
public void encode(BsonWriter writer, GeoWithinFilter value, EncoderContext encoderContext) { | ||
document(writer, value.path(datastore.getMapper()), () -> { | ||
if (value.isNot()) { | ||
document(writer, "$not", () -> { | ||
encodeFilter(writer, value, encoderContext); | ||
}); | ||
} else { | ||
encodeFilter(writer, value, encoderContext); | ||
} | ||
}); | ||
} | ||
|
||
private void encodeFilter(BsonWriter writer, GeoWithinFilter value, EncoderContext encoderContext) { | ||
document(writer, value.getName(), () -> { | ||
document(writer, "$geometry", () -> { | ||
Geometry geometry = (Geometry) value.getValue(); | ||
value(writer, "type", geometry.getType().getTypeName()); | ||
GeoJsonObjectType type = geometry.getType(); | ||
if (type == GeoJsonObjectType.POLYGON) { | ||
var coordinates = ((Polygon) geometry).getCoordinates(); | ||
value(datastore.getCodecRegistry(), writer, "coordinates", coordinates, encoderContext); | ||
} else if (type == GeoJsonObjectType.MULTI_POLYGON) { | ||
var coordinates = ((MultiPolygon) geometry).getCoordinates(); | ||
value(datastore.getCodecRegistry(), writer, "coordinates", coordinates, encoderContext); | ||
} | ||
CoordinateReferenceSystem crs = geometry.getCoordinateReferenceSystem(); | ||
if (crs != null) { | ||
value(datastore.getCodecRegistry(), writer, "crs", crs, encoderContext); | ||
} | ||
|
||
}); | ||
}); | ||
} | ||
|
||
@Override | ||
public Class<GeoWithinFilter> getEncoderClass() { | ||
return GeoWithinFilter.class; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
23 changes: 23 additions & 0 deletions
23
core/src/test/java/dev/morphia/test/query/filters/TestBox.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
package dev.morphia.test.query.filters; | ||
|
||
import com.mongodb.client.model.geojson.Point; | ||
import com.mongodb.client.model.geojson.Position; | ||
|
||
import org.testng.annotations.Test; | ||
|
||
import static dev.morphia.query.filters.Filters.box; | ||
|
||
public class TestBox extends FilterTest { | ||
|
||
/** | ||
* test data: dev/morphia/test/query/filters/box/example1 | ||
*/ | ||
@Test(testName = "main") | ||
public void testExample1() { | ||
Point bottomLeft = new Point(new Position(0, 0)); | ||
Point upperRight = new Point(new Position(100, 100)); | ||
testQuery(new QueryTestOptions().skipDataCheck(true), | ||
(query) -> query.filter( | ||
box("loc", bottomLeft, upperRight))); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.