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 * @since 8415 056 */ 057 public Environment(OsmPrimitive osm) { 058 this.osm = osm; 059 } 060 061 /** 062 * Creates a new environment. 063 */ 064 public Environment(OsmPrimitive osm, MultiCascade mc, String layer, StyleSource source) { 065 this.osm = osm; 066 this.mc = mc; 067 this.layer = layer; 068 this.source = source; 069 } 070 071 /** 072 * Creates a clone of the environment {@code other}. 073 * 074 * @param other the other environment. Must not be null. 075 * @throws IllegalArgumentException if {@code param} is {@code null} 076 */ 077 public Environment(Environment other) { 078 CheckParameterUtil.ensureParameterNotNull(other); 079 this.osm = other.osm; 080 this.mc = other.mc; 081 this.layer = other.layer; 082 this.parent = other.parent; 083 this.child = other.child; 084 this.source = other.source; 085 this.index = other.index; 086 this.count = other.count; 087 this.context = other.getContext(); 088 } 089 090 /** 091 * Creates a clone of this environment, with the specified primitive. 092 * @return A clone of this environment, with the specified primitive 093 * @see #osm 094 */ 095 public Environment withPrimitive(OsmPrimitive osm) { 096 Environment e = new Environment(this); 097 e.osm = osm; 098 return e; 099 } 100 101 /** 102 * Creates a clone of this environment, with the specified parent. 103 * @param parent the matching parent object 104 * @return A clone of this environment, with the specified parent 105 * @see #parent 106 */ 107 public Environment withParent(OsmPrimitive parent) { 108 Environment e = new Environment(this); 109 e.parent = parent; 110 return e; 111 } 112 113 /** 114 * Creates a clone of this environment, with the specified parent, index, and context set to {@link Context#LINK}. 115 * @param parent the matching parent object 116 * @param index index of node in parent way or member in parent relation 117 * @param count count of nodes in parent way or members in parent relation 118 * @return A clone of this environment, with the specified parent, index, and context set to {@link Context#LINK} 119 * @see #parent 120 * @see #index 121 * @since 6175 122 */ 123 public Environment withParentAndIndexAndLinkContext(OsmPrimitive parent, int index, int count) { 124 Environment e = new Environment(this); 125 e.parent = parent; 126 e.index = index; 127 e.count = count; 128 e.context = Context.LINK; 129 return e; 130 } 131 132 /** 133 * Creates a clone of this environment, with the specified child. 134 * @param child the matching child object 135 * @return A clone of this environment, with the specified child 136 * @see #child 137 */ 138 public Environment withChild(OsmPrimitive child) { 139 Environment e = new Environment(this); 140 e.child = child; 141 return e; 142 } 143 144 /** 145 * Creates a clone of this environment, with the specified child, index, and context set to {@link Context#LINK}. 146 * @param child the matching child object 147 * @param index index of node in parent way or member in parent relation 148 * @param count count of nodes in parent way or members in parent relation 149 * @return A clone of this environment, with the specified child, index, and context set to {@code Context#LINK} 150 * @see #child 151 * @see #index 152 * @since 6175 153 */ 154 public Environment withChildAndIndexAndLinkContext(OsmPrimitive child, int index, int count) { 155 Environment e = new Environment(this); 156 e.child = child; 157 e.index = index; 158 e.count = count; 159 e.context = Context.LINK; 160 return e; 161 } 162 163 /** 164 * Creates a clone of this environment, with the specified index. 165 * @param index index of node in parent way or member in parent relation 166 * @param count count of nodes in parent way or members in parent relation 167 * @return A clone of this environment, with the specified index 168 * @see #index 169 */ 170 public Environment withIndex(int index, int count) { 171 Environment e = new Environment(this); 172 e.index = index; 173 e.count = count; 174 return e; 175 } 176 177 /** 178 * Creates a clone of this environment, with the specified {@link Context}. 179 * @return A clone of this environment, with the specified {@code Context} 180 */ 181 public Environment withContext(Context context) { 182 Environment e = new Environment(this); 183 e.context = context == null ? Context.PRIMITIVE : context; 184 return e; 185 } 186 187 /** 188 * Creates a clone of this environment, with context set to {@link Context#LINK}. 189 * @return A clone of this environment, with context set to {@code Context#LINK} 190 */ 191 public Environment withLinkContext() { 192 Environment e = new Environment(this); 193 e.context = Context.LINK; 194 return e; 195 } 196 197 /** 198 * Determines if the context of this environment is {@link Context#LINK}. 199 * @return {@code true} if the context of this environment is {@code Context#LINK}, {@code false} otherwise 200 */ 201 public boolean isLinkContext() { 202 return Context.LINK.equals(context); 203 } 204 205 /** 206 * Determines if this environment has a relation as parent. 207 * @return {@code true} if this environment has a relation as parent, {@code false} otherwise 208 * @see #parent 209 */ 210 public boolean hasParentRelation() { 211 return parent instanceof Relation; 212 } 213 214 /** 215 * Replies the current context. 216 * 217 * @return the current context 218 */ 219 public Context getContext() { 220 return context == null ? Context.PRIMITIVE : context; 221 } 222 223 public String getRole() { 224 if (getContext().equals(Context.PRIMITIVE)) 225 return null; 226 227 if (parent instanceof Relation) 228 return ((Relation) parent).getMember(index).getRole(); 229 if (child != null && osm instanceof Relation) 230 return ((Relation) osm).getMember(index).getRole(); 231 return null; 232 } 233 234 public void clearSelectorMatchingInformation() { 235 parent = null; 236 child = null; 237 index = null; 238 count = null; 239 } 240 241 public Cascade getCascade(String layer) { 242 return mc == null ? null : mc.getCascade(layer == null ? this.layer : layer); 243 } 244}