From 4d3bf2ed4277bdfc46c1ffdbb575edf6bb7d4f62 Mon Sep 17 00:00:00 2001 From: Martin Raifer Date: Tue, 27 Nov 2018 19:31:03 +0100 Subject: [PATCH] fix some issues with full history output also slightly leaner implementation with less special cases --- .../executor/ElementsRequestExecutor.java | 94 +++++++++---------- .../ohsomeapi/executor/ExecutionUtils.java | 43 +++++++++ 2 files changed, 90 insertions(+), 47 deletions(-) diff --git a/src/main/java/org/heigit/bigspatialdata/ohsome/ohsomeapi/executor/ElementsRequestExecutor.java b/src/main/java/org/heigit/bigspatialdata/ohsome/ohsomeapi/executor/ElementsRequestExecutor.java index c9ee3627..2b8dfc4d 100644 --- a/src/main/java/org/heigit/bigspatialdata/ohsome/ohsomeapi/executor/ElementsRequestExecutor.java +++ b/src/main/java/org/heigit/bigspatialdata/ohsome/ohsomeapi/executor/ElementsRequestExecutor.java @@ -259,64 +259,64 @@ public static void executeElementsFullHistory(RequestParameters contributionRequ String endTimestamp = endTimestampWithZ.substring(0, endTimestampWithZ.length() - 1); contributionPreResult = mapRedContribution.groupByEntity().flatMap(contributions -> { - Map properties = new TreeMap<>(); List output = new LinkedList<>(); - int startIndex = 1; + + Map properties; + Geometry currentGeom = null; + OSMEntity currentEntity = null; + String validFrom = null; + String validTo; + boolean skipNext = false; + // first contribution: - // if not "creation": take "before" as starting "row" (geom, tags), validFrom = t_start - if (!contributions.get(0).getContributionTypes().contains(ContributionType.CREATION)) { - properties.put("validFrom", startTimestamp); + if (contributions.get(0).is(ContributionType.CREATION)) { + // if creation: skip next output + skipNext = true; } else { - // if creation - properties.put("validFrom", contributions.get(0).getTimestamp().toString()); - if (contributions.size() == 1) { - // use latest timestamp from input parameter for validTo - properties.put("validTo", endTimestamp); - output.add(exeUtils.createOSMDataFeature(keys, values, mapTagTranslator.get(), keysInt, - valuesInt, contributions.get(0), false, properties, gjw, includeTags, - includeOSMMetadata, elemGeom)); - properties = new TreeMap<>(); - return output; - } else { - // use timestamp of contribution 2 for validTo - properties.put("validTo", contributions.get(1).getTimestamp().toString()); - output.add(exeUtils.createOSMDataFeature(keys, values, mapTagTranslator.get(), keysInt, - valuesInt, contributions.get(0), false, properties, gjw, includeTags, - includeOSMMetadata, elemGeom)); + // if not "creation": take "before" as starting "row" (geom, tags), valid_from = t_start + currentEntity = contributions.get(0).getEntityBefore(); + currentGeom = contributions.get(0).getGeometryBefore(); + validFrom = startTimestamp; + } + + // then for each contribution: + for (OSMContribution contribution : contributions) { + // set valid_to of previous row, add to output list (output.add(…)) + validTo = contribution.getTimestamp().toString(); + if (!skipNext) { properties = new TreeMap<>(); + properties.put("validFrom", validFrom); + properties.put("validTo", validTo); + output.add(exeUtils.createOSMFeature( + currentEntity, currentGeom, properties, + keysInt, includeTags, includeOSMMetadata, elemGeom, mapTagTranslator.get(), gjw + )); } - if (!contributions.get(1).getContributionTypes().contains(ContributionType.DELETION)) { - properties.put("validFrom", contributions.get(1).getTimestamp().toString()); - } - // to skip the 2nd contribution in the following loop - startIndex = 2; - } - for (int i = startIndex; i < contributions.size(); i++) { - // for each contribution: - // set valid_to of previous row, add to output list (output.add(…)) - properties.put("validTo", contributions.get(i).getTimestamp().toString()); - output.add(exeUtils.createOSMDataFeature(keys, values, mapTagTranslator.get(), keysInt, - valuesInt, contributions.get(i), false, properties, gjw, includeTags, - includeOSMMetadata, elemGeom)); - properties = new TreeMap<>(); - // if deletion: skip output of next row - if (contributions.get(i).getContributionTypes().contains(ContributionType.DELETION)) { - i++; + skipNext = false; + if (contribution.is(ContributionType.DELETION)) { + // if deletion: skip output of next row + skipNext = true; } else { - // else: take "after" as next row - properties.put("validFrom", contributions.get(i).getTimestamp().toString()); + // else: take "after" as next row + currentEntity = contribution.getEntityAfter(); + currentGeom = contribution.getGeometryAfter(); + validFrom = contribution.getTimestamp().toString(); } } + // after loop: - // if last contribution was not "deletion": set valid_to = t_end, add row to output list - if (!contributions.get(contributions.size() - 1).getContributionTypes() - .contains(ContributionType.DELETION)) { - properties.put("validTo", endTimestamp); - output.add(exeUtils.createOSMDataFeature(keys, values, mapTagTranslator.get(), keysInt, - valuesInt, contributions.get(contributions.size() - 1), false, properties, gjw, - includeTags, includeOSMMetadata, elemGeom)); + if (!contributions.get(contributions.size()-1).is(ContributionType.DELETION)) { + // if last contribution was not "deletion": set valid_to = t_end, add row to output list + validTo = endTimestamp; properties = new TreeMap<>(); + properties.put("validFrom", validFrom); + properties.put("validTo", validTo); + output.add(exeUtils.createOSMFeature( + currentEntity, currentGeom, properties, + keysInt, includeTags, includeOSMMetadata, elemGeom, mapTagTranslator.get(), gjw + )); } + return output; }); diff --git a/src/main/java/org/heigit/bigspatialdata/ohsome/ohsomeapi/executor/ExecutionUtils.java b/src/main/java/org/heigit/bigspatialdata/ohsome/ohsomeapi/executor/ExecutionUtils.java index 790c1524..1c085aa6 100644 --- a/src/main/java/org/heigit/bigspatialdata/ohsome/ohsomeapi/executor/ExecutionUtils.java +++ b/src/main/java/org/heigit/bigspatialdata/ohsome/ohsomeapi/executor/ExecutionUtils.java @@ -304,6 +304,49 @@ public org.wololo.geojson.Feature createOSMDataFeature(String[] keys, String[] v } } + /** Creates the Feature objects in the OSM data response. */ + public org.wololo.geojson.Feature createOSMFeature(OSMEntity entity, + Geometry geometry, Map properties, int[] keysInt, + boolean includeTags, boolean includeOSMMetadata, ElementsGeometry elemGeom, + TagTranslator tt, GeoJSONWriter gjw) { + properties.put("osmId", entity.getType().toString().toLowerCase() + "/" + entity.getId()); + if (includeOSMMetadata) { + properties.put("version", entity.getVersion()); + properties.put("osmType", entity.getType()); + properties.put("changesetId", entity.getChangeset()); + } + if (includeTags) { + for (OSHDBTag oshdbTag : entity.getTags()) { + OSMTag tag = tt.getOSMTagOf(oshdbTag); + properties.put(tag.getKey(), tag.getValue()); + } + } else if (keysInt != null && keysInt.length != 0) { + int[] tags = entity.getRawTags(); + for (int i = 0; i < tags.length; i += 2) { + int tagKeyId = tags[i]; + int tagValueId = tags[i + 1]; + for (int key : keysInt) { + if (tagKeyId == key) { + OSMTag tag = tt.getOSMTagOf(tagKeyId, tagValueId); + properties.put(tag.getKey(), tag.getValue()); + } + } + } + } + switch (elemGeom) { + case BBOX: + Envelope envelope = geometry.getEnvelopeInternal(); + OSHDBBoundingBox bbox = OSHDBGeometryBuilder.boundingBoxOf(envelope); + return new org.wololo.geojson.Feature(gjw.write(OSHDBGeometryBuilder.getGeometry(bbox)), + properties); + case CENTROID: + return new org.wololo.geojson.Feature(gjw.write(geometry.getCentroid()), properties); + case RAW: + default: + return new org.wololo.geojson.Feature(gjw.write(geometry), properties); + } + } + /** Computes the result for the /count|length|perimeter|area/groupBy/boundary resources. */ @SuppressWarnings({"unchecked"}) // intentionally as check for P on Polygonal is already performed public

SortedMap, ? extends Number> computeCountLengthPerimeterAreaGbB(