Index: trunk/src/spikes/TextComponentDemo.java
===================================================================
--- trunk/src/spikes/TextComponentDemo.java	(revision 416)
+++ trunk/src/spikes/TextComponentDemo.java	(revision 416)
@@ -0,0 +1,422 @@
+
+package spikes;
+
+
+import java.awt.*;
+import java.awt.event.*;
+import java.util.HashMap;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.swing.*;
+import javax.swing.text.*;
+import javax.swing.event.*;
+import javax.swing.undo.*;
+
+public class TextComponentDemo extends JFrame {
+    JTextPane textPane;
+    AbstractDocument doc;
+    static final int MAX_CHARACTERS = 300;
+    JTextArea changeLog;
+    String newline = "\n";
+    HashMap<Object, Action> actions;
+
+    //undo helpers
+    protected UndoAction undoAction;
+    protected RedoAction redoAction;
+    protected UndoManager undo = new UndoManager();
+    private ClearAction saveAction = new ClearAction();
+
+    public TextComponentDemo() {
+        super("TextComponentDemo");
+
+        //Create the text pane and configure it.
+        textPane = new JTextPane();
+        textPane.setCaretPosition(0);
+        textPane.setMargin(new Insets(5,5,5,5));
+        StyledDocument styledDoc = textPane.getStyledDocument();
+        if (styledDoc instanceof AbstractDocument) {
+            doc = (AbstractDocument)styledDoc;
+            doc.setDocumentFilter(new DocumentSizeFilter(MAX_CHARACTERS));
+        } else {
+            System.err.println("Text pane's document isn't an AbstractDocument!");
+            System.exit(-1);
+        }
+        JScrollPane scrollPane = new JScrollPane(textPane);
+        scrollPane.setPreferredSize(new Dimension(200, 200));
+
+        //Create the text area for the status log and configure it.
+        changeLog = new JTextArea(5, 30);
+        changeLog.setEditable(false);
+        JScrollPane scrollPaneForLog = new JScrollPane(changeLog);
+
+        //Create a split pane for the change log and the text area.
+        JSplitPane splitPane = new JSplitPane(
+                                       JSplitPane.VERTICAL_SPLIT,
+                                       scrollPane, scrollPaneForLog);
+        splitPane.setOneTouchExpandable(true);
+
+        //Create the status area.
+        JPanel statusPane = new JPanel(new GridLayout(1, 1));
+        CaretListenerLabel caretListenerLabel =
+                new CaretListenerLabel("Caret Status");
+        statusPane.add(caretListenerLabel);
+
+        //Add the components.
+        getContentPane().add(splitPane, BorderLayout.CENTER);
+        getContentPane().add(statusPane, BorderLayout.PAGE_END);
+
+        //Set up the menu bar.
+        actions=createActionTable(textPane);
+        JMenu editMenu = createEditMenu();
+        JMenu styleMenu = createStyleMenu();
+        JMenuBar mb = new JMenuBar();
+        mb.add(editMenu);
+        mb.add(styleMenu);
+        setJMenuBar(mb);
+
+        //Add some key bindings.
+        addBindings();
+
+        //Put the initial text into the text pane.
+        initDocument();
+        textPane.setCaretPosition(0);
+
+        //Start watching for undoable edits and caret changes.
+        doc.addUndoableEditListener(new MyUndoableEditListener());
+        textPane.addCaretListener(caretListenerLabel);
+        doc.addDocumentListener(new MyDocumentListener());
+    }
+
+    //This listens for and reports caret movements.
+    protected class CaretListenerLabel extends JLabel
+                                       implements CaretListener {
+        public CaretListenerLabel(String label) {
+            super(label);
+        }
+
+        //Might not be invoked from the event dispatch thread.
+        public void caretUpdate(CaretEvent e) {
+            displaySelectionInfo(e.getDot(), e.getMark());
+        }
+
+        //This method can be invoked from any thread.  It 
+        //invokes the setText and modelToView methods, which 
+        //must run on the event dispatch thread. We use
+        //invokeLater to schedule the code for execution
+        //on the event dispatch thread.
+        protected void displaySelectionInfo(final int dot,
+                                            final int mark) {
+            SwingUtilities.invokeLater(new Runnable() {
+                public void run() {
+                    if (dot == mark) {  // no selection
+                        try {
+                            Rectangle caretCoords = textPane.modelToView(dot);
+                            //Convert it to view coordinates.
+                            setText("caret: text position: " + dot
+                                    + ", view location = ["
+                                    + caretCoords.x + ", "
+                                    + caretCoords.y + "]"
+                                    + newline);
+                        } catch (BadLocationException ble) {
+                            setText("caret: text position: " + dot + newline);
+                        }
+                    } else if (dot < mark) {
+                        setText("selection from: " + dot
+                                + " to " + mark + newline);
+                    } else {
+                        setText("selection from: " + mark
+                                + " to " + dot + newline);
+                    }
+                }
+            });
+        }
+    }
+
+    //This one listens for edits that can be undone.
+    protected class MyUndoableEditListener
+                    implements UndoableEditListener {
+        public void undoableEditHappened(UndoableEditEvent e) {
+            //Remember the edit and update the menus.
+            undo.addEdit(e.getEdit());
+            undoAction.updateUndoState();
+            redoAction.updateRedoState();
+        }
+    }
+
+    //And this one listens for any changes to the document.
+    protected class MyDocumentListener
+                    implements DocumentListener {
+        public void insertUpdate(DocumentEvent e) {
+            displayEditInfo(e);
+        }
+        public void removeUpdate(DocumentEvent e) {
+            displayEditInfo(e);
+        }
+        public void changedUpdate(DocumentEvent e) {
+            displayEditInfo(e);
+        }
+        private void displayEditInfo(DocumentEvent e) {
+            Document document = e.getDocument();
+            int changeLength = e.getLength();
+            changeLog.append(e.getType().toString() + ": " +
+                changeLength + " character" +
+                ((changeLength == 1) ? ". " : "s. ") +
+                " Text length = " + document.getLength() +
+                "." + newline);
+        }
+    }
+
+    //Add a couple of emacs key bindings for navigation.
+    protected void addBindings() {
+        InputMap inputMap = textPane.getInputMap();
+        ActionMap actionMap = textPane.getActionMap();
+        //Ctrl-b to go backward one character
+        KeyStroke key = KeyStroke.getKeyStroke(KeyEvent.VK_B, Event.CTRL_MASK);
+        //inputMap.put(key, DefaultEditorKit.backwardAction);
+        inputMap.put(key, "myAction");
+        actionMap.put("myAction", saveAction);
+        
+        //Ctrl-f to go forward one character
+        key = KeyStroke.getKeyStroke(KeyEvent.VK_F, Event.CTRL_MASK);
+        inputMap.put(key, DefaultEditorKit.forwardAction);
+
+        //Ctrl-p to go up one line
+        key = KeyStroke.getKeyStroke(KeyEvent.VK_P, Event.CTRL_MASK);
+        inputMap.put(key, DefaultEditorKit.upAction);
+
+        //Ctrl-n to go down one line
+        key = KeyStroke.getKeyStroke(KeyEvent.VK_N, Event.CTRL_MASK);
+        inputMap.put(key, DefaultEditorKit.downAction);
+    }
+
+    //Create the edit menu.
+    protected JMenu createEditMenu() {
+        JMenu menu = new JMenu("Edit");
+
+        //Undo and redo are actions of our own creation.
+        undoAction = new UndoAction();
+        menu.add(undoAction);
+
+        redoAction = new RedoAction();
+        menu.add(redoAction);
+
+        menu.addSeparator();
+
+        //These actions come from the default editor kit.
+        //Get the ones we want and stick them in the menu.
+        menu.add(getActionByName(DefaultEditorKit.cutAction));
+        menu.add(getActionByName(DefaultEditorKit.copyAction));
+        menu.add(getActionByName(DefaultEditorKit.pasteAction));
+
+        menu.addSeparator();
+
+        menu.add(getActionByName(DefaultEditorKit.selectAllAction));
+        return menu;
+    }
+
+    //Create the style menu.
+    protected JMenu createStyleMenu() {
+        JMenu menu = new JMenu("Style");
+
+        Action action = new StyledEditorKit.BoldAction();
+        action.putValue(Action.NAME, "Bold");
+        menu.add(action);
+
+        action = new StyledEditorKit.ItalicAction();
+        action.putValue(Action.NAME, "Italic");
+        menu.add(action);
+
+        action = new StyledEditorKit.UnderlineAction();
+        action.putValue(Action.NAME, "Underline");
+        menu.add(action);
+
+        menu.addSeparator();
+
+        menu.add(new StyledEditorKit.FontSizeAction("12", 12));
+        menu.add(new StyledEditorKit.FontSizeAction("14", 14));
+        menu.add(new StyledEditorKit.FontSizeAction("18", 18));
+
+        menu.addSeparator();
+
+        menu.add(new StyledEditorKit.FontFamilyAction("Serif",
+                                                      "Serif"));
+        menu.add(new StyledEditorKit.FontFamilyAction("SansSerif",
+                                                      "SansSerif"));
+
+        menu.addSeparator();
+
+        menu.add(new StyledEditorKit.ForegroundAction("Red",
+                                                      Color.red));
+        menu.add(new StyledEditorKit.ForegroundAction("Green",
+                                                      Color.green));
+        menu.add(new StyledEditorKit.ForegroundAction("Blue",
+                                                      Color.blue));
+        menu.add(new StyledEditorKit.ForegroundAction("Black",
+                                                      Color.black));
+
+        return menu;
+    }
+
+    protected void initDocument() {
+        String initString[] =
+                { "Use the mouse to place the caret.",
+                  "Use the edit menu to cut, copy, paste, and select text.",
+                  "Also to undo and redo changes.",
+                  "Use the style menu to change the style of the text.",
+                  "Use the arrow keys on the keyboard or these emacs key bindings to move the caret:",
+                  "Ctrl-f, Ctrl-b, Ctrl-n, Ctrl-p." };
+
+        SimpleAttributeSet[] attrs = initAttributes(initString.length);
+
+        try {
+            for (int i = 0; i < initString.length; i ++) {
+                doc.insertString(doc.getLength(), initString[i] + newline,
+                        attrs[i]);
+            }
+        } catch (BadLocationException ble) {
+            System.err.println("Couldn't insert initial text.");
+        }
+    }
+
+    protected SimpleAttributeSet[] initAttributes(int length) {
+        //Hard-code some attributes.
+        SimpleAttributeSet[] attrs = new SimpleAttributeSet[length];
+
+        attrs[0] = new SimpleAttributeSet();
+        StyleConstants.setFontFamily(attrs[0], "SansSerif");
+        StyleConstants.setFontSize(attrs[0], 16);
+
+        attrs[1] = new SimpleAttributeSet(attrs[0]);
+        StyleConstants.setBold(attrs[1], true);
+
+        attrs[2] = new SimpleAttributeSet(attrs[0]);
+        StyleConstants.setItalic(attrs[2], true);
+
+        attrs[3] = new SimpleAttributeSet(attrs[0]);
+        StyleConstants.setFontSize(attrs[3], 20);
+
+        attrs[4] = new SimpleAttributeSet(attrs[0]);
+        StyleConstants.setFontSize(attrs[4], 12);
+
+        attrs[5] = new SimpleAttributeSet(attrs[0]);
+        StyleConstants.setForeground(attrs[5], Color.red);
+
+        return attrs;
+    }
+
+    //The following two methods allow us to find an
+    //action provided by the editor kit by its name.
+    private HashMap<Object, Action> createActionTable(JTextComponent textComponent) {
+        HashMap<Object, Action> actions = new HashMap<Object, Action>();
+        Action[] actionsArray = textComponent.getActions();
+        for (int i = 0; i < actionsArray.length; i++) {
+            Action a = actionsArray[i];
+            actions.put(a.getValue(Action.NAME), a);
+        }
+	return actions;
+    }
+
+    private Action getActionByName(String name) {
+        return actions.get(name);
+    }
+
+    class ClearAction extends AbstractAction 
+    {
+        public void actionPerformed(ActionEvent evt) 
+        {
+            JTextPane src = (JTextPane) evt.getSource();
+            StyledDocument doc = src.getStyledDocument();
+            int length = doc.getLength();
+            try {
+                doc.remove(0,length);
+            } catch (BadLocationException ex) {
+                Logger.getLogger(TextComponentDemo.class.getName()).log(Level.SEVERE, null, ex);
+            }
+        }
+    }
+
+    class UndoAction extends AbstractAction {
+        public UndoAction() {
+            super("Undo");
+            setEnabled(false);
+        }
+
+        public void actionPerformed(ActionEvent e) {
+            try {
+                undo.undo();
+            } catch (CannotUndoException ex) {
+                System.out.println("Unable to undo: " + ex);
+                ex.printStackTrace();
+            }
+            updateUndoState();
+            redoAction.updateRedoState();
+        }
+
+        protected void updateUndoState() {
+            if (undo.canUndo()) {
+                setEnabled(true);
+                putValue(Action.NAME, undo.getUndoPresentationName());
+            } else {
+                setEnabled(false);
+                putValue(Action.NAME, "Undo");
+            }
+        }
+    }
+
+    class RedoAction extends AbstractAction {
+        public RedoAction() {
+            super("Redo");
+            setEnabled(false);
+        }
+
+        public void actionPerformed(ActionEvent e) {
+            try {
+                undo.redo();
+            } catch (CannotRedoException ex) {
+                System.out.println("Unable to redo: " + ex);
+                ex.printStackTrace();
+            }
+            updateRedoState();
+            undoAction.updateUndoState();
+        }
+
+        protected void updateRedoState() {
+            if (undo.canRedo()) {
+                setEnabled(true);
+                putValue(Action.NAME, undo.getRedoPresentationName());
+            } else {
+                setEnabled(false);
+                putValue(Action.NAME, "Redo");
+            }
+        }
+    }
+
+    /**
+     * Create the GUI and show it.  For thread safety,
+     * this method should be invoked from the
+     * event dispatch thread.
+     */
+    private static void createAndShowGUI() {
+        //Create and set up the window.
+        final TextComponentDemo frame = new TextComponentDemo();
+        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+
+        //Display the window.
+        frame.pack();
+        frame.setVisible(true);
+    }
+
+    //The standard main method.
+    public static void main(String[] args) {
+        //Schedule a job for the event dispatch thread:
+        //creating and showing this application's GUI.
+        SwingUtilities.invokeLater(new Runnable() {
+            public void run() {
+                //Turn off metal's use of bold fonts
+	        UIManager.put("swing.boldMetal", Boolean.FALSE);
+		createAndShowGUI();
+            }
+        });
+    }
+}
Index: trunk/src/spikes/DocumentSizeFilter.java
===================================================================
--- trunk/src/spikes/DocumentSizeFilter.java	(revision 416)
+++ trunk/src/spikes/DocumentSizeFilter.java	(revision 416)
@@ -0,0 +1,51 @@
+
+package spikes;
+
+import javax.swing.*;
+import javax.swing.text.*;
+import java.awt.Toolkit;
+
+public class DocumentSizeFilter extends DocumentFilter {
+    int maxCharacters;
+    boolean DEBUG = false;
+
+    public DocumentSizeFilter(int maxChars) {
+        maxCharacters = maxChars;
+    }
+
+    public void insertString(FilterBypass fb, int offs,
+                             String str, AttributeSet a)
+        throws BadLocationException {
+        if (DEBUG) {
+            System.out.println("in DocumentSizeFilter's insertString method");
+        }
+
+        //This rejects the entire insertion if it would make
+        //the contents too long. Another option would be
+        //to truncate the inserted string so the contents
+        //would be exactly maxCharacters in length.
+        if ((fb.getDocument().getLength() + str.length()) <= maxCharacters)
+            super.insertString(fb, offs, str, a);
+        else
+            Toolkit.getDefaultToolkit().beep();
+    }
+    
+    public void replace(FilterBypass fb, int offs,
+                        int length, 
+                        String str, AttributeSet a)
+        throws BadLocationException {
+        if (DEBUG) {
+            System.out.println("in DocumentSizeFilter's replace method");
+        }
+        //This rejects the entire replacement if it would make
+        //the contents too long. Another option would be
+        //to truncate the replacement string so the contents
+        //would be exactly maxCharacters in length.
+        if ((fb.getDocument().getLength() + str.length()
+             - length) <= maxCharacters)
+            super.replace(fb, offs, length, str, a);
+        else
+            Toolkit.getDefaultToolkit().beep();
+    }
+
+}
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
      */
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/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/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;
     
