source: tmcsimulator/trunk/src/tmcsim/cadsimulator/paramicscontrol/ParamicsIncidentWriter.java @ 2

Revision 2, 17.5 KB checked in by jdalbey, 10 years ago (diff)

Initial Import of project files

Line 
1package tmcsim.cadsimulator.paramicscontrol;
2
3import java.util.Iterator;
4import java.util.TreeMap;
5
6import javax.xml.parsers.DocumentBuilderFactory;
7
8import org.w3c.dom.Document;
9import org.w3c.dom.Element;
10
11import tmcsim.cadmodels.CMSInfo;
12import tmcsim.common.XMLIncident;
13
14/**
15 * ParamicsIncidentWriter extends from ParamicsWriter to manage the current
16 * simulation data and transmit update XML Document messages to the
17 * ParamicsCommunicator for simulation control.  The updateIncident() and
18 * updateDiversion() methods are used to notify this class of changes in current
19 * incidents and diversions.  This data is converted to an XML Document and
20 * transmitted to the ParamicsCommunicator everytime the sendUpdate() method is
21 * called.  This method will not transmit simulation updates until a network is
22 * loaded.  To load a network, call the loadNetwork() method to transmit the
23 * registration information to paramics, and when paramics has finished warming up,
24 * call the networkLoaded() method to begin update transmission.
25 *
26 * @author Matthew Cechini (mcechini@calpoly.edu)
27 * @version $Date: 2006/06/06 20:46:40 $ $Revision: 1.4 $
28 */
29public class ParamicsIncidentWriter extends ParamicsWriter {
30
31    /**
32     * Enumeration with XML tag names.
33     * @author Matthew Cechini
34     */
35    private static enum XML_TAGS {
36        /** CAD incident update. */
37        CAD_DATA      ("CAD_DATA"),
38        /** Basic update information. */
39        BASIC         ("Basic"),
40        /** Current simulation incidents. */
41        CAD_INCIDENTS ("CAD_Incidents"),
42        /** Current simulation data. */
43        SIMULATION_DATA ("Simulation_Data"),
44        /** Current CMS diversions. */
45        MANAGEMENT    ("Management"),
46        /** Current communications interval. */
47        COMM_INTERVAL ("Comm_Interval"),
48        /** Current loaded paramics network. */
49        NETWORK_ID    ("Network_ID"),
50        /** Boolean value of whether the simulation has started. */
51        SIMULATION    ("Simulation"),
52        /** Boolean value of whether an incident is current active. */
53        INCIDENT      ("Incident"),
54        /** Current CAD simulation time. */
55        CAD_CLOCK     ("CAD_clock"),
56        /** Current simulation speed. */
57        SIM_SPEED       ("Simulation_speed"),
58        /** Current CAD clock hours value. */
59        HOUR            ("hour"),
60        /** Current CAD clock minutes value. */
61        MINUTE          ("minute"),
62        /** Current CAD clock seconds value. */
63        SECOND          ("second");
64       
65        /** Tag name */
66        public String tag;
67       
68        private XML_TAGS(String t) {
69            tag = t;
70        }
71
72    }
73       
74   
75    /** Flag to designate whether a network has been loaded */
76    private boolean networkLoaded = false;
77   
78    /** Flag to designate whether the simulation is running. */
79    private boolean simulation   = false;
80   
81    /** Flag to designate whether incidents have occured in the simulation. */
82    private boolean incident     = false;
83   
84    /** Flag to designate whether CMS diversions have been set. */
85    private boolean management   = false;
86   
87    /** Loaded Paramics network ID. */
88    private int     networkID    = 1;
89       
90    /** Communications interval for paramics to read incident status files. (in seconds) */
91    private int     commInterval = 0;
92   
93    /** Current simulation speed */
94    private int     speed        = 0;
95   
96    /** Current simulation time. */
97    private long    simTime      = 0;
98
99    /**
100     * A map containing XMLIncident objects for each incident that is being updated.
101     */
102    private TreeMap<String, XMLIncident> incidentsMap;
103   
104    /**
105     * A map containing the current active CMS diversions.
106     */
107    private TreeMap<String, CMSInfo> diversionsMap;         
108   
109    /**
110     * A Map containing queued Incident Events.  It is possible to queue one incident event
111     * per incident. This happens if an incident update is received, but the previous has not
112     * been transmitted yet.  The new updated is queued until the current is transmitted.  There
113     * is a possibility that more than one incident event can be received and added to the map, and
114     * the first would be lost.  This would be inidcative of other problems, or bad script creation.
115     * Either increase the interval frequencyl, or make more time in script between events.
116     */
117    private TreeMap<String, XMLIncident> queuedIncidentEvents;
118   
119
120    /**
121     * Constructor.  Initializes private members.
122     *
123     * @param interval Number of seconds beetween transmission of XML update.
124     */ 
125    public ParamicsIncidentWriter(Integer interval) {
126        super();
127       
128        commInterval = interval;
129
130        incidentsMap         = new TreeMap<String, XMLIncident>();
131        diversionsMap        = new TreeMap<String, CMSInfo>();     
132        queuedIncidentEvents = new TreeMap<String, XMLIncident>(); 
133   
134    }
135   
136    /**
137     * This method sets the local network ID to the parameter value and sends
138     * an updated XML message to load the network.
139     *
140     * @param newID Paramics network id.
141     */
142    public void loadNetwork(int newID) {
143        networkID = newID;
144
145        transmitXMLUpdate();
146    }
147   
148    /**
149     * Updates the networkLoaded flag to true.
150     */
151    public void networkLoaded() {
152        networkLoaded = true;
153    }
154   
155    /**
156     * Set the simulation started flag to true.  If a network has been
157     * loaded, send an update to the ParamicsCommunicator.
158     */
159    public void startSimulation() {
160       
161        simulation = true;
162
163        if(networkLoaded) {
164            sendUpdate(0);     
165        }
166    }
167   
168    /**
169     * This method resets current simulation data.  All maps of incident data
170     * are cleared.  The incident, simulation, and management flags are set to
171     * false.  If a network has been previously loaded, send an update to the
172     * ParamicsCommunicator.
173     */
174    public void resetSimulation() {
175       
176        incidentsMap.clear();
177        diversionsMap.clear();     
178        queuedIncidentEvents.clear();
179
180        simulation = false;
181        incident   = false;
182        management = false;     
183       
184        if(networkLoaded) {
185            sendUpdate(0);
186        }
187    }   
188   
189    /**
190     * This method is transmits an XML update object to the ParamicsCommunicator
191     * if a network has ben loaded.  After the update object has been formed and
192     * sent, the incident list is updated to remove all cleared Incidents.
193     * Any queued IncidentEvents are placed into the map of incidents that will
194     * be used for update creation.  The incident flag is set to true if there
195     * are still ongoing incidents, false if not.
196     */ 
197    public void sendUpdate(long simulationTime) {
198        simTime = simulationTime;       
199
200        if(!networkLoaded) return;     
201               
202        transmitXMLUpdate();
203   
204        updateIncidentList();
205       
206        for(String key : queuedIncidentEvents.keySet()) {
207            incidentsMap.put(key, queuedIncidentEvents.remove(key));
208        }
209       
210        incident = incidentsMap.size() != 0;
211       
212    }
213   
214    /**
215     * This method updates the map of XMLIncident objects that are used for
216     * updating the Paramics modeler.  If the parameter XMLIncident is not
217     * currently in the local map of incidents, add it.  If it is in the
218     * map of incidents, queue the new XMLIncident to be processed later. 
219     * Set the incident flag to true to signify that an incident exists in the
220     * system.
221     *
222     * @param newXML The XMLIncident object that will be used to update
223     *               an existing incident.
224     */
225    public void updateIncident(XMLIncident newXML) {
226       
227        if(incidentsMap.get(newXML.getIdentifier()) == null ) { 
228            incidentsMap.put(newXML.getIdentifier(), newXML);               
229        }
230        else {
231             queuedIncidentEvents.put(newXML.getIdentifier(), newXML);
232        }       
233
234        incident = true;               
235    }
236   
237    /**
238     * This method updates the map of CMSInfo diversion objects that are used
239     * for updating the Paramics modeler.  If the diversion is being cleared,
240     * remove it from the map of diversions.  If it is not being cleared,
241     * update the map with the new CMSInfo object. Set the management flag to be
242     * true if there are diversions remaining, false if not.
243     *
244     * @param theDiversion A new CMSDiversion object containing new diversion info.
245     */
246    public void updateDiversion(CMSInfo theDiversion) {
247               
248        if(theDiversion.isCleared())
249            diversionsMap.remove(theDiversion.cmsID);
250        else
251            diversionsMap.put(theDiversion.cmsID, theDiversion);
252           
253        management = diversionsMap.size() > 0; 
254   
255    }   
256   
257    /**
258     * Update the current map of incidents. If an incident
259     * has been cleared, remove it from the list.  Otherwise,
260     * call its update() method to set its status to ON_GOING.
261     *
262     * Set the incident flag to true if there are incidents still
263     * in the incident map, false if not.
264     */
265    private void updateIncidentList() {
266       
267        Iterator<XMLIncident> incIter = incidentsMap.values().iterator();
268       
269        while(incIter.hasNext()) {
270            XMLIncident inc = incIter.next();
271           
272            if(inc.isCleared()) 
273                incIter.remove();
274            else
275                inc.update();
276        }
277       
278        incident = incidentsMap.size() != 0;
279    }
280   
281   
282    /**
283     * Creates an XML Document containing all Paramics update information. 
284     * This XML object will then be written to the parent class' writeXML method
285     * for transmission to the Paramics Communicator.  Helper methods are used
286     * to create each individual section.  The simulation, incident, and
287     * diversion secions will only appear if they are currently active in the
288     * simulation.  The format of the resulting XML object is as follows:<br>
289     * <br>
290     * <CAD_DATA><br>
291     *    <Basic><br>
292     *       <Comm_Interval/><br/>
293     *       <Network_ID/><br/>
294     *       <Simulation/><br/>
295     *       <Incident/><br/>
296     *    </Basic>
297     *
298     *    <Simulation_Data>
299     *       <Simulation_speed/><br/>
300     *       <CAD_clock><br/>
301     *          <hour/><br/>
302     *          <minute/><br/>
303     *          <second/><br/>
304     *          <Location><br/>
305     *       </CAD_clock><br/>
306     *    </Simulation_Data>
307     *   
308     *    <CAD_Incidents>
309     *       <Incident><br/>
310     *          <Identifier/><br/>
311     *          <Status/><br/>
312     *          <Location><br/>
313     *              <Route/><br/>
314     *              <Direction/><br/>
315     *              <Location_type/><br/>
316     *              <Postmile/><br/>
317     *          </Location><br/>
318     *          <Incident_type/><br/>
319     *          <Lanes><br/>
320     *             <Lane_number/><br/>
321     *             ...
322     *          </Lanes><br/>
323     *       </Incident><br/>
324     *       ...
325     *    </CAD_Incidents>   
326     *   
327     *    <Management>
328     *       <Diversion>
329     *          <Diversion_path>
330     *             <Identifier/>
331     *             <Percentage/>
332     *          <Diversion_path>
333     *          ...
334     *       </Diversion>
335     *       ...
336     *    </Management>
337     * 
338     * </CAD_DATA>
339     *
340     */
341    private void transmitXMLUpdate() {
342
343        try {
344           
345            Document theDoc = DocumentBuilderFactory.newInstance()
346                .newDocumentBuilder().newDocument();
347           
348            Element cadDataElement = theDoc.createElement(XML_TAGS.CAD_DATA.tag);
349            theDoc.appendChild(cadDataElement);
350           
351            //***** BASIC *****//
352            writeBasicXML(cadDataElement);     
353           
354            //***** SIMULATION *****//
355            if(simulation)
356                writeSimulationXML(cadDataElement);
357           
358           
359            //***** INCIDENTS *****//
360            if(incident)
361                writeIncidents(cadDataElement);             
362           
363           
364            //***** MANAGEMENT *****//
365            if(management)
366                writeManagement(cadDataElement);
367           
368            writeXML(theDoc);
369           
370        } catch (Exception e) {
371            e.printStackTrace();
372        }
373    }
374   
375    /**
376     * Appends the <Basic> XML Element to the parameter Element root.
377     * The format for this section is as follows:<br>
378     *
379     * <Basic>
380     *    <Comm_Interval/><br/>
381     *    <Network_ID/><br/>
382     *    <Simulation/><br/>
383     *    <Incident/><br/>
384     * </Basic>
385     *
386     * @param currElem XML Element to use as a root.
387     */
388    private void writeBasicXML(Element currElem) {     
389                   
390        Document theDoc = currElem.getOwnerDocument();
391       
392        Element basicElem = theDoc.createElement(XML_TAGS.BASIC.tag);
393        currElem.appendChild(basicElem);
394
395        Element intervalElement = theDoc.createElement(XML_TAGS.COMM_INTERVAL.tag);
396        intervalElement.appendChild(theDoc.createTextNode( String.valueOf(commInterval)));
397        basicElem.appendChild(intervalElement);
398
399        Element networkElement = theDoc.createElement(XML_TAGS.NETWORK_ID.tag);
400        networkElement.appendChild(theDoc.createTextNode(String.valueOf(networkID)));
401        basicElem.appendChild(networkElement);
402
403        Element simElement = theDoc.createElement(XML_TAGS.SIMULATION.tag);
404        simElement.appendChild(theDoc.createTextNode(String.valueOf(simulation).toUpperCase()));
405        basicElem.appendChild(simElement);
406
407        Element incidentElement = theDoc.createElement(XML_TAGS.INCIDENT.tag);
408        incidentElement.appendChild(theDoc.createTextNode(String.valueOf(incident).toUpperCase()));
409        basicElem.appendChild(incidentElement);
410
411    }
412   
413    /**
414     * Appends the <Simulation_Data> XML Element to the parameter Element root.
415     * The format for this section is as follows:<br>
416     *
417     * <Simulation_Data>
418     *    <Simulation_speed/><br/>
419     *    <CAD_clock><br/>
420     *       <hour/><br/>
421     *       <minute/><br/>
422     *       <second/><br/>
423     *       <Location><br/>
424     *    </CAD_clock><br/>
425     * </Simulation_Data>
426     *
427     * @param currElem XML Element to use as a root.
428     */
429    private void writeSimulationXML(Element currElem) {
430
431        Document theDoc = currElem.getOwnerDocument();
432       
433        Element simDataElem = theDoc.createElement(XML_TAGS.SIMULATION_DATA.tag);
434        currElem.appendChild(simDataElem);
435
436        Element speedElement = theDoc.createElement(XML_TAGS.SIM_SPEED.tag);
437        speedElement.appendChild(theDoc.createTextNode(String.valueOf(speed)));
438        simDataElem.appendChild(speedElement);   
439
440        Element clockElement = theDoc.createElement(XML_TAGS.CAD_CLOCK.tag);
441        simDataElem.appendChild(clockElement); 
442
443        Element hourElement = theDoc.createElement(XML_TAGS.HOUR.tag);
444        hourElement.appendChild(theDoc.createTextNode(String.valueOf(6 + (long)simTime/3600)));
445        clockElement.appendChild(hourElement); 
446
447        Element minuteElement = theDoc.createElement(XML_TAGS.MINUTE.tag);
448        minuteElement.appendChild(theDoc.createTextNode(String.valueOf((long)((simTime%3600)/60))));
449        clockElement.appendChild(minuteElement); 
450
451        Element secondElement = theDoc.createElement(XML_TAGS.SECOND.tag);
452        secondElement.appendChild(theDoc.createTextNode(String.valueOf((long)(simTime%60))));
453        clockElement.appendChild(secondElement);   
454
455    }
456   
457    /**
458     * Appends the <Simulation_Data> XML Element to the parameter Element root.
459     * This is done by converting all current XMLIncident objects
460     * to their XML output.  The format for this section is as follows:<br>
461     *
462     * <CAD_Incidents>
463     *    <Incident><br/>
464     *       <Identifier/><br/>
465     *       <Status/><br/>
466     *       <Location><br/>
467     *           <Route/><br/>
468     *           <Direction/><br/>
469     *           <Location_type/><br/>
470     *           <Postmile/><br/>
471     *       </Location><br/>
472     *       <Incident_type/><br/>
473     *       <Lanes><br/>
474     *          <Lane_number/><br/>
475     *          ...
476     *       </Lanes><br/>
477     *    </Incident><br/>
478     *    ...
479     * </CAD_Incidents>
480     *
481     * @param currElem XML Element to use as a root.
482     */
483    private void writeIncidents(Element currElem) {
484
485        Document theDoc = currElem.getOwnerDocument();
486       
487        Element incidentElem = theDoc.createElement(XML_TAGS.CAD_INCIDENTS.tag);
488        currElem.appendChild(incidentElem);
489
490        for(XMLIncident incident : incidentsMap.values()) {
491            incident.toXML(incidentElem);
492        }
493
494    }
495
496    /**
497     * Appends the <Simulation_Data> XML Element to the parameter Element root.
498     * This is done by converting all current CMS Diversion objects
499     * to their XML output.  The format for this section is as follows:<br>
500     *
501     * <Management>
502     *    <Diversion>
503     *       <Diversion_path>
504     *          <Identifier/>
505     *          <Percentage/>
506     *       <Diversion_path>
507     *       ...
508     *    </Diversion>
509     *    ...
510     * </Management>
511     *
512     * @param currElem XML Element to use as a root.
513     */
514    private void writeManagement(Element currElem) {
515
516        Document theDoc = currElem.getOwnerDocument();
517       
518        Element mgmtElem = theDoc.createElement(XML_TAGS.MANAGEMENT.tag);
519        currElem.appendChild(mgmtElem);
520
521        for(CMSInfo div : diversionsMap.values()) {
522            div.toXML(mgmtElem);
523        }                       
524    }
525       
526}
527
Note: See TracBrowser for help on using the repository browser.