Index: trunk/src/tmcsim/application.properties
===================================================================
--- trunk/src/tmcsim/application.properties	(revision 407)
+++ trunk/src/tmcsim/application.properties	(revision 416)
@@ -1,5 +1,5 @@
-#Thu, 16 May 2019 14:30:48 -0700
+#Wed, 05 Jun 2019 16:17:15 -0700
 
-Application.revision=406
+Application.revision=414
 
-Application.buildnumber=138
+Application.buildnumber=140
Index: trunk/src/tmcsim/client/CADlogDisplay.java
===================================================================
--- trunk/src/tmcsim/client/CADlogDisplay.java	(revision 416)
+++ trunk/src/tmcsim/client/CADlogDisplay.java	(revision 416)
@@ -0,0 +1,291 @@
+package tmcsim.client;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.FileInputStream;
+import java.rmi.Naming;
+import java.rmi.RemoteException;
+import java.rmi.server.UnicastRemoteObject;
+import java.util.Properties;
+import java.util.Vector;
+import java.util.concurrent.TimeUnit;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import javax.swing.JOptionPane;
+import javax.swing.JWindow;
+import javax.swing.Timer;
+import javax.swing.UIManager;
+import javax.swing.table.DefaultTableModel;
+import tmcsim.client.cadclientgui.data.Incident;
+import tmcsim.client.cadclientgui.enums.CADDataEnums.INC_TABLE;
+import tmcsim.common.SimulationException;
+import tmcsim.interfaces.CADClientInterface;
+import tmcsim.interfaces.CoordinatorInterface;
+
+/**
+ * CADlogDisplays shows the current CAD log for all incidents. It operates as a client of the
+ * CAD server, using RMI to poll the server every second for the current
+ * list of incidents and associated comments/notes table. 
+ *
+ * @author jdalbey
+ */
+public class CADlogDisplay extends UnicastRemoteObject implements
+        CADClientInterface
+{
+    /**
+     * Error logger.
+     */
+    private static Logger cadClientLogger = Logger.getLogger("tmcsim.client");
+
+    @Override
+    public void refresh() throws RemoteException
+    {
+        throw new UnsupportedOperationException("Not supported yet.");
+    }
+
+    /**
+     * Enumeration containing properties name values. See CADClient class
+     * description for more information.
+     *
+     * @author Matthew Cechini
+     * @see CADClient
+     */
+    private static enum PROPERTIES
+    {
+        CAD_SIM_HOST("CADSimulatorHost"), CAD_SIM_PORT("CADSimulatorSocketPort"), CAD_RMI_PORT(
+        "CADRmiPort"), CLIENT_CAD_POS("CADPosition"), CLIENT_USER_ID(
+        "CADUserID"), KEYBOARD_TYPE("KeyboardType"), DISPLAY_TYPE(
+        "DisplayType");
+        public String name;
+
+        private PROPERTIES(String n)
+        {
+            name = n;
+        }
+    }
+    /**
+     * CADClientSocket Object to handle socket communication between the Client
+     * and CAD Simulator.
+     */
+    private CADClientSocket theClientSocket;
+    /**
+     * Instance of the ClockView.
+     */
+    private ClockView theView;
+    /**
+     * Properties object for the CADClient class.
+     */
+    private Properties cadClientProp;
+    /**
+     * RMI interface for communication with the remote Coordinator.
+     */
+    private static CoordinatorInterface theCoorInt;
+    /**
+     * reference to itself to be used for disconnecting from CADSimulator
+     */
+    private CADClientInterface client = this;
+    private static final String CONFIG_FILE_NAME = "cad_client_config.properties";
+    private final static int TEN_SECONDS = 10000;
+
+    /**
+     * Constructor. Initialize data from parsed properties file. Create a socket
+     * connection to the CADSimulator.
+     *
+     * @param propertiesFile File path (absolute or relative) to the properties
+     * file containing configuration data.
+     */
+    public CADlogDisplay(String propertiesFile) throws SimulationException,
+            RemoteException
+    {
+        if (!verifyProperties(propertiesFile))
+        {
+            System.exit(0);
+        }
+
+        connect(cadClientProp.getProperty(PROPERTIES.CAD_SIM_HOST.name).trim(),
+                cadClientProp.getProperty(PROPERTIES.CAD_RMI_PORT.name).trim());
+
+        //theView = new ClockView();
+        //theView.setVisible(true);
+
+        // Create a timer that fetches the simulation time every second.
+        Timer timer = new Timer(TEN_SECONDS, new ActionListener()
+        {
+            public void actionPerformed(ActionEvent e)
+            {
+                try
+                {
+                    Vector<Incident> incList = theCoorInt.getIncidentList(); 
+                    StringBuffer sb = new StringBuffer();
+
+                    for (Incident incident: incList)
+                    {
+                    // DefaultTableModel noteTable = (DefaultTableModel) theCoorInt.getCadDataIncidentTable(INC_TABLE.COMMENTS_NOTES, incident.getLogNum());
+                     // Output noteTable
+                        sb.append("Incident # " + incident.logNum + "\n");
+                        // Retrieve the table of comments/notes the users created
+                        DefaultTableModel notesTable = incident.getCommentsNotesTable();
+                        // Retrieve the notes chronologically (Most recent is in first row)
+                        for (int row=notesTable.getRowCount()-1; row >=0; row--)
+                        {
+                            // Combine the fields into one export entry
+                            sb.append(notesTable.getValueAt(row,1) + " "); // time
+                            String initials = (String) notesTable.getValueAt(row,2); // initials
+                            // If there are no user intials, it's a scripted item
+                            if (initials.length() == 0)
+                            {
+                                initials = "Script";
+                            }
+                            sb.append(initials + " ");
+                            sb.append(notesTable.getValueAt(row,4) + "\n"); // notes
+                        }
+                    }
+                    System.out.println(sb);
+                    //long simtime = theCoorInt.getCurrentSimulationTime();
+                    //theView.updateTime("" + formatInterval(simtime));
+                } catch (RemoteException ex)
+                {
+                    Logger.getLogger(CADlogDisplay.class.getName()).log(Level.SEVERE, null, ex);
+                }
+            }
+        });
+        timer.start();
+
+        ensureProperShutdown();
+    }
+
+    /**
+     * Connect to the Coordinator's RMI object, and register this object for
+     * callback with the Coordinator.
+     *
+     * @param hostname Host name of the CAD Simulator.
+     * @param portNumber Port number of the CAD Simulator RMI communication.
+     * @throws SimulationException if there is an error creating the RMI
+     * connection.
+     */
+    protected void connect(String hostname, String portNumber)
+            throws SimulationException
+    {
+
+        String coorIntURL = "";
+
+        try
+        {
+            coorIntURL = "rmi://" + hostname + ":" + portNumber
+                    + "/coordinator";
+            theCoorInt = (CoordinatorInterface) Naming.lookup(coorIntURL);
+            theCoorInt.registerForCallback(this);
+        } catch (Exception e)
+        {
+            throw new SimulationException(SimulationException.CAD_SIM_CONNECT,
+                    e);
+        }
+    }
+
+    /**
+     * 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 verifyProperties(String propertiesFile)
+            throws SimulationException
+    {
+
+        // Load the properties file.
+        try
+        {
+            cadClientProp = new Properties();
+            cadClientProp.load(new FileInputStream(propertiesFile));
+        } catch (Exception e)
+        {
+            cadClientLogger.logp(Level.SEVERE, "SimulationManager",
+                    "Constructor", "Exception in reading properties file.", e);
+
+            throw new SimulationException(SimulationException.INITIALIZE_ERROR,
+                    e);
+        }
+
+
+        // Ensure that the properties file does not have null values for the
+        // CAD Simulator's connection information.
+        if (cadClientProp.getProperty(PROPERTIES.CAD_SIM_HOST.name) == null
+                || cadClientProp.getProperty(PROPERTIES.CAD_SIM_PORT.name) == null)
+        {
+            cadClientLogger.logp(Level.SEVERE, "SimulationManager",
+                    "Constructor", "Null value in properties file.");
+            throw new SimulationException(SimulationException.INITIALIZE_ERROR);
+        }
+
+        return true;
+    }
+
+    /**
+     * 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);
+    }
+
+    public void ensureProperShutdown()
+    {
+        Runtime.getRuntime().addShutdownHook(new Thread()
+        {
+            public void run()
+            {
+                try
+                {
+                    theCoorInt.unregisterForCallback(client);
+                } catch (RemoteException e)
+                {
+                    e.printStackTrace();
+                }
+            }
+        });
+    }
+
+    /**
+     * Construct the CADClient with the properties file path, either from the
+     * command line arguments or default.
+     *
+     * @param args Command line arguments.
+     */
+    public static void main(String[] args)
+    {
+        if (System.getProperty("CONFIG_DIR") == null)
+        {
+            System.setProperty("CONFIG_DIR", "config");
+        }
+
+        try
+        {
+            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
+            new CADlogDisplay(System.getProperty("CONFIG_DIR") + System.getProperty("file.separator") + CONFIG_FILE_NAME);
+
+        } catch (Exception e)
+        {
+            cadClientLogger.logp(Level.SEVERE, "SimulationManager", "Main",
+                    "Error initializing application.");
+
+            JOptionPane.showMessageDialog(new JWindow(), e.getMessage(),
+                    "Error - Program Exiting", JOptionPane.ERROR_MESSAGE);
+
+            System.exit(-1);
+        }
+
+    }
+}
Index: trunk/src/tmcsim/simulationmanager/SimulationManagerView.java
===================================================================
--- trunk/src/tmcsim/simulationmanager/SimulationManagerView.java	(revision 365)
+++ trunk/src/tmcsim/simulationmanager/SimulationManagerView.java	(revision 416)
@@ -47,4 +47,5 @@
 import tmcsim.simulationmanager.actions.DeleteIncidentAction;
 import tmcsim.simulationmanager.actions.ExitAction;
+import tmcsim.simulationmanager.actions.ExportAction;
 import tmcsim.simulationmanager.actions.GotoTimeIndexAction;
 import tmcsim.simulationmanager.actions.LoadParamicsNetworkAction;
@@ -686,9 +687,11 @@
     private void createMenuBar() {
 
-        gotoMenuItem = new JMenuItem(new GotoTimeIndexAction(this));        
+        gotoMenuItem = new JMenuItem(new GotoTimeIndexAction(this));    
+        exportMenuItem = new JMenuItem(new ExportAction(this));
         exitMenuItem = new JMenuItem(new ExitAction(this));
         
         fileMenu = new JMenu("File");
         fileMenu.add(gotoMenuItem);
+        fileMenu.add(exportMenuItem);
         fileMenu.add(exitMenuItem);
         
@@ -1255,4 +1258,5 @@
     private JMenu fileMenu;
     private JMenuItem gotoMenuItem;
+    private JMenuItem exportMenuItem;
     private JMenuItem exitMenuItem;
     
Index: trunk/src/tmcsim/simulationmanager/actions/ExportAction.java
===================================================================
--- trunk/src/tmcsim/simulationmanager/actions/ExportAction.java	(revision 416)
+++ trunk/src/tmcsim/simulationmanager/actions/ExportAction.java	(revision 416)
@@ -0,0 +1,92 @@
+package tmcsim.simulationmanager.actions;
+
+import java.awt.event.ActionEvent;
+import java.io.File;
+import java.util.Vector;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.swing.AbstractAction;
+import javax.swing.JFileChooser;
+import javax.swing.JOptionPane;
+import javax.swing.table.DefaultTableModel;
+import javax.xml.parsers.SAXParserFactory;
+
+import tmcsim.client.cadclientgui.data.Incident;
+import tmcsim.common.ScriptException;
+import tmcsim.client.cadclientgui.ScriptHandler;
+import tmcsim.common.SimulationException;
+import tmcsim.common.CADEnums.SCRIPT_STATUS;
+import tmcsim.simulationmanager.SimulationManagerView;
+import tmcsim.simulationmanager.dialogs.AddIncidentDialog;
+
+
+/**
+ * ExportAction is an AbstractAction that exports Incident data from the 
+ * current simulation.  (Initially, just shows data in popup window).
+ * @author jdalbey
+ */
+@SuppressWarnings("serial")
+public class ExportAction extends AbstractAction {
+    
+    /** Reference to the SimulationManagerView object. */
+    private SimulationManagerView theSimManagerView = null;
+    
+    /** 
+     * Constructor.
+     * @param view View class object for the Simulation Manager.
+     */     
+    public ExportAction(SimulationManagerView view) {
+        super("Export Incident Notes");
+        theSimManagerView = view;
+    }
+    /** Perform the action of exporting. */
+    public void actionPerformed(ActionEvent evt) 
+    {
+        /** Create a process that can run in a separate thread so the
+         *  simulation can get back to work.
+         */
+        Runnable addRunnable = new Runnable() 
+        {
+            public void run() 
+            {
+                try {
+                    // Retrieve the current incidents from the simulation mgr.
+                    Vector<Incident> currIncidents = theSimManagerView.getModel().getIncidentList();
+                    
+                    StringBuffer sb = new StringBuffer();
+                    // For each incident in the list
+                    for (Incident inc : currIncidents) 
+                    {
+                        sb.append("Incident # " + inc.logNum + "\n");
+                        // Retrieve the table of comments/notes the users created
+                        DefaultTableModel notesTable = inc.getCommentsNotesTable();
+                        // Retrieve the notes chronologically (Most recent is in first row)
+                        for (int row=notesTable.getRowCount()-1; row >=0; row--)
+                        {
+                            // Combine the fields into one export entry
+                            sb.append(notesTable.getValueAt(row,1) + " "); // time
+                            String initials = (String) notesTable.getValueAt(row,2); // initials
+                            // If there are no user intials, it's a scripted item
+                            if (initials.length() == 0)
+                            {
+                                initials = "Script";
+                            }
+                            sb.append(initials + " ");
+                            sb.append(notesTable.getValueAt(row,4) + "\n"); // notes
+                        }
+                        System.out.println(sb);
+                    }
+                    JOptionPane.showMessageDialog(theSimManagerView, sb, "Export", JOptionPane.INFORMATION_MESSAGE);
+                } catch (SimulationException ex) {
+                    Logger.getLogger(ExportAction.class.getName()).log(Level.SEVERE, null, ex);
+                }
+            }
+        };
+
+        Thread theThread = new Thread(addRunnable);
+            theThread.start();
+
+    }
+
+}
Index: trunk/src/tmcsim/cadsimulator/Coordinator.java
===================================================================
--- trunk/src/tmcsim/cadsimulator/Coordinator.java	(revision 407)
+++ trunk/src/tmcsim/cadsimulator/Coordinator.java	(revision 416)
@@ -98,7 +98,5 @@
      * The name of the file where the simulation clock time is written
      */
-    private String kSimClockFilename = "webapps" + 
-            System.getProperty("file.separator") + "dynamicdata" + 
-            System.getProperty("file.separator") + "sim_elapsedtime.json";        
+    private String kSimClockFilename;
     /**
      * Error logger.
@@ -125,5 +123,5 @@
      * Constructor. Call UnicastRemoteObject constructor and call
      * initializeSimulation.
-     *
+     * @param simTimeFilename name of the file where the simulation clock time is written
      * @throws RemoteException
      */
