001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.gui.mappaint;
003
004import java.util.Collection;
005import java.util.HashMap;
006import java.util.Map;
007import java.util.Map.Entry;
008
009import org.openstreetmap.josm.tools.CheckParameterUtil;
010
011/**
012 * Several layers / cascades, e.g. one for the main Line and one for each overlay.
013 * The range is (0,Infinity) at first and it shrinks in the process when
014 * StyleSources apply zoom level dependent properties.
015 */
016public class MultiCascade implements StyleKeys {
017
018    private final Map<String, Cascade> layers;
019    /**
020     * The scale range this cascade is valid for
021     */
022    public Range range;
023
024    /**
025     * Constructs a new {@code MultiCascade}.
026     */
027    public MultiCascade() {
028        layers = new HashMap<>();
029        range = Range.ZERO_TO_INFINITY;
030    }
031
032    /**
033     * Return the cascade with the given name. If it doesn't exist, create
034     * a new layer with that name and return it. The new layer will be
035     * a clone of the "*" layer, if it exists.
036     * @param layer layer
037     * @return cascade
038     */
039    public Cascade getOrCreateCascade(String layer) {
040        CheckParameterUtil.ensureParameterNotNull(layer);
041        Cascade c = layers.get(layer);
042        if (c == null) {
043            if (layers.containsKey("*")) {
044                c = new Cascade(layers.get("*"));
045            } else {
046                c = new Cascade();
047                // Everything that is not on the default layer is assumed to
048                // be a modifier. Can be overridden in style definition.
049                if (!"default".equals(layer) && !"*".equals(layer)) {
050                    c.put(MODIFIER, Boolean.TRUE);
051                }
052            }
053            layers.put(layer, c);
054        }
055        return c;
056    }
057
058    /**
059     * Read-only version of {@link #getOrCreateCascade}. For convenience, it returns an
060     * empty cascade for non-existing layers. However this empty (read-only) cascade
061     * is not added to this MultiCascade object.
062     * @param layer layer
063     * @return cascade
064     */
065    public Cascade getCascade(String layer) {
066        if (layer == null) {
067            layer = "default";
068        }
069        Cascade c = layers.get(layer);
070        if (c == null) {
071            c = new Cascade();
072            if (!"default".equals(layer) && !"*".equals(layer)) {
073                c.put(MODIFIER, Boolean.TRUE);
074            }
075        }
076        return c;
077    }
078
079    /**
080     * Gets all cascades for the known layers
081     * @return The cascades for the layers
082     */
083    public Collection<Entry<String, Cascade>> getLayers() {
084        return layers.entrySet();
085    }
086
087    /**
088     * Check whether this cascade has a given layer
089     * @param layer The layer to check for
090     * @return <code>true</code> if it has that layer
091     */
092    public boolean hasLayer(String layer) {
093        return layers.containsKey(layer);
094    }
095}