From b23eef23020fddf99c507f46dc6145657eb008f4 Mon Sep 17 00:00:00 2001 From: Taylor Smock Date: Wed, 20 May 2020 10:41:08 -0600 Subject: [PATCH] Add method to remove empty keys/tags Signed-off-by: Taylor Smock --- .../mapwithai/backend/GetDataRunnable.java | 58 +++++++++++++++++++ .../backend/MapWithAIRemoteControlTest.java | 4 +- 2 files changed, 60 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/openstreetmap/josm/plugins/mapwithai/backend/GetDataRunnable.java b/src/main/java/org/openstreetmap/josm/plugins/mapwithai/backend/GetDataRunnable.java index c0beb82..ea3e24c 100644 --- a/src/main/java/org/openstreetmap/josm/plugins/mapwithai/backend/GetDataRunnable.java +++ b/src/main/java/org/openstreetmap/josm/plugins/mapwithai/backend/GetDataRunnable.java @@ -23,6 +23,7 @@ import org.openstreetmap.josm.data.Bounds; import org.openstreetmap.josm.data.osm.AbstractPrimitive; import org.openstreetmap.josm.data.osm.BBox; import org.openstreetmap.josm.data.osm.DataSet; +import org.openstreetmap.josm.data.osm.IPrimitive; import org.openstreetmap.josm.data.osm.Node; import org.openstreetmap.josm.data.osm.OsmPrimitive; import org.openstreetmap.josm.data.osm.Relation; @@ -142,6 +143,7 @@ public class GetDataRunnable extends RecursiveTask { private static synchronized void realCleanup(DataSet dataSet, Bounds bounds) { replaceTags(dataSet); removeCommonTags(dataSet); + removeEmptyTags(dataSet, bounds); mergeNodes(dataSet); cleanupDataSet(dataSet); mergeWays(dataSet); @@ -151,6 +153,38 @@ public class GetDataRunnable extends RecursiveTask { .filter(way -> !way.isDeleted()).forEach(GetDataRunnable::cleanupArtifacts); } + /** + * Remove empty tags from primitives + * + * @param dataSet The dataset to remove tags from + * @param bounds The bounds to remove the empty tags from (performance) + */ + public static void removeEmptyTags(DataSet dataSet, Bounds bounds) { + if (bounds == null && !dataSet.getDataSourceBounds().isEmpty()) { + bounds = dataSet.getDataSourceBounds().get(0); + dataSet.getDataSourceBounds().forEach(bounds::extend); + } else if (bounds == null) { + bounds = new Bounds(-90, -180, 90, 180); + } + dataSet.searchPrimitives(bounds.toBBox()).forEach(GetDataRunnable::realRemoveEmptyTags); + } + + /** + * Remove empty tags from primitives. We assume that the `getKey` implementation + * returns a new map. + * + * @param prim The primitive to remove empty tags from. + */ + private static void realRemoveEmptyTags(IPrimitive prim) { + Map keys = prim.getKeys(); + for (Map.Entry entry : keys.entrySet()) { + if (entry.getValue() == null || entry.getValue().trim().isEmpty()) { + // The OsmPrimitives all return a new map, so this is safe. + prim.remove(entry.getKey()); + } + } + } + /** * Remove ways that have already been added to an OSM layer * @@ -227,6 +261,30 @@ public class GetDataRunnable extends RecursiveTask { final Map replaceTags = MapWithAIPreferenceHelper.getReplacementTags().entrySet().parallelStream() .map(entry -> new Pair<>(Tag.ofString(entry.getKey()), Tag.ofString(entry.getValue()))) .collect(Collectors.toMap(pair -> pair.a, pair -> pair.b)); + replaceTags(dataSet, replaceTags); + } + + /** + * Replace tags in a dataset with a set of replacement tags + * + * @param dataSet The dataset with primitives to change + * @param replaceKeys The keys to replace (does not replace values) + */ + public static void replaceKeys(DataSet dataSet, Map replaceKeys) { + replaceKeys.entrySet().stream().filter(e -> !e.getKey().equals(e.getValue())).forEach( + e -> dataSet.allNonDeletedPrimitives().stream().filter(p -> p.hasKey(e.getKey())).forEach(p -> { + p.put(e.getValue(), p.get(e.getKey())); + p.remove(e.getKey()); + })); + } + + /** + * Replace tags in a dataset with a set of replacement tags + * + * @param dataSet The dataset with primitives to change + * @param map The tags to replace + */ + public static void replaceTags(DataSet dataSet, Map replaceTags) { replaceTags.forEach((orig, replace) -> dataSet.allNonDeletedPrimitives().parallelStream() .filter(prim -> prim.hasTag(orig.getKey(), orig.getValue())).forEach(prim -> prim.put(replace))); } diff --git a/test/unit/org/openstreetmap/josm/plugins/mapwithai/backend/MapWithAIRemoteControlTest.java b/test/unit/org/openstreetmap/josm/plugins/mapwithai/backend/MapWithAIRemoteControlTest.java index a8abbf6..53d7e52 100644 --- a/test/unit/org/openstreetmap/josm/plugins/mapwithai/backend/MapWithAIRemoteControlTest.java +++ b/test/unit/org/openstreetmap/josm/plugins/mapwithai/backend/MapWithAIRemoteControlTest.java @@ -109,7 +109,7 @@ public class MapWithAIRemoteControlTest { final Integer maxObj = 1; newHandler("http://127.0.0.1:8111/mapwithai?bbox=" + getTestBBox().toStringCSV(",") + "&max_obj=" + maxObj.toString()).handle(); - Awaitility.await().atMost(Durations.ONE_SECOND) + Awaitility.await().atMost(Durations.TWO_SECONDS) .until(() -> !MainApplication.getLayerManager().getLayersOfType(MapWithAILayer.class).isEmpty()); assertFalse(MainApplication.getLayerManager().getLayersOfType(MapWithAILayer.class).isEmpty()); @@ -128,7 +128,7 @@ public class MapWithAIRemoteControlTest { public void testBBox() throws Exception { BBox temp = getTestBBox(); newHandler("http://127.0.0.1:8111/mapwithai?bbox={bbox}".replace("{bbox}", temp.toStringCSV(","))).handle(); - Awaitility.await().atMost(Durations.ONE_SECOND) + Awaitility.await().atMost(Durations.TWO_SECONDS) .until(() -> !MainApplication.getLayerManager().getLayersOfType(MapWithAILayer.class).isEmpty()); assertFalse(MainApplication.getLayerManager().getLayersOfType(MapWithAILayer.class).isEmpty());