From 16928ca4f27e7d9d744b74bae15bacd28959d238 Mon Sep 17 00:00:00 2001
From: Rafael Troilo
Date: Fri, 16 Jun 2023 15:53:21 +0200
Subject: [PATCH 01/11] adding missing getters
---
.../filter/ChangesetIdFilterEqualsAnyOf.java | 12 +++++-----
.../oshdb/filter/ChangesetIdFilterRange.java | 7 ++++++
.../oshdb/filter/IdFilterEqualsAnyOf.java | 22 ++++++++++++++-----
.../ohsome/oshdb/filter/IdFilterRange.java | 7 ++++++
.../ohsome/oshdb/filter/TagFilterAnyOf.java | 21 ++++++++++++------
5 files changed, 52 insertions(+), 17 deletions(-)
diff --git a/oshdb-filter/src/main/java/org/heigit/ohsome/oshdb/filter/ChangesetIdFilterEqualsAnyOf.java b/oshdb-filter/src/main/java/org/heigit/ohsome/oshdb/filter/ChangesetIdFilterEqualsAnyOf.java
index 76feb9201..914ec30b1 100644
--- a/oshdb-filter/src/main/java/org/heigit/ohsome/oshdb/filter/ChangesetIdFilterEqualsAnyOf.java
+++ b/oshdb-filter/src/main/java/org/heigit/ohsome/oshdb/filter/ChangesetIdFilterEqualsAnyOf.java
@@ -14,11 +14,13 @@
* A filter which selects OSM contributions by matching to a list of changeset ids.
*/
public class ChangesetIdFilterEqualsAnyOf extends NegatableFilter {
- private final Collection changesetIdList;
+ private final Collection changesetIds;
ChangesetIdFilterEqualsAnyOf(@Nonnull Collection changesetIdList) {
+ this(new HashSet<>(changesetIdList));
+ }
+ ChangesetIdFilterEqualsAnyOf(@Nonnull Set changesetIds) {
super(new FilterInternal() {
- private final Set changesetIds = new HashSet<>(changesetIdList);
@Override
public boolean applyOSH(OSHEntity entity) {
@@ -37,15 +39,15 @@ public boolean applyOSMEntitySnapshot(OSMEntitySnapshot ignored) {
@Override
public String toString() {
- return "changeset:in(" + changesetIdList.stream().map(String::valueOf)
+ return "changeset:in(" + changesetIds.stream().map(String::valueOf)
.collect(Collectors.joining(",")) + ")";
}
});
- this.changesetIdList = changesetIdList;
+ this.changesetIds = changesetIds;
}
@Contract(pure = true)
public Collection getChangesetIdList() {
- return this.changesetIdList;
+ return this.changesetIds;
}
}
diff --git a/oshdb-filter/src/main/java/org/heigit/ohsome/oshdb/filter/ChangesetIdFilterRange.java b/oshdb-filter/src/main/java/org/heigit/ohsome/oshdb/filter/ChangesetIdFilterRange.java
index 9b0cfb4fc..672b671c9 100644
--- a/oshdb-filter/src/main/java/org/heigit/ohsome/oshdb/filter/ChangesetIdFilterRange.java
+++ b/oshdb-filter/src/main/java/org/heigit/ohsome/oshdb/filter/ChangesetIdFilterRange.java
@@ -8,6 +8,8 @@
* A filter which selects OSM contributions by matching to a range of changeset ids.
*/
public class ChangesetIdFilterRange extends NegatableFilter {
+ private final IdRange changesetIdRange;
+
ChangesetIdFilterRange(IdRange changesetIdRange) {
super(new FilterInternal() {
@Override
@@ -30,5 +32,10 @@ public String toString() {
return "changeset:in-range" + changesetIdRange;
}
});
+ this.changesetIdRange = changesetIdRange;
+ }
+
+ public IdRange getChangesetIdRange() {
+ return changesetIdRange;
}
}
diff --git a/oshdb-filter/src/main/java/org/heigit/ohsome/oshdb/filter/IdFilterEqualsAnyOf.java b/oshdb-filter/src/main/java/org/heigit/ohsome/oshdb/filter/IdFilterEqualsAnyOf.java
index 9904b9025..cd3d79b7f 100644
--- a/oshdb-filter/src/main/java/org/heigit/ohsome/oshdb/filter/IdFilterEqualsAnyOf.java
+++ b/oshdb-filter/src/main/java/org/heigit/ohsome/oshdb/filter/IdFilterEqualsAnyOf.java
@@ -12,13 +12,19 @@
* A tag filter which executes a "id [not] in (id1, id2, …)" check.
*/
public class IdFilterEqualsAnyOf extends NegatableFilter {
+
+ private final Set ids;
+
IdFilterEqualsAnyOf(@Nonnull Collection idList) {
+ this(new HashSet<>(idList));
+ }
+
+ IdFilterEqualsAnyOf(@Nonnull Set ids) {
super(new FilterInternal() {
- private final Set ids = new HashSet<>(idList);
@Override
public boolean applyOSH(OSHEntity entity) {
- return this.ids.contains(entity.getId());
+ return ids.contains(entity.getId());
}
@Override
@@ -28,7 +34,7 @@ boolean applyOSHNegated(OSHEntity entity) {
@Override
public boolean applyOSM(OSMEntity entity) {
- return this.ids.contains(entity.getId());
+ return ids.contains(entity.getId());
}
@Override
@@ -38,12 +44,18 @@ boolean applyOSMNegated(OSMEntity entity) {
@Override
public String toString() {
- return "id:in" + this.ids.stream().map(String::valueOf).collect(Collectors.joining(","));
+ return "id:in" + ids.stream().map(String::valueOf).collect(Collectors.joining(","));
}
});
- if (idList.isEmpty()) {
+ if (ids.isEmpty()) {
throw new IllegalStateException("list of ids must not be empty in a id in (list) filter");
}
+
+ this.ids = ids;
+ }
+
+ public Set getIds() {
+ return ids;
}
}
\ No newline at end of file
diff --git a/oshdb-filter/src/main/java/org/heigit/ohsome/oshdb/filter/IdFilterRange.java b/oshdb-filter/src/main/java/org/heigit/ohsome/oshdb/filter/IdFilterRange.java
index ac332e888..3ff4679ae 100644
--- a/oshdb-filter/src/main/java/org/heigit/ohsome/oshdb/filter/IdFilterRange.java
+++ b/oshdb-filter/src/main/java/org/heigit/ohsome/oshdb/filter/IdFilterRange.java
@@ -8,6 +8,8 @@
* A filter which executes a "id [not] in range" check.
*/
public class IdFilterRange extends NegatableFilter {
+ private final IdRange range;
+
IdFilterRange(@Nonnull IdRange range) {
super(new FilterInternal() {
@Override
@@ -35,5 +37,10 @@ public String toString() {
return "id:in-range" + range;
}
});
+ this.range = range;
+ }
+
+ public IdRange getRange() {
+ return range;
}
}
\ No newline at end of file
diff --git a/oshdb-filter/src/main/java/org/heigit/ohsome/oshdb/filter/TagFilterAnyOf.java b/oshdb-filter/src/main/java/org/heigit/ohsome/oshdb/filter/TagFilterAnyOf.java
index 954522351..b57d04bc5 100644
--- a/oshdb-filter/src/main/java/org/heigit/ohsome/oshdb/filter/TagFilterAnyOf.java
+++ b/oshdb-filter/src/main/java/org/heigit/ohsome/oshdb/filter/TagFilterAnyOf.java
@@ -12,19 +12,26 @@
*/
abstract class TagFilterAnyOf implements Filter {
final int keyId;
- final Set tags;
+ final HashSet tags;
TagFilterAnyOf(@Nonnull Collection tags) {
Optional firstTag = tags.stream().findFirst();
- if (!firstTag.isPresent()) {
- throw new IllegalStateException("list of tags must not be empty in a key in (values) filter");
- } else {
- this.keyId = firstTag.get().getKey();
- this.tags = new HashSet<>(tags);
- }
+ this.keyId = firstTag
+ .orElseThrow(() -> new IllegalStateException("list of tags must not be empty in a key in (values) filter"))
+ .getKey();
+ this.tags = new HashSet<>(tags);
+
if (!tags.stream().allMatch(tag -> tag.getKey() == this.keyId)) {
throw new IllegalStateException(
"list of tags must all share the same tag key in a key in (values) filter");
}
}
+
+ public int getKeyId() {
+ return keyId;
+ }
+
+ public Set getTags() {
+ return tags;
+ }
}
From 514a5cc525587880158f2c3f9b6dbf940e955a08 Mon Sep 17 00:00:00 2001
From: Rafael Troilo
Date: Fri, 16 Jun 2023 15:55:23 +0200
Subject: [PATCH 02/11] minor fixes and changes for java 17 new features
---
.../ohsome/oshdb/filter/FilterExpression.java | 20 +++++++++----------
1 file changed, 10 insertions(+), 10 deletions(-)
diff --git a/oshdb-filter/src/main/java/org/heigit/ohsome/oshdb/filter/FilterExpression.java b/oshdb-filter/src/main/java/org/heigit/ohsome/oshdb/filter/FilterExpression.java
index c1f23c763..bb06b2101 100644
--- a/oshdb-filter/src/main/java/org/heigit/ohsome/oshdb/filter/FilterExpression.java
+++ b/oshdb-filter/src/main/java/org/heigit/ohsome/oshdb/filter/FilterExpression.java
@@ -81,7 +81,7 @@ default boolean applyOSMGeometry(OSMEntity entity, Geometry geometry) {
* Apply a filter to a snapshot ({@link OSMEntitySnapshot}) of an OSM entity.
*
* @param snapshot a snapshot of the OSM entity to check
- * @return true if the the OSM entity snapshot fulfills the specified filter, otherwise false.
+ * @return true if the OSM entity snapshot fulfills the specified filter, otherwise false.
*/
@Contract(pure = true)
default boolean applyOSMEntitySnapshot(OSMEntitySnapshot snapshot) {
@@ -95,7 +95,7 @@ default boolean applyOSMEntitySnapshot(OSMEntitySnapshot snapshot) {
* modification or the state of it after the modification matches the filter.
*
* @param contribution a modification of the OSM entity to check
- * @return true if the the OSM contribution fulfills the specified filter, otherwise false.
+ * @return true if the OSM contribution fulfills the specified filter, otherwise false.
*/
@Contract(pure = true)
default boolean applyOSMContribution(OSMContribution contribution) {
@@ -133,11 +133,11 @@ default boolean applyOSMContribution(OSMContribution contribution) {
*/
@Contract(pure = true)
default List> normalize() {
- if (this instanceof Filter) {
- return Collections.singletonList(Collections.singletonList((Filter) this));
- } else if (this instanceof AndOperator) {
- List> exp1 = ((BinaryOperator) this).getLeftOperand().normalize();
- List> exp2 = ((BinaryOperator) this).getRightOperand().normalize();
+ if (this instanceof Filter filter) {
+ return Collections.singletonList(Collections.singletonList(filter));
+ } else if (this instanceof AndOperator operator) {
+ List> exp1 = operator.getLeftOperand().normalize();
+ List> exp2 = operator.getRightOperand().normalize();
// return cross product of exp1 and exp2
List> combined = new LinkedList<>();
for (List e1 : exp1) {
@@ -149,9 +149,9 @@ default List> normalize() {
}
}
return combined;
- } else if (this instanceof OrOperator) {
- List> exp1 = ((BinaryOperator) this).getLeftOperand().normalize();
- List> exp2 = ((BinaryOperator) this).getRightOperand().normalize();
+ } else if (this instanceof OrOperator operator) {
+ List> exp1 = operator.getLeftOperand().normalize();
+ List> exp2 = operator.getRightOperand().normalize();
List> combined = new ArrayList<>(exp1.size() + exp2.size());
combined.addAll(exp1);
combined.addAll(exp2);
From b6421235b015850736746ba3bb7795ebda9625e0 Mon Sep 17 00:00:00 2001
From: Rafael Troilo
Date: Fri, 16 Jun 2023 16:50:06 +0200
Subject: [PATCH 03/11] generate stream from IdRange
---
.../main/java/org/heigit/ohsome/oshdb/filter/IdRange.java | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/oshdb-filter/src/main/java/org/heigit/ohsome/oshdb/filter/IdRange.java b/oshdb-filter/src/main/java/org/heigit/ohsome/oshdb/filter/IdRange.java
index 4efc8b4f5..de10c7bda 100644
--- a/oshdb-filter/src/main/java/org/heigit/ohsome/oshdb/filter/IdRange.java
+++ b/oshdb-filter/src/main/java/org/heigit/ohsome/oshdb/filter/IdRange.java
@@ -1,6 +1,7 @@
package org.heigit.ohsome.oshdb.filter;
import java.io.Serializable;
+import java.util.stream.LongStream;
/**
* Helper class to handle ranges of ids (incl. user ids, changeset ids, etc.).
@@ -34,4 +35,8 @@ public String toString() {
+ ".."
+ (toId == Long.MAX_VALUE ? "" : toId);
}
+
+ public LongStream getIds() {
+ return LongStream.range(fromId, toId+1);
+ }
}
From 4a9580a4438d180f425a79dc1cb2da779746a894 Mon Sep 17 00:00:00 2001
From: Rafael Troilo
Date: Fri, 16 Jun 2023 16:51:04 +0200
Subject: [PATCH 04/11] new FilterUtil for extraction of ids from expression
---
.../ohsome/oshdb/filter/FilterUtil.java | 36 +++++++++++++++++++
1 file changed, 36 insertions(+)
create mode 100644 oshdb-filter/src/main/java/org/heigit/ohsome/oshdb/filter/FilterUtil.java
diff --git a/oshdb-filter/src/main/java/org/heigit/ohsome/oshdb/filter/FilterUtil.java b/oshdb-filter/src/main/java/org/heigit/ohsome/oshdb/filter/FilterUtil.java
new file mode 100644
index 000000000..4d5d58a01
--- /dev/null
+++ b/oshdb-filter/src/main/java/org/heigit/ohsome/oshdb/filter/FilterUtil.java
@@ -0,0 +1,36 @@
+package org.heigit.ohsome.oshdb.filter;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+public class FilterUtil {
+
+ private FilterUtil() {
+ // utility class
+ }
+
+ public static Set ids(FilterExpression expression) {
+ var normalized = expression.normalize();
+ return ids(normalized);
+ }
+
+ private static Set ids(List> normalized) {
+ var ids = new HashSet();
+ for (var orGroups : normalized) {
+ for (var filter: orGroups) {
+ if (filter instanceof IdFilterEquals equals){
+ ids.add(equals.getId());
+ } else if (filter instanceof IdFilterEqualsAnyOf equalsAnyOf) {
+ ids.addAll(equalsAnyOf.getIds());
+ } else if (filter instanceof IdFilterRange range) {
+ range.getRange().getIds().forEach(ids::add);
+ } else {
+ return Collections.emptySet();
+ }
+ }
+ }
+ return ids;
+ }
+}
From 6d83b248010e2ae01f3e68ebdf7cacc4b6bb372c Mon Sep 17 00:00:00 2001
From: Rafael Troilo
Date: Fri, 16 Jun 2023 17:09:20 +0200
Subject: [PATCH 05/11] new FilterUtil for extraction of ids from expression
---
.../ohsome/oshdb/filter/FilterUtil.java | 21 +++++++------
.../ohsome/oshdb/filter/FilterUtilTest.java | 30 +++++++++++++++++++
2 files changed, 42 insertions(+), 9 deletions(-)
create mode 100644 oshdb-filter/src/test/java/org/heigit/ohsome/oshdb/filter/FilterUtilTest.java
diff --git a/oshdb-filter/src/main/java/org/heigit/ohsome/oshdb/filter/FilterUtil.java b/oshdb-filter/src/main/java/org/heigit/ohsome/oshdb/filter/FilterUtil.java
index 4d5d58a01..43aac13a2 100644
--- a/oshdb-filter/src/main/java/org/heigit/ohsome/oshdb/filter/FilterUtil.java
+++ b/oshdb-filter/src/main/java/org/heigit/ohsome/oshdb/filter/FilterUtil.java
@@ -1,10 +1,11 @@
package org.heigit.ohsome.oshdb.filter;
-import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
+import static java.util.Collections.emptySet;
+
public class FilterUtil {
private FilterUtil() {
@@ -12,24 +13,26 @@ private FilterUtil() {
}
public static Set ids(FilterExpression expression) {
- var normalized = expression.normalize();
- return ids(normalized);
+ return ids(expression.normalize());
}
- private static Set ids(List> normalized) {
+ public static Set ids(List> normalized) {
var ids = new HashSet();
for (var orGroups : normalized) {
+ var groupIds = new HashSet();
for (var filter: orGroups) {
if (filter instanceof IdFilterEquals equals){
- ids.add(equals.getId());
+ groupIds.add(equals.getId());
} else if (filter instanceof IdFilterEqualsAnyOf equalsAnyOf) {
- ids.addAll(equalsAnyOf.getIds());
+ groupIds.addAll(equalsAnyOf.getIds());
} else if (filter instanceof IdFilterRange range) {
- range.getRange().getIds().forEach(ids::add);
- } else {
- return Collections.emptySet();
+ range.getRange().getIds().forEach(groupIds::add);
}
}
+ if (groupIds.isEmpty()) {
+ return emptySet();
+ }
+ ids.addAll(groupIds);
}
return ids;
}
diff --git a/oshdb-filter/src/test/java/org/heigit/ohsome/oshdb/filter/FilterUtilTest.java b/oshdb-filter/src/test/java/org/heigit/ohsome/oshdb/filter/FilterUtilTest.java
new file mode 100644
index 000000000..bab47b59c
--- /dev/null
+++ b/oshdb-filter/src/test/java/org/heigit/ohsome/oshdb/filter/FilterUtilTest.java
@@ -0,0 +1,30 @@
+package org.heigit.ohsome.oshdb.filter;
+
+import org.junit.jupiter.api.Test;
+
+import java.util.Set;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+class FilterUtilTest extends FilterTest{
+
+ @Test
+ void extractIds() {
+ extractIds("id:123", Set.of(123L));
+ extractIds("id:123 or id:234", Set.of(123L, 234L));
+ extractIds("id:123 and not id:234", Set.of(123L));
+ extractIds("id:123 or name=heigit", Set.of());
+ extractIds("id:(123, 234)", Set.of(123L, 234L));
+ extractIds("id:(123 .. 125)", Set.of(123L, 124L, 125L));
+ }
+
+ private void extractIds(String filter, Set expected) {
+ var expression = parser.parse(filter);
+ var actual = FilterUtil.ids(expression);
+
+ assertEquals(expected.size(), actual.size());
+ assertTrue(expected.containsAll(actual));
+ }
+
+}
\ No newline at end of file
From 4529e568f11e269b762bd4e4fc0bc0e9cad75231 Mon Sep 17 00:00:00 2001
From: Rafael Troilo
Date: Fri, 16 Jun 2023 18:12:03 +0200
Subject: [PATCH 06/11] changes for review
---
.../filter/ChangesetIdFilterEqualsAnyOf.java | 4 +-
.../ohsome/oshdb/filter/FilterUtil.java | 43 +++++++++++++------
.../heigit/ohsome/oshdb/filter/IdRange.java | 33 +++++++++++++-
.../ohsome/oshdb/filter/TagFilterAnyOf.java | 2 +-
.../ohsome/oshdb/filter/FilterUtilTest.java | 17 ++++----
5 files changed, 72 insertions(+), 27 deletions(-)
diff --git a/oshdb-filter/src/main/java/org/heigit/ohsome/oshdb/filter/ChangesetIdFilterEqualsAnyOf.java b/oshdb-filter/src/main/java/org/heigit/ohsome/oshdb/filter/ChangesetIdFilterEqualsAnyOf.java
index 914ec30b1..2b6a62461 100644
--- a/oshdb-filter/src/main/java/org/heigit/ohsome/oshdb/filter/ChangesetIdFilterEqualsAnyOf.java
+++ b/oshdb-filter/src/main/java/org/heigit/ohsome/oshdb/filter/ChangesetIdFilterEqualsAnyOf.java
@@ -14,7 +14,7 @@
* A filter which selects OSM contributions by matching to a list of changeset ids.
*/
public class ChangesetIdFilterEqualsAnyOf extends NegatableFilter {
- private final Collection changesetIds;
+ private final Set changesetIds;
ChangesetIdFilterEqualsAnyOf(@Nonnull Collection changesetIdList) {
this(new HashSet<>(changesetIdList));
@@ -47,7 +47,7 @@ public String toString() {
}
@Contract(pure = true)
- public Collection getChangesetIdList() {
+ public Set getChangesetIdList() {
return this.changesetIds;
}
}
diff --git a/oshdb-filter/src/main/java/org/heigit/ohsome/oshdb/filter/FilterUtil.java b/oshdb-filter/src/main/java/org/heigit/ohsome/oshdb/filter/FilterUtil.java
index 43aac13a2..d0b3ae384 100644
--- a/oshdb-filter/src/main/java/org/heigit/ohsome/oshdb/filter/FilterUtil.java
+++ b/oshdb-filter/src/main/java/org/heigit/ohsome/oshdb/filter/FilterUtil.java
@@ -1,10 +1,10 @@
package org.heigit.ohsome.oshdb.filter;
-import java.util.HashSet;
+import java.util.ArrayList;
import java.util.List;
-import java.util.Set;
-import static java.util.Collections.emptySet;
+import static java.util.Collections.emptyList;
+import static java.util.Comparator.comparingLong;
public class FilterUtil {
@@ -12,28 +12,43 @@ private FilterUtil() {
// utility class
}
- public static Set ids(FilterExpression expression) {
+ public static List ids(FilterExpression expression) {
return ids(expression.normalize());
}
- public static Set ids(List> normalized) {
- var ids = new HashSet();
+ public static List ids(List> normalized) {
+ var ranges = new ArrayList();
for (var orGroups : normalized) {
- var groupIds = new HashSet();
+ var groupRanges = new ArrayList();
for (var filter: orGroups) {
if (filter instanceof IdFilterEquals equals){
- groupIds.add(equals.getId());
+ groupRanges.add(new IdRange(equals.getId()));
} else if (filter instanceof IdFilterEqualsAnyOf equalsAnyOf) {
- groupIds.addAll(equalsAnyOf.getIds());
+ equalsAnyOf.getIds().stream().map(IdRange::new).forEach(groupRanges::add);
} else if (filter instanceof IdFilterRange range) {
- range.getRange().getIds().forEach(groupIds::add);
+ groupRanges.add(range.getRange());
}
}
- if (groupIds.isEmpty()) {
- return emptySet();
+ if (groupRanges.isEmpty()) {
+ return emptyList();
}
- ids.addAll(groupIds);
+ ranges.addAll(groupRanges);
}
- return ids;
+ var compact = new ArrayList(ranges.size());
+
+ ranges.sort(comparingLong(IdRange::getFromId));
+ var itr = ranges.iterator();
+ var range = itr.next();
+ while (itr.hasNext()) {
+ var next = itr.next();
+ if (next.getFromId() <= range.getToId() + 1) {
+ range = new IdRange(range.getFromId(), next.getToId());
+ } else {
+ compact.add(range);
+ range = next;
+ }
+ }
+ compact.add(range);
+ return compact;
}
}
diff --git a/oshdb-filter/src/main/java/org/heigit/ohsome/oshdb/filter/IdRange.java b/oshdb-filter/src/main/java/org/heigit/ohsome/oshdb/filter/IdRange.java
index de10c7bda..bf9d9e296 100644
--- a/oshdb-filter/src/main/java/org/heigit/ohsome/oshdb/filter/IdRange.java
+++ b/oshdb-filter/src/main/java/org/heigit/ohsome/oshdb/filter/IdRange.java
@@ -1,6 +1,7 @@
package org.heigit.ohsome.oshdb.filter;
import java.io.Serializable;
+import java.util.Objects;
import java.util.stream.LongStream;
/**
@@ -9,7 +10,7 @@
* The range's limits are tested inclusively: the range (10..12) would match the values 10,
* 11 and 12, but not 9 or 13 for example.
*/
-class IdRange implements Serializable {
+public class IdRange implements Serializable {
private final long fromId;
private final long toId;
@@ -20,11 +21,15 @@ class IdRange implements Serializable {
* @param fromId lower limit of the range.
* @param toId upper limit of the range.
*/
- IdRange(long fromId, long toId) {
+ public IdRange(long fromId, long toId) {
this.fromId = Math.min(fromId, toId);
this.toId = Math.max(fromId, toId);
}
+ public IdRange(long id) {
+ this(id, id);
+ }
+
/** Checks if the given id falls into the id range. */
public boolean test(long id) {
return id >= fromId && id <= toId;
@@ -36,6 +41,30 @@ public String toString() {
+ (toId == Long.MAX_VALUE ? "" : toId);
}
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof IdRange idRange)) return false;
+ return fromId == idRange.fromId && toId == idRange.toId;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(fromId, toId);
+ }
+
+ public long getFromId() {
+ return fromId;
+ }
+
+ public long getToId() {
+ return toId;
+ }
+
+ public long size() {
+ return 1 + toId - fromId;
+ }
+
public LongStream getIds() {
return LongStream.range(fromId, toId+1);
}
diff --git a/oshdb-filter/src/main/java/org/heigit/ohsome/oshdb/filter/TagFilterAnyOf.java b/oshdb-filter/src/main/java/org/heigit/ohsome/oshdb/filter/TagFilterAnyOf.java
index b57d04bc5..e017bd348 100644
--- a/oshdb-filter/src/main/java/org/heigit/ohsome/oshdb/filter/TagFilterAnyOf.java
+++ b/oshdb-filter/src/main/java/org/heigit/ohsome/oshdb/filter/TagFilterAnyOf.java
@@ -12,7 +12,7 @@
*/
abstract class TagFilterAnyOf implements Filter {
final int keyId;
- final HashSet tags;
+ final Set tags;
TagFilterAnyOf(@Nonnull Collection tags) {
Optional firstTag = tags.stream().findFirst();
diff --git a/oshdb-filter/src/test/java/org/heigit/ohsome/oshdb/filter/FilterUtilTest.java b/oshdb-filter/src/test/java/org/heigit/ohsome/oshdb/filter/FilterUtilTest.java
index bab47b59c..dc6bd73f2 100644
--- a/oshdb-filter/src/test/java/org/heigit/ohsome/oshdb/filter/FilterUtilTest.java
+++ b/oshdb-filter/src/test/java/org/heigit/ohsome/oshdb/filter/FilterUtilTest.java
@@ -2,7 +2,7 @@
import org.junit.jupiter.api.Test;
-import java.util.Set;
+import java.util.List;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
@@ -11,15 +11,16 @@ class FilterUtilTest extends FilterTest{
@Test
void extractIds() {
- extractIds("id:123", Set.of(123L));
- extractIds("id:123 or id:234", Set.of(123L, 234L));
- extractIds("id:123 and not id:234", Set.of(123L));
- extractIds("id:123 or name=heigit", Set.of());
- extractIds("id:(123, 234)", Set.of(123L, 234L));
- extractIds("id:(123 .. 125)", Set.of(123L, 124L, 125L));
+ extractIds("id:123", List.of(new IdRange(123L)));
+ extractIds("id:123 or id:234", List.of(new IdRange(123L), new IdRange(234L)));
+ extractIds("id:123 or id:124", List.of(new IdRange(123L, 124L)));
+ extractIds("id:123 and not id:234", List.of(new IdRange(123L)));
+ extractIds("id:123 or name=heigit", List.of());
+ extractIds("id:(123, 234)", List.of(new IdRange(123L), new IdRange(234L)));
+ extractIds("id:(123 .. 125)", List.of(new IdRange(123L, 125L)));
}
- private void extractIds(String filter, Set expected) {
+ private void extractIds(String filter, List expected) {
var expression = parser.parse(filter);
var actual = FilterUtil.ids(expression);
From bb87c508bae6b76ecf36a2cd495570ecb60205ff Mon Sep 17 00:00:00 2001
From: Rafael Troilo
Date: Mon, 19 Jun 2023 15:05:51 +0200
Subject: [PATCH 07/11] Apply suggestions from code review
Co-authored-by: Martin Raifer
---
.../main/java/org/heigit/ohsome/oshdb/filter/FilterUtil.java | 2 +-
.../src/main/java/org/heigit/ohsome/oshdb/filter/IdRange.java | 1 +
2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/oshdb-filter/src/main/java/org/heigit/ohsome/oshdb/filter/FilterUtil.java b/oshdb-filter/src/main/java/org/heigit/ohsome/oshdb/filter/FilterUtil.java
index d0b3ae384..1a51ab3cc 100644
--- a/oshdb-filter/src/main/java/org/heigit/ohsome/oshdb/filter/FilterUtil.java
+++ b/oshdb-filter/src/main/java/org/heigit/ohsome/oshdb/filter/FilterUtil.java
@@ -9,7 +9,7 @@
public class FilterUtil {
private FilterUtil() {
- // utility class
+ throw new IllegalStateException("utility class");
}
public static List ids(FilterExpression expression) {
diff --git a/oshdb-filter/src/main/java/org/heigit/ohsome/oshdb/filter/IdRange.java b/oshdb-filter/src/main/java/org/heigit/ohsome/oshdb/filter/IdRange.java
index bf9d9e296..fe8b2e7be 100644
--- a/oshdb-filter/src/main/java/org/heigit/ohsome/oshdb/filter/IdRange.java
+++ b/oshdb-filter/src/main/java/org/heigit/ohsome/oshdb/filter/IdRange.java
@@ -65,6 +65,7 @@ public long size() {
return 1 + toId - fromId;
}
+ /** Converts the id range to a stream of consecutive ids. */
public LongStream getIds() {
return LongStream.range(fromId, toId+1);
}
From 9284e1a87fa98449dc017454fdae06c963774134 Mon Sep 17 00:00:00 2001
From: Rafael Troilo
Date: Mon, 19 Jun 2023 15:25:34 +0200
Subject: [PATCH 08/11] add assert for idFilterEqualsAny.getIds()
---
.../src/test/java/org/heigit/ohsome/oshdb/filter/ParseTest.java | 2 ++
1 file changed, 2 insertions(+)
diff --git a/oshdb-filter/src/test/java/org/heigit/ohsome/oshdb/filter/ParseTest.java b/oshdb-filter/src/test/java/org/heigit/ohsome/oshdb/filter/ParseTest.java
index 243322b79..7daeb3582 100644
--- a/oshdb-filter/src/test/java/org/heigit/ohsome/oshdb/filter/ParseTest.java
+++ b/oshdb-filter/src/test/java/org/heigit/ohsome/oshdb/filter/ParseTest.java
@@ -158,6 +158,8 @@ void testIdFilterEqualsAnyOf() {
FilterExpression expression = parser.parse("id:(1,2,3)");
assertTrue(expression instanceof IdFilterEqualsAnyOf);
assertEquals("id:in1,2,3", expression.toString());
+ var filter = (IdFilterEqualsAnyOf) expression;
+ assertTrue(filter.getIds().containsAll(List.of(1L, 2L, 3L)));
}
@Test
From e335a4b851b2e76a4c900e98953b1ec51f45c233 Mon Sep 17 00:00:00 2001
From: Rafael Troilo
Date: Mon, 19 Jun 2023 15:36:58 +0200
Subject: [PATCH 09/11] clean up and fix some warnings
---
.../heigit/ohsome/oshdb/filter/ParseTest.java | 69 ++++++++-----------
1 file changed, 27 insertions(+), 42 deletions(-)
diff --git a/oshdb-filter/src/test/java/org/heigit/ohsome/oshdb/filter/ParseTest.java b/oshdb-filter/src/test/java/org/heigit/ohsome/oshdb/filter/ParseTest.java
index 7daeb3582..5090719d7 100644
--- a/oshdb-filter/src/test/java/org/heigit/ohsome/oshdb/filter/ParseTest.java
+++ b/oshdb-filter/src/test/java/org/heigit/ohsome/oshdb/filter/ParseTest.java
@@ -1,14 +1,5 @@
package org.heigit.ohsome.oshdb.filter;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertThrows;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.EnumSet;
-import java.util.List;
import org.heigit.ohsome.oshdb.OSHDBTag;
import org.heigit.ohsome.oshdb.filter.GeometryTypeFilter.GeometryType;
import org.heigit.ohsome.oshdb.osm.OSMType;
@@ -16,6 +7,10 @@
import org.jparsec.error.ParserException;
import org.junit.jupiter.api.Test;
+import java.util.*;
+
+import static org.junit.jupiter.api.Assertions.*;
+
/**
* Tests the parsing of filters and the application to OSM entities.
*/
@@ -24,7 +19,7 @@ class ParseTest extends FilterTest {
void testTagFilterEquals() {
FilterExpression expression = parser.parse("highway=residential");
assertTrue(expression instanceof TagFilterEquals);
- OSHDBTag tag = tagTranslator.getOSHDBTagOf("highway", "residential").get();
+ OSHDBTag tag = tagTranslator.getOSHDBTagOf("highway", "residential").orElseThrow();
assertEquals(tag, ((TagFilterEquals) expression).getTag());
assertEquals("tag:" + tag.getKey() + "=" + tag.getValue(), expression.toString());
}
@@ -44,7 +39,7 @@ void testTagFilterStrings() {
void testTagFilterEqualsAny() {
FilterExpression expression = parser.parse("highway=*");
assertTrue(expression instanceof TagFilterEqualsAny);
- OSHDBTagKey tag = tagTranslator.getOSHDBTagKeyOf("highway").get();
+ OSHDBTagKey tag = tagTranslator.getOSHDBTagKeyOf("highway").orElseThrow();
assertEquals(tag, ((TagFilterEqualsAny) expression).getTag());
assertEquals("tag:" + tag.toInt() + "=*", expression.toString());
}
@@ -53,7 +48,7 @@ void testTagFilterEqualsAny() {
void testTagFilterNotEquals() {
FilterExpression expression = parser.parse("highway!=residential");
assertTrue(expression instanceof TagFilterNotEquals);
- OSHDBTag tag = tagTranslator.getOSHDBTagOf("highway", "residential").get();
+ OSHDBTag tag = tagTranslator.getOSHDBTagOf("highway", "residential").orElseThrow();
assertEquals(tag, ((TagFilterNotEquals) expression).getTag());
assertEquals("tag:" + tag.getKey() + "!=" + tag.getValue(), expression.toString());
}
@@ -62,7 +57,7 @@ void testTagFilterNotEquals() {
void testTagFilterNotEqualsAny() {
FilterExpression expression = parser.parse("highway!=*");
assertTrue(expression instanceof TagFilterNotEqualsAny);
- OSHDBTagKey tag = tagTranslator.getOSHDBTagKeyOf("highway").get();
+ OSHDBTagKey tag = tagTranslator.getOSHDBTagKeyOf("highway").orElseThrow();
assertEquals(tag, ((TagFilterNotEqualsAny) expression).getTag());
assertEquals("tag:" + tag.toInt() + "!=*", expression.toString());
}
@@ -72,8 +67,8 @@ void testTagFilterNotEqualsAny() {
void testTagFilterEqualsAnyOf() {
FilterExpression expression = parser.parse("highway in (residential, track)");
assertTrue(expression instanceof TagFilterEqualsAnyOf);
- OSHDBTag tag1 = tagTranslator.getOSHDBTagOf("highway", "residential").get();
- OSHDBTag tag2 = tagTranslator.getOSHDBTagOf("highway", "track").get();
+ OSHDBTag tag1 = tagTranslator.getOSHDBTagOf("highway", "residential").orElseThrow();
+ OSHDBTag tag2 = tagTranslator.getOSHDBTagOf("highway", "track").orElseThrow();
assertTrue(expression.toString().matches("tag:" + tag1.getKey() + "in("
+ tag1.getValue() + "," + tag2.getValue() + "|"
+ tag2.getValue() + "," + tag1.getValue() + ")"
@@ -85,8 +80,8 @@ void testTagFilterEqualsAnyOf() {
void testTagFilterNotEqualsAnyOf() {
FilterExpression expression = parser.parse("not highway in (residential, track)");
assertTrue(expression instanceof TagFilterNotEqualsAnyOf);
- OSHDBTag tag1 = tagTranslator.getOSHDBTagOf("highway", "residential").get();
- OSHDBTag tag2 = tagTranslator.getOSHDBTagOf("highway", "track").get();
+ OSHDBTag tag1 = tagTranslator.getOSHDBTagOf("highway", "residential").orElseThrow();
+ OSHDBTag tag2 = tagTranslator.getOSHDBTagOf("highway", "track").orElseThrow();
assertTrue(expression.toString().matches("tag:" + tag1.getKey() + "not-in("
+ tag1.getValue() + "," + tag2.getValue() + "|"
+ tag2.getValue() + "," + tag1.getValue() + ")"
@@ -95,36 +90,30 @@ void testTagFilterNotEqualsAnyOf() {
@Test()
void testTagFilterEqualsAnyOfCheckEmpty() {
- assertThrows(IllegalStateException.class, () -> {
- new TagFilterEqualsAnyOf(Collections.emptyList());
- });
+ var list = Collections.emptyList();
+ assertThrows(IllegalStateException.class, () -> new TagFilterEqualsAnyOf(list));
}
@Test()
void testTagFilterNotEqualsAnyOfCheckEmpty() {
- assertThrows(IllegalStateException.class, () -> {
- new TagFilterNotEqualsAnyOf(Collections.emptyList());
- });
+ var list = Collections.emptyList();
+ assertThrows(IllegalStateException.class, () -> new TagFilterNotEqualsAnyOf(list));
}
@Test()
void testTagFilterEqualsAnyOfCheckMixed() {
- assertThrows(IllegalStateException.class, () -> {
- new TagFilterEqualsAnyOf(Arrays.asList(
- tagTranslator.getOSHDBTagOf("highway", "residential").get(),
- tagTranslator.getOSHDBTagOf("building", "yes").get()
- ));
- });
+ var list = Arrays.asList(
+ tagTranslator.getOSHDBTagOf("highway", "residential").orElseThrow(),
+ tagTranslator.getOSHDBTagOf("building", "yes").orElseThrow());
+ assertThrows(IllegalStateException.class, () -> new TagFilterEqualsAnyOf(list));
}
@Test()
void testTagFilterNotEqualsAnyOfCheckMixed() {
- assertThrows(IllegalStateException.class, () -> {
- new TagFilterNotEqualsAnyOf(Arrays.asList(
- tagTranslator.getOSHDBTagOf("highway", "residential").get(),
- tagTranslator.getOSHDBTagOf("building", "yes").get()
- ));
- });
+ var list = Arrays.asList(
+ tagTranslator.getOSHDBTagOf("highway", "residential").orElseThrow(),
+ tagTranslator.getOSHDBTagOf("building", "yes").orElseThrow());
+ assertThrows(IllegalStateException.class, () -> new TagFilterNotEqualsAnyOf(list));
}
@Test
@@ -173,9 +162,8 @@ void testIdTypeFilterEqualsAnyOf() {
@Test()
void testIdFilterEqualsAnyOfCheckEmpty() {
- assertThrows(IllegalStateException.class, () -> {
- new IdFilterEqualsAnyOf(Collections.emptyList());
- });
+ var emptyList = Collections.emptyList();
+ assertThrows(IllegalStateException.class, () -> new IdFilterEqualsAnyOf(emptyList));
}
@Test
@@ -432,11 +420,8 @@ void testContributorUserIdRangeFilter() {
assertEquals("contributor:in-range10..12", expression.toString());
}
- @SuppressWarnings("ResultOfMethodCallIgnored")
@Test()
void testContributorIdFilterNotEnabled() {
- assertThrows(ParserException.class, () -> {
- parser.parse("contributor:0");
- });
+ assertThrows(ParserException.class, () -> parser.parse("contributor:0"));
}
}
From bdb936b3fe1951b9cd72ab02174cabf76391fc65 Mon Sep 17 00:00:00 2001
From: Rafael Troilo
Date: Mon, 19 Jun 2023 17:54:00 +0200
Subject: [PATCH 10/11] incooperate typefilter for id extraction as well
---
.../ohsome/oshdb/filter/FilterUtil.java | 71 +++++++++++--------
.../ohsome/oshdb/filter/FilterUtilTest.java | 44 +++++++++---
2 files changed, 76 insertions(+), 39 deletions(-)
diff --git a/oshdb-filter/src/main/java/org/heigit/ohsome/oshdb/filter/FilterUtil.java b/oshdb-filter/src/main/java/org/heigit/ohsome/oshdb/filter/FilterUtil.java
index 1a51ab3cc..827143da3 100644
--- a/oshdb-filter/src/main/java/org/heigit/ohsome/oshdb/filter/FilterUtil.java
+++ b/oshdb-filter/src/main/java/org/heigit/ohsome/oshdb/filter/FilterUtil.java
@@ -1,9 +1,10 @@
package org.heigit.ohsome.oshdb.filter;
-import java.util.ArrayList;
-import java.util.List;
+import org.heigit.ohsome.oshdb.osm.OSMType;
-import static java.util.Collections.emptyList;
+import java.util.*;
+
+import static java.util.Collections.*;
import static java.util.Comparator.comparingLong;
public class FilterUtil {
@@ -12,43 +13,53 @@ private FilterUtil() {
throw new IllegalStateException("utility class");
}
- public static List ids(FilterExpression expression) {
+ public static Map, List> ids(FilterExpression expression) {
return ids(expression.normalize());
}
- public static List ids(List> normalized) {
- var ranges = new ArrayList();
- for (var orGroups : normalized) {
+ public static Map, List> ids(List> normalized) {
+ var result = new HashMap, List>();
+ for (var group : normalized) {
+ var type = EnumSet.allOf(OSMType.class);
var groupRanges = new ArrayList();
- for (var filter: orGroups) {
- if (filter instanceof IdFilterEquals equals){
- groupRanges.add(new IdRange(equals.getId()));
- } else if (filter instanceof IdFilterEqualsAnyOf equalsAnyOf) {
- equalsAnyOf.getIds().stream().map(IdRange::new).forEach(groupRanges::add);
- } else if (filter instanceof IdFilterRange range) {
- groupRanges.add(range.getRange());
+ for (var filter: group) {
+ if (filter instanceof TypeFilter typeFilter) {
+ type = EnumSet.of(typeFilter.getType());
+ } else if (filter instanceof IdFilterEquals idFilter){
+ groupRanges.add(new IdRange(idFilter.getId()));
+ } else if (filter instanceof IdFilterEqualsAnyOf idFilter) {
+ idFilter.getIds().stream().map(IdRange::new).forEach(groupRanges::add);
+ } else if (filter instanceof IdFilterRange idFilter) {
+ groupRanges.add(idFilter.getRange());
}
}
if (groupRanges.isEmpty()) {
- return emptyList();
+ return emptyMap();
}
- ranges.addAll(groupRanges);
+ result.computeIfAbsent(type, x -> new ArrayList<>()).addAll(groupRanges);
}
- var compact = new ArrayList(ranges.size());
-
- ranges.sort(comparingLong(IdRange::getFromId));
- var itr = ranges.iterator();
- var range = itr.next();
- while (itr.hasNext()) {
- var next = itr.next();
- if (next.getFromId() <= range.getToId() + 1) {
- range = new IdRange(range.getFromId(), next.getToId());
- } else {
- compact.add(range);
- range = next;
+ compactRanges(result);
+ return result;
+ }
+
+ private static void compactRanges(HashMap, List> result) {
+ for (var entry : result.entrySet()) {
+ var ranges = entry.getValue();
+ var compact = new ArrayList(ranges.size());
+ ranges.sort(comparingLong(IdRange::getFromId));
+ var itr = ranges.iterator();
+ var range = itr.next();
+ while (itr.hasNext()) {
+ var next = itr.next();
+ if (next.getFromId() <= range.getToId() + 1) {
+ range = new IdRange(range.getFromId(), next.getToId());
+ } else {
+ compact.add(range);
+ range = next;
+ }
}
+ compact.add(range);
+ entry.setValue(compact);
}
- compact.add(range);
- return compact;
}
}
diff --git a/oshdb-filter/src/test/java/org/heigit/ohsome/oshdb/filter/FilterUtilTest.java b/oshdb-filter/src/test/java/org/heigit/ohsome/oshdb/filter/FilterUtilTest.java
index dc6bd73f2..b149e6119 100644
--- a/oshdb-filter/src/test/java/org/heigit/ohsome/oshdb/filter/FilterUtilTest.java
+++ b/oshdb-filter/src/test/java/org/heigit/ohsome/oshdb/filter/FilterUtilTest.java
@@ -1,8 +1,11 @@
package org.heigit.ohsome.oshdb.filter;
+import org.heigit.ohsome.oshdb.osm.OSMType;
import org.junit.jupiter.api.Test;
+import java.util.EnumSet;
import java.util.List;
+import java.util.Map;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
@@ -11,21 +14,44 @@ class FilterUtilTest extends FilterTest{
@Test
void extractIds() {
- extractIds("id:123", List.of(new IdRange(123L)));
- extractIds("id:123 or id:234", List.of(new IdRange(123L), new IdRange(234L)));
- extractIds("id:123 or id:124", List.of(new IdRange(123L, 124L)));
- extractIds("id:123 and not id:234", List.of(new IdRange(123L)));
- extractIds("id:123 or name=heigit", List.of());
- extractIds("id:(123, 234)", List.of(new IdRange(123L), new IdRange(234L)));
- extractIds("id:(123 .. 125)", List.of(new IdRange(123L, 125L)));
+ extractIds("id:123", Map.of(EnumSet.allOf(OSMType.class),List.of(new IdRange(123L))));
+ extractIds("id:123 or id:234", Map.of(EnumSet.allOf(OSMType.class),List.of(new IdRange(123L), new IdRange(234L))));
+ extractIds("id:123 or id:124", Map.of(EnumSet.allOf(OSMType.class),List.of(new IdRange(123L, 124L))));
+ extractIds("id:123 and not id:234", Map.of(EnumSet.allOf(OSMType.class),List.of(new IdRange(123L))));
+ extractIds("id:123 or name=heigit", Map.of());
+ extractIds("id:(123, 234)", Map.of(EnumSet.allOf(OSMType.class),List.of(new IdRange(123L), new IdRange(234L))));
+ extractIds("id:(123 .. 125)", Map.of(EnumSet.allOf(OSMType.class),List.of(new IdRange(123L, 125L))));
}
- private void extractIds(String filter, List expected) {
+ @Test
+ void extractIdsWithTypes() {
+ extractIds("id:node/123 or id:way/234", Map.of(
+ EnumSet.of(OSMType.NODE), List.of(new IdRange(123L)),
+ EnumSet.of(OSMType.WAY), List.of(new IdRange(234L))));
+ extractIds("id:node/123 or id:way/234 or id:way/235", Map.of(
+ EnumSet.of(OSMType.NODE), List.of(new IdRange(123L)),
+ EnumSet.of(OSMType.WAY), List.of(new IdRange(234L, 235L))));
+ extractIds("id:node/123 or (type:way and id:234)", Map.of(
+ EnumSet.of(OSMType.NODE), List.of(new IdRange(123L)),
+ EnumSet.of(OSMType.WAY), List.of(new IdRange(234L))));
+ extractIds("id:node/123 or id:234", Map.of(
+ EnumSet.of(OSMType.NODE), List.of(new IdRange(123L)),
+ EnumSet.allOf(OSMType.class), List.of(new IdRange(234L))));
+ extractIds("not type:node and id:123", Map.of(
+ EnumSet.of(OSMType.WAY), List.of(new IdRange(123L)),
+ EnumSet.of(OSMType.RELATION), List.of(new IdRange(123L))));
+ }
+
+ private void extractIds(String filter, Map,List> expected) {
var expression = parser.parse(filter);
var actual = FilterUtil.ids(expression);
assertEquals(expected.size(), actual.size());
- assertTrue(expected.containsAll(actual));
+ for (var entry : expected.entrySet()) {
+ assertTrue(actual.containsKey(entry.getKey()));
+ assertEquals(entry.getValue().size(), actual.get(entry.getKey()).size());
+ assertTrue(actual.get(entry.getKey()).containsAll(entry.getValue()));
+ }
}
}
\ No newline at end of file
From d2df8622599d5596e69d907f0254e007e718e7ed Mon Sep 17 00:00:00 2001
From: Rafael Troilo
Date: Mon, 19 Jun 2023 19:15:09 +0200
Subject: [PATCH 11/11] add tag extraction
---
.../ohsome/oshdb/filter/FilterUtil.java | 67 ++++++++++++++-----
.../ohsome/oshdb/filter/FilterUtilTest.java | 13 +++-
2 files changed, 60 insertions(+), 20 deletions(-)
diff --git a/oshdb-filter/src/main/java/org/heigit/ohsome/oshdb/filter/FilterUtil.java b/oshdb-filter/src/main/java/org/heigit/ohsome/oshdb/filter/FilterUtil.java
index 827143da3..01717068b 100644
--- a/oshdb-filter/src/main/java/org/heigit/ohsome/oshdb/filter/FilterUtil.java
+++ b/oshdb-filter/src/main/java/org/heigit/ohsome/oshdb/filter/FilterUtil.java
@@ -1,8 +1,12 @@
package org.heigit.ohsome.oshdb.filter;
+import org.heigit.ohsome.oshdb.OSHDBTag;
import org.heigit.ohsome.oshdb.osm.OSMType;
import java.util.*;
+import java.util.function.Function;
+import java.util.function.Predicate;
+import java.util.stream.Stream;
import static java.util.Collections.*;
import static java.util.Comparator.comparingLong;
@@ -13,39 +17,66 @@ private FilterUtil() {
throw new IllegalStateException("utility class");
}
- public static Map, List> ids(FilterExpression expression) {
- return ids(expression.normalize());
+ public static Map, Set> tags(FilterExpression expression, Predicate test) {
+ return tags(expression.normalize(), test);
}
- public static Map, List> ids(List> normalized) {
- var result = new HashMap, List>();
- for (var group : normalized) {
+ public static Map, Set> tags(List> normalized, Predicate test) {
+ return extract(normalized, filter -> {
+ if (filter instanceof TagFilterEquals tagFilter) {
+ return Stream.of(tagFilter.getTag()).filter(test);
+ } else if (filter instanceof TagFilterEqualsAny tagFilter) {
+ return Stream.of(tagFilter.getTag()).map(key -> new OSHDBTag(key.toInt(), -1)).filter(test);
+ } else if (filter instanceof TagFilterEqualsAnyOf tagFilter) {
+ return tagFilter.tags.stream().filter(test);
+ }
+ return Stream.empty();
+ });
+ }
+
+ private static Map, Set> extract(List> normalized, Function> extractor) {
+ var result = new HashMap, Set>();
+ for(var group: normalized){
var type = EnumSet.allOf(OSMType.class);
- var groupRanges = new ArrayList();
- for (var filter: group) {
+ var groupResult = new HashSet();
+ for (var filter : group) {
if (filter instanceof TypeFilter typeFilter) {
type = EnumSet.of(typeFilter.getType());
- } else if (filter instanceof IdFilterEquals idFilter){
- groupRanges.add(new IdRange(idFilter.getId()));
- } else if (filter instanceof IdFilterEqualsAnyOf idFilter) {
- idFilter.getIds().stream().map(IdRange::new).forEach(groupRanges::add);
- } else if (filter instanceof IdFilterRange idFilter) {
- groupRanges.add(idFilter.getRange());
+ } else {
+ extractor.apply(filter).forEach(groupResult::add);
}
}
- if (groupRanges.isEmpty()) {
+ if (groupResult.isEmpty()) {
return emptyMap();
}
- result.computeIfAbsent(type, x -> new ArrayList<>()).addAll(groupRanges);
+ result.computeIfAbsent(type, x -> new HashSet<>()).addAll(groupResult);
}
+ return result;
+ }
+
+ public static Map, Set> extractIds(FilterExpression expression) {
+ return extractIds(expression.normalize());
+ }
+
+ public static Map, Set> extractIds(List> normalized) {
+ var result = extract(normalized, filter -> {
+ if (filter instanceof IdFilterEquals idFilter){
+ return Stream.of(new IdRange(idFilter.getId()));
+ } else if (filter instanceof IdFilterEqualsAnyOf idFilter) {
+ return idFilter.getIds().stream().map(IdRange::new);
+ } else if (filter instanceof IdFilterRange idFilter) {
+ return Stream.of(idFilter.getRange());
+ }
+ return Stream.empty();
+ });
compactRanges(result);
return result;
}
- private static void compactRanges(HashMap, List> result) {
+ private static void compactRanges(Map, Set> result) {
for (var entry : result.entrySet()) {
- var ranges = entry.getValue();
- var compact = new ArrayList(ranges.size());
+ var ranges = new ArrayList<>(entry.getValue());
+ var compact = new HashSet(ranges.size());
ranges.sort(comparingLong(IdRange::getFromId));
var itr = ranges.iterator();
var range = itr.next();
diff --git a/oshdb-filter/src/test/java/org/heigit/ohsome/oshdb/filter/FilterUtilTest.java b/oshdb-filter/src/test/java/org/heigit/ohsome/oshdb/filter/FilterUtilTest.java
index b149e6119..0dd5ba963 100644
--- a/oshdb-filter/src/test/java/org/heigit/ohsome/oshdb/filter/FilterUtilTest.java
+++ b/oshdb-filter/src/test/java/org/heigit/ohsome/oshdb/filter/FilterUtilTest.java
@@ -1,5 +1,6 @@
package org.heigit.ohsome.oshdb.filter;
+import org.heigit.ohsome.oshdb.OSHDBTag;
import org.heigit.ohsome.oshdb.osm.OSMType;
import org.junit.jupiter.api.Test;
@@ -42,9 +43,17 @@ void extractIdsWithTypes() {
EnumSet.of(OSMType.RELATION), List.of(new IdRange(123L))));
}
- private void extractIds(String filter, Map,List> expected) {
+ @Test
+ void extractTags() {
+ var expression = parser.parse("type:way and (highway=primary or building=*)");
+ var result = FilterUtil.tags(expression, x -> true);
+ assertTrue(result.containsKey(EnumSet.of(OSMType.WAY)));
+ assertTrue(result.get(EnumSet.of(OSMType.WAY)).containsAll(List.of(new OSHDBTag(2,7), new OSHDBTag(1,-1))));
+ }
+
+ private void extractIds(String filter, Map, List> expected) {
var expression = parser.parse(filter);
- var actual = FilterUtil.ids(expression);
+ var actual = FilterUtil.extractIds(expression);
assertEquals(expected.size(), actual.size());
for (var entry : expected.entrySet()) {