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