View Javadoc
1   package org.opentrafficsim.road.network.factory.xml.old;
2   
3   import java.io.IOException;
4   import java.io.InputStream;
5   import java.io.Serializable;
6   import java.net.URL;
7   import java.rmi.RemoteException;
8   import java.util.ArrayList;
9   import java.util.HashMap;
10  import java.util.HashSet;
11  import java.util.LinkedHashSet;
12  import java.util.List;
13  import java.util.Map;
14  import java.util.Set;
15  
16  import javax.naming.NamingException;
17  import javax.xml.parsers.DocumentBuilder;
18  import javax.xml.parsers.DocumentBuilderFactory;
19  import javax.xml.parsers.ParserConfigurationException;
20  
21  import org.djunits.unit.FrequencyUnit;
22  import org.djunits.unit.TimeUnit;
23  import org.djunits.value.StorageType;
24  import org.djunits.value.ValueException;
25  import org.djunits.value.vdouble.vector.FrequencyVector;
26  import org.djunits.value.vdouble.vector.TimeVector;
27  import org.djutils.immutablecollections.Immutable;
28  import org.djutils.immutablecollections.ImmutableArrayList;
29  import org.djutils.immutablecollections.ImmutableList;
30  import org.opentrafficsim.base.parameters.ParameterException;
31  import org.opentrafficsim.core.animation.gtu.colorer.GTUColorer;
32  import org.opentrafficsim.core.animation.network.NetworkAnimation;
33  import org.opentrafficsim.core.dsol.OTSSimulatorInterface;
34  import org.opentrafficsim.core.geometry.OTSGeometryException;
35  import org.opentrafficsim.core.geometry.OTSLine3D;
36  import org.opentrafficsim.core.geometry.OTSPoint3D;
37  import org.opentrafficsim.core.gtu.GTUException;
38  import org.opentrafficsim.core.gtu.GTUType;
39  import org.opentrafficsim.core.gtu.TemplateGTUType;
40  import org.opentrafficsim.core.network.Link;
41  import org.opentrafficsim.core.network.LinkType;
42  import org.opentrafficsim.core.network.NetworkException;
43  import org.opentrafficsim.core.network.OTSNode;
44  import org.opentrafficsim.road.gtu.generator.od.DefaultGTUCharacteristicsGeneratorOD;
45  import org.opentrafficsim.road.gtu.generator.od.GTUCharacteristicsGeneratorOD;
46  import org.opentrafficsim.road.gtu.generator.od.ODOptions;
47  import org.opentrafficsim.road.gtu.strategical.od.Categorization;
48  import org.opentrafficsim.road.gtu.strategical.od.Category;
49  import org.opentrafficsim.road.gtu.strategical.od.Interpolation;
50  import org.opentrafficsim.road.gtu.strategical.od.ODMatrix;
51  import org.opentrafficsim.road.network.OTSRoadNetwork;
52  import org.opentrafficsim.road.network.factory.xml.XmlParserException;
53  import org.opentrafficsim.road.network.factory.xml.demand.XmlOdParser;
54  import org.opentrafficsim.road.network.lane.CrossSectionLink;
55  import org.opentrafficsim.road.network.lane.LaneType;
56  import org.opentrafficsim.road.network.lane.changing.LaneKeepingPolicy;
57  import org.w3c.dom.Comment;
58  import org.w3c.dom.Document;
59  import org.w3c.dom.Node;
60  import org.w3c.dom.NodeList;
61  import org.xml.sax.SAXException;
62  
63  import nl.tudelft.simulation.dsol.SimRuntimeException;
64  
65  /**
66   * <p>
67   * Copyright (c) 2013-2019 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
68   * BSD-style license. See <a href="http://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
69   * <p>
70   * $LastChangedDate: 2015-07-24 02:58:59 +0200 (Fri, 24 Jul 2015) $, @version $Revision: 1147 $, by $Author: averbraeck $,
71   * initial version Jul 23, 2015 <br>
72   * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
73   */
74  public class XmlNetworkLaneParserOld implements Serializable
75  {
76      /** */
77      private static final long serialVersionUID = 20150723L;
78  
79      /** Global values from the GLOBAL tag. */
80      @SuppressWarnings("visibilitymodifier")
81      protected GlobalTag globalTag;
82  
83      /** The UNprocessed nodes for further reference. */
84      @SuppressWarnings("visibilitymodifier")
85      protected Map<String, NodeTag> nodeTags = new HashMap<>();
86  
87      /** The UNprocessed connectors for further reference. */
88      @SuppressWarnings("visibilitymodifier")
89      protected Map<String, ConnectorTag> connectorTags = new HashMap<>();
90  
91      /** The UNprocessed links for further reference. */
92      @SuppressWarnings("visibilitymodifier")
93      protected Map<String, LinkTag> linkTags = new HashMap<>();
94  
95      /** The GTU tags for further reference. */
96      @SuppressWarnings("visibilitymodifier")
97      public Map<String, GTUTag> gtuTags = new HashMap<>();
98  
99      /** The GTUmix tags for further reference. */
100     @SuppressWarnings("visibilitymodifier")
101     protected Map<String, GTUMixTag> gtuMixTags = new HashMap<>();
102 
103     /** The route tags for further reference. */
104     @SuppressWarnings("visibilitymodifier")
105     protected Map<String, RouteTag> routeTags = new HashMap<>();
106 
107     /** The route mix tags for further reference. */
108     @SuppressWarnings("visibilitymodifier")
109     protected Map<String, RouteMixTag> routeMixTags = new HashMap<>();
110 
111     /** The shortest route tags for further reference. */
112     @SuppressWarnings("visibilitymodifier")
113     protected Map<String, ShortestRouteTag> shortestRouteTags = new HashMap<>();
114 
115     /** The shortest route mix tags for further reference. */
116     @SuppressWarnings("visibilitymodifier")
117     protected Map<String, ShortestRouteMixTag> shortestRouteMixTags = new HashMap<>();
118 
119     /** The road type tags for further reference. */
120     @SuppressWarnings("visibilitymodifier")
121     protected Map<String, RoadTypeTag> roadTypeTags = new HashMap<>();
122 
123     /** The road layout tags for further reference. */
124     @SuppressWarnings("visibilitymodifier")
125     protected Map<String, RoadLayoutTag> roadLayoutTags = new HashMap<>();
126 
127     /** The GTUTypes that have been created. public to make it accessible from LaneAttributes. */
128     @SuppressWarnings("visibilitymodifier")
129     public Map<String, GTUType> gtuTypes = new HashMap<>();
130 
131     /** The LaneType tags that have been created. */
132     @SuppressWarnings("visibilitymodifier")
133     protected Map<String, LaneTypeTag> laneTypeTags = new HashMap<>();
134 
135     /** The LaneTypes that have been created. */
136     @SuppressWarnings("visibilitymodifier")
137     protected Map<String, LaneType> laneTypes = new HashMap<>();
138 
139     /** The simulator for creating the animation. Null if no animation needed. */
140     @SuppressWarnings("visibilitymodifier")
141     protected OTSSimulatorInterface simulator;
142 
143     /** The network to register the nodes, links, roads, lanes, and GTUs in. */
144     @SuppressWarnings("visibilitymodifier")
145     protected OTSRoadNetwork network;
146 
147     /** The network to register the drawing information for the network in. */
148     @SuppressWarnings("visibilitymodifier")
149     protected NetworkAnimation networkAnimation;
150 
151     /** All comments encountered in the XML file. */
152     List<String> xmlComments = new ArrayList<>();
153 
154     /**
155      * @param simulator OTSSimulatorInterface; the simulator for creating the animation. Null if no animation needed.
156      */
157     public XmlNetworkLaneParserOld(final OTSSimulatorInterface simulator)
158     {
159         this.simulator = simulator;
160         LaneTypeTag laneTypeTagNoTraffic = new LaneTypeTag();
161         laneTypeTagNoTraffic.name = "NOTRAFFIC";
162         this.laneTypeTags.put(laneTypeTagNoTraffic.name, laneTypeTagNoTraffic);
163     }
164 
165     /**
166      * @param simulator OTSSimulatorInterface; the simulator for creating the animation. Null if no animation needed.
167      * @param colorer GTUColorer; GTU colorer
168      */
169     public XmlNetworkLaneParserOld(final OTSSimulatorInterface simulator, final GTUColorer colorer)
170     {
171         this.simulator = simulator;
172         GTUColorerTag.defaultColorer = colorer;
173         LaneTypeTag laneTypeTagNoTraffic = new LaneTypeTag();
174         laneTypeTagNoTraffic.name = "NOTRAFFIC";
175         this.laneTypeTags.put(laneTypeTagNoTraffic.name, laneTypeTagNoTraffic);
176     }
177 
178     /**
179      * @param url URL; the file with the network in the agreed xml-grammar.
180      * @param interpretXMLComments boolean; if true; interpret specifically formatted XML comments and modify the network
181      *            accordingly
182      * @return the network with Nodes, Links, and Lanes.
183      * @throws NetworkException in case of parsing problems.
184      * @throws SAXException in case of parsing problems.
185      * @throws ParserConfigurationException in case of parsing problems.
186      * @throws IOException in case of file reading problems.
187      * @throws NamingException in case the animation context cannot be found
188      * @throws GTUException in case of a problem with creating the LaneBlock (which is a GTU right now)
189      * @throws OTSGeometryException when construction of a lane contour or offset design line fails
190      * @throws SimRuntimeException when simulator cannot be used to schedule GTU generation
191      * @throws ParameterException ...
192      * @throws ValueException ...
193      */
194     @SuppressWarnings("checkstyle:needbraces")
195     public final OTSRoadNetwork build(final URL url, boolean interpretXMLComments)
196             throws NetworkException, ParserConfigurationException, SAXException, IOException, NamingException, GTUException,
197             OTSGeometryException, SimRuntimeException, ValueException, ParameterException
198     {
199         return build(url, new OTSRoadNetwork(url.toString(), true), interpretXMLComments);
200     }
201 
202     /**
203      * @param stream InputStream; the input stream with the network in the agreed xml-grammar.
204      * @param interpretXMLComments boolean; if true; interpret specifically formatted XML comments and modify the network
205      *            accordingly
206      * @return the network with Nodes, Links, and Lanes.
207      * @throws NetworkException in case of parsing problems.
208      * @throws SAXException in case of parsing problems.
209      * @throws ParserConfigurationException in case of parsing problems.
210      * @throws IOException in case of file reading problems.
211      * @throws NamingException in case the animation context cannot be found
212      * @throws GTUException in case of a problem with creating the LaneBlock (which is a GTU right now)
213      * @throws OTSGeometryException when construction of a lane contour or offset design line fails
214      * @throws SimRuntimeException when simulator cannot be used to schedule GTU generation
215      * @throws ParameterException ...
216      * @throws ValueException ...
217      */
218     @SuppressWarnings("checkstyle:needbraces")
219     public final OTSRoadNetwork build(final InputStream stream, boolean interpretXMLComments)
220             throws NetworkException, ParserConfigurationException, SAXException, IOException, NamingException, GTUException,
221             OTSGeometryException, SimRuntimeException, ValueException, ParameterException
222     {
223         return build(stream, new OTSRoadNetwork(stream.toString(), true), interpretXMLComments);
224     }
225 
226     /**
227      * @param url URL; the file with the network in the agreed xml-grammar.
228      * @param otsNetwork OTSRoadNetwork; the network
229      * @param interpretXMLComments boolean; if true; interpret specifically formatted XML comments and modify the network
230      *            accordingly
231      * @return the network with Nodes, Links, and Lanes.
232      * @throws NetworkException in case of parsing problems.
233      * @throws SAXException in case of parsing problems.
234      * @throws ParserConfigurationException in case of parsing problems.
235      * @throws IOException in case of file reading problems.
236      * @throws NamingException in case the animation context cannot be found
237      * @throws GTUException in case of a problem with creating the LaneBlock (which is a GTU right now)
238      * @throws OTSGeometryException when construction of a lane contour or offset design line fails
239      * @throws SimRuntimeException when simulator cannot be used to schedule GTU generation
240      * @throws ParameterException ...
241      * @throws ValueException ...
242      */
243     @SuppressWarnings("checkstyle:needbraces")
244     public final OTSRoadNetwork build(final URL url, final OTSRoadNetwork otsNetwork, boolean interpretXMLComments)
245             throws NetworkException, ParserConfigurationException, SAXException, IOException, NamingException, GTUException,
246             OTSGeometryException, SimRuntimeException, ValueException, ParameterException
247     {
248         return build(url.openStream(), otsNetwork, interpretXMLComments);
249     }
250 
251     /**
252      * @param stream InputStream; the input stream with the network in the agreed xml-grammar.
253      * @param otsNetwork OTSRoadNetwork; the network
254      * @param interpretXMLComments boolean; if true; interpret specifically formatted XML comments and modify the network
255      *            accordingly
256      * @return the network with Nodes, Links, and Lanes.
257      * @throws NetworkException in case of parsing problems.
258      * @throws SAXException in case of parsing problems.
259      * @throws ParserConfigurationException in case of parsing problems.
260      * @throws IOException in case of file reading problems.
261      * @throws NamingException in case the animation context cannot be found
262      * @throws GTUException in case of a problem with creating the LaneBlock (which is a GTU right now)
263      * @throws OTSGeometryException when construction of a lane contour or offset design line fails
264      * @throws SimRuntimeException when simulator cannot be used to schedule GTU generation
265      * @throws ParameterException ...
266      * @throws ValueException ...
267      */
268     @SuppressWarnings("checkstyle:needbraces")
269     public final OTSRoadNetwork build(final InputStream stream, final OTSRoadNetwork otsNetwork, boolean interpretXMLComments)
270             throws NetworkException, ParserConfigurationException, SAXException, IOException, NamingException, GTUException,
271             OTSGeometryException, SimRuntimeException, ValueException, ParameterException
272     {
273         // try
274         // {
275         // if (url.getFile().length() > 0 && !(new File(url.toURI()).exists()))
276         // throw new SAXException("XmlNetworkLaneParser.build: File " + url.getFile() + " does not exist");
277         // }
278         // catch (URISyntaxException exception)
279         // {
280         // throw new SAXException("XmlNetworkLaneParser.build: File " + url.getFile() + " is not properly formatted",
281         // exception);
282         // }
283         this.network = otsNetwork;
284         this.networkAnimation = new NetworkAnimation(this.network);
285         this.xmlComments.clear();
286 
287         DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
288         factory.setNamespaceAware(true);
289         factory.setXIncludeAware(true);
290         DocumentBuilder builder = factory.newDocumentBuilder();
291         Document document = builder.parse(stream);
292         NodeList networkNodeList = document.getDocumentElement().getChildNodes();
293 
294         for (int i = 0; i < networkNodeList.getLength(); i++)
295         {
296             Node node = networkNodeList.item(i);
297             if (node instanceof Comment)
298             {
299                 this.xmlComments.add(node.getTextContent());
300             }
301         }
302 
303         if (!document.getDocumentElement().getNodeName().equals("NETWORK"))
304             throw new SAXException("XmlNetworkLaneParser.build: XML document does not start with an NETWORK tag, found "
305                     + document.getDocumentElement().getNodeName() + " instead");
306 
307         // there should be some definitions using DEFINITIONS tags (could be more than one due to include files)
308         List<Node> definitionNodes = XMLParser.getNodes(networkNodeList, "DEFINITIONS");
309 
310         if (definitionNodes.size() == 0)
311             throw new SAXException("XmlNetworkLaneParser.build: XML document does not have a DEFINITIONS tag");
312 
313         // make the GTUTypes ALL and NONE to get started
314         this.gtuTypes.put("ALL", otsNetwork.getGtuType(GTUType.DEFAULTS.VEHICLE));
315         // this.gtuTypes.put("NONE", GTUType.NONE);
316 
317         // parse the DEFINITIONS tags
318         for (Node definitionNode : definitionNodes)
319             GlobalTag.parseGlobal(definitionNode.getChildNodes(), this);
320         for (Node definitionNode : definitionNodes)
321             GTUTypeTag.parseGTUTypes(definitionNode.getChildNodes(), this);
322         for (Node definitionNode : definitionNodes)
323             GTUTag.parseGTUs(definitionNode.getChildNodes(), this);
324         for (Node definitionNode : definitionNodes)
325             GTUMixTag.parseGTUMix(definitionNode.getChildNodes(), this);
326         for (Node definitionNode : definitionNodes)
327             RoadTypeTag.parseRoadTypes(definitionNode.getChildNodes(), this);
328         for (Node definitionNode : definitionNodes)
329             LaneTypeTag.parseLaneTypes(definitionNode.getChildNodes(), this);
330         for (Node definitionNode : definitionNodes)
331             RoadLayoutTag.parseRoadTypes(definitionNode.getChildNodes(), this);
332 
333         // parse the NETWORK tag
334         NodeTag.parseNodes(networkNodeList, this);
335         RouteTag.parseRoutes(networkNodeList, this);
336         ShortestRouteTag.parseShortestRoutes(networkNodeList, this);
337         RouteMixTag.parseRouteMix(networkNodeList, this);
338         ShortestRouteMixTag.parseShortestRouteMix(networkNodeList, this);
339         ConnectorTag.parseConnectors(networkNodeList, this);
340         LinkTag.parseLinks(networkNodeList, this);
341 
342         // process nodes and links to calculate coordinates and positions
343         for (LinkTag linkTag : this.linkTags.values())
344             Links.calculateNodeAngles(linkTag);
345         for (ConnectorTag connectorTag : this.connectorTags.values())
346             Links.buildConnector(connectorTag, this, this.simulator);
347         for (LinkTag linkTag : this.linkTags.values())
348             Links.buildLink(linkTag, this, this.simulator);
349         for (LinkTag linkTag : this.linkTags.values())
350             Links.applyRoadTypeToLink(linkTag, this, this.simulator);
351 
352         // process the routes
353         for (RouteTag routeTag : this.routeTags.values())
354             routeTag.makeRoute();
355         // TODO shortestRoute, routeMix, ShortestRouteMix
356 
357         // store the structure information in the network
358         makeNetwork();
359         if (interpretXMLComments)
360         {
361             // fixOD(result);
362         }
363 
364         List<Node> od = XMLParser.getNodes(networkNodeList, "OD");
365         if (od.size() == 1)
366         {
367             Set<TemplateGTUType> templates = new LinkedHashSet<>();
368             for (String gtuType : this.gtuTags.keySet())
369             {
370                 GTUTag gtuTag = this.gtuTags.get(gtuType);
371                 templates.add(new TemplateGTUType(this.gtuTypes.get(gtuType), gtuTag.lengthDist, gtuTag.widthDist,
372                         gtuTag.maxSpeedDist));
373             }
374             GTUCharacteristicsGeneratorOD gtuTypeGenerator = new DefaultGTUCharacteristicsGeneratorOD(templates);
375             ODOptions odOptions = new ODOptions().set(ODOptions.GTU_TYPE, gtuTypeGenerator);
376             // TODO add chosen model in gtuTypeGenerator
377             XmlOdParser xmlOdParser =
378                     new XmlOdParser(this.simulator, this.network, new LinkedHashSet<>(this.gtuTypes.values()));
379             try
380             {
381                 xmlOdParser.apply(od.get(0), odOptions);
382             }
383             catch (XmlParserException exception)
384             {
385                 throw new SAXException("Exception while applying OD.", exception);
386             }
387         }
388         else if (od.size() > 1)
389         {
390             throw new SAXException("XmlNetworkLaneParser.build: XML document contains multiple OD tags");
391         }
392         return this.network;
393     }
394 
395     /**
396      * Retrieve the OD info from the XML comments and apply it to the network.
397      * @param otsNetwork OTSRoadNetwork; the network
398      * @throws NetworkException should never happen (of course)
399      * @throws OTSGeometryException might happen if a centroid is positioned on top of the entry exit point of a link
400      * @throws NamingException on error
401      * @throws RemoteException on error
402      * @throws ValueException on error
403      * @throws SimRuntimeException on error
404      * @throws ParameterException on error
405      */
406     private void fixOD(final OTSRoadNetwork otsNetwork) throws NetworkException, OTSGeometryException, RemoteException,
407             NamingException, ValueException, ParameterException, SimRuntimeException
408     {
409         // Reduce the list to only OD comments and strip the OD header and parse each into a key-value map.
410         Map<String, Map<String, String>> odInfo = new HashMap<>();
411         for (String comment : getXMLComments())
412         {
413             if (comment.startsWith("OD "))
414             {
415                 String odText = comment.substring(3);
416                 odInfo.put(odText, parseODLine(odText));
417             }
418         }
419         System.out.println("There are " + odInfo.size() + " OD comments");
420         // Find the GTUTypes
421         List<GTUType> odGTUTypes = new ArrayList<>(this.gtuTypes.values());
422         for (GTUType gtuType : odGTUTypes)
423         {
424             if (otsNetwork.getGtuType(GTUType.DEFAULTS.VEHICLE).equals(gtuType))
425             {
426                 odGTUTypes.remove(gtuType);
427                 break;
428             }
429         }
430         double startTime = Double.NaN;
431         // Extract the simulation start time
432         for (Map<String, String> map : odInfo.values())
433         {
434             String startTimeString = map.get("simulationStartTime");
435             if (null != startTimeString)
436             {
437                 startTime = Double.parseDouble(startTimeString);
438             }
439         }
440         if (Double.isNaN(startTime))
441         {
442             throw new NetworkException("Cannot find start time XML comment");
443         }
444         // Construct the centroid nodes and the links between the centroid nodes and the generation and extraction nodes
445         Set<org.opentrafficsim.core.network.Node> origins = new HashSet<>();
446         Set<org.opentrafficsim.core.network.Node> destinations = new HashSet<>();
447         Set<String> startTimeStrings = new HashSet<>();
448         Map<String, String> durations = new HashMap<>();
449         for (Map<String, String> map : odInfo.values())
450         {
451             String od = map.get("od");
452             if (null == od)
453             {
454                 continue;
455             }
456             String startTimeString = map.get("startTime");
457             if (null != startTimeString)
458             {
459                 startTimeStrings.add(startTimeString);
460                 String durationString = map.get("duration");
461                 if (null == durationString)
462                 {
463                     throw new NetworkException("No duration specified");
464                 }
465                 String old = durations.get(startTimeString);
466                 if (null != old && (!durationString.equals(old)))
467                 {
468                     throw new NetworkException("Duration for period starting at " + startTimeString + " changed from " + old
469                             + " to " + durationString);
470                 }
471                 else
472                 {
473                     durations.put(startTimeString, durationString);
474                 }
475             }
476             String centroidName = map.get("centroid");
477             String[] coordinates = map.get("centroidLocation").split(",");
478             OTSPoint3D centroidPoint = new OTSPoint3D(Double.parseDouble(coordinates[0]), Double.parseDouble(coordinates[1]));
479             org.opentrafficsim.core.network.Node centroidNode = otsNetwork.getNode(centroidName);
480             if (null == centroidNode)
481             {
482                 centroidNode = new OTSNode(otsNetwork, centroidName, centroidPoint);
483             }
484             String linkId = map.get("link");
485             Link link = otsNetwork.getLink(linkId);
486             if (null == link)
487             {
488                 throw new NetworkException("Cannot find link with id \"" + linkId + "\"");
489             }
490             org.opentrafficsim.core.network.Node from = null;
491             org.opentrafficsim.core.network.Node to = null;
492             if ("attracts".equals(od))
493             {
494                 destinations.add(centroidNode);
495                 from = link.getEndNode();
496                 to = centroidNode;
497 
498             }
499             else if ("generates".equals(od))
500             {
501                 origins.add(centroidNode);
502                 from = centroidNode;
503                 to = link.getStartNode();
504             }
505             OTSLine3D designLine = new OTSLine3D(from.getPoint(), to.getPoint());
506             String linkName = String.format("connector_from_%s_to_%s", from.getId(), to.getId());
507             Link connectorLink = otsNetwork.getLink(linkName);
508             if (null == connectorLink)
509             {
510                 System.out.println("Constructing connector link " + linkName);
511                 connectorLink = new CrossSectionLink(otsNetwork, linkName, from, to,
512                         otsNetwork.getLinkType(LinkType.DEFAULTS.CONNECTOR), designLine, this.simulator,
513                         LaneKeepingPolicy.KEEPRIGHT);
514             }
515         }
516         if (startTimeStrings.size() > 1)
517         {
518             throw new NetworkException("Cannot handle multiple start times - yet");
519         }
520         if (startTimeStrings.size() == 0)
521         {
522             throw new NetworkException("Missing start time XML comment");
523         }
524         String startTimeString = startTimeStrings.iterator().next();
525         double start = Double.parseDouble(startTimeString);
526         start = 0;
527         double duration = Double.parseDouble(durations.get(startTimeString));
528         TimeVector tv = new TimeVector(new double[] {start, start + duration}, TimeUnit.BASE, StorageType.DENSE);
529         // Categorization categorization = new Categorization("AimsunOTSExport", firstGTUType, otherGTUTypes);
530         Categorization categorization = new Categorization("AimsunOTSExport", GTUType.class);
531         ODMatrix od = new ODMatrix("ODExample", new ArrayList<>(origins), new ArrayList<>(destinations), categorization, tv,
532                 Interpolation.STEPWISE);
533         for (Map<String, String> map : odInfo.values())
534         {
535             String flow = map.get("flow");
536             if (null == flow)
537             {
538                 continue;
539             }
540             String vehicleClassName = map.get("vehicleClass");
541             GTUType gtuType = null;
542             for (GTUType gt : odGTUTypes)
543             {
544                 if (gt.getId().equals(vehicleClassName))
545                 {
546                     gtuType = gt;
547                 }
548             }
549             if (null == gtuType)
550             {
551                 throw new NetworkException("Can not find GTUType with name " + vehicleClassName);
552             }
553             Category category = new Category(categorization, gtuType);
554             org.opentrafficsim.core.network.Node from = otsNetwork.getNode(map.get("origin"));
555             org.opentrafficsim.core.network.Node to = otsNetwork.getNode(map.get("destination"));
556             FrequencyVector demand = new FrequencyVector(new double[] {Double.parseDouble(map.get("flow")), 0},
557                     FrequencyUnit.PER_HOUR, StorageType.DENSE);
558             od.putDemandVector(from, to, category, demand);
559             System.out.println(
560                     "Adding demand from " + from.getId() + " to " + to.getId() + " category " + category + ": " + demand);
561         }
562         Set<TemplateGTUType> templates = new HashSet<>();
563         for (GTUType gtuType : odGTUTypes)
564         {
565             GTUTag gtuTag = this.gtuTags.get(gtuType.getId());
566             templates.add(new TemplateGTUType(gtuType, gtuTag.lengthDist, gtuTag.widthDist, gtuTag.maxSpeedDist));
567         }
568         od.print();
569     }
570 
571     /**
572      * Parse a line that should look like a list of key=value pairs.
573      * @param line String; the line to parse
574      * @return Map&lt;String,String&gt;; the parsed line
575      */
576     private Map<String, String> parseODLine(final String line)
577     {
578         Map<String, String> result = new HashMap<>();
579         // For now we'll assume that names of centroids, links and nodes do not contain spaces.
580         for (String pair : line.split(" "))
581         {
582             String[] fields = pair.split("=");
583             // Concatenate elements 1..n
584             for (int index = fields.length; --index >= 2;)
585             {
586                 fields[index - 1] += "=" + fields[index];
587             }
588             if (fields.length < 2)
589             {
590                 throw new IndexOutOfBoundsException("can not find equals sign in \"" + pair + "\"");
591             }
592             if (fields[1].startsWith("\"") && fields[1].endsWith("\"") && fields[1].length() >= 2)
593             {
594                 fields[1] = fields[1].substring(1, fields[1].length() - 1);
595             }
596             result.put(fields[0], fields[1]);
597         }
598         return result;
599     }
600 
601     /**
602      * Adds routes.
603      * @throws NetworkException if items cannot be added to the Network
604      */
605     private void makeNetwork() throws NetworkException
606     {
607         for (RouteTag routeTag : this.routeTags.values())
608         {
609             // TODO Make routes GTU specific. See what to do with GTUType.ALL for routes
610             // TODO Automate addition of Routes to network
611             this.network.addRoute(this.network.getGtuType(GTUType.DEFAULTS.VEHICLE), routeTag.route);
612         }
613     }
614 
615     /**
616      * Obtain an immutable copy of the collected XML comments.
617      * @return List&lt;String&gt;; a list of the XML comments
618      */
619     public ImmutableList<String> getXMLComments()
620     {
621         return new ImmutableArrayList<>(this.xmlComments, Immutable.COPY);
622     }
623 
624     /**
625      * @return the network animation data belonging to the network that was parsed.
626      */
627     public final NetworkAnimation getNetworkAnimation()
628     {
629         return this.networkAnimation;
630     }
631 
632     /** {@inheritDoc} */
633     @Override
634     public String toString()
635     {
636         return "XmlNetworkLaneParser [globalTag=" + this.globalTag + ", nodeTags.size=" + this.nodeTags.size()
637                 + ", linkTags.size=" + this.linkTags.size() + ", gtuTags.size=" + this.gtuTags.size() + ", gtuMixTags.size="
638                 + this.gtuMixTags.size() + ", routeTags.size=" + this.routeTags.size() + ", routeMixTags.size="
639                 + this.routeMixTags.size() + ", shortestRouteTagssize.=" + this.shortestRouteTags.size()
640                 + ", shortestRouteMixTags.size=" + this.shortestRouteMixTags.size() + ", roadTypeTags.size="
641                 + this.roadTypeTags.size() + ", gtuTypes.size=" + this.gtuTypes.size() + ", laneTypes.size="
642                 + this.laneTypeTags.size() + "]";
643     }
644 
645 }