View Javadoc
1   package org.opentrafficsim.road.network.factory.xml.old;
2   
3   import java.io.Serializable;
4   import java.util.LinkedHashMap;
5   import java.util.List;
6   import java.util.Map;
7   
8   import org.djunits.value.vdouble.scalar.Length;
9   import org.djunits.value.vdouble.scalar.Speed;
10  import org.opentrafficsim.core.gtu.GTUType;
11  import org.opentrafficsim.core.network.NetworkException;
12  import org.opentrafficsim.core.network.factory.xml.units.LengthUnits;
13  import org.opentrafficsim.core.network.factory.xml.units.SpeedUnits;
14  import org.opentrafficsim.road.network.lane.changing.LaneKeepingPolicy;
15  import org.opentrafficsim.road.network.lane.changing.OvertakingConditions;
16  import org.w3c.dom.NamedNodeMap;
17  import org.w3c.dom.Node;
18  import org.w3c.dom.NodeList;
19  import org.xml.sax.SAXException;
20  
21  /**
22   * ROADLAYOUT tag parser.
23   * 
24   * <pre>
25   * {@code
26    <xsd:element name="ROADLAYOUT">
27      <xsd:complexType>
28        <xsd:sequence>
29  
30          <xsd:element name="SPEEDLIMIT" minOccurs="0" maxOccurs="unbounded">
31            <xsd:complexType>
32              <xsd:attribute name="GTUTYPE" type="xsd:string" use="required" />
33              <xsd:attribute name="LEGALSPEEDLIMIT" type="SPEEDTYPE" use="optional" />
34            </xsd:complexType>
35          </xsd:element>
36  
37          <xsd:choice minOccurs="1" maxOccurs="unbounded">
38  
39            <xsd:element name="LANE" minOccurs="0" maxOccurs="unbounded">
40              <xsd:complexType>
41                <xsd:sequence minOccurs="0" maxOccurs="unbounded">
42                  <xsd:element name="SPEEDLIMIT" minOccurs="1" maxOccurs="unbounded">
43                    <xsd:complexType>
44                      <xsd:attribute name="GTUTYPE" type="xsd:string" use="required" />
45                      <xsd:attribute name="LEGALSPEEDLIMIT" type="SPEEDTYPE" use="optional" />
46                    </xsd:complexType>
47                  </xsd:element>
48                </xsd:sequence>
49                <xsd:attribute name="NAME" type="xsd:string" use="required" />
50                <xsd:attribute name="LANETYPE" type="xsd:string" use="optional" />
51                <xsd:attribute name="OFFSET" type="SIGNEDLENGTHTYPE" use="required" />
52                <xsd:attribute name="WIDTH" type="LENGTHTYPE" use="optional" />
53                <xsd:attribute name="DIRECTION" type="DIRECTIONTYPE" use="required" />
54                <xsd:attribute name="COLOR" type="COLORTYPE" use="optional" />
55                <xsd:attribute name="OVERTAKING" type="OVERTAKINGTYPE" use="optional" />
56              </xsd:complexType>
57            </xsd:element>
58  
59            <xsd:element name="NOTRAFFICLANE" minOccurs="0" maxOccurs="unbounded">
60              <xsd:complexType>
61                <xsd:attribute name="NAME" type="xsd:string" use="optional" />
62                <xsd:attribute name="OFFSET" type="SIGNEDLENGTHTYPE" use="required" />
63                <xsd:attribute name="WIDTH" type="LENGTHTYPE" use="optional" />
64                <xsd:attribute name="COLOR" type="COLORTYPE" use="optional" />
65              </xsd:complexType>
66            </xsd:element>
67  
68            <xsd:element name="SHOULDER" minOccurs="0" maxOccurs="unbounded">
69              <xsd:complexType>
70                <xsd:attribute name="NAME" type="xsd:string" use="optional" />
71                <xsd:attribute name="OFFSET" type="SIGNEDLENGTHTYPE" use="required" />
72                <xsd:attribute name="WIDTH" type="LENGTHTYPE" use="optional" />
73                <xsd:attribute name="COLOR" type="COLORTYPE" use="optional" />
74              </xsd:complexType>
75            </xsd:element>
76  
77            <xsd:element name="STRIPE" minOccurs="0" maxOccurs="unbounded">
78              <xsd:complexType>
79                <xsd:attribute name="NAME" type="xsd:string" use="optional" />
80                <xsd:attribute name="TYPE" type="STRIPETYPE" use="required" />
81                <xsd:attribute name="OFFSET" type="SIGNEDLENGTHTYPE" use="required" />
82                <xsd:attribute name="WIDTH" type="LENGTHTYPE" use="optional" />
83                <xsd:attribute name="COLOR" type="COLORTYPE" use="optional" />
84              </xsd:complexType>
85            </xsd:element>
86  
87          </xsd:choice>
88        </xsd:sequence>
89        <xsd:attribute name="NAME" type="xsd:string" use="required" />
90        <xsd:attribute name="ROADTYPE" type="xsd:string" use="required" />
91        <xsd:attribute name="WIDTH" type="LENGTHTYPE" use="optional" />
92        <xsd:attribute name="LANEKEEPING" type="LANEKEEPINGTYPE" use="optional" />
93        <xsd:attribute name="OVERTAKING" type="OVERTAKINGTYPE" use="optional" />
94        <xsd:attribute ref="xml:base" />
95      </xsd:complexType>
96    </xsd:element>
97   * }
98   * </pre>
99   * <p>
100  * Copyright (c) 2013-2019 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
101  * BSD-style license. See <a href="http://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
102  * <p>
103  * $LastChangedDate: 2015-07-24 02:58:59 +0200 (Fri, 24 Jul 2015) $, @version $Revision: 1147 $, by $Author: averbraeck $,
104  * initial version Jul 23, 2015 <br>
105  * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
106  */
107 class RoadLayoutTag implements Serializable
108 {
109     /** */
110     private static final long serialVersionUID = 20150723L;
111 
112     /** Name. */
113     @SuppressWarnings("checkstyle:visibilitymodifier")
114     String name = null;
115 
116     /** Road Type. */
117     @SuppressWarnings("checkstyle:visibilitymodifier")
118     RoadTypeTag roadTypeTag = null;
119 
120     /** Speed limits. */
121     @SuppressWarnings("checkstyle:visibilitymodifier")
122     Map<GTUType, Speed> legalSpeedLimits = null;
123 
124     /** The lane keeping policy, i.e., keep left, keep right or keep lane. */
125     @SuppressWarnings("checkstyle:visibilitymodifier")
126     LaneKeepingPolicy laneKeepingPolicy = null;
127 
128     /** The overtaking conditions for the lanes of this road type. */
129     @SuppressWarnings("checkstyle:visibilitymodifier")
130     OvertakingConditions overtakingConditions = null;
131 
132     /** Default lane width. */
133     @SuppressWarnings("checkstyle:visibilitymodifier")
134     Length defaultLaneWidth = null;
135 
136     /** CrossSectionElementTags, order is important, so a LinkedHashMap. */
137     @SuppressWarnings("checkstyle:visibilitymodifier")
138     Map<String, CrossSectionElementTag> cseTags = new LinkedHashMap<>();
139 
140     /**
141      * Parse the ROADLAYOUT tags. Delegates to a separate method because the RoadTypeTag can also occur inside a LINK tag. In
142      * the latter case, it should not be stored in the central map. When this parseRoadTypes method is called, the tags
143      * <b>are</b> stored in the central map in the parser class.
144      * @param nodeList NodeList; nodeList the top-level nodes of the XML-file
145      * @param parser XmlNetworkLaneParserOld; the parser with the lists of information
146      * @throws SAXException when parsing of the tag fails
147      * @throws NetworkException when parsing of the tag fails
148      */
149     @SuppressWarnings("checkstyle:needbraces")
150     static void parseRoadTypes(final NodeList nodeList, final XmlNetworkLaneParserOld parser)
151             throws SAXException, NetworkException
152     {
153         for (Node node : XMLParser.getNodes(nodeList, "ROADLAYOUT"))
154         {
155             RoadLayoutTag roadLayoutTag = parseRoadType(node, parser);
156             parser.roadLayoutTags.put(roadLayoutTag.name, roadLayoutTag);
157         }
158     }
159 
160     /**
161      * Parse the ROADLAYOUT tags.
162      * @param node Node; the ROADLAYOUT nodes of the XML-file
163      * @param parser XmlNetworkLaneParserOld; the parser with the lists of information
164      * @return the parsed RoadTypeTag
165      * @throws SAXException when parsing of the tag fails
166      * @throws NetworkException when parsing of the tag fails
167      */
168     @SuppressWarnings("checkstyle:needbraces")
169     static RoadLayoutTag parseRoadType(final Node node, final XmlNetworkLaneParserOld parser)
170             throws SAXException, NetworkException
171     {
172         NamedNodeMap attributes = node.getAttributes();
173         RoadLayoutTag roadLayoutTag = new RoadLayoutTag();
174 
175         Node name = attributes.getNamedItem("NAME");
176         if (name == null)
177             throw new SAXException("ROADLAYOUT: missing attribute NAME");
178         roadLayoutTag.name = name.getNodeValue().trim();
179         if (parser.roadLayoutTags.keySet().contains(roadLayoutTag.name))
180             throw new SAXException("ROADLAYOUT: NAME " + roadLayoutTag.name + " defined twice");
181 
182         Node roadType = attributes.getNamedItem("ROADTYPE");
183         if (roadType == null)
184             throw new SAXException("ROADLAYOUT: missing attribute ROADTYPE");
185         if (!parser.roadTypeTags.containsKey(roadType.getNodeValue().trim()))
186             throw new SAXException("ROADLAYOUT: ROADTYPE " + roadType.getNodeValue().trim() + " not defined");
187         roadLayoutTag.roadTypeTag = parser.roadTypeTags.get(roadType.getNodeValue().trim());
188 
189         Node width = attributes.getNamedItem("WIDTH");
190         if (width != null)
191             roadLayoutTag.defaultLaneWidth = LengthUnits.parseLength(width.getNodeValue());
192 
193         Node lkp = attributes.getNamedItem("LANEKEEPING");
194         if (lkp != null)
195             roadLayoutTag.laneKeepingPolicy = LaneAttributes.parseLaneKeepingPolicy(lkp.getNodeValue().trim());
196 
197         Node oc = attributes.getNamedItem("OVERTAKING");
198         if (oc != null)
199             roadLayoutTag.overtakingConditions = LaneAttributes.parseOvertakingConditions(oc.getNodeValue().trim(), parser);
200 
201         List<Node> speedLimitList = XMLParser.getNodes(node.getChildNodes(), "SPEEDLIMIT");
202         if (speedLimitList.size() > 0)
203             roadLayoutTag.legalSpeedLimits = new LinkedHashMap<>();
204         for (Node speedLimitNode : speedLimitList)
205         {
206             NamedNodeMap speedLimitAttributes = speedLimitNode.getAttributes();
207 
208             Node gtuTypeName = speedLimitAttributes.getNamedItem("GTUTYPE");
209             if (gtuTypeName == null)
210                 throw new NetworkException("ROADLAYOUT.SPEEDLIMIT: No GTUTYPE defined");
211             if (!parser.gtuTypes.containsKey(gtuTypeName.getNodeValue().trim()))
212                 throw new NetworkException("ROADLAYOUT.SPEEDLIMIT: " + roadLayoutTag.name + " GTUTYPE "
213                         + gtuTypeName.getNodeValue().trim() + " not defined");
214             GTUType gtuType = parser.gtuTypes.get(gtuTypeName.getNodeValue().trim());
215 
216             Node speedNode = speedLimitAttributes.getNamedItem("LEGALSPEEDLIMIT");
217             if (speedNode == null)
218                 throw new NetworkException("ROADLAYOUT.SPEEDLIMIT: " + roadLayoutTag.name + " GTUTYPE " + gtuType.getId()
219                         + ": LEGALSPEEDLIMIT not defined");
220             Speed speed = SpeedUnits.parseSpeed(speedNode.getNodeValue().trim());
221 
222             roadLayoutTag.legalSpeedLimits.put(gtuType, speed);
223         }
224 
225         int cseCount = 0;
226 
227         for (Node laneNode : XMLParser.getNodes(node.getChildNodes(), "LANE"))
228         {
229             CrossSectionElementTag.parseLane(laneNode, parser, roadLayoutTag);
230             cseCount++;
231         }
232 
233         for (Node ntlNode : XMLParser.getNodes(node.getChildNodes(), "NOTRAFFICLANE"))
234         {
235             CrossSectionElementTag.parseNoTrafficLane(ntlNode, parser, roadLayoutTag);
236             cseCount++;
237         }
238 
239         for (Node stripeNode : XMLParser.getNodes(node.getChildNodes(), "STRIPE"))
240         {
241             CrossSectionElementTag.parseStripe(stripeNode, parser, roadLayoutTag);
242             cseCount++;
243         }
244 
245         for (Node shoulderNode : XMLParser.getNodes(node.getChildNodes(), "SHOULDER"))
246         {
247             CrossSectionElementTag.parseShoulder(shoulderNode, parser, roadLayoutTag);
248             cseCount++;
249         }
250 
251         if (cseCount == 0)
252             throw new NetworkException("ROADLAYOUT: No elements defined for road type " + roadLayoutTag.name);
253 
254         return roadLayoutTag;
255     }
256 
257     /** {@inheritDoc} */
258     @Override
259     public String toString()
260     {
261         return "RoadLayoutTag [name=" + this.name + ", roadTypeTag=" + this.roadTypeTag + ", legalSpeedLimits="
262                 + this.legalSpeedLimits + ", laneKeepingPolicy=" + this.laneKeepingPolicy + ", overtakingConditions="
263                 + this.overtakingConditions + ", defaultLaneWidth=" + this.defaultLaneWidth + ", cseTags=" + this.cseTags + "]";
264     }
265 
266 }