diff --git a/CHANGELOG.md b/CHANGELOG.md index 4290d755..ded5b5c7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ Changelog * fix returning invalid GeoJSON using empty coordinates for deletion contributions ([#129], [#131]) * fix using a proper boolean data type instead of a string for contributionType in response ([#135]) * fix NPE with createOSMFeature ([#141]) +* make sure geometry filters are applied to all returned features of elementsFullHistory requests ([#109]) ### Performance and Code Quality @@ -25,6 +26,7 @@ Changelog [#83]: https://github.com/GIScience/ohsome-api/issues/83 [#98]: https://github.com/GIScience/ohsome-api/issues/98 +[#109]: https://github.com/GIScience/ohsome-api/issues/109 [#111]: https://github.com/GIScience/ohsome-api/issues/111 [#113]: https://github.com/GIScience/ohsome-api/issues/113 [#114]: https://github.com/GIScience/ohsome-api/pull/114 diff --git a/src/main/lombok/org/heigit/ohsome/ohsomeapi/executor/DataExtractionTransformer.java b/src/main/lombok/org/heigit/ohsome/ohsomeapi/executor/DataExtractionTransformer.java index 919515f8..39e4d1ba 100644 --- a/src/main/lombok/org/heigit/ohsome/ohsomeapi/executor/DataExtractionTransformer.java +++ b/src/main/lombok/org/heigit/ohsome/ohsomeapi/executor/DataExtractionTransformer.java @@ -7,12 +7,12 @@ import java.util.Map; import java.util.Set; import java.util.TreeMap; -import java.util.function.Supplier; import org.heigit.bigspatialdata.oshdb.api.object.OSMContribution; import org.heigit.bigspatialdata.oshdb.api.object.OSMEntitySnapshot; import org.heigit.bigspatialdata.oshdb.osm.OSMEntity; import org.heigit.bigspatialdata.oshdb.util.celliterator.ContributionType; import org.heigit.bigspatialdata.oshdb.util.time.TimestampFormatter; +import org.heigit.ohsome.filter.FilterExpression; import org.heigit.ohsome.ohsomeapi.controller.dataextraction.elements.ElementsGeometry; import org.heigit.ohsome.ohsomeapi.inputprocessing.InputProcessingUtils; import org.heigit.ohsome.ohsomeapi.inputprocessing.SimpleFeatureType; @@ -28,6 +28,7 @@ public class DataExtractionTransformer implements Serializable { private final String startTimestamp; private final InputProcessingUtils utils; private final Set simpleFeatureTypes; + private final FilterExpression filter; private final Set keysInt; private final boolean includeTags; private final boolean includeOSMMetadata; @@ -38,8 +39,9 @@ public class DataExtractionTransformer implements Serializable { public DataExtractionTransformer(boolean isContributionsLatestEndpoint, boolean isContributionsEndpoint, ExecutionUtils exeUtils, boolean clipGeometries, String startTimestamp, InputProcessingUtils utils, - Set simpleFeatureTypes, Set keysInt, boolean includeTags, - boolean includeOSMMetadata, ElementsGeometry elementsGeometry, String endTimestamp, + Set simpleFeatureTypes, FilterExpression filter, + Set keysInt, boolean includeTags, boolean includeOSMMetadata, + ElementsGeometry elementsGeometry, String endTimestamp, boolean isContainingSimpleFeatureTypes) { this.isContributionsLatestEndpoint = isContributionsLatestEndpoint; this.isContributionsEndpoint = isContributionsEndpoint; @@ -48,6 +50,7 @@ public DataExtractionTransformer(boolean isContributionsLatestEndpoint, this.startTimestamp = startTimestamp; this.utils = utils; this.simpleFeatureTypes = simpleFeatureTypes; + this.filter = filter; this.keysInt = keysInt; this.includeTags = includeTags; this.includeOSMMetadata = includeOSMMetadata; @@ -90,9 +93,7 @@ public List buildChangedFeatures(List contributions) { // set valid_to of previous row validTo = TimestampFormatter.getInstance().isoDateTime(contribution.getTimestamp()); if (!skipNext && currentGeom != null && !currentGeom.isEmpty()) { - final Geometry geomToCheck = currentGeom; - boolean addToOutput = addEntityToOutput(isContainingSimpleFeatureTypes, utils, - simpleFeatureTypes, () -> geomToCheck); + boolean addToOutput = addEntityToOutput(currentEntity, currentGeom); if (addToOutput) { properties = new TreeMap<>(); if (!isContributionsEndpoint) { @@ -134,9 +135,7 @@ public List buildChangedFeatures(List contributions) { TimestampFormatter.getInstance().isoDateTime(lastContribution.getTimestamp())); } if (!currentGeom.isEmpty()) { - final Geometry geomToCheck = currentGeom; - boolean addToOutput = addEntityToOutput(isContainingSimpleFeatureTypes, utils, - simpleFeatureTypes, () -> geomToCheck); + boolean addToOutput = addEntityToOutput(currentEntity, currentGeom); if (addToOutput) { output.add(exeUtils.createOSMFeature(currentEntity, currentGeom, properties, keysInt, includeTags, includeOSMMetadata, isContributionsEndpoint, elementsGeometry, @@ -162,21 +161,20 @@ public List buildUnchangedFeatures(OSMEntitySnapshot snapshot) { if (includeOSMMetadata) { properties.put("@lastEdit", entity.getTimestamp().toString()); } - Supplier geom; + Geometry geom; if (clipGeometries) { - geom = snapshot::getGeometry; + geom = snapshot.getGeometry(); } else { - geom = snapshot::getGeometryUnclipped; + geom = snapshot.getGeometryUnclipped(); } properties.put("@snapshotTimestamp", TimestampFormatter.getInstance().isoDateTime(snapshot.getTimestamp())); properties.put("@validFrom", startTimestamp); properties.put("@validTo", endTimestamp); - boolean addToOutput = addEntityToOutput(isContainingSimpleFeatureTypes, utils, - simpleFeatureTypes, geom); + boolean addToOutput = addEntityToOutput(entity, geom); if (addToOutput) { return Collections.singletonList( - exeUtils.createOSMFeature(entity, geom.get(), properties, keysInt, includeTags, + exeUtils.createOSMFeature(entity, geom, properties, keysInt, includeTags, includeOSMMetadata, isContributionsEndpoint, elementsGeometry, null)); } else { return Collections.emptyList(); @@ -184,17 +182,11 @@ public List buildUnchangedFeatures(OSMEntitySnapshot snapshot) { } /** Checks whether the given entity should be added to the output (true) or not (false). */ - public static boolean addEntityToOutput( - boolean isContainingSimpleFeatureTypes, - InputProcessingUtils utils, - final Set simpleFeatureTypes, - Supplier currentGeom) { - boolean addToOutput; + public boolean addEntityToOutput(OSMEntity currentEntity, Geometry currentGeom) { if (isContainingSimpleFeatureTypes) { - addToOutput = utils.checkGeometryOnSimpleFeatures(currentGeom.get(), simpleFeatureTypes); + return utils.checkGeometryOnSimpleFeatures(currentGeom, simpleFeatureTypes); } else { - addToOutput = true; + return filter == null || filter.applyOSMGeometry(currentEntity, currentGeom); } - return addToOutput; } } diff --git a/src/main/lombok/org/heigit/ohsome/ohsomeapi/executor/DataRequestExecutor.java b/src/main/lombok/org/heigit/ohsome/ohsomeapi/executor/DataRequestExecutor.java index 44442b01..8276f221 100644 --- a/src/main/lombok/org/heigit/ohsome/ohsomeapi/executor/DataRequestExecutor.java +++ b/src/main/lombok/org/heigit/ohsome/ohsomeapi/executor/DataRequestExecutor.java @@ -110,8 +110,8 @@ public void extract() throws Exception { final boolean isContainingSimpleFeatureTypes = processingData.isContainingSimpleFeatureTypes(); DataExtractionTransformer dataExtractionTransformer = new DataExtractionTransformer( isContributionsLatestEndpoint, isContributionsEndpoint, exeUtils, clipGeometries, - startTimestamp, utils, simpleFeatureTypes, keysInt, includeTags, includeOSMMetadata, - elementsGeometry, endTimestamp, isContainingSimpleFeatureTypes); + startTimestamp, utils, simpleFeatureTypes, filter.orElse(null), keysInt, includeTags, + includeOSMMetadata, elementsGeometry, endTimestamp, isContainingSimpleFeatureTypes); MapReducer contributionPreResult = mapRedContributions .flatMap(dataExtractionTransformer::buildChangedFeatures) .filter(Objects::nonNull); diff --git a/src/test/java/org/heigit/ohsome/ohsomeapi/controller/DataExtractionTest.java b/src/test/java/org/heigit/ohsome/ohsomeapi/controller/DataExtractionTest.java index ad71f8f2..6b496363 100644 --- a/src/test/java/org/heigit/ohsome/ohsomeapi/controller/DataExtractionTest.java +++ b/src/test/java/org/heigit/ohsome/ohsomeapi/controller/DataExtractionTest.java @@ -426,7 +426,7 @@ public void contributionsVersionTest() { } @Test - public void contributionsAssociationChangeSetIdWithOsmIdAndVersion() { + public void contributionsAssociationChangeSetIdWithOsmIdAndVersionTest() { TestRestTemplate restTemplate = new TestRestTemplate(); ResponseEntity response = restTemplate.getForEntity(server + port + "/contributions/bbox?bboxes=8.70606,49.412150,8.70766,49.413686" @@ -515,4 +515,18 @@ public void contributionsLatestCreationTest() { assertTrue( response.getBody().get("features").get(0).get("properties").get("@creation").asBoolean()); } + + @Test + public void issue109Test() { + // see https://github.com/GIScience/ohsome-api/issues/109 + TestRestTemplate restTemplate = new TestRestTemplate(); + // this uses the centroid endpoint to make sure that geometry filters are even applied to + // the geometries before being transformed to, e.g., centroid points + ResponseEntity response = restTemplate.getForEntity( + server + port + + "/elementsFullHistory/centroid?bboxes=8.69525,49.40938,8.70461,49.41203&" + + "time=2011-09-05,2011-09-06&filter=geometry:polygon and id:relation/1391838", + JsonNode.class); + assertEquals(1, response.getBody().get("features").size()); + } } diff --git a/src/test/java/org/heigit/ohsome/ohsomeapi/controller/GetControllerTest.java b/src/test/java/org/heigit/ohsome/ohsomeapi/controller/GetControllerTest.java index ed247eda..decf45a6 100644 --- a/src/test/java/org/heigit/ohsome/ohsomeapi/controller/GetControllerTest.java +++ b/src/test/java/org/heigit/ohsome/ohsomeapi/controller/GetControllerTest.java @@ -1238,7 +1238,7 @@ public void getOrFilterTest() { } @Test - public void getRequestEndsByQuestionMark() { + public void getRequestEndsByQuestionMarkTest() { TestRestTemplate restTemplate = new TestRestTemplate(); ResponseEntity response = restTemplate.getForEntity(server + port + "/users/count?", JsonNode.class); diff --git a/src/test/java/org/heigit/ohsome/ohsomeapi/controller/PostControllerTest.java b/src/test/java/org/heigit/ohsome/ohsomeapi/controller/PostControllerTest.java index 3aa97b85..9bcc7fe7 100644 --- a/src/test/java/org/heigit/ohsome/ohsomeapi/controller/PostControllerTest.java +++ b/src/test/java/org/heigit/ohsome/ohsomeapi/controller/PostControllerTest.java @@ -1129,7 +1129,7 @@ public void postUmlautFilterTest() { } @Test - public void postQueryRequestEndsByQuestionMark() { + public void postQueryRequestEndsByQuestionMarkTest() { TestRestTemplate restTemplate = new TestRestTemplate(); MultiValueMap map = new LinkedMultiValueMap<>(); ResponseEntity response =