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 public OsmPrimitive osm; 018 019 public MultiCascade mc; 020 public String layer; 021 public StyleSource source; 022 private Context context = Context.PRIMITIVE; 023 public static final String DEFAULT_LAYER = "default"; 024 025 /** 026 * If not null, this is the matching parent object if a condition or an expression 027 * is evaluated in a {@link LinkSelector} (within a child selector) 028 */ 029 public OsmPrimitive parent; 030 031 /** 032 * The same for parent selector. Only one of the 2 fields (parent or child) is not null in any environment. 033 */ 034 public OsmPrimitive child; 035 036 /** 037 * index of node in parent way or member in parent relation. Must be != null in LINK context. 038 */ 039 public Integer index; 040 041 /** 042 * count of nodes in parent way or members in parent relation. Must be != null in LINK context. 043 */ 044 public Integer count; 045 046 /** 047 * Creates a new uninitialized environment. 048 */ 049 public Environment() { 050 // environment can be initialized later through with* methods 051 } 052 053 /** 054 * Creates a new environment. 055 * @param osm OSM primitive 056 * @since 8415 057 */ 058 public Environment(OsmPrimitive osm) { 059 this.osm = osm; 060 } 061 062 /** 063 * Creates a new environment. 064 * @param osm OSM primitive 065 * @param mc multi cascade 066 * @param layer layer 067 * @param source style source 068 */ 069 public Environment(OsmPrimitive osm, MultiCascade mc, String layer, StyleSource source) { 070 this.osm = osm; 071 this.mc = mc; 072 this.layer = layer; 073 this.source = source; 074 } 075 076 /** 077 * Creates a clone of the environment {@code other}. 078 * 079 * @param other the other environment. Must not be null. 080 * @throws IllegalArgumentException if {@code param} is {@code null} 081 */ 082 public Environment(Environment other) { 083 CheckParameterUtil.ensureParameterNotNull(other); 084 this.osm = other.osm; 085 this.mc = other.mc; 086 this.layer = other.layer; 087 this.parent = other.parent; 088 this.child = other.child; 089 this.source = other.source; 090 this.index = other.index; 091 this.count = other.count; 092 this.context = other.getContext(); 093 } 094 095 /** 096 * Creates a clone of this environment, with the specified primitive. 097 * @param osm OSM primitive 098 * @return A clone of this environment, with the specified primitive 099 * @see #osm 100 */ 101 public Environment withPrimitive(OsmPrimitive osm) { 102 Environment e = new Environment(this); 103 e.osm = osm; 104 return e; 105 } 106 107 /** 108 * Creates a clone of this environment, with the specified parent. 109 * @param parent the matching parent object 110 * @return A clone of this environment, with the specified parent 111 * @see #parent 112 */ 113 public Environment withParent(OsmPrimitive parent) { 114 Environment e = new Environment(this); 115 e.parent = parent; 116 return e; 117 } 118 119 /** 120 * Creates a clone of this environment, with the specified parent, index, and context set to {@link Context#LINK}. 121 * @param parent the matching parent object 122 * @param index index of node in parent way or member in parent relation 123 * @param count count of nodes in parent way or members in parent relation 124 * @return A clone of this environment, with the specified parent, index, and context set to {@link Context#LINK} 125 * @see #parent 126 * @see #index 127 * @since 6175 128 */ 129 public Environment withParentAndIndexAndLinkContext(OsmPrimitive parent, int index, int count) { 130 Environment e = new Environment(this); 131 e.parent = parent; 132 e.index = index; 133 e.count = count; 134 e.context = Context.LINK; 135 return e; 136 } 137 138 /** 139 * Creates a clone of this environment, with the specified child. 140 * @param child the matching child object 141 * @return A clone of this environment, with the specified child 142 * @see #child 143 */ 144 public Environment withChild(OsmPrimitive child) { 145 Environment e = new Environment(this); 146 e.child = child; 147 return e; 148 } 149 150 /** 151 * Creates a clone of this environment, with the specified child, index, and context set to {@link Context#LINK}. 152 * @param child the matching child object 153 * @param index index of node in parent way or member in parent relation 154 * @param count count of nodes in parent way or members in parent relation 155 * @return A clone of this environment, with the specified child, index, and context set to {@code Context#LINK} 156 * @see #child 157 * @see #index 158 * @since 6175 159 */ 160 public Environment withChildAndIndexAndLinkContext(OsmPrimitive child, int index, int count) { 161 Environment e = new Environment(this); 162 e.child = child; 163 e.index = index; 164 e.count = count; 165 e.context = Context.LINK; 166 return e; 167 } 168 169 /** 170 * Creates a clone of this environment, with the specified index. 171 * @param index index of node in parent way or member in parent relation 172 * @param count count of nodes in parent way or members in parent relation 173 * @return A clone of this environment, with the specified index 174 * @see #index 175 */ 176 public Environment withIndex(int index, int count) { 177 Environment e = new Environment(this); 178 e.index = index; 179 e.count = count; 180 return e; 181 } 182 183 /** 184 * Creates a clone of this environment, with the specified {@link Context}. 185 * @param context context 186 * @return A clone of this environment, with the specified {@code Context} 187 */ 188 public Environment withContext(Context context) { 189 Environment e = new Environment(this); 190 e.context = context == null ? Context.PRIMITIVE : context; 191 return e; 192 } 193 194 /** 195 * Creates a clone of this environment, with context set to {@link Context#LINK}. 196 * @return A clone of this environment, with context set to {@code Context#LINK} 197 */ 198 public Environment withLinkContext() { 199 Environment e = new Environment(this); 200 e.context = Context.LINK; 201 return e; 202 } 203 204 /** 205 * Determines if the context of this environment is {@link Context#LINK}. 206 * @return {@code true} if the context of this environment is {@code Context#LINK}, {@code false} otherwise 207 */ 208 public boolean isLinkContext() { 209 return Context.LINK.equals(context); 210 } 211 212 /** 213 * Determines if this environment has a relation as parent. 214 * @return {@code true} if this environment has a relation as parent, {@code false} otherwise 215 * @see #parent 216 */ 217 public boolean hasParentRelation() { 218 return parent instanceof Relation; 219 } 220 221 /** 222 * Replies the current context. 223 * 224 * @return the current context 225 */ 226 public Context getContext() { 227 return context == null ? Context.PRIMITIVE : context; 228 } 229 230 public String getRole() { 231 if (getContext().equals(Context.PRIMITIVE)) 232 return null; 233 234 if (parent instanceof Relation) 235 return ((Relation) parent).getMember(index).getRole(); 236 if (child != null && osm instanceof Relation) 237 return ((Relation) osm).getMember(index).getRole(); 238 return null; 239 } 240 241 public void clearSelectorMatchingInformation() { 242 parent = null; 243 child = null; 244 index = null; 245 count = null; 246 } 247 248 public Cascade getCascade(String layer) { 249 return mc == null ? null : mc.getCascade(layer == null ? this.layer : layer); 250 } 251}