Index: trunk/src/tmcsim/cadsimulator/managers/TrafficModelViewer.java
===================================================================
--- trunk/src/tmcsim/cadsimulator/managers/TrafficModelViewer.java	(revision 187)
+++ trunk/src/tmcsim/cadsimulator/managers/TrafficModelViewer.java	(revision 187)
@@ -0,0 +1,304 @@
+package tmcsim.cadsimulator.managers;
+
+import tmcsim.client.*;
+import atmsdriver.model.TrafficEvent;
+import java.text.ParseException;
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import javax.swing.AbstractListModel;
+import javax.swing.JOptionPane;
+
+/**
+ * GUI for the Traffic Model Manager.
+ * @author jdalbey
+ */
+public class TrafficModelViewer extends javax.swing.JFrame
+{
+
+    /**
+     * Reference to the driver associated with this GUI
+     */
+    private TrafficModelManager driver;
+    private final List<String> incidents;
+
+    /**
+     * Creates new form ATMSBatchViewer.
+     *
+     * @param incidents a list of incidents to show in a list.
+     */
+    public TrafficModelViewer(TrafficModelManager driver, List<String> incidentList)
+    {
+        initComponents();
+        this.driver = driver;
+        this.incidents = incidentList;
+        lstIncidents.setModel(new javax.swing.AbstractListModel<String>()
+        {
+            public int getSize()
+            {
+                return incidents.size();
+            }
+
+            public String getElementAt(int i)
+            {
+                return incidents.get(i);
+            }
+        });
+    }
+
+    public void update(String currentTime, String atmsTime, List<TrafficEvent> events)
+    {
+        lstEvents.setModel(new MyListModel(events));
+        txtClockTime.setText(currentTime + " / " + atmsTime);
+    }
+
+    class MyListModel extends AbstractListModel<String>
+    {
+
+        TrafficEvent[] strings;// = { "item 1", "item 2" };
+
+        public MyListModel(List<TrafficEvent> events)
+        {
+            strings = events.toArray(new TrafficEvent[events.size()]);
+        }
+
+        public int getSize()
+        {
+            return strings.length;
+        }
+
+        public String getElementAt(int i)
+        {
+            return strings[i].rawString;
+        }
+    }
+
+    /**
+     * This method is called from within the constructor to initialize the form.
+     * WARNING: Do NOT modify this code. The content of this method is always
+     * regenerated by the Form Editor.
+     */
+    @SuppressWarnings("unchecked")
+    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
+    private void initComponents()
+    {
+
+        pnlEvents = new javax.swing.JPanel();
+        scrollEvents = new javax.swing.JScrollPane();
+        lstEvents = new javax.swing.JList<>();
+        txtClockTime = new javax.swing.JLabel();
+        pnlIncidents = new javax.swing.JPanel();
+        jScrollPane1 = new javax.swing.JScrollPane();
+        lstIncidents = new javax.swing.JList<>();
+        btnClear = new javax.swing.JButton();
+
+        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
+        setTitle("ATMS Batch Driver");
+
+        lstEvents.setFont(new java.awt.Font("Noto Mono", 0, 12)); // NOI18N
+        lstEvents.setModel(new javax.swing.AbstractListModel<String>()
+        {
+            String[] strings = { "item 1", "item 2" };
+            public int getSize() { return strings.length; }
+            public String getElementAt(int i) { return strings[i]; }
+        });
+        scrollEvents.setViewportView(lstEvents);
+
+        txtClockTime.setFont(new java.awt.Font("Noto Sans", 1, 14)); // NOI18N
+        txtClockTime.setText("0:00:00");
+
+        javax.swing.GroupLayout pnlEventsLayout = new javax.swing.GroupLayout(pnlEvents);
+        pnlEvents.setLayout(pnlEventsLayout);
+        pnlEventsLayout.setHorizontalGroup(
+            pnlEventsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+            .addGroup(pnlEventsLayout.createSequentialGroup()
+                .addGroup(pnlEventsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+                    .addGroup(pnlEventsLayout.createSequentialGroup()
+                        .addGap(112, 112, 112)
+                        .addComponent(txtClockTime, javax.swing.GroupLayout.PREFERRED_SIZE, 225, javax.swing.GroupLayout.PREFERRED_SIZE))
+                    .addGroup(pnlEventsLayout.createSequentialGroup()
+                        .addContainerGap()
+                        .addComponent(scrollEvents, javax.swing.GroupLayout.PREFERRED_SIZE, 430, javax.swing.GroupLayout.PREFERRED_SIZE)))
+                .addContainerGap(20, Short.MAX_VALUE))
+        );
+        pnlEventsLayout.setVerticalGroup(
+            pnlEventsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, pnlEventsLayout.createSequentialGroup()
+                .addComponent(txtClockTime, javax.swing.GroupLayout.PREFERRED_SIZE, 28, javax.swing.GroupLayout.PREFERRED_SIZE)
+                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                .addComponent(scrollEvents, javax.swing.GroupLayout.DEFAULT_SIZE, 172, Short.MAX_VALUE)
+                .addContainerGap())
+        );
+
+        lstIncidents.setFont(new java.awt.Font("Noto Mono", 0, 15)); // NOI18N
+        lstIncidents.setModel(new javax.swing.AbstractListModel<String>()
+        {
+            String[] strings = { "Item 1", "Item 2", "Item 3", "Item 4", "Item 5" };
+            public int getSize() { return strings.length; }
+            public String getElementAt(int i) { return strings[i]; }
+        });
+        lstIncidents.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
+        jScrollPane1.setViewportView(lstIncidents);
+
+        btnClear.setText("Clear Incident");
+        btnClear.addActionListener(new java.awt.event.ActionListener()
+        {
+            public void actionPerformed(java.awt.event.ActionEvent evt)
+            {
+                btnClearActionPerformed(evt);
+            }
+        });
+
+        javax.swing.GroupLayout pnlIncidentsLayout = new javax.swing.GroupLayout(pnlIncidents);
+        pnlIncidents.setLayout(pnlIncidentsLayout);
+        pnlIncidentsLayout.setHorizontalGroup(
+            pnlIncidentsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+            .addGroup(pnlIncidentsLayout.createSequentialGroup()
+                .addGroup(pnlIncidentsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+                    .addComponent(btnClear)
+                    .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 211, javax.swing.GroupLayout.PREFERRED_SIZE))
+                .addGap(0, 0, Short.MAX_VALUE))
+        );
+        pnlIncidentsLayout.setVerticalGroup(
+            pnlIncidentsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, pnlIncidentsLayout.createSequentialGroup()
+                .addContainerGap()
+                .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 179, javax.swing.GroupLayout.PREFERRED_SIZE)
+                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                .addComponent(btnClear)
+                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
+        );
+
+        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
+        getContentPane().setLayout(layout);
+        layout.setHorizontalGroup(
+            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+            .addGroup(layout.createSequentialGroup()
+                .addGap(1, 1, 1)
+                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
+                    .addGroup(layout.createSequentialGroup()
+                        .addGap(12, 12, 12)
+                        .addComponent(pnlIncidents, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
+                    .addComponent(pnlEvents, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
+                .addGap(0, 26, Short.MAX_VALUE))
+        );
+        layout.setVerticalGroup(
+            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+            .addGroup(layout.createSequentialGroup()
+                .addComponent(pnlEvents, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                .addComponent(pnlIncidents, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+                .addContainerGap())
+        );
+
+        pack();
+    }// </editor-fold>//GEN-END:initComponents
+
+    private void btnClearActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_btnClearActionPerformed
+    {//GEN-HEADEREND:event_btnClearActionPerformed
+        String selectedItem = lstIncidents.getSelectedValue();
+        if (selectedItem == null)
+        {
+            JOptionPane.showMessageDialog(this, "No Incident Selected", "Warning", JOptionPane.INFORMATION_MESSAGE);
+        }
+        else
+        {
+            System.out.println("Clicked Incident:" + selectedItem);
+            if (driver != null)
+            {
+                driver.clearIncident(selectedItem);
+            }
+            lstIncidents.clearSelection();
+            // Remove selectedItem from list model;
+            incidents.remove(selectedItem);
+            // Update the list displayed
+            String[] array = new String[incidents.size()];
+            array = incidents.toArray(array);
+            lstIncidents.setListData(array);
+        }
+    }//GEN-LAST:event_btnClearActionPerformed
+
+    /**
+     * @param args the command line arguments
+     */
+    public static void main(String args[])
+    {
+        /* Set the Nimbus look and feel */
+        //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
+        /* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
+         * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html 
+         */
+        try
+        {
+            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels())
+            {
+                if ("Nimbus".equals(info.getName()))
+                {
+                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
+                    break;
+                }
+            }
+        }
+        catch (ClassNotFoundException ex)
+        {
+            java.util.logging.Logger.getLogger(TrafficModelViewer.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
+        }
+        catch (InstantiationException ex)
+        {
+            java.util.logging.Logger.getLogger(TrafficModelViewer.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
+        }
+        catch (IllegalAccessException ex)
+        {
+            java.util.logging.Logger.getLogger(TrafficModelViewer.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
+        }
+        catch (javax.swing.UnsupportedLookAndFeelException ex)
+        {
+            java.util.logging.Logger.getLogger(TrafficModelViewer.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
+        }
+        //</editor-fold>
+        //</editor-fold>
+        //</editor-fold>
+        //</editor-fold>
+
+        /* Create and display the form */
+        java.awt.EventQueue.invokeLater(new Runnable()
+        {
+            public void run()
+            {
+                try
+                {
+                    TrafficEvent alpha = new TrafficEvent("181 00:01:30 405 S 0.6 11.0 G");
+                    TrafficEvent beta = new TrafficEvent("183 00:12:30 405 S 0.6 11.0 G");
+                    TrafficEvent charly = new TrafficEvent("181 00:22:00 5 S 0.6 11.0 G");
+                    LinkedList<TrafficEvent> sample = new LinkedList<TrafficEvent>();
+                    sample.add(alpha);
+                    sample.add(beta);
+                    List<String> items = new ArrayList<String>();
+                    items.add("180");
+                    items.add("1291");
+                    TrafficModelViewer view = new TrafficModelViewer(null, items);
+                    view.setVisible(true);
+                    view.update("01", "02", sample);
+                }
+                catch (ParseException ex)
+                {
+                    Logger.getLogger(TrafficModelViewer.class.getName()).log(Level.SEVERE, null, ex);
+                }
+
+            }
+        });
+    }
+
+    // Variables declaration - do not modify//GEN-BEGIN:variables
+    private javax.swing.JButton btnClear;
+    private javax.swing.JScrollPane jScrollPane1;
+    private javax.swing.JList<String> lstEvents;
+    private javax.swing.JList<String> lstIncidents;
+    private javax.swing.JPanel pnlEvents;
+    private javax.swing.JPanel pnlIncidents;
+    private javax.swing.JScrollPane scrollEvents;
+    private javax.swing.JLabel txtClockTime;
+    // End of variables declaration//GEN-END:variables
+}
Index: trunk/src/tmcsim/cadsimulator/managers/TrafficModelViewer.form
===================================================================
--- trunk/src/tmcsim/cadsimulator/managers/TrafficModelViewer.form	(revision 187)
+++ trunk/src/tmcsim/cadsimulator/managers/TrafficModelViewer.form	(revision 187)
@@ -0,0 +1,186 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<Form version="1.3" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JFrameFormInfo">
+  <Properties>
+    <Property name="defaultCloseOperation" type="int" value="3"/>
+    <Property name="title" type="java.lang.String" value="ATMS Batch Driver"/>
+  </Properties>
+  <SyntheticProperties>
+    <SyntheticProperty name="formSizePolicy" type="int" value="1"/>
+    <SyntheticProperty name="generateCenter" type="boolean" value="false"/>
+  </SyntheticProperties>
+  <AuxValues>
+    <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="0"/>
+    <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
+    <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
+    <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/>
+    <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/>
+    <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
+    <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
+    <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
+    <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
+  </AuxValues>
+
+  <Layout>
+    <DimensionLayout dim="0">
+      <Group type="103" groupAlignment="0" attributes="0">
+          <Group type="102" alignment="0" attributes="0">
+              <EmptySpace min="-2" pref="1" max="-2" attributes="0"/>
+              <Group type="103" groupAlignment="0" max="-2" attributes="0">
+                  <Group type="102" attributes="0">
+                      <EmptySpace min="12" pref="12" max="-2" attributes="0"/>
+                      <Component id="pnlIncidents" max="32767" attributes="0"/>
+                  </Group>
+                  <Component id="pnlEvents" min="-2" max="-2" attributes="0"/>
+              </Group>
+              <EmptySpace min="0" pref="26" max="32767" attributes="0"/>
+          </Group>
+      </Group>
+    </DimensionLayout>
+    <DimensionLayout dim="1">
+      <Group type="103" groupAlignment="0" attributes="0">
+          <Group type="102" alignment="0" attributes="0">
+              <Component id="pnlEvents" min="-2" max="-2" attributes="0"/>
+              <EmptySpace max="-2" attributes="0"/>
+              <Component id="pnlIncidents" max="32767" attributes="0"/>
+              <EmptySpace max="-2" attributes="0"/>
+          </Group>
+      </Group>
+    </DimensionLayout>
+  </Layout>
+  <SubComponents>
+    <Container class="javax.swing.JPanel" name="pnlEvents">
+
+      <Layout>
+        <DimensionLayout dim="0">
+          <Group type="103" groupAlignment="0" attributes="0">
+              <Group type="102" attributes="0">
+                  <Group type="103" groupAlignment="0" attributes="0">
+                      <Group type="102" attributes="0">
+                          <EmptySpace min="-2" pref="112" max="-2" attributes="0"/>
+                          <Component id="txtClockTime" min="-2" pref="225" max="-2" attributes="0"/>
+                      </Group>
+                      <Group type="102" alignment="0" attributes="0">
+                          <EmptySpace max="-2" attributes="0"/>
+                          <Component id="scrollEvents" min="-2" pref="430" max="-2" attributes="0"/>
+                      </Group>
+                  </Group>
+                  <EmptySpace pref="20" max="32767" attributes="0"/>
+              </Group>
+          </Group>
+        </DimensionLayout>
+        <DimensionLayout dim="1">
+          <Group type="103" groupAlignment="0" attributes="0">
+              <Group type="102" alignment="1" attributes="0">
+                  <Component id="txtClockTime" min="-2" pref="28" max="-2" attributes="0"/>
+                  <EmptySpace max="-2" attributes="0"/>
+                  <Component id="scrollEvents" pref="172" max="32767" attributes="0"/>
+                  <EmptySpace max="-2" attributes="0"/>
+              </Group>
+          </Group>
+        </DimensionLayout>
+      </Layout>
+      <SubComponents>
+        <Container class="javax.swing.JScrollPane" name="scrollEvents">
+          <AuxValues>
+            <AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
+          </AuxValues>
+
+          <Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
+          <SubComponents>
+            <Component class="javax.swing.JList" name="lstEvents">
+              <Properties>
+                <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
+                  <Font name="Noto Mono" size="12" style="0"/>
+                </Property>
+                <Property name="model" type="javax.swing.ListModel" editor="org.netbeans.modules.form.editors2.ListModelEditor">
+                  <StringArray count="2">
+                    <StringItem index="0" value="item 1"/>
+                    <StringItem index="1" value="item 2"/>
+                  </StringArray>
+                </Property>
+              </Properties>
+              <AuxValues>
+                <AuxValue name="JavaCodeGenerator_TypeParameters" type="java.lang.String" value="&lt;String&gt;"/>
+              </AuxValues>
+            </Component>
+          </SubComponents>
+        </Container>
+        <Component class="javax.swing.JLabel" name="txtClockTime">
+          <Properties>
+            <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
+              <Font name="Noto Sans" size="14" style="1"/>
+            </Property>
+            <Property name="text" type="java.lang.String" value="0:00:00"/>
+          </Properties>
+        </Component>
+      </SubComponents>
+    </Container>
+    <Container class="javax.swing.JPanel" name="pnlIncidents">
+
+      <Layout>
+        <DimensionLayout dim="0">
+          <Group type="103" groupAlignment="0" attributes="0">
+              <Group type="102" attributes="0">
+                  <Group type="103" groupAlignment="0" attributes="0">
+                      <Component id="btnClear" min="-2" max="-2" attributes="0"/>
+                      <Component id="jScrollPane1" min="-2" pref="211" max="-2" attributes="0"/>
+                  </Group>
+                  <EmptySpace min="0" pref="0" max="32767" attributes="0"/>
+              </Group>
+          </Group>
+        </DimensionLayout>
+        <DimensionLayout dim="1">
+          <Group type="103" groupAlignment="0" attributes="0">
+              <Group type="102" alignment="1" attributes="0">
+                  <EmptySpace max="-2" attributes="0"/>
+                  <Component id="jScrollPane1" min="-2" pref="179" max="-2" attributes="0"/>
+                  <EmptySpace max="-2" attributes="0"/>
+                  <Component id="btnClear" min="-2" max="-2" attributes="0"/>
+                  <EmptySpace max="32767" attributes="0"/>
+              </Group>
+          </Group>
+        </DimensionLayout>
+      </Layout>
+      <SubComponents>
+        <Container class="javax.swing.JScrollPane" name="jScrollPane1">
+          <AuxValues>
+            <AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
+          </AuxValues>
+
+          <Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
+          <SubComponents>
+            <Component class="javax.swing.JList" name="lstIncidents">
+              <Properties>
+                <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
+                  <Font name="Noto Mono" size="15" style="0"/>
+                </Property>
+                <Property name="model" type="javax.swing.ListModel" editor="org.netbeans.modules.form.editors2.ListModelEditor">
+                  <StringArray count="5">
+                    <StringItem index="0" value="Item 1"/>
+                    <StringItem index="1" value="Item 2"/>
+                    <StringItem index="2" value="Item 3"/>
+                    <StringItem index="3" value="Item 4"/>
+                    <StringItem index="4" value="Item 5"/>
+                  </StringArray>
+                </Property>
+                <Property name="selectionMode" type="int" value="0"/>
+              </Properties>
+              <AuxValues>
+                <AuxValue name="JavaCodeGenerator_TypeParameters" type="java.lang.String" value="&lt;String&gt;"/>
+              </AuxValues>
+            </Component>
+          </SubComponents>
+        </Container>
+        <Component class="javax.swing.JButton" name="btnClear">
+          <Properties>
+            <Property name="text" type="java.lang.String" value="Clear Incident"/>
+          </Properties>
+          <Events>
+            <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnClearActionPerformed"/>
+          </Events>
+        </Component>
+      </SubComponents>
+    </Container>
+  </SubComponents>
+</Form>
Index: trunk/src/tmcsim/cadsimulator/managers/TrafficModelManager.java
===================================================================
--- trunk/src/tmcsim/cadsimulator/managers/TrafficModelManager.java	(revision 187)
+++ trunk/src/tmcsim/cadsimulator/managers/TrafficModelManager.java	(revision 187)
@@ -0,0 +1,383 @@
+package tmcsim.cadsimulator.managers;
+
+import atmsdriver.ConsoleTrafficDriver;
+import atmsdriver.model.Highways;
+import atmsdriver.model.LoopDetector;
+import atmsdriver.model.TrafficEvent;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.rmi.RemoteException;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Observable;
+import java.util.Properties;
+import java.util.Scanner;
+import java.util.concurrent.TimeUnit;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import javax.swing.JOptionPane;
+import javax.swing.Timer;
+import tmcsim.cadsimulator.Coordinator;
+import tmcsim.client.ATMSBatchDriver;
+import tmcsim.client.ATMSBatchViewer;
+import tmcsim.common.SimulationException;
+
+/**
+ * Traffic Model Manager is a model and controller for the Traffic Model
+ * used in the simulation.  It represents all the highways and traffic
+ * events that occur.
+ * @author jdalbey
+ * @version 2.0
+ */
+public class TrafficModelManager extends Observable 
+{
+    private final static int ONE_SECOND = 1000;
+    private static final int FEPSIM_INTERVAL = 30000;
+    private final static SimpleDateFormat formatter = new SimpleDateFormat("HH:mm:ss");
+
+    /**
+     * Error Logger.
+     */
+    private static Logger atmsLogger = Logger.getLogger("tmcsim.cadsimulator.managers");
+
+    /**
+     * Enumeration containing property names for Properties parsing.
+     *
+     * @author Matthew Cechini
+     */
+    private static enum PROPERTIES
+    {
+        /**
+         *
+         */
+        HIGHWAYS_MAP_FILE("Highways_Map_File"),
+        /**
+         *
+         */
+        FEPSIM_IP_ADDR("FEPSim_IP_addr"),
+        /**
+         *
+         */
+        EVENTS_FILE("Events_File");
+
+        public String name;
+
+        private PROPERTIES(String n)
+        {
+            name = n;
+        }
+    };
+
+    /**
+     * Reference to the simulation Coordinator from whom we get simulation
+     * elapsed time.
+     */
+    private Coordinator theCoordinator;
+
+    /**
+     * Properties Object.
+     */
+    private Properties atmsProperties = null;
+    /**
+     * Highways in traffic network
+     */
+    final private Highways highways;
+
+    /**
+     * LinkedList of batch events
+     */
+    private LinkedList<TrafficEvent> eventQueue;
+    /**
+     * Map of incidents to events
+     */
+    private Map<String, List<TrafficEvent>> incidents;
+
+    /**
+     * GUI for this driver
+     */
+    private TrafficModelViewer theView;
+    
+    /**
+     * Constructor. Loads the Properties file and initializes the
+     * ATMSCommunicator with the parsed data.
+     *
+     * @param propertiesFile Target file path of properties file.
+     */
+    public TrafficModelManager(String propertiesFile) throws SimulationException 
+    {
+        if (!loadProperties(propertiesFile))
+        {
+            System.exit(0);
+        }
+
+        // Initialize the highway model
+        incidents = new HashMap<String, List<TrafficEvent>>();
+        highways = new Highways(
+                "config/vds_data/highways_fullmap.txt",
+                //        "192.168.251.46", 8080);  //IP address of FEP Sim Linux VM
+                "localhost", 8080); 
+
+        // READ THE BATCH FILE OF COMMANDS and put in a queue
+        readBatchFile();
+        // Launch the display
+        theView = new TrafficModelViewer(this, new ArrayList<String>(incidents.keySet()));
+        theView.setVisible(true);
+        theView.update("0:00", "1:11", eventQueue);
+
+        // Create a timer that fetches the simulation time every second.
+        Timer timer = new Timer(ONE_SECOND, new ActionListener()
+        {
+            // Every second, see if an event should be launched
+            public void actionPerformed(ActionEvent e)
+            {
+                String currentClock = "";
+                String currentATMStime = "";
+                Date simClock = new Date();
+                // Obtain the simulation time from the CAD server
+                try
+                {
+                    long simtime = theCoordinator.getCurrentSimulationTime();
+                    currentClock = formatInterval(simtime);
+                    // For Debugging, show the ATMS time
+//                    long ATMStime = theCoorInt.getATMStime();       
+//                    Date atmsdate = new Date(ATMStime);
+//                    currentATMStime = formatter.format(atmsdate);
+                    try
+                    {
+                        simClock = formatter.parse(currentClock);
+                    }
+                    catch (ParseException ex)
+                    {
+                        Logger.getLogger(ATMSBatchDriver.class.getName()).log(Level.SEVERE, null, ex);
+                        System.out.println("Invalid simulation clock time found in ATMSDriverClient");
+                        System.exit(-1);
+                    }
+                    //System.out.println("Current clock: " + currentClock);
+                }
+                catch (RemoteException ex)
+                {
+                    System.out.println("Remote Exception reading sim or ATMS clock time");
+                    Logger.getLogger(ATMSBatchDriver.class.getName()).log(Level.SEVERE, null, ex);
+                }
+                // If we have any events left to process
+                if (!eventQueue.isEmpty())
+                {
+                    // Get the time to launch the next event
+                    TrafficEvent nextEvent = eventQueue.peek();
+                    Date eventTime = nextEvent.eventDate;
+                    //System.out.println("Next event will be launched at: " + formatter.format(eventTime));
+                    // Check the queue of events to see if the first
+                    // item should be launched.  IF so, 
+                    // issue that command and remove it from queue.
+                    if (eventTime.before(simClock) || eventTime.equals(simClock))
+                    {
+                        System.out.println("LAUNCHING EVENT: " + nextEvent.toString());
+                        // apply colorization to highways
+                        highways.applyColorToHighwayStretch(nextEvent.routeNumber, nextEvent.dir,
+                                nextEvent.postmile, nextEvent.range, nextEvent.color);
+                        // Remove this event from the queue, we're done with it.
+                        eventQueue.remove();
+                    }
+
+                    theView.update(currentClock, currentATMStime, eventQueue);
+                }
+            }
+        });
+        timer.start();
+
+        // Start the FEP thread (to update ATMS every 30 sec). (See class def below)
+        Thread wtfep = new WriteToFEPThread();
+        wtfep.start();
+        
+    }
+
+    /**
+     * This method verifies that the CAD Simulator Host and Port values are not
+     * null. Also, if a CAD Position or User ID do not exist in the properties
+     * file, the user is prompted to enter values. These values are written to
+     * the properties file. If the user cancels the process of entering these
+     * values, the verification fails.
+     *
+     * @param propertiesFile File path (absolute or relative) to the properties
+     * file containing configuration data.
+     * @return True if the properties file is valid, false if not.
+     * @throws SimulationException if there is an exception in verifying the
+     * properties file, or if the user cancels input.
+     */
+    private boolean loadProperties(String propertiesFile)
+            throws SimulationException
+    {
+        // Load the properties file.
+        try
+        {
+            atmsProperties = new Properties();
+            atmsProperties.load(new FileInputStream(propertiesFile));
+
+        } catch (Exception e)
+        {
+            atmsLogger.logp(Level.SEVERE, "TrafficModelManager", "Constructor",
+                    "Exception in parsing properties file.", e);
+            throw new SimulationException(SimulationException.INITIALIZE_ERROR,
+                    e);            
+        }
+
+
+        // Ensure that the properties file does not have null values for the
+        // required information.
+        if (atmsProperties.getProperty(PROPERTIES.HIGHWAYS_MAP_FILE.name) == null
+                || atmsProperties.getProperty(PROPERTIES.FEPSIM_IP_ADDR.name) == null
+                || atmsProperties.getProperty(PROPERTIES.EVENTS_FILE.name) == null)
+        {
+            atmsLogger.logp(Level.SEVERE, "TrafficModelManager",
+                    "Constructor", "Null value in properties file.");
+            throw new SimulationException(SimulationException.INITIALIZE_ERROR);
+        }
+
+        return true;
+    }
+    private void readBatchFile()
+    {
+        FileInputStream fis;
+        try
+        {
+            fis = new FileInputStream("config/vds_data/atmsBatchEvents.txt");
+            eventQueue = new LinkedList<TrafficEvent>();
+            // Read all lines from the file of events
+            Scanner scan = new Scanner(fis);
+            while (scan.hasNext())
+            {
+                // Read a line and add it to the event queue
+                String line = scan.nextLine().trim();
+                if (line.charAt(0) != '#')
+                {
+                    TrafficEvent evt;
+                    try
+                    {
+                        evt = new TrafficEvent(line);
+                        eventQueue.add(evt);
+                        String incident = evt.incident;
+                        // Add the line to the list for the corresponding incident
+                        List evtList;
+                        if (incidents.containsKey(evt.incident))
+                        {
+                            evtList = incidents.get(evt.incident);
+                        }
+                        else
+                        {
+                            evtList = new ArrayList<String>();
+                        }
+                        evtList.add(evt);
+                        // and put it back in the map
+                        incidents.put(incident, evtList);
+                    }
+                    catch (ParseException ex)
+                    {
+                        Logger.getLogger(ATMSBatchDriver.class.getName()).log(Level.SEVERE, null, ex);
+                        System.out.println("Wrong format data in batch event file: " + line + " \nskipping.");
+                        System.out.println("Skipping badly formatted event.");
+                    }
+                }
+            }
+        }
+        catch (FileNotFoundException ex)
+        {
+            Logger.getLogger(ATMSBatchDriver.class.getName()).log(Level.SEVERE, null, ex);
+        }
+        System.out.println("Events file read, " + eventQueue.size() + " events queued.");
+        // Put the events in chronological order
+        Collections.sort(eventQueue);
+    }
+
+    /**
+     * Clear an incident. For each event associated with an incident, turn the
+     * dots in its range Green and remove it from the event queue.
+     *
+     * @param incidentNumber incident to be cleared.
+     */
+    public void clearIncident(String incidentNumber)
+    {
+        boolean ok = incidents.containsKey(incidentNumber);
+        if (!ok)
+        {
+            System.out.println("Sorry, that incident number isn't found.");
+            return;
+        }
+        System.out.println("Clearing incident " + incidentNumber);
+        List<TrafficEvent> events = incidents.get(incidentNumber);
+        // Process each event associated with this incident 
+        for (TrafficEvent event : events)
+        {
+            System.out.println("Event: " + event + " cleared.");
+            eventQueue.remove(event);
+
+            // apply colorization to highways, forcing to green, indicating cleared
+            highways.applyColorToHighwayStretch(event.routeNumber, event.dir,
+                    event.postmile, event.range, LoopDetector.DOTCOLOR.GREEN);
+
+        }
+        // Now refresh the view with the updated queue of events
+        theView.update("0:00", "0:00", eventQueue);
+    }
+
+    /**
+     * Format a time in seconds as HH:MM:SS
+     *
+     * @param l
+     * @return
+     */
+    private String formatInterval(final long l)
+    {
+        final long hr = TimeUnit.SECONDS.toHours(l);
+        final long min = TimeUnit.SECONDS.toMinutes(l - TimeUnit.HOURS.toSeconds(hr));
+        final long sec = TimeUnit.SECONDS.toSeconds(l - TimeUnit.HOURS.toSeconds(hr) - TimeUnit.MINUTES.toSeconds(min));
+        return String.format("%02d:%02d:%02d", hr, min, sec);
+    }
+
+    class WriteToFEPThread extends Thread
+    {
+
+        public void run()
+        {
+            System.out.println("WriteToFEP Thread starting.");
+            // Run indefinitely
+            while (true)
+            {
+                try
+                {
+                    // Write the highway network status to the FEP Simulator
+                    highways.writeToFEP();
+                }
+                catch (SimulationException ex)
+                {
+                    // Ask user if they want to proceed without FEP Sim connection
+                    int reply = JOptionPane.showConfirmDialog(null, "Failed to connect to FEP Sim, proceed anyway?", "Network Failure", JOptionPane.YES_NO_OPTION);
+                    if (reply == JOptionPane.NO_OPTION)
+                    {
+                        System.exit(0);
+                    }
+                    System.out.println("Skipping writeToFEP...");
+                }
+
+                // Wait for FEP Sim to process the data we just sent
+                try
+                {
+                    Thread.sleep(FEPSIM_INTERVAL);
+                }
+                catch (InterruptedException ie)
+                {
+                    ie.printStackTrace();
+                }
+            }
+
+        }
+    }
+}
