1 package org.opentrafficsim.core.network.factory.xml;
2
3 import java.awt.Color;
4 import java.util.UUID;
5
6 import org.opentrafficsim.core.OTS_SCALAR;
7 import org.opentrafficsim.core.network.LongitudinalDirectionality;
8 import org.opentrafficsim.core.network.NetworkException;
9 import org.opentrafficsim.core.network.factory.xml.units.Colors;
10 import org.opentrafficsim.core.network.factory.xml.units.Directions;
11 import org.opentrafficsim.core.network.factory.xml.units.LengthUnits;
12 import org.opentrafficsim.core.network.factory.xml.units.SpeedUnits;
13 import org.opentrafficsim.core.network.lane.LaneType;
14 import org.w3c.dom.NamedNodeMap;
15 import org.w3c.dom.Node;
16 import org.xml.sax.SAXException;
17
18
19
20
21
22
23
24
25
26
27 class CrossSectionElementTag implements OTS_SCALAR
28 {
29
30 @SuppressWarnings({"javadoc", "checkstyle:javadocvariable"})
31 enum ElementType
32 {
33 LANE, NOTRAFFICLANE, SHOULDER, STRIPE
34 };
35
36
37 @SuppressWarnings({"javadoc", "checkstyle:javadocvariable"})
38 enum StripeType
39 {
40 SOLID, DASHED, BLOCKED, DOUBLE, LEFTONLY, RIGHTONLY
41 };
42
43
44 @SuppressWarnings("checkstyle:visibilitymodifier")
45 ElementType elementType = null;
46
47
48 @SuppressWarnings("checkstyle:visibilitymodifier")
49 String name = null;
50
51
52 @SuppressWarnings("checkstyle:visibilitymodifier")
53 String laneTypeString = null;
54
55
56 @SuppressWarnings("checkstyle:visibilitymodifier")
57 LaneType laneType = XmlNetworkLaneParser.noTrafficLaneType;
58
59
60 @SuppressWarnings("checkstyle:visibilitymodifier")
61 StripeType stripeType = null;
62
63
64 @SuppressWarnings("checkstyle:visibilitymodifier")
65 Length.Rel offset = null;
66
67
68 @SuppressWarnings("checkstyle:visibilitymodifier")
69 Speed.Abs speed = null;
70
71
72 @SuppressWarnings("checkstyle:visibilitymodifier")
73 Length.Rel width = null;
74
75
76 @SuppressWarnings("checkstyle:visibilitymodifier")
77 LongitudinalDirectionality direction;
78
79
80 @SuppressWarnings("checkstyle:visibilitymodifier")
81 Color color;
82
83
84
85
86
87
88
89
90
91
92 @SuppressWarnings("checkstyle:needbraces")
93 static CrossSectionElementTag
94 parseLane(final Node node, final XmlNetworkLaneParser parser, final RoadTypeTag roadTypeTag) throws SAXException,
95 NetworkException
96 {
97 NamedNodeMap attributes = node.getAttributes();
98 CrossSectionElementTag cseTag = new CrossSectionElementTag();
99
100 if (attributes.getNamedItem("NAME") == null)
101 throw new SAXException("ROADTYPE.LANE: missing attribute NAME for ROADTYPE " + roadTypeTag.name);
102 String name = attributes.getNamedItem("NAME").getNodeValue().trim();
103 if (roadTypeTag.cseTags.containsKey(name))
104 throw new SAXException("ROADTYPE.LANE: LANE NAME " + name + " defined twice");
105 cseTag.name = name;
106
107 cseTag.elementType = ElementType.LANE;
108
109 if (attributes.getNamedItem("TYPE") == null)
110 throw new SAXException("ROADTYPE.LANE: missing attribute TYPE for lane " + roadTypeTag.name + "." + name);
111 cseTag.laneTypeString = attributes.getNamedItem("TYPE").getNodeValue().trim();
112 if (!parser.laneTypes.containsKey(cseTag.laneTypeString))
113 throw new SAXException("ROADTYPE.LANE: TYPE " + cseTag.laneTypeString + " for lane " + roadTypeTag.name + "."
114 + name + " does not have compatible GTUs defined in a COMPATIBILITY element");
115 cseTag.laneType = parser.laneTypes.get(cseTag.laneTypeString);
116
117 if (attributes.getNamedItem("OFFSET") != null)
118 cseTag.offset = LengthUnits.parseLengthRel(attributes.getNamedItem("OFFSET").getNodeValue());
119 else
120 throw new SAXException("ROADTYPE.LANE: missing attribute OFFSET for lane " + roadTypeTag.name + "." + name);
121
122 if (attributes.getNamedItem("WIDTH") != null)
123 cseTag.width = LengthUnits.parseLengthRel(attributes.getNamedItem("WIDTH").getNodeValue());
124 else if (roadTypeTag.width != null)
125 cseTag.width = roadTypeTag.width;
126 else if (parser.globalTag.defaultLaneWidth != null)
127 cseTag.width = parser.globalTag.defaultLaneWidth;
128 else
129 throw new SAXException("ROADTYPE.LANE: cannot determine WIDTH for lane: " + roadTypeTag.name + "." + name);
130
131 if (attributes.getNamedItem("SPEED") != null)
132 cseTag.speed = SpeedUnits.parseSpeedAbs(attributes.getNamedItem("SPEED").getNodeValue());
133 else if (roadTypeTag.speed != null)
134 cseTag.speed = roadTypeTag.speed;
135 else if (parser.globalTag.defaultMaxSpeed != null)
136 cseTag.speed = parser.globalTag.defaultMaxSpeed;
137 else
138 throw new SAXException("ROADTYPE.LANE: cannot determine SPEED for lane: " + roadTypeTag.name + "." + name);
139
140 if (attributes.getNamedItem("DIRECTION") == null)
141 throw new SAXException("ROADTYPE.LANE: missing attribute DIRECTION for lane " + roadTypeTag.name + "." + name);
142 cseTag.direction = Directions.parseDirection(attributes.getNamedItem("DIRECTION").getNodeValue());
143
144 if (attributes.getNamedItem("COLOR") != null)
145 cseTag.color = Colors.parseColor(attributes.getNamedItem("COLOR").getNodeValue());
146 else
147 cseTag.color = Color.LIGHT_GRAY;
148
149 roadTypeTag.cseTags.put(cseTag.name, cseTag);
150 return cseTag;
151 }
152
153
154
155
156
157
158
159
160
161
162 @SuppressWarnings("checkstyle:needbraces")
163 static CrossSectionElementTag parseNoTrafficLane(final Node node, final XmlNetworkLaneParser parser,
164 final RoadTypeTag roadTypeTag) throws SAXException, NetworkException
165 {
166 NamedNodeMap attributes = node.getAttributes();
167 CrossSectionElementTag cseTag = new CrossSectionElementTag();
168
169 String name;
170 if (attributes.getNamedItem("NAME") != null)
171 name = attributes.getNamedItem("NAME").getNodeValue().trim();
172 else
173 name = UUID.randomUUID().toString();
174 if (roadTypeTag.cseTags.containsKey(name))
175 throw new SAXException("ROADTYPE.NOTRAFFICLANE: LANE NAME " + name + " defined twice");
176 cseTag.name = name;
177
178 cseTag.elementType = ElementType.NOTRAFFICLANE;
179
180 if (attributes.getNamedItem("OFFSET") != null)
181 cseTag.offset = LengthUnits.parseLengthRel(attributes.getNamedItem("OFFSET").getNodeValue());
182 else
183 throw new SAXException("ROADTYPE.LANE: missing attribute OFFSET for lane " + roadTypeTag.name + "." + name);
184
185 if (attributes.getNamedItem("WIDTH") != null)
186 cseTag.width = LengthUnits.parseLengthRel(attributes.getNamedItem("WIDTH").getNodeValue());
187 else if (roadTypeTag.width != null)
188 cseTag.width = roadTypeTag.width;
189 else if (parser.globalTag.defaultLaneWidth != null)
190 cseTag.width = parser.globalTag.defaultLaneWidth;
191 else
192 throw new SAXException("ROADTYPE.NOTRAFFICLANE: cannot determine WIDTH for NOTRAFFICLANE: " + roadTypeTag.name
193 + "." + name);
194
195 if (attributes.getNamedItem("COLOR") != null)
196 cseTag.color = Colors.parseColor(attributes.getNamedItem("COLOR").getNodeValue());
197 else
198 cseTag.color = Color.GRAY;
199
200 roadTypeTag.cseTags.put(cseTag.name, cseTag);
201 return cseTag;
202 }
203
204
205
206
207
208
209
210
211
212
213 @SuppressWarnings("checkstyle:needbraces")
214 static CrossSectionElementTag parseShoulder(final Node node, final XmlNetworkLaneParser parser,
215 final RoadTypeTag roadTypeTag) throws SAXException, NetworkException
216 {
217 NamedNodeMap attributes = node.getAttributes();
218 CrossSectionElementTag cseTag = new CrossSectionElementTag();
219
220 String name;
221 if (attributes.getNamedItem("NAME") != null)
222 name = attributes.getNamedItem("NAME").getNodeValue().trim();
223 else
224 name = UUID.randomUUID().toString();
225 if (roadTypeTag.cseTags.containsKey(name))
226 throw new SAXException("ROADTYPE.SHOULDER: LANE NAME " + name + " defined twice");
227 cseTag.name = name;
228
229 cseTag.elementType = ElementType.SHOULDER;
230
231 if (attributes.getNamedItem("OFFSET") != null)
232 cseTag.offset = LengthUnits.parseLengthRel(attributes.getNamedItem("OFFSET").getNodeValue());
233 else
234 throw new SAXException("ROADTYPE.LANE: missing attribute OFFSET for lane " + roadTypeTag.name + "." + name);
235
236 if (attributes.getNamedItem("WIDTH") != null)
237 cseTag.width = LengthUnits.parseLengthRel(attributes.getNamedItem("WIDTH").getNodeValue());
238 else if (roadTypeTag.width != null)
239 cseTag.width = roadTypeTag.width;
240 else if (parser.globalTag.defaultLaneWidth != null)
241 cseTag.width = parser.globalTag.defaultLaneWidth;
242 else
243 throw new SAXException("ROADTYPE.SHOULDER: cannot determine WIDTH for NOTRAFFICLANE: " + roadTypeTag.name + "."
244 + name);
245
246 if (attributes.getNamedItem("COLOR") != null)
247 cseTag.color = Colors.parseColor(attributes.getNamedItem("COLOR").getNodeValue());
248 else
249 cseTag.color = Color.GREEN;
250
251 roadTypeTag.cseTags.put(cseTag.name, cseTag);
252 return cseTag;
253 }
254
255
256
257
258
259
260
261
262
263
264 @SuppressWarnings("checkstyle:needbraces")
265 static CrossSectionElementTag parseStripe(final Node node, final XmlNetworkLaneParser parser,
266 final RoadTypeTag roadTypeTag) throws SAXException, NetworkException
267 {
268 NamedNodeMap attributes = node.getAttributes();
269 CrossSectionElementTag cseTag = new CrossSectionElementTag();
270
271 String name;
272 if (attributes.getNamedItem("NAME") != null)
273 name = attributes.getNamedItem("NAME").getNodeValue().trim();
274 else
275 name = UUID.randomUUID().toString();
276 if (roadTypeTag.cseTags.containsKey(name))
277 throw new SAXException("ROADTYPE.STRIPE: LANE NAME " + name + " defined twice");
278 cseTag.name = name;
279
280 cseTag.elementType = ElementType.STRIPE;
281
282 if (attributes.getNamedItem("TYPE") != null)
283 cseTag.stripeType = parseStripeType(attributes.getNamedItem("TYPE").getNodeValue());
284
285 if (attributes.getNamedItem("OFFSET") != null)
286 cseTag.offset = LengthUnits.parseLengthRel(attributes.getNamedItem("OFFSET").getNodeValue());
287 else
288 throw new SAXException("ROADTYPE.LANE: missing attribute OFFSET for lane " + roadTypeTag.name + "." + name);
289
290 if (attributes.getNamedItem("WIDTH") != null)
291 cseTag.width = LengthUnits.parseLengthRel(attributes.getNamedItem("WIDTH").getNodeValue());
292 else
293 cseTag.width = new Length.Rel(0.2, METER);
294
295 if (attributes.getNamedItem("COLOR") != null)
296 cseTag.color = Colors.parseColor(attributes.getNamedItem("COLOR").getNodeValue());
297 else
298 cseTag.color = Color.WHITE;
299
300 roadTypeTag.cseTags.put(cseTag.name, cseTag);
301 return cseTag;
302 }
303
304
305
306
307
308
309 private static StripeType parseStripeType(final String stripeStr) throws NetworkException
310 {
311 if (stripeStr.equals("SOLID"))
312 {
313 return StripeType.SOLID;
314 }
315 else if (stripeStr.equals("DASHED"))
316 {
317 return StripeType.DASHED;
318 }
319 else if (stripeStr.equals("BLOCKED"))
320 {
321 return StripeType.BLOCKED;
322 }
323 else if (stripeStr.equals("DOUBLE"))
324 {
325 return StripeType.DOUBLE;
326 }
327 else if (stripeStr.equals("LEFTONLY"))
328 {
329 return StripeType.LEFTONLY;
330 }
331 else if (stripeStr.equals("RIGHTONLY"))
332 {
333 return StripeType.RIGHTONLY;
334 }
335 throw new NetworkException("Unknown stripe type: " + stripeStr);
336 }
337
338 }