001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.gui.mappaint.mapcss;
003
004import java.util.List;
005
006import org.openstreetmap.josm.gui.mappaint.Environment;
007import org.openstreetmap.josm.tools.Utils;
008
009/**
010 * A MapCSS rule.
011 *
012 * A MapCSS style is simply a list of MapCSS rules. Each rule has a selector
013 * and a declaration. Whenever the selector matches the primitive, the
014 * declaration block is executed for this primitive.
015 */
016public class MapCSSRule implements Comparable<MapCSSRule> {
017
018    public final Selector selector;
019    public final Declaration declaration;
020
021    public static class Declaration {
022        public final List<Instruction> instructions;
023        // declarations in the StyleSource are numbered consecutively
024        public final int idx;
025
026        public Declaration(List<Instruction> instructions, int idx) {
027            this.instructions = instructions;
028            this.idx = idx;
029        }
030
031        /**
032         * <p>Executes the instructions against the environment {@code env}</p>
033         *
034         * @param env the environment
035         */
036        public void execute(Environment env) {
037            for (Instruction i : instructions) {
038                i.execute(env);
039            }
040        }
041
042        @Override
043        public int hashCode() {
044            final int prime = 31;
045            int result = 1;
046            result = prime * result + idx;
047            result = prime * result + ((instructions == null) ? 0 : instructions.hashCode());
048            return result;
049        }
050
051        @Override
052        public boolean equals(Object obj) {
053            if (this == obj)
054                return true;
055            if (obj == null)
056                return false;
057            if (!(obj instanceof Declaration))
058                return false;
059            Declaration other = (Declaration) obj;
060            if (idx != other.idx)
061                return false;
062            if (instructions == null) {
063                if (other.instructions != null)
064                    return false;
065            } else if (!instructions.equals(other.instructions))
066                return false;
067            return true;
068        }
069
070        @Override
071        public String toString() {
072            return "Declaration [instructions=" + instructions + ", idx=" + idx + ']';
073        }
074    }
075
076    /**
077     * Constructs a new {@code MapCSSRule}.
078     * @param selector The selector
079     * @param declaration The declaration
080     */
081    public MapCSSRule(Selector selector, Declaration declaration) {
082        this.selector = selector;
083        this.declaration = declaration;
084    }
085
086    /**
087     * <p>Executes the instructions against the environment {@code env}</p>
088     *
089     * @param env the environment
090     */
091    public void execute(Environment env) {
092        declaration.execute(env);
093    }
094
095    @Override
096    public int compareTo(MapCSSRule o) {
097        return declaration.idx - o.declaration.idx;
098    }
099
100    @Override
101    public String toString() {
102        return selector + " {\n  " + Utils.join("\n  ", declaration.instructions) + "\n}";
103    }
104}
105