diff --git a/src/org/openstreetmap/josm/gui/autofilter/AutoFilterRule.java b/src/org/openstreetmap/josm/gui/autofilter/AutoFilterRule.java
index 9c35c387e9..f722122bd6 100644
|
a
|
b
|
|
| 2 | 2 | package org.openstreetmap.josm.gui.autofilter; |
| 3 | 3 | |
| 4 | 4 | import java.text.DecimalFormat; |
| 5 | | import java.util.Arrays; |
| 6 | | import java.util.Locale; |
| 7 | | import java.util.Objects; |
| 8 | | import java.util.Optional; |
| | 5 | import java.util.*; |
| 9 | 6 | import java.util.function.Function; |
| 10 | 7 | import java.util.function.IntFunction; |
| 11 | 8 | import java.util.function.ToIntFunction; |
| 12 | 9 | import java.util.regex.Matcher; |
| 13 | 10 | import java.util.regex.Pattern; |
| 14 | 11 | import java.util.stream.IntStream; |
| | 12 | import java.util.stream.Stream; |
| 15 | 13 | |
| 16 | 14 | import org.openstreetmap.josm.data.osm.OsmPrimitive; |
| 17 | 15 | import org.openstreetmap.josm.data.osm.OsmUtils; |
| 18 | 16 | import org.openstreetmap.josm.data.preferences.BooleanProperty; |
| 19 | 17 | import org.openstreetmap.josm.tools.Logging; |
| 20 | 18 | |
| | 19 | import static java.util.stream.Collectors.toList; |
| | 20 | |
| 21 | 21 | /** |
| 22 | 22 | * An auto filter rule determines how auto filter can be built from visible map data. |
| 23 | 23 | * Several rules can be registered, but only one rule is active at the same time. |
| … |
… |
public class AutoFilterRule {
|
| 42 | 42 | |
| 43 | 43 | private IntFunction<String> valueFormatter = Integer::toString; |
| 44 | 44 | |
| | 45 | /** The union of {@link #key} and the keys provided by {@link #setExtraKeys(List)}. */ |
| | 46 | private List<String> allKeys; |
| | 47 | |
| 45 | 48 | /** |
| 46 | 49 | * Constructs a new {@code AutoFilterRule}. |
| 47 | 50 | * @param key the OSM key on which the rule applies |
| … |
… |
public class AutoFilterRule {
|
| 50 | 53 | public AutoFilterRule(String key, int minZoomLevel) { |
| 51 | 54 | this.key = key; |
| 52 | 55 | this.minZoomLevel = minZoomLevel; |
| | 56 | this.allKeys = List.of(key); |
| 53 | 57 | } |
| 54 | 58 | |
| 55 | 59 | /** |
| … |
… |
public class AutoFilterRule {
|
| 111 | 115 | return this; |
| 112 | 116 | } |
| 113 | 117 | |
| | 118 | /** |
| | 119 | * Sets extra OSM keys on which the rule applies in addition to the primary key ({@link #getKey()}). |
| | 120 | * This allows a filter to look at the values of more than one key at the same time. |
| | 121 | * @param extraKeys the list of extra keys, may be empty |
| | 122 | * @return {@code this} |
| | 123 | * @throws NullPointerException if {@code extraKeys} is null |
| | 124 | */ |
| | 125 | public AutoFilterRule setExtraKeys(List<String> extraKeys) { |
| | 126 | Objects.requireNonNull(extraKeys); |
| | 127 | this.allKeys = Stream.concat(Stream.of(key), extraKeys.stream()).collect(toList()); |
| | 128 | return this; |
| | 129 | } |
| | 130 | |
| 114 | 131 | /** |
| 115 | 132 | * Returns the numeric values for the given OSM primitive |
| 116 | 133 | * @param osm the primitive |
| 117 | 134 | * @return a stream of numeric values |
| 118 | 135 | */ |
| 119 | 136 | public IntStream getTagValuesForPrimitive(OsmPrimitive osm) { |
| | 137 | if (allKeys.size() == 1) { |
| | 138 | IntStream values = getTagValuesForPrimitive(osm, key); |
| | 139 | if (values != null) return values; |
| | 140 | } else { |
| | 141 | Set<Integer> allValues = new HashSet<>(); |
| | 142 | for (String k : allKeys) { |
| | 143 | IntStream values = getTagValuesForPrimitive(osm, k); |
| | 144 | if (values != null) { values.forEach(allValues::add); } |
| | 145 | } |
| | 146 | if (!allValues.isEmpty()) return allValues.stream().mapToInt(it -> it).sorted(); |
| | 147 | } |
| | 148 | return Boolean.TRUE.equals(PROP_AUTO_FILTER_DEFAULTS.get()) ? defaultValueSupplier.apply(osm) : IntStream.empty(); |
| | 149 | } |
| | 150 | |
| | 151 | private IntStream getTagValuesForPrimitive(OsmPrimitive osm, String key) { |
| 120 | 152 | String value = osm.get(key); |
| 121 | 153 | if (value != null) { |
| 122 | 154 | Pattern p = Pattern.compile("(-?[0-9]+)-(-?[0-9]+)"); |
| … |
… |
public class AutoFilterRule {
|
| 136 | 168 | } |
| 137 | 169 | }); |
| 138 | 170 | } |
| 139 | | return Boolean.TRUE.equals(PROP_AUTO_FILTER_DEFAULTS.get()) ? defaultValueSupplier.apply(osm) : IntStream.empty(); |
| | 171 | return null; |
| 140 | 172 | } |
| 141 | 173 | |
| 142 | 174 | /** |
| … |
… |
public class AutoFilterRule {
|
| 156 | 188 | new AutoFilterRule("layer", 16) |
| 157 | 189 | .setDefaultValueSupplier(AutoFilterRule::defaultLayer), |
| 158 | 190 | new AutoFilterRule("level", 17) |
| | 191 | .setExtraKeys(List.of("repeat_on")) |
| 159 | 192 | // #17109, support values like 0.5 or 1.5 - level values are multiplied by 2 when parsing, values are divided by 2 for formatting |
| 160 | 193 | .setValueExtractor(s -> (int) (Double.parseDouble(s) * 2.)) |
| 161 | 194 | .setValueFormatter(v -> DecimalFormat.getInstance(Locale.ROOT).format(v / 2.)), |
diff --git a/test/unit/org/openstreetmap/josm/gui/autofilter/AutoFilterRuleTest.java b/test/unit/org/openstreetmap/josm/gui/autofilter/AutoFilterRuleTest.java
index d68b4bcaec..ae1b15b909 100644
|
a
|
b
|
import org.junit.jupiter.api.Test;
|
| 22 | 22 | @I18n |
| 23 | 23 | class AutoFilterRuleTest { |
| 24 | 24 | /** |
| 25 | | * Unit test of {@link AutoFilterRule#getTagValuesForPrimitive}. |
| | 25 | * Unit test of {@link AutoFilterRule#getTagValuesForPrimitive(OsmPrimitive)}. |
| 26 | 26 | */ |
| 27 | 27 | @Test |
| 28 | 28 | void testTagValuesForPrimitive() { |
| … |
… |
class AutoFilterRuleTest {
|
| 36 | 36 | assertTagValuesForPrimitive(level, "way level=6-9", 12, 13, 14, 15, 16, 17, 18); |
| 37 | 37 | assertTagValuesForPrimitive(level, "way level=10;12-13", 20, 24, 25, 26); |
| 38 | 38 | assertTagValuesForPrimitive(level, "way level=0;0.5;1;1.5;2;2.5;3", 0, 1, 2, 3, 4, 5, 6); |
| | 39 | assertTagValuesForPrimitive(level, "node level=0 repeat_on=1;2", 0, 2, 4); |
| | 40 | assertTagValuesForPrimitive(level, "way level=4 repeat_on=4;5 layer=1", 8, 10); |
| 39 | 41 | assertEquals("0 0.5 1 1.5 2 2.5 3", |
| 40 | 42 | IntStream.of(0, 1, 2, 3, 4, 5, 6).mapToObj(level::formatValue).collect(Collectors.joining(" "))); |
| 41 | 43 | } |
| 42 | 44 | |
| 43 | 45 | /** |
| 44 | | * Unit test of {@link AutoFilterRule#getTagValuesForPrimitive} to deal with {@code %} of key {@code incline}. |
| | 46 | * Unit test of {@link AutoFilterRule#getTagValuesForPrimitive(OsmPrimitive)} to deal with {@code %} of key {@code incline}. |
| 45 | 47 | */ |
| 46 | 48 | @Test |
| 47 | 49 | void testTagValuesForPrimitiveInclineUnit() { |
| … |
… |
class AutoFilterRuleTest {
|
| 52 | 54 | } |
| 53 | 55 | |
| 54 | 56 | /** |
| 55 | | * Unit test of {@link AutoFilterRule#getTagValuesForPrimitive} provides sensible defaults, see #17496. |
| | 57 | * Unit test of {@link AutoFilterRule#getTagValuesForPrimitive(OsmPrimitive)} provides sensible defaults, see #17496. |
| 56 | 58 | */ |
| 57 | 59 | @Test |
| 58 | 60 | void testTagValuesForPrimitivesDefaults() { |