001// License: GPL. For details, see LICENSE file. 002package org.openstreetmap.josm.gui.mappaint; 003 004import org.openstreetmap.josm.data.osm.OsmPrimitive; 005import org.openstreetmap.josm.data.osm.Relation; 006import org.openstreetmap.josm.gui.mappaint.mapcss.Condition.Context; 007import org.openstreetmap.josm.gui.mappaint.mapcss.Selector.LinkSelector; 008import org.openstreetmap.josm.tools.CheckParameterUtil; 009 010/** 011 * Environment is a data object to provide access to various "global" parameters. 012 * It is used during processing of MapCSS rules and for the generation of 013 * style elements. 014 */ 015public class Environment { 016 017 /** 018 * The primitive that is currently evaluated 019 */ 020 public OsmPrimitive osm; 021 022 /** 023 * The cascades that are currently evaluated 024 */ 025 public MultiCascade mc; 026 /** 027 * The current MapCSS layer 028 */ 029 public String layer; 030 /** 031 * The style source that is evaluated 032 */ 033 public StyleSource source; 034 private Context context = Context.PRIMITIVE; 035 036 /** 037 * The name of the default layer. It is used if no layer is specified in the MapCSS rule 038 */ 039 public static final String DEFAULT_LAYER = "default"; 040 041 /** 042 * If not null, this is the matching parent object if a condition or an expression 043 * is evaluated in a {@link LinkSelector} (within a child selector) 044 */ 045 public OsmPrimitive parent; 046 047 /** 048 * The same for parent selector. Only one of the 2 fields (parent or child) is not null in any environment. 049 */ 050 public OsmPrimitive child; 051 052 /** 053 * index of node in parent way or member in parent relation. Must be != null in LINK context. 054 */ 055 public Integer index; 056 057 /** 058 * count of nodes in parent way or members in parent relation. Must be != null in LINK context. 059 */ 060 public Integer count; 061 062 /** 063 * Creates a new uninitialized environment. 064 */ 065 public Environment() { 066 // environment can be initialized later through with* methods 067 } 068 069 /** 070 * Creates a new environment. 071 * @param osm OSM primitive 072 * @since 8415 073 */ 074 public Environment(OsmPrimitive osm) { 075 this.osm = osm; 076 } 077 078 /** 079 * Creates a new environment. 080 * @param osm OSM primitive 081 * @param mc multi cascade 082 * @param layer layer 083 * @param source style source 084 */ 085 public Environment(OsmPrimitive osm, MultiCascade mc, String layer, StyleSource source) { 086 this.osm = osm; 087 this.mc = mc; 088 this.layer = layer; 089 this.source = source; 090 } 091 092 /** 093 * Creates a clone of the environment {@code other}. 094 * 095 * @param other the other environment. Must not be null. 096 * @throws IllegalArgumentException if {@code param} is {@code null} 097 */ 098 public Environment(Environment other) { 099 CheckParameterUtil.ensureParameterNotNull(other); 100 this.osm = other.osm; 101 this.mc = other.mc; 102 this.layer = other.layer; 103 this.parent = other.parent; 104 this.child = other.child; 105 this.source = other.source; 106 this.index = other.index; 107 this.count = other.count; 108 this.context = other.getContext(); 109 } 110 111 /** 112 * Creates a clone of this environment, with the specified primitive. 113 * @param osm OSM primitive 114 * @return A clone of this environment, with the specified primitive 115 * @see #osm 116 */ 117 public Environment withPrimitive(OsmPrimitive osm) { 118 Environment e = new Environment(this); 119 e.osm = osm; 120 return e; 121 } 122 123 /** 124 * Creates a clone of this environment, with the specified parent. 125 * @param parent the matching parent object 126 * @return A clone of this environment, with the specified parent 127 * @see #parent 128 */ 129 public Environment withParent(OsmPrimitive parent) { 130 Environment e = new Environment(this); 131 e.parent = parent; 132 return e; 133 } 134 135 /** 136 * Creates a clone of this environment, with the specified parent, index, and context set to {@link Context#LINK}. 137 * @param parent the matching parent object 138 * @param index index of node in parent way or member in parent relation 139 * @param count count of nodes in parent way or members in parent relation 140 * @return A clone of this environment, with the specified parent, index, and context set to {@link Context#LINK} 141 * @see #parent 142 * @see #index 143 * @since 6175 144 */ 145 public Environment withParentAndIndexAndLinkContext(OsmPrimitive parent, int index, int count) { 146 Environment e = new Environment(this); 147 e.parent = parent; 148 e.index = index; 149 e.count = count; 150 e.context = Context.LINK; 151 return e; 152 } 153 154 /** 155 * Creates a clone of this environment, with the specified child. 156 * @param child the matching child object 157 * @return A clone of this environment, with the specified child 158 * @see #child 159 */ 160 public Environment withChild(OsmPrimitive child) { 161 Environment e = new Environment(this); 162 e.child = child; 163 return e; 164 } 165 166 /** 167 * Creates a clone of this environment, with the specified child, index, and context set to {@link Context#LINK}. 168 * @param child the matching child object 169 * @param index index of node in parent way or member in parent relation 170 * @param count count of nodes in parent way or members in parent relation 171 * @return A clone of this environment, with the specified child, index, and context set to {@code Context#LINK} 172 * @see #child 173 * @see #index 174 * @since 6175 175 */ 176 public Environment withChildAndIndexAndLinkContext(OsmPrimitive child, int index, int count) { 177 Environment e = new Environment(this); 178 e.child = child; 179 e.index = index; 180 e.count = count; 181 e.context = Context.LINK; 182 return e; 183 } 184 185 /** 186 * Creates a clone of this environment, with the specified index. 187 * @param index index of node in parent way or member in parent relation 188 * @param count count of nodes in parent way or members in parent relation 189 * @return A clone of this environment, with the specified index 190 * @see #index 191 */ 192 public Environment withIndex(int index, int count) { 193 Environment e = new Environment(this); 194 e.index = index; 195 e.count = count; 196 return e; 197 } 198 199 /** 200 * Creates a clone of this environment, with the specified {@link Context}. 201 * @param context context 202 * @return A clone of this environment, with the specified {@code Context} 203 */ 204 public Environment withContext(Context context) { 205 Environment e = new Environment(this); 206 e.context = context == null ? Context.PRIMITIVE : context; 207 return e; 208 } 209 210 /** 211 * Creates a clone of this environment, with context set to {@link Context#LINK}. 212 * @return A clone of this environment, with context set to {@code Context#LINK} 213 */ 214 public Environment withLinkContext() { 215 Environment e = new Environment(this); 216 e.context = Context.LINK; 217 return e; 218 } 219 220 /** 221 * Determines if the context of this environment is {@link Context#LINK}. 222 * @return {@code true} if the context of this environment is {@code Context#LINK}, {@code false} otherwise 223 */ 224 public boolean isLinkContext() { 225 return Context.LINK.equals(context); 226 } 227 228 /** 229 * Determines if this environment has a relation as parent. 230 * @return {@code true} if this environment has a relation as parent, {@code false} otherwise 231 * @see #parent 232 */ 233 public boolean hasParentRelation() { 234 return parent instanceof Relation; 235 } 236 237 /** 238 * Replies the current context. 239 * 240 * @return the current context 241 */ 242 public Context getContext() { 243 return context == null ? Context.PRIMITIVE : context; 244 } 245 246 /** 247 * Gets the role of the matching primitive in the relation 248 * @return The role 249 */ 250 public String getRole() { 251 if (getContext().equals(Context.PRIMITIVE)) 252 return null; 253 254 if (parent instanceof Relation) 255 return ((Relation) parent).getMember(index).getRole(); 256 if (child != null && osm instanceof Relation) 257 return ((Relation) osm).getMember(index).getRole(); 258 return null; 259 } 260 261 /** 262 * Clears all matching context information 263 */ 264 public void clearSelectorMatchingInformation() { 265 parent = null; 266 child = null; 267 index = null; 268 count = null; 269 } 270 271 /** 272 * Gets the current cascade for a given layer 273 * @param layer The layer to use, <code>null</code> to use the layer of the {@link Environment} 274 * @return The cascade 275 */ 276 public Cascade getCascade(String layer) { 277 return mc == null ? null : mc.getCascade(layer == null ? this.layer : layer); 278 } 279}