Skip to content

Commit

Permalink
improve osmCreateFeature tag handling
Browse files Browse the repository at this point in the history
manually squash of the following commits:
* 3c4c5b6
* a240374
* 42cc9fb
* 8b20332
* ff09be4
* ec431a3
* 7bc17e6
* d431854
* 7cba1d7
* 518151b

and a few additional changes:
* mention tag key escaping in docs
* add to changelog

fixes #40
  • Loading branch information
rtroilo authored and tyrasd committed Jan 8, 2021
1 parent 96fc156 commit 4a7e393
Show file tree
Hide file tree
Showing 6 changed files with 43 additions and 42 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
## current master

* data extraction: escape tags with `@` characters ([#40](https://github.com/GIScience/ohsome-api/issues/40))

## 1.2.3

### Bug Fixes
Expand Down
7 changes: 7 additions & 0 deletions docs/response-parameters.rst
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,13 @@ Description of parameters that are present in every response.
* ``attribution`` - copyrights and attribution
* ``apiVersion`` - version of the ohsome API

OSM Tags
--------

When requested, the result will contain OSM elements' tags as individual GeoJSON properties.

.. note:: Any OSM tag with a key starting with the special `@` character (e.g.: `@osmId`), will be modified through the addition of another `@` at the start (the example would be changed to `@@osmId`).

Aggregation Parameters
----------------------

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,12 +83,7 @@ public void extract() throws Exception {
}
TagTranslator tt = DbConnData.tagTranslator;
String[] keys = requestParameters.getKeys();
int[] keysInt = new int[keys.length];
if (keys.length != 0) {
for (int i = 0; i < keys.length; i++) {
keysInt[i] = tt.getOSHDBTagKeyOf(keys[i]).toInt();
}
}
final Set<Integer> keysInt = ExecutionUtils.keysToKeysInt(keys, tt);
ExecutionUtils exeUtils = new ExecutionUtils(processingData);
inputProcessor.processPropertiesParam();
inputProcessor.processIsUnclippedParam();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.stream.Collectors;
Expand Down Expand Up @@ -108,12 +109,7 @@ public static void extract(RequestResource requestResource, ElementsGeometry ele
RequestParameters requestParameters = processingData.getRequestParameters();
TagTranslator tt = DbConnData.tagTranslator;
String[] keys = requestParameters.getKeys();
int[] keysInt = new int[keys.length];
if (keys.length != 0) {
for (int i = 0; i < keys.length; i++) {
keysInt[i] = tt.getOSHDBTagKeyOf(keys[i]).toInt();
}
}
final Set<Integer> keysInt = ExecutionUtils.keysToKeysInt(keys, tt);
final MapReducer<Feature> preResult;
ExecutionUtils exeUtils = new ExecutionUtils(processingData);
preResult = mapRed.map(snapshot -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
import com.fasterxml.jackson.core.util.DefaultPrettyPrinter;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.google.common.collect.Iterables;
import com.google.common.collect.Streams;
import com.opencsv.CSVWriter;
import com.zaxxer.hikari.HikariDataSource;
import java.io.ByteArrayOutputStream;
Expand All @@ -17,7 +19,9 @@
import java.sql.SQLException;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.util.Collections;
import java.util.EnumSet;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
Expand Down Expand Up @@ -408,29 +412,18 @@ public List<String[]> createCsvTopComments(String url, String text, String apiVe

/** Creates the <code>Feature</code> objects in the OSM data response. */
public org.wololo.geojson.Feature createOSMFeature(OSMEntity entity, Geometry geometry,
Map<String, Object> properties, int[] keysInt, boolean includeTags,
Map<String, Object> properties, Set<Integer> keysInt, boolean includeTags,
boolean includeOSMMetadata, boolean isContributionsEndpoint, ElementsGeometry elemGeom,
EnumSet<ContributionType> contributionTypes) {
if (geometry.isEmpty() && !contributionTypes.contains(ContributionType.DELETION)) {
// skip invalid geometries (e.g. ways with 0 nodes)
return null;
}
if (includeTags) {
for (OSHDBTag oshdbTag : entity.getTags()) {
properties.put(String.valueOf(oshdbTag.getKey()), oshdbTag);
}
} else if (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) {
properties.put(String.valueOf(tagKeyId), new OSHDBTag(tagKeyId, tagValueId));
break;
}
}
}
properties.put("@tags", Iterables.toArray(entity.getTags(), OSHDBTag.class));
} else if (!keysInt.isEmpty()) {
properties.put("@tags", Streams.stream(entity.getTags())
.filter(t -> keysInt.contains(t.getKey())).toArray(OSHDBTag[]::new));
}
if (includeOSMMetadata) {
properties =
Expand Down Expand Up @@ -912,20 +905,15 @@ private void writeStreamResponse(ThreadLocal<JsonGenerator> outputJsonGen,
try {
threadPool.submit(() -> stream.parallel().map(data -> {
// 0. resolve tags
Map<String, Object> tags = data.getProperties();
List<String> keysToDelete = new LinkedList<>();
List<OSMTag> tagsToAdd = new LinkedList<>();
for (Entry<String, Object> tag : tags.entrySet()) {
String key = tag.getKey();
if (key.charAt(0) != '@') {
keysToDelete.add(key);
tagsToAdd.add(tts.get().getOSMTagOf((OSHDBTag) tag.getValue()));
Map<String, Object> props = data.getProperties();
OSHDBTag[] tags = (OSHDBTag[]) props.remove("@tags");
if (tags != null) {
for (OSHDBTag tag : tags) {
OSMTag osmTag = tts.get().getOSMTagOf(tag);
String key = osmTag.getKey();
props.put(key.startsWith("@") ? "@" + key : key, osmTag.getValue());
}
}
tags.keySet().removeAll(keysToDelete);
for (OSMTag tag : tagsToAdd) {
tags.put(tag.getKey(), tag.getValue());
}
// 1. convert features to geojson
try {
outputBuffers.get().reset();
Expand Down Expand Up @@ -1018,6 +1006,19 @@ private Map<String, Object> addAdditionalProperties(OSMEntity entity,
return properties;
}

static Set<Integer> keysToKeysInt(String[] keys, TagTranslator tt) {
final Set<Integer> keysInt;
if (keys.length != 0) {
keysInt = new HashSet<>(keys.length);
for (int i = 0; i < keys.length; i++) {
keysInt.add(tt.getOSHDBTagKeyOf(keys[i]).toInt());
}
} else {
keysInt = Collections.emptySet();
}
return keysInt;
}

/** Enum type used in /ratio computation. */
public enum MatchType {
MATCHES1, MATCHES2, MATCHESBOTH, MATCHESNONE
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public class FlatMapExecutor implements Serializable {
private final Set<SimpleFeatureType> simpleFeatureTypes;
private final boolean requiresGeometryTypeCheck;
private final FilterExpression filterExpression;
private final int[] keysInt;
private final Set<Integer> keysInt;
private final boolean includeTags;
private final boolean includeOSMMetadata;
private final ElementsGeometry elementsGeometry;
Expand All @@ -41,7 +41,7 @@ public FlatMapExecutor(boolean isContributionsLatestEndpoint, boolean isContribu
ExecutionUtils exeUtils, boolean clipGeometries, String startTimestamp,
InputProcessingUtils utils,
Set<SimpleFeatureType> simpleFeatureTypes, boolean requiresGeometryTypeCheck,
FilterExpression filterExpression, int[] keysInt, boolean includeTags,
FilterExpression filterExpression, Set<Integer> keysInt, boolean includeTags,
boolean includeOSMMetadata,
ElementsGeometry elementsGeometry, String endTimestamp,
boolean isContainingSimpleFeatureTypes) {
Expand Down

0 comments on commit 4a7e393

Please sign in to comment.