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