001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.gui.autofilter;
003
004import java.util.Comparator;
005import java.util.Objects;
006import java.util.function.Function;
007
008/**
009 * An auto filter rule determines how auto filter can be built from visible map data.
010 * Several rules can be registered, but only one rule is active at the same time.
011 * Rules are identified by the OSM key on which they apply.
012 * The dynamic values discovering operates only below a certain zoom level, for performance reasons.
013 * @since 12400
014 */
015public class AutoFilterRule {
016
017    private final String key;
018
019    private final int minZoomLevel;
020
021    private Function<String, String> valueFormatter = s -> s;
022
023    private Comparator<String> valueComparator = Comparator.comparingInt(s -> Integer.parseInt(valueFormatter.apply(s)));
024
025    /**
026     * Constructs a new {@code AutoFilterRule}.
027     * @param key the OSM key on which the rule applies
028     * @param minZoomLevel the minimum zoom level at which the rule applies
029     */
030    public AutoFilterRule(String key, int minZoomLevel) {
031        this.key = key;
032        this.minZoomLevel = minZoomLevel;
033    }
034
035    /**
036     * Returns the OSM key on which the rule applies.
037     * @return the OSM key on which the rule applies
038     */
039    public String getKey() {
040        return key;
041    }
042
043    /**
044     * Returns the minimum zoom level at which the rule applies.
045     * @return the minimum zoom level at which the rule applies
046     */
047    public int getMinZoomLevel() {
048        return minZoomLevel;
049    }
050
051    /**
052     * Returns the OSM value formatter that defines the associated button label.
053     * @return the OSM value formatter that defines the associated button label (identity by default)
054     */
055    public Function<String, String> getValueFormatter() {
056        return valueFormatter;
057    }
058
059    /**
060     * Sets a OSM value formatter that defines the associated button label.
061     * @param valueFormatter OSM value formatter. Cannot be null
062     * @return {@code this}
063     * @throws NullPointerException if {@code valueFormatter} is null
064     */
065    public AutoFilterRule setValueFormatter(Function<String, String> valueFormatter) {
066        this.valueFormatter = Objects.requireNonNull(valueFormatter);
067        return this;
068    }
069
070    /**
071     * Returns the OSM value comparator used to order the buttons.
072     * @return the OSM value comparator
073     */
074    public Comparator<String> getValueComparator() {
075        return valueComparator;
076    }
077
078    /**
079     * Sets the OSM value comparator used to order the buttons.
080     * @param valueComparator the OSM value comparator
081     * @return {@code this}
082     * @throws NullPointerException if {@code valueComparator} is null
083     */
084    public AutoFilterRule setValueComparator(Comparator<String> valueComparator) {
085        this.valueComparator = valueComparator;
086        return this;
087    }
088
089    /**
090     * Returns the default list of auto filter rules. Plugins can extend the list by registering additional rules.
091     * @return the default list of auto filter rules
092     */
093    public static AutoFilterRule[] defaultRules() {
094        return new AutoFilterRule[] {
095            new AutoFilterRule("level", 17),
096            new AutoFilterRule("layer", 16),
097            new AutoFilterRule("maxspeed", 16)
098                .setValueFormatter(s -> s.replaceAll(" mph", "")),
099            new AutoFilterRule("voltage", 5)
100                .setValueFormatter(s -> s.replaceAll("000$", "k") + 'V')
101                .setValueComparator(Comparator.comparingInt(Integer::parseInt))
102        };
103    }
104
105    @Override
106    public String toString() {
107        return key + '[' + minZoomLevel + ']';
108    }
109}