Skip to content

Commit

Permalink
more tests. geo stuff.
Browse files Browse the repository at this point in the history
  • Loading branch information
evanchooly committed Jun 13, 2024
1 parent b4a6b3e commit 396a9b5
Show file tree
Hide file tree
Showing 30 changed files with 435 additions and 8 deletions.
2 changes: 0 additions & 2 deletions audits/src/main/kotlin/dev/morphia/audits/RstAuditor.kt
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,6 @@ class RstAuditor(val type: OperatorType) {
}
source.addTestCases(operator)

println("**************** source = \n\n${source}")
if (!outputFile.parentFile.mkdirs() && !outputFile.parentFile.exists()) {
throw IOException(
String.format("Could not create directory: %s", outputFile.parentFile)
Expand Down Expand Up @@ -212,7 +211,6 @@ class RstAuditor(val type: OperatorType) {
text = "test data: ${example.folder.relativeTo(coreTestRoot)}\n" + text
method.javaDoc.text = text
}
println("**************** text = ${text}")
}

private fun updateTestAnnotation(
Expand Down
2 changes: 2 additions & 0 deletions core/src/main/java/dev/morphia/MorphiaDatastore.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import com.mongodb.client.MongoDatabase;
import com.mongodb.client.model.CreateCollectionOptions;
import com.mongodb.client.model.ValidationOptions;
import com.mongodb.client.model.geojson.codecs.GeoJsonCodecProvider;
import com.mongodb.client.result.DeleteResult;
import com.mongodb.client.result.InsertManyResult;
import com.mongodb.client.result.InsertOneResult;
Expand Down Expand Up @@ -172,6 +173,7 @@ private CodecRegistry buildRegistry(CodecRegistry codecRegistry) {

providers.addAll(morphiaCodecProviders);
providers.add(codecRegistry);
providers.add(new GeoJsonCodecProvider());
codecRegistry = fromProviders(providers);
return codecRegistry;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import dev.morphia.mapping.codec.filters.FieldLessFilterCodec;
import dev.morphia.mapping.codec.filters.FilterCodec;
import dev.morphia.mapping.codec.filters.GeoIntersectsFilterCodec;
import dev.morphia.mapping.codec.filters.GeoWithinFilterCodec;
import dev.morphia.mapping.codec.filters.JsonSchemaFilterCodec;
import dev.morphia.mapping.codec.filters.LogicalFilterCodec;
import dev.morphia.mapping.codec.filters.NearFilterCodec;
Expand Down Expand Up @@ -43,6 +44,7 @@ public MorphiaFilterCodecProvider(MorphiaDatastore datastore) {
addCodec(new FilterCodec(datastore));
addCodec(new FieldLessFilterCodec(datastore));
addCodec(new GeoIntersectsFilterCodec(datastore));
addCodec(new GeoWithinFilterCodec(datastore));
addCodec(new JsonSchemaFilterCodec(datastore));
addCodec(new LogicalFilterCodec(datastore));
addCodec(new ModFilterCodec(datastore));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ public MorphiaTypesCodecProvider(MorphiaDatastore datastore) {
addCodec(new MorphiaMapCodec(datastore));
addCodec(new MorphiaLocalDateTimeCodec(datastore));
addCodec(new MorphiaLocalTimeCodec());
addCodec(new PolygonCoordinatesCodec());
addCodec(new ClassCodec());
addCodec(new LocaleCodec());
addCodec(new ObjectCodec(datastore));
Expand Down
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");
}
}

}
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;
}
}
1 change: 1 addition & 0 deletions core/src/main/java/dev/morphia/query/filters/Filter.java
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ public Filter not() {
* @hidden
* @morphia.internal
*/
@Nullable
@MorphiaInternal
public String getName() {
return name;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,28 @@
import static dev.morphia.query.filters.Filters.bitsAnyClear;

public class TestBitsAnyClear extends FilterTest {
/**
* test data: dev/morphia/test/query/filters/bitsAnyClear/example1
*
*/
@Test(testName = "Bit Position Array")
public void testExample1() {
testQuery((query) -> query.filter(bitsAnyClear("a", new int[] { 1, 5 })));
}

/**
* test data: dev/morphia/test/query/filters/bitsAnyClear/example2
*
*/
@Test(testName = "Integer Bitmask")
public void testExample2() {
testQuery((query) -> query.filter(bitsAnyClear("a", 35)));
}

/**
* test data: dev/morphia/test/query/filters/bitsAnyClear/example3
*
*/
@Test(testName = "BinData Bitmask")
public void testExample3() {
testQuery((query) -> query.filter(bitsAnyClear("a", new byte[] { 48 })));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,31 @@
import static dev.morphia.query.filters.Filters.bitsAnySet;

public class TestBitsAnySet extends FilterTest {
/**
* test data: dev/morphia/test/query/filters/bitsAnySet/example1
*
*/
@Test(testName = "Bit Position Array")
public void testExample1() {
testQuery((query) -> query.filter(
bitsAnySet("a", new int[] { 1, 5 })));
testQuery((query) -> query.filter(bitsAnySet("a", new int[] { 1, 5 })));
}

/**
* test data: dev/morphia/test/query/filters/bitsAnySet/example2
*
*/
@Test(testName = "Integer Bitmask")
public void testExample2() {
testQuery((query) -> query.filter(
bitsAnySet("a", 35)));
testQuery((query) -> query.filter(bitsAnySet("a", 35)));
}

/**
* test data: dev/morphia/test/query/filters/bitsAnySet/example3
*
*/
@Test(testName = "BinData Bitmask")
public void testExample3() {
testQuery((query) -> query.filter(
bitsAnySet("a", new byte[] { 48 })));
testQuery((query) -> query.filter(bitsAnySet("a", new byte[] { 48 })));
}

}
23 changes: 23 additions & 0 deletions core/src/test/java/dev/morphia/test/query/filters/TestBox.java
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)));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,28 @@
import static dev.morphia.query.filters.Filters.lt;

public class TestElemMatch extends FilterTest {
/**
* test data: dev/morphia/test/query/filters/elemMatch/example1
*
*/
@Test(testName = "Element Match")
public void testExample1() {
testQuery((query) -> query.filter(elemMatch("results", gte(80), lt(85))));
}

/**
* test data: dev/morphia/test/query/filters/elemMatch/example2
*
*/
@Test(testName = "Array of Embedded Documents")
public void testExample2() {
testQuery((query) -> query.filter(elemMatch("results", eq("product", "xyz"), gte("score", 8))));
}

/**
* test data: dev/morphia/test/query/filters/elemMatch/example3
*
*/
@Test(testName = "Single Query Condition")
public void testExample3() {
testQuery((query) -> query.filter(elemMatch("results", eq("product", "xyz"))));
Expand Down
Loading

0 comments on commit 396a9b5

Please sign in to comment.