001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.gui.mappaint.mapcss;
003
004import java.util.List;
005import java.util.stream.Collectors;
006
007import org.openstreetmap.josm.gui.mappaint.Environment;
008import org.openstreetmap.josm.tools.Utils;
009
010/**
011 * A MapCSS rule.
012 *
013 * A MapCSS style is simply a list of MapCSS rules. Each rule has a selector
014 * and a declaration. Whenever the selector matches the primitive, the
015 * declaration block is executed for this primitive.
016 */
017public class MapCSSRule implements Comparable<MapCSSRule> {
018
019    /**
020     * The selector. If it matches, this rule should be applied
021     */
022    public final List<Selector> selectors;
023    /**
024     * The instructions for this selector
025     */
026    public final Declaration declaration;
027
028    /**
029     * Constructs a new {@code MapCSSRule}.
030     * @param selectors The selectors
031     * @param declaration The declaration
032     */
033    public MapCSSRule(List<Selector> selectors, Declaration declaration) {
034        this.selectors = Utils.toUnmodifiableList(selectors);
035        this.declaration = declaration;
036    }
037
038    /**
039     * Test whether the selector of this rule applies to the primitive.
040     *
041     * @param env the Environment. env.mc and env.layer are read-only when matching a selector.
042     * env.source is not needed. This method will set the matchingReferrers field of env as
043     * a side effect! Make sure to clear it before invoking this method.
044     * @return true, if the selector applies
045     * @see Selector#matches
046     */
047    public boolean matches(Environment env) {
048        return selectors.stream().anyMatch(s -> s.matches(env));
049    }
050
051    /**
052     * <p>Executes the instructions against the environment {@code env}</p>
053     *
054     * @param env the environment
055     * @see Declaration#execute
056     */
057    public void execute(Environment env) {
058        declaration.execute(env);
059    }
060
061    @Override
062    public int compareTo(MapCSSRule o) {
063        return declaration.idx - o.declaration.idx;
064    }
065
066    @Override
067    public String toString() {
068        final String selectorsString = selectors.stream().map(String::valueOf)
069                .collect(Collectors.joining(",\n"));
070        final String declarationString = declaration.instructions.stream()
071                .map(String::valueOf)
072                .collect(Collectors.joining("\n  ", " {\n  ", "\n}"));
073        return selectorsString + declarationString;
074    }
075}
076