// License: GPL. For details, see LICENSE file. package org.openstreetmap.josm.gui.mappaint; import org.openstreetmap.josm.data.osm.OsmPrimitive; import org.openstreetmap.josm.data.osm.Relation; import org.openstreetmap.josm.gui.mappaint.mapcss.Condition.Context; import org.openstreetmap.josm.gui.mappaint.mapcss.Selector.LinkSelector; import org.openstreetmap.josm.tools.CheckParameterUtil; /** * Environment is a data object to provide access to various "global" parameters. * It is used during processing of MapCSS rules and for the generation of * style elements. */ public class Environment { public OsmPrimitive osm; public MultiCascade mc; public String layer; public StyleSource source; private Context context = Context.PRIMITIVE; public static final String DEFAULT_LAYER = "default"; /** * If not null, this is the matching parent object if a condition or an expression * is evaluated in a {@link LinkSelector} (within a child selector) */ public OsmPrimitive parent; /** * The same for parent selector. Only one of the 2 fields (parent or child) is not null in any environment. */ public OsmPrimitive child; /** * index of node in parent way or member in parent relation. Must be != null in LINK context. */ public Integer index; /** * count of nodes in parent way or members in parent relation. Must be != null in LINK context. */ public Integer count; /** * Creates a new uninitialized environment. */ public Environment() { // environment can be initialized later through with* methods } /** * Creates a new environment. * @param osm OSM primitive * @since 8415 */ public Environment(OsmPrimitive osm) { this.osm = osm; } /** * Creates a new environment. * @param osm OSM primitive * @param mc multi cascade * @param layer layer * @param source style source */ public Environment(OsmPrimitive osm, MultiCascade mc, String layer, StyleSource source) { this.osm = osm; this.mc = mc; this.layer = layer; this.source = source; } /** * Creates a clone of the environment {@code other}. * * @param other the other environment. Must not be null. * @throws IllegalArgumentException if {@code param} is {@code null} */ public Environment(Environment other) { CheckParameterUtil.ensureParameterNotNull(other); this.osm = other.osm; this.mc = other.mc; this.layer = other.layer; this.parent = other.parent; this.child = other.child; this.source = other.source; this.index = other.index; this.count = other.count; this.context = other.getContext(); } /** * Creates a clone of this environment, with the specified primitive. * @param osm OSM primitive * @return A clone of this environment, with the specified primitive * @see #osm */ public Environment withPrimitive(OsmPrimitive osm) { Environment e = new Environment(this); e.osm = osm; return e; } /** * Creates a clone of this environment, with the specified parent. * @param parent the matching parent object * @return A clone of this environment, with the specified parent * @see #parent */ public Environment withParent(OsmPrimitive parent) { Environment e = new Environment(this); e.parent = parent; return e; } /** * Creates a clone of this environment, with the specified parent, index, and context set to {@link Context#LINK}. * @param parent the matching parent object * @param index index of node in parent way or member in parent relation * @param count count of nodes in parent way or members in parent relation * @return A clone of this environment, with the specified parent, index, and context set to {@link Context#LINK} * @see #parent * @see #index * @since 6175 */ public Environment withParentAndIndexAndLinkContext(OsmPrimitive parent, int index, int count) { Environment e = new Environment(this); e.parent = parent; e.index = index; e.count = count; e.context = Context.LINK; return e; } /** * Creates a clone of this environment, with the specified child. * @param child the matching child object * @return A clone of this environment, with the specified child * @see #child */ public Environment withChild(OsmPrimitive child) { Environment e = new Environment(this); e.child = child; return e; } /** * Creates a clone of this environment, with the specified child, index, and context set to {@link Context#LINK}. * @param child the matching child object * @param index index of node in parent way or member in parent relation * @param count count of nodes in parent way or members in parent relation * @return A clone of this environment, with the specified child, index, and context set to {@code Context#LINK} * @see #child * @see #index * @since 6175 */ public Environment withChildAndIndexAndLinkContext(OsmPrimitive child, int index, int count) { Environment e = new Environment(this); e.child = child; e.index = index; e.count = count; e.context = Context.LINK; return e; } /** * Creates a clone of this environment, with the specified index. * @param index index of node in parent way or member in parent relation * @param count count of nodes in parent way or members in parent relation * @return A clone of this environment, with the specified index * @see #index */ public Environment withIndex(int index, int count) { Environment e = new Environment(this); e.index = index; e.count = count; return e; } /** * Creates a clone of this environment, with the specified {@link Context}. * @param context context * @return A clone of this environment, with the specified {@code Context} */ public Environment withContext(Context context) { Environment e = new Environment(this); e.context = context == null ? Context.PRIMITIVE : context; return e; } /** * Creates a clone of this environment, with context set to {@link Context#LINK}. * @return A clone of this environment, with context set to {@code Context#LINK} */ public Environment withLinkContext() { Environment e = new Environment(this); e.context = Context.LINK; return e; } /** * Determines if the context of this environment is {@link Context#LINK}. * @return {@code true} if the context of this environment is {@code Context#LINK}, {@code false} otherwise */ public boolean isLinkContext() { return Context.LINK.equals(context); } /** * Determines if this environment has a relation as parent. * @return {@code true} if this environment has a relation as parent, {@code false} otherwise * @see #parent */ public boolean hasParentRelation() { return parent instanceof Relation; } /** * Replies the current context. * * @return the current context */ public Context getContext() { return context == null ? Context.PRIMITIVE : context; } public String getRole() { if (getContext().equals(Context.PRIMITIVE)) return null; if (parent instanceof Relation) return ((Relation) parent).getMember(index).getRole(); if (child != null && osm instanceof Relation) return ((Relation) osm).getMember(index).getRole(); return null; } public void clearSelectorMatchingInformation() { parent = null; child = null; index = null; count = null; } public Cascade getCascade(String layer) { return mc == null ? null : mc.getCascade(layer == null ? this.layer : layer); } }