LISTSERV mailing list manager LISTSERV 16.5

Help for HPS-SVN Archives


HPS-SVN Archives

HPS-SVN Archives


HPS-SVN@LISTSERV.SLAC.STANFORD.EDU


View:

Message:

[

First

|

Previous

|

Next

|

Last

]

By Topic:

[

First

|

Previous

|

Next

|

Last

]

By Author:

[

First

|

Previous

|

Next

|

Last

]

Font:

Proportional Font

LISTSERV Archives

LISTSERV Archives

HPS-SVN Home

HPS-SVN Home

HPS-SVN  April 2015

HPS-SVN April 2015

Subject:

r2671 - in /java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application: ./ model/ util/

From:

[log in to unmask]

Reply-To:

Notification of commits to the hps svn repository <[log in to unmask]>

Date:

Fri, 10 Apr 2015 02:23:08 -0000

Content-Type:

text/plain

Parts/Attachments:

Parts/Attachments

text/plain (11598 lines)

Author: [log in to unmask]
Date: Thu Apr  9 19:22:57 2015
New Revision: 2671

Log:
Code cleanup in monitoring-app module.

Modified:
    java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/AbstractFieldsPanel.java
    java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/AddActionListener.java
    java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/Commands.java
    java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/ConditionsCollectionTableModel.java
    java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/ConditionsPanel.java
    java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/ConnectionSettingsPanel.java
    java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/ConnectionStatusPanel.java
    java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/DataSourceComboBox.java
    java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/DatePanel.java
    java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/EventButtonsPanel.java
    java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/EventDashboard.java
    java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/EventProcessing.java
    java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/FieldPanel.java
    java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/JobSettingsPanel.java
    java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/LogLevelFilterComboBox.java
    java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/LogPanel.java
    java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/LogTable.java
    java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/Main.java
    java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/MenuBar.java
    java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/MonitoringApplication.java
    java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/MonitoringApplicationFrame.java
    java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/PlotInfoPanel.java
    java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/PlotPanel.java
    java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/SettingsDialog.java
    java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/SettingsPanel.java
    java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/SystemStatusEventsTable.java
    java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/SystemStatusPanel.java
    java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/SystemStatusTable.java
    java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/ToolbarPanel.java
    java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/TriggerDiagnosticsPanel.java
    java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/model/AbstractModel.java
    java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/model/Configuration.java
    java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/model/ConfigurationModel.java
    java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/model/ConnectionStatus.java
    java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/model/ConnectionStatusModel.java
    java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/model/HasConfigurationModel.java
    java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/model/RunModel.java
    java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/model/SteeringType.java
    java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/model/SystemStatusTableModel.java
    java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/package-info.java
    java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/util/AIDAServer.java
    java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/util/DialogUtil.java
    java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/util/ErrorHandler.java
    java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/util/EtSystemUtil.java
    java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/util/EvioFileFilter.java
    java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/util/ResourceUtil.java
    java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/util/SyncEventProcessor.java
    java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/util/TableExporter.java

Modified: java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/AbstractFieldsPanel.java
 =============================================================================
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/AbstractFieldsPanel.java	(original)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/AbstractFieldsPanel.java	Thu Apr  9 19:22:57 2015
@@ -16,6 +16,7 @@
 import javax.swing.JLabel;
 import javax.swing.JPanel;
 import javax.swing.JTextField;
+import javax.swing.SwingConstants;
 
 import org.hps.monitoring.application.model.ConfigurationModel;
 import org.hps.monitoring.application.model.HasConfigurationModel;
@@ -23,6 +24,8 @@
 /**
  * A <code>JPanel</code> which has a number of fields with the labels in the first column and the components for
  * showing/editing the fields in the second. It uses <code>GridBagConstraints</code> for layout.
+ *
+ * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a>
  */
 @SuppressWarnings("serial")
 abstract class AbstractFieldsPanel extends JPanel implements PropertyChangeListener, HasConfigurationModel,
@@ -83,18 +86,14 @@
      * @return <code>true</code> if property change event should be accepted
      */
     boolean accept(final PropertyChangeEvent evt) {
-        if (evt.getPropertyName().equals("ancestor")) {
-            return false;
-        } else {
-            return true;
-        }
+        return !"ancestor".equals(evt.getPropertyName());
     }
 
     /**
      * Add an ActionListener to this component. By default this does nothing, but individual sub-components should
      * attach this to individual components.
      *
-     * @param listener The AcitonListener to add.
+     * @param listener the AcitonListener to add
      */
     @Override
     public void addActionListener(final ActionListener listener) {
@@ -124,10 +123,10 @@
     /**
      * Add a check box.
      *
-     * @param name The name of the check box.
-     * @param selected Whether the check box is selected or not.
-     * @param enabled Whether it is enabled or not.
-     * @return The JCheckBox component.
+     * @param name the name of the check box
+     * @param selected whether the check box is selected or not
+     * @param enabled whether it is enabled or not
+     * @return the JCheckBox component
      */
     protected final JCheckBox addCheckBox(final String name, final boolean selected, final boolean enabled) {
 
@@ -157,10 +156,10 @@
     /**
      * Add a check box.
      *
-     * @param name The name of the check box.
-     * @param tooltip The tooltip text.
-     * @param selected Whether the box is selected or not.
-     * @param enabled Whether it is enabled or not.
+     * @param name the name of the check box
+     * @param tooltip the tooltip text
+     * @param selected <code>true</code> if component is selected
+     * @param enabled <code>true</code> if component enabled
      * @return The JCheckBox component.
      */
     protected final JCheckBox addCheckBox(final String name, final String tooltip, final boolean selected,
@@ -173,9 +172,9 @@
     /**
      * Add a combo box.
      *
-     * @param name The name of the combo box.
-     * @param values The set of values for the combo box.
-     * @return The JComboBox component.
+     * @param name the name of the combo box
+     * @param values the set of values for the combo box
+     * @return the JComboBox component
      */
     @SuppressWarnings({ "rawtypes", "unchecked" })
     protected final JComboBox addComboBox(final String name, final String[] values) {
@@ -186,7 +185,7 @@
         c.insets = this.insets;
         c.anchor = GridBagConstraints.WEST;
         final JLabel waitModeLabel = new JLabel(name);
-        waitModeLabel.setHorizontalAlignment(JLabel.LEFT);
+        waitModeLabel.setHorizontalAlignment(SwingConstants.LEFT);
         this.add(waitModeLabel, c);
 
         c = new GridBagConstraints();
@@ -206,9 +205,9 @@
     /**
      * Add a multiline combo box.
      *
-     * @param name The name of the combo box.
-     * @param values The values for the combo box.
-     * @return The JComboBox component.
+     * @param name the name of the combo box
+     * @param values the values for the combo box
+     * @return the <code>JComboBox</code> component
      */
     @SuppressWarnings({ "rawtypes", "unchecked" })
     protected final JComboBox addComboBoxMultiline(final String name, final String[] values) {
@@ -220,7 +219,7 @@
         c.insets = this.insets;
         c.anchor = GridBagConstraints.WEST;
         final JLabel waitModeLabel = new JLabel(name + ":");
-        waitModeLabel.setHorizontalAlignment(JLabel.LEFT);
+        waitModeLabel.setHorizontalAlignment(SwingConstants.LEFT);
         this.add(waitModeLabel, c);
         ++this.currentGridY;
 
@@ -242,8 +241,8 @@
     /**
      * Add a labeled JComponent to the panel.
      *
-     * @param name The label text.
-     * @param component The component to add.
+     * @param name the label text
+     * @param component the component to add
      */
     void addComponent(final String name, final JComponent component) {
 
@@ -270,9 +269,9 @@
     /**
      * Add a field.
      *
-     * @param name The name of the field.
-     * @param size The size of the field.
-     * @return The JTextField component.
+     * @param name the name of the field
+     * @param size the size of the field
+     * @return the <code>JTextField</code> component
      */
     protected final JTextField addField(final String name, final int size) {
         return this.addField(name, "", size, this.editable);
@@ -281,10 +280,10 @@
     /**
      * Add a field.
      *
-     * @param name The name of the field.
-     * @param value The default value of the field.
-     * @param size The size of the field.
-     * @return The JTextField component.
+     * @param name the name of the field
+     * @param value the default value of the field
+     * @param size the size of the field
+     * @return the <code>JTextField</code> component
      */
     protected final JTextField addField(final String name, final String value, final int size) {
         return this.addField(name, value, size, this.editable);
@@ -293,11 +292,11 @@
     /**
      * Add a field.
      *
-     * @param name The name of the field.
-     * @param value The default value of the field.
-     * @param size The size of the field.
-     * @param editable The editable setting.
-     * @return The JTextField component.
+     * @param name the name of the field
+     * @param value the default value of the field
+     * @param size the size of the field
+     * @param editable the editable setting
+     * @return the <code>JTextField</code> component
      */
     protected final JFormattedTextField addField(final String name, final String value, final int size,
             final boolean editable) {
@@ -317,7 +316,7 @@
         // JFormattedTextField field = new JFormattedTextField(value, size);
         final JFormattedTextField field = new JFormattedTextField(value);
         field.setColumns(size);
-        field.setHorizontalAlignment(JTextField.RIGHT);
+        field.setHorizontalAlignment(SwingConstants.RIGHT);
         field.setEditable(editable);
         field.setBackground(Color.WHITE);
         this.add(field, c);
@@ -330,12 +329,12 @@
     /**
      * Add a field.
      *
-     * @param name The name of the field.
-     * @param value The default value of the field.
-     * @param tooltip The tooltip text.
-     * @param size The size of the field.
-     * @param editable The editable setting.
-     * @return The JTextField component.
+     * @param name the name of the field
+     * @param value the default value of the field
+     * @param tooltip the tooltip text
+     * @param size the size of the field
+     * @param editable the editable setting
+     * @return the <code>JTextField</code> component
      */
     protected final JFormattedTextField addField(final String name, final String value, final String tooltip,
             final int size, final boolean editable) {
@@ -345,9 +344,9 @@
     }
 
     /**
-     * Get the configuration model for this component.
-     * 
-     * @return the configuration model for the component
+     * Get the {@link org.hps.monitoring.application.model.ConfigurationModel} for this component
+     *
+     * @return the {@link org.hps.monitoring.application.model.ConfigurationModel} for this component
      */
     @Override
     public ConfigurationModel getConfigurationModel() {

Modified: java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/AddActionListener.java
 =============================================================================
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/AddActionListener.java	(original)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/AddActionListener.java	Thu Apr  9 19:22:57 2015
@@ -4,13 +4,14 @@
 
 /**
  * Mixin interface for components which can be assigned an external <code>ActionListener</code>.
- * 
- * @author Jeremy McCormick <[log in to unmask]>
+ *
+ * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a>
  */
 interface AddActionListener {
 
     /**
      * Assign an <code>ActionListener</code> to this component which will assign to appropriate child components.
+     *
      * @param listener the <code>ActionListener</code> to assign to this component
      */
     void addActionListener(ActionListener listener);

Modified: java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/Commands.java
 =============================================================================
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/Commands.java	(original)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/Commands.java	Thu Apr  9 19:22:57 2015
@@ -1,8 +1,8 @@
 package org.hps.monitoring.application;
 
 /**
- * These strings are used to identify ActionEvents in the MonitoringApplication. A few commands
- * handled only by sub-components are not listed here.
+ * These strings are used to identify ActionEvents in the MonitoringApplication. A few commands handled only by
+ * sub-components are not listed here.
  *
  * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a>
  */

Modified: java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/ConditionsCollectionTableModel.java
 =============================================================================
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/ConditionsCollectionTableModel.java	(original)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/ConditionsCollectionTableModel.java	Thu Apr  9 19:22:57 2015
@@ -10,10 +10,10 @@
 /**
  * This is a table model for a collection of conditions objects.
  *
- * @author Jeremy McCormick <[log in to unmask]>
- *
+ * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a>
  */
-class ConditionsCollectionTableModel extends DefaultTableModel {
+@SuppressWarnings("serial")
+final class ConditionsCollectionTableModel extends DefaultTableModel {
 
     /**
      * The {@link org.hps.conditions.api.ConditionsObjectCollection} for the model.

Modified: java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/ConditionsPanel.java
 =============================================================================
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/ConditionsPanel.java	(original)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/ConditionsPanel.java	Thu Apr  9 19:22:57 2015
@@ -28,15 +28,21 @@
 /**
  * The component for showing conditions tables in the monitoring app.
  *
- * @author Jeremy McCormick <[log in to unmask]>
+ * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a>
  */
-public class ConditionsPanel extends JPanel {
+@SuppressWarnings("serial")
+public final class ConditionsPanel extends JPanel {
 
     /**
      * The listener for updating the panel when conditions are changed.
      */
     class ConditionsPanelListener implements ConditionsListener {
 
+        /**
+         * Handle conditions change event.
+         *
+         * @param event the conditions change event
+         */
         @Override
         public void conditionsChanged(final ConditionsEvent event) {
 
@@ -65,12 +71,24 @@
         }
     }
 
+    /**
+     * The GUI component listing the conditions sets for the run.
+     */
     private final JList<String> conditionsList = new JList<String>();
 
+    /**
+     * The table which shows the currently selected conditions set from the list.
+     */
     private final JTable conditionsTable = new JTable();
 
+    /**
+     * Map of conditions set names to table models.
+     */
     private Map<String, ConditionsCollectionTableModel> tableModels;
 
+    /**
+     * Class constructor which will initialize sub-components.
+     */
     ConditionsPanel() {
         super(new BorderLayout());
 
@@ -81,7 +99,7 @@
                 final String tableName = ConditionsPanel.this.conditionsList.getSelectedValue();
                 final TableModel model = ConditionsPanel.this.tableModels.get(tableName);
                 ConditionsPanel.this.conditionsTable.setModel(model);
-                ConditionsPanel.this.conditionsTable.setRowSorter(new TableRowSorter(model));
+                ConditionsPanel.this.conditionsTable.setRowSorter(new TableRowSorter<TableModel>(model));
                 ConditionsPanel.this.conditionsTable.revalidate();
             }
         });
@@ -90,8 +108,8 @@
 
         final JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, this.conditionsList, new JScrollPane(
                 this.conditionsTable));
-        splitPane.setResizeWeight(0.6);
+        // splitPane.setResizeWeight(0.6);
 
         this.add(splitPane);
     }
-}
+}

Modified: java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/ConnectionSettingsPanel.java
 =============================================================================
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/ConnectionSettingsPanel.java	(original)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/ConnectionSettingsPanel.java	Thu Apr  9 19:22:57 2015
@@ -15,8 +15,11 @@
 
 /**
  * Connection settings panel.
+ *
+ * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a>
  */
-class ConnectionSettingsPanel extends AbstractFieldsPanel {
+@SuppressWarnings("serial")
+final class ConnectionSettingsPanel extends AbstractFieldsPanel {
 
     /**
      * Updates the GUI from changes in the ConfigurationModel.
@@ -58,20 +61,69 @@
         }
     }
 
-    static final String[] waitModes = { Mode.SLEEP.name(), Mode.TIMED.name(), Mode.ASYNC.name() };
+    /**
+     * The available wait mode settings (sleep, timed and asynchronous).
+     */
+    private static final String[] WAIT_MODES = { Mode.SLEEP.name(), Mode.TIMED.name(), Mode.ASYNC.name() };
+
+    /**
+     * Check box for blocking setting.
+     */
     private final JCheckBox blockingCheckBox;
+
+    /**
+     * Field for chunk size.
+     */
     private final JTextField chunkSizeField;
+
+    /**
+     * Field for ET name (file).
+     */
     private final JTextField etNameField;
+
+    /**
+     * Field for host name.
+     */
     private final JTextField hostField;
+
+    /**
+     * Field for TCP/IP port.
+     */
     private final JTextField portField;
+
+    /**
+     * Field for prescale setting.
+     */
     private final JTextField prescaleField;
+
+    /**
+     * Field for queue size.
+     */
     private final JTextField queueSizeField;
+
+    /**
+     * Field for station name.
+     */
     private final JTextField stationNameField;
+
+    /**
+     * Field for station position.
+     */
     private final JTextField stationPositionField;
+
+    /**
+     * Check box for verbose flag.
+     */
     private final JCheckBox verboseCheckBox;
 
+    /**
+     * Check box for wait mode selection.
+     */
     private final JComboBox<?> waitModeComboBox;
 
+    /**
+     * Field for wait time.
+     */
     private final JTextField waitTimeField;
 
     /**
@@ -112,7 +164,7 @@
         this.stationPositionField = this.addField("Station Position", 3);
         this.stationPositionField.addPropertyChangeListener("value", this);
 
-        this.waitModeComboBox = this.addComboBox("Wait Mode", waitModes);
+        this.waitModeComboBox = this.addComboBox("Wait Mode", WAIT_MODES);
         this.waitModeComboBox.setActionCommand(Commands.WAIT_MODE_CHANGED);
         this.waitModeComboBox.addActionListener(this);
 
@@ -125,6 +177,8 @@
 
     /**
      * Used to update the ConfigurationModel from GUI components.
+     *
+     * @param e the <code>ActionEvent</code> to handle
      */
     @Override
     public void actionPerformed(final ActionEvent e) {
@@ -139,8 +193,8 @@
 
     /**
      * Enable or disable the connection panel GUI elements.
-     * 
-     * @param e Set to true for enabled; false to disable.
+     *
+     * @param e <code>true</code> to enable the components in the panel
      */
     void enableConnectionPanel(final boolean e) {
         this.etNameField.setEnabled(e);
@@ -192,6 +246,10 @@
         }
     }
 
+    /**
+     * Set configuration model (using <code>super</code> method) and add a property change listener for connection
+     * settings.
+     */
     @Override
     public void setConfigurationModel(final ConfigurationModel model) {
         super.setConfigurationModel(model);
@@ -199,4 +257,4 @@
         // This listener updates the GUI from changes in the configuration.
         this.getConfigurationModel().addPropertyChangeListener(new ConnectionSettingsChangeListener());
     }
-}
+}

Modified: java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/ConnectionStatusPanel.java
 =============================================================================
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/ConnectionStatusPanel.java	(original)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/ConnectionStatusPanel.java	Thu Apr  9 19:22:57 2015
@@ -11,59 +11,81 @@
 import javax.swing.JLabel;
 import javax.swing.JPanel;
 import javax.swing.JTextField;
+import javax.swing.SwingConstants;
 
 import org.hps.monitoring.application.model.ConnectionStatus;
 import org.hps.monitoring.application.model.ConnectionStatusModel;
 
 /**
- * This is the panel for showing the current connection status (connected, disconnected, etc.).
+ * This is the panel for showing the current connection status (connected, disconnected, etc.) in the tool bar.
+ *
+ * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a>
  */
-class ConnectionStatusPanel extends JPanel implements PropertyChangeListener {
+final class ConnectionStatusPanel extends JPanel implements PropertyChangeListener {
 
-    JTextField statusField;
-    JTextField dateField;
+    /**
+     * Date formatting.
+     */
+    private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("MMMM-dd-yyyy HH:mm:ss");
 
-    // Format for date field.
-    private final SimpleDateFormat dateFormat = new SimpleDateFormat("MMMM-dd-yyyy HH:mm:ss");
-    
-    ConnectionStatusModel model;
+    /**
+     * Field for date when status changed (read only).
+     */
+    private final JTextField dateField;
+
+    /**
+     * The model for getting connection status changes.
+     */
+    private final ConnectionStatusModel model;
+
+    /**
+     * The field showing the current connection status (read only).
+     */
+    private final JTextField statusField;
 
     /**
      * Class constructor.
+     *
+     * @param model the model which notifies this component of connection status changes
      */
-    ConnectionStatusPanel(ConnectionStatusModel model) {
-        
+    ConnectionStatusPanel(final ConnectionStatusModel model) {
+
         this.model = model;
         this.model.addPropertyChangeListener(this);
-        
+
         setLayout(new FlowLayout(FlowLayout.LEFT, 5, 0));
-                
-        statusField = new JTextField("", 10);
-        statusField.setHorizontalAlignment(JTextField.LEFT);
-        statusField.setEditable(false);
-        statusField.setBackground(Color.WHITE);
-        statusField.setFont(new Font("Arial", Font.BOLD, 16));
-        statusField.setForeground(model.getConnectionStatus().getColor());
-        statusField.setText(model.getConnectionStatus().name());
-        add(statusField);
-        
+
+        this.statusField = new JTextField("", 10);
+        this.statusField.setHorizontalAlignment(SwingConstants.LEFT);
+        this.statusField.setEditable(false);
+        this.statusField.setBackground(Color.WHITE);
+        this.statusField.setFont(new Font("Arial", Font.BOLD, 16));
+        this.statusField.setForeground(model.getConnectionStatus().getColor());
+        this.statusField.setText(model.getConnectionStatus().name());
+        add(this.statusField);
+
         add(new JLabel("@"));
-        
-        dateField = new JTextField("", 21);
-        dateField.setEditable(false);
-        dateField.setBackground(Color.WHITE);
-        dateField.setHorizontalAlignment(JTextField.LEFT);
-        dateField.setFont(new Font("Arial", Font.PLAIN, 14));
-        add(dateField);
+
+        this.dateField = new JTextField("", 21);
+        this.dateField.setEditable(false);
+        this.dateField.setBackground(Color.WHITE);
+        this.dateField.setHorizontalAlignment(SwingConstants.LEFT);
+        this.dateField.setFont(new Font("Arial", Font.PLAIN, 14));
+        add(this.dateField);
     }
 
+    /**
+     * Handle a property change event coming from the model.
+     *
+     * @param evt the property change event
+     */
     @Override
-    public void propertyChange(PropertyChangeEvent evt) {
+    public void propertyChange(final PropertyChangeEvent evt) {
         if (evt.getPropertyName().equals(ConnectionStatusModel.CONNECTION_STATUS_PROPERTY)) {
             final ConnectionStatus status = (ConnectionStatus) evt.getNewValue();
-            statusField.setForeground(status.getColor());
-            statusField.setText(status.name());
-            dateField.setText(dateFormat.format(new Date()));
-        }        
+            this.statusField.setForeground(status.getColor());
+            this.statusField.setText(status.name());
+            this.dateField.setText(ConnectionStatusPanel.DATE_FORMAT.format(new Date()));
+        }
     }
 }

Modified: java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/DataSourceComboBox.java
 =============================================================================
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/DataSourceComboBox.java	(original)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/DataSourceComboBox.java	Thu Apr  9 19:22:57 2015
@@ -21,28 +21,48 @@
 import org.hps.record.enums.DataSourceType;
 
 /**
- * This is a combo box that shows the current data source such as an LCIO file, EVIO file or ET ring.
- * It can also be used to select a new data source for the new session. 
+ * This is a combo box that shows the current data source such as an LCIO file, EVIO file or ET ring. It can also be
+ * used to select a data source for the next monitoring session.
  * <p>
- * The way this works is kind of odd because it is not directly connected to an event loop, so it must 
- * catch changes to the configuration and update its items accordingly.
+ * This component is not directly connected to an event loop, so it must catch changes to the configuration via property
+ * change events and then update its state accordingly.
  * <p>
- * A single ET item is kept in the list and updated as changes are made to the global configuration.
- * 
- * @author Jeremy McCormick <[log in to unmask]>
+ * Only a single "global" ET item is kept in the list, and it is updated as changes are made to the configuration model.
+ *
+ * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a>
  */
-class DataSourceComboBox extends JComboBox<DataSourceItem> implements PropertyChangeListener, ActionListener{
-
-    ConnectionStatusModel connectionModel;
-    ConfigurationModel configurationModel;
-
+@SuppressWarnings("serial")
+final class DataSourceComboBox extends JComboBox<DataSourceItem> implements PropertyChangeListener, ActionListener {
+
+    /**
+     * This class represents a data source item in the combo box, which has a name for display, a full path to the file,
+     * and an implicit type (EVIO, LCIO or ET).
+     */
     static class DataSourceItem {
 
+        /**
+         * The name of the data source which will show in the drop down box.
+         */
         private String name;
-        private String path;
-        private DataSourceType type;
-
-        DataSourceItem(String path, String name, DataSourceType type) {
+
+        /**
+         * The full path used for the data source (for ET this is not used directly).
+         */
+        private final String path;
+
+        /**
+         * The implicit data type (EVIO, LCIO and ET).
+         */
+        private final DataSourceType type;
+
+        /**
+         * Create a data source item.
+         *
+         * @param path the data source path
+         * @param name the data source name
+         * @param type the data source type
+         */
+        DataSourceItem(final String path, final String name, final DataSourceType type) {
             if (path == null) {
                 throw new IllegalArgumentException("path is null");
             }
@@ -57,48 +77,81 @@
             this.path = path;
         }
 
-        public String toString() {
-            return name;
-        }
-        
-        public String getPath() {
-            return path;
-        }
-        
-        public String getName() {
-            return name;
-        }
-
-        public boolean equals(Object object) {
+        /**
+         * Implementation of equals operation.
+         *
+         * @param object the other object
+         */
+        @Override
+        public boolean equals(final Object object) {
             if (!(object instanceof DataSourceItem)) {
                 return false;
             }
-            DataSourceItem otherItem = (DataSourceItem) object;
-            if (this.name == otherItem.name && this.path == otherItem.path && this.type == otherItem.type) {
-                return true;
-            } else {
-                return false;
-            }
-        }
-    }
-    
-    @SuppressWarnings({ "rawtypes", "serial", "unchecked" })
-    DataSourceComboBox(ConfigurationModel configurationModel, ConnectionStatusModel connectionModel) {
+            final DataSourceItem otherItem = (DataSourceItem) object;
+            return this.name == otherItem.name && this.path == otherItem.path && this.type == otherItem.type;
+        }
+
+        /**
+         * Get the name of the source that is used as text in the drop down menu.
+         *
+         * @return the name of the data source
+         */
+        public String getName() {
+            return this.name;
+        }
+
+        /**
+         * Get the full path to the data source which is used as tool tip text (not used directly for ET sources).
+         *
+         * @return the full path to the data source
+         */
+        public String getPath() {
+            return this.path;
+        }
+
+        /**
+         * Convert this object to a string.
+         *
+         * @return this object converted to a string
+         */
+        @Override
+        public String toString() {
+            return this.name;
+        }
+    }
+
+    /**
+     * The preferred width of this component in pixels.
+     */
+    private static final int PREFERRED_WIDTH = 510;
+
+    /**
+     * The backing configuration model.
+     */
+    private ConfigurationModel configurationModel;
+
+    /**
+     * Create a new data source combo box.
+     *
+     * @param configurationModel the underlying configuration data model
+     * @param connectionModel the underlying connection status data model
+     */
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+    DataSourceComboBox(final ConfigurationModel configurationModel, final ConnectionStatusModel connectionModel) {
         addActionListener(this);
         setActionCommand(Commands.DATA_SOURCE_CHANGED);
-        setPreferredSize(new Dimension(510, this.getPreferredSize().height));
+        setPreferredSize(new Dimension(PREFERRED_WIDTH, this.getPreferredSize().height));
         setEditable(false);
         this.configurationModel = configurationModel;
-        connectionModel.addPropertyChangeListener(this);                
+        connectionModel.addPropertyChangeListener(this);
         configurationModel.addPropertyChangeListener(this);
-        
-        ListCellRenderer renderer = new DefaultListCellRenderer() {
+
+        final ListCellRenderer renderer = new DefaultListCellRenderer() {
             @Override
-            public Component getListCellRendererComponent(JList<?> list,
-                    Object value, int index, boolean isSelected,
-                    boolean cellHasFocus) {
+            public Component getListCellRendererComponent(final JList<?> list, final Object value, final int index,
+                    final boolean isSelected, final boolean cellHasFocus) {
                 if (value instanceof DataSourceItem) {
-                    setToolTipText(((DataSourceItem)value).getPath());
+                    setToolTipText(((DataSourceItem) value).getPath());
                 } else {
                     setToolTipText(null);
                 }
@@ -108,48 +161,142 @@
         };
         this.setRenderer(renderer);
     }
-            
-    boolean containsItem(DataSourceItem item) {
+
+    /**
+     * Handle action events.
+     *
+     * @param evt the <code>ActionEvent</code> to handle
+     */
+    @Override
+    public void actionPerformed(final ActionEvent evt) {
+        if (evt.getActionCommand().equals(Commands.DATA_SOURCE_CHANGED)) {
+            try {
+                // Update the model with data source settings.
+                this.configurationModel.removePropertyChangeListener(this);
+                final DataSourceItem item = (DataSourceItem) getSelectedItem();
+                if (item != null) {
+                    this.configurationModel.setDataSourceType(item.type);
+                    if (item.type != DataSourceType.ET_SERVER) {
+                        this.configurationModel.setDataSourcePath(item.getPath());
+                    }
+                }
+            } finally {
+                this.configurationModel.addPropertyChangeListener(this);
+            }
+        }
+    }
+
+    /**
+     * Add a data source item with a specific type and path.
+     *
+     * @param path the data source path
+     * @param type the data source type
+     * @return the new data source item
+     */
+    DataSourceItem addDataSourceItem(final String path, final DataSourceType type) {
+        final DataSourceItem newItem = new DataSourceItem(path, new File(path).getName(), type);
+        addItem(newItem);
+        return newItem;
+    }
+
+    /**
+     * Add a data source item. Attempting to add an item that already exists will be ignored.
+     */
+    @Override
+    public void addItem(final DataSourceItem item) {
+        if (containsItem(item)) {
+            return;
+        }
+        if (findItem(item.getPath()) == null) {
+            super.addItem(item);
+        }
+    }
+
+    /**
+     * Return true if the (exact) given item exists in the combo box model.
+     *
+     * @param item the data source item
+     * @return <code>true</code> if data source item exists in the model
+     */
+    boolean containsItem(final DataSourceItem item) {
         return ((DefaultComboBoxModel<DataSourceItem>) getModel()).getIndexOf(item) != -1;
     }
 
+    /**
+     * Find the single data source item for the ET configuration in the items.
+     *
+     * @return the data source item for the ET configuration or <code>null</code> if does not exist
+     */
+    DataSourceItem findEtItem() {
+        for (int i = 0; i < this.getItemCount(); i++) {
+            final DataSourceItem item = this.getItemAt(i);
+            if (item.type == DataSourceType.ET_SERVER) {
+                return item;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Find an item by its path.
+     *
+     * @param path the path of the item
+     * @return the item or <code>null</code> if does not exist
+     */
+    DataSourceItem findItem(final String path) {
+        for (int i = 0; i < this.getItemCount(); i++) {
+            final DataSourceItem item = this.getItemAt(i);
+            if (item.getPath().equals(path)) {
+                return item;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Handle property change events which is used to update the GUI from changes to the global configuration model.
+     *
+     * @param evt the property change event
+     */
     @Override
-    public void propertyChange(PropertyChangeEvent evt) {
-        configurationModel.removePropertyChangeListener(this);
+    public void propertyChange(final PropertyChangeEvent evt) {
+        this.configurationModel.removePropertyChangeListener(this);
         try {
             if (evt.getPropertyName().equals(ConnectionStatusModel.CONNECTION_STATUS_PROPERTY)) {
-                ConnectionStatus status = (ConnectionStatus) evt.getNewValue();
+                final ConnectionStatus status = (ConnectionStatus) evt.getNewValue();
                 if (status.equals(ConnectionStatus.DISCONNECTED)) {
                     setEnabled(true);
                 } else {
                     setEnabled(false);
                 }
             } else if (evt.getPropertyName().equals(ConfigurationModel.DATA_SOURCE_PATH_PROPERTY)) {
-                if (configurationModel.hasValidProperty(ConfigurationModel.DATA_SOURCE_TYPE_PROPERTY)) {                    
-                    String path = configurationModel.getDataSourcePath();
-                    DataSourceType type = DataSourceType.getDataSourceType(path);
+                if (this.configurationModel.hasValidProperty(ConfigurationModel.DATA_SOURCE_TYPE_PROPERTY)) {
+                    final String path = this.configurationModel.getDataSourcePath();
+                    final DataSourceType type = DataSourceType.getDataSourceType(path);
                     if (type.isFile()) {
                         DataSourceItem item = findItem(path);
                         if (item == null) {
                             item = addDataSourceItem(path, type);
                         }
-                        if (configurationModel.getDataSourceType().isFile()) {
+                        if (this.configurationModel.getDataSourceType().isFile()) {
                             setSelectedItem(item);
                         }
                     }
                 }
             } else if (evt.getPropertyName().equals(ConfigurationModel.DATA_SOURCE_TYPE_PROPERTY)) {
-                if (configurationModel.getDataSourceType() == DataSourceType.ET_SERVER) {
+                if (this.configurationModel.getDataSourceType() == DataSourceType.ET_SERVER) {
                     DataSourceItem item = findEtItem();
                     if (item == null) {
-                        item = new DataSourceItem(configurationModel.getEtPath(), configurationModel.getEtPath(), DataSourceType.ET_SERVER);
+                        item = new DataSourceItem(this.configurationModel.getEtPath(),
+                                this.configurationModel.getEtPath(), DataSourceType.ET_SERVER);
                     }
                     setSelectedItem(item);
                 } else {
-                    if (configurationModel.hasValidProperty(ConfigurationModel.DATA_SOURCE_PATH_PROPERTY)) {
-                        DataSourceItem item = findItem(configurationModel.getDataSourcePath());
+                    if (this.configurationModel.hasValidProperty(ConfigurationModel.DATA_SOURCE_PATH_PROPERTY)) {
+                        DataSourceItem item = findItem(this.configurationModel.getDataSourcePath());
                         if (item == null) {
-                            item = addDataSourceItem(configurationModel.getDataSourcePath(), configurationModel.getDataSourceType());
+                            item = addDataSourceItem(this.configurationModel.getDataSourcePath(),
+                                    this.configurationModel.getDataSourceType());
                         }
                         setSelectedItem(item);
                     }
@@ -162,76 +309,33 @@
                 updateEtItem();
             }
         } finally {
-            configurationModel.addPropertyChangeListener(this);
-        }
-    }
-    
+            this.configurationModel.addPropertyChangeListener(this);
+        }
+    }
+
+    /**
+     * Set the currently selected item.
+     *
+     * @param object the currently selected item (should be an instance of this class)
+     */
     @Override
-    public void setSelectedItem(Object object) {
+    public void setSelectedItem(final Object object) {
         super.setSelectedItem(object);
-        this.setToolTipText(((DataSourceItem)object).getPath());
-    }
-
-    public void actionPerformed(ActionEvent evt) {
-        if (evt.getActionCommand().equals(Commands.DATA_SOURCE_CHANGED)) {
-            try {
-                // Update the model with data source settings.
-                configurationModel.removePropertyChangeListener(this);
-                DataSourceItem item = (DataSourceItem) getSelectedItem();
-                if (item != null) {
-                    configurationModel.setDataSourceType(item.type);
-                    if (item.type != DataSourceType.ET_SERVER) {
-                        configurationModel.setDataSourcePath(item.getPath());
-                    }
-                }
-            } finally {
-                configurationModel.addPropertyChangeListener(this);
-            }
-        } 
-    }
-       
-    public void addItem(DataSourceItem item) {
-        if (containsItem(item)) {
-            return;
-        }
-        if (findItem(item.getPath()) == null) {
-            super.addItem(item);
-        }
-    }
-
-    DataSourceItem findItem(String path) {
-        for (int i = 0; i < this.getItemCount(); i++) {
-            DataSourceItem item = this.getItemAt(i);
-            if (item.getPath().equals(path)) {
-                return item;
-            }
-        }
-        return null;
-    }
-    
-    DataSourceItem findEtItem() {
-        for (int i = 0; i < this.getItemCount(); i++) {
-            DataSourceItem item = this.getItemAt(i);
-            if (item.type == DataSourceType.ET_SERVER) {
-                return item;
-            }
-        }
-        return null;
-    }
-
-    DataSourceItem addDataSourceItem(String path, DataSourceType type) {
-        DataSourceItem newItem = new DataSourceItem(path, new File(path).getName(), type);
-        addItem(newItem);
-        return newItem;
-    }
-    
+        this.setToolTipText(((DataSourceItem) object).getPath());
+    }
+
+    /**
+     * Update the path value of the current ET item from the current global configuration. There is only one ET item
+     * present in the list at one time so property changes to ET configuration will trigger this method.
+     */
     void updateEtItem() {
         DataSourceItem item = findEtItem();
         if (item == null) {
-            item = new DataSourceItem(configurationModel.getEtPath(), configurationModel.getEtPath(), DataSourceType.ET_SERVER);
+            item = new DataSourceItem(this.configurationModel.getEtPath(), this.configurationModel.getEtPath(),
+                    DataSourceType.ET_SERVER);
             addItem(item);
         } else {
-            item.name = configurationModel.getEtPath();
-        }
-    }
-}
+            item.name = this.configurationModel.getEtPath();
+        }
+    }
+}

Modified: java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/DatePanel.java
 =============================================================================
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/DatePanel.java	(original)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/DatePanel.java	Thu Apr  9 19:22:57 2015
@@ -6,32 +6,71 @@
 
 /**
  * A small JPanel with a date field and a label on its border.
+ *
+ * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a>
  */
-class DatePanel extends FieldPanel {
+@SuppressWarnings("serial")
+final class DatePanel extends FieldPanel {
 
+    /**
+     * Default date formatting.
+     */
     private SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
 
-    DatePanel(String fieldName, String defaultValue, int size, boolean editable) {
+    /**
+     * Create a date panel.
+     *
+     * @param fieldName the field name for the label
+     * @param defaultValue the default value
+     * @param format the date formatter
+     * @param size the size of the field
+     * @param editable <code>true</code> to enable editing
+     */
+    DatePanel(final String fieldName, final Date defaultValue, final SimpleDateFormat format, final int size,
+            final boolean editable) {
+        super(fieldName, format.format(defaultValue), size, editable);
+    }
+
+    /**
+     * Create a date panel with default date formatting.
+     *
+     * @param fieldName the field name for the label
+     * @param defaultValue the default value
+     * @param size the size of the field
+     * @param editable <code>true</code> to enable editing
+     */
+    DatePanel(final String fieldName, final String defaultValue, final int size, final boolean editable) {
         super(fieldName, defaultValue, size, editable);
     }
 
-    DatePanel(String fieldName, Date defaultValue, SimpleDateFormat format, int size, boolean editable) {
-        super(fieldName, format.format(defaultValue), size, editable);
+    /**
+     * Get the value of the field.
+     *
+     * @return the <code>Date</code> object
+     */
+    Date getDateValue() {
+        try {
+            return this.dateFormat.parse(getValue());
+        } catch (final ParseException e) {
+            throw new RuntimeException(e);
+        }
     }
 
-    void setDateFormat(SimpleDateFormat dateFormat) {
+    /**
+     * Set the date formatter.
+     *
+     * @param dateFormat the date formatter
+     */
+    void setDateFormat(final SimpleDateFormat dateFormat) {
         this.dateFormat = dateFormat;
     }
 
-    void setValue(Date date) {
-        setValue(dateFormat.format(date));
-    }
-
-    Date getDateValue() {
-        try {
-            return dateFormat.parse(getValue());
-        } catch (ParseException e) {
-            throw new RuntimeException(e);
-        }
+    /**
+     * Set the value of the field.
+     *
+     * @param date the <code>Date</code> object
+     */
+    void setValue(final Date date) {
+        setValue(this.dateFormat.format(date));
     }
 }

Modified: java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/EventButtonsPanel.java
 =============================================================================
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/EventButtonsPanel.java	(original)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/EventButtonsPanel.java	Thu Apr  9 19:22:57 2015
@@ -16,32 +16,94 @@
 import org.hps.monitoring.application.model.ConnectionStatusModel;
 
 /**
- * This is the panel with buttons for connecting or disconnecting from the session
- * and controlling the application from pause mode.
+ * This is the panel with buttons for connecting or disconnecting from the session and controlling the application when
+ * event processing is paused.
+ *
+ * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a>
  */
-class EventButtonsPanel extends JPanel implements PropertyChangeListener {
+@SuppressWarnings("serial")
+final class EventButtonsPanel extends JPanel implements PropertyChangeListener {
 
-    JButton nextButton;
-    JButton pauseButton;
-    JButton connectButton;
-    JButton resumeButton;
-    
-    static final ImageIcon connectedIcon = getImageIcon("/monitoringButtonGraphics/connected-128.png");
-    static final ImageIcon disconnectedIcon = getImageIcon("/monitoringButtonGraphics/disconnected-128.png");
-    
-    EventButtonsPanel(ConnectionStatusModel connectionModel, ActionListener listener) {
-        
+    /**
+     * Icon when application is connected to event processing session.
+     */
+    static final ImageIcon CONNECTED_ICON = getImageIcon("/monitoringButtonGraphics/connected-128.png");
+
+    /**
+     * Icon when application is disconnected from event processing.
+     */
+    static final ImageIcon DISCONNECTED_ICON = getImageIcon("/monitoringButtonGraphics/disconnected-128.png");
+
+    /**
+     * The icon size (width and height) in pixels.
+     */
+    private static final int ICON_SIZE = 24;
+
+    /**
+     * Get an image icon from a jar resource.
+     *
+     * @param resource the resource path
+     * @return the image icon
+     */
+    static ImageIcon getImageIcon(final String resource) {
+        Image image = null;
+        try {
+            image = ImageIO.read(EventButtonsPanel.class.getResource(resource));
+            image = image.getScaledInstance(ICON_SIZE, ICON_SIZE, 0);
+        } catch (final IOException e) {
+        }
+        return new ImageIcon(image);
+    }
+
+    /**
+     * Button for connect and disconnect which is toggled depending on state.
+     */
+    private final JButton connectButton;
+
+    /**
+     * Button for getting next event when paused.
+     */
+    private final JButton nextButton;
+
+    /**
+     * Button for pausing the event processing.
+     */
+    private final JButton pauseButton;
+
+    /**
+     * Button for resuming the event processing.
+     */
+    private final JButton resumeButton;
+
+    /**
+     * Class constructor.
+     *
+     * @param connectionModel the global connection model
+     * @param listener the action listener
+     */
+    EventButtonsPanel(final ConnectionStatusModel connectionModel, final ActionListener listener) {
+
         connectionModel.addPropertyChangeListener(this);
-        
+
         setLayout(new FlowLayout());
-        connectButton = addButton(disconnectedIcon, Commands.CONNECT, listener, true);
-        resumeButton = addButton("/toolbarButtonGraphics/media/Play24.gif", Commands.RESUME, listener, false);
-        pauseButton = addButton("/toolbarButtonGraphics/media/Pause24.gif", Commands.PAUSE, listener, false);
-        nextButton = addButton("/toolbarButtonGraphics/media/StepForward24.gif", Commands.NEXT, listener, false);
+        this.connectButton = addButton(DISCONNECTED_ICON, Commands.CONNECT, listener, true);
+        this.resumeButton = addButton("/toolbarButtonGraphics/media/Play24.gif", Commands.RESUME, listener, false);
+        this.pauseButton = addButton("/toolbarButtonGraphics/media/Pause24.gif", Commands.PAUSE, listener, false);
+        this.nextButton = addButton("/toolbarButtonGraphics/media/StepForward24.gif", Commands.NEXT, listener, false);
     }
-           
-    final JButton addButton(ImageIcon icon, String command, ActionListener listener, boolean enabled) {
-        JButton button = new JButton();
+
+    /**
+     * Add a button to the panel.
+     *
+     * @param icon the button's image icon
+     * @param command the command for the action event
+     * @param listener the action listener which handles action events
+     * @param enabled <code>true</code> if button should be enabled initially
+     * @return the new button object
+     */
+    private JButton addButton(final ImageIcon icon, final String command, final ActionListener listener,
+            final boolean enabled) {
+        final JButton button = new JButton();
         button.setIcon(icon);
         button.setEnabled(enabled);
         button.addActionListener(listener);
@@ -49,21 +111,24 @@
         this.add(button);
         return button;
     }
-    
-    final JButton addButton(String resource, String actionCommand, ActionListener listener, boolean enabled) {
+
+    /**
+     * Add a button to the panel.
+     *
+     * @param resource the resource for the image icon
+     * @param command the command for the action event
+     * @param listener the action listener which handles action events
+     * @param enabled <code>true</code> if button should be enabled initially
+     * @return the new button object
+     */
+    private JButton addButton(final String resource, final String actionCommand, final ActionListener listener,
+            final boolean enabled) {
         return addButton(getImageIcon(resource), actionCommand, listener, enabled);
     }
-        
-    static ImageIcon getImageIcon(String resource) {
-        Image image = null;
-        try {
-            image = ImageIO.read(EventButtonsPanel.class.getResource(resource));
-            image = image.getScaledInstance(24, 24, 0);
-        } catch (IOException e) {            
-        }
-        return new ImageIcon(image);
-    }
 
+    /**
+     * Handle property change events to set status from changes to the connection status model.
+     */
     @Override
     public void propertyChange(final PropertyChangeEvent evt) {
         if (evt.getPropertyName().equals(ConnectionStatusModel.CONNECTION_STATUS_PROPERTY)) {
@@ -72,35 +137,45 @@
             setPaused((boolean) evt.getNewValue());
         }
     }
-    
-    void setConnectionStatus(final ConnectionStatus status) {
+
+    /**
+     * Set the connection status to update the button state.
+     *
+     * @param status the new connection status
+     */
+    private void setConnectionStatus(final ConnectionStatus status) {
         if (status.equals(ConnectionStatus.DISCONNECTED)) {
-            nextButton.setEnabled(false);
-            pauseButton.setEnabled(false);
-            resumeButton.setEnabled(false);
-            connectButton.setActionCommand(Commands.CONNECT);
-            connectButton.setIcon(disconnectedIcon);
-            connectButton.setToolTipText("Start new session");
-            connectButton.setEnabled(true);
+            this.nextButton.setEnabled(false);
+            this.pauseButton.setEnabled(false);
+            this.resumeButton.setEnabled(false);
+            this.connectButton.setActionCommand(Commands.CONNECT);
+            this.connectButton.setIcon(DISCONNECTED_ICON);
+            this.connectButton.setToolTipText("Start new session");
+            this.connectButton.setEnabled(true);
         } else if (status.equals(ConnectionStatus.DISCONNECTING)) {
-            nextButton.setEnabled(false);
-            pauseButton.setEnabled(false);
-            resumeButton.setEnabled(false);
-            connectButton.setEnabled(false);
+            this.nextButton.setEnabled(false);
+            this.pauseButton.setEnabled(false);
+            this.resumeButton.setEnabled(false);
+            this.connectButton.setEnabled(false);
         } else if (status.equals(ConnectionStatus.CONNECTED)) {
-            nextButton.setEnabled(false);            
-            pauseButton.setEnabled(true);
-            resumeButton.setEnabled(false);
-            connectButton.setActionCommand(Commands.DISCONNECT);
-            connectButton.setIcon(connectedIcon);
-            connectButton.setToolTipText("Disconnect from session");
-            connectButton.setEnabled(true);
+            this.nextButton.setEnabled(false);
+            this.pauseButton.setEnabled(true);
+            this.resumeButton.setEnabled(false);
+            this.connectButton.setActionCommand(Commands.DISCONNECT);
+            this.connectButton.setIcon(CONNECTED_ICON);
+            this.connectButton.setToolTipText("Disconnect from session");
+            this.connectButton.setEnabled(true);
         }
-    }       
-    
-    void setPaused(final boolean paused) {
-        resumeButton.setEnabled(paused);
-        pauseButton.setEnabled(!paused);
-        nextButton.setEnabled(paused);
     }
-}
+
+    /**
+     * Set pause mode.
+     *
+     * @param paused <code>true</code> to set paused state
+     */
+    private void setPaused(final boolean paused) {
+        this.resumeButton.setEnabled(paused);
+        this.pauseButton.setEnabled(!paused);
+        this.nextButton.setEnabled(paused);
+    }
+}

Modified: java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/EventDashboard.java
 =============================================================================
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/EventDashboard.java	(original)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/EventDashboard.java	Thu Apr  9 19:22:57 2015
@@ -20,248 +20,400 @@
 import org.lcsim.event.EventHeader;
 
 /**
- * Dashboard for displaying information about the current run.
- * @author Jeremy McCormick <[log in to unmask]>
+ * This class implements a "dashboard" for displaying information about the current run.
+ *
+ * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a>
  */
-class EventDashboard extends JPanel implements PropertyChangeListener {
-
-    FieldPanel runNumberField = new FieldPanel("Run Number", "", 10, false);
-    DatePanel startDateField = new DatePanel("Run Start", "", 14, false);
-    DatePanel endDateField = new DatePanel("Run End", "", 14, false);
-    FieldPanel lengthField = new FieldPanel("Run Length [sec]", "", 12, false);
-    FieldPanel totalEventsField = new FieldPanel("Total Events in Run", "", 14, false);
-    FieldPanel elapsedTimeField = new FieldPanel("Elapsed Time [sec]", "", 14, false);
-    FieldPanel eventsReceivedField = new FieldPanel("Events Received", "", 14, false);
-    FieldPanel dataReceivedField = new FieldPanel("Data Received [MB]", "", 14, false);
-    FieldPanel eventNumberField = new FieldPanel("Event Number", "", 14, false);
-    FieldPanel dataRateField = new FieldPanel("Data Rate [MB/s]", "", 12, false);
-    FieldPanel eventRateField = new FieldPanel("Event Rate [Hz]", "", 14, false);
-
-    RunModel runModel;
-    
-    static final NumberFormat formatter = new DecimalFormat("#0.0000"); 
-
-    public EventDashboard() {
-        build();
-    }
-    
-    public EventDashboard(RunModel runModel) {
-        this.runModel = runModel;
-        this.runModel.addPropertyChangeListener(this);
-        build();
-    }
-    
-    private void build() {
-        
-        setLayout(new FlowLayout(FlowLayout.LEADING));
-
-        add(runNumberField);
-        add(startDateField);
-        add(endDateField);
-        add(lengthField);
-        add(totalEventsField);
-        
-        add(elapsedTimeField);
-        add(eventsReceivedField);
-        add(dataReceivedField);
-        add(eventNumberField);
-        add(dataRateField);
-        add(eventRateField);
-    }
-    
-    public void setModel(RunModel runModel) {
-        this.runModel = runModel;
-    }
-
+@SuppressWarnings("serial")
+final class EventDashboard extends JPanel implements PropertyChangeListener {
+
+    /**
+     * Updates the fields as events are processed.
+     */
     class EventDashboardUpdater extends CompositeRecordProcessor {
 
-        Timer timer;
-        
-        int eventsReceived;
-        double bytesReceived;
-        int totalEvents;
-        int eventNumber;
-        int runNumber = -1;
-        long jobStartMillis;
-        long lastTickMillis = 0;
-        static final long millis = 1000;
-        
+        /**
+         * Task to periodically update the fields as events are processed.
+         */
         class RunTimerTask extends TimerTask {
-            
-            public void run() {                     
-                                
-                double tickLengthSeconds = (System.currentTimeMillis() - lastTickMillis) / (double)millis;
-                int elapsedTime = (int) ((System.currentTimeMillis() - jobStartMillis) / (double)millis);
-                double megaBytesReceived = bytesReceived / 1000000;
-                totalEvents += eventsReceived;
-
-                /*
-                System.out.println("tickLengthSeconds = " + tickLengthSeconds);
-                System.out.println("elapsedTime = " + elapsedTime);
-                System.out.println("eventsReceived = " + eventsReceived);
-                System.out.println("dataRate = " + (megaBytesReceived / tickLengthSeconds));
-                System.out.println("eventNumber = " + eventNumber);
-                System.out.println("eventRate = " + (eventsReceived / tickLengthSeconds));
-                System.out.println("totalEvents = " + totalEvents);
-                System.out.println("megaBytesReceived = " + megaBytesReceived);
-                */
-                
-                runModel.setElapsedTime(elapsedTime);
-                runModel.setEventsReceived(totalEvents);
-                runModel.setDataRate(megaBytesReceived / tickLengthSeconds);
-                runModel.addDataReceived(megaBytesReceived);
-                runModel.setEventNumber(eventNumber);
-                runModel.setEventRate(eventsReceived / tickLengthSeconds);
-                
-                eventsReceived = 0;
-                bytesReceived = 0;
-                eventNumber = 0;  
-                
-                lastTickMillis = System.currentTimeMillis();
-                
+
+            @Override
+            public void run() {
+
+                final double tickLengthSeconds = (System.currentTimeMillis() - EventDashboardUpdater.this.lastTickMillis)
+                        / (double) MILLIS;
+                final int elapsedTime = (int) ((System.currentTimeMillis() - EventDashboardUpdater.this.jobStartMillis) / (double) MILLIS);
+                final double megaBytesReceived = EventDashboardUpdater.this.bytesReceived / 1000000;
+                EventDashboardUpdater.this.totalEvents += EventDashboardUpdater.this.eventsReceived;
+
+                // Print to System.out if debugging the processor (by default this is off).
+                if (DEBUG) {
+                    System.out.println("tickLengthSeconds = " + tickLengthSeconds);
+                    System.out.println("elapsedTime = " + elapsedTime);
+                    System.out.println("eventsReceived = " + EventDashboardUpdater.this.eventsReceived);
+                    System.out.println("dataRate = " + megaBytesReceived / tickLengthSeconds);
+                    System.out.println("eventNumber = " + EventDashboardUpdater.this.eventNumber);
+                    System.out.println("eventRate = " + EventDashboardUpdater.this.eventsReceived / tickLengthSeconds);
+                    System.out.println("totalEvents = " + EventDashboardUpdater.this.totalEvents);
+                    System.out.println("megaBytesReceived = " + megaBytesReceived);
+
+                }
+
+                EventDashboard.this.runModel.setElapsedTime(elapsedTime);
+                EventDashboard.this.runModel.setEventsReceived(EventDashboardUpdater.this.totalEvents);
+                EventDashboard.this.runModel.setDataRate(megaBytesReceived / tickLengthSeconds);
+                EventDashboard.this.runModel.addDataReceived(megaBytesReceived);
+                EventDashboard.this.runModel.setEventNumber(EventDashboardUpdater.this.eventNumber);
+                EventDashboard.this.runModel
+                        .setEventRate(EventDashboardUpdater.this.eventsReceived / tickLengthSeconds);
+
+                EventDashboardUpdater.this.eventsReceived = 0;
+                EventDashboardUpdater.this.bytesReceived = 0;
+                EventDashboardUpdater.this.eventNumber = 0;
+
+                EventDashboardUpdater.this.lastTickMillis = System.currentTimeMillis();
+
                 // System.out.println();
-            }        
-        }
-        
+            }
+        }
+
+        /**
+         * Set to <code>true</code> to enable debugging.
+         */
+        private static final boolean DEBUG = false;
+
+        /**
+         * Helper for second to milliseconds conversion.
+         */
+        private static final long MILLIS = 1000;
+
+        /**
+         * Helper for second to nanoseconds conversion.
+         */
+        private static final int NANOS = 1000000000;
+
+        /**
+         * The number of bytes received.
+         */
+        private double bytesReceived;
+
+        /**
+         * The current event number.
+         */
+        private int eventNumber;
+
+        /**
+         * The number of events received.
+         */
+        private int eventsReceived;
+
+        /**
+         * The system time in milliseconds when the job started.
+         */
+        private long jobStartMillis;
+
+        /**
+         * The system time in milliseconds when the last timer tick occurred.
+         */
+        private long lastTickMillis = 0;
+
+        /**
+         * The current run number.
+         */
+        private int runNumber = -1;
+
+        /**
+         * The timer for running the update task.
+         */
+        private Timer timer;
+
+        /**
+         * The total number of events received.
+         */
+        private int totalEvents;
+
+        /**
+         * Check for head bank and update the run info if necessary.
+         *
+         * @param evioEvent the EVIO event
+         */
+        private void checkHeadBank(final EvioEvent evioEvent) {
+            final BaseStructure headBank = EvioEventUtilities.getHeadBank(evioEvent);
+            if (headBank != null) {
+                final int headBankRun = headBank.getIntData()[1];
+                if (headBankRun != this.runNumber) {
+                    this.runNumber = headBankRun;
+                    EventDashboard.this.runModel.setRunNumber(headBankRun);
+                    EventDashboard.this.runModel.setStartDate(new Date(headBank.getIntData()[3] * MILLIS));
+                }
+            }
+        }
+
+        /**
+         * Perform end of job hook, which will cancel the update timer.
+         */
         @Override
-        public void startJob() {
-            runModel.reset();
-            jobStartMillis = System.currentTimeMillis();
-            
-            // Start the timer to update GUI components about once per second.
-            timer = new Timer("RunModelUpdaterTimer");
-            lastTickMillis = System.currentTimeMillis();
-            timer.scheduleAtFixedRate(new RunTimerTask(), 0, 1000);
-        }
-
+        public void endJob() {
+            this.timer.cancel();
+
+            // Push final values into GUI.
+            this.timer = new Timer("RunModelUpdaterEndJobTimer");
+            this.timer.schedule(new RunTimerTask(), 0);
+        }
+
+        /**
+         * Handle an EVIO END event.
+         *
+         * @param evioEvent the EVIO END event
+         */
+        private void endRun(final EvioEvent evioEvent) {
+            // Get end run data.
+            final int[] data = EvioEventUtilities.getControlEventData(evioEvent);
+            if (data != null) {
+                final int seconds = data[0];
+                final int eventCount = data[2];
+                final long endMillis = (long) seconds * 1000;
+
+                // Update the GUI.
+                EventDashboard.this.runModel.setEndDate(new Date(endMillis));
+                EventDashboard.this.runModel.computeRunLength();
+                EventDashboard.this.runModel.setTotalEvents(eventCount);
+            }
+        }
+
+        /**
+         * Process a {@link org.hps.record.composite.CompositeRecord} to extract information from available event
+         * sources and update the running values.
+         */
         @Override
-        public void process(CompositeRecord event) {          
+        public void process(final CompositeRecord event) {
             // FIXME: CompositeRecord number is always -1 here.
             if (event.getEvioEvent() != null) {
-                EvioEvent evioEvent = event.getEvioEvent();
-                bytesReceived += evioEvent.getTotalBytes();
+                final EvioEvent evioEvent = event.getEvioEvent();
+                this.bytesReceived += evioEvent.getTotalBytes();
                 if (EvioEventUtilities.isPreStartEvent(evioEvent)) {
                     // Get run start info from pre start event.
                     startRun(evioEvent);
                 } else if (EvioEventUtilities.isEndEvent(evioEvent)) {
                     // Get end run info from end event.
                     endRun(evioEvent);
-                } else if (EvioEventUtilities.isPhysicsEvent(evioEvent)) {                    
+                } else if (EvioEventUtilities.isPhysicsEvent(evioEvent)) {
                     // Check for run info in head bank.
                     checkHeadBank(evioEvent);
-                    eventNumber = evioEvent.getEventNumber();
-                    eventsReceived += 1;
+                    this.eventNumber = evioEvent.getEventNumber();
+                    this.eventsReceived += 1;
                 }
             } else if (event.getEtEvent() != null) {
-                bytesReceived += event.getEtEvent().getData().length;
-                eventNumber = event.getEtEvent().getId();
-                eventsReceived += 1;
+                this.bytesReceived += event.getEtEvent().getData().length;
+                this.eventNumber = event.getEtEvent().getId();
+                this.eventsReceived += 1;
             } else if (event.getLcioEvent() != null) {
-                EventHeader lcioEvent = event.getLcioEvent();
-                eventNumber = lcioEvent.getEventNumber();
-                if (lcioEvent.getRunNumber() != runNumber) {
-                    runNumber = lcioEvent.getRunNumber();
+                final EventHeader lcioEvent = event.getLcioEvent();
+                this.eventNumber = lcioEvent.getEventNumber();
+                if (lcioEvent.getRunNumber() != this.runNumber) {
+                    this.runNumber = lcioEvent.getRunNumber();
                     startRun(lcioEvent);
                 }
-                eventsReceived += 1;
-            }                    
-        }
-
-        /**
-         * Check for head bank and update the run info if necessary.
-         * @param evioEvent The EVIO event.
-         */
-        private void checkHeadBank(EvioEvent evioEvent) {
-            BaseStructure headBank = EvioEventUtilities.getHeadBank(evioEvent);
-            if (headBank != null) {
-                int headBankRun = headBank.getIntData()[1];
-                if (headBankRun != runNumber) {
-                    runNumber = headBankRun;
-                    runModel.setRunNumber(headBankRun);
-                    runModel.setStartDate(new Date(headBank.getIntData()[3] * 1000));
-                }
-            }
-        }
-
-        private void endRun(EvioEvent evioEvent) {
-            // Get end run data.
-            int[] data = EvioEventUtilities.getControlEventData(evioEvent);
+                this.eventsReceived += 1;
+            }
+        }
+
+        /**
+         * Perform start of job hook which initializes this processor.
+         */
+        @Override
+        public void startJob() {
+            EventDashboard.this.runModel.reset();
+            this.jobStartMillis = System.currentTimeMillis();
+
+            // Start the timer to update GUI components about once per second.
+            this.timer = new Timer("RunModelUpdaterTimer");
+            this.lastTickMillis = System.currentTimeMillis();
+            this.timer.scheduleAtFixedRate(new RunTimerTask(), 0, MILLIS);
+        }
+
+        /**
+         * Handle start of run using an LCIO event.
+         *
+         * @param lcioEvent the LCIO event
+         */
+        private void startRun(final EventHeader lcioEvent) {
+            EventDashboard.this.runModel.setRunNumber(lcioEvent.getRunNumber());
+            final long seconds = lcioEvent.getTimeStamp() / NANOS;
+            EventDashboard.this.runModel.setStartDate(new Date((int) seconds));
+        }
+
+        /**
+         * Handle start of run using an EVIO START event.
+         *
+         * @param evioEvent the EVIO START event
+         */
+        private void startRun(final EvioEvent evioEvent) {
+            // Get start of run data.
+            final int[] data = EvioEventUtilities.getControlEventData(evioEvent);
             if (data != null) {
-                int seconds = data[0];
-                int eventCount = data[2];
-                long endMillis = ((long) seconds) * 1000;
+                final int seconds = data[0];
+                this.runNumber = data[1];
 
                 // Update the GUI.
-                runModel.setEndDate(new Date(endMillis));
-                runModel.computeRunLength();
-                runModel.setTotalEvents(eventCount);
-            }
-        }
-
-        private void startRun(EvioEvent evioEvent) {
-            // Get start of run data.
-            int[] data = EvioEventUtilities.getControlEventData(evioEvent);
-            if (data != null) {
-                int seconds = data[0];
-                runNumber = data[1];
-                
-                // Update the GUI.
-                runModel.setRunNumber(runNumber);
-                runModel.setStartDate(new Date(seconds * 1000));
-            }
-        }
-        
-        private void startRun(EventHeader lcioEvent) {
-            runModel.setRunNumber(lcioEvent.getRunNumber());
-            long seconds = lcioEvent.getTimeStamp() / 1000000000;
-            runModel.setStartDate(new Date((int)seconds));
-        }
-        
-        @Override
-        public void endJob() {
-            timer.cancel();
-            
-            // Push final values into GUI.
-            timer = new Timer("RunModelUpdaterEndJobTimer");
-            timer.schedule(new RunTimerTask(), 0);
-        }
-    }
-    
-    /**
-     * Update the GUI from changes to the backing RunModel object.
+                EventDashboard.this.runModel.setRunNumber(this.runNumber);
+                EventDashboard.this.runModel.setStartDate(new Date(seconds * MILLIS));
+            }
+        }
+    }
+
+    /**
+     * The decimal format (shows decimal numbers to 4 places).
+     */
+    static final NumberFormat DECIMAL_FORMAT = new DecimalFormat("#0.0000");
+
+    /**
+     * Field for showing the data rate in MB per second.
+     */
+    FieldPanel dataRateField = new FieldPanel("Data Rate [MB/s]", "", 12, false);
+
+    /**
+     * Field for showing the total data received in MB.
+     */
+    FieldPanel dataReceivedField = new FieldPanel("Data Received [MB]", "", 14, false);
+
+    /**
+     * Field for showing the elapsed job time in seconds.
+     */
+    FieldPanel elapsedTimeField = new FieldPanel("Elapsed Time [sec]", "", 14, false);
+
+    /**
+     * Field for showing the end date.
+     */
+    DatePanel endDateField = new DatePanel("Run End", "", 14, false);
+
+    /**
+     * Field for showing the current event number.
+     */
+    FieldPanel eventNumberField = new FieldPanel("Event Number", "", 14, false);
+
+    /**
+     * Field showing the event rate in Hertz.
+     */
+    FieldPanel eventRateField = new FieldPanel("Event Rate [Hz]", "", 14, false);
+
+    /**
+     * Field for showing the total number of events received.
+     */
+    FieldPanel eventsReceivedField = new FieldPanel("Events Received", "", 14, false);
+
+    /**
+     * Field for showing the length of the run in seconds.
+     */
+    FieldPanel lengthField = new FieldPanel("Run Length [sec]", "", 12, false);
+
+    /**
+     * The backing model with run and event information.
+     */
+    RunModel runModel;
+
+    /**
+     * Field for showing the run number.
+     */
+    FieldPanel runNumberField = new FieldPanel("Run Number", "", 10, false);
+
+    /**
+     * Field for showing the start date.
+     */
+    DatePanel startDateField = new DatePanel("Run Start", "", 14, false);
+
+    /**
+     * Field for showing the total events in the run.
+     */
+    FieldPanel totalEventsField = new FieldPanel("Total Events in Run", "", 14, false);
+
+    /**
+     * Class constructor which will build the GUI components.
+     */
+    public EventDashboard() {
+        build();
+    }
+
+    /**
+     * Class constructor which takes reference to backing model.
+     *
+     * @param runModel the backing {@link org.hps.monitoring.application.model.RunModel} with event and run information
+     */
+    public EventDashboard(final RunModel runModel) {
+        this.runModel = runModel;
+        this.runModel.addPropertyChangeListener(this);
+        build();
+    }
+
+    /**
+     * Build the GUI components.
+     */
+    private void build() {
+
+        setLayout(new FlowLayout(FlowLayout.LEADING));
+
+        add(this.runNumberField);
+        add(this.startDateField);
+        add(this.endDateField);
+        add(this.lengthField);
+        add(this.totalEventsField);
+
+        add(this.elapsedTimeField);
+        add(this.eventsReceivedField);
+        add(this.dataReceivedField);
+        add(this.eventNumberField);
+        add(this.dataRateField);
+        add(this.eventRateField);
+    }
+
+    /**
+     * Update the GUI from changes to the backing {@link org.hps.monitoring.application.model.RunModel} object.
+     *
+     * @param evt the {@link java.beans.PropertyChangeEvent} to handle
      */
     @Override
-    public void propertyChange(PropertyChangeEvent evt) {
-        //System.out.println("RunPanel.propertyChange - " + evt.getPropertyName());
-        Object value = evt.getNewValue();
+    public void propertyChange(final PropertyChangeEvent evt) {
+        // System.out.println("RunPanel.propertyChange - " + evt.getPropertyName());
+        final Object value = evt.getNewValue();
         if (RunModel.RUN_NUMBER_PROPERTY.equals(evt.getPropertyName())) {
-            runNumberField.setValue((Integer) value);
+            this.runNumberField.setValue((Integer) value);
         } else if (RunModel.START_DATE_PROPERTY.equals(evt.getPropertyName())) {
-            if (value != null)
-                startDateField.setValue((Date) value);
-            else
-                startDateField.setValue("");
+            if (value != null) {
+                this.startDateField.setValue((Date) value);
+            } else {
+                this.startDateField.setValue("");
+            }
         } else if (RunModel.END_DATE_PROPERTY.equals(evt.getPropertyName())) {
-            if (value != null)
-                endDateField.setValue((Date) value);
-            else
-                endDateField.setValue("");
+            if (value != null) {
+                this.endDateField.setValue((Date) value);
+            } else {
+                this.endDateField.setValue("");
+            }
         } else if (RunModel.RUN_LENGTH_PROPERTY.equals(evt.getPropertyName())) {
-            lengthField.setValue((Integer) value);
+            this.lengthField.setValue((Integer) value);
         } else if (RunModel.TOTAL_EVENTS_PROPERTY.equals(evt.getPropertyName())) {
-            totalEventsField.setValue((Integer) value);
+            this.totalEventsField.setValue((Integer) value);
         } else if (RunModel.EVENTS_RECEIVED_PROPERTY.equals(evt.getPropertyName())) {
-            eventsReceivedField.setValue((Integer) value);
+            this.eventsReceivedField.setValue((Integer) value);
         } else if (RunModel.ELAPSED_TIME_PROPERTY.equals(evt.getPropertyName())) {
-            elapsedTimeField.setValue((Integer) value);
+            this.elapsedTimeField.setValue((Integer) value);
         } else if (RunModel.DATA_RECEIVED_PROPERTY.equals(evt.getPropertyName())) {
-            dataReceivedField.setValue(formatter.format((Double) value));
+            this.dataReceivedField.setValue(DECIMAL_FORMAT.format(value));
         } else if (RunModel.EVENT_NUMBER_PROPERTY.equals(evt.getPropertyName())) {
-            eventNumberField.setValue((Integer) value);
+            this.eventNumberField.setValue((Integer) value);
         } else if (RunModel.DATA_RATE_PROPERTY.equals(evt.getPropertyName())) {
-            dataRateField.setValue(formatter.format((Double) value));
+            this.dataRateField.setValue(DECIMAL_FORMAT.format(value));
         } else if (RunModel.EVENT_RATE_PROPERTY.equals(evt.getPropertyName())) {
-            eventRateField.setValue(formatter.format((Double) value));
-        }
-    }
-}
+            this.eventRateField.setValue(DECIMAL_FORMAT.format(value));
+        }
+    }
+
+    /**
+     * Set the backing {@link org.hps.monitoring.application.model.RunModel} of the component.
+     *
+     * @param runModel the backing {@link org.hps.monitoring.application.model.RunModel} of the component
+     */
+    public void setModel(final RunModel runModel) {
+        this.runModel = runModel;
+    }
+}

Modified: java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/EventProcessing.java
 =============================================================================
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/EventProcessing.java	(original)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/EventProcessing.java	Thu Apr  9 19:22:57 2015
@@ -18,7 +18,6 @@
 import org.hps.monitoring.application.model.SteeringType;
 import org.hps.monitoring.application.util.ErrorHandler;
 import org.hps.monitoring.application.util.EtSystemUtil;
-import org.hps.monitoring.application.util.SyncEventProcessor;
 import org.hps.monitoring.subsys.et.EtSystemMonitor;
 import org.hps.monitoring.subsys.et.EtSystemStripCharts;
 import org.hps.record.LCSimEventBuilder;
@@ -27,13 +26,9 @@
 import org.hps.record.composite.CompositeRecordProcessor;
 import org.hps.record.composite.EventProcessingThread;
 import org.hps.record.enums.DataSourceType;
-import org.hps.record.epics.EpicsEtProcessor;
 import org.hps.record.et.EtConnection;
-import org.hps.record.et.EtEventProcessor;
 import org.hps.record.et.EtStationThread;
-import org.hps.record.et.PreStartProcessor;
 import org.hps.record.evio.EvioDetectorConditionsProcessor;
-import org.hps.record.evio.EvioEventConstants;
 import org.jlab.coda.et.EtConstants;
 import org.jlab.coda.et.exception.EtClosedException;
 import org.jlab.coda.et.exception.EtException;
@@ -43,73 +38,404 @@
 import org.lcsim.util.Driver;
 
 /**
- * This class encapsulates all of the logic involved with processing events and managing the related
- * state and objects within the monitoring application.
- * 
- * @author Jeremy McCormick <[log in to unmask]>
+ * This class encapsulates all of the logic involved with processing events and managing the related state and objects
+ * within the monitoring application.
+ *
+ * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a>
  */
-class EventProcessing {
-
-    SessionState sessionState;
-    MonitoringApplication application;
-    ConfigurationModel configurationModel;
-    ConnectionStatusModel connectionModel;
-    ErrorHandler errorHandler;
-    Logger logger;
-    
-    /**
-     * This class is used to organize the objects for an event processing session.
-     */
-    class SessionState {
-        
-        List<CompositeRecordProcessor> processors;
-        List<Driver> drivers;
-        List<ConditionsListener> conditionsListeners;
-        
-        JobManager jobManager;
-        LCSimEventBuilder eventBuilder;
-        CompositeLoop loop;
-        
-        boolean usingEtServer;
-        
-        EventProcessingThread processingThread;
-        Thread sessionWatchdogThread;
-        ThreadGroup stationThreadGroup = new ThreadGroup("Station Threads");
-        List<EtStationThread> stations = new ArrayList<EtStationThread>();
-        EtConnection connection;                                      
-    }
-
-    /**
-     * Initialize with reference to the current monitoring application and a list of extra
-     * processors to add to the loop after configuration.
-     * @param application The current monitoring application.
-     * @param processors A list of processors to add after configuration is performed.
-     */
-    EventProcessing(
-            MonitoringApplication application, 
-            List<CompositeRecordProcessor> processors, 
-            List<Driver> drivers, 
-            List<ConditionsListener> conditionsListeners) {
-        
+final class EventProcessing {
+
+    /**
+     * This class is used internally to organize the objects used by an event processing session.
+     */
+    private final class SessionState {
+
+        /**
+         * A list of extra {@link org.lcsim.conditions.ConditionsListener} objects to add to the loop.
+         */
+        private List<ConditionsListener> conditionsListeners;
+
+        /**
+         * An {@link org.hps.record.et.EtConnection} with ET configuration (can be null if using file source).
+         */
+        private EtConnection connection;
+
+        /**
+         * A list of extra {@link org.lcsim.util.Driver} objects to add to the loop.
+         */
+        private List<Driver> drivers;
+
+        /**
+         * The class for building the LCSim events from EVIO data.
+         */
+        private LCSimEventBuilder eventBuilder;
+
+        /**
+         * The LCSim {@link org.hps.job.JobManager} which handles the <code>Driver</code> setup from XML steering files.
+         */
+        private JobManager jobManager;
+
+        /**
+         * The loop which manages the ET to EVIO to LCIO event building and processing.
+         */
+        private CompositeLoop loop;
+
+        /**
+         * The {@link org.hps.record.composite.EventProcessingThread} on which event processing executes.
+         */
+        private EventProcessingThread processingThread;
+
+        /**
+         * The list of extra {@link org.hps.record.composite.CompositeRecordProcessor} objects to add to the loop.
+         */
+        private List<CompositeRecordProcessor> processors;
+
+        /**
+         * A {@link java.lang.Thread} which is used to monitor the event processing.
+         */
+        private Thread sessionWatchdogThread;
+
+        /**
+         * A list of ET stations on separate threads (currently unused).
+         */
+        private List<EtStationThread> stations = new ArrayList<EtStationThread>();
+
+        /**
+         * The ET station thread group (currently unused).
+         */
+        private ThreadGroup stationThreadGroup = new ThreadGroup("Station Threads");
+
+        /**
+         * This is <code>true</code> if the session will connect to a network ET event server.
+         */
+        private boolean usingEtServer;
+    }
+
+    /**
+     * This class will cause the application to disconnect from the current event processing session if the event
+     * processing thread completes.
+     */
+    private final class SessionWatchdogThread extends Thread {
+
+        /**
+         * A reference to the current {{@link #EventProcessing(Thread)}.
+         */
+        private final Thread processingThread;
+
+        /**
+         * Class constructor.
+         *
+         * @param processingThread the current {{@link #EventProcessing(Thread)}
+         */
+        private SessionWatchdogThread(final Thread processingThread) {
+            this.processingThread = processingThread;
+        }
+
+        /**
+         * Run this thread, which will disconnect from the current session if the event processing ends for any reason.
+         */
+        @Override
+        public void run() {
+            try {
+                // This thread waits on the event processing thread to die.
+                this.processingThread.join();
+
+                // Activate a disconnect using the ActionEvent which is used by the disconnect button.
+                EventProcessing.this.logger.finest("processing thread ended so automatic disconnect is happening");
+                EventProcessing.this.application.actionPerformed(new ActionEvent(Thread.currentThread(), 0,
+                        Commands.DISCONNECT));
+
+            } catch (final InterruptedException e) {
+                EventProcessing.this.logger.finest("SessionWatchdogThread got interrupted");
+                // This happens when the thread is interrupted by the user pressing the disconnect button.
+            }
+        }
+    }
+
+    /**
+     * Create the select array from event selection in ET stations (not currently used).
+     *
+     * @return The select array.
+     */
+    static int[] createSelectArray() {
+        final int[] select = new int[EtConstants.stationSelectInts];
+        Arrays.fill(select, -1);
+        return select;
+    }
+
+    /**
+     * Reference to the current application.
+     */
+    private MonitoringApplication application;
+
+    /**
+     * Reference to the global configuration model.
+     */
+    private ConfigurationModel configurationModel;
+
+    /**
+     * Reference to the global connection model.
+     */
+    private ConnectionStatusModel connectionModel;
+
+    /**
+     * The error handler, which is just a reference to the application's error handler.
+     */
+    private ErrorHandler errorHandler;
+
+    /**
+     * The logger to use for message which is the application's logger.
+     */
+    private Logger logger;
+
+    /**
+     * The current {@link EventProcessing.SessionState} object which has all of the session state for event processing.
+     */
+    private SessionState sessionState;
+
+    /**
+     * Class constructor, which will initialize with reference to the current monitoring application and lists of extra
+     * processors to add to the loop as well as supplemental conditions listeners that activate when conditions change.
+     *
+     * @param application the current monitoring application
+     * @param processors a list of processors to add after configuration is performed
+     * @param drivers a list of extra {@link org.lcsim.util.Driver} objects to add to the loop
+     * @param conditionsListeners a list of extra {@link org.lcsim.conditions.ConditionsListener} to add to the loop
+     */
+    EventProcessing(final MonitoringApplication application, final List<CompositeRecordProcessor> processors,
+            final List<Driver> drivers, final List<ConditionsListener> conditionsListeners) {
+
         this.application = application;
-        logger = MonitoringApplication.logger;        
-        configurationModel = application.configurationModel;
-        connectionModel = application.connectionModel;
-        errorHandler = application.errorHandler;
-        
-        sessionState = new SessionState();                        
-        sessionState.processors = processors;
-        sessionState.drivers = drivers;
-        sessionState.conditionsListeners = conditionsListeners;
-        sessionState.usingEtServer = application.configurationModel.getDataSourceType().equals(DataSourceType.ET_SERVER);
-    }
-    
-    /**
-     * Setup this class from the global configuration.
-     * @param configurationModel The global configuration.
-     */
-    void setup(ConfigurationModel configurationModel) {
-        
+        this.logger = application.getLogger();
+        this.configurationModel = application.getConfigurationModel();
+        this.connectionModel = application.getConnectionModel();
+        this.errorHandler = application.getErrorHandler();
+
+        this.sessionState = new SessionState();
+        this.sessionState.processors = processors;
+        this.sessionState.drivers = drivers;
+        this.sessionState.conditionsListeners = conditionsListeners;
+        this.sessionState.usingEtServer = application.getConfigurationModel().getDataSourceType()
+                .equals(DataSourceType.ET_SERVER);
+    }
+
+    /**
+     * Close the current ET connection.
+     * <p>
+     * This method does not need to be <code>synchronized</code>, because it is only called from the
+     * {@link #disconnect()} method which is itself <code>synchronized</code>.
+     */
+    private void closeEtConnection() {
+        if (this.sessionState.connection != null) {
+            this.logger.fine("closing ET connection");
+            if (this.sessionState.connection.getEtSystem().alive()) {
+                this.logger.finest("cleaning up the connection ...");
+                this.sessionState.connection.cleanup();
+                this.logger.finest("connection cleanup successful");
+            }
+            this.sessionState.connection = null;
+            this.logger.fine("ET connection closed");
+        }
+    }
+
+    /**
+     * Connect to the ET system using the current connection settings.
+     *
+     * @throws IOException if any error occurs while creating the ET connection
+     */
+    synchronized void connect() throws IOException {
+        // Setup the network connection if using an ET server.
+        if (usingEtServer()) {
+            // Create a connection to the ET server.
+            try {
+                this.logger.fine("connecting to ET system ...");
+
+                // Create the main ET system connection.
+                createEtConnection();
+
+                // FIXME: Separate event processing ET stations not currently used due to synchronization and ET issues.
+
+                // Add an attachment that listens for DAQ configuration changes via physics SYNC events.
+                // createSyncStation();
+
+                // Add an attachment which listens for EPICs events with scalar data.
+                // createEpicsStation();
+
+                // Add an attachment that listens for PRESTART events.
+                // createPreStartStation();
+
+            } catch (final Exception e) {
+                throw new IOException(e);
+            }
+
+            this.logger.fine("ET system is connected");
+        } else {
+            // This is when a direct file source is used and ET is not needed.
+            this.connectionModel.setConnectionStatus(ConnectionStatus.CONNECTED);
+        }
+
+    }
+
+    /**
+     * Create a connection to an ET system using current parameters from the GUI.
+     * <p>
+     * This method does not need to be <code>synchronized</code>, because it is only called from the {@link #connect()}
+     * method which is itself <code>synchronized</code>.
+     */
+    private void createEtConnection() {
+        // Setup connection to ET system.
+        this.sessionState.connection = EtSystemUtil.createEtConnection(this.configurationModel);
+
+        if (this.sessionState.connection != null) {
+            // Set status to connected as there is now a live ET connection.
+            this.connectionModel.setConnectionStatus(ConnectionStatus.CONNECTED);
+        } else {
+            this.errorHandler.setError(new RuntimeException("Failed to create ET connection.")).log().printStackTrace()
+                    .raiseException();
+        }
+    }
+
+    /**
+     * Create the event builder for converting EVIO events to LCSim.
+     *
+     * @param configurationModel the current global {@link org.hps.monitoring.application.ConfigurationModel} object
+     */
+    private void createEventBuilder(final ConfigurationModel configurationModel) {
+
+        // Get the class for the event builder.
+        final String eventBuilderClassName = configurationModel.getEventBuilderClassName();
+
+        try {
+            // Create a new instance of the builder class.
+            this.sessionState.eventBuilder = (LCSimEventBuilder) Class.forName(eventBuilderClassName, true,
+                    Thread.currentThread().getContextClassLoader()).newInstance();
+        } catch (final Exception e) {
+            throw new RuntimeException("Failed to create LCSimEventBuilder.", e);
+        }
+
+        // Add the builder as a listener so it is notified when conditions change.
+        ConditionsManager.defaultInstance().addConditionsListener(this.sessionState.eventBuilder);
+    }
+
+    /**
+     * Disconnect from the current session, closing the ET connection if necessary.
+     */
+    synchronized void disconnect() {
+
+        // Cleanup the ET connection.
+        if (usingEtServer()) {
+            closeEtConnection();
+        }
+
+        // Change application state to disconnected.
+        this.connectionModel.setConnectionStatus(ConnectionStatus.DISCONNECTED);
+    }
+
+    /**
+     * Invalidate all of the local variables and session state so that this object is not usable after a disconnect.
+     */
+    void invalidate() {
+
+        this.application = null;
+        this.logger = null;
+        this.configurationModel = null;
+        this.connectionModel = null;
+        this.errorHandler = null;
+
+        this.sessionState.conditionsListeners = null;
+        this.sessionState.drivers = null;
+        this.sessionState.processors = null;
+        this.sessionState.jobManager = null;
+        this.sessionState.eventBuilder = null;
+        this.sessionState.loop = null;
+        this.sessionState.processingThread = null;
+        this.sessionState.sessionWatchdogThread = null;
+        this.sessionState.stationThreadGroup = null;
+        this.sessionState.stations = null;
+        this.sessionState.connection = null;
+
+        this.sessionState = null;
+    }
+
+    /**
+     * Return <code>true</code> if the event processing thread is valid (non-null) and active.
+     *
+     * @return <code>true</code> if event processing thread is active
+     */
+    boolean isActive() {
+        return this.sessionState.processingThread != null && this.sessionState.processingThread.isAlive();
+    }
+
+    /**
+     * Interrupt and join to the processing watchdog thread.
+     * <p>
+     * This will happen if there is a user requested disconnect from pushing the disconnect button in the GUI.
+     */
+    synchronized void killWatchdogThread() {
+        // Is the session watchdog thread not null?
+        if (this.sessionState.sessionWatchdogThread != null) {
+            this.logger.finest("killing watchdog thread ...");
+            // Is the thread still alive?
+            if (this.sessionState.sessionWatchdogThread.isAlive()) {
+                // Interrupt the thread which should cause it to stop.
+                this.sessionState.sessionWatchdogThread.interrupt();
+                try {
+                    // This should always work once the thread is interrupted.
+                    this.sessionState.sessionWatchdogThread.join();
+                } catch (final InterruptedException e) {
+                }
+            }
+            // Set the thread object to null.
+            this.sessionState.sessionWatchdogThread = null;
+            this.logger.finest("watchdog thread killed");
+        }
+    }
+
+    /**
+     * Get the next event from the loop if in pause mode.
+     */
+    synchronized void next() {
+        this.logger.finest("getting next event");
+        if (this.connectionModel.getPaused()) {
+            this.connectionModel.setPaused(false);
+            this.sessionState.loop.execute(Command.GO_N, 1L, true);
+            this.connectionModel.setPaused(true);
+        }
+        this.logger.finest("got next event");
+    }
+
+    /**
+     * Notify the loop to pause event processing.
+     */
+    synchronized void pause() {
+        this.logger.finest("pausing");
+        if (!this.connectionModel.getPaused()) {
+            this.sessionState.loop.pause();
+            this.connectionModel.setPaused(true);
+        }
+        this.logger.finest("paused");
+    }
+
+    /**
+     * Resume processing events from pause mode by resuming loop event processing.
+     */
+    synchronized void resume() {
+        this.logger.finest("resuming");
+        if (this.connectionModel.getPaused()) {
+            // Notify event processor to continue.
+            this.sessionState.loop.resume();
+            this.connectionModel.setPaused(false);
+        }
+        this.logger.finest("resumed");
+    }
+
+    /**
+     * Setup this class from the global {@link org.hps.monitoring.model.ConfigurationModel} object.
+     *
+     * @param configurationModel the global @link org.hps.monitoring.model.ConfigurationModel} object
+     */
+    void setup(final ConfigurationModel configurationModel) {
+
         // Setup LCSim from the configuration.
         setupLcsim(configurationModel);
 
@@ -118,37 +444,41 @@
     }
 
     /**
-     * @param configurationModel
-     */
-    void setupLcsim(ConfigurationModel configurationModel) {
-        MonitoringApplication.logger.info("setting up lcsim");
+     * Setup LCSim event processing from the global {@link org.hps.monitoring.model.ConfigurationModel} object.
+     *
+     * @param configurationModel the global @link org.hps.monitoring.model.ConfigurationModel} object
+     */
+    private void setupLcsim(final ConfigurationModel configurationModel) {
+        this.logger.info("setting up lcsim");
 
         // Get steering resource or file as a String parameter.
         String steering = null;
-        SteeringType steeringType = configurationModel.getSteeringType();
+        final SteeringType steeringType = configurationModel.getSteeringType();
         if (steeringType.equals(SteeringType.FILE)) {
             steering = configurationModel.getSteeringFile();
         } else {
             steering = configurationModel.getSteeringResource();
         }
 
-        MonitoringApplication.logger.config("set steering " + steering + " with type " + (steeringType == SteeringType.RESOURCE ? "RESOURCE" : "FILE"));
+        this.logger.config("set steering " + steering + " with type "
+                + (steeringType == SteeringType.RESOURCE ? "RESOURCE" : "FILE"));
 
         try {
             // Create the job manager. A new conditions manager is instantiated from this call but not configured.
-            sessionState.jobManager = new JobManager();
+            this.sessionState.jobManager = new JobManager();
 
             // Add conditions listeners after new database conditions manager is initialized from the job manager.
-            DatabaseConditionsManager conditionsManager = DatabaseConditionsManager.getInstance();
-            for (ConditionsListener conditionsListener : sessionState.conditionsListeners) {
-                logger.config("adding conditions listener " + conditionsListener.getClass().getName());
+            final DatabaseConditionsManager conditionsManager = DatabaseConditionsManager.getInstance();
+            for (final ConditionsListener conditionsListener : this.sessionState.conditionsListeners) {
+                this.logger.config("adding conditions listener " + conditionsListener.getClass().getName());
                 conditionsManager.addConditionsListener(conditionsListener);
             }
 
             if (configurationModel.hasValidProperty(ConfigurationModel.DETECTOR_ALIAS_PROPERTY)) {
                 // Set a detector alias.
-                ConditionsReader.addAlias(configurationModel.getDetectorName(), "file://" + configurationModel.getDetectorAlias());
-                logger.config("using detector alias " + configurationModel.getDetectorAlias());
+                ConditionsReader.addAlias(configurationModel.getDetectorName(),
+                        "file://" + configurationModel.getDetectorAlias());
+                this.logger.config("using detector alias " + configurationModel.getDetectorAlias());
             }
 
             // Setup the event builder to translate from EVIO to LCIO.
@@ -156,7 +486,7 @@
             createEventBuilder(configurationModel);
 
             // Configure the job manager for the XML steering.
-            sessionState.jobManager.setPerformDryRun(true);
+            this.sessionState.jobManager.setPerformDryRun(true);
             if (steeringType == SteeringType.RESOURCE) {
                 setupSteeringResource(steering);
             } else if (steeringType.equals(SteeringType.FILE)) {
@@ -164,143 +494,157 @@
             }
 
             // Set conditions tag.
-            if (configurationModel.hasValidProperty(ConfigurationModel.CONDITIONS_TAG_PROPERTY) && !configurationModel.getConditionsTag().equals("")) {
-                logger.config("conditions tag is set to " + configurationModel.getConditionsTag());
+            if (configurationModel.hasValidProperty(ConfigurationModel.CONDITIONS_TAG_PROPERTY)
+                    && !configurationModel.getConditionsTag().equals("")) {
+                this.logger.config("conditions tag is set to " + configurationModel.getConditionsTag());
             } else {
-                logger.config("conditions NOT using a tag");
+                this.logger.config("conditions NOT using a tag");
             }
 
             // Is there a user specified run number from the JobPanel?
             if (configurationModel.hasValidProperty(ConfigurationModel.USER_RUN_NUMBER_PROPERTY)) {
-                int userRunNumber = configurationModel.getUserRunNumber();
-                String detectorName = configurationModel.getDetectorName();
-                logger.config("setting user run number " + userRunNumber + " with detector " + detectorName);
+                final int userRunNumber = configurationModel.getUserRunNumber();
+                final String detectorName = configurationModel.getDetectorName();
+                this.logger.config("setting user run number " + userRunNumber + " with detector " + detectorName);
                 conditionsManager.setDetector(configurationModel.getDetectorName(), userRunNumber);
                 if (configurationModel.hasPropertyKey(ConfigurationModel.FREEZE_CONDITIONS_PROPERTY)) {
                     // Freeze the conditions system to ignore run numbers from the events.
-                    logger.config("user configured to freeze conditions system");
+                    this.logger.config("user configured to freeze conditions system");
                     conditionsManager.freeze();
                 } else {
                     // Allow run numbers to be picked up from the events.
-                    logger.config("user run number provided but conditions system is NOT frozen");
+                    this.logger.config("user run number provided but conditions system is NOT frozen");
                     conditionsManager.unfreeze();
                 }
             }
 
-            logger.info("lcsim setup was successful");
-
-        } catch (Throwable t) {
+            this.logger.info("lcsim setup was successful");
+
+        } catch (final Throwable t) {
             throw new RuntimeException("Error setting up LCSim.", t);
         }
     }
 
     /**
-     * Create the event builder for converting EVIO events to LCSim.
-     */
-    void createEventBuilder(ConfigurationModel configurationModel) {
-
-        // Get the class for the event builder.
-        String eventBuilderClassName = configurationModel.getEventBuilderClassName();
-
-        try {
-            // Create a new instance of the builder class.
-            sessionState.eventBuilder = (LCSimEventBuilder) Class.forName(eventBuilderClassName, true, Thread.currentThread().getContextClassLoader()).newInstance();
-        } catch (Exception e) {
-            throw new RuntimeException("Failed to create LCSimEventBuilder.", e);
-        }
-
-        // Add the builder as a listener so it is notified when conditions change.
-        ConditionsManager.defaultInstance().addConditionsListener(sessionState.eventBuilder);
-    }
-
-    /**
-     * Setup the loop from the global configuration.
-     * @param configurationModel The global configuration.
-     */
-    void setupLoop(ConfigurationModel configurationModel) {
-
-        logger.config("setting up record loop ...");
-        
-        CompositeLoopConfiguration loopConfig = new CompositeLoopConfiguration()
-            .setStopOnEndRun(configurationModel.getDisconnectOnEndRun())
-            .setStopOnErrors(configurationModel.getDisconnectOnError())
-            .setDataSourceType(configurationModel.getDataSourceType())
-            .setProcessingStage(configurationModel.getProcessingStage())
-            .setEtConnection(sessionState.connection)
-            .setFilePath(configurationModel.getDataSourcePath())
-            .setLCSimEventBuilder(sessionState.eventBuilder);
-        
-        logger.config("data source path is " + configurationModel.getDataSourcePath());
-        logger.config("data source type is " + configurationModel.getDataSourceType());
+     * Setup the {@link org.hps.record.composite.CompositeLoop} from the global
+     * {@link org.hps.monitoring.model.ConfigurationModel} object.
+     *
+     * @param configurationModel the global {@link org.hps.monitoring.model.ConfigurationModel} object
+     */
+    private void setupLoop(final ConfigurationModel configurationModel) {
+
+        this.logger.config("setting up record loop ...");
+
+        // Initialize the loop from configuration model.
+        final CompositeLoopConfiguration loopConfig = new CompositeLoopConfiguration()
+                .setStopOnEndRun(configurationModel.getDisconnectOnEndRun())
+                .setStopOnErrors(configurationModel.getDisconnectOnError())
+                .setDataSourceType(configurationModel.getDataSourceType())
+                .setProcessingStage(configurationModel.getProcessingStage())
+                .setEtConnection(this.sessionState.connection).setFilePath(configurationModel.getDataSourcePath())
+                .setLCSimEventBuilder(this.sessionState.eventBuilder);
+
+        this.logger.config("data source path is " + configurationModel.getDataSourcePath());
+        this.logger.config("data source type is " + configurationModel.getDataSourceType());
 
         if (configurationModel.hasValidProperty(ConfigurationModel.MAX_EVENTS_PROPERTY)) {
-            long maxEvents = configurationModel.getMaxEvents();
+            final long maxEvents = configurationModel.getMaxEvents();
             if (maxEvents > 0L) {
                 loopConfig.setMaxRecords(maxEvents);
             }
         }
 
         // Add all Drivers from the JobManager.
-        for (Driver driver : sessionState.jobManager.getDriverExecList()) {
+        for (final Driver driver : this.sessionState.jobManager.getDriverExecList()) {
             loopConfig.add(driver);
-            logger.config("added Driver " + driver.getName());
+            this.logger.config("added Driver " + driver.getName());
         }
 
         // Using ET server?
         if (configurationModel.getDataSourceType().equals(DataSourceType.ET_SERVER)) {
 
             // ET system monitor.
-            logger.config("added EtSystemMonitor");
+            this.logger.config("added EtSystemMonitor");
             loopConfig.add(new EtSystemMonitor());
 
             // ET system strip charts.
-            logger.config("added EtSystemStripCharts");
+            this.logger.config("added EtSystemStripCharts");
             loopConfig.add(new EtSystemStripCharts());
         }
 
         // Add extra CompositeRecordProcessors to the loop config.
-        for (CompositeRecordProcessor processor : sessionState.processors) {
+        for (final CompositeRecordProcessor processor : this.sessionState.processors) {
             loopConfig.add(processor);
-            logger.config("added extra processor " + processor.getClass().getSimpleName());
+            this.logger.config("added extra processor " + processor.getClass().getSimpleName());
         }
 
         // Add extra Drivers to the loop config.
-        for (Driver driver : sessionState.drivers) {
+        for (final Driver driver : this.sessionState.drivers) {
             loopConfig.add(driver);
-            logger.config("added extra Driver " + driver.getName());
+            this.logger.config("added extra Driver " + driver.getName());
         }
 
         // Enable conditions system activation from EVIO event data in case the PRESTART is missed.
         loopConfig.add(new EvioDetectorConditionsProcessor(configurationModel.getDetectorName()));
-        logger.config("added EvioDetectorConditionsProcessor to job with detector " + configurationModel.getDetectorName());
+        this.logger.config("added EvioDetectorConditionsProcessor to job with detector "
+                + configurationModel.getDetectorName());
 
         // Create the CompositeLoop with the configuration.
-        sessionState.loop = new CompositeLoop(loopConfig);
-        
-        logger.config("record loop is setup");
-    }
-
-    /**
-     * Setup a steering file on disk.
-     * @param steering The steering file.
-     */
-    void setupSteeringFile(String steering) {
-        sessionState.jobManager.setup(new File(steering));
-    }
-
-    /**
-     * Setup a steering resource.
-     * @param steering The steering resource.
-     * @throws IOException if there is a problem setting up or accessing the resource.
-     */
-    void setupSteeringResource(String steering) throws IOException {
-        InputStream is = this.getClass().getClassLoader().getResourceAsStream(steering);
-        if (is == null)
+        this.sessionState.loop = new CompositeLoop(loopConfig);
+
+        this.logger.config("record loop is setup");
+    }
+
+    /**
+     * Setup XML steering from a file from disk.
+     *
+     * @param steering the steering file path
+     */
+    private void setupSteeringFile(final String steering) {
+        this.sessionState.jobManager.setup(new File(steering));
+    }
+
+    /**
+     * Setup XML steering from a jar resource.
+     *
+     * @param steering the steering resource
+     * @throws IOException if there is a problem accessing or setting up the resource
+     */
+    private void setupSteeringResource(final String steering) throws IOException {
+        final InputStream is = this.getClass().getClassLoader().getResourceAsStream(steering);
+        if (is == null) {
             throw new IOException("Steering resource is not accessible or does not exist.");
-        sessionState.jobManager.setup(is);
+        }
+        this.sessionState.jobManager.setup(is);
         is.close();
     }
 
+    /**
+     * Start event processing on a separate thread and also start the watchdog thread.
+     * <p>
+     * This method is called externally by the app to activate event processing after it is initialized and configured.
+     */
+    synchronized void start() {
+
+        this.logger.fine("event processing threads are starting");
+
+        // Start the event processing thread.
+        this.sessionState.processingThread = new EventProcessingThread(this.sessionState.loop);
+        this.sessionState.processingThread.start();
+
+        // Start the watch dog thread which will auto-disconnect when event processing is done.
+        this.sessionState.sessionWatchdogThread = new SessionWatchdogThread(this.sessionState.processingThread);
+        this.sessionState.sessionWatchdogThread.start();
+
+        this.logger.fine("started event processing threads");
+    }
+
+    /**
+     * Stop the current session, which will bring down the current ET client connection and activate end-of-job and
+     * end-of-run hooks on all registered event processors.
+     * <p>
+     * This method is called externally by the app to stop an event processing session e.g. from action event handling.
+     */
     synchronized void stop() {
 
         // Kill session watchdog thread.
@@ -308,398 +652,92 @@
 
         // Wake up all ET stations to unblock the system and make sure secondary stations are detached.
         if (usingEtServer()) {
-            wakeUpEtStations();   
-        }
-        
+            wakeUpEtStations();
+        }
+
         // Stop the event processing now that ET system is unblocked.
-        logger.fine("sending STOP command to loop ...");
-        sessionState.loop.execute(Command.STOP);
-        logger.fine("loop got command STOP");
+        this.logger.fine("sending STOP command to loop ...");
+        this.sessionState.loop.execute(Command.STOP);
+        this.logger.fine("loop got command STOP");
 
         // Cleanup the event processing thread since it was told to stop now.
         try {
-            logger.fine("waiting for event processing thread to end ...");
-            sessionState.processingThread.join();
-            logger.fine("event processing thread ended");   
-        } catch (InterruptedException e) {
+            this.logger.fine("waiting for event processing thread to end ...");
+            this.sessionState.processingThread.join();
+            this.logger.fine("event processing thread ended");
+        } catch (final InterruptedException e) {
             e.printStackTrace();
         }
 
         // Notify of last error that occurred in event processing.
-        if (sessionState.loop.getLastError() != null) {
+        if (this.sessionState.loop.getLastError() != null) {
             // Log the error.
-            errorHandler.setError(sessionState.loop.getLastError()).log();
+            this.errorHandler.setError(this.sessionState.loop.getLastError()).log();
         }
 
         // Invalidate the loop.
-        sessionState.loop = null;
+        this.sessionState.loop = null;
 
         // Disconnect from the ET system.
         disconnect();
-        
+
         // Invalidate the event processing object so it is unusable now.
         invalidate();
     }
 
     /**
-     * Wake up all ET stations associated with event processing.
-     */
-    void wakeUpEtStations() {
-        if (sessionState.connection != null) {
-            logger.fine("waking up ET stations ...");
+     * Return <code>true</code> if using an ET server.
+     *
+     * @return <code>true</code> if using an ET server in the current session
+     */
+    private boolean usingEtServer() {
+        return this.sessionState.usingEtServer;
+    }
+
+    /**
+     * Wake up all ET stations associated with the event processing.
+     */
+    private void wakeUpEtStations() {
+        if (this.sessionState.connection != null) {
+            this.logger.fine("waking up ET stations ...");
 
             // Wake up secondary ET stations.
-            for (EtStationThread station : sessionState.stations) {
-                
+            for (final EtStationThread station : this.sessionState.stations) {
+
                 // First unblock if in ET call.
                 station.wakeUp();
-                
+
                 // Next interrupt so that it will definitely stop.
                 station.interrupt();
             }
 
             // Wait for station threads to die after being woken up.
-            while (sessionState.stationThreadGroup.activeCount() != 0) {
-                logger.finest("waiting for station threads to die ...");
-                Object lock = new Object();
+            while (this.sessionState.stationThreadGroup.activeCount() != 0) {
+                this.logger.finest("waiting for station threads to die ...");
+                final Object lock = new Object();
                 synchronized (lock) {
                     try {
                         lock.wait(500);
-                    } catch (InterruptedException e) {
+                    } catch (final InterruptedException e) {
                         e.printStackTrace();
                     }
                 }
             }
-            
-            sessionState.stationThreadGroup.destroy();
-            
-            logger.finest("station threads destroyed");
+
+            this.sessionState.stationThreadGroup.destroy();
+
+            this.logger.finest("station threads destroyed");
 
             // Wake up the primary ET station doing the event processing.
-            logger.finest("waking up event processing station ...");
+            this.logger.finest("waking up event processing station ...");
             try {
-                sessionState.connection.getEtSystem().wakeUpAll(sessionState.connection.getEtStation());
-                logger.finest("event processing station was woken up");
+                this.sessionState.connection.getEtSystem().wakeUpAll(this.sessionState.connection.getEtStation());
+                this.logger.finest("event processing station was woken up");
             } catch (IOException | EtException | EtClosedException e) {
                 e.printStackTrace();
             }
 
-            logger.finest("ET stations all woken up");
-        }
-    }    
-
-    /**
-     * Start event processing on the event processing thread and start the watchdog thread.
-     */
-    synchronized void start() {
-
-        logger.fine("event processing threads are starting");
-
-        // Start the event processing thread.
-        sessionState.processingThread = new EventProcessingThread(sessionState.loop);
-        sessionState.processingThread.start();
-
-        // Start the watch dog thread which will auto-disconnect when event processing is done.
-        sessionState.sessionWatchdogThread = new SessionWatchdogThread(sessionState.processingThread);
-        sessionState.sessionWatchdogThread.start();
-
-        logger.fine("started event processing threads");
-    }
-
-    /**
-     * Notify the event processor to pause processing.
-     */
-    synchronized void pause() {
-        logger.finest("pausing");
-        if (!connectionModel.getPaused()) {
-            sessionState.loop.pause();
-            connectionModel.setPaused(true);
-        }
-        logger.finest("paused");
-    }
-
-    /**
-     * Get next event if in pause mode.
-     */
-    synchronized void next() {
-        logger.finest("getting next event");
-        if (connectionModel.getPaused()) {
-            connectionModel.setPaused(false);
-            sessionState.loop.execute(Command.GO_N, 1L, true);
-            connectionModel.setPaused(true);
-        }
-        logger.finest("got next event");
-    }
-
-    /**
-     * Resume processing events from pause mode.
-     */
-    synchronized void resume() {
-        logger.finest("resuming");
-        if (connectionModel.getPaused()) {
-            // Notify event processor to continue.
-            sessionState.loop.resume();
-            connectionModel.setPaused(false);
-        }
-        logger.finest("resumed");
-    }
-
-    /**
-     * Interrupt and join to the processing watchdog thread.
-     */
-    synchronized void killWatchdogThread() {
-        // Is the session watchdog thread not null?
-        if (sessionState.sessionWatchdogThread != null) {
-            logger.finest("killing watchdog thread ...");
-            // Is the thread still alive?
-            if (sessionState.sessionWatchdogThread.isAlive()) {
-                // Interrupt the thread which should cause it to stop.
-                sessionState.sessionWatchdogThread.interrupt();
-                try {
-                    // This should always work once the thread is interrupted.
-                    sessionState.sessionWatchdogThread.join();
-                } catch (InterruptedException e) {                    
-                }
-            }
-            // Set the thread object to null.
-            sessionState.sessionWatchdogThread = null;
-            logger.finest("watchdog thread killed");
-        }
-    }
-
-    /**
-     * Cleanup the ET connection.
-     */
-    synchronized void closeEtConnection() {
-        if (sessionState.connection != null) {
-            logger.fine("closing ET connection");
-            if (sessionState.connection.getEtSystem().alive()) {
-                logger.finest("cleaning up the connection ...");
-                sessionState.connection.cleanup();
-                logger.finest("connection cleanup successful");
-            }
-            sessionState.connection = null;
-            logger.fine("ET connection closed");
-        }
-    }
-
-    /**
-     * True if the processing thread is valid and active.
-     * @return True if processing thread is active.
-     */
-    boolean isActive() {
-        return sessionState.processingThread != null && sessionState.processingThread.isAlive();
-    }
-
-    /**
-     * Connect to the ET system using the current connection settings.
-     */
-    synchronized void connect() throws IOException {        
-        // Setup the network connection if using an ET server.
-        if (usingEtServer()) {
-            // Create a connection to the ET server.
-            try {
-                logger.fine("connecting to ET system ...");
-                
-                // Create the main ET system connection.
-                createEtConnection();
-
-                // Add an attachment that listens for DAQ configuration changes via physics SYNC events.
-                //createSyncStation();
-                
-                // Add an attachment which listens for EPICs events with scalar data.
-                //createEpicsStation();
-                
-                // Add an attachment that listens for PRESTART events.
-                //createPreStartStation();
-                
-            } catch (Exception e) {
-                throw new IOException(e);
-            }
-            
-            logger.fine("ET system is connected");
-        } else {
-            // This is when a direct file source is used and ET is not needed.
-            connectionModel.setConnectionStatus(ConnectionStatus.CONNECTED);
-        }
-        
-    }
-
-    /**
-     * True if using an ET server.
-     * @return True if using an ET server.
-     */
-    boolean usingEtServer() {
-        return sessionState.usingEtServer;
-    }
-
-    /**
-     * Create a connection to an ET system using current parameters from the GUI. 
-     */
-    synchronized void createEtConnection() {
-        // Setup connection to ET system.
-        sessionState.connection = EtSystemUtil.createEtConnection(configurationModel);
-
-        if (sessionState.connection != null) {
-            // Set status to connected as there is now a live ET connection.
-            connectionModel.setConnectionStatus(ConnectionStatus.CONNECTED);
-        } else {
-            errorHandler.setError(new RuntimeException("Failed to create ET connection.")).log().printStackTrace().raiseException();
-        }
-    }       
-    
-    /**
-     * Create the select array from event selection in ET stations.
-     * @return The select array.
-     */
-    static int[] createSelectArray() {
-        int select[] = new int[EtConstants.stationSelectInts];
-        Arrays.fill(select, -1);
-        return select;   
-    }    
-     
-    /**
-     * Create a station that listens for physics sync events
-     * containing DAQ configuration.
-     */
-    void createSyncStation() {
-        
-        // Sync events have bits 6 and 7 set.
-        int syncEventType = 0;
-        syncEventType = syncEventType ^ (1 << 6); 
-        syncEventType = syncEventType ^ (1 << 7);
-        int select[] = createSelectArray();
-        select[1] = syncEventType;
-        
-        createStationThread(
-                new SyncEventProcessor(),
-                "SYNC", 
-                1,
-                select);
-    }                                                                                                                                                                                                                                                                               
-    
-    /**
-     * Create a station that listens for PRESTART events
-     * to initialize the conditions system.
-     */
-    void createPreStartStation() {
-                
-        // Select only PRESTART events.
-        int[] select = createSelectArray();
-        select[0] = EvioEventConstants.PRESTART_EVENT_TAG;
-        
-        createStationThread(
-                new PreStartProcessor(configurationModel.getDetectorName()),
-                "PRESTART",
-                1,
-                select);
-    }
-    
-    /**
-     * Create a station that listens for EPICS control events (currently not activated).     
-     */
-    void createEpicsStation() {
-        
-        // Select only EPICS events.
-        int[] select = createSelectArray();
-        select[0] = EvioEventConstants.EPICS_EVENT_TAG;
-        
-        createStationThread(
-                new EpicsEtProcessor(),
-                "EPICS",
-                1,
-                select);
-    }
-    
-    /**
-     * Create an ET station thread.
-     * @param processor The event processor to run on the thread.
-     * @param nameAppend The string to append for naming this station.
-     * @param stationPosition The position of the station.
-     * @param select The event selection data array.
-     */
-    void createStationThread(EtEventProcessor processor, String nameAppend, int stationPosition, int[] select) {
-        EtStationThread stationThread = new EtStationThread(
-                processor,
-                sessionState.connection.getEtSystem(),
-                sessionState.connection.getEtStation().getName() + "_" + nameAppend,
-                stationPosition,
-                select);
-        new Thread(sessionState.stationThreadGroup, stationThread).start();
-        sessionState.stations.add(stationThread);
-        logger.config("started ET station " + nameAppend);
-        StringBuffer sb = new StringBuffer();
-        for (int word : select) {
-            sb.append(word + " ");
-        }
-        logger.config("station has select array: " + sb.toString());
-    }
-
-    /**
-     * Disconnect from the current ET session.
-     * @param status The connection status.
-     */
-    synchronized void disconnect() {
-                
-        // Cleanup the ET connection.
-        if (usingEtServer()) {
-            closeEtConnection();
-        }
-
-        // Change application state to disconnected.
-        connectionModel.setConnectionStatus(ConnectionStatus.DISCONNECTED);
-    }
-
-    /**
-     * This class notifies the application to disconnect if the event processing thread completes.
-     */
-    class SessionWatchdogThread extends Thread {
-
-        Thread processingThread;
-
-        SessionWatchdogThread(Thread processingThread) {
-            this.processingThread = processingThread;
-        }
-
-        public void run() {
-            try {
-                // This thread waits on the event processing thread to die.
-                processingThread.join();
-
-                // Activate a disconnect using the ActionEvent which is used by the disconnect button.
-                logger.finest("processing thread ended so automatic disconnect is happening");
-                application.actionPerformed(new ActionEvent(Thread.currentThread(), 0, Commands.DISCONNECT));
-
-            } catch (InterruptedException e) {
-                logger.finest("SessionWatchdogThread got interrupted");
-                // This happens when the thread is interrupted by the user pressing the disconnect button.
-            }
-        }
-    }
-    
-    /**
-     * Invalidate all 
-     */
-    void invalidate() {
-
-        application = null;
-        logger = null;
-        configurationModel = null;
-        connectionModel = null;
-        errorHandler = null;
-        
-        sessionState.conditionsListeners = null;
-        sessionState.drivers = null;        
-        sessionState.processors = null;        
-        sessionState.jobManager = null;
-        sessionState.eventBuilder = null;
-        sessionState.loop = null;
-        sessionState.processingThread = null;
-        sessionState.sessionWatchdogThread = null;
-        sessionState.stationThreadGroup = null;
-        sessionState.stations = null;
-        sessionState.connection = null;
-        
-        sessionState = null;
+            this.logger.finest("ET stations all woken up");
+        }
     }
 }

Modified: java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/FieldPanel.java
 =============================================================================
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/FieldPanel.java	(original)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/FieldPanel.java	Thu Apr  9 19:22:57 2015
@@ -3,81 +3,138 @@
 import javax.swing.BorderFactory;
 import javax.swing.JPanel;
 import javax.swing.JTextField;
+import javax.swing.SwingConstants;
 import javax.swing.SwingUtilities;
 import javax.swing.border.Border;
 import javax.swing.border.TitledBorder;
 
 /**
  * A panel with a label and a text field.
+ *
+ * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a>
  */
+@SuppressWarnings("serial")
 class FieldPanel extends JPanel {
 
-    String fieldName;
-    String defaultValue;
-    JTextField field;
+    /**
+     * The default component border.
+     */
+    private static final Border DEFAULT_BORDER = BorderFactory.createLoweredBevelBorder();
 
-    static Border border = BorderFactory.createLoweredBevelBorder();
+    /**
+     * The component with the field value.
+     */
+    private final JTextField field;
 
-    FieldPanel(String fieldName, String defaultValue, int size, boolean editable) {
+    /**
+     * Class constructor.
+     *
+     * @param fieldName the name of the field for the label
+     * @param defaultValue the default value
+     * @param size the size of the field
+     * @param editable <code>true</code> if field is editable
+     */
+    protected FieldPanel(final String fieldName, final String defaultValue, final int size, final boolean editable) {
 
-        this.fieldName = fieldName;
-        this.defaultValue = defaultValue;
-
-        TitledBorder title = BorderFactory.createTitledBorder(border, fieldName);
+        final TitledBorder title = BorderFactory.createTitledBorder(DEFAULT_BORDER, fieldName);
         title.setTitleJustification(TitledBorder.LEFT);
 
-        field = new JTextField(defaultValue, size);
-        field.setHorizontalAlignment(JTextField.RIGHT);
-        field.setEditable(editable);
-        field.setBorder(title);
-        add(field);
+        this.field = new JTextField(defaultValue, size);
+        this.field.setHorizontalAlignment(SwingConstants.RIGHT);
+        this.field.setEditable(editable);
+        this.field.setBorder(title);
+        add(this.field);
     }
 
-    void setValue(final String value) {
+    /**
+     * Get a <code>Double</code> value from the field.
+     *
+     * @return the <code>Double</code> value
+     */
+    final Double getDoubleValue() {
+        return Double.parseDouble(getValue());
+    }
+
+    /**
+     * Get an <code>Integer</code> value from the field.
+     *
+     * @return the <code>Integer</code> value
+     */
+    final Integer getIntegerValue() {
+        return Integer.parseInt(getValue());
+    }
+
+    /**
+     * Get a <code>Long</code> value from the field.
+     *
+     * @return the <code>Long</code> value
+     */
+    final Long getLongValue() {
+        return Long.parseLong(getValue());
+    }
+
+    /**
+     * Get the <code>String</code> value from the field.
+     *
+     * @return the <code>String</code> value from the field
+     */
+    final String getValue() {
+        return this.field.getText();
+    }
+
+    /**
+     * Set the field value from a <code>double</code>.
+     *
+     * @param value the <code>double</code> value
+     */
+    final void setValue(final double value) {
         SwingUtilities.invokeLater(new Runnable() {
+            @Override
             public void run() {
-                field.setText(value);
+                FieldPanel.this.field.setText(new Double(value).toString());
             }
         });
     }
 
-    void setValue(final int value) {
+    /**
+     * Set the field value from an <code>int</code>.
+     *
+     * @param value the <code>int</code> value
+     */
+    final void setValue(final int value) {
         SwingUtilities.invokeLater(new Runnable() {
+            @Override
             public void run() {
-                field.setText(new Integer(value).toString());
+                FieldPanel.this.field.setText(new Integer(value).toString());
             }
         });
     }
 
-    void setValue(final double value) {
+    /**
+     * Set the field value from a <code>long</code>.
+     *
+     * @param value the <code>long</code> value
+     */
+    final void setValue(final long value) {
         SwingUtilities.invokeLater(new Runnable() {
+            @Override
             public void run() {
-                field.setText(new Double(value).toString());
+                FieldPanel.this.field.setText(new Long(value).toString());
             }
         });
     }
 
-    void setValue(final long value) {
+    /**
+     * Set the field value from a <code>String</code>.
+     *
+     * @param value the <code>String</code> value
+     */
+    void setValue(final String value) {
         SwingUtilities.invokeLater(new Runnable() {
+            @Override
             public void run() {
-                field.setText(new Long(value).toString());
+                FieldPanel.this.field.setText(value);
             }
         });
     }
-
-    String getValue() {
-        return field.getText();
-    }
-
-    Integer getIntegerValue() {
-        return Integer.parseInt(getValue());
-    }
-
-    Double getDoubleValue() {
-        return Double.parseDouble(getValue());
-    }
-
-    Long getLongValue() {
-        return Long.parseLong(getValue());
-    }
-}
+}

Modified: java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/JobSettingsPanel.java
 =============================================================================
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/JobSettingsPanel.java	(original)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/JobSettingsPanel.java	Thu Apr  9 19:22:57 2015
@@ -28,29 +28,41 @@
 import org.jdom.input.SAXBuilder;
 
 /**
- * This is the GUI panel for setting job parameters. It is connected to the global configuration via a
+ * This is the GUI panel for setting job parameters. It is connected to the global configuration settings via a
  * {@link org.hps.monitoring.model.ConfigurationModel} object.
+ *
+ * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a>
  */
 // FIXME: Combo boxes should use explicit types.
-class JobSettingsPanel extends AbstractFieldsPanel {
+@SuppressWarnings("serial")
+final class JobSettingsPanel extends AbstractFieldsPanel {
 
     /**
      * This filter will accept only files called compact.xml which should be an LCSim detector description file.
      */
     static class CompactFileFilter extends FileFilter {
 
+        /**
+         * Class constructor.
+         */
         public CompactFileFilter() {
         }
 
+        /**
+         * Returns <code>true</code> if the path passes the filter.
+         *
+         * @return <code>true</code> if the path passes the filter
+         */
         @Override
         public boolean accept(final File pathname) {
-            if (pathname.getName().equals("compact.xml")) {
-                return true;
-            } else {
-                return false;
-            }
-        }
-
+            return "compact.xml".equals(pathname.getName());
+        }
+
+        /**
+         * Get the description of the filter.
+         *
+         * @return the description of the filter
+         */
         @Override
         public String getDescription() {
             return "Compact XML files";
@@ -61,6 +73,10 @@
      * Update the GUI from changes in the underlying model. The changes are distinguishable by their property name.
      */
     private class JobSettingsChangeListener implements PropertyChangeListener {
+
+        /**
+         * Handle {@link java.beans.PropertyChangeEvent} by updating the GUI from changes to the model.
+         */
         @Override
         public void propertyChange(final PropertyChangeEvent evt) {
             if (evt.getSource() instanceof ConfigurationModel) {
@@ -121,37 +137,110 @@
         }
     }
 
-    // The available LogLevel settings as an array of strings.
+    /**
+     * The available LogLevel settings as an array of strings.
+     */
     static final String[] LOG_LEVELS = new String[] { Level.ALL.toString(), Level.FINEST.toString(),
-        Level.FINER.toString(), Level.FINE.toString(), Level.CONFIG.toString(), Level.INFO.toString(),
-        Level.WARNING.toString(), Level.SEVERE.toString(), Level.OFF.toString() };
-    // The package where steering resources must be located.
-    static final String STEERING_PACKAGE = "org/hps/steering/monitoring/";
+            Level.FINER.toString(), Level.FINE.toString(), Level.CONFIG.toString(), Level.INFO.toString(),
+            Level.WARNING.toString(), Level.SEVERE.toString(), Level.OFF.toString() };
+
+    /**
+     * The package where steering resources must be located.
+     */
+    private static final String STEERING_PACKAGE = "org/hps/steering/monitoring/";
+
+    /**
+     * Field for name of remote AIDA server.
+     */
     private final JTextField aidaServerNameField;
+
+    /**
+     * Combo box for selecting a conditions system tag.
+     */
     private final JComboBox<String> conditionsTagComboBox;
+
+    /**
+     * Field setting a detector alias to a local file.
+     */
     private final JTextField detectorAliasField;
+
+    /**
+     * Combo box for selecting a detector model.
+     */
     private final JComboBox<String> detectorNameComboBox;
+
+    /**
+     * Check box for enabling disconnect on end run.
+     */
     private final JCheckBox disconnectOnEndRunCheckBox;
+
+    /**
+     * Check box for enabling disconnect on event processing errors.
+     */
     private final JCheckBox disconnectOnErrorCheckBox;
+
+    /**
+     * Combo box for selecting the event builder class.
+     */
     private final JComboBox<String> eventBuilderComboBox;
+
+    /**
+     * Check box for freezing conditions system provided there is a user selected run number and detector.
+     */
     private final JCheckBox freezeConditionsCheckBox;
+
+    /**
+     * Field for specifying an output log file.
+     */
     private final JTextField logFileNameField;
+
+    /**
+     * Field for setting the log level.
+     */
     private final JComboBox<?> logLevelComboBox;
+
+    /**
+     * Check box for enabling logging to a file.
+     */
     private final JCheckBox logToFileCheckbox;
+
+    /**
+     * Field for setting the maximum number of events to process in the session.
+     */
     private final JTextField maxEventsField;
+
+    /**
+     * Combo box for selecting the processing stage(s) to execute (ET, EVIO or LCIO).
+     */
     private final JComboBox<ProcessingStage> processingStageComboBox;
 
+    /**
+     * Field for setting an XML steering file.
+     */
     private final JTextField steeringFileField;
 
+    /**
+     * Combo box for selecting a steering file resource.
+     */
     private final JComboBox<?> steeringResourcesComboBox;
 
+    /**
+     * Combo box for selecting between current file or resource for XML steering.
+     */
     private final JComboBox<?> steeringTypeComboBox;
 
+    /**
+     * Field for setting a user run number for conditions system activation.
+     */
     private final JTextField userRunNumberField;
 
     /**
      * Class constructor.
-     */
+     *
+     * @param model the current {@link org.hps.monitoring.application.model.ConfigurationModel} with global
+     *            configuration
+     */
+    @SuppressWarnings("unchecked")
     JobSettingsPanel(final ConfigurationModel model) {
 
         super(new Insets(5, 3, 3, 5), true);
@@ -248,6 +337,11 @@
         this.aidaServerNameField.addPropertyChangeListener("value", this);
     }
 
+    /**
+     * Handle {@link java.awt.event.ActionEvent} objects by pushing changes from the GUI into the model.
+     *
+     * @param event the {@link java.awt.event.ActionEvent} to handle
+     */
     @Override
     public void actionPerformed(final ActionEvent event) {
         try {
@@ -300,7 +394,9 @@
     }
 
     /**
-     * Attaches the ActionListener from the main app to specific GUI components in this class.
+     * Attaches the ActionListener from the main application to specific GUI components in this class.
+     *
+     * @param the {@link java.awt.event.ActionListener} to register with the relevant components
      */
     @Override
     public void addActionListener(final ActionListener listener) {
@@ -309,25 +405,25 @@
     }
 
     /**
-     * Parse the lcsim steering file to see if it appears to be valid.
+     * Parse the LCSim XML steering file to see if it looks valid.
      *
-     * @param file The input steering file.
-     * @throws IOException if there is a basic IO problem.
-     * @throws JDOMException if the XML is not valid.
+     * @param file the input steering file
+     * @throws IOException if there is a basic IO problem like reading the file
+     * @throws JDOMException if the XML is not valid
      */
     private void checkSteeringFile(final File file) throws IOException, JDOMException {
         final SAXBuilder builder = new SAXBuilder();
         final Document document = builder.build(file);
         final Element rootNode = document.getRootElement();
-        if (!rootNode.getName().equals("lcsim")) {
-            throw new IOException("Not an LCSim XML file: " + file.getPath());
+        if (!"lcsim".equals(rootNode.getName())) {
+            throw new IOException("not an LCSim XML file: " + file.getPath());
         }
     }
 
     /**
      * Choose a compact XML file to override the one embedded in the jar as a resource.
      */
-    void chooseCompactFile() {
+    private void chooseCompactFile() {
         final JFileChooser fc = new JFileChooser();
         fc.setDialogTitle("Choose a Compact XML File");
         fc.setCurrentDirectory(new File("."));
@@ -340,9 +436,9 @@
     }
 
     /**
-     * Choose an lcsim steering file.
-     */
-    void chooseSteeringFile() {
+     * Choose an LCSim steering file.
+     */
+    private void chooseSteeringFile() {
         final JFileChooser fc = new JFileChooser();
         fc.setDialogTitle("Choose an LCSim Steering File");
         fc.setCurrentDirectory(new File("."));
@@ -418,9 +514,17 @@
         }
     }
 
+    /**
+     * Sets the {@link org.hps.monitoring.application.model.ConfigurationModel} for the component containing global
+     * configuration.
+     * <p>
+     * The job settings will be updated automatically if the model changes.
+     *
+     * @param the {@link org.hps.monitoring.application.model.ConfigurationModel} for the component
+     */
     @Override
     public void setConfigurationModel(final ConfigurationModel model) {
         super.setConfigurationModel(model);
         model.addPropertyChangeListener(new JobSettingsChangeListener());
     }
-}
+}

Modified: java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/LogLevelFilterComboBox.java
 =============================================================================
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/LogLevelFilterComboBox.java	(original)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/LogLevelFilterComboBox.java	Thu Apr  9 19:22:57 2015
@@ -14,62 +14,74 @@
 
 /**
  * This is a combo box used to filter the log table messages by level.
- * @author Jeremy McCormick <[log in to unmask]>
+ *
+ * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a>
  */
-class LogLevelFilterComboBox extends JComboBox<Level> implements ActionListener, PropertyChangeListener {
-   
-    ConfigurationModel configurationModel;
-    
-    static final Level[] LOG_LEVELS = new Level[] {
-        Level.ALL, 
-        Level.FINEST, 
-        Level.FINER, 
-        Level.FINE, 
-        Level.CONFIG, 
-        Level.INFO, 
-        Level.WARNING, 
-        Level.SEVERE
-    };
-    
-    LogLevelFilterComboBox(ConfigurationModel configurationModel) {
-        
+@SuppressWarnings("serial")
+final class LogLevelFilterComboBox extends JComboBox<Level> implements ActionListener, PropertyChangeListener {
+
+    /**
+     * Available log levels.
+     */
+    private static final Level[] LOG_LEVELS = new Level[] { Level.ALL, Level.FINEST, Level.FINER, Level.FINE,
+            Level.CONFIG, Level.INFO, Level.WARNING, Level.SEVERE };
+
+    /**
+     * The {@link org.hps.monitoring.application.model.ConfigurationModel} providing the backing model.
+     */
+    private final ConfigurationModel configurationModel;
+
+    /**
+     * Class constructor.
+     *
+     * @param configurationModel the {@link org.hps.monitoring.application.model.ConfigurationModel} providing the
+     *            backing model
+     */
+    LogLevelFilterComboBox(final ConfigurationModel configurationModel) {
+
         configurationModel.addPropertyChangeListener(this);
-        this.configurationModel = configurationModel;       
-        
+        this.configurationModel = configurationModel;
+
         setModel(new DefaultComboBoxModel<Level>(LOG_LEVELS));
         setPrototypeDisplayValue(Level.WARNING);
-        setSelectedItem(Level.ALL);                       
+        setSelectedItem(Level.ALL);
         setActionCommand(Commands.LOG_LEVEL_FILTER_CHANGED);
         addActionListener(this);
         setPreferredSize(new Dimension(100, getPreferredSize().height));
         setSize(new Dimension(100, getPreferredSize().height));
-    }   
-    
+    }
+
     /**
-     * Push change in log level filtering to the configuration model.
+     * The {@link java.awt.event.ActionEvent} handling, which is used to push changes to the global data model.
+     *
+     * @param event the {@link java.awt.event.ActionEvent} object
      */
-    public void actionPerformed(ActionEvent event) {
+    @Override
+    public void actionPerformed(final ActionEvent event) {
         if (event.getActionCommand().equals(Commands.LOG_LEVEL_FILTER_CHANGED)) {
-            configurationModel.removePropertyChangeListener(this);
-            try {                
-                configurationModel.setLogLevelFilter((Level) getSelectedItem());
+            this.configurationModel.removePropertyChangeListener(this);
+            try {
+                this.configurationModel.setLogLevelFilter((Level) getSelectedItem());
             } finally {
-                configurationModel.addPropertyChangeListener(this);
+                this.configurationModel.addPropertyChangeListener(this);
             }
         }
     }
-    
+
     /**
-     * Get change in log level filtering from the configuration model.     
+     * The {@link java.beans.PropertyChangeEvent} handling, which is used to get changes from the model into the GUI.
+     *
+     * @param event the {@link java.beans.PropertyChangeEvent} object to handle
      */
-    public void propertyChange(PropertyChangeEvent event) {
+    @Override
+    public void propertyChange(final PropertyChangeEvent event) {
         if (event.getPropertyName().equals(ConfigurationModel.LOG_LEVEL_FILTER_PROPERTY)) {
-            Level newLevel = (Level) event.getNewValue();
-            configurationModel.removePropertyChangeListener(this);
+            final Level newLevel = (Level) event.getNewValue();
+            this.configurationModel.removePropertyChangeListener(this);
             try {
                 setSelectedItem(newLevel);
             } finally {
-                configurationModel.addPropertyChangeListener(this);
+                this.configurationModel.addPropertyChangeListener(this);
             }
         }
     }

Modified: java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/LogPanel.java
 =============================================================================
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/LogPanel.java	(original)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/LogPanel.java	Thu Apr  9 19:22:57 2015
@@ -15,46 +15,66 @@
 
 /**
  * This is a simple GUI component for the log table and its controls.
- * @author Jeremy McCormick <[log in to unmask]>
+ *
+ * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a>
  */
-class LogPanel extends JPanel{ 
+final class LogPanel extends JPanel {
 
-    LogTable logTable;
-    LogLevelFilterComboBox logFilterComboBox;
-    
-    ConfigurationModel configurationModel;
-        
-    LogPanel(ConfigurationModel configurationModel, ActionListener listener) {
-        
-        this.configurationModel = configurationModel;
-        
+    /**
+     * The combo box for filtering which messages are currently showing in the table.
+     */
+    private final LogLevelFilterComboBox logFilterComboBox;
+
+    /**
+     * The table containing the log messages.
+     */
+    private final LogTable logTable;
+
+    /**
+     * Class constructor.
+     *
+     * @param configurationModel the {@link org.hps.monitoring.application.model.ConfigurationModel} providing the data
+     *            model
+     * @param listener an {@link java.awt.event.ActionListener} to register on certain components
+     */
+    LogPanel(final ConfigurationModel configurationModel, final ActionListener listener) {
+
         setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
-        
-        logTable = new LogTable(configurationModel);
-                        
-        JPanel controlsPanel = new JPanel();
+
+        this.logTable = new LogTable(configurationModel);
+
+        final JPanel controlsPanel = new JPanel();
         controlsPanel.setLayout(new FlowLayout(FlowLayout.LEFT, 10, 5));
-        
-        JLabel label = new JLabel("Log Level Filter");
-        logFilterComboBox = new LogLevelFilterComboBox(configurationModel);
-        logFilterComboBox.setToolTipText("Messages below this level will be filtered out.");
-        controlsPanel.add(label);        
-        controlsPanel.add(logFilterComboBox);
-        
-        JButton exportButton = new JButton("Export ...");
+
+        final JLabel label = new JLabel("Log Level Filter");
+        this.logFilterComboBox = new LogLevelFilterComboBox(configurationModel);
+        this.logFilterComboBox.setToolTipText("Messages below this level will be filtered out.");
+        controlsPanel.add(label);
+        controlsPanel.add(this.logFilterComboBox);
+
+        final JButton exportButton = new JButton("Export ...");
         exportButton.setActionCommand(Commands.SAVE_LOG_TABLE);
         exportButton.addActionListener(listener);
         controlsPanel.add(exportButton);
-        
-        JButton clearButton = new JButton("Clear");
+
+        final JButton clearButton = new JButton("Clear");
         clearButton.setActionCommand(Commands.CLEAR_LOG_TABLE);
         clearButton.addActionListener(listener);
         controlsPanel.add(clearButton);
-                              
-        JScrollPane tablePane = new JScrollPane(logTable);        
+
+        final JScrollPane tablePane = new JScrollPane(this.logTable);
         controlsPanel.setMaximumSize(new Dimension(tablePane.getPreferredSize().width, 200));
-                
+
         add(controlsPanel, BorderLayout.PAGE_START);
         add(tablePane, BorderLayout.PAGE_END);
-    }          
+    }
+
+    /**
+     * Get the log table.
+     *
+     * @return the log table
+     */
+    LogTable getLogTable() {
+        return this.logTable;
+    }
 }

Modified: java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/LogTable.java
 =============================================================================
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/LogTable.java	(original)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/LogTable.java	Thu Apr  9 19:22:57 2015
@@ -18,79 +18,144 @@
 import org.hps.monitoring.application.model.ConfigurationModel;
 
 /**
- * This is a simple Swing component for the table of log messages.
- * @author Jeremy McCormick <[log in to unmask]>
+ * This is a simple {@link avax.swing.JTable} component for displaying log messages.
+ *
+ * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a>
  */
-class LogTable extends JTable implements PropertyChangeListener {
-    
-    static final String[] COLUMN_NAMES = { "Date", "Level", "Message" };
-    
-    LogRecordModel model;
-    TableRowSorter<LogRecordModel> sorter;
-
-    Level filterLevel = Level.ALL;
-    
-    final static SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
-            
-    LogTable(ConfigurationModel configurationModel) {
-        configurationModel.addPropertyChangeListener(this);
-        model = new LogRecordModel();
-        setModel(model);
-        sorter = new TableRowSorter<LogRecordModel>(model);
-        sorter.setRowFilter(new LevelFilter());
-        getColumnModel().getColumn(0).setCellRenderer(new DateRenderer());        
-        setRowSorter(sorter);
-        getColumnModel().getColumn(0).setPreferredWidth(142);
-        getColumnModel().getColumn(0).setMaxWidth(142);
-        getColumnModel().getColumn(1).setPreferredWidth(60);
-        getColumnModel().getColumn(1).setMaxWidth(60);
-        setEnabled(false);
-    }
-        
+@SuppressWarnings("serial")
+final class LogTable extends JTable implements PropertyChangeListener {
+
+    /**
+     * The table cell renderer for displaying dates.
+     */
     static class DateRenderer extends DefaultTableCellRenderer {
-        public void setValue(Object value) {
-            setText((value == null) ? "" : formatter.format(value));
-        }
-    }       
-
-    class LevelFilter extends RowFilter<LogRecordModel, Integer> {
-
-        public boolean include(Entry<? extends LogRecordModel, ? extends Integer> entry) {
-            LogRecordModel model = entry.getModel();
-            LogRecord record = model.get(entry.getIdentifier());
-            if (record.getLevel().intValue() >= filterLevel.intValue()) {
+        @Override
+        public void setValue(final Object value) {
+            setText(value == null ? "" : DATE_FORMAT.format(value));
+        }
+    }
+
+    /**
+     * A filter which determines what level of messages to display in the table.
+     */
+    private class LevelFilter extends RowFilter<LogRecordModel, Integer> {
+
+        /**
+         * Return <code>true</code> to display the entry.
+         *
+         * @param entry the table entry (model with a row ID)
+         */
+        @Override
+        public boolean include(final Entry<? extends LogRecordModel, ? extends Integer> entry) {
+            final LogRecordModel model = entry.getModel();
+            final LogRecord record = model.get(entry.getIdentifier());
+            if (record.getLevel().intValue() >= LogTable.this.filterLevel.intValue()) {
                 return true;
             }
             return false;
         }
     }
-   
-    static class LogRecordModel extends AbstractTableModel {        
-        
-        List<LogRecord> records = new ArrayList<LogRecord>();
-
-        LogRecord get(Integer rowIndex) {
-            return records.get(rowIndex);
-        }
-
-        void add(LogRecord record) {
-            records.add(record);
+
+    /**
+     * The table model implementation.
+     */
+    static class LogRecordModel extends AbstractTableModel {
+
+        /**
+         * The list of {@link java.util.logging.LogRecord} objects to display in the table.
+         */
+        private final List<LogRecord> records = new ArrayList<LogRecord>();
+
+        /**
+         * Add a new {@link java.util.logging.LogRecord} object to the table.
+         *
+         * @param record the new {@link java.util.logging.LogRecord} object
+         */
+        void add(final LogRecord record) {
+            this.records.add(record);
             fireTableDataChanged();
         }
 
-        @Override
-        public int getRowCount() {
-            return records.size();
-        }
-
+        /**
+         * Clear all the records from the table.
+         */
+        void clear() {
+            this.records.clear();
+            fireTableDataChanged();
+        }
+
+        /**
+         * Get a record by its index.
+         *
+         * @param rowIndex the row index
+         * @return the {@link java.util.logging.LogRecord} object
+         * @throws IndexOutOfBoundsException if rowIndex is invalid
+         */
+        private LogRecord get(final Integer rowIndex) {
+            return this.records.get(rowIndex);
+        }
+
+        /**
+         * Get the class of a column.
+         *
+         * @param columnIndex the column's index
+         * @return the column's class
+         */
+        @Override
+        public Class<?> getColumnClass(final int columnIndex) {
+            switch (columnIndex) {
+            case 0:
+                return Date.class;
+            case 1:
+                return Level.class;
+            case 2:
+                return String.class;
+            default:
+                return Object.class;
+            }
+        }
+
+        /**
+         * Get the number of columns.
+         *
+         * @return the number of columns
+         */
         @Override
         public int getColumnCount() {
             return COLUMN_NAMES.length;
         }
 
-        @Override
-        public Object getValueAt(int rowIndex, int columnIndex) {
-            LogRecord record = records.get(rowIndex);
+        /**
+         * Get the column name.
+         *
+         * @param columnIndex the column index
+         * @return the name of the column
+         */
+        @Override
+        public String getColumnName(final int columnIndex) {
+            return COLUMN_NAMES[columnIndex];
+        }
+
+        /**
+         * Get the number of rows.
+         *
+         * @return the number of rows
+         */
+        @Override
+        public int getRowCount() {
+            return this.records.size();
+        }
+
+        /**
+         * Get a cell value from the table.
+         *
+         * @param rowIndex the row index
+         * @param column the column index
+         * @return the cell value or <code>null</code> if does not exist (e.g. invalid column number)
+         */
+        @Override
+        public Object getValueAt(final int rowIndex, final int columnIndex) {
+            final LogRecord record = this.get(rowIndex);
             switch (columnIndex) {
             case 0:
                 return new Date(record.getMillis());
@@ -102,39 +167,70 @@
                 return null;
             }
         }
-
-        @Override
-        public Class<?> getColumnClass(int columnIndex) {
-            switch (columnIndex) {
-            case 0:
-                return Date.class;
-            case 1:
-                return Level.class;
-            case 2:
-                return String.class;
-            default:
-                return Object.class;
-            }
-        }
-        
-        @Override
-        public String getColumnName(int columnIndex) {
-            return COLUMN_NAMES[columnIndex];
-        }
-        
-        void clear() {
-            records.clear();
-            fireTableDataChanged();
-        }
+    }
+
+    /**
+     * The column names.
+     */
+    static final String[] COLUMN_NAMES = { "Date", "Level", "Message" };
+
+    /**
+     * Date formatting.
+     */
+    private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+
+    /**
+     * The current filtering level.
+     */
+    private Level filterLevel = Level.ALL;
+
+    /**
+     * The backing table model.
+     */
+    private final LogRecordModel model;
+
+    /**
+     * The table sorer.
+     */
+    private final TableRowSorter<LogRecordModel> sorter;
+
+    /**
+     * Class constructor.
+     *
+     * @param configurationModel the {@link org.hps.monitoring.application.model.ConfigurationModel} for the application
+     */
+    LogTable(final ConfigurationModel configurationModel) {
+        configurationModel.addPropertyChangeListener(this);
+        this.model = new LogRecordModel();
+        setModel(this.model);
+        this.sorter = new TableRowSorter<LogRecordModel>(this.model);
+        this.sorter.setRowFilter(new LevelFilter());
+        getColumnModel().getColumn(0).setCellRenderer(new DateRenderer());
+        setRowSorter(this.sorter);
+        getColumnModel().getColumn(0).setPreferredWidth(142);
+        getColumnModel().getColumn(0).setMaxWidth(142);
+        getColumnModel().getColumn(1).setPreferredWidth(60);
+        getColumnModel().getColumn(1).setMaxWidth(60);
+        setEnabled(false);
+    }
+
+    /**
+     * Get the table model.
+     *
+     * @return the table model
+     */
+    LogRecordModel getLogRecordModel() {
+        return this.model;
     }
 
     /**
      * Get change in log level filtering from the configuration model.
      */
-    public void propertyChange(PropertyChangeEvent event) {
+    @Override
+    public void propertyChange(final PropertyChangeEvent event) {
         if (event.getPropertyName().equals(ConfigurationModel.LOG_LEVEL_FILTER_PROPERTY)) {
-            filterLevel = (Level) event.getNewValue();
-            model.fireTableDataChanged();
-        }
-    }    
+            this.filterLevel = (Level) event.getNewValue();
+            this.model.fireTableDataChanged();
+        }
+    }
 }

Modified: java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/Main.java
 =============================================================================
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/Main.java	(original)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/Main.java	Thu Apr  9 19:22:57 2015
@@ -12,42 +12,55 @@
 import org.hps.monitoring.application.model.Configuration;
 
 /**
- * This is the front-end for running the monitoring app via a {@link #main(String[])} method.
+ * This is the front-end for running the monitoring application via a {@link #main(String[])} method.
+ *
+ * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a>
  */
 public final class Main {
 
-    private Main() {
-    }
-    
-    public static void main(String[] args) {
-        
+    /**
+     * The main method which starts the monitoring application, which is how users should start the application.
+     *
+     * @param args the command line arguments
+     */
+    public static void main(final String[] args) {
+
         // Set up command line parsing.
-        Options options = new Options();
+        final Options options = new Options();
         options.addOption(new Option("h", false, "Print help."));
         options.addOption(new Option("c", true, "Load a properties file with configuration parameters."));
-        CommandLineParser parser = new PosixParser();
-        
+        final CommandLineParser parser = new PosixParser();
+
         // Parse command line arguments.
         final CommandLine cl;
         try {
             cl = parser.parse(options, args);
-        } catch (ParseException e) {
+        } catch (final ParseException e) {
             throw new RuntimeException("Problem parsing command line options.", e);
         }
 
         // Print help and exit.
         if (cl.hasOption("h")) {
-            HelpFormatter help = new HelpFormatter();
+            final HelpFormatter help = new HelpFormatter();
             help.printHelp(" ", options);
             System.exit(1);
         }
-        
+
         // Load the connection settings.
         Configuration configuration = null;
         if (cl.hasOption("c")) {
             configuration = new Configuration(new File(cl.getOptionValue("c")));
-        }        
-        
+        }
+
         MonitoringApplication.create(configuration);
-    }    
-}
+    }
+
+    /**
+     * Class constructor, which should not be used.
+     * <p>
+     * Call the {@link #main(String[])} method instead.
+     */
+    private Main() {
+        throw new UnsupportedOperationException("Do not instantiate this class.");
+    }
+}

Modified: java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/MenuBar.java
 =============================================================================
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/MenuBar.java	(original)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/MenuBar.java	Thu Apr  9 19:22:57 2015
@@ -18,116 +18,173 @@
 
 /**
  * This is the primary menu bar for the monitoring application.
- * 
- * @author Jeremy McCormick <[log in to unmask]>
+ *
+ * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a>
  */
 @SuppressWarnings("serial")
-class MenuBar extends JMenuBar implements PropertyChangeListener, ActionListener {
-    
-    ConfigurationModel configurationModel;
-    
-    JMenuItem closeFileItem;
-    JMenuItem openFileItem;    
-    JMenu settingsMenu;
-    JMenuItem logItem;
-    JMenuItem serverItem;
-    JMenu recentFilesMenu;    
-    
-    class RecentFileItem extends JMenuItem {
-        
-        String path;        
-        
-        RecentFileItem(String path, int mnemonic) {
-            setText((mnemonic - KeyEvent.VK_0) + " " + path);
+final class MenuBar extends JMenuBar implements PropertyChangeListener, ActionListener {
+
+    /**
+     * The implementation of {@link javax.swing.JMenuItem} for recent file items.
+     */
+    private class RecentFileItem extends JMenuItem {
+
+        /**
+         * The recent file's path.
+         */
+        private final String path;
+
+        /**
+         * Class constructor with file's path and its numerical mnemonic (0-9).
+         *
+         * @param path the path
+         * @param mnemonic the item's mnemonic shortcut (0-9)
+         */
+        RecentFileItem(final String path, final int mnemonic) {
+            setText(mnemonic - KeyEvent.VK_0 + " " + path);
             setMnemonic(mnemonic);
             this.path = path;
         }
-        
-        String getPath() {
-            return path;
-        }        
-    }
-                   
-    MenuBar(ConfigurationModel configurationModel, ConnectionStatusModel connectionModel, ActionListener listener) {
-         
-        this.configurationModel = configurationModel;        
+
+        /**
+         * Get the file path of the item.
+         *
+         * @return the file path
+         */
+        private String getPath() {
+            return this.path;
+        }
+    }
+
+    /**
+     * Starting mnemonic for recent files (this is equivalent to '0').
+     */
+    private static final int RECENT_FILES_START_INDEX = 48;
+
+    /**
+     * Menu item for closing a file source.
+     */
+    private final JMenuItem closeFileItem;
+
+    /**
+     * The application backing model.
+     */
+    private final ConfigurationModel configurationModel;
+
+    /**
+     * Menu item for logging to a file.
+     */
+    private final JMenuItem logItem;
+
+    /**
+     * Menu item for opening a file data source.
+     */
+    private final JMenuItem openFileItem;
+
+    /**
+     * Menu with list of recent files (10 max).
+     */
+    private final JMenu recentFilesMenu;
+
+    /**
+     * Menu item for activating the remote AIDA server.
+     */
+    private final JMenuItem serverItem;
+
+    /**
+     * Menu item for opening the settings dialog window.
+     */
+    private final JMenu settingsMenu;
+
+    /**
+     * Class constructor.
+     *
+     * @param configurationModel the {@link org.hps.monitoring.application.model.ConfigurationModel} providing the model
+     * @param connectionModel the {@link org.hps.monitoring.application.model.ConnectionStatusModel} providing
+     *            connection status
+     * @param listener an {@link ava.awt.event.ActionListener} which is assigned to certain components
+     */
+    MenuBar(final ConfigurationModel configurationModel, final ConnectionStatusModel connectionModel,
+            final ActionListener listener) {
+
+        this.configurationModel = configurationModel;
         this.configurationModel.addPropertyChangeListener(this);
-        
+
         // Need to listen for connection status changes.
-        connectionModel.addPropertyChangeListener(this);  
-        
-        JMenu fileMenu = new JMenu("File");
+        connectionModel.addPropertyChangeListener(this);
+
+        final JMenu fileMenu = new JMenu("File");
         fileMenu.setMnemonic(KeyEvent.VK_F);
         add(fileMenu);
-        
-        openFileItem = new JMenuItem("Open File ...");
-        openFileItem.setMnemonic(KeyEvent.VK_P);
-        openFileItem.setActionCommand(Commands.OPEN_FILE);
-        openFileItem.addActionListener(listener);
-        openFileItem.setToolTipText("Open an EVIO or LCIO data file");
-        fileMenu.add(openFileItem);
-        
-        closeFileItem = new JMenuItem("Close File");
-        closeFileItem.setMnemonic(KeyEvent.VK_C);
-        closeFileItem.setActionCommand(Commands.CLOSE_FILE);
-        closeFileItem.addActionListener(listener);
-        closeFileItem.setToolTipText("Close the current file data source");
-        fileMenu.add(closeFileItem);
-                                      
-        recentFilesMenu = new JMenu("Recent Files");
-        recentFilesMenu.setMnemonic(KeyEvent.VK_R);
-        recentFilesMenu.setToolTipText("List of recent data files");
-        JMenuItem noRecentFilesItem = new JMenuItem("No recent files");
+
+        this.openFileItem = new JMenuItem("Open File ...");
+        this.openFileItem.setMnemonic(KeyEvent.VK_P);
+        this.openFileItem.setActionCommand(Commands.OPEN_FILE);
+        this.openFileItem.addActionListener(listener);
+        this.openFileItem.setToolTipText("Open an EVIO or LCIO data file");
+        fileMenu.add(this.openFileItem);
+
+        this.closeFileItem = new JMenuItem("Close File");
+        this.closeFileItem.setMnemonic(KeyEvent.VK_C);
+        this.closeFileItem.setActionCommand(Commands.CLOSE_FILE);
+        this.closeFileItem.addActionListener(listener);
+        this.closeFileItem.setToolTipText("Close the current file data source");
+        fileMenu.add(this.closeFileItem);
+
+        this.recentFilesMenu = new JMenu("Recent Files");
+        this.recentFilesMenu.setMnemonic(KeyEvent.VK_R);
+        this.recentFilesMenu.setToolTipText("List of recent data files");
+        final JMenuItem noRecentFilesItem = new JMenuItem("No recent files");
         noRecentFilesItem.setEnabled(false);
-        recentFilesMenu.add(noRecentFilesItem);
-        fileMenu.add(recentFilesMenu);
-        
+        this.recentFilesMenu.add(noRecentFilesItem);
+        fileMenu.add(this.recentFilesMenu);
+
         fileMenu.addSeparator();
-        
-        JMenuItem exitItem = new JMenuItem("Exit");
+
+        final JMenuItem exitItem = new JMenuItem("Exit");
         exitItem.setMnemonic(KeyEvent.VK_X);
         exitItem.setActionCommand(Commands.EXIT);
         exitItem.addActionListener(listener);
         exitItem.setToolTipText("Exit from the application");
         fileMenu.add(exitItem);
-                
-        settingsMenu = new JMenu("Settings");
-        settingsMenu.setMnemonic(KeyEvent.VK_S);
-        add(settingsMenu);
-        
-        JMenuItem settingsItem = new JMenuItem("Open Settings Window ...");
+
+        this.settingsMenu = new JMenu("Settings");
+        this.settingsMenu.setMnemonic(KeyEvent.VK_S);
+        add(this.settingsMenu);
+
+        final JMenuItem settingsItem = new JMenuItem("Open Settings Window ...");
         settingsItem.setMnemonic(KeyEvent.VK_O);
         settingsItem.setActionCommand(Commands.SHOW_SETTINGS);
         settingsItem.addActionListener(listener);
         settingsItem.setToolTipText("Show settings dialog");
-        settingsMenu.add(settingsItem);
-        
-        JMenuItem loadConfigItem = new JMenuItem("Load Settings ...");
+        this.settingsMenu.add(settingsItem);
+
+        final JMenuItem loadConfigItem = new JMenuItem("Load Settings ...");
         loadConfigItem.addActionListener(listener);
         loadConfigItem.setMnemonic(KeyEvent.VK_L);
         loadConfigItem.setActionCommand(Commands.LOAD_SETTINGS);
         loadConfigItem.setToolTipText("Load settings from a properties file");
-        settingsMenu.add(loadConfigItem);
-
-        JMenuItem saveConfigItem = new JMenuItem("Save Settings ...");
+        this.settingsMenu.add(loadConfigItem);
+
+        final JMenuItem saveConfigItem = new JMenuItem("Save Settings ...");
         saveConfigItem.addActionListener(listener);
         saveConfigItem.setMnemonic(KeyEvent.VK_S);
         saveConfigItem.setActionCommand(Commands.SAVE_SETTINGS);
         saveConfigItem.setToolTipText("Save configuration to a properties file");
-        settingsMenu.add(saveConfigItem);
-        
-        JMenuItem defaultSettingsItem = new JMenuItem("Load Default Settings");
+        this.settingsMenu.add(saveConfigItem);
+
+        final JMenuItem defaultSettingsItem = new JMenuItem("Load Default Settings");
         defaultSettingsItem.addActionListener(listener);
         defaultSettingsItem.setMnemonic(KeyEvent.VK_D);
         defaultSettingsItem.setActionCommand(Commands.LOAD_DEFAULT_SETTINGS);
         defaultSettingsItem.setToolTipText("Load the default settings");
-        settingsMenu.add(defaultSettingsItem);
-        
-        JMenu plotsMenu = new JMenu("Plots");
+        this.settingsMenu.add(defaultSettingsItem);
+
+        final JMenu plotsMenu = new JMenu("Plots");
         plotsMenu.setMnemonic(KeyEvent.VK_P);
         add(plotsMenu);
-        
-        JMenuItem savePlotsItem = new JMenuItem("Save plots ...");
+
+        final JMenuItem savePlotsItem = new JMenuItem("Save plots ...");
         savePlotsItem.setMnemonic(KeyEvent.VK_S);
         savePlotsItem.setActionCommand(Commands.SAVE_PLOTS);
         savePlotsItem.addActionListener(listener);
@@ -135,140 +192,162 @@
         savePlotsItem.setToolTipText("Save all plots to a file");
         plotsMenu.add(savePlotsItem);
 
-        JMenuItem clearPlotsItem = new JMenuItem("Clear plots");
+        final JMenuItem clearPlotsItem = new JMenuItem("Clear plots");
         clearPlotsItem.setMnemonic(KeyEvent.VK_C);
         clearPlotsItem.setActionCommand(Commands.CLEAR_PLOTS);
         clearPlotsItem.addActionListener(listener);
         clearPlotsItem.setEnabled(true);
         clearPlotsItem.setToolTipText("Clear the AIDA plots");
         plotsMenu.add(clearPlotsItem);
-        
-        JMenu toolsMenu = new JMenu("Tools");
+
+        final JMenu toolsMenu = new JMenu("Tools");
         toolsMenu.setMnemonic(KeyEvent.VK_T);
         add(toolsMenu);
-        
-        JMenuItem screenshotItem = new JMenuItem("Save Screenshot ...");
+
+        final JMenuItem screenshotItem = new JMenuItem("Save Screenshot ...");
         screenshotItem.setMnemonic(KeyEvent.VK_S);
         screenshotItem.setActionCommand(Commands.SAVE_SCREENSHOT);
         screenshotItem.addActionListener(listener);
         screenshotItem.setEnabled(true);
         screenshotItem.setToolTipText("Save a screenshot to a graphics file");
         toolsMenu.add(screenshotItem);
-        
-        logItem = new JMenuItem("Log to File ...");
-        logItem.setMnemonic(KeyEvent.VK_L);
-        logItem.setActionCommand(Commands.LOG_TO_FILE);
-        logItem.addActionListener(listener);
-        logItem.setEnabled(true);
-        logItem.setToolTipText("Redirect System.out to a file instead of terminal");
-        toolsMenu.add(logItem);
-        
-        serverItem = new JMenuItem("Start AIDA Server ...");
-        serverItem.setMnemonic(KeyEvent.VK_A);
-        serverItem.setActionCommand(Commands.START_AIDA_SERVER);
-        serverItem.setEnabled(true);
-        serverItem.setToolTipText("Start AIDA RMI Server");
-        serverItem.addActionListener(listener);
-        toolsMenu.add(serverItem);
-        
-        JMenu windowMenu = new JMenu("Window");
+
+        this.logItem = new JMenuItem("Log to File ...");
+        this.logItem.setMnemonic(KeyEvent.VK_L);
+        this.logItem.setActionCommand(Commands.LOG_TO_FILE);
+        this.logItem.addActionListener(listener);
+        this.logItem.setEnabled(true);
+        this.logItem.setToolTipText("Redirect System.out to a file instead of terminal");
+        toolsMenu.add(this.logItem);
+
+        this.serverItem = new JMenuItem("Start AIDA Server ...");
+        this.serverItem.setMnemonic(KeyEvent.VK_A);
+        this.serverItem.setActionCommand(Commands.START_AIDA_SERVER);
+        this.serverItem.setEnabled(true);
+        this.serverItem.setToolTipText("Start AIDA RMI Server");
+        this.serverItem.addActionListener(listener);
+        toolsMenu.add(this.serverItem);
+
+        final JMenu windowMenu = new JMenu("Window");
         windowMenu.setMnemonic(KeyEvent.VK_W);
         add(windowMenu);
-        
-        JMenuItem maximizeItem = new JMenuItem("Maximize");
+
+        final JMenuItem maximizeItem = new JMenuItem("Maximize");
         maximizeItem.setMnemonic(KeyEvent.VK_M);
         maximizeItem.setActionCommand(Commands.MAXIMIZE_WINDOW);
         maximizeItem.addActionListener(listener);
         maximizeItem.setEnabled(true);
         maximizeItem.setToolTipText("Maximize the application window");
         windowMenu.add(maximizeItem);
-        
-        JMenuItem minimizeItem = new JMenuItem("Minimize");
+
+        final JMenuItem minimizeItem = new JMenuItem("Minimize");
         minimizeItem.setMnemonic(KeyEvent.VK_I);
         minimizeItem.setActionCommand(Commands.MINIMIZE_WINDOW);
         minimizeItem.addActionListener(listener);
         minimizeItem.setEnabled(true);
         minimizeItem.setToolTipText("Minimize the application window");
         windowMenu.add(minimizeItem);
-        
-        JMenuItem defaultsItem = new JMenuItem("Restore Defaults");
+
+        final JMenuItem defaultsItem = new JMenuItem("Restore Defaults");
         defaultsItem.setMnemonic(KeyEvent.VK_D);
         defaultsItem.setActionCommand(Commands.DEFAULT_WINDOW);
         defaultsItem.addActionListener(listener);
         defaultsItem.setEnabled(true);
         defaultsItem.setToolTipText("Restore the window defaults");
-        windowMenu.add(defaultsItem);               
-    }
-
+        windowMenu.add(defaultsItem);
+    }
+
+    /**
+     * The {@link java.awt.event.ActionEvent} handling which sets GUI values from the model.
+     *
+     * @param the {@link java.awt.event.ActionEvent} to handle
+     */
     @Override
-    public void propertyChange(PropertyChangeEvent evt) {
-        configurationModel.removePropertyChangeListener(this);        
-        try {            
+    public void actionPerformed(final ActionEvent e) {
+        if (e.getActionCommand().equals(Commands.DATA_SOURCE_CHANGED)) {
+            if (!this.configurationModel.getDataSourceType().equals(DataSourceType.ET_SERVER)) {
+                this.closeFileItem.setEnabled(true);
+            } else {
+                this.closeFileItem.setEnabled(false);
+            }
+        }
+    }
+
+    /**
+     * The {@link java.beans.PropertyChangeEvent} handling which sets GUI values from the model.
+     *
+     * @param the {@link java.beans.PropertyChangeEvent} to handle
+     */
+    @Override
+    public void propertyChange(final PropertyChangeEvent evt) {
+        this.configurationModel.removePropertyChangeListener(this);
+        try {
             if (evt.getPropertyName().equals(ConnectionStatusModel.CONNECTION_STATUS_PROPERTY)) {
-                ConnectionStatus status = (ConnectionStatus) evt.getNewValue();
-                boolean connected = status.equals(ConnectionStatus.CONNECTED);
-                closeFileItem.setEnabled(!connected);
-                openFileItem.setEnabled(!connected);
+                final ConnectionStatus status = (ConnectionStatus) evt.getNewValue();
+                final boolean connected = status.equals(ConnectionStatus.CONNECTED);
+                this.closeFileItem.setEnabled(!connected);
+                this.openFileItem.setEnabled(!connected);
             } else if (evt.getPropertyName().equals(ConfigurationModel.LOG_TO_FILE_PROPERTY)) {
-                Boolean logToFile = (Boolean) evt.getNewValue();
-                if (logToFile == true) {
+                final Boolean logToFile = (Boolean) evt.getNewValue();
+                if (logToFile) {
                     // Toggle log item state to send to terminal.
-                    logItem.setText("Log to Terminal ...");
-                    logItem.setActionCommand(Commands.LOG_TO_TERMINAL);
-                    logItem.setToolTipText("Log messages to the terminal");
+                    this.logItem.setText("Log to Terminal ...");
+                    this.logItem.setActionCommand(Commands.LOG_TO_TERMINAL);
+                    this.logItem.setToolTipText("Log messages to the terminal");
                 } else {
                     // Toggle log item state to send to file.
-                    logItem.setText("Log to File ...");
-                    logItem.setActionCommand(Commands.LOG_TO_FILE);
-                    logItem.setToolTipText("Log messages to a file");
+                    this.logItem.setText("Log to File ...");
+                    this.logItem.setActionCommand(Commands.LOG_TO_FILE);
+                    this.logItem.setToolTipText("Log messages to a file");
                 }
             } else if (evt.getPropertyName().equals(ConfigurationModel.RECENT_FILES_PROPERTY)) {
-                setRecentFiles(configurationModel.getRecentFilesList());
-            } 
-            
+                setRecentFiles(this.configurationModel.getRecentFilesList());
+            }
+
         } finally {
-            configurationModel.addPropertyChangeListener(this);
-        }
-    }
-
-    @Override
-    public void actionPerformed(ActionEvent e) {
-        if (e.getActionCommand().equals(Commands.DATA_SOURCE_CHANGED)) {
-            if (!configurationModel.getDataSourceType().equals(DataSourceType.ET_SERVER)) {
-                closeFileItem.setEnabled(true);
-            } else {
-                closeFileItem.setEnabled(false);
-            }
-        } 
-    }    
-    
-    void setRecentFiles(List<String> recentFiles) {
-        recentFilesMenu.removeAll();
-        int fileMnemonic = 48; /* starts at KeyEvent.VK_0 */
-        for (String recentFile : recentFiles) {
-            RecentFileItem recentFileItem = new RecentFileItem(recentFile, fileMnemonic);
+            this.configurationModel.addPropertyChangeListener(this);
+        }
+    }
+
+    /**
+     * Set the recent file menu items.
+     *
+     * @param recentFiles the list of recent files from the model
+     */
+    private void setRecentFiles(final List<String> recentFiles) {
+        this.recentFilesMenu.removeAll();
+        int fileMnemonic = RECENT_FILES_START_INDEX; /* starts at KeyEvent.VK_0 */
+        for (final String recentFile : recentFiles) {
+            final RecentFileItem recentFileItem = new RecentFileItem(recentFile, fileMnemonic);
             recentFileItem.addActionListener(new ActionListener() {
-                public void actionPerformed(ActionEvent e) {            
-                    String recentFile = ((RecentFileItem) e.getSource()).getPath();
-                    DataSourceType dst = DataSourceType.getDataSourceType(recentFile);
-                    configurationModel.setDataSourcePath(recentFile); 
-                    configurationModel.setDataSourceType(dst);
+                @Override
+                public void actionPerformed(final ActionEvent e) {
+                    final String recentFile = ((RecentFileItem) e.getSource()).getPath();
+                    final DataSourceType dst = DataSourceType.getDataSourceType(recentFile);
+                    MenuBar.this.configurationModel.setDataSourcePath(recentFile);
+                    MenuBar.this.configurationModel.setDataSourceType(dst);
                 }
-            });                
-            recentFilesMenu.add(recentFileItem);
+            });
+            this.recentFilesMenu.add(recentFileItem);
             ++fileMnemonic;
-        }        
-    }
-    
+        }
+    }
+
+    /**
+     * Set state for AIDA server started.
+     */
     void startAIDAServer() {
-        serverItem.setActionCommand(Commands.STOP_AIDA_SERVER);
-        serverItem.setText("Stop AIDA Server");
-        serverItem.setToolTipText("Stop the remote AIDA server");
-    }
-    
+        this.serverItem.setActionCommand(Commands.STOP_AIDA_SERVER);
+        this.serverItem.setText("Stop AIDA Server");
+        this.serverItem.setToolTipText("Stop the remote AIDA server");
+    }
+
+    /**
+     * Set state for AIDA server stopped.
+     */
     void stopAIDAServer() {
-        serverItem.setActionCommand(Commands.START_AIDA_SERVER);
-        serverItem.setText("Start AIDA Server");
-        serverItem.setToolTipText("Start the remote AIDA server");
+        this.serverItem.setActionCommand(Commands.START_AIDA_SERVER);
+        this.serverItem.setText("Start AIDA Server");
+        this.serverItem.setToolTipText("Start the remote AIDA server");
     }
 }

Modified: java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/MonitoringApplication.java
 =============================================================================
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/MonitoringApplication.java	(original)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/MonitoringApplication.java	Thu Apr  9 19:22:57 2015
@@ -3,8 +3,8 @@
 import hep.aida.jfree.AnalysisFactory;
 import hep.aida.jfree.plotter.PlotterRegion;
 import hep.aida.jfree.plotter.PlotterRegionListener;
-import hep.aida.ref.remote.rmi.client.RmiStoreFactory;
-
+
+import java.awt.Frame;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
 import java.awt.event.WindowEvent;
@@ -29,7 +29,6 @@
 
 import javax.imageio.ImageIO;
 import javax.swing.JFileChooser;
-import javax.swing.JFrame;
 import javax.swing.JOptionPane;
 import javax.swing.JTable;
 import javax.swing.filechooser.FileFilter;
@@ -60,217 +59,308 @@
 import org.lcsim.util.log.DefaultLogFormatter;
 
 /**
- * This is the primary class that implements the monitoring GUI application.
- * It should not be used directly.  Instead the {@link Main} class should be
- * used from the command line.
- * 
- * @author Jeremy McCormick <[log in to unmask]>
+ * This is the primary class that implements the data monitoring GUI application.
+ * <p>
+ * It should not be used directly. Instead the {@link Main} class should be used from the command line.
+ *
+ * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a>
  */
 final class MonitoringApplication implements ActionListener, PropertyChangeListener {
 
-    // Statically initialize logging, which will be fully setup later.
-    static final Logger logger;
-    static {
-        logger = Logger.getLogger(MonitoringApplication.class.getSimpleName());
-    }
-    static final Level DEFAULT_LEVEL = Level.ALL;
-
-    // Default log stream.
-    MonitoringApplicationStreamHandler streamHandler;
-    LogHandler logHandler;
-    PrintStream sysOut = System.out;
-    PrintStream sysErr = System.err;
-    
-    // Application error handling.
-    ErrorHandler errorHandler;
-   
-    // The main GUI components inside a JFrame.
-    MonitoringApplicationFrame frame;    
-    
-    // The primary data models.
-    final RunModel runModel = new RunModel();
-    final ConfigurationModel configurationModel = new ConfigurationModel();
-    final ConnectionStatusModel connectionModel = new ConnectionStatusModel();
-        
-    // The default configuration resource embedded in the jar.
-    static final String DEFAULT_CONFIGURATION = "/org/hps/monitoring/config/default_config.prop";
-
-    // Encapsulation of ET connection and event processing.
-    EventProcessing processing;
-        
-    // Filters for opening files.
-    static final FileFilter lcioFilter = new FileNameExtensionFilter("LCIO files", "slcio");
-    static final EvioFileFilter evioFilter = new EvioFileFilter();
-    
-    AIDAServer server = new AIDAServer("hps-monitoring-app");
-    static final RmiStoreFactory rsf = new RmiStoreFactory();
-            
-    /**
-     * Default log handler.
+    /**
+     * The default log handler which puts records into the table GUI component.
      */
     class LogHandler extends Handler {
+
+        /**
+         * Close the handler.
+         *
+         * @throws SecurityException never
+         */
+        @Override
+        public void close() throws SecurityException {
+            // Does nothing.
+        }
+
+        /**
+         * Flush the handler.
+         */
+        @Override
+        public void flush() {
+            // Does nothing.
+        }
 
         /**
          * This method inserts a record into the log table.
          */
-        public void publish(LogRecord record) {
+        @Override
+        public void publish(final LogRecord record) {
+            // Add the record to the table's model.
             getLogRecordModel().add(record);
         }
-
-        public void close() throws SecurityException {
-        }
-
-        public void flush() {
-        }
-    }    
-    
-    LogRecordModel getLogRecordModel() {
-        return frame.logPanel.logTable.model;
-    }
-    
-    LogTable getLogTable() {
-        return frame.logPanel.logTable;
-    }
-    
+    }
+
+    /**
+     * Log handler which publishes messages to a stream (console or file in this case).
+     */
     class MonitoringApplicationStreamHandler extends StreamHandler {
-        
-        MonitoringApplicationStreamHandler(PrintStream ps) {
+
+        /**
+         * Class constructor.
+         *
+         * @param ps the output stream
+         */
+        MonitoringApplicationStreamHandler(final PrintStream ps) {
             super(ps, new DefaultLogFormatter());
         }
-        
-        public void publish(LogRecord record) {
+
+        /**
+         * Publish a record which will automatically flush the handler.
+         *
+         * @param record the <code>LogRecord</code> to publish
+         */
+        @Override
+        public void publish(final LogRecord record) {
             super.publish(record);
+
+            // FIXME: Is this efficient? Should this always happen here?
             flush();
         }
-        
-        public void setOutputStream(OutputStream out) {
+
+        /**
+         * Set the output stream.
+         *
+         * @param out the output stream
+         */
+        @Override
+        public void setOutputStream(final OutputStream out) {
             super.setOutputStream(out);
-        }        
-    }
-                 
+        }
+    }
+
+    /**
+     * The default configuration resource from the jar.
+     */
+    private static final String DEFAULT_CONFIGURATION = "/org/hps/monitoring/config/default_config.prop";
+
+    /**
+     * The default log level (shows all messages).
+     */
+    private static final Level DEFAULT_LEVEL = Level.ALL;
+
+    /**
+     * A filter for selecting EVIO files.
+     */
+    private static final EvioFileFilter EVIO_FILTER = new EvioFileFilter();
+
+    /**
+     * A filter for selecting LCIO files.
+     */
+    private static final FileFilter LCIO_FILTER = new FileNameExtensionFilter("LCIO files", "slcio");
+
+    /**
+     * Global logging object.
+     */
+    private static final Logger LOGGER;
+
+    /**
+     * Saved reference to <code>System.err</code> for convenience.
+     */
+    private static final PrintStream SYS_ERR = System.err;
+
+    /**
+     * Saved reference to <code>System.out</code> for convenience.
+     */
+    private static final PrintStream SYS_OUT = System.out;
+
+    /**
+     * Initialize logging which will be fully configured later.
+     */
+    static {
+        LOGGER = Logger.getLogger(MonitoringApplication.class.getSimpleName());
+    }
+
+    /**
+     * Static utility method for creating new instance.
+     *
+     * @param configuration the application settings
+     * @return the new monitoring application instance
+     */
+    static MonitoringApplication create(final Configuration configuration) {
+        return new MonitoringApplication(configuration);
+    }
+
+    /**
+     * The global configuration model.
+     */
+    private final ConfigurationModel configurationModel = new ConfigurationModel();
+
+    /**
+     * The global connection status model.
+     */
+    private final ConnectionStatusModel connectionModel = new ConnectionStatusModel();
+
+    /**
+     * The error handling object.
+     */
+    private ErrorHandler errorHandler;
+
+    /**
+     * The primary GUI component which is a <code>JFrame</code>.
+     */
+    private MonitoringApplicationFrame frame;
+
+    /**
+     * The current log handler.
+     */
+    private LogHandler logHandler;
+
+    /**
+     * Event processing wrapper.
+     */
+    private EventProcessing processing;
+
+    /**
+     * The model which has information about the current run and events being processed.
+     */
+    private final RunModel runModel = new RunModel();
+
+    /**
+     * A remote AIDA server instance.
+     */
+    private final AIDAServer server = new AIDAServer("hps-monitoring-app");
+
+    /**
+     * The handler for putting messages into the log table.
+     */
+    private MonitoringApplicationStreamHandler streamHandler;
+
     /**
      * Instantiate and show the monitoring application with the given configuration.
-     * @param userConfiguration The Configuration object containing application settings.
-     */
-    MonitoringApplication(Configuration userConfiguration) {
-        
+     *
+     * @param userConfiguration the Configuration object containing application settings
+     */
+    MonitoringApplication(final Configuration userConfiguration) {
+
         try {
-        
+
             // Setup the main GUI component.
-            frame = new MonitoringApplicationFrame(this);
-            
+            this.frame = new MonitoringApplicationFrame(this);
+
             // Add window listener to perform clean shutdown.
-            frame.addWindowListener(new WindowListener() {
-
+            this.frame.addWindowListener(new WindowListener() {
+
+                /**
+                 * Not used.
+                 *
+                 * @param e
+                 */
                 @Override
-                public void windowOpened(WindowEvent e) {
+                public void windowActivated(final WindowEvent e) {
                 }
 
+                /**
+                 * Activate cleanup when window closes.
+                 *
+                 * @param e the window event
+                 */
                 @Override
-                public void windowClosing(WindowEvent e) {
-                }
-
-                @Override
-                public void windowClosed(WindowEvent e) {
+                public void windowClosed(final WindowEvent e) {
                     exit();
                 }
 
+                /**
+                 * Not used.
+                 *
+                 * @param e
+                 */
                 @Override
-                public void windowIconified(WindowEvent e) {
+                public void windowClosing(final WindowEvent e) {
                 }
 
+                /**
+                 * Not used.
+                 *
+                 * @param e
+                 */
                 @Override
-                public void windowDeiconified(WindowEvent e) {
+                public void windowDeactivated(final WindowEvent e) {
                 }
 
+                /**
+                 * Not used.
+                 *
+                 * @param e
+                 */
                 @Override
-                public void windowActivated(WindowEvent e) {
+                public void windowDeiconified(final WindowEvent e) {
                 }
 
+                /**
+                 * Not used.
+                 *
+                 * @param e
+                 */
                 @Override
-                public void windowDeactivated(WindowEvent e) {
+                public void windowIconified(final WindowEvent e) {
+                }
+
+                /**
+                 * Not used.
+                 *
+                 * @param e
+                 */
+                @Override
+                public void windowOpened(final WindowEvent e) {
                 }
             });
-        
+
             // Setup the error handler.
-            errorHandler = new ErrorHandler(frame, logger);
-                       
+            this.errorHandler = new ErrorHandler(this.frame, LOGGER);
+
             // Add this class as a listener on the configuration model.
-            configurationModel.addPropertyChangeListener(this);
-        
+            this.configurationModel.addPropertyChangeListener(this);
+
             // Setup the logger.
             setupLogger();
-               
+
             // Setup AIDA plotting and connect it to the GUI.
             setupAida();
-            
+
             // Load the default configuration.
             loadConfiguration(new Configuration(DEFAULT_CONFIGURATION), false);
-                    
+
             if (userConfiguration != null) {
                 // Load user configuration.
                 loadConfiguration(userConfiguration, true);
-            } 
-        
+            }
+
             // Enable the GUI now that initialization is complete.
-            frame.setEnabled(true);
-        
-            logger.info("application initialized successfully");
-        
-        } catch (Exception e) {
+            this.frame.setEnabled(true);
+
+            LOGGER.info("application initialized successfully");
+
+        } catch (final Exception e) {
             // Don't use the ErrorHandler here because we don't know that it initialized successfully.
             System.err.println("MonitoringApplication failed to initialize without errors!");
-            DialogUtil.showErrorDialog(null, "Error Starting Monitoring Application", "Monitoring application failed to initialize.");
+            DialogUtil.showErrorDialog(null, "Error Starting Monitoring Application",
+                    "Monitoring application failed to initialize.");
             e.printStackTrace();
             System.exit(1);
-        }        
-    }
-    
-    /**
-     * Setup the logger.
-     */
-    void setupLogger() {
-        logger.setUseParentHandlers(false);        
-        logHandler = new LogHandler();
-        logger.addHandler(logHandler);
-        streamHandler = new MonitoringApplicationStreamHandler(System.out);
-        logger.addHandler(streamHandler);
-        for (Handler handler : logger.getHandlers()) {
-            handler.setLevel(DEFAULT_LEVEL);
-        }
-        logger.setLevel(DEFAULT_LEVEL);
-        logger.info("logging initialized");
-    }
-        
-    /**
-     * Static utility method for creating new instance.
-     * @param configuration The application settings.
-     * @return The new monitoring application instance.
-     */
-    static MonitoringApplication create(Configuration configuration) {
-        return new MonitoringApplication(configuration);
-    }    
-        
-    /**
-     * Handle property changes.
-     * @param evt The property change event.
+        }
+    }
+
+    /**
+     * The primary action handler for the application.
+     *
+     * @param e the {@link java.awt.ActionEvent} to handle
      */
     @Override
-    public void propertyChange(PropertyChangeEvent evt) {
-        if (evt.getPropertyName().equals(ConfigurationModel.LOG_LEVEL_PROPERTY)) {
-            setLogLevel();
-        }
-    }
-    
-    /**
-     * The primary action handler for the application.
-     * @param e The ActionEvent to handle.
-     */
-    public void actionPerformed(ActionEvent e) {
-
-        //logger.finest("actionPerformed - " + e.getActionCommand());
-        
-        String command = e.getActionCommand();
+    public void actionPerformed(final ActionEvent e) {
+
+        // logger.finest("actionPerformed - " + e.getActionCommand());
+
+        final String command = e.getActionCommand();
         if (Commands.CONNECT.equals(command)) {
             startSession();
         } else if (Commands.DISCONNECT.equals(command)) {
@@ -279,20 +369,20 @@
             savePlots();
         } else if (Commands.EXIT.equals(command)) {
             // This will trigger the window closing action that cleans everything up.
-            frame.dispose();
-        } else if (Commands.PAUSE.equals(command)) { 
-            processing.pause();
+            this.frame.dispose();
+        } else if (Commands.PAUSE.equals(command)) {
+            this.processing.pause();
         } else if (Commands.NEXT.equals(command)) {
-            processing.next();
+            this.processing.next();
         } else if (Commands.RESUME.equals(command)) {
-            processing.resume();
+            this.processing.resume();
         } else if (Commands.SHOW_SETTINGS.equals(command)) {
             showSettingsDialog();
         } else if (Commands.LOAD_SETTINGS.equals(command)) {
             loadSettings();
         } else if (Commands.SAVE_SETTINGS.equals(command)) {
             saveSettings();
-        }  else if (Commands.CLEAR_PLOTS.equals(command)) {
+        } else if (Commands.CLEAR_PLOTS.equals(command)) {
             clearPlots();
         } else if (Commands.LOAD_DEFAULT_SETTINGS.equals(command)) {
             loadDefaultSettings();
@@ -321,562 +411,672 @@
         } else if (Commands.STOP_AIDA_SERVER.equals(command)) {
             stopAIDAServer();
         }
-    }    
-    
-    /**
-     * Setup AIDA plotting into the GUI components.
-     */
-    void setupAida() {
-        // Register the factory for displaying plots in tabs.
-        MonitoringAnalysisFactory.register();
-        
-        // Set the root tab pane for displaying plots.
-        MonitoringPlotFactory.setRootPane(frame.plotPanel.getPlotPane());
-        
-        // Setup the region listener to connect the plot info window.
-        MonitoringPlotFactory.setPlotterRegionListener(new PlotterRegionListener() {
-            @Override
-            public void regionSelected(PlotterRegion region) {
-                if (region != null) {
-                    frame.plotInfoPanel.setCurrentRegion(region);
-                }
+    }
+
+    /**
+     * Redirect <code>System.out</code> and <code>System.err</code> to file chosen by a file chooser.
+     */
+    private void chooseLogFile() {
+        final JFileChooser fc = new JFileChooser();
+        fc.setAcceptAllFileFilterUsed(false);
+        fc.setDialogTitle("Save Log Messages to File");
+        fc.setCurrentDirectory(new File("."));
+        final int r = fc.showSaveDialog(this.frame);
+        if (r == JFileChooser.APPROVE_OPTION) {
+            final String fileName = fc.getSelectedFile().getPath();
+            if (new File(fileName).exists()) {
+                DialogUtil.showErrorDialog(this.frame, "File Exists", "File already exists.");
+            } else {
+                logToFile(new File(fileName));
             }
-        });
-        
-        // Perform global configuration of the JFreeChart back end.
-        AnalysisFactory.configure();
-    }
-                
+        }
+    }
+
+    /**
+     * Clear the current set of AIDA plots in the default data tree.
+     */
+    private void clearPlots() {
+        final int confirmation = DialogUtil.showConfirmationDialog(this.frame,
+                "Are you sure you want to clear the plots", "Clear Plots Confirmation");
+        if (confirmation == JOptionPane.YES_OPTION) {
+            AIDA.defaultInstance().clearAll();
+            DialogUtil.showInfoDialog(this.frame, "Plots Clear", "The AIDA plots were cleared.");
+        }
+        LOGGER.info("plots were cleared");
+    }
+
+    /**
+     * Remove the currently selected file from the data source list.
+     */
+    private void closeFile() {
+        if (!this.configurationModel.getDataSourceType().equals(DataSourceType.ET_SERVER)) {
+            final DataSourceItem item = (DataSourceItem) this.frame.getToolbarPanel().getDataSourceComboBox()
+                    .getSelectedItem();
+            if (item.getPath().equals(this.configurationModel.getDataSourcePath())) {
+                this.frame.getToolbarPanel().getDataSourceComboBox()
+                        .removeItem(this.frame.getToolbarPanel().getDataSourceComboBox().getSelectedItem());
+            }
+        }
+    }
+
+    /**
+     * Exit from the application from exit menu item or hitting close window button.
+     */
+    private void exit() {
+        if (this.connectionModel.isConnected()) {
+            this.processing.stop();
+        }
+        this.logHandler.setLevel(Level.OFF);
+        LOGGER.info("exiting the application");
+        this.streamHandler.flush();
+        System.exit(0);
+    }
+
+    /**
+     * Get the current configuration model.
+     *
+     * @return the current configuration model
+     */
+    ConfigurationModel getConfigurationModel() {
+        return this.configurationModel;
+    }
+
+    /**
+     * Get the current connection status model.
+     *
+     * @return the current connections status model
+     */
+    ConnectionStatusModel getConnectionModel() {
+        return this.connectionModel;
+    }
+
+    /**
+     * Get the application's error handling object.
+     *
+     * @return the error handling object
+     */
+    ErrorHandler getErrorHandler() {
+        return this.errorHandler;
+    }
+
+    /**
+     * Get the logger.
+     *
+     * @return the logger
+     */
+    Logger getLogger() {
+        return LOGGER;
+    }
+
+    /**
+     * Get the table model for log records.
+     *
+     * @return the table model for log records
+     */
+    LogRecordModel getLogRecordModel() {
+        return this.frame.getLogPanel().getLogTable().getLogRecordModel();
+    }
+
+    /**
+     * Get the log table.
+     *
+     * @return the log table
+     */
+    LogTable getLogTable() {
+        return this.frame.getLogPanel().getLogTable();
+    }
+
+    /**
+     * Get a list of relevant run data from the model for writing to a PDF.
+     *
+     * @return the list of run data from the model
+     */
+    private List<String> getRunData() {
+        final List<String> data = new ArrayList<String>();
+        data.add("Created: " + new Date());
+        data.add("Run Number: " + this.runModel.getRunNumber());
+        data.add("Started: " + this.runModel.getStartDate());
+        data.add("Ended: " + this.runModel.getEndDate());
+        data.add("Length: " + this.runModel.getRunLength() + " seconds");
+        data.add("Total Events: " + this.runModel.getTotalEvents());
+        data.add("Elapsed Time: " + this.runModel.getElapsedTime());
+        data.add("Events Processed: " + this.runModel.getEventsReceived());
+        return data;
+    }
+
+    /**
+     * Get the run model with information about the run and event(s) currently being processed.
+     *
+     * @return the run model
+     */
+    RunModel getRunModel() {
+        return this.runModel;
+    }
+
     /**
      * This method sets the configuration on the model, which fires a change for every property.
+     *
      * @param configuration The new configuration.
      * @param merge True to merge the configuration into the current one rather than replace it.
      */
-    void loadConfiguration(Configuration configuration, boolean merge) {
-                               
+    private void loadConfiguration(final Configuration configuration, final boolean merge) {
+
         if (merge) {
             // This will merge in additional properties so that default or current settings are preserved.
-            configurationModel.merge(configuration);
+            this.configurationModel.merge(configuration);
         } else {
             // HACK: Clear data source combo box for clean configuration.
-            frame.toolbarPanel.dataSourceComboBox.removeAllItems();
-            
+            this.frame.getToolbarPanel().getDataSourceComboBox().removeAllItems();
+
             // This will reset all configuration properties.
-            configurationModel.setConfiguration(configuration);
-        }
-        
-        if (configuration.getFile() != null)
-            logger.config("loaded config from file " + configuration.getFile().getPath());
-        else
-            logger.config("loaded config from resource " + configuration.getResourcePath());
-    }
-              
+            this.configurationModel.setConfiguration(configuration);
+        }
+
+        if (configuration.getFile() != null) {
+            LOGGER.config("loaded config from file " + configuration.getFile().getPath());
+        } else {
+            LOGGER.config("loaded config from resource " + configuration.getResourcePath());
+        }
+    }
+
+    /**
+     * Load default application settings.
+     */
+    private void loadDefaultSettings() {
+        loadConfiguration(new Configuration(MonitoringApplication.DEFAULT_CONFIGURATION), false);
+        DialogUtil.showInfoDialog(this.frame, "Default Configuration Loaded", "The default configuration was loaded.");
+        LOGGER.config("default settings loaded");
+    }
+
+    /**
+     * Load settings from a properties file using a file chooser.
+     */
+    private void loadSettings() {
+        final JFileChooser fc = new JFileChooser();
+        fc.setDialogTitle("Load Settings");
+        fc.setCurrentDirectory(new File("."));
+        final int r = fc.showDialog(this.frame, "Load ...");
+        if (r == JFileChooser.APPROVE_OPTION) {
+            final File f = fc.getSelectedFile();
+            loadConfiguration(new Configuration(f), true);
+            LOGGER.info("loaded configuration from file: " + f.getPath());
+            DialogUtil.showInfoDialog(this.frame, "Settings Loaded", "Settings were loaded successfully.");
+        }
+    }
+
+    /**
+     * Redirect <code>System.out</code> and <code>System.err</code> to a file.
+     *
+     * @param file The output log file.
+     * @throws FileNotFoundException if the file does not exist.
+     */
+    private void logToFile(final File file) {
+        try {
+
+            // Create the output file stream.
+            final PrintStream fileStream = new PrintStream(new FileOutputStream(file.getPath()));
+            System.setOut(fileStream);
+            System.setErr(fileStream);
+
+            // Flush the current handler, but do NOT close here or System.out gets clobbered!
+            this.streamHandler.flush();
+
+            // Replace the current handler with one using the file stream.
+            LOGGER.removeHandler(this.streamHandler);
+            this.streamHandler = new MonitoringApplicationStreamHandler(fileStream);
+            this.streamHandler.setLevel(LOGGER.getLevel());
+            LOGGER.addHandler(this.streamHandler);
+
+            // Set the properties on the model.
+            this.configurationModel.setLogFileName(file.getPath());
+            this.configurationModel.setLogToFile(true);
+
+            LOGGER.info("Saving log messages to " + this.configurationModel.getLogFileName());
+            DialogUtil.showInfoDialog(this.frame, "Logging to File", "Log messages redirected to file" + '\n'
+                    + this.configurationModel.getLogFileName());
+
+        } catch (final FileNotFoundException e) {
+            this.errorHandler.setError(e).log().showErrorDialog();
+        }
+    }
+
+    /**
+     * Send <code>System.out</code> and <code>System.err</code> back to the terminal, e.g. if they were previously sent
+     * to a file.
+     */
+    private void logToTerminal() {
+
+        // Reset System.out and err back to original streams.
+        System.setOut(MonitoringApplication.SYS_OUT);
+        System.setErr(MonitoringApplication.SYS_ERR);
+
+        // Flush and close the current handler, which is using a file stream.
+        this.streamHandler.flush();
+        this.streamHandler.close();
+
+        // Replace the handler with the one printing to the terminal.
+        LOGGER.removeHandler(this.streamHandler);
+        this.streamHandler = new MonitoringApplicationStreamHandler(System.out);
+        this.streamHandler.setLevel(LOGGER.getLevel());
+        LOGGER.addHandler(this.streamHandler);
+
+        LOGGER.log(Level.INFO, "log messages redirected to terminal");
+
+        // Update the model to indicate logging to file has been disabled.
+        this.configurationModel.setLogToFile(false);
+
+        DialogUtil.showInfoDialog(this.frame, "Log to Terminal", "Log messages will be sent to the terminal.");
+    }
+
+    /**
+     * Maximize the application window.
+     */
+    private void maximizeWindow() {
+        this.frame.setExtendedState(Frame.MAXIMIZED_BOTH);
+    }
+
+    /**
+     * Minimize the application window.
+     */
+    private void minimizeWindow() {
+        this.frame.setExtendedState(Frame.ICONIFIED);
+    }
+
+    /**
+     * Open a file data source using a <code>JFileChooser</code>.
+     */
+    private void openFile() {
+        final JFileChooser fc = new JFileChooser(System.getProperty("user.dir"));
+        fc.setAcceptAllFileFilterUsed(false);
+        fc.addChoosableFileFilter(LCIO_FILTER);
+        fc.addChoosableFileFilter(EVIO_FILTER);
+        fc.setDialogTitle("Select Data File");
+        final int r = fc.showDialog(this.frame, "Select ...");
+        if (r == JFileChooser.APPROVE_OPTION) {
+
+            // Set data source path.
+            final String filePath = fc.getSelectedFile().getPath();
+
+            // Set data source type.
+            final FileFilter filter = fc.getFileFilter();
+            DataSourceType type = null;
+            if (filter == LCIO_FILTER) {
+                type = DataSourceType.LCIO_FILE;
+            } else if (filter == EVIO_FILTER) {
+                type = DataSourceType.EVIO_FILE;
+            } else {
+                // This should never happen.
+                throw new RuntimeException();
+            }
+
+            this.configurationModel.setDataSourcePath(filePath);
+            this.configurationModel.setDataSourceType(type);
+
+            this.configurationModel.addRecentFile(filePath);
+
+            LOGGER.config("set new data source " + filePath + " with type " + type);
+        }
+    }
+
+    /**
+     * Handle property changes.
+     *
+     * @param evt The property change event.
+     */
+    @Override
+    public void propertyChange(final PropertyChangeEvent evt) {
+        if (evt.getPropertyName().equals(ConfigurationModel.LOG_LEVEL_PROPERTY)) {
+            setLogLevel();
+        }
+    }
+
     /**
      * Reset the plots and clear the tabs in the plot window.
      */
-    void resetPlots() {
-        
+    private void resetPlots() {
+
         // Clear global list of registered plotters.
-        MonitoringPlotFactory.getPlotterRegistry().clear();  
-        
+        MonitoringPlotFactory.getPlotterRegistry().clear();
+
         // Clear the static AIDA tree in case plots are hanging around from previous sessions.
         AIDA.defaultInstance().clearAll();
 
         // Reset plot panel which removes all its tabs.
-        frame.plotPanel.reset();
-        
-        logger.info("plots were cleared");
-    }                                    
-                   
-    /**
-     * Configure the system status monitor panel for a new job.
-     */
-    void setupSystemStatusMonitor() {
-        
-        // Clear the system status monitor table.
-        frame.systemStatusPanel.clear();
-
-        // Get the global registry of SystemStatus objects.
-        SystemStatusRegistry registry = SystemStatusRegistry.getSystemStatusRegistery();
-
-        // Process the SystemStatus objects.
-        for (SystemStatus systemStatus : registry.getSystemStatuses()) {
-            // This will add the status to the two tables.
-            frame.systemStatusPanel.addSystemStatus(systemStatus);
-        }
-        
-        logger.info("system status monitor initialized successfully");
-    }
-    
-    /**
-     * Start a new monitoring session.
-     */
-    synchronized void startSession() {
-        
-        logger.info("starting new session");
-
-        try {
-                        
-            // Reset the plot panel and global AIDA state.
-            resetPlots();
-
-            // The system status registry is cleared here before any event processors
-            // which might create a SystemStatus are added to the event processing chain
-            // e.g. an LCSim Driver, etc.
-            SystemStatusRegistry.getSystemStatusRegistery().clear();
-
-            // List of extra composite record processors including the updater for the RunPanel.
-            List<CompositeRecordProcessor> processors = new ArrayList<CompositeRecordProcessor>();
-            processors.add(frame.dashboardPanel.new EventDashboardUpdater());
-            
-            // Add Driver to update the trigger diagnostics tables.
-            List<Driver> drivers = new ArrayList<Driver>();
-            drivers.add(frame.triggerPanel.new TriggerDiagnosticGUIDriver());
-
-            // Add listener to push conditions changes to conditions panel.
-            List<ConditionsListener> conditionsListeners = new ArrayList<ConditionsListener>();
-            conditionsListeners.add(frame.conditionsPanel.new ConditionsPanelListener());
-            
-            // Instantiate the event processing wrapper.
-            processing = new EventProcessing(this, processors, drivers, conditionsListeners);
-            
-            // Connect to the ET system, if applicable.
-            processing.connect();
-            
-            // Configure event processing from the global application settings, including setup of record loop.
-            logger.info("setting up event processing on source " + configurationModel.getDataSourcePath() 
-                    + " with type " + configurationModel.getDataSourceType());
-            processing.setup(configurationModel);
-                                  
-            // Setup the system status monitor table.
-            setupSystemStatusMonitor();
-                                            
-            // Start the event processing thread.            
-            processing.start();            
-            
-            logger.info("new session successfully initialized");
-
-        } catch (Exception e) {
-
-            // Disconnect from the ET system.
-            processing.disconnect();
-            
-            // Log the error that occurred and show a pop up dialog.
-            errorHandler.setError(e).log().printStackTrace().showErrorDialog("There was an error while starting the session." 
-                    + '\n' + "See the log for details.", "Session Error");
-            
-            logger.severe("failed to start new session");
-        }
-    }
-           
-    /**
-     * Exit from the application from exit menu item or hitting close window button.
-     */
-    void exit() {        
-        if (connectionModel.isConnected()) {
-            processing.stop();
-        }
-        logHandler.setLevel(Level.OFF);
-        logger.info("exiting the application");
-        streamHandler.flush();
-        System.exit(0);
-    }
-            
+        this.frame.getPlotPanel().reset();
+
+        LOGGER.info("plots were cleared");
+    }
+
+    /**
+     * Restore the default GUI layout.
+     */
+    private void restoreDefaultWindow() {
+        maximizeWindow();
+        this.frame.restoreDefaults();
+    }
+
+    /**
+     * Run the disconnection on a separate thread.
+     */
+    private void runDisconnectThread() {
+        new Thread() {
+            @Override
+            public void run() {
+                LOGGER.fine("disconnect thread is running ...");
+                MonitoringApplication.this.connectionModel.setConnectionStatus(ConnectionStatus.DISCONNECTING);
+                MonitoringApplication.this.processing.stop();
+                LOGGER.fine("disconnect thread finished!");
+            }
+        }.run();
+    }
+
+    /**
+     * Save the log table to a file using a file chooser.
+     */
+    private void saveLogTable() {
+        saveTable(this.frame.getLogPanel().getLogTable());
+    }
+
     /**
      * Save plots to an AIDA, ROOT or PDF file using a file chooser.
      */
-    void savePlots() {
-        JFileChooser fc = new JFileChooser();
+    private void savePlots() {
+        final JFileChooser fc = new JFileChooser();
         fc.addChoosableFileFilter(new FileNameExtensionFilter("ROOT file", "root"));
-        FileFilter filter = new FileNameExtensionFilter("AIDA file", "aida");
+        final FileFilter filter = new FileNameExtensionFilter("AIDA file", "aida");
         fc.addChoosableFileFilter(filter);
         fc.addChoosableFileFilter(new FileNameExtensionFilter("PDF file", "pdf"));
         fc.setAcceptAllFileFilterUsed(false);
         fc.setFileSelectionMode(JFileChooser.FILES_ONLY);
         fc.setFileFilter(filter);
-        int r = fc.showSaveDialog(frame);
+        final int r = fc.showSaveDialog(this.frame);
         if (r == JFileChooser.APPROVE_OPTION) {
-            File selectedFile = fc.getSelectedFile();
+            final File selectedFile = fc.getSelectedFile();
             if (!selectedFile.exists()) {
                 String fileName = fc.getSelectedFile().getAbsolutePath();
-                String extension = ((FileNameExtensionFilter) fc.getFileFilter()).getExtensions()[0];
+                final String extension = ((FileNameExtensionFilter) fc.getFileFilter()).getExtensions()[0];
                 if (!fileName.endsWith(".aida") && !fileName.endsWith(".root") && !fileName.endsWith(".pdf")) {
                     fileName += "." + extension;
                 }
                 try {
-                    if (extension.equals("pdf")) {
+                    if ("pdf".equals(extension)) {
                         // Write to a single PDF file.
-                        ExportPdf.write(MonitoringPlotFactory.getPlotterRegistry().getPlotters(), fileName, getRunData());
+                        ExportPdf.write(MonitoringPlotFactory.getPlotterRegistry().getPlotters(), fileName,
+                                getRunData());
                     } else {
                         // Save plot object data to AIDA or ROOT file.
                         AIDA.defaultInstance().saveAs(fileName);
                     }
-                    logger.info("saved plots to " + fileName);
-                    DialogUtil.showInfoDialog(frame, "Plots Saved", "Plots were successfully saved to " + '\n' + fileName);
-                } catch (IOException e) {
-                    errorHandler.setError(e).setMessage("Error Saving Plots").printStackTrace().log().showErrorDialog();
+                    LOGGER.info("saved plots to " + fileName);
+                    DialogUtil.showInfoDialog(this.frame, "Plots Saved", "Plots were successfully saved to " + '\n'
+                            + fileName);
+                } catch (final IOException e) {
+                    this.errorHandler.setError(e).setMessage("Error Saving Plots").printStackTrace().log()
+                            .showErrorDialog();
                 }
             } else {
-                DialogUtil.showErrorDialog(frame, "File Exists", "Selected file already exists.");
+                DialogUtil.showErrorDialog(this.frame, "File Exists", "Selected file already exists.");
             }
         }
     }
-    
-    /**
-     * Get a list of run data for writing to a PDF.
-     * @return The list of run data from the model.
-     */
-    List<String> getRunData() {
-         List<String> data = new ArrayList<String>();
-         data.add("Created: " + new Date());
-         data.add("Run Number: " + runModel.getRunNumber());
-         data.add("Started: " + runModel.getStartDate());
-         data.add("Ended: " + runModel.getEndDate());
-         data.add("Length: " + runModel.getRunLength() + " seconds");
-         data.add("Total Events: " + runModel.getTotalEvents());
-         data.add("Elapsed Time: " + runModel.getElapsedTime());
-         data.add("Events Processed: " + runModel.getEventsReceived());
-         return data;
-    }
-    
-    /**
-     * Clear the current set of AIDA plots in the default data tree.
-     */
-    void clearPlots() {
-        int confirmation = DialogUtil.showConfirmationDialog(frame, 
-                "Are you sure you want to clear the plots", "Clear Plots Confirmation");
-        if (confirmation == JOptionPane.YES_OPTION) {
-            AIDA.defaultInstance().clearAll();
-            DialogUtil.showInfoDialog(frame, "Plots Clear", "The AIDA plots were cleared.");
-        }
-        logger.info("plots were cleared");
-    }
-    
-    /**
-     * Load default application settings.
-     */
-    void loadDefaultSettings() {
-        loadConfiguration(new Configuration(MonitoringApplication.DEFAULT_CONFIGURATION), false);
-        DialogUtil.showInfoDialog(frame, "Default Configuration Loaded", "The default configuration was loaded.");
-        logger.config("default settings loaded");
-    }
-    
-    /**
-     * Show the settings dialog window.
-     */
-    void showSettingsDialog() {
-        frame.settingsDialog.setVisible(true);        
-    }
-        
-    /**
-     * Open a file data source using a <code>JFileChooser</code>.
-     */
-    void openFile() {
-        JFileChooser fc = new JFileChooser(System.getProperty("user.dir"));
-        fc.setAcceptAllFileFilterUsed(false);
-        fc.addChoosableFileFilter(lcioFilter);
-        fc.addChoosableFileFilter(evioFilter);
-        fc.setDialogTitle("Select Data File");
-        int r = fc.showDialog(frame, "Select ...");        
-        if (r == JFileChooser.APPROVE_OPTION) {
-                                  
-            // Set data source path.            
-            final String filePath = fc.getSelectedFile().getPath();
-            
-            // Set data source type.
-            FileFilter filter = fc.getFileFilter();
-            DataSourceType type = null;
-            if (filter == lcioFilter) {
-                type = DataSourceType.LCIO_FILE;
-            } else if (filter == evioFilter) {
-                type = DataSourceType.EVIO_FILE;
-            } else {
-                // This should never happen.
-                throw new RuntimeException();
-            }
-                        
-            configurationModel.setDataSourcePath(filePath);
-            configurationModel.setDataSourceType(type);
-            
-            configurationModel.addRecentFile(filePath);
-            
-            logger.config("set new data source " + filePath + " with type " + type);
-        }
-    }    
-    
-    /**
-     * Save current settings to a file using a file chooser.
-     */
-    void saveSettings() {
-        JFileChooser fc = new JFileChooser();
-        fc.setDialogTitle("Save Configuration");
-        fc.setCurrentDirectory(new File("."));
-        int r = fc.showSaveDialog(frame);
-        if (r == JFileChooser.APPROVE_OPTION) {
-            File f = fc.getSelectedFile();
-            configurationModel.getConfiguration().writeToFile(f);
-            logger.info("saved configuration to file: " + f.getPath());
-            DialogUtil.showInfoDialog(frame, "Settings Saved", "Settings were saved successfully.");
-        }
-    }
-    
-    /**
-     * Load settings from a properties file using a file chooser.
-     */
-    void loadSettings() {
-        JFileChooser fc = new JFileChooser();
-        fc.setDialogTitle("Load Settings");
-        fc.setCurrentDirectory(new File("."));
-        int r = fc.showDialog(frame, "Load ...");
-        if (r == JFileChooser.APPROVE_OPTION) {
-            File f = fc.getSelectedFile();
-            loadConfiguration(new Configuration(f), true);
-            logger.info("loaded configuration from file: " + f.getPath());
-            DialogUtil.showInfoDialog(frame, "Settings Loaded", "Settings were loaded successfully.");
-        }
-    }
-    
-    /**
-     * Maximize the application window.
-     */
-    void maximizeWindow() {
-        frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
-    }   
-    
-    /**
-     * Minimize the application window.
-     */
-    void minimizeWindow() {
-        frame.setExtendedState(JFrame.ICONIFIED);
-    }    
-    
-    /**
-     * Restore the default GUI layout.
-     */
-    void restoreDefaultWindow() {
-        maximizeWindow();
-        frame.restoreDefaults();
-    }    
-    
-    /**
-     * Remove the currently selected file from the data source list.
-     */
-    void closeFile() {
-        if (!configurationModel.getDataSourceType().equals(DataSourceType.ET_SERVER)) {
-            DataSourceItem item = (DataSourceItem) frame.toolbarPanel.dataSourceComboBox.getSelectedItem();
-            if (item.getPath().equals(configurationModel.getDataSourcePath())) {
-                frame.toolbarPanel.dataSourceComboBox.removeItem(frame.toolbarPanel.dataSourceComboBox.getSelectedItem());    
-            }            
-        }
-    }
-    
+
     /**
      * Save a screenshot to a file using a file chooser.
      */
-    void saveScreenshot() {
-        JFileChooser fc = new JFileChooser();
+    private void saveScreenshot() {
+        final JFileChooser fc = new JFileChooser();
         fc.setAcceptAllFileFilterUsed(false);
         fc.setDialogTitle("Save Screenshot");
-        FileNameExtensionFilter pngFilter = new FileNameExtensionFilter("png file (*.png)", "png");
-        String format = pngFilter.getExtensions()[0];
+        final FileNameExtensionFilter pngFilter = new FileNameExtensionFilter("png file (*.png)", "png");
+        final String format = pngFilter.getExtensions()[0];
         fc.addChoosableFileFilter(pngFilter);
         fc.setCurrentDirectory(new File("."));
-        int r = fc.showSaveDialog(frame);
-        if (r == JFileChooser.APPROVE_OPTION) {            
+        final int r = fc.showSaveDialog(this.frame);
+        if (r == JFileChooser.APPROVE_OPTION) {
             String fileName = fc.getSelectedFile().getPath();
             if (!fileName.endsWith("." + format)) {
                 fileName += "." + format;
             }
-            frame.repaint();
-            Object lock = new Object();
-            synchronized (lock) {
-                try {
-                    lock.wait(500);
-                } catch (InterruptedException e) {
-                    e.printStackTrace();
+            /*
+             * final Object lock = new Object(); synchronized (lock) { try { lock.wait(500); } catch (final
+             * InterruptedException e) { e.printStackTrace(); } }
+             */
+            writeScreenshot(fileName, format);
+            DialogUtil.showInfoDialog(this.frame, "Screenshot Saved", "Screenshot was saved to file" + '\n' + fileName);
+            LOGGER.info("saved screenshot to " + fileName);
+        }
+    }
+
+    /**
+     * Save current settings to a file using a file chooser.
+     */
+    private void saveSettings() {
+        final JFileChooser fc = new JFileChooser();
+        fc.setDialogTitle("Save Configuration");
+        fc.setCurrentDirectory(new File("."));
+        final int r = fc.showSaveDialog(this.frame);
+        if (r == JFileChooser.APPROVE_OPTION) {
+            final File f = fc.getSelectedFile();
+            this.configurationModel.getConfiguration().writeToFile(f);
+            LOGGER.info("saved configuration to file: " + f.getPath());
+            DialogUtil.showInfoDialog(this.frame, "Settings Saved", "Settings were saved successfully.");
+        }
+    }
+
+    /**
+     * Export a JTable's data to a comma-delimited text file using a file chooser.
+     *
+     * @param table the table to export
+     */
+    private void saveTable(final JTable table) {
+        final JFileChooser fc = new JFileChooser();
+        fc.setDialogTitle("Save Table to Text File");
+        fc.setCurrentDirectory(new File("."));
+        final int r = fc.showSaveDialog(this.frame);
+        if (r == JFileChooser.APPROVE_OPTION) {
+            final String fileName = fc.getSelectedFile().getPath();
+            try {
+                TableExporter.export(table, fileName, ',');
+                LOGGER.info("saved table data to " + fileName);
+                DialogUtil.showInfoDialog(this.frame, "Table Data Saved", "The table was exported successfully.");
+            } catch (final IOException e) {
+                DialogUtil.showErrorDialog(this.frame, "Table Export Error", "The table export failed.");
+                LOGGER.warning("failed to save table data to " + fileName);
+            }
+        }
+    }
+
+    /**
+     * Set the log level from the configuration model.
+     */
+    private void setLogLevel() {
+        final Level newLevel = this.configurationModel.getLogLevel();
+        if (LOGGER.getLevel() != newLevel) {
+            LOGGER.setLevel(newLevel);
+            LOGGER.log(Level.INFO, "Log Level was changed to <" + this.configurationModel.getLogLevel().toString()
+                    + ">");
+        }
+    }
+
+    /**
+     * Setup AIDA plotting into the GUI components.
+     */
+    private void setupAida() {
+        // Register the factory for displaying plots in tabs.
+        MonitoringAnalysisFactory.register();
+
+        // Set the root tab pane for displaying plots.
+        MonitoringPlotFactory.setRootPane(this.frame.getPlotPanel().getPlotPane());
+
+        // Setup the region listener to connect the plot info window.
+        MonitoringPlotFactory.setPlotterRegionListener(new PlotterRegionListener() {
+            @Override
+            public void regionSelected(final PlotterRegion region) {
+                if (region != null) {
+                    MonitoringApplication.this.frame.getPlotInfoPanel().setCurrentRegion(region);
                 }
             }
-            writeScreenshot(fileName, format);
-            DialogUtil.showInfoDialog(frame, "Screenshot Saved", "Screenshot was saved to file" + '\n' + fileName);
-            logger.info("saved screenshot to " + fileName);
-        }
+        });
+
+        // Perform global configuration of the JFreeChart back end.
+        AnalysisFactory.configure();
+    }
+
+    /**
+     * Setup the logger.
+     */
+    private void setupLogger() {
+        LOGGER.setUseParentHandlers(false);
+        this.logHandler = new LogHandler();
+        LOGGER.addHandler(this.logHandler);
+        this.streamHandler = new MonitoringApplicationStreamHandler(System.out);
+        LOGGER.addHandler(this.streamHandler);
+        for (final Handler handler : LOGGER.getHandlers()) {
+            handler.setLevel(DEFAULT_LEVEL);
+        }
+        LOGGER.setLevel(DEFAULT_LEVEL);
+        LOGGER.info("logging initialized");
+    }
+
+    /**
+     * Configure the system status monitor panel for a new job.
+     */
+    private void setupSystemStatusMonitor() {
+
+        // Clear the system status monitor table.
+        this.frame.getSystemStatusPanel().clear();
+
+        // Get the global registry of SystemStatus objects.
+        final SystemStatusRegistry registry = SystemStatusRegistry.getSystemStatusRegistery();
+
+        // Process the SystemStatus objects.
+        for (final SystemStatus systemStatus : registry.getSystemStatuses()) {
+            // This will add the status to the two tables.
+            this.frame.getSystemStatusPanel().addSystemStatus(systemStatus);
+        }
+
+        LOGGER.info("system status monitor initialized successfully");
+    }
+
+    /**
+     * Show the settings dialog window.
+     */
+    private void showSettingsDialog() {
+        this.frame.getSettingsDialog().setVisible(true);
+    }
+
+    /**
+     * Start the AIDA server instance.
+     */
+    private void startAIDAServer() {
+        if (this.configurationModel.hasValidProperty(ConfigurationModel.AIDA_SERVER_NAME_PROPERTY)) {
+            this.server.setName(this.configurationModel.getAIDAServerName());
+        }
+        final boolean started = this.server.start();
+        if (started) {
+            this.frame.getApplicationMenu().startAIDAServer();
+            LOGGER.info("AIDA server started at " + this.server.getName());
+            DialogUtil
+                    .showInfoDialog(this.frame, "AIDA Server Started", "The remote AIDA server started successfully.");
+        } else {
+            LOGGER.warning("AIDA server failed to start");
+            DialogUtil.showErrorDialog(this.frame, "Failed to Start AIDA Server",
+                    "The remote AIDA server failed to start.");
+        }
+    }
+
+    /**
+     * Start a new monitoring session.
+     */
+    private synchronized void startSession() {
+
+        LOGGER.info("starting new session");
+
+        try {
+
+            // Reset the plot panel and global AIDA state.
+            resetPlots();
+
+            // The system status registry is cleared here before any event processors
+            // which might create a SystemStatus are added to the event processing chain
+            // e.g. an LCSim Driver, etc.
+            SystemStatusRegistry.getSystemStatusRegistery().clear();
+
+            // List of extra composite record processors including the updater for the RunPanel.
+            final List<CompositeRecordProcessor> processors = new ArrayList<CompositeRecordProcessor>();
+            processors.add(this.frame.getEventDashboard().new EventDashboardUpdater());
+
+            // Add Driver to update the trigger diagnostics tables.
+            final List<Driver> drivers = new ArrayList<Driver>();
+            drivers.add(this.frame.getTriggerPanel().new TriggerDiagnosticGUIDriver());
+
+            // Add listener to push conditions changes to conditions panel.
+            final List<ConditionsListener> conditionsListeners = new ArrayList<ConditionsListener>();
+            conditionsListeners.add(this.frame.getConditionsPanel().new ConditionsPanelListener());
+
+            // Instantiate the event processing wrapper.
+            this.processing = new EventProcessing(this, processors, drivers, conditionsListeners);
+
+            // Connect to the ET system, if applicable.
+            this.processing.connect();
+
+            // Configure event processing from the global application settings, including setup of record loop.
+            LOGGER.info("setting up event processing on source " + this.configurationModel.getDataSourcePath()
+                    + " with type " + this.configurationModel.getDataSourceType());
+            this.processing.setup(this.configurationModel);
+
+            // Setup the system status monitor table.
+            setupSystemStatusMonitor();
+
+            // Start the event processing thread.
+            this.processing.start();
+
+            LOGGER.info("new session successfully initialized");
+
+        } catch (final Exception e) {
+
+            // Disconnect from the ET system.
+            this.processing.disconnect();
+
+            // Log the error that occurred and show a pop up dialog.
+            this.errorHandler
+                    .setError(e)
+                    .log()
+                    .printStackTrace()
+                    .showErrorDialog(
+                            "There was an error while starting the session." + '\n' + "See the log for details.",
+                            "Session Error");
+
+            LOGGER.severe("failed to start new session");
+        }
+    }
+
+    /**
+     * Stop the AIDA server instance.
+     */
+    private void stopAIDAServer() {
+        this.server.disconnect();
+        this.frame.getApplicationMenu().stopAIDAServer();
+        LOGGER.info("AIDA server was stopped");
+        DialogUtil.showInfoDialog(this.frame, "AIDA Server Stopped", "The AIDA server was stopped.");
     }
 
     /**
      * Save a screenshot to an output file.
-     * @param fileName The name of the output file.
-     */
-    void writeScreenshot(String fileName, String format) {
-        BufferedImage image = new BufferedImage(frame.getWidth(), frame.getHeight(), BufferedImage.TYPE_INT_RGB);
-        frame.paint(image.getGraphics()); 
+     *
+     * @param fileName the name of the output file
+     * @param format the output file format (must be accepted by <code>ImageIO</code>)
+     */
+    private void writeScreenshot(final String fileName, final String format) {
+        this.frame.repaint();
+        final BufferedImage image = new BufferedImage(this.frame.getWidth(), this.frame.getHeight(),
+                BufferedImage.TYPE_INT_RGB);
+        this.frame.paint(image.getGraphics());
         try {
             ImageIO.write(image, format, new File(fileName));
-        } catch (IOException e) {
-            errorHandler.setError(e).setMessage("Failed to save screenshot.").printStackTrace().log().showErrorDialog();
-        }        
-    }            
-    
-    /**
-     * Set the log level from the configuration model.
-     */
-    void setLogLevel() {
-        Level newLevel = configurationModel.getLogLevel();
-        if (logger.getLevel() != newLevel) {
-            logger.setLevel(newLevel);
-            logger.log(Level.INFO, "Log Level was changed to <" + configurationModel.getLogLevel().toString() + ">");
-        }
-    }      
-    
-    /**
-     * Export a JTable's data to a comma-delimited text file using a file chooser.
-     */
-    void saveTable(JTable table) {
-        JFileChooser fc = new JFileChooser();
-        fc.setDialogTitle("Save Table to Text File");
-        fc.setCurrentDirectory(new File("."));
-        int r = fc.showSaveDialog(frame);
-        if (r == JFileChooser.APPROVE_OPTION) {            
-            String fileName = fc.getSelectedFile().getPath();
-            try {
-                TableExporter.export(table, fileName, ',');
-                logger.info("saved table data to " + fileName);
-                DialogUtil.showInfoDialog(frame, "Table Data Saved", "The table was exported successfully.");
-            } catch (IOException e) {
-                DialogUtil.showErrorDialog(frame, "Table Export Error", "The table export failed.");
-                logger.warning("failed to save table data to " + fileName);
-            }                        
-        }
-    }
-    
-    /**
-     * Save the log table to a file using a file chooser.
-     */
-    void saveLogTable() {
-        saveTable(frame.logPanel.logTable);
-    }
-        
-    /**
-     * Redirect <code>System.out</code> and <code>System.err</code> to file chosen
-     * by a file chooser.
-     */
-    void chooseLogFile() {
-        JFileChooser fc = new JFileChooser();
-        fc.setAcceptAllFileFilterUsed(false);
-        fc.setDialogTitle("Save Log Messages to File");       
-        fc.setCurrentDirectory(new File("."));
-        int r = fc.showSaveDialog(frame);
-        if (r == JFileChooser.APPROVE_OPTION) {            
-            String fileName = fc.getSelectedFile().getPath();
-            if (new File(fileName).exists()) {
-                DialogUtil.showErrorDialog(frame, "File Exists", "File already exists.");
-            } else {
-                logToFile(new File(fileName));
-            }
-        }        
-    }
-    
-    /**
-     * Redirect <code>System.out</code> and <code>System.err</code> to a file.
-     * @param file The output log file.
-     * @throws FileNotFoundException if the file does not exist.
-     */
-    void logToFile(File file) {
-        try {
-            
-            // Create the output file stream.
-            PrintStream fileStream = new PrintStream(new FileOutputStream(file.getPath()));
-            System.setOut(fileStream);
-            System.setErr(fileStream);
-            
-            // Flush the current handler, but do NOT close here or System.out gets clobbered!
-            streamHandler.flush();
-            
-            // Replace the current handler with one using the file stream.
-            logger.removeHandler(streamHandler);
-            streamHandler = new MonitoringApplicationStreamHandler(fileStream);
-            streamHandler.setLevel(logger.getLevel());
-            logger.addHandler(streamHandler);
-            
-            // Set the properties on the model.
-            configurationModel.setLogFileName(file.getPath());
-            configurationModel.setLogToFile(true);
-            
-            logger.info("Saving log messages to " + configurationModel.getLogFileName());
-            DialogUtil.showInfoDialog(frame, "Logging to File", 
-                    "Log messages redirected to file" + '\n' + configurationModel.getLogFileName());
-            
-        } catch (FileNotFoundException e) {
-            errorHandler.setError(e).log().showErrorDialog();
-        }
-    }      
-    
-    /**
-     * Send <code>System.out</code> and <code>System.err</code> back to the terminal, 
-     * e.g. if they were previously sent to a file.
-     */
-    void logToTerminal() {
-        
-        // Reset System.out and err back to original streams.
-        System.setOut(sysOut);
-        System.setErr(sysErr);
-        
-        // Flush and close the current handler, which is using a file stream.
-        streamHandler.flush();
-        streamHandler.close();
-        
-        // Replace the handler with the one printing to the terminal.
-        logger.removeHandler(streamHandler);               
-        streamHandler = new MonitoringApplicationStreamHandler(System.out);
-        streamHandler.setLevel(logger.getLevel());
-        logger.addHandler(streamHandler);
-        
-        logger.log(Level.INFO, "log messages redirected to terminal");
-        
-        // Update the model to indicate logging to file has been disabled.
-        configurationModel.setLogToFile(false);
-        
-        DialogUtil.showInfoDialog(frame, "Log to Terminal", "Log messages will be sent to the terminal.");
-    }    
-    
-    /**
-     * Start the AIDA server instance.
-     */
-    void startAIDAServer() {
-        if (configurationModel.hasValidProperty(ConfigurationModel.AIDA_SERVER_NAME_PROPERTY)) {
-            server.setName(configurationModel.getAIDAServerName());
-        }
-        boolean started = server.start();
-        if (started) {
-            frame.menu.startAIDAServer();
-            logger.info("AIDA server started at " + server.getName());
-            DialogUtil.showInfoDialog(frame, "AIDA Server Started", "The remote AIDA server started successfully.");
-        } else {
-            logger.warning("AIDA server failed to start");
-            DialogUtil.showErrorDialog(frame, "Failed to Start AIDA Server", "The remote AIDA server failed to start.");
-        }
-    }
-    
-    /**
-     * Stop the AIDA server instance.
-     */
-    void stopAIDAServer() {
-        server.disconnect();
-        frame.menu.stopAIDAServer();
-        logger.info("AIDA server was stopped");
-        DialogUtil.showInfoDialog(frame, "AIDA Server Stopped", "The AIDA server was stopped.");
-    }    
-    
-    /**
-     * Run the disconnection on a separate thread.
-     */
-    void runDisconnectThread() {
-        new Thread() {
-            public void run() {
-                logger.fine("disconnect thread is running ...");
-                connectionModel.setConnectionStatus(ConnectionStatus.DISCONNECTING);
-                MonitoringApplication.this.processing.stop();
-                logger.fine("disconnect thread finished!");
-            }
-        }.run();
-    }
-}
+        } catch (final IOException e) {
+            this.errorHandler.setError(e).setMessage("Failed to save screenshot.").printStackTrace().log()
+                    .showErrorDialog();
+        }
+    }
+}

Modified: java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/MonitoringApplicationFrame.java
 =============================================================================
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/MonitoringApplicationFrame.java	(original)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/MonitoringApplicationFrame.java	Thu Apr  9 19:22:57 2015
@@ -2,6 +2,7 @@
 
 import java.awt.BorderLayout;
 import java.awt.Dimension;
+import java.awt.Frame;
 import java.awt.GraphicsEnvironment;
 import java.awt.Rectangle;
 
@@ -12,132 +13,283 @@
 
 /**
  * This class instantiates the primary GUI components of the monitoring application.
- * 
- * @author Jeremy McCormick <[log in to unmask]>
+ *
+ * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a>
  */
 @SuppressWarnings("serial")
-class MonitoringApplicationFrame extends JFrame {
-            
-    EventDashboard dashboardPanel;    
-    PlotPanel plotPanel;
-    PlotInfoPanel plotInfoPanel;
-    LogPanel logPanel;
-    TriggerDiagnosticsPanel triggerPanel;
-    ConditionsPanel conditionsPanel;
-    SystemStatusPanel systemStatusPanel;
-    ToolbarPanel toolbarPanel;
-    MenuBar menu; 
-    
-    JSplitPane mainSplitPane;
-    JSplitPane rightSplitPane;
-    JSplitPane leftSplitPane;
-        
-    SettingsDialog settingsDialog;
-       
-    static final Rectangle BOUNDS = GraphicsEnvironment.getLocalGraphicsEnvironment().getMaximumWindowBounds();
-    static final int PIXEL_WIDTH_MAX = (int) BOUNDS.getWidth();
-    static final int PIXEL_HEIGHT_MAX = (int) BOUNDS.getHeight();
-    
-    /**
-     * 
-     * @param listener
-     */
-    public MonitoringApplicationFrame(
-            MonitoringApplication application) {
-        
+final class MonitoringApplicationFrame extends JFrame {
+
+    /**
+     * The current graphics bounds.
+     */
+    private static final Rectangle BOUNDS = GraphicsEnvironment.getLocalGraphicsEnvironment().getMaximumWindowBounds();
+
+    /**
+     * The maximum height of a window in pixels.
+     */
+    private static final int PIXEL_HEIGHT_MAX = (int) BOUNDS.getHeight();
+
+    /**
+     * The maximum width of a window in pixels.
+     */
+    private static final int PIXEL_WIDTH_MAX = (int) BOUNDS.getWidth();
+
+    /**
+     * The conditions panel.
+     */
+    private final ConditionsPanel conditionsPanel;
+
+    /**
+     * The dashboard panel.
+     */
+    private final EventDashboard dashboardPanel;
+
+    /**
+     * The left split pane that divides the dashboard and the tabs.
+     */
+    private final JSplitPane leftSplitPane;
+
+    /**
+     * The log panel.
+     */
+    private final LogPanel logPanel;
+
+    /**
+     * The primary split pain dividing the left and right panels.
+     */
+    private final JSplitPane mainSplitPane;
+
+    /**
+     * The application's menu bar.
+     */
+    private final MenuBar menu;
+
+    /**
+     * The plot info panel.
+     */
+    private final PlotInfoPanel plotInfoPanel;
+
+    /**
+     * The plot panel.
+     */
+    private final PlotPanel plotPanel;
+
+    /**
+     * The right split pane showing plots and statistics.
+     */
+    private final JSplitPane rightSplitPane;
+
+    /**
+     * The settings dialog window.
+     */
+    private final SettingsDialog settingsDialog;
+
+    /**
+     * The system status panel which shows under the tabs.
+     */
+    private final SystemStatusPanel systemStatusPanel;
+
+    /**
+     * The toolbar panel with the buttons, data source and connection information.
+     */
+    private final ToolbarPanel toolbarPanel;
+
+    /**
+     * The trigger diagnostics panel.
+     */
+    private final TriggerDiagnosticsPanel triggerPanel;
+
+    /**
+     * Class constructor.
+     *
+     * @param application the associated application object
+     */
+    public MonitoringApplicationFrame(final MonitoringApplication application) {
+
         // Disable interaction until specifically enabled externally after initialization.
         setEnabled(false);
-                
+
         // Create the content panel.
-        JPanel contentPanel = new JPanel();
+        final JPanel contentPanel = new JPanel();
         setContentPane(contentPanel);
         contentPanel.setLayout(new BorderLayout());
         contentPanel.setOpaque(true);
         contentPanel.setPreferredSize(new Dimension(PIXEL_WIDTH_MAX, PIXEL_HEIGHT_MAX));
-                
+
         // Create the top panel.
-        toolbarPanel = new ToolbarPanel(application.configurationModel, application.connectionModel, application);        
-        contentPanel.add(toolbarPanel, BorderLayout.NORTH);
-                        
+        this.toolbarPanel = new ToolbarPanel(application.getConfigurationModel(), application.getConnectionModel(),
+                application);
+        contentPanel.add(this.toolbarPanel, BorderLayout.NORTH);
+
         // Create the bottom panel.
-        JPanel bottomPanel = new JPanel();
+        final JPanel bottomPanel = new JPanel();
         bottomPanel.setLayout(new BorderLayout());
         contentPanel.add(bottomPanel, BorderLayout.CENTER);
-                                        
+
         // Create the left panel.
-        JPanel leftPanel = new JPanel();
+        final JPanel leftPanel = new JPanel();
         leftPanel.setLayout(new BorderLayout());
-                            
+
         // Create the run dashboard.
-        dashboardPanel = new EventDashboard(application.runModel);
+        this.dashboardPanel = new EventDashboard(application.getRunModel());
 
         // Create the tabbed pane for content in bottom of left panel such as log table and system monitor.
-        JTabbedPane tableTabbedPane = new JTabbedPane();
-        
+        final JTabbedPane tableTabbedPane = new JTabbedPane();
+
         // Create the log table and add it to the tabs.
-        logPanel = new LogPanel(application.configurationModel, application);
-        tableTabbedPane.addTab("Log Messages", logPanel);
-        
+        this.logPanel = new LogPanel(application.getConfigurationModel(), application);
+        tableTabbedPane.addTab("Log Messages", this.logPanel);
+
         // Create the system monitor.
-        //systemStatusTable = new SystemStatusTable();
-        systemStatusPanel = new SystemStatusPanel();
-        tableTabbedPane.addTab("System Status Monitor", systemStatusPanel);
-        
+        // systemStatusTable = new SystemStatusTable();
+        this.systemStatusPanel = new SystemStatusPanel();
+        tableTabbedPane.addTab("System Status Monitor", this.systemStatusPanel);
+
         // Add the trigger diagnostics tables.
-        triggerPanel = new TriggerDiagnosticsPanel();
-        tableTabbedPane.addTab("Trigger Diagnostics", triggerPanel);
-        
+        this.triggerPanel = new TriggerDiagnosticsPanel();
+        tableTabbedPane.addTab("Trigger Diagnostics", this.triggerPanel);
+
         // Add the conditions panel.
-        conditionsPanel = new ConditionsPanel();
-        tableTabbedPane.addTab("Detector Conditions", conditionsPanel);
-        
+        this.conditionsPanel = new ConditionsPanel();
+        tableTabbedPane.addTab("Detector Conditions", this.conditionsPanel);
+
         // Vertical split pane in left panel.
-        leftSplitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, dashboardPanel, tableTabbedPane);
-        leftSplitPane.setDividerLocation(250);
-        leftPanel.add(leftSplitPane, BorderLayout.CENTER);
-                                
+        this.leftSplitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, this.dashboardPanel, tableTabbedPane);
+        this.leftSplitPane.setDividerLocation(250);
+        leftPanel.add(this.leftSplitPane, BorderLayout.CENTER);
+
         // Create the right panel.
-        JPanel rightPanel = new JPanel();
+        final JPanel rightPanel = new JPanel();
         rightPanel.setLayout(new BorderLayout());
-                
+
         // Create the plot info panel.
-        plotInfoPanel = new PlotInfoPanel();
-                
+        this.plotInfoPanel = new PlotInfoPanel();
+
         // Create the plot panel.
-        plotPanel = new PlotPanel();        
-        plotInfoPanel.saveButton.addActionListener(plotPanel);
-        
+        this.plotPanel = new PlotPanel();
+        this.plotInfoPanel.saveButton.addActionListener(this.plotPanel);
+
         // Create the right panel vertical split pane for displaying plots and their information and statistics.
-        rightSplitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, plotPanel, plotInfoPanel);
-        rightSplitPane.setDividerLocation(680);
-        rightPanel.add(rightSplitPane, BorderLayout.CENTER);
-                       
+        this.rightSplitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, this.plotPanel, this.plotInfoPanel);
+        this.rightSplitPane.setDividerLocation(680);
+        rightPanel.add(this.rightSplitPane, BorderLayout.CENTER);
+
         // Create the main horizontal split pane for dividing the left and right panels.
-        mainSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, leftPanel, rightPanel);
-        mainSplitPane.setDividerLocation(600);
-        bottomPanel.add(mainSplitPane, BorderLayout.CENTER);
-        
+        this.mainSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, leftPanel, rightPanel);
+        this.mainSplitPane.setDividerLocation(600);
+        bottomPanel.add(this.mainSplitPane, BorderLayout.CENTER);
+
         // Create the menu bar.
-        menu = new MenuBar(application.configurationModel, application.connectionModel, application);
-        setJMenuBar(menu);
-        toolbarPanel.dataSourceComboBox.addActionListener(menu);
-        
+        this.menu = new MenuBar(application.getConfigurationModel(), application.getConnectionModel(), application);
+        setJMenuBar(this.menu);
+        this.toolbarPanel.getDataSourceComboBox().addActionListener(this.menu);
+
         // Setup the settings dialog box (invisible until activated).
-        settingsDialog = new SettingsDialog(application.configurationModel, application);        
-               
-        // Setup the frame now that all components have been added.        
+        this.settingsDialog = new SettingsDialog(application.getConfigurationModel(), application);
+
+        // Setup the frame now that all components have been added.
         pack();
-        setExtendedState(JFrame.MAXIMIZED_BOTH);
-        setVisible(true); 
-    }
-             
+        setExtendedState(Frame.MAXIMIZED_BOTH);
+        setVisible(true);
+    }
+
+    /**
+     * Get the application menu.
+     *
+     * @return the application menu
+     */
+    MenuBar getApplicationMenu() {
+        return this.menu;
+    }
+
+    /**
+     * Get the panel showing conditions information.
+     *
+     * @return the conditions panel
+     */
+    ConditionsPanel getConditionsPanel() {
+        return this.conditionsPanel;
+    }
+
+    /**
+     * Get the panel for the dashboard.
+     *
+     * @return the dashboard panel
+     */
+    EventDashboard getEventDashboard() {
+        return this.dashboardPanel;
+    }
+
+    /**
+     * Get the panel that shows the log table and controls.
+     *
+     * @return the log panel
+     */
+    LogPanel getLogPanel() {
+        return this.logPanel;
+    }
+
+    /**
+     * Get the plot info panel that shows plot statistics.
+     *
+     * @return the plot info panel
+     */
+    PlotInfoPanel getPlotInfoPanel() {
+        return this.plotInfoPanel;
+    }
+
+    /**
+     * Get the plot panel for displaying AIDA plots.
+     *
+     * @return the plot panel
+     */
+    PlotPanel getPlotPanel() {
+        return this.plotPanel;
+    }
+
+    /**
+     * Get the settings dialog window.
+     *
+     * @return the settings dialog window
+     */
+    SettingsDialog getSettingsDialog() {
+        return this.settingsDialog;
+    }
+
+    /**
+     * Get the system status panel.
+     *
+     * @return the system status panel
+     */
+    SystemStatusPanel getSystemStatusPanel() {
+        return this.systemStatusPanel;
+    }
+
+    /**
+     * Get the toolbar panel with the buttons etc.
+     *
+     * @return the toolbar panel
+     */
+    ToolbarPanel getToolbarPanel() {
+        return this.toolbarPanel;
+    }
+
+    /**
+     * Get the trigger diagnostics panel.
+     *
+     * @return the trigger diagnostics panel
+     */
+    TriggerDiagnosticsPanel getTriggerPanel() {
+        return this.triggerPanel;
+    }
+
     /**
      * Restore default window settings.
      */
     void restoreDefaults() {
-        setExtendedState(JFrame.MAXIMIZED_BOTH);
-        mainSplitPane.resetToPreferredSizes();
-        leftSplitPane.resetToPreferredSizes();
-        rightSplitPane.resetToPreferredSizes();        
-    }    
-}
+        setExtendedState(Frame.MAXIMIZED_BOTH);
+        this.mainSplitPane.resetToPreferredSizes();
+        this.leftSplitPane.resetToPreferredSizes();
+        this.rightSplitPane.resetToPreferredSizes();
+    }
+}

Modified: java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/PlotInfoPanel.java
 =============================================================================
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/PlotInfoPanel.java	(original)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/PlotInfoPanel.java	Thu Apr  9 19:22:57 2015
@@ -38,26 +38,28 @@
 
 /**
  * <p>
- * This is a GUI component for showing the statistics and other information about an AIDA plot
- * when it is clicked on in the monitoring application.
+ * This is a GUI component for showing the statistics and other information about an AIDA plot when it is clicked on in
+ * the monitoring application.
  * <p>
  * The information in the table is updated dynamically via the <code>AIDAObserver</code> API on the AIDA object.
+ *
+ * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a>
  */
-class PlotInfoPanel extends JPanel implements AIDAListener, ActionListener, FunctionListener {
-
-    JComboBox<Object> plotComboBox;
+final class PlotInfoPanel extends JPanel implements AIDAListener, ActionListener, FunctionListener {
+
+    static final String[] COLUMN_NAMES = { "Field", "Value" };
+    static final int MAX_ROWS = 13;
+    static final int MIN_HEIGHT = 300;
+    static final int MIN_WIDTH = 400;
+
+    static final String PLOT_SELECTED = "PlotSelected";
+    Object currentObject;
+
+    PlotterRegion currentRegion;
     JTable infoTable = new JTable();
     DefaultTableModel model;
+    JComboBox<Object> plotComboBox;
     JButton saveButton;
-    
-    PlotterRegion currentRegion;
-    Object currentObject;
-    
-    static final int MAX_ROWS = 13;
-    static final int MIN_WIDTH = 400;
-    static final int MIN_HEIGHT = 300;
-    static final String[] COLUMN_NAMES = { "Field", "Value" };
-    static final String PLOT_SELECTED = "PlotSelected";
 
     Timer timer = new Timer();
 
@@ -66,39 +68,42 @@
      */
     @SuppressWarnings("unchecked")
     PlotInfoPanel() {
-                
+
         setLayout(new FlowLayout(FlowLayout.CENTER));
 
-        JPanel leftPanel = new JPanel();
+        final JPanel leftPanel = new JPanel();
         leftPanel.setLayout(new BoxLayout(leftPanel, BoxLayout.PAGE_AXIS));
         leftPanel.setPreferredSize(new Dimension(MIN_WIDTH, MIN_HEIGHT));
-        
-        Dimension filler = new Dimension(0, 10);
-        
+
+        final Dimension filler = new Dimension(0, 10);
+
         // Save button.
-        saveButton = new JButton("Save Current Plot Tab ...");
-        saveButton.setActionCommand(Commands.SAVE_SELECTED_PLOTS);
-        saveButton.setAlignmentX(CENTER_ALIGNMENT);
-        leftPanel.add(saveButton);
-        
+        this.saveButton = new JButton("Save Current Plot Tab ...");
+        this.saveButton.setActionCommand(Commands.SAVE_SELECTED_PLOTS);
+        this.saveButton.setAlignmentX(CENTER_ALIGNMENT);
+        leftPanel.add(this.saveButton);
+
         leftPanel.add(new Box.Filler(filler, filler, filler));
 
         // Combo box for selecting plotted object.
-        plotComboBox = new JComboBox<Object>() {
+        this.plotComboBox = new JComboBox<Object>() {
+            @Override
             public Dimension getMaximumSize() {
-                Dimension max = super.getMaximumSize();
+                final Dimension max = super.getMaximumSize();
                 max.height = getPreferredSize().height;
                 return max;
             }
         };
-        plotComboBox.setActionCommand(PLOT_SELECTED);
-        plotComboBox.setAlignmentX(CENTER_ALIGNMENT);
-        plotComboBox.setRenderer(new BasicComboBoxRenderer() {
+        this.plotComboBox.setActionCommand(PLOT_SELECTED);
+        this.plotComboBox.setAlignmentX(CENTER_ALIGNMENT);
+        this.plotComboBox.setRenderer(new BasicComboBoxRenderer() {
+            @Override
             @SuppressWarnings("rawtypes")
-            public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
+            public Component getListCellRendererComponent(final JList list, final Object value, final int index,
+                    final boolean isSelected, final boolean cellHasFocus) {
                 super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
                 if (value != null) {
-                    String title = getObjectTitle(value);
+                    final String title = getObjectTitle(value);
                     setText(value.getClass().getSimpleName() + " - " + title);
                 } else {
                     setText("Click on a plot region ...");
@@ -106,172 +111,103 @@
                 return this;
             }
         });
-        plotComboBox.addActionListener(this);
-        leftPanel.add(plotComboBox);
-        
+        this.plotComboBox.addActionListener(this);
+        leftPanel.add(this.plotComboBox);
+
         leftPanel.add(new Box.Filler(filler, filler, filler));
-        
+
         // Table with plot info.
-        String data[][] = new String[0][0];
-        model = new DefaultTableModel(data, COLUMN_NAMES);
-        model.setColumnIdentifiers(COLUMN_NAMES);
-        infoTable.setModel(model);
-        ((DefaultTableModel)infoTable.getModel()).setRowCount(MAX_ROWS);
-        infoTable.setAlignmentX(CENTER_ALIGNMENT);
-        leftPanel.add(infoTable);
-        
+        final String data[][] = new String[0][0];
+        this.model = new DefaultTableModel(data, COLUMN_NAMES);
+        this.model.setColumnIdentifiers(COLUMN_NAMES);
+        this.infoTable.setModel(this.model);
+        ((DefaultTableModel) this.infoTable.getModel()).setRowCount(MAX_ROWS);
+        this.infoTable.setAlignmentX(CENTER_ALIGNMENT);
+        leftPanel.add(this.infoTable);
+
         add(leftPanel);
     }
 
     /**
-     * This method will be called when the backing AIDA object is updated and a state change is
-     * fired via the <code>AIDAObservable</code> API. The table is updated to reflect the new state
-     * of the object.
-     * @param evt The EventObject pointing to the backing AIDA object.
+     * Implementation of <code>actionPerformed</code> to handle the selection of a new object from the combo box.
      */
     @Override
-    public void stateChanged(final EventObject evt) {
-               
-        // Make a timer task for running the update.
-        TimerTask task = new TimerTask() {
-            public void run() {
-                                
-                // Is the state change from the current AIDAObservable?
-                if (evt.getSource() != currentObject) {
-                    // Assume this means that a different AIDAObservable was selected in the GUI.
-                    return;
-                }
-
-                // Update the table values on the Swing EDT.
-                runUpdateTable();
-
-                // Set the observable to valid so subsequent state changes are received.
-                ((AIDAObservable) currentObject).setValid((AIDAListener) PlotInfoPanel.this);
-            }
-        };
-
-        /*
-         * Schedule the task to run in ~0.5 seconds. If the Runnable runs immediately, somehow the
-         * observable state gets permanently set to invalid and additional state changes will not be
-         * received!
-         */
-        timer.schedule(task, 500);
-    }
-
-    /**
-     * Implementation of <code>actionPerformed</code> to handle the selection of a new object from
-     * the combo box.
-     */
-    @Override
-    public void actionPerformed(ActionEvent e) {
+    public void actionPerformed(final ActionEvent e) {
         // Is there a new item selected in the combo box?
         if (PLOT_SELECTED.equals(e.getActionCommand())) {
-            if (plotComboBox.getSelectedItem() != null) {
+            if (this.plotComboBox.getSelectedItem() != null) {
                 // Set the current object from the combo box value, to update the GUI state.
-                setCurrentObject(plotComboBox.getSelectedItem());
-            }
-        }
-    }
-
-    /**
-     * Get the title of an AIDA object.  Unfortunately there is no base type with this information,
-     * so it is read manually from each possible type.
-     * @param object The AIDA object.
-     * @return The title of the object from its title method or value of its toString method, if
-     *         none exists.
-     */
-    String getObjectTitle(Object object) {
-        if (object instanceof IBaseHistogram) {
-            return ((IBaseHistogram) object).title();
-        } else if (object instanceof IDataPointSet) {
-            return ((IDataPointSet) object).title();
-        } else if (object instanceof IFunction) {
-            return ((IFunction) object).title();
-        } else {
-            return object.toString();
-        }
-    }
-
-    /**
-     * Set the current plotter region, which will rebuild the GUI accordingly.
-     * @param region The current plotter region.
-     */
-    synchronized void setCurrentRegion(PlotterRegion region) {
-        if (region != currentRegion) {
-            currentRegion = region;
-            updateComboBox();
-            setCurrentObject(plotComboBox.getSelectedItem());
-            setupContentPane();
-        }
-    }
-
-    /**
-     * Configure the frame's content panel from current component settings.
-     */
-    void setupContentPane() {
-        plotComboBox.setSize(plotComboBox.getPreferredSize());
-        infoTable.setSize(infoTable.getPreferredSize());
-        setVisible(true);
-    }
-
-    /**
-     * Update the info table from the state of the current AIDA object.
-     */
-    void updateTable() {
-        model.setRowCount(0);        
-        if (currentObject instanceof IHistogram1D) {
-            addRows((IHistogram1D) currentObject);
-        } else if (currentObject instanceof IHistogram2D) {
-            addRows((IHistogram2D) currentObject);
-        } else if (currentObject instanceof ICloud2D) {
-            addRows((ICloud2D) currentObject);
-        } else if (currentObject instanceof ICloud1D) {
-            if (((ICloud1D) currentObject).isConverted()) {
-                addRows(((ICloud1D) currentObject).histogram());
-            }
-        } else if (currentObject instanceof IFunction) {
-            addRows((IFunction) currentObject);
-        }
-    }
-
-    /**
-     * Run the {@link #updateTable()} method on the Swing EDT.
-     */
-    void runUpdateTable() {
-        SwingUtilities.invokeLater(new Runnable() {
-            public void run() {
-                updateTable();
-            }
-        });
-    }
-
-    /**
-     * Update the combo box contents with the plots from the current region.
-     */
-    void updateComboBox() {
-        plotComboBox.removeAllItems();
-        List<Object> objects = currentRegion.getPlottedObjects();
-        for (Object object : objects) {
-            if (isValidObject(object)) {
-                plotComboBox.addItem(object);
-            }
-        }
-    }
-
-    boolean isValidObject(Object object) {
-        if (object == null)
-            return false;
-        if (object instanceof IBaseHistogram || object instanceof IFunction || object instanceof IDataPointSet) {
-            return true;
-        } 
-        return false;
+                setCurrentObject(this.plotComboBox.getSelectedItem());
+            }
+        }
+    }
+
+    /**
+     * Add this object as an <code>AIDAListener</code> on the current <code>AIDAObservable</code>.
+     */
+    void addListener() {
+        if (this.currentObject instanceof AIDAObservable && !(this.currentObject instanceof FunctionDispatcher)) {
+            // Setup a listener on the current AIDA object.
+            final AIDAObservable observable = (AIDAObservable) this.currentObject;
+            observable.addListener(this);
+            observable.setValid(this);
+            observable.setConnected(true);
+        } else if (this.currentObject instanceof IFunction) {
+            if (this.currentObject instanceof FunctionDispatcher) {
+                ((FunctionDispatcher) this.currentObject).addFunctionListener(this);
+            }
+        }
+    }
+
+    /**
+     * Add a row to the info table.
+     *
+     * @param field The field name.
+     * @param value The field value.
+     */
+    void addRow(final String field, final Object value) {
+        this.model.insertRow(this.infoTable.getRowCount(), new Object[] { field, value });
+    }
+
+    /**
+     * Add rows to the info table from the state of a 2D cloud.
+     *
+     * @param cloud The AIDA object.
+     */
+    void addRows(final ICloud2D cloud) {
+        addRow("title", cloud.title());
+        addRow("entries", cloud.entries());
+        addRow("max entries", cloud.maxEntries());
+        addRow("x lower edge", cloud.lowerEdgeX());
+        addRow("x upper edge", cloud.upperEdgeX());
+        addRow("y lower edge", cloud.lowerEdgeY());
+        addRow("y upper edge", cloud.upperEdgeY());
+        addRow("x mean", String.format("%.10f%n", cloud.meanX()));
+        addRow("y mean", String.format("%.10f%n", cloud.meanY()));
+        addRow("x rms", String.format("%.10f%n", cloud.rmsX()));
+        addRow("y rms", String.format("%.10f%n", cloud.rmsY()));
+    }
+
+    /**
+     * Add rows to the info table from the state of a 2D cloud.
+     *
+     * @param cloud The AIDA object.
+     */
+    void addRows(final IFunction function) {
+        addRow("title", function.title());
+
+        // Add generically the values of all function parameters.
+        for (final String parameter : function.parameterNames()) {
+            addRow(parameter, function.parameter(parameter));
+        }
     }
 
     /**
      * Add rows to the info table from the state of a 1D histogram.
+     *
      * @param histogram The AIDA object.
      */
-    void addRows(IHistogram1D histogram) {
+    void addRows(final IHistogram1D histogram) {
         addRow("title", histogram.title());
         addRow("bins", histogram.axis().bins());
         addRow("entries", histogram.entries());
@@ -285,9 +221,10 @@
 
     /**
      * Add rows to the info table from the state of a 2D histogram.
+     *
      * @param histogram The AIDA object.
      */
-    void addRows(IHistogram2D histogram) {
+    void addRows(final IHistogram2D histogram) {
         addRow("title", histogram.title());
         addRow("x bins", histogram.xAxis().bins());
         addRow("y bins", histogram.yAxis().bins());
@@ -305,62 +242,95 @@
     }
 
     /**
-     * Add rows to the info table from the state of a 2D cloud.
-     * @param cloud The AIDA object.
-     */
-    void addRows(ICloud2D cloud) {
-        addRow("title", cloud.title());
-        addRow("entries", cloud.entries());
-        addRow("max entries", cloud.maxEntries());
-        addRow("x lower edge", cloud.lowerEdgeX());
-        addRow("x upper edge", cloud.upperEdgeX());
-        addRow("y lower edge", cloud.lowerEdgeY());
-        addRow("y upper edge", cloud.upperEdgeY());
-        addRow("x mean", String.format("%.10f%n", cloud.meanX()));
-        addRow("y mean", String.format("%.10f%n", cloud.meanY()));
-        addRow("x rms", String.format("%.10f%n", cloud.rmsX()));
-        addRow("y rms", String.format("%.10f%n", cloud.rmsY()));
-    }
-    
-    /**
-     * Add rows to the info table from the state of a 2D cloud.
-     * @param cloud The AIDA object.
-     */
-    void addRows(IFunction function) {
-        addRow("title", function.title());
-        
-        // Add generically the values of all function parameters.
-        for (String parameter : function.parameterNames()) {
-            addRow(parameter, function.parameter(parameter));
-        }
-    }
-    
-    /**
-     * Add a row to the info table.
-     * @param field The field name.
-     * @param value The field value.
-     */
-    void addRow(String field, Object value) {
-        model.insertRow(infoTable.getRowCount(), new Object[] { field, value });
+     * Callback for updating from changed to <code>IFunction</code> object.
+     *
+     * @param event The change event (unused in this method).
+     */
+    @Override
+    public void functionChanged(final FunctionChangedEvent event) {
+        try {
+            runUpdateTable();
+        } catch (final Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * Get the title of an AIDA object. Unfortunately there is no base type with this information, so it is read
+     * manually from each possible type.
+     *
+     * @param object The AIDA object.
+     * @return The title of the object from its title method or value of its toString method, if none exists.
+     */
+    String getObjectTitle(final Object object) {
+        if (object instanceof IBaseHistogram) {
+            return ((IBaseHistogram) object).title();
+        } else if (object instanceof IDataPointSet) {
+            return ((IDataPointSet) object).title();
+        } else if (object instanceof IFunction) {
+            return ((IFunction) object).title();
+        } else {
+            return object.toString();
+        }
+    }
+
+    boolean isValidObject(final Object object) {
+        if (object == null) {
+            return false;
+        }
+        if (object instanceof IBaseHistogram || object instanceof IFunction || object instanceof IDataPointSet) {
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Remove this as a listener on the current AIDA object.
+     */
+    void removeListener() {
+        if (this.currentObject != null) {
+            if (this.currentObject instanceof AIDAObservable && !(this.currentObject instanceof IFunction)) {
+                // Remove this object as an listener on the AIDA observable.
+                ((AIDAObservable) this.currentObject).removeListener(this);
+            } else if (this.currentObject instanceof FunctionDispatcher) {
+                // Remove this object as function listener.
+                ((FunctionDispatcher) this.currentObject).removeFunctionListener(this);
+            }
+        }
+    }
+
+    /**
+     * Run the {@link #updateTable()} method on the Swing EDT.
+     */
+    void runUpdateTable() {
+        SwingUtilities.invokeLater(new Runnable() {
+            @Override
+            public void run() {
+                updateTable();
+            }
+        });
     }
 
     /**
      * Set the current AIDA object that backs this GUI, i.e. an IHistogram1D etc.
+     *
      * @param object The backing AIDA object.
      */
-    synchronized void setCurrentObject(Object object) {
-        
-        if (object == null)
+    synchronized void setCurrentObject(final Object object) {
+
+        if (object == null) {
             throw new IllegalArgumentException("The object arg is null!");
-        
-        if (object == currentObject)
+        }
+
+        if (object == this.currentObject) {
             return;
+        }
 
         // Remove the AIDAListener from the previous object.
         removeListener();
 
         // Set the current object reference.
-        currentObject = object;
+        this.currentObject = object;
 
         // Update the table immediately with information from the current object.
         // We need to wait for this the first time, so we know the preferred size
@@ -372,47 +342,93 @@
     }
 
     /**
-     * Remove this as a listener on the current AIDA object.
-     */
-    void removeListener() {
-        if (currentObject != null) {
-            if (currentObject instanceof AIDAObservable && !(currentObject instanceof IFunction)) {
-                // Remove this object as an listener on the AIDA observable.
-                ((AIDAObservable) currentObject).removeListener(this);
-            } else if (currentObject instanceof FunctionDispatcher) {
-                // Remove this object as function listener.
-                ((FunctionDispatcher)currentObject).removeFunctionListener(this);
-            }
-        }
-    }
-
-    /**
-     * Add this object as an <code>AIDAListener</code> on the current <code>AIDAObservable</code>.
-     */
-    void addListener() {
-        if (currentObject instanceof AIDAObservable && !(currentObject instanceof FunctionDispatcher)) {
-            // Setup a listener on the current AIDA object.
-            AIDAObservable observable = (AIDAObservable) currentObject;
-            observable.addListener(this);
-            observable.setValid(this);
-            observable.setConnected(true);
-        } else if (currentObject instanceof IFunction) {
-            if (currentObject instanceof FunctionDispatcher) {
-                ((FunctionDispatcher)currentObject).addFunctionListener(this);
-            }
-        }
-    }
-
-    /**
-     * Callback for updating from changed to <code>IFunction</code> object.
-     * @param event The change event (unused in this method).
+     * Set the current plotter region, which will rebuild the GUI accordingly.
+     *
+     * @param region The current plotter region.
+     */
+    synchronized void setCurrentRegion(final PlotterRegion region) {
+        if (region != this.currentRegion) {
+            this.currentRegion = region;
+            updateComboBox();
+            setCurrentObject(this.plotComboBox.getSelectedItem());
+            setupContentPane();
+        }
+    }
+
+    /**
+     * Configure the frame's content panel from current component settings.
+     */
+    void setupContentPane() {
+        this.plotComboBox.setSize(this.plotComboBox.getPreferredSize());
+        this.infoTable.setSize(this.infoTable.getPreferredSize());
+        setVisible(true);
+    }
+
+    /**
+     * This method will be called when the backing AIDA object is updated and a state change is fired via the
+     * <code>AIDAObservable</code> API. The table is updated to reflect the new state of the object.
+     *
+     * @param evt The EventObject pointing to the backing AIDA object.
      */
     @Override
-    public void functionChanged(FunctionChangedEvent event) {
-        try {
-            runUpdateTable();
-        } catch (Exception e) {
-            e.printStackTrace();
+    public void stateChanged(final EventObject evt) {
+
+        // Make a timer task for running the update.
+        final TimerTask task = new TimerTask() {
+            @Override
+            public void run() {
+
+                // Is the state change from the current AIDAObservable?
+                if (evt.getSource() != PlotInfoPanel.this.currentObject) {
+                    // Assume this means that a different AIDAObservable was selected in the GUI.
+                    return;
+                }
+
+                // Update the table values on the Swing EDT.
+                runUpdateTable();
+
+                // Set the observable to valid so subsequent state changes are received.
+                ((AIDAObservable) PlotInfoPanel.this.currentObject).setValid(PlotInfoPanel.this);
+            }
+        };
+
+        /*
+         * Schedule the task to run in ~0.5 seconds. If the Runnable runs immediately, somehow the observable state gets
+         * permanently set to invalid and additional state changes will not be received!
+         */
+        this.timer.schedule(task, 500);
+    }
+
+    /**
+     * Update the combo box contents with the plots from the current region.
+     */
+    void updateComboBox() {
+        this.plotComboBox.removeAllItems();
+        final List<Object> objects = this.currentRegion.getPlottedObjects();
+        for (final Object object : objects) {
+            if (isValidObject(object)) {
+                this.plotComboBox.addItem(object);
+            }
+        }
+    }
+
+    /**
+     * Update the info table from the state of the current AIDA object.
+     */
+    void updateTable() {
+        this.model.setRowCount(0);
+        if (this.currentObject instanceof IHistogram1D) {
+            addRows((IHistogram1D) this.currentObject);
+        } else if (this.currentObject instanceof IHistogram2D) {
+            addRows((IHistogram2D) this.currentObject);
+        } else if (this.currentObject instanceof ICloud2D) {
+            addRows((ICloud2D) this.currentObject);
+        } else if (this.currentObject instanceof ICloud1D) {
+            if (((ICloud1D) this.currentObject).isConverted()) {
+                addRows(((ICloud1D) this.currentObject).histogram());
+            }
+        } else if (this.currentObject instanceof IFunction) {
+            addRows((IFunction) this.currentObject);
         }
     }
 }

Modified: java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/PlotPanel.java
 =============================================================================
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/PlotPanel.java	(original)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/PlotPanel.java	Thu Apr  9 19:22:57 2015
@@ -1,7 +1,6 @@
 package org.hps.monitoring.application;
 
 import hep.aida.IPlotter;
-import hep.aida.jfree.plotter.Plotter;
 
 import java.awt.BorderLayout;
 import java.awt.Component;
@@ -23,45 +22,25 @@
 
 /**
  * This is the panel containing the tabs with the monitoring plots.
- * @author Jeremy McCormick <[log in to unmask]>
+ *
+ * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a>
  */
-class PlotPanel extends JPanel implements ActionListener {
-    
-    private JTabbedPane plotPane;    
-    
+final class PlotPanel extends JPanel implements ActionListener {
+
+    private final JTabbedPane plotPane;
+
     public PlotPanel() {
         setLayout(new BorderLayout());
-        plotPane = new JTabbedPane();
-        plotPane.setPreferredSize(getPreferredSize());
-        add(plotPane, BorderLayout.CENTER);
-    }
-    
-    JTabbedPane getPlotPane() {
-        return plotPane;
+        this.plotPane = new JTabbedPane();
+        this.plotPane.setPreferredSize(getPreferredSize());
+        add(this.plotPane, BorderLayout.CENTER);
     }
 
-    /**
-     * Get the indices of the current selected tabs.
-     * @return The indices of the current tabs.
-     */
-    int[] getSelectedTabIndices() {
-        int[] indices = new int[2];
-        indices[0] = plotPane.getSelectedIndex();
-        Component component = plotPane.getSelectedComponent();
-        if (component instanceof JTabbedPane) {
-            indices[1] = ((JTabbedPane)component).getSelectedIndex();
-        } 
-        return indices;
-    }
-    
-    Component getSelectedTab() {
-        return ((JTabbedPane) plotPane.getSelectedComponent()).getSelectedComponent();
-    }
-    
-    public void actionPerformed(ActionEvent event) {
+    @Override
+    public void actionPerformed(final ActionEvent event) {
         if (event.getActionCommand().equals(Commands.SAVE_SELECTED_PLOTS)) {
-            int[] indices = getSelectedTabIndices();
-            IPlotter plotter = MonitoringPlotFactory.getPlotterRegistry().find(indices[0], indices[1]);
+            final int[] indices = getSelectedTabIndices();
+            final IPlotter plotter = MonitoringPlotFactory.getPlotterRegistry().find(indices[0], indices[1]);
             if (plotter != null) {
                 savePlotter(plotter);
             } else {
@@ -69,9 +48,36 @@
             }
         }
     }
-            
-    void savePlotter(IPlotter plotter) {
-        JFileChooser fc = new JFileChooser();
+
+    JTabbedPane getPlotPane() {
+        return this.plotPane;
+    }
+
+    Component getSelectedTab() {
+        return ((JTabbedPane) this.plotPane.getSelectedComponent()).getSelectedComponent();
+    }
+
+    /**
+     * Get the indices of the current selected tabs.
+     *
+     * @return The indices of the current tabs.
+     */
+    int[] getSelectedTabIndices() {
+        final int[] indices = new int[2];
+        indices[0] = this.plotPane.getSelectedIndex();
+        final Component component = this.plotPane.getSelectedComponent();
+        if (component instanceof JTabbedPane) {
+            indices[1] = ((JTabbedPane) component).getSelectedIndex();
+        }
+        return indices;
+    }
+
+    void reset() {
+        this.plotPane.removeAll();
+    }
+
+    void savePlotter(final IPlotter plotter) {
+        final JFileChooser fc = new JFileChooser();
         fc.setAcceptAllFileFilterUsed(false);
         fc.setDialogTitle("Save Plots - " + plotter.title());
         fc.setCurrentDirectory(new File("."));
@@ -79,25 +85,21 @@
         fc.setFileFilter(new FileNameExtensionFilter("PNG file", "png"));
         fc.addChoosableFileFilter(new FileNameExtensionFilter("JPG file", "jpg"));
         fc.addChoosableFileFilter(new FileNameExtensionFilter("GIF file", "gif"));
-        int r = fc.showSaveDialog(this);
-        if (r == JFileChooser.APPROVE_OPTION) {                        
+        final int r = fc.showSaveDialog(this);
+        if (r == JFileChooser.APPROVE_OPTION) {
             String path = fc.getSelectedFile().getPath();
-            FileNameExtensionFilter filter = (FileNameExtensionFilter) fc.getFileFilter();
+            final FileNameExtensionFilter filter = (FileNameExtensionFilter) fc.getFileFilter();
             if (!path.endsWith("." + filter.getExtensions()[0])) {
                 path += "." + filter.getExtensions()[0];
             }
-            BufferedImage image = ExportPdf.getImage(getSelectedTab());
+            final BufferedImage image = ExportPdf.getImage(getSelectedTab());
             try {
                 ImageIO.write(image, filter.getExtensions()[0], new File(path));
                 DialogUtil.showInfoDialog(this, "Plots Saved", "Plots from panel were saved to" + '\n' + path);
-            } catch (IOException e) {
+            } catch (final IOException e) {
                 e.printStackTrace();
                 DialogUtil.showErrorDialog(this, "Error Saving Plots", "There was an error saving the plots.");
             }
-        }        
+        }
     }
-    
-    void reset() {
-        plotPane.removeAll();        
-    }    
 }

Modified: java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/SettingsDialog.java
 =============================================================================
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/SettingsDialog.java	(original)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/SettingsDialog.java	Thu Apr  9 19:22:57 2015
@@ -9,21 +9,22 @@
 import org.hps.monitoring.application.model.ConfigurationModel;
 
 /**
- * The modal dialog for entering settings. It contains a <code>JPanel</code> with the different
- * settings sub-tabs.
+ * The modal dialog for entering settings. It contains a <code>JPanel</code> with the different settings sub-tabs.
+ *
+ * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a>
  */
-class SettingsDialog extends JDialog {
+final class SettingsDialog extends JDialog {
 
     final SettingsPanel settingsPanel;
 
-    public SettingsDialog(ConfigurationModel configurationModel, ActionListener listener) {
+    public SettingsDialog(final ConfigurationModel configurationModel, final ActionListener listener) {
 
         // Initialize the GUI panel.
-        settingsPanel = new SettingsPanel(this, configurationModel, listener);
-        
+        this.settingsPanel = new SettingsPanel(this, configurationModel, listener);
+
         // Configure the frame.
         setTitle("Settings");
-        setContentPane(settingsPanel);
+        setContentPane(this.settingsPanel);
         setResizable(false);
         setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
         setModalityType(ModalityType.APPLICATION_MODAL);
@@ -31,13 +32,15 @@
 
         // Add window listener for turning invisible when closing.
         addWindowListener(new WindowAdapter() {
-            public void windowClosing(WindowEvent e) {
+            @Override
+            public void windowClosing(final WindowEvent e) {
                 setVisible(false);
             }
-            
-            public void windowOpened(WindowEvent event) {
-                SettingsDialog.this.setLocationRelativeTo(null);                    
+
+            @Override
+            public void windowOpened(final WindowEvent event) {
+                SettingsDialog.this.setLocationRelativeTo(null);
             }
-        });        
+        });
     }
 }

Modified: java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/SettingsPanel.java
 =============================================================================
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/SettingsPanel.java	(original)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/SettingsPanel.java	Thu Apr  9 19:22:57 2015
@@ -16,44 +16,46 @@
 
 /**
  * The container component with the tabs that have job and connection settings.
+ *
+ * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a>
  */
-class SettingsPanel extends JPanel implements ActionListener {
+final class SettingsPanel extends JPanel implements ActionListener {
+
+    static final String OKAY_COMMAND = "settingsOkay";
+    ConnectionSettingsPanel connectionPanel;
+    JobSettingsPanel jobPanel;
+    JDialog parent;
 
     JTabbedPane tabs;
-    JobSettingsPanel jobPanel;
-    ConnectionSettingsPanel connectionPanel;
-    static final String OKAY_COMMAND = "settingsOkay";
 
-    JDialog parent;
-
-    SettingsPanel(JDialog parent, ConfigurationModel configurationModel, ActionListener listener) {
+    SettingsPanel(final JDialog parent, final ConfigurationModel configurationModel, final ActionListener listener) {
 
         this.parent = parent;
-        
-        connectionPanel = new ConnectionSettingsPanel();        
-        jobPanel = new JobSettingsPanel(configurationModel);
-        
+
+        this.connectionPanel = new ConnectionSettingsPanel();
+        this.jobPanel = new JobSettingsPanel(configurationModel);
+
         // Push configuration to sub-components.
-        connectionPanel.setConfigurationModel(configurationModel);
-        jobPanel.setConfigurationModel(configurationModel);
-        
+        this.connectionPanel.setConfigurationModel(configurationModel);
+        this.jobPanel.setConfigurationModel(configurationModel);
+
         // Add ActionListener to sub-components.
-        connectionPanel.addActionListener(listener);
-        jobPanel.addActionListener(listener);
-               
+        this.connectionPanel.addActionListener(listener);
+        this.jobPanel.addActionListener(listener);
+
         this.setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
 
-        tabs = new JTabbedPane();
-        tabs.addTab("Connection Settings", connectionPanel);
-        tabs.addTab("Job Settings", jobPanel);
-        add(tabs);
+        this.tabs = new JTabbedPane();
+        this.tabs.addTab("Connection Settings", this.connectionPanel);
+        this.tabs.addTab("Job Settings", this.jobPanel);
+        add(this.tabs);
 
-        JButton okayButton = new JButton("Okay");
+        final JButton okayButton = new JButton("Okay");
         okayButton.setActionCommand(OKAY_COMMAND);
         okayButton.addActionListener(this);
 
         add(Box.createRigidArea(new Dimension(1, 5)));
-        JPanel buttonsPanel = new JPanel();
+        final JPanel buttonsPanel = new JPanel();
         buttonsPanel.add(okayButton);
         buttonsPanel.setLayout(new FlowLayout());
         add(buttonsPanel);
@@ -61,9 +63,9 @@
     }
 
     @Override
-    public void actionPerformed(ActionEvent e) {
+    public void actionPerformed(final ActionEvent e) {
         if (e.getActionCommand().equals(OKAY_COMMAND)) {
-            parent.setVisible(false);
+            this.parent.setVisible(false);
         }
-    }    
+    }
 }

Modified: java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/SystemStatusEventsTable.java
 =============================================================================
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/SystemStatusEventsTable.java	(original)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/SystemStatusEventsTable.java	Thu Apr  9 19:22:57 2015
@@ -1,5 +1,5 @@
 /**
- * 
+ *
  */
 package org.hps.monitoring.application;
 
@@ -22,125 +22,130 @@
 
 /**
  * This is a table that shows every system status change in a different row.
- * 
- * @author Jeremy McCormick <[log in to unmask]>
+ *
+ * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a>
  */
-public class SystemStatusEventsTable extends JTable {
-    
+final class SystemStatusEventsTable extends JTable {
+
+    static class SystemStatusEventsTableModel extends DefaultTableModel implements SystemStatusListener {
+
+        Class<?>[] columnClasses = { Date.class, Subsystem.class, SystemStatus.class, String.class, String.class };
+
+        String[] columnNames = { "Date", "Subsystem", "Status Code", "Description", "Message" };
+        List<SystemStatus> statuses = new ArrayList<SystemStatus>();
+
+        SystemStatusEventsTableModel() {
+        }
+
+        /**
+         * Register the listener on this status.
+         *
+         * @param status The system status.
+         */
+        void addSystemStatus(final SystemStatus status) {
+            status.addListener(this);
+        }
+
+        public void clear() {
+            this.statuses.clear();
+            this.setRowCount(0);
+        }
+
+        @Override
+        public Class<?> getColumnClass(final int column) {
+            return this.columnClasses[column];
+        }
+
+        @Override
+        public int getColumnCount() {
+            return this.columnNames.length;
+        }
+
+        @Override
+        public String getColumnName(final int column) {
+            return this.columnNames[column];
+        }
+
+        @Override
+        public int getRowCount() {
+            if (this.statuses != null) {
+                return this.statuses.size();
+            } else {
+                return 0;
+            }
+        }
+
+        @Override
+        public Object getValueAt(final int row, final int column) {
+            final SystemStatus status = this.statuses.get(row);
+            switch (column) {
+            case 0:
+                return new Date(status.getLastChangedMillis());
+            case 1:
+                return status.getSubsystem();
+            case 2:
+                return status.getStatusCode();
+            case 3:
+                return status.getDescription();
+            case 4:
+                return status.getMessage();
+            default:
+                return null;
+            }
+        }
+
+        /**
+         * Update the table with status changes.
+         *
+         * @param status The system status.
+         */
+        @Override
+        public void statusChanged(final SystemStatus status) {
+            final SystemStatus newStatus = new SystemStatusImpl(status);
+            this.statuses.add(newStatus);
+            fireTableDataChanged();
+        }
+    }
+
     SystemStatusEventsTableModel tableModel = new SystemStatusEventsTableModel();
-    
+
     SystemStatusEventsTable() {
-        setModel(tableModel);
-        
+        setModel(this.tableModel);
+
         // Date formatting.
         getColumnModel().getColumn(0).setCellRenderer(new DefaultTableCellRenderer() {
 
             final SimpleDateFormat dateFormat = new SimpleDateFormat("MMMM-dd-yyyy HH:mm:ss.SSS");
 
             @Override
-            public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
+            public Component getTableCellRendererComponent(final JTable table, Object value, final boolean isSelected,
+                    final boolean hasFocus, final int row, final int column) {
                 if (value instanceof Date) {
-                    value = dateFormat.format(value);
+                    value = this.dateFormat.format(value);
                 }
                 return super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
             }
         });
-        
+
         // Rendering of system status cells using different background colors.
         getColumnModel().getColumn(2).setCellRenderer(new DefaultTableCellRenderer() {
 
             @Override
-            public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int col) {
+            public Component getTableCellRendererComponent(final JTable table, final Object value,
+                    final boolean isSelected, final boolean hasFocus, final int row, final int col) {
 
                 // Cells are by default rendered as a JLabel.
-                JLabel label = (JLabel) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, col);
+                final JLabel label = (JLabel) super.getTableCellRendererComponent(table, value, isSelected, hasFocus,
+                        row, col);
 
                 // Color code the cell by its status.
-                StatusCode statusCode = (StatusCode) value;
+                final StatusCode statusCode = (StatusCode) value;
                 label.setBackground(statusCode.getColor());
                 return label;
             }
         });
     }
-    
+
     void registerListener() {
     }
-    
-    static class SystemStatusEventsTableModel extends DefaultTableModel implements SystemStatusListener {
-        
-        List<SystemStatus> statuses = new ArrayList<SystemStatus>();
-        
-        String[] columnNames = { "Date", "Subsystem", "Status Code", "Description", "Message" };
-        Class<?>[] columnClasses = { Date.class, Subsystem.class, SystemStatus.class, String.class, String.class };
-
-        SystemStatusEventsTableModel() {
-        }
-        
-        @Override
-        public String getColumnName(int column) {
-            return columnNames[column];
-        }
-        
-        @Override
-        public Class<?> getColumnClass(int column) {
-            return columnClasses[column];
-        }
-
-        /**
-         * Update the table with status changes.
-         * @param status The system status.
-         */
-        @Override
-        public void statusChanged(SystemStatus status) {
-            SystemStatus newStatus = new SystemStatusImpl(status);
-            statuses.add(newStatus);
-            fireTableDataChanged();
-        }
-        
-        /**
-         * Register the listener on this status.
-         * @param status The system status.
-         */
-        void addSystemStatus(SystemStatus status) {
-            status.addListener(this);
-        }
-        
-        @Override
-        public int getColumnCount() {
-            return columnNames.length;
-        }
-        
-        @Override
-        public int getRowCount() {
-            if (statuses != null) {
-                return statuses.size();
-            } else {
-                return 0;
-            }
-        }
-        
-        @Override
-        public Object getValueAt(int row, int column) {
-            SystemStatus status = statuses.get(row);
-            switch (column) {
-                case 0:
-                    return new Date(status.getLastChangedMillis());
-                case 1:
-                    return status.getSubsystem();
-                case 2:
-                    return status.getStatusCode();
-                case 3:
-                    return status.getDescription();
-                case 4: 
-                    return status.getMessage();
-                default:
-                    return null;
-            }
-        }
-        
-        public void clear() {
-            this.statuses.clear();
-            this.setRowCount(0);
-        }
-    }    
 }

Modified: java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/SystemStatusPanel.java
 =============================================================================
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/SystemStatusPanel.java	(original)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/SystemStatusPanel.java	Thu Apr  9 19:22:57 2015
@@ -1,5 +1,5 @@
 /**
- * 
+ *
  */
 package org.hps.monitoring.application;
 
@@ -13,39 +13,35 @@
 import org.hps.monitoring.subsys.SystemStatus;
 
 /**
- * This is a panel showing the two tables for viewing the system statuses,
- * one showing the current state of all system status monitors and the other
- * all system status change events.
- * 
- * @author Jeremy McCormick <[log in to unmask]>
+ * This is a panel showing the two tables for viewing the system statuses, one showing the current state of all system
+ * status monitors and the other all system status change events.
+ *
+ * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a>
  */
-public class SystemStatusPanel extends JPanel {
-    
+final class SystemStatusPanel extends JPanel {
+
+    SystemStatusEventsTable eventsTable = new SystemStatusEventsTable();
     SystemStatusTable statusTable = new SystemStatusTable();
-    SystemStatusEventsTable eventsTable = new SystemStatusEventsTable();
-        
-    SystemStatusPanel() {         
+
+    SystemStatusPanel() {
         super(new BorderLayout());
-        JSplitPane splitPane = new JSplitPane(
-                JSplitPane.VERTICAL_SPLIT, 
-                new JScrollPane(statusTable), 
-                new JScrollPane(eventsTable));
+        final JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, new JScrollPane(this.statusTable),
+                new JScrollPane(this.eventsTable));
         splitPane.setDividerLocation(50);
-        add(splitPane,
-            BorderLayout.CENTER);
-    }   
-    
-    void addSystemStatus(SystemStatus status) {
+        add(splitPane, BorderLayout.CENTER);
+    }
+
+    void addSystemStatus(final SystemStatus status) {
         // Register listeners of table models on this status.
-        statusTable.getTableModel().addSystemStatus(status);        
-        eventsTable.tableModel.addSystemStatus(status);
+        this.statusTable.getTableModel().addSystemStatus(status);
+        this.eventsTable.tableModel.addSystemStatus(status);
     }
-    
+
     void clear() {
         // Clear the system status monitor table.
-        statusTable.getTableModel().clear();    
+        this.statusTable.getTableModel().clear();
 
         // Clear the system status events table.
-        ((SystemStatusEventsTableModel)eventsTable.getModel()).clear();
+        ((SystemStatusEventsTableModel) this.eventsTable.getModel()).clear();
     }
 }

Modified: java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/SystemStatusTable.java
 =============================================================================
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/SystemStatusTable.java	(original)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/SystemStatusTable.java	Thu Apr  9 19:22:57 2015
@@ -17,8 +17,55 @@
 
 /**
  * This table shows the current state of {@link org.hps.monitoring.subsys.SystemStatus} objects.
+ *
+ * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a>
  */
-class SystemStatusTable extends JTable {
+final class SystemStatusTable extends JTable {
+
+    /**
+     * Renders a button if the status is clearable.
+     */
+    private class ButtonRenderer extends JButton implements TableCellRenderer {
+
+        public ButtonRenderer(final String label) {
+            this.setText(label);
+        }
+
+        @Override
+        public Component getTableCellRendererComponent(final JTable table, final Object value,
+                final boolean isSelected, final boolean hasFocus, final int row, final int column) {
+            final boolean clearable = (Boolean) table.getModel().getValueAt(row, SystemStatusTableModel.CLEARABLE_COL);
+            if (clearable) {
+                return this;
+            } else {
+                return null;
+            }
+        }
+    }
+
+    /**
+     * Fires a mouse click event when the clear button is pressed, which in turn will activate the action event for the
+     * button. The <code>ActionListener</code> then sets the <code>StatusCode</code> to <code>CLEARED</code>.
+     */
+    private static class JTableButtonMouseListener extends MouseAdapter {
+        private final JTable table;
+
+        public JTableButtonMouseListener(final JTable table) {
+            this.table = table;
+        }
+
+        @Override
+        public void mouseClicked(final MouseEvent e) {
+            final int column = this.table.getColumnModel().getColumnIndexAtX(e.getX());
+            final int row = e.getY() / this.table.getRowHeight();
+            if (row < this.table.getRowCount() && row >= 0 && column < this.table.getColumnCount() && column >= 0) {
+                final Object value = this.table.getValueAt(row, column);
+                if (value instanceof JButton) {
+                    ((JButton) value).doClick();
+                }
+            }
+        }
+    }
 
     SystemStatusTable() {
 
@@ -28,31 +75,35 @@
         getColumnModel().getColumn(SystemStatusTableModel.STATUS_COL).setCellRenderer(new DefaultTableCellRenderer() {
 
             @Override
-            public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int col) {
+            public Component getTableCellRendererComponent(final JTable table, final Object value,
+                    final boolean isSelected, final boolean hasFocus, final int row, final int col) {
 
                 // Cells are by default rendered as a JLabel.
-                JLabel label = (JLabel) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, col);
+                final JLabel label = (JLabel) super.getTableCellRendererComponent(table, value, isSelected, hasFocus,
+                        row, col);
 
                 // Color code the cell by its status.
-                StatusCode statusCode = StatusCode.valueOf((String) value);
+                final StatusCode statusCode = StatusCode.valueOf((String) value);
                 label.setBackground(statusCode.getColor());
                 return label;
             }
         });
 
         // Date formatting for last changed.
-        getColumnModel().getColumn(SystemStatusTableModel.LAST_CHANGED_COL).setCellRenderer(new DefaultTableCellRenderer() {
+        getColumnModel().getColumn(SystemStatusTableModel.LAST_CHANGED_COL).setCellRenderer(
+                new DefaultTableCellRenderer() {
 
-            final SimpleDateFormat dateFormat = new SimpleDateFormat("MMMM-dd-yyyy HH:mm:ss.SSS");
+                    final SimpleDateFormat dateFormat = new SimpleDateFormat("MMMM-dd-yyyy HH:mm:ss.SSS");
 
-            @Override
-            public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
-                if (value instanceof Date) {
-                    value = dateFormat.format(value);
-                }
-                return super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
-            }
-        });
+                    @Override
+                    public Component getTableCellRendererComponent(final JTable table, Object value,
+                            final boolean isSelected, final boolean hasFocus, final int row, final int column) {
+                        if (value instanceof Date) {
+                            value = this.dateFormat.format(value);
+                        }
+                        return super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
+                    }
+                });
 
         // Button for clearing system statuses.
         getColumnModel().getColumn(SystemStatusTableModel.RESET_COL).setCellRenderer(new ButtonRenderer("Clear"));
@@ -73,46 +124,4 @@
     public SystemStatusTableModel getTableModel() {
         return (SystemStatusTableModel) getModel();
     }
-
-    /**
-     * Renders a button if the status is clearable.
-     */
-    private class ButtonRenderer extends JButton implements TableCellRenderer {
-
-        public ButtonRenderer(String label) {
-            this.setText(label);
-        }
-
-        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
-            boolean clearable = (Boolean) table.getModel().getValueAt(row, SystemStatusTableModel.CLEARABLE_COL);
-            if (clearable)
-                return this;
-            else
-                return null;
-        }
-    }
-
-    /**
-     * Fires a mouse click event when the clear button is pressed, which in turn will activate the
-     * action event for the button. The <code>ActionListener</code> then sets the
-     * <code>StatusCode</code> to <code>CLEARED</code>.
-     */
-    private static class JTableButtonMouseListener extends MouseAdapter {
-        private final JTable table;
-
-        public JTableButtonMouseListener(JTable table) {
-            this.table = table;
-        }
-
-        public void mouseClicked(MouseEvent e) {
-            int column = table.getColumnModel().getColumnIndexAtX(e.getX());
-            int row = e.getY() / table.getRowHeight();
-            if (row < table.getRowCount() && row >= 0 && column < table.getColumnCount() && column >= 0) {
-                Object value = table.getValueAt(row, column);
-                if (value instanceof JButton) {
-                    ((JButton) value).doClick();
-                }
-            }
-        }
-    }
 }

Modified: java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/ToolbarPanel.java
 =============================================================================
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/ToolbarPanel.java	(original)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/ToolbarPanel.java	Thu Apr  9 19:22:57 2015
@@ -13,21 +13,22 @@
 
 /**
  * A GUI component for the top-level toolbar of the monitoring app.
- * 
- * @author Jeremy McCormick <[log in to unmask]>
+ *
+ * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a>
  */
-public class ToolbarPanel extends JPanel {
+final class ToolbarPanel extends JPanel {
 
-    DataSourceComboBox dataSourceComboBox;
-    JPanel buttonsPanel;
+    private final JPanel buttonsPanel;
+    private final DataSourceComboBox dataSourceComboBox;
 
-    ToolbarPanel(ConfigurationModel configurationModel, ConnectionStatusModel connectionModel, ActionListener listener) {
+    ToolbarPanel(final ConfigurationModel configurationModel, final ConnectionStatusModel connectionModel,
+            final ActionListener listener) {
 
         setLayout(new FlowLayout(FlowLayout.LEFT));
-        
-        JPanel containerPanel = new JPanel();
+
+        final JPanel containerPanel = new JPanel();
         containerPanel.setLayout(new GridBagLayout());
-        
+
         // Create the connection status panel.
         GridBagConstraints gbs = new GridBagConstraints();
         gbs.anchor = GridBagConstraints.WEST;
@@ -36,30 +37,34 @@
         gbs.weightx = 0.5;
         gbs.fill = GridBagConstraints.BOTH;
         gbs.insets = new Insets(10, 0, 0, 10);
-        JPanel connectionPanel = new ConnectionStatusPanel(connectionModel);
+        final JPanel connectionPanel = new ConnectionStatusPanel(connectionModel);
         containerPanel.add(connectionPanel, gbs);
 
         // Create the buttons panel.
-        buttonsPanel = new EventButtonsPanel(connectionModel, listener);
+        this.buttonsPanel = new EventButtonsPanel(connectionModel, listener);
         gbs.anchor = GridBagConstraints.WEST;
         gbs.gridx = 1;
         gbs.gridy = 0;
         gbs.weightx = 0.5;
         gbs.fill = GridBagConstraints.BOTH;
         gbs.insets = new Insets(0, 0, 0, 10);
-        containerPanel.add(buttonsPanel, gbs);
+        containerPanel.add(this.buttonsPanel, gbs);
 
         // Add the data source combo box.
-        dataSourceComboBox = new DataSourceComboBox(configurationModel, connectionModel);
+        this.dataSourceComboBox = new DataSourceComboBox(configurationModel, connectionModel);
         gbs = new GridBagConstraints();
         gbs.anchor = GridBagConstraints.WEST;
         gbs.gridx = 2;
         gbs.gridy = 0;
         gbs.weightx = 1.0;
         gbs.fill = GridBagConstraints.HORIZONTAL;
-        containerPanel.add(dataSourceComboBox, gbs);
-        
+        containerPanel.add(this.dataSourceComboBox, gbs);
+
         add(containerPanel);
     }
 
+    DataSourceComboBox getDataSourceComboBox() {
+        return this.dataSourceComboBox;
+    }
+
 }

Modified: java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/TriggerDiagnosticsPanel.java
 =============================================================================
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/TriggerDiagnosticsPanel.java	(original)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/TriggerDiagnosticsPanel.java	Thu Apr  9 19:22:57 2015
@@ -18,36 +18,12 @@
 
 /**
  * This is a panel containing the trigger diagnostics tables.
- * 
- * @author Jeremy McCormick <[log in to unmask]>
+ *
+ * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a>
  */
 @SuppressWarnings("serial")
-class TriggerDiagnosticsPanel extends JPanel {
+final class TriggerDiagnosticsPanel extends JPanel {
 
-    JTabbedPane tabs = new JTabbedPane();
-    ClusterTablePanel clusterPanel = new ClusterTablePanel();
-    SinglesTablePanel singlesPanel = new SinglesTablePanel();
-    PairTablePanel pairsPanel = new PairTablePanel();
-    EfficiencyTablePanel efficiencyPanel = new EfficiencyTablePanel();
-    
-    List<DiagnosticUpdatable> updateList = new ArrayList<DiagnosticUpdatable>();
-    
-    TriggerDiagnosticsPanel() {
-        setLayout(new BorderLayout());
-                       
-        tabs.addTab("Clusters", clusterPanel);
-        tabs.addTab("Singles", singlesPanel);
-        tabs.addTab("Pairs", pairsPanel);
-        tabs.addTab("Efficiency", efficiencyPanel);
-        
-        updateList.add(clusterPanel);
-        updateList.add(singlesPanel);
-        updateList.add(pairsPanel);
-        updateList.add(efficiencyPanel);
-        
-        add(tabs, BorderLayout.CENTER);
-    }
-        
     /**
      * Driver for updating the tables.
      */
@@ -55,24 +31,50 @@
 
         // FIXME: Hard-coded collection name.
         private String diagnosticCollectionName = "DiagnosticSnapshot";
-        
+
         @Override
-        public void process(EventHeader event) {
+        public void process(final EventHeader event) {
             // Updates are only performed if a diagnostic snapshot object
             // exists. Otherwise, do nothing.
-            if(event.hasCollection(DiagnosticSnapshot.class, diagnosticCollectionName)) {
+            if (event.hasCollection(DiagnosticSnapshot.class, this.diagnosticCollectionName)) {
                 // Get the snapshot collection.
-                List<DiagnosticSnapshot> snapshotList = event.get(DiagnosticSnapshot.class, diagnosticCollectionName);
-                
+                final List<DiagnosticSnapshot> snapshotList = event.get(DiagnosticSnapshot.class,
+                        this.diagnosticCollectionName);
+
                 // Update the GUI panels.
-                for (DiagnosticUpdatable update : updateList) {
+                for (final DiagnosticUpdatable update : TriggerDiagnosticsPanel.this.updateList) {
                     update.updatePanel(snapshotList.get(1), snapshotList.get(0));
                 }
-            } 
+            }
         }
-        
-        void setDiagnosticCollectionName(String name) {
-            diagnosticCollectionName = name;
+
+        void setDiagnosticCollectionName(final String name) {
+            this.diagnosticCollectionName = name;
         }
-    }  
+    }
+
+    ClusterTablePanel clusterPanel = new ClusterTablePanel();
+    EfficiencyTablePanel efficiencyPanel = new EfficiencyTablePanel();
+    PairTablePanel pairsPanel = new PairTablePanel();
+    SinglesTablePanel singlesPanel = new SinglesTablePanel();
+
+    JTabbedPane tabs = new JTabbedPane();
+
+    List<DiagnosticUpdatable> updateList = new ArrayList<DiagnosticUpdatable>();
+
+    TriggerDiagnosticsPanel() {
+        setLayout(new BorderLayout());
+
+        this.tabs.addTab("Clusters", this.clusterPanel);
+        this.tabs.addTab("Singles", this.singlesPanel);
+        this.tabs.addTab("Pairs", this.pairsPanel);
+        this.tabs.addTab("Efficiency", this.efficiencyPanel);
+
+        this.updateList.add(this.clusterPanel);
+        this.updateList.add(this.singlesPanel);
+        this.updateList.add(this.pairsPanel);
+        this.updateList.add(this.efficiencyPanel);
+
+        add(this.tabs, BorderLayout.CENTER);
+    }
 }

Modified: java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/model/AbstractModel.java
 =============================================================================
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/model/AbstractModel.java	(original)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/model/AbstractModel.java	Thu Apr  9 19:22:57 2015
@@ -15,56 +15,70 @@
 
 /**
  * An abstract class which updates a set of listeners when there are property changes to a backing model.
- * @author Jeremy McCormick <[log in to unmask]>
+ *
+ * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a>
  */
 public abstract class AbstractModel {
+
+    /**
+     * This method will statically extract property names from a class, which in this package's conventions are
+     * statically declared, public strings that end with "_PROPERTY".
+     *
+     * @param type The class with the properties.
+     * @return The list of property names.
+     */
+    protected static String[] getPropertyNames(final Class<? extends AbstractModel> type) {
+        final List<String> fields = new ArrayList<String>();
+        for (final Field field : type.getDeclaredFields()) {
+            final int modifiers = field.getModifiers();
+            if (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers) && field.getName().endsWith("_PROPERTY")) {
+                try {
+                    fields.add((String) field.get(null));
+                } catch (IllegalArgumentException | IllegalAccessException e) {
+                    throw new RuntimeException(e);
+                }
+            }
+        }
+        return fields.toArray(new String[] {});
+    }
 
     protected PropertyChangeSupport propertyChangeSupport;
 
     public AbstractModel() {
-        propertyChangeSupport = new PropertyChangeSupport(this);
+        this.propertyChangeSupport = new PropertyChangeSupport(this);
     }
 
-    public void addPropertyChangeListener(PropertyChangeListener listener) {
-        propertyChangeSupport.addPropertyChangeListener(listener);
+    public void addPropertyChangeListener(final PropertyChangeListener listener) {
+        this.propertyChangeSupport.addPropertyChangeListener(listener);
     }
 
-    public void removePropertyChangeListener(PropertyChangeListener listener) {
-        propertyChangeSupport.removePropertyChangeListener(listener);
-    }
-       
-    protected void firePropertyChange(String propertyName, Object oldValue, Object newValue) {
-        propertyChangeSupport.firePropertyChange(propertyName, oldValue, newValue);
+    public void fireModelChanged() {
+        firePropertiesChanged(Arrays.asList(getPropertyNames()));
     }
 
-    protected void firePropertyChange(PropertyChangeEvent evt) {
-        propertyChangeSupport.firePropertyChange(evt);
-    }
-
-    abstract public String[] getPropertyNames();
-
-    void firePropertiesChanged(Collection<String> properties) {
-        propertyLoop: for (String property : properties) {
+    void firePropertiesChanged(final Collection<String> properties) {
+        propertyLoop: for (final String property : properties) {
             Method getMethod = null;
-            for (Method method : getClass().getMethods()) {
+            for (final Method method : getClass().getMethods()) {
                 if (method.getName().equals("get" + property)) {
                     getMethod = method;
                     break;
                 }
             }
-            //System.out.println(getMethod.getName());
+            // System.out.println(getMethod.getName());
             try {
                 Object value = null;
                 try {
                     value = getMethod.invoke(this, (Object[]) null);
-                    //System.out.println("  value = " + value);
-                } catch (NullPointerException e) {
+                    // System.out.println("  value = " + value);
+                } catch (final NullPointerException e) {
                     // This means there is no get method for the property which is a throwable error.
                     throw new RuntimeException("Property " + property + " is missing a get method.", e);
-                } catch (InvocationTargetException e) {
+                } catch (final InvocationTargetException e) {
                     // Is the cause of the problem an illegal argument to the method?
                     if (e.getCause() instanceof IllegalArgumentException) {
-                        // For this error, assume that the key itself is missing from the configuration which is a warning.
+                        // For this error, assume that the key itself is missing from the configuration which is a
+                        // warning.
                         System.err.println("The key " + property + " is not set in the configuration.");
                         continue propertyLoop;
                     } else {
@@ -74,7 +88,8 @@
                 }
                 if (value != null) {
                     firePropertyChange(property, value, value);
-                    for (PropertyChangeListener listener : propertyChangeSupport.getPropertyChangeListeners()) {
+                    for (final PropertyChangeListener listener : this.propertyChangeSupport
+                            .getPropertyChangeListeners()) {
                         // FIXME: For some reason calling the propertyChangeSupport methods directly here doesn't work!
                         listener.propertyChange(new PropertyChangeEvent(this, property, value, value));
                     }
@@ -85,30 +100,18 @@
             }
         }
     }
-    
-    public void fireModelChanged() {
-        firePropertiesChanged(Arrays.asList(getPropertyNames()));
+
+    protected void firePropertyChange(final PropertyChangeEvent evt) {
+        this.propertyChangeSupport.firePropertyChange(evt);
     }
 
-    /**
-     * This method will statically extract property names from a class, which in this package's conventions are statically declared, 
-     * public strings that end with "_PROPERTY".
-     * 
-     * @param type The class with the properties.
-     * @return The list of property names.
-     */
-    protected static String[] getPropertyNames(Class<? extends AbstractModel> type) {
-        List<String> fields = new ArrayList<String>();
-        for (Field field : type.getDeclaredFields()) {
-            int modifiers = field.getModifiers();
-            if (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers) && field.getName().endsWith("_PROPERTY")) {
-                try {
-                    fields.add((String) field.get(null));
-                } catch (IllegalArgumentException | IllegalAccessException e) {
-                    throw new RuntimeException(e);
-                }
-            }
-        }
-        return fields.toArray(new String[] {});
+    protected void firePropertyChange(final String propertyName, final Object oldValue, final Object newValue) {
+        this.propertyChangeSupport.firePropertyChange(propertyName, oldValue, newValue);
+    }
+
+    abstract public String[] getPropertyNames();
+
+    public void removePropertyChangeListener(final PropertyChangeListener listener) {
+        this.propertyChangeSupport.removePropertyChangeListener(listener);
     }
 }

Modified: java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/model/Configuration.java
 =============================================================================
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/model/Configuration.java	(original)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/model/Configuration.java	Thu Apr  9 19:22:57 2015
@@ -9,210 +9,227 @@
 import java.util.Set;
 
 /**
- * This class provides a list of key, value pairs backed by a <code>Properties</code> object. The
- * getter and setter methods for these values are not public, because the 
- * {@link org.hps.monitoring.application.model.ConfigurationModel} class should be used instead
- * to get or set application configuration values.
+ * This class provides a list of key, value pairs backed by a <code>Properties</code> object. The getter and setter
+ * methods for these values are not public, because the {@link org.hps.monitoring.application.model.ConfigurationModel}
+ * class should be used instead to get or set application configuration values.
+ *
+ * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a>
  */
 public final class Configuration {
 
+    File file;
     Properties properties;
-    File file;
     String resourcePath;
 
     Configuration() {
-        properties = new Properties();
+        this.properties = new Properties();
     }
 
     /**
      * Load a configuration from a properties file.
+     * 
      * @param file The properties file.
      */
-    public Configuration(File file) {
+    public Configuration(final File file) {
         this.file = file;
         try {
-            properties = new Properties();
-            properties.load(new FileInputStream(this.file));
-        } catch (IOException e) {
+            this.properties = new Properties();
+            this.properties.load(new FileInputStream(this.file));
+        } catch (final IOException e) {
             throw new RuntimeException("Error parsing properties file.", e);
         }
     }
 
     /**
      * Load a configuration from a resource path pointing to a properties file.
+     * 
      * @param resourcePath The resource path to the properties file.
      */
-    public Configuration(String resourcePath) {
+    public Configuration(final String resourcePath) {
         this.resourcePath = resourcePath;
-        InputStream is = this.getClass().getResourceAsStream(this.resourcePath);
-        try {
-            properties = new Properties();
-            properties.load(is);
-        } catch (IOException e) {
+        final InputStream is = this.getClass().getResourceAsStream(this.resourcePath);
+        try {
+            this.properties = new Properties();
+            this.properties.load(is);
+        } catch (final IOException e) {
             throw new RuntimeException("Error parsing properties resource.", e);
         }
     }
 
     /**
+     * Check if the properties contains the key and if it has a non-null value.
+     * 
+     * @param key The properties key.
+     * @return True if properties key is valid.
+     */
+    boolean checkKey(final String key) {
+        return hasKey(key) && this.properties.getProperty(key) != null;
+    }
+
+    /**
+     * Get a key value as a string.
+     * 
+     * @param key The key to lookup.
+     * @return The value or null if does not exist.
+     */
+    String get(final String key) {
+        if (checkKey(key)) {
+            // Return the key value for properties that are set.
+            return this.properties.getProperty(key);
+        } else {
+            // Return null for unset properties.
+            return null;
+        }
+    }
+
+    /**
+     * Get a key value as a boolean.
+     * 
+     * @param key The key to lookup.
+     * @return The value or null if does not exist.
+     */
+    Boolean getBoolean(final String key) {
+        if (checkKey(key)) {
+            return Boolean.parseBoolean(this.properties.getProperty(key));
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * Get a key value as a double.
+     * 
+     * @param key The key to lookup.
+     * @return The value or null if does not exist.
+     */
+    Double getDouble(final String key) {
+        if (checkKey(key)) {
+            return Double.parseDouble(this.properties.getProperty(key));
+        } else {
+            return null;
+        }
+    }
+
+    /**
      * Get the file associated with this configuration or <code>null</code> if not set.
+     * 
      * @return The file associated with the configuration.
      */
     public File getFile() {
-        return file;
-    }
-
-    /**
-     * Get the resource path associated with this configuration or <code>null</code> if not
-     * applicable.
+        return this.file;
+    }
+
+    /**
+     * Get a key value as an integer.
+     * 
+     * @param key The key to lookup.
+     * @return The value or null if does not exist.
+     */
+    Integer getInteger(final String key) {
+        if (checkKey(key)) {
+            return Integer.parseInt(this.properties.getProperty(key));
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * Get the property keys.
+     * 
+     * @return The collection of property keys.
+     */
+    public Set<String> getKeys() {
+        return this.properties.stringPropertyNames();
+    }
+
+    /**
+     * Get a key value as a Long.
+     * 
+     * @param key The key to lookup.
+     * @param key The value or null if does not exist.
+     * @return
+     */
+    Long getLong(final String key) {
+        if (checkKey(key)) {
+            return Long.parseLong(this.properties.getProperty(key));
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * Get the resource path associated with this configuration or <code>null</code> if not applicable.
+     * 
      * @return The resource path of this configuration.
      */
     public String getResourcePath() {
-        return resourcePath;
+        return this.resourcePath;
     }
 
     /**
      * True if configuration has value for the key.
+     * 
      * @param key The key.
      * @return True if configuration has value for the key.
      */
-    boolean hasKey(String key) {
-        try {
-            return properties.containsKey(key);
-        } catch (java.lang.NullPointerException e) {
+    boolean hasKey(final String key) {
+        try {
+            return this.properties.containsKey(key);
+        } catch (final java.lang.NullPointerException e) {
             return false;
         }
     }
 
     /**
-     * Get a key value as a string.
-     * @param key The key to lookup.
-     * @return The value or null if does not exist.
-     */
-    String get(String key) {
-        if (checkKey(key)) {
-            // Return the key value for properties that are set.
-            return properties.getProperty(key);
-        } else {
-            // Return null for unset properties.
-            return null;
-        }
-    }
-
-    /**
-     * Get a key value as a boolean.
-     * @param key The key to lookup.
-     * @return The value or null if does not exist.
-     */
-    Boolean getBoolean(String key) {
-        if (checkKey(key)) {
-            return Boolean.parseBoolean(properties.getProperty(key));    
-        } else {
-            return null;
-        }        
-    }
-
-    /**
-     * Get a key value as a double.
-     * @param key The key to lookup.
-     * @return The value or null if does not exist.
-     */
-    Double getDouble(String key) {
-        if (checkKey(key)) {
-            return Double.parseDouble(properties.getProperty(key));
-        } else {
-            return null;
-        }
-    }
-
-    /**
-     * Get a key value as an integer.
-     * @param key The key to lookup.
-     * @return The value or null if does not exist.
-     */
-    Integer getInteger(String key) {
-        if (checkKey(key)) {
-            return Integer.parseInt(properties.getProperty(key));
-        } else {
-            return null;
-        }
-    }
-    
-    /**
-     * Get a key value as a Long.
-     * @param key The key to lookup.
-     * @param key The value or null if does not exist.
-     * @return
-     */
-    Long getLong(String key) {
-        if (checkKey(key)) {
-            return Long.parseLong(properties.getProperty(key));
-        } else {
-            return null;
-        }
-    }
-
-    /**
-     * Write this configuration to a file and set that file as the current one.
-     * @param file The output file.
-     */
-    public void writeToFile(File file) {
-        this.file = file;
-        try {
-            properties.store(new FileOutputStream(this.file), null);
-        } catch (IOException e) {
-            throw new RuntimeException("Error saving properties file.", e);
-        }
-    }
-    
-    /**
-     * Check if the properties contains the key and if it has a non-null value.
-     * @param key The properties key.
-     * @return True if properties key is valid.
-     */
-    boolean checkKey(String key) {
-        return hasKey(key) && properties.getProperty(key) != null;
+     * Merge in values from another configuration into this one which will override properties that already exist with
+     * new values.
+     * 
+     * @param configuration The configuration with the properties to merge.
+     */
+    void merge(final Configuration configuration) {
+        for (final String property : configuration.getKeys()) {
+            this.set(property, configuration.get(property));
+        }
+    }
+
+    /**
+     * Remove a configuration value.
+     * 
+     * @param key The key of the value.
+     */
+    void remove(final String key) {
+        this.properties.remove(key);
     }
 
     /**
      * Set a configuration value.
+     * 
      * @param key The key for lookup.
      * @param value The value to assign to that key.
      */
-    void set(String key, Object value) {
-        properties.put(key, String.valueOf(value));
-    }
-
-    /**
-     * Remove a configuration value.
-     * @param key The key of the value.
-     */
-    void remove(String key) {
-        properties.remove(key);
+    void set(final String key, final Object value) {
+        this.properties.put(key, String.valueOf(value));
     }
 
     /**
      * Convert this object to a string by printing out its properties list.
      */
+    @Override
     public String toString() {
-        return properties.toString();        
-    }
-    
-    /**
-     * Get the property keys.
-     * @return The collection of property keys.
-     */
-    public Set<String> getKeys() {
-        return properties.stringPropertyNames();
-    }
-    
-    /**
-     * Merge in values from another configuration into this one which will override
-     * properties that already exist with new values.
-     * @param configuration The configuration with the properties to merge.
-     */
-    void merge(Configuration configuration) {
-        for (String property : configuration.getKeys()) {
-            this.set(property, configuration.get(property));
+        return this.properties.toString();
+    }
+
+    /**
+     * Write this configuration to a file and set that file as the current one.
+     * 
+     * @param file The output file.
+     */
+    public void writeToFile(final File file) {
+        this.file = file;
+        try {
+            this.properties.store(new FileOutputStream(this.file), null);
+        } catch (final IOException e) {
+            throw new RuntimeException("Error saving properties file.", e);
         }
     }
 }

Modified: java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/model/ConfigurationModel.java
 =============================================================================
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/model/ConfigurationModel.java	(original)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/model/ConfigurationModel.java	Thu Apr  9 19:22:57 2015
@@ -9,497 +9,505 @@
 import org.jlab.coda.et.enums.Mode;
 
 /**
- * A model of the global configuration parameters that can be used to automatically update the GUI
- * from a configuration or push changes from GUI components into the current configuration.
+ * A model of the global configuration parameters that can be used to automatically update the GUI from a configuration
+ * or push changes from GUI components into the current configuration.
+ *
+ * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a>
  */
 public final class ConfigurationModel extends AbstractModel {
 
-    Configuration configuration;    
-    
     // Job setting properties.
     public static final String AIDA_SERVER_NAME_PROPERTY = "AIDAServerName";
+
+    public static final String BLOCKING_PROPERTY = "Blocking";
+
+    public static final String CHUNK_SIZE_PROPERTY = "ChunkSize";
     public static final String CONDITIONS_TAG_PROPERTY = "ConditionsTag";
+    static final String[] CONFIG_PROPERTIES = AbstractModel.getPropertyNames(ConfigurationModel.class);
+    public static final String CONFIGURATION_CHANGED = "configurationChanged";
+    public static final String DATA_SOURCE_PATH_PROPERTY = "DataSourcePath";
+    public static final String DATA_SOURCE_TYPE_PROPERTY = "DataSourceType";
+    public static final String DETECTOR_ALIAS_PROPERTY = "DetectorAlias";
     public static final String DETECTOR_NAME_PROPERTY = "DetectorName";
-    public static final String DETECTOR_ALIAS_PROPERTY = "DetectorAlias";
+    public static final String DISCONNECT_ON_END_RUN_PROPERTY = "DisconnectOnEndRun";
     public static final String DISCONNECT_ON_ERROR_PROPERTY = "DisconnectOnError";
-    public static final String DISCONNECT_ON_END_RUN_PROPERTY = "DisconnectOnEndRun";
+    public static final String ET_NAME_PROPERTY = "EtName";
     public static final String EVENT_BUILDER_PROPERTY = "EventBuilderClassName";
     public static final String FREEZE_CONDITIONS_PROPERTY = "FreezeConditions";
+    public static final String HOST_PROPERTY = "Host";
     public static final String LOG_FILE_NAME_PROPERTY = "LogFileName";
+    public static final String LOG_LEVEL_FILTER_PROPERTY = "LogLevelFilter";
     public static final String LOG_LEVEL_PROPERTY = "LogLevel";
-    public static final String LOG_LEVEL_FILTER_PROPERTY = "LogLevelFilter";
     public static final String LOG_TO_FILE_PROPERTY = "LogToFile";
     public static final String MAX_EVENTS_PROPERTY = "MaxEvents";
+    private static final int MAX_RECENT_FILES = 10;
+    public static final String PORT_PROPERTY = "Port";
+    public static final String PRESCALE_PROPERTY = "Prescale";
+    public static final String PROCESSING_STAGE_PROPERTY = "ProcessingStage";
+    public static final String QUEUE_SIZE_PROPERTY = "QueueSize";
     public static final String RECENT_FILES_PROPERTY = "RecentFiles";
-    public static final String STEERING_TYPE_PROPERTY = "SteeringType";
+    public static final String STATION_NAME_PROPERTY = "StationName";
+    public static final String STATION_POSITION_PROPERTY = "StationPosition";
     public static final String STEERING_FILE_PROPERTY = "SteeringFile";
     public static final String STEERING_RESOURCE_PROPERTY = "SteeringResource";
+    public static final String STEERING_TYPE_PROPERTY = "SteeringType";
     public static final String USER_RUN_NUMBER_PROPERTY = "UserRunNumber";
-
-    // Data source properties.
-    public static final String DATA_SOURCE_TYPE_PROPERTY = "DataSourceType";
-    public static final String DATA_SOURCE_PATH_PROPERTY = "DataSourcePath";
-    public static final String PROCESSING_STAGE_PROPERTY = "ProcessingStage";
-
-    // ET connection parameters.
-    public static final String ET_NAME_PROPERTY = "EtName";
-    public static final String HOST_PROPERTY = "Host";
-    public static final String PORT_PROPERTY = "Port";
-    public static final String BLOCKING_PROPERTY = "Blocking";
     public static final String VERBOSE_PROPERTY = "Verbose";
-    public static final String STATION_NAME_PROPERTY = "StationName";
-    public static final String CHUNK_SIZE_PROPERTY = "ChunkSize";
-    public static final String QUEUE_SIZE_PROPERTY = "QueueSize";
-    public static final String STATION_POSITION_PROPERTY = "StationPosition";
     public static final String WAIT_MODE_PROPERTY = "WaitMode";
     public static final String WAIT_TIME_PROPERTY = "WaitTime";
-    public static final String PRESCALE_PROPERTY = "Prescale";
-    
-    // Action command to get notified after configuration change is performed.
-    public static final String CONFIGURATION_CHANGED = "configurationChanged";
-
-    static final String[] CONFIG_PROPERTIES = AbstractModel.getPropertyNames(ConfigurationModel.class);
+
+    Configuration configuration;
 
     public ConfigurationModel() {
         this.configuration = new Configuration();
     }
 
-    public ConfigurationModel(Configuration configuration) {
+    public ConfigurationModel(final Configuration configuration) {
         this.configuration = configuration;
         fireModelChanged();
     }
-    
-    public void setConfiguration(Configuration configuration) {
+
+    public void addRecentFile(final String recentFile) {
+        if (!this.configuration.checkKey(RECENT_FILES_PROPERTY)) {
+            this.configuration.set(RECENT_FILES_PROPERTY, recentFile);
+            firePropertyChange(RECENT_FILES_PROPERTY, null, recentFile);
+        } else {
+            final List<String> recentFilesList = getRecentFilesList();
+            if (!recentFilesList.contains(recentFile)) {
+                if (getRecentFilesList().size() >= MAX_RECENT_FILES) {
+                    // Bump the first file from the list if max recent files is exceeded (10 files).
+                    recentFilesList.remove(0);
+                    setRecentFilesList(recentFilesList);
+                }
+                final String oldValue = this.configuration.get(RECENT_FILES_PROPERTY);
+                final String recentFiles = oldValue + "\n" + recentFile;
+                this.configuration.set(RECENT_FILES_PROPERTY, recentFiles);
+                firePropertyChange(RECENT_FILES_PROPERTY, oldValue, recentFile);
+            }
+        }
+
+    }
+
+    @Override
+    public void fireModelChanged() {
+        firePropertiesChanged(this.configuration.getKeys());
+    }
+
+    public String getAIDAServerName() {
+        return this.configuration.get(AIDA_SERVER_NAME_PROPERTY);
+    }
+
+    public Boolean getBlocking() {
+        return this.configuration.getBoolean(BLOCKING_PROPERTY);
+    }
+
+    public Integer getChunkSize() {
+        return this.configuration.getInteger(CHUNK_SIZE_PROPERTY);
+    }
+
+    public String getConditionsTag() {
+        return this.configuration.get(CONDITIONS_TAG_PROPERTY);
+    }
+
+    public Configuration getConfiguration() {
+        return this.configuration;
+    }
+
+    public String getDataSourcePath() {
+        return this.configuration.get(DATA_SOURCE_PATH_PROPERTY);
+    }
+
+    public DataSourceType getDataSourceType() {
+        if (this.configuration.checkKey(DATA_SOURCE_TYPE_PROPERTY)) {
+            return DataSourceType.valueOf(this.configuration.get(DATA_SOURCE_TYPE_PROPERTY));
+        } else {
+            return null;
+        }
+    }
+
+    public String getDetectorAlias() {
+        return this.configuration.get(DETECTOR_ALIAS_PROPERTY);
+    }
+
+    public String getDetectorName() {
+        return this.configuration.get(DETECTOR_NAME_PROPERTY);
+    }
+
+    public Boolean getDisconnectOnEndRun() {
+        return this.configuration.getBoolean(DISCONNECT_ON_END_RUN_PROPERTY);
+    }
+
+    public Boolean getDisconnectOnError() {
+        return this.configuration.getBoolean(DISCONNECT_ON_ERROR_PROPERTY);
+    }
+
+    public String getEtName() {
+        return this.configuration.get(ET_NAME_PROPERTY);
+    }
+
+    public String getEtPath() {
+        return getEtName() + "@" + getHost() + ":" + getPort();
+    }
+
+    public String getEventBuilderClassName() {
+        return this.configuration.get(EVENT_BUILDER_PROPERTY);
+    }
+
+    public Boolean getFreezeConditions() {
+        return this.configuration.getBoolean(FREEZE_CONDITIONS_PROPERTY);
+    }
+
+    public String getHost() {
+        return this.configuration.get(HOST_PROPERTY);
+    }
+
+    public String getLogFileName() {
+        return this.configuration.get(LOG_FILE_NAME_PROPERTY);
+    }
+
+    public Level getLogLevel() {
+        return Level.parse(this.configuration.get(LOG_LEVEL_PROPERTY));
+    }
+
+    public Level getLogLevelFilter() {
+        return Level.parse(this.configuration.get(LOG_LEVEL_FILTER_PROPERTY));
+    }
+
+    public Boolean getLogToFile() {
+        return this.configuration.getBoolean(LOG_TO_FILE_PROPERTY);
+    }
+
+    public Long getMaxEvents() {
+        return this.configuration.getLong(MAX_EVENTS_PROPERTY);
+    }
+
+    public Integer getPort() {
+        return this.configuration.getInteger(PORT_PROPERTY);
+    }
+
+    public Integer getPrescale() {
+        return this.configuration.getInteger(PRESCALE_PROPERTY);
+    }
+
+    public ProcessingStage getProcessingStage() {
+        if (this.configuration.get(PROCESSING_STAGE_PROPERTY) == null) {
+            throw new RuntimeException(PROCESSING_STAGE_PROPERTY + " is null!!!");
+        }
+        return ProcessingStage.valueOf(this.configuration.get(PROCESSING_STAGE_PROPERTY));
+    }
+
+    @Override
+    public String[] getPropertyNames() {
+        return CONFIG_PROPERTIES;
+    }
+
+    public Integer getQueueSize() {
+        return this.configuration.getInteger(QUEUE_SIZE_PROPERTY);
+    }
+
+    public String getRecentFiles() {
+        if (this.configuration.hasKey(RECENT_FILES_PROPERTY)) {
+            return this.configuration.get(RECENT_FILES_PROPERTY);
+        } else {
+            return null;
+        }
+    }
+
+    public List<String> getRecentFilesList() {
+        final List<String> recentFilesList = new ArrayList<String>();
+        if (this.configuration.hasKey(RECENT_FILES_PROPERTY)) {
+            for (final String recentFile : this.configuration.get(RECENT_FILES_PROPERTY).split("\n")) {
+                recentFilesList.add(recentFile);
+            }
+        }
+        return recentFilesList;
+    }
+
+    /*
+     * public void setDataSource(String dataSource) { setDataSourcePath(dataSource); DataSourceType dst =
+     * DataSourceType.getDataSourceType(dataSource); setDataSourceType(dst); }
+     */
+
+    public String getStationName() {
+        return this.configuration.get(STATION_NAME_PROPERTY);
+    }
+
+    public Integer getStationPosition() {
+        return this.configuration.getInteger(STATION_POSITION_PROPERTY);
+    }
+
+    public String getSteeringFile() {
+        return this.configuration.get(STEERING_FILE_PROPERTY);
+    }
+
+    public String getSteeringResource() {
+        return this.configuration.get(STEERING_RESOURCE_PROPERTY);
+    }
+
+    public SteeringType getSteeringType() {
+        return SteeringType.valueOf(this.configuration.get(STEERING_TYPE_PROPERTY));
+    }
+
+    public Integer getUserRunNumber() {
+        return this.configuration.getInteger(USER_RUN_NUMBER_PROPERTY);
+    }
+
+    public Boolean getVerbose() {
+        return this.configuration.getBoolean(VERBOSE_PROPERTY);
+    }
+
+    public Mode getWaitMode() {
+        return Mode.valueOf(this.configuration.get(WAIT_MODE_PROPERTY));
+    }
+
+    public Integer getWaitTime() {
+        return this.configuration.getInteger(WAIT_TIME_PROPERTY);
+    }
+
+    public boolean hasPropertyKey(final String key) {
+        return this.configuration.hasKey(key);
+    }
+
+    public boolean hasValidProperty(final String key) {
+        return this.configuration.checkKey(key);
+    }
+
+    public void merge(final Configuration configuration) {
+        this.configuration.merge(configuration);
+        this.firePropertiesChanged(configuration.getKeys());
+    }
+
+    public void remove(final String property) {
+        if (hasPropertyKey(property)) {
+            final Object oldValue = this.configuration.get(property);
+            if (oldValue != null) {
+                this.configuration.remove(property);
+                firePropertyChange(property, oldValue, null);
+            }
+        }
+    }
+
+    public void setAIDAServerName(final String AIDAServerName) {
+        final String oldValue = getAIDAServerName();
+        this.configuration.set(AIDA_SERVER_NAME_PROPERTY, AIDAServerName);
+        firePropertyChange(AIDA_SERVER_NAME_PROPERTY, oldValue, getAIDAServerName());
+    }
+
+    public void setBlocking(final Boolean blocking) {
+        final Boolean oldValue = getBlocking();
+        this.configuration.set(BLOCKING_PROPERTY, blocking);
+        firePropertyChange(BLOCKING_PROPERTY, oldValue, getBlocking());
+    }
+
+    public void setChunkSize(final Integer chunkSize) {
+        final Integer oldValue = getChunkSize();
+        this.configuration.set(CHUNK_SIZE_PROPERTY, chunkSize);
+        firePropertyChange(CHUNK_SIZE_PROPERTY, oldValue, getChunkSize());
+    }
+
+    public void setConditionsTag(final String conditionsTag) {
+        final String oldValue = getConditionsTag();
+        this.configuration.set(CONDITIONS_TAG_PROPERTY, conditionsTag);
+        firePropertyChange(CONDITIONS_TAG_PROPERTY, oldValue, getConditionsTag());
+    }
+
+    public void setConfiguration(final Configuration configuration) {
         this.configuration = configuration;
         fireModelChanged();
     }
-     
-    public Configuration getConfiguration() {
-        return this.configuration;
-    }
-
-    public Level getLogLevel() {
-        return Level.parse(configuration.get(LOG_LEVEL_PROPERTY));
-    }
-
-    public void setLogLevel(Level level) { 
-        Level oldValue = getLogLevel();
-        configuration.set(LOG_LEVEL_PROPERTY, level.getName());
-        firePropertyChange(LOG_LEVEL_PROPERTY, oldValue, getLogLevel());
-    }
-    
-    public Level getLogLevelFilter() {
-        return Level.parse(configuration.get(LOG_LEVEL_FILTER_PROPERTY));
-    }
-
-    public void setLogLevelFilter(Level level) {
-        Level oldValue = getLogLevelFilter();
-        configuration.set(LOG_LEVEL_FILTER_PROPERTY, level.getName());
-        firePropertyChange(LOG_LEVEL_FILTER_PROPERTY, oldValue, getLogLevelFilter());
-    }
-
-    public SteeringType getSteeringType() {
-        return SteeringType.valueOf(configuration.get(STEERING_TYPE_PROPERTY));
-    }
-
-    public void setSteeringType(SteeringType steeringType) {
-        SteeringType oldValue = getSteeringType();
-        configuration.set(STEERING_TYPE_PROPERTY, steeringType.name());
-        firePropertyChange(STEERING_TYPE_PROPERTY, oldValue, getSteeringType());
-    }
-
-    public String getSteeringFile() {        
-        return configuration.get(STEERING_FILE_PROPERTY);
-    }
-
-    public void setSteeringFile(String steeringFile) {
-        String oldValue = getSteeringFile();
-        configuration.set(STEERING_FILE_PROPERTY, steeringFile);
-        firePropertyChange(STEERING_FILE_PROPERTY, oldValue, getSteeringFile());
-    }
-
-    public String getSteeringResource() {
-        return configuration.get(STEERING_RESOURCE_PROPERTY);
-    }
-
-    public void setSteeringResource(String steeringResource) {
-        String oldValue = getSteeringResource();
-        configuration.set(STEERING_RESOURCE_PROPERTY, steeringResource);
-        firePropertyChange(STEERING_RESOURCE_PROPERTY, oldValue, steeringResource);
-    }
-
-    public String getDetectorName() {
-        return configuration.get(DETECTOR_NAME_PROPERTY);
-    }
-
-    public void setDetectorName(String detectorName) {
-        String oldValue = getDetectorName();
-        configuration.set(DETECTOR_NAME_PROPERTY, detectorName);
-        firePropertyChange(DETECTOR_NAME_PROPERTY, oldValue, getDetectorName());
-    }
-
-    public String getDetectorAlias() {
-        return configuration.get(DETECTOR_ALIAS_PROPERTY);
-    }
-
-    public void setDetectorAlias(String detectorAlias) {
+
+    public void setDataSourcePath(final String dataSourcePath) {
+        final String oldValue = getDataSourcePath();
+        this.configuration.set(DATA_SOURCE_PATH_PROPERTY, dataSourcePath);
+        firePropertyChange(DATA_SOURCE_PATH_PROPERTY, oldValue, getDataSourcePath());
+    }
+
+    public void setDataSourceType(final DataSourceType dataSourceType) {
+        final DataSourceType oldValue = getDataSourceType();
+        this.configuration.set(DATA_SOURCE_TYPE_PROPERTY, dataSourceType);
+        firePropertyChange(DATA_SOURCE_TYPE_PROPERTY, oldValue, getDataSourceType());
+    }
+
+    public void setDetectorAlias(final String detectorAlias) {
         String oldValue = null;
         if (hasPropertyKey(DETECTOR_ALIAS_PROPERTY)) {
             oldValue = getDetectorAlias();
         }
-        configuration.set(DETECTOR_ALIAS_PROPERTY, detectorAlias);
+        this.configuration.set(DETECTOR_ALIAS_PROPERTY, detectorAlias);
         firePropertyChange(DETECTOR_ALIAS_PROPERTY, oldValue, getDetectorAlias());
     }
 
-    public String getEventBuilderClassName() {
-        return configuration.get(EVENT_BUILDER_PROPERTY);
-    }
-
-    public void setEventBuilderClassName(String eventBuilderClassName) {
-        String oldValue = getEventBuilderClassName();
-        configuration.set(EVENT_BUILDER_PROPERTY, eventBuilderClassName);
+    public void setDetectorName(final String detectorName) {
+        final String oldValue = getDetectorName();
+        this.configuration.set(DETECTOR_NAME_PROPERTY, detectorName);
+        firePropertyChange(DETECTOR_NAME_PROPERTY, oldValue, getDetectorName());
+    }
+
+    public void setDisconnectOnEndRun(final Boolean disconnectOnEndRun) {
+        final Boolean oldValue = getDisconnectOnEndRun();
+        this.configuration.set(DISCONNECT_ON_END_RUN_PROPERTY, disconnectOnEndRun);
+        firePropertyChange(DISCONNECT_ON_END_RUN_PROPERTY, oldValue, getDisconnectOnEndRun());
+    }
+
+    public void setDisconnectOnError(final Boolean disconnectOnError) {
+        final Boolean oldValue = getDisconnectOnError();
+        this.configuration.set(DISCONNECT_ON_ERROR_PROPERTY, disconnectOnError);
+        firePropertyChange(DISCONNECT_ON_ERROR_PROPERTY, oldValue, getDisconnectOnError());
+    }
+
+    public void setEtName(final String etName) {
+        final String oldValue = getEtName();
+        this.configuration.set(ET_NAME_PROPERTY, etName);
+        firePropertyChange(ET_NAME_PROPERTY, oldValue, getEtName());
+    }
+
+    public void setEventBuilderClassName(final String eventBuilderClassName) {
+        final String oldValue = getEventBuilderClassName();
+        this.configuration.set(EVENT_BUILDER_PROPERTY, eventBuilderClassName);
         firePropertyChange(EVENT_BUILDER_PROPERTY, oldValue, getEventBuilderClassName());
     }
 
-    public Boolean getLogToFile() {
-        return configuration.getBoolean(LOG_TO_FILE_PROPERTY);
-    }
-
-    public void setLogToFile(Boolean logToFile) {
-        Boolean oldValue = getLogToFile();
-        configuration.set(LOG_TO_FILE_PROPERTY, logToFile);
+    public void setFreezeConditions(final Boolean freezeConditions) {
+        Boolean oldValue = null;
+        if (hasPropertyKey(FREEZE_CONDITIONS_PROPERTY)) {
+            oldValue = getFreezeConditions();
+        }
+        this.configuration.set(FREEZE_CONDITIONS_PROPERTY, freezeConditions);
+        firePropertyChange(FREEZE_CONDITIONS_PROPERTY, oldValue, freezeConditions);
+    }
+
+    public void setHost(final String host) {
+        final String oldValue = getHost();
+        this.configuration.set(HOST_PROPERTY, host);
+        firePropertyChange(HOST_PROPERTY, oldValue, getHost());
+    }
+
+    public void setLogFileName(final String logFileName) {
+        final String oldValue = getLogFileName();
+        this.configuration.set(LOG_FILE_NAME_PROPERTY, logFileName);
+        firePropertyChange(LOG_FILE_NAME_PROPERTY, oldValue, getLogFileName());
+    }
+
+    public void setLogLevel(final Level level) {
+        final Level oldValue = getLogLevel();
+        this.configuration.set(LOG_LEVEL_PROPERTY, level.getName());
+        firePropertyChange(LOG_LEVEL_PROPERTY, oldValue, getLogLevel());
+    }
+
+    public void setLogLevelFilter(final Level level) {
+        final Level oldValue = getLogLevelFilter();
+        this.configuration.set(LOG_LEVEL_FILTER_PROPERTY, level.getName());
+        firePropertyChange(LOG_LEVEL_FILTER_PROPERTY, oldValue, getLogLevelFilter());
+    }
+
+    public void setLogToFile(final Boolean logToFile) {
+        final Boolean oldValue = getLogToFile();
+        this.configuration.set(LOG_TO_FILE_PROPERTY, logToFile);
         firePropertyChange(LOG_TO_FILE_PROPERTY, oldValue, getLogToFile());
     }
 
-    public String getLogFileName() {
-        return configuration.get(LOG_FILE_NAME_PROPERTY);
-    }
-
-    public void setLogFileName(String logFileName) {
-        String oldValue = getLogFileName();
-        configuration.set(LOG_FILE_NAME_PROPERTY, logFileName);
-        firePropertyChange(LOG_FILE_NAME_PROPERTY, oldValue, getLogFileName());
-    }
-
-    public Boolean getDisconnectOnError() {
-        return configuration.getBoolean(DISCONNECT_ON_ERROR_PROPERTY);
-    }
-
-    public void setDisconnectOnError(Boolean disconnectOnError) {
-        Boolean oldValue = getDisconnectOnError();
-        configuration.set(DISCONNECT_ON_ERROR_PROPERTY, disconnectOnError);
-        firePropertyChange(DISCONNECT_ON_ERROR_PROPERTY, oldValue, getDisconnectOnError());
-    }
-
-    public Boolean getDisconnectOnEndRun() {
-        return configuration.getBoolean(DISCONNECT_ON_END_RUN_PROPERTY);
-    }
-
-    public void setDisconnectOnEndRun(Boolean disconnectOnEndRun) {
-        Boolean oldValue = getDisconnectOnEndRun();
-        configuration.set(DISCONNECT_ON_END_RUN_PROPERTY, disconnectOnEndRun);
-        firePropertyChange(DISCONNECT_ON_END_RUN_PROPERTY, oldValue, getDisconnectOnEndRun());
-    }
-
-    public DataSourceType getDataSourceType() {
-        if (configuration.checkKey(DATA_SOURCE_TYPE_PROPERTY)) {
-            return DataSourceType.valueOf(configuration.get(DATA_SOURCE_TYPE_PROPERTY));
-        } else {
-            return null;
-        }
-    }
-
-    public void setDataSourceType(DataSourceType dataSourceType) {
-        DataSourceType oldValue = getDataSourceType();
-        configuration.set(DATA_SOURCE_TYPE_PROPERTY, dataSourceType);
-        firePropertyChange(DATA_SOURCE_TYPE_PROPERTY, oldValue, getDataSourceType());
-    }
-
-    public String getDataSourcePath() {
-        return configuration.get(DATA_SOURCE_PATH_PROPERTY);
-    }
-
-    public void setDataSourcePath(String dataSourcePath) {
-        String oldValue = getDataSourcePath();
-        configuration.set(DATA_SOURCE_PATH_PROPERTY, dataSourcePath);
-        firePropertyChange(DATA_SOURCE_PATH_PROPERTY, oldValue, getDataSourcePath());
-    }
-     
-    /*
-    public void setDataSource(String dataSource) {
-        setDataSourcePath(dataSource);
-        DataSourceType dst = DataSourceType.getDataSourceType(dataSource);
-        setDataSourceType(dst);
-    }
-    */
-
-    public ProcessingStage getProcessingStage() {
-        if (configuration.get(PROCESSING_STAGE_PROPERTY) == null)
-            throw new RuntimeException(PROCESSING_STAGE_PROPERTY + " is null!!!");
-        return ProcessingStage.valueOf(configuration.get(PROCESSING_STAGE_PROPERTY));
-    }
-
-    public void setProcessingStage(ProcessingStage processingStage) {
-        ProcessingStage oldValue = getProcessingStage();
-        configuration.set(PROCESSING_STAGE_PROPERTY, processingStage);
+    public void setMaxEvents(final Long maxEvents) {
+        final Long oldValue = getMaxEvents();
+        this.configuration.set(MAX_EVENTS_PROPERTY, maxEvents);
+        firePropertyChange(MAX_EVENTS_PROPERTY, oldValue, getMaxEvents());
+    }
+
+    public void setPort(final Integer port) {
+        final Integer oldValue = getPort();
+        this.configuration.set(PORT_PROPERTY, port);
+        firePropertyChange(PORT_PROPERTY, oldValue, getPort());
+    }
+
+    public void setPrescale(final Integer prescale) {
+        final Integer oldValue = getPrescale();
+        this.configuration.set(PRESCALE_PROPERTY, prescale);
+        firePropertyChange(PRESCALE_PROPERTY, oldValue, getPrescale());
+    }
+
+    public void setProcessingStage(final ProcessingStage processingStage) {
+        final ProcessingStage oldValue = getProcessingStage();
+        this.configuration.set(PROCESSING_STAGE_PROPERTY, processingStage);
         firePropertyChange(PROCESSING_STAGE_PROPERTY, oldValue, getProcessingStage());
     }
 
-    public String getEtName() {
-        return configuration.get(ET_NAME_PROPERTY);
-    }
-
-    public void setEtName(String etName) {
-        String oldValue = getEtName();
-        configuration.set(ET_NAME_PROPERTY, etName);
-        firePropertyChange(ET_NAME_PROPERTY, oldValue, getEtName());
-    }
-
-    public String getHost() {
-        return configuration.get(HOST_PROPERTY);
-    }
-
-    public void setHost(String host) {
-        String oldValue = getHost();
-        configuration.set(HOST_PROPERTY, host);
-        firePropertyChange(HOST_PROPERTY, oldValue, getHost());
-    }
-
-    public Integer getPort() {
-        return configuration.getInteger(PORT_PROPERTY);
-    }
-
-    public void setPort(Integer port) {
-        Integer oldValue = getPort();
-        configuration.set(PORT_PROPERTY, port);
-        firePropertyChange(PORT_PROPERTY, oldValue, getPort());
-    }
-
-    public Boolean getBlocking() {
-        return configuration.getBoolean(BLOCKING_PROPERTY);
-    }
-
-    public void setBlocking(Boolean blocking) {
-        Boolean oldValue = getBlocking();
-        configuration.set(BLOCKING_PROPERTY, blocking);
-        firePropertyChange(BLOCKING_PROPERTY, oldValue, getBlocking());
-    }
-
-    public Boolean getVerbose() {
-        return configuration.getBoolean(VERBOSE_PROPERTY);
-    }
-
-    public void setVerbose(Boolean verbose) {
-        Boolean oldValue = getVerbose();
-        configuration.set(VERBOSE_PROPERTY, verbose);
-        firePropertyChange(VERBOSE_PROPERTY, oldValue, getVerbose());
-    }
-
-    public String getStationName() {
-        return configuration.get(STATION_NAME_PROPERTY);
-    }
-
-    public void setStationName(String stationName) {
-        String oldValue = getStationName();
-        configuration.set(STATION_NAME_PROPERTY, stationName);
+    public void setQueueSize(final Integer queueSize) {
+        final Integer oldValue = getQueueSize();
+        this.configuration.set(QUEUE_SIZE_PROPERTY, queueSize);
+        firePropertyChange(QUEUE_SIZE_PROPERTY, oldValue, getQueueSize());
+    }
+
+    public void setRecentFiles(final String recentFiles) {
+        String oldValue = null;
+        if (this.configuration.checkKey(RECENT_FILES_PROPERTY)) {
+            oldValue = this.configuration.get(RECENT_FILES_PROPERTY);
+        }
+        this.configuration.set(RECENT_FILES_PROPERTY, recentFiles);
+        firePropertyChange(RECENT_FILES_PROPERTY, oldValue, this.configuration.get(RECENT_FILES_PROPERTY));
+    }
+
+    private void setRecentFilesList(final List<String> recentFilesList) {
+        final StringBuffer sb = new StringBuffer();
+        for (final String recentFile : recentFilesList) {
+            sb.append(recentFile + "\n");
+        }
+        sb.setLength(sb.length() - 2);
+        this.configuration.set(RECENT_FILES_PROPERTY, sb.toString());
+    }
+
+    public void setStationName(final String stationName) {
+        final String oldValue = getStationName();
+        this.configuration.set(STATION_NAME_PROPERTY, stationName);
         firePropertyChange(STATION_NAME_PROPERTY, oldValue, getStationName());
     }
 
-    public Integer getChunkSize() {
-        return configuration.getInteger(CHUNK_SIZE_PROPERTY);
-    }
-
-    public void setChunkSize(Integer chunkSize) {
-        Integer oldValue = getChunkSize();
-        configuration.set(CHUNK_SIZE_PROPERTY, chunkSize);
-        firePropertyChange(CHUNK_SIZE_PROPERTY, oldValue, getChunkSize());
-    }
-
-    public Integer getQueueSize() {
-        return configuration.getInteger(QUEUE_SIZE_PROPERTY);
-    }
-
-    public void setQueueSize(Integer queueSize) {
-        Integer oldValue = getQueueSize();
-        configuration.set(QUEUE_SIZE_PROPERTY, queueSize);
-        firePropertyChange(QUEUE_SIZE_PROPERTY, oldValue, getQueueSize());
-    }
-
-    public Integer getStationPosition() {
-        return configuration.getInteger(STATION_POSITION_PROPERTY);
-    }
-
-    public void setStationPosition(Integer stationPosition) {
-        Integer oldValue = getStationPosition();
-        configuration.set(STATION_POSITION_PROPERTY, stationPosition);
+    public void setStationPosition(final Integer stationPosition) {
+        final Integer oldValue = getStationPosition();
+        this.configuration.set(STATION_POSITION_PROPERTY, stationPosition);
         firePropertyChange(STATION_POSITION_PROPERTY, oldValue, getStationPosition());
     }
 
-    public Mode getWaitMode() {
-        return Mode.valueOf(configuration.get(WAIT_MODE_PROPERTY));
-    }
-
-    public void setWaitMode(Mode waitMode) {
-        Mode oldValue = getWaitMode();
-        configuration.set(WAIT_MODE_PROPERTY, waitMode.name());
-        firePropertyChange(WAIT_MODE_PROPERTY, oldValue, getWaitMode());
-    }
-
-    public Integer getWaitTime() {
-        return configuration.getInteger(WAIT_TIME_PROPERTY);
-    }
-
-    public void setWaitTime(Integer waitTime) {
-        Integer oldValue = getWaitTime();
-        configuration.set(WAIT_TIME_PROPERTY, waitTime);
-        firePropertyChange(WAIT_TIME_PROPERTY, oldValue, getWaitTime());
-    }
-
-    public Integer getPrescale() {
-        return configuration.getInteger(PRESCALE_PROPERTY);
-    }
-
-    public void setPrescale(Integer prescale) {
-        Integer oldValue = getPrescale();
-        configuration.set(PRESCALE_PROPERTY, prescale);
-        firePropertyChange(PRESCALE_PROPERTY, oldValue, getPrescale());
-    }
-
-    public void setUserRunNumber(Integer userRunNumber) {
+    public void setSteeringFile(final String steeringFile) {
+        final String oldValue = getSteeringFile();
+        this.configuration.set(STEERING_FILE_PROPERTY, steeringFile);
+        firePropertyChange(STEERING_FILE_PROPERTY, oldValue, getSteeringFile());
+    }
+
+    public void setSteeringResource(final String steeringResource) {
+        final String oldValue = getSteeringResource();
+        this.configuration.set(STEERING_RESOURCE_PROPERTY, steeringResource);
+        firePropertyChange(STEERING_RESOURCE_PROPERTY, oldValue, steeringResource);
+    }
+
+    public void setSteeringType(final SteeringType steeringType) {
+        final SteeringType oldValue = getSteeringType();
+        this.configuration.set(STEERING_TYPE_PROPERTY, steeringType.name());
+        firePropertyChange(STEERING_TYPE_PROPERTY, oldValue, getSteeringType());
+    }
+
+    public void setUserRunNumber(final Integer userRunNumber) {
         Integer oldValue = null;
         if (hasPropertyKey(USER_RUN_NUMBER_PROPERTY)) {
             oldValue = getUserRunNumber();
         }
-        configuration.set(USER_RUN_NUMBER_PROPERTY, userRunNumber);
+        this.configuration.set(USER_RUN_NUMBER_PROPERTY, userRunNumber);
         firePropertyChange(USER_RUN_NUMBER_PROPERTY, oldValue, getUserRunNumber());
     }
 
-    public Integer getUserRunNumber() {
-        return configuration.getInteger(USER_RUN_NUMBER_PROPERTY);
-    }
-
-    public void setFreezeConditions(Boolean freezeConditions) {
-        Boolean oldValue = null;
-        if (hasPropertyKey(FREEZE_CONDITIONS_PROPERTY)) {
-            oldValue = getFreezeConditions();
-        }
-        configuration.set(FREEZE_CONDITIONS_PROPERTY, freezeConditions);
-        firePropertyChange(FREEZE_CONDITIONS_PROPERTY, oldValue, freezeConditions);
-    }
-
-    public Boolean getFreezeConditions() {
-        return configuration.getBoolean(FREEZE_CONDITIONS_PROPERTY);
-    }
-
-    public void setMaxEvents(Long maxEvents) {
-        Long oldValue = getMaxEvents();
-        configuration.set(MAX_EVENTS_PROPERTY, maxEvents);
-        firePropertyChange(MAX_EVENTS_PROPERTY, oldValue, getMaxEvents());
-    }
-
-    public Long getMaxEvents() {
-        return configuration.getLong(MAX_EVENTS_PROPERTY);
-    }
-       
-    public String getEtPath() {
-        return getEtName() + "@" + getHost() + ":" + getPort();
-    }
-    
-    public void setConditionsTag(String conditionsTag) {
-        String oldValue = getConditionsTag();
-        configuration.set(CONDITIONS_TAG_PROPERTY, conditionsTag);
-        firePropertyChange(CONDITIONS_TAG_PROPERTY, oldValue, getConditionsTag());
-    }     
-    
-    public String getConditionsTag() {
-        return configuration.get(CONDITIONS_TAG_PROPERTY);
-    }
-    
-    public void setAIDAServerName(String AIDAServerName) {
-        String oldValue = getAIDAServerName();
-        configuration.set(AIDA_SERVER_NAME_PROPERTY, AIDAServerName);
-        firePropertyChange(AIDA_SERVER_NAME_PROPERTY, oldValue, getAIDAServerName());
-    } 
-    
-    public String getAIDAServerName() {
-        return configuration.get(AIDA_SERVER_NAME_PROPERTY);
-    }
-    
-    public String getRecentFiles() {
-        if (configuration.hasKey(RECENT_FILES_PROPERTY)) {
-            return configuration.get(RECENT_FILES_PROPERTY);
-        } else {
-            return null;
-        }         
-    }
-    
-    public List<String> getRecentFilesList() {
-        List<String> recentFilesList = new ArrayList<String>();
-        if (configuration.hasKey(RECENT_FILES_PROPERTY)) {
-            for (String recentFile : configuration.get(RECENT_FILES_PROPERTY).split("\n")) {
-                recentFilesList.add(recentFile);
-            }
-        }
-        return recentFilesList;
-    }
-    
-    public void addRecentFile(String recentFile) {
-        if (!configuration.checkKey(RECENT_FILES_PROPERTY)) {
-            configuration.set(RECENT_FILES_PROPERTY, recentFile);
-            firePropertyChange(RECENT_FILES_PROPERTY, null, recentFile);
-        } else {
-            List<String> recentFilesList = getRecentFilesList();
-            if (!recentFilesList.contains(recentFile)) {            
-                if (getRecentFilesList().size() >= 10) {
-                    throw new IllegalArgumentException("Maximum number of recent files reached.");
-                }                                   
-                String oldValue = configuration.get(RECENT_FILES_PROPERTY);
-                String recentFiles = oldValue + "\n" + recentFile;
-                configuration.set(RECENT_FILES_PROPERTY, recentFiles);
-                firePropertyChange(RECENT_FILES_PROPERTY, oldValue, recentFile);
-            }
-        }
-        
-    }
-    
-    public void setRecentFiles(String recentFiles) {
-        String oldValue = null;
-        if (configuration.checkKey(RECENT_FILES_PROPERTY)) {
-            oldValue = configuration.get(RECENT_FILES_PROPERTY);
-        }
-        configuration.set(RECENT_FILES_PROPERTY, recentFiles);
-        firePropertyChange(RECENT_FILES_PROPERTY, oldValue, configuration.get(RECENT_FILES_PROPERTY));
-    }
-
-    public void remove(String property) {
-        if (hasPropertyKey(property)) {
-            Object oldValue = configuration.get(property);
-            if (oldValue != null) {
-                configuration.remove(property);
-                firePropertyChange(property, oldValue, null);
-            }
-        }
-    }
-
-    public boolean hasPropertyKey(String key) {
-        return configuration.hasKey(key);
-    }
-
-    public boolean hasValidProperty(String key) {
-        return configuration.checkKey(key);
-    }
-
-    @Override
-    public String[] getPropertyNames() {
-        return CONFIG_PROPERTIES;
-    }    
-    
-    public void fireModelChanged() {
-        firePropertiesChanged(configuration.getKeys());
-    }    
-    
-    public void merge(Configuration configuration) {
-        this.configuration.merge(configuration);
-        this.firePropertiesChanged(configuration.getKeys());
+    public void setVerbose(final Boolean verbose) {
+        final Boolean oldValue = getVerbose();
+        this.configuration.set(VERBOSE_PROPERTY, verbose);
+        firePropertyChange(VERBOSE_PROPERTY, oldValue, getVerbose());
+    }
+
+    public void setWaitMode(final Mode waitMode) {
+        final Mode oldValue = getWaitMode();
+        this.configuration.set(WAIT_MODE_PROPERTY, waitMode.name());
+        firePropertyChange(WAIT_MODE_PROPERTY, oldValue, getWaitMode());
+    }
+
+    public void setWaitTime(final Integer waitTime) {
+        final Integer oldValue = getWaitTime();
+        this.configuration.set(WAIT_TIME_PROPERTY, waitTime);
+        firePropertyChange(WAIT_TIME_PROPERTY, oldValue, getWaitTime());
     }
 }

Modified: java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/model/ConnectionStatus.java
 =============================================================================
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/model/ConnectionStatus.java	(original)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/model/ConnectionStatus.java	Thu Apr  9 19:22:57 2015
@@ -3,23 +3,22 @@
 import java.awt.Color;
 
 /**
- * This is the status of the connection to the ET server from the monitoring client,
- * and it includes a color that should be displayed in the GUI for the associated
- * text.
+ * This is the status of the connection to the ET server from the monitoring client, and it includes a color that should
+ * be displayed in the GUI for the associated text.
+ *
+ * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a>
  */
 public enum ConnectionStatus {
 
-    DISCONNECTED(Color.RED),
-    DISCONNECTING(Color.YELLOW),
-    CONNECTED(Color.GREEN);
-    
-    Color color;    
-    
-    ConnectionStatus(Color color) {
+    CONNECTED(Color.GREEN), DISCONNECTED(Color.RED), DISCONNECTING(Color.YELLOW);
+
+    Color color;
+
+    ConnectionStatus(final Color color) {
         this.color = color;
     }
-    
+
     public Color getColor() {
-        return color;
+        return this.color;
     }
 }

Modified: java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/model/ConnectionStatusModel.java
 =============================================================================
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/model/ConnectionStatusModel.java	(original)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/model/ConnectionStatusModel.java	Thu Apr  9 19:22:57 2015
@@ -4,62 +4,60 @@
 import java.beans.PropertyChangeListener;
 
 /**
- * This model updates listeners when the connection status changes from disconnected
- * to connected or vice versa.  It will also notify when the event processing is 
- * paused.
- * 
- * @author Jeremy McCormick <[log in to unmask]>
+ * This model updates listeners when the connection status changes from disconnected to connected or vice versa. It will
+ * also notify when the event processing is paused.
+ *
+ * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a>
  */
 public final class ConnectionStatusModel extends AbstractModel {
-    
+
     public static final String CONNECTION_STATUS_PROPERTY = "ConnectionStatus";
     public static final String PAUSED_PROPERTY = "Paused";
-    
-    static final String[] propertyNames = new String[] { 
-        CONNECTION_STATUS_PROPERTY, 
-        PAUSED_PROPERTY 
-    };
+
+    static final String[] propertyNames = new String[] { CONNECTION_STATUS_PROPERTY, PAUSED_PROPERTY };
 
     ConnectionStatus connectionStatus = ConnectionStatus.DISCONNECTED;
     boolean paused = false;
-    
+
+    public ConnectionStatus getConnectionStatus() {
+        return this.connectionStatus;
+    }
+
+    public boolean getPaused() {
+        return this.paused;
+    }
+
+    @Override
     public String[] getPropertyNames() {
         return propertyNames;
     }
-    
-    public ConnectionStatus getConnectionStatus() {
-        return connectionStatus;
+
+    public boolean isConnected() {
+        return this.connectionStatus == ConnectionStatus.CONNECTED;
     }
-    
-    public void setConnectionStatus(ConnectionStatus connectionStatus) {
-        ConnectionStatus oldValue = connectionStatus;
+
+    public boolean isDisconnected() {
+        return this.connectionStatus == ConnectionStatus.DISCONNECTED;
+    }
+
+    public boolean isDisconnecting() {
+        return this.connectionStatus == ConnectionStatus.DISCONNECTING;
+    }
+
+    public void setConnectionStatus(final ConnectionStatus connectionStatus) {
+        final ConnectionStatus oldValue = connectionStatus;
         this.connectionStatus = connectionStatus;
-        for (PropertyChangeListener listener : propertyChangeSupport.getPropertyChangeListeners()) {
-            listener.propertyChange(new PropertyChangeEvent(this, CONNECTION_STATUS_PROPERTY, oldValue, this.connectionStatus));
+        for (final PropertyChangeListener listener : this.propertyChangeSupport.getPropertyChangeListeners()) {
+            listener.propertyChange(new PropertyChangeEvent(this, CONNECTION_STATUS_PROPERTY, oldValue,
+                    this.connectionStatus));
         }
-    }        
-    
-    public boolean getPaused() {
-        return paused;
     }
-    
-    public void setPaused(boolean paused) {
-        boolean oldValue = this.paused;
+
+    public void setPaused(final boolean paused) {
+        final boolean oldValue = this.paused;
         this.paused = paused;
-        for (PropertyChangeListener listener : propertyChangeSupport.getPropertyChangeListeners()) {
+        for (final PropertyChangeListener listener : this.propertyChangeSupport.getPropertyChangeListeners()) {
             listener.propertyChange(new PropertyChangeEvent(this, PAUSED_PROPERTY, oldValue, this.paused));
         }
     }
-    
-    public boolean isConnected() {
-        return this.connectionStatus == ConnectionStatus.CONNECTED;
-    }
-    
-    public boolean isDisconnected() {
-        return this.connectionStatus == ConnectionStatus.DISCONNECTED;
-    }
-    
-    public boolean isDisconnecting() {
-        return this.connectionStatus == ConnectionStatus.DISCONNECTING;
-    }
 }

Modified: java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/model/HasConfigurationModel.java
 =============================================================================
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/model/HasConfigurationModel.java	(original)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/model/HasConfigurationModel.java	Thu Apr  9 19:22:57 2015
@@ -2,18 +2,22 @@
 
 /**
  * Mix-in interface for classes that have an associated {@link ConfigurationModel}.
+ *
+ * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a>
  */
 public interface HasConfigurationModel {
 
     /**
+     * Get the current ConfigurationModel of the object.
+     * 
+     * @return The ConfigurationModel.
+     */
+    ConfigurationModel getConfigurationModel();
+
+    /**
      * Set the ConfigurationModel of the object.
+     * 
      * @param configurationModel The ConfigurationModel.
      */
     void setConfigurationModel(ConfigurationModel configurationModel);
-
-    /**
-     * Get the current ConfigurationModel of the object.
-     * @return The ConfigurationModel.
-     */
-    ConfigurationModel getConfigurationModel();
 }

Modified: java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/model/RunModel.java
 =============================================================================
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/model/RunModel.java	(original)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/model/RunModel.java	Thu Apr  9 19:22:57 2015
@@ -4,161 +4,98 @@
 
 /**
  * Backing model for run information that shows in the {@link org.hps.monitoring.application.EventDashboard}.
+ *
+ * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a>
  */
 public final class RunModel extends AbstractModel {
 
+    public final static String DATA_RATE_PROPERTY = "DataRate"; // data rate in megabytes per second
+    public final static String DATA_RECEIVED_PROPERTY = "DataReceived"; // updated on the fly, in bytes
+    public final static String ELAPSED_TIME_PROPERTY = "ElapsedTime"; // updated on the fly, in seconds
+    public final static String END_DATE_PROPERTY = "EndDate";
+    public final static String EVENT_NUMBER_PROPERTY = "EventNumber"; // current event number
+    public final static String EVENT_RATE_PROPERTY = "EventRate"; // event rate per second
+    public final static String EVENTS_RECEIVED_PROPERTY = "EventsReceived"; // events received so far
+    public final static String RUN_LENGTH_PROPERTY = "RunLength"; // set at end, in seconds
     public final static String RUN_NUMBER_PROPERTY = "RunNumber";
+    static final String[] RUN_PROPERTIES = AbstractModel.getPropertyNames(RunModel.class);
     public final static String START_DATE_PROPERTY = "StartDate";
-    public final static String END_DATE_PROPERTY = "EndDate";
-    public final static String RUN_LENGTH_PROPERTY = "RunLength"; // set at end, in seconds
+
     public final static String TOTAL_EVENTS_PROPERTY = "TotalEvents"; // only set at end
-    public final static String EVENTS_RECEIVED_PROPERTY = "EventsReceived"; // events received so far
-    public final static String ELAPSED_TIME_PROPERTY = "ElapsedTime"; // updated on the fly, in seconds
-    public final static String DATA_RECEIVED_PROPERTY = "DataReceived"; // updated on the fly, in bytes
-    public final static String EVENT_NUMBER_PROPERTY = "EventNumber"; // current event number
-    public final static String DATA_RATE_PROPERTY = "DataRate"; // data rate in megabytes per second
-    public final static String EVENT_RATE_PROPERTY = "EventRate"; // event rate per second
 
-    static final String[] RUN_PROPERTIES = AbstractModel.getPropertyNames(RunModel.class);
-    
+    Double dataRate;
+    Double dataReceived;
+    Integer elapsedTime;
+    Date endDate;
+    Integer eventNumber;
+    Double eventRate;
+    Integer eventsReceived;
+    Integer runLength;
     Integer runNumber;
     Date startDate;
-    Date endDate;
-    Integer runLength;
     Integer totalEvents;
-    Integer eventsReceived;
-    Integer elapsedTime;
-    Double dataReceived;
-    Integer eventNumber;
-    Double dataRate;
-    Double eventRate;
 
+    public void addDataReceived(final double addDataReceived) {
+        this.setDataReceived(this.dataReceived + addDataReceived);
+    }
+
+    public void computeRunLength() {
+        if (this.startDate != null && this.endDate != null) {
+            final long elapsedMillis = this.endDate.getTime() - this.startDate.getTime();
+            final int elapsedSeconds = (int) (elapsedMillis / 1000.);
+            this.setRunLength(elapsedSeconds);
+        }
+    }
+
+    public double getDataRate() {
+        return this.dataRate;
+    }
+
+    public double getDataReceived() {
+        return this.dataReceived;
+    }
+
+    public int getElapsedTime() {
+        return this.elapsedTime;
+    }
+
+    public Date getEndDate() {
+        return this.endDate;
+    }
+
+    public int getEventNumber() {
+        return this.eventNumber;
+    }
+
+    public double getEventRate() {
+        return this.eventRate;
+    }
+
+    public int getEventsReceived() {
+        return this.eventsReceived;
+    }
+
+    @Override
     public String[] getPropertyNames() {
         return RUN_PROPERTIES;
     }
 
-    public void setRunNumber(int runNumber) {
-        Integer oldValue = this.runNumber;
-        this.runNumber = runNumber;
-        this.firePropertyChange(RUN_NUMBER_PROPERTY, oldValue, this.runNumber);
+    public int getRunLength() {
+        return this.runLength;
     }
-    
+
     public int getRunNumber() {
         return this.runNumber;
     }
 
-    public void setStartDate(Date startDate) {
-        Date oldValue = this.startDate;
-        this.startDate = startDate;
-        this.firePropertyChange(START_DATE_PROPERTY, oldValue, this.startDate);
-    }
-    
     public Date getStartDate() {
-        return startDate;
+        return this.startDate;
     }
 
-    public void setEndDate(Date endDate) {
-        Date oldValue = this.endDate;
-        this.endDate = endDate;
-        this.firePropertyChange(END_DATE_PROPERTY, oldValue, this.endDate);
-    }
-    
-    public Date getEndDate() {
-        return endDate;
+    public int getTotalEvents() {
+        return this.totalEvents;
     }
 
-    public void setRunLength(int runLength) {
-        Integer oldValue = this.runLength;
-        this.runLength = runLength;
-        this.firePropertyChange(RUN_LENGTH_PROPERTY, oldValue, this.runLength);
-    }
-    
-    public int getRunLength() {
-        return runLength;
-    }
-
-    public void computeRunLength() {
-        if (startDate != null && endDate != null) {
-            long elapsedMillis = endDate.getTime() - startDate.getTime();
-            int elapsedSeconds = (int) ((double) elapsedMillis / 1000.);
-            this.setRunLength(elapsedSeconds);
-        }
-    }
-
-    public void setTotalEvents(int totalEvents) {
-        Integer oldValue = this.totalEvents;
-        this.totalEvents = totalEvents;
-        this.firePropertyChange(TOTAL_EVENTS_PROPERTY, oldValue, this.totalEvents);
-    }
-    
-    public int getTotalEvents() {
-        return totalEvents;
-    }
-
-    public void setEventsReceived(int eventsReceived) {
-        Integer oldValue = this.eventsReceived;
-        this.eventsReceived = eventsReceived;
-        this.firePropertyChange(EVENTS_RECEIVED_PROPERTY, oldValue, this.eventsReceived);
-    }
-    
-    public int getEventsReceived() {
-        return eventsReceived;
-    }
-
-    public void setElapsedTime(int elapsedTime) {
-        Integer oldValue = this.elapsedTime;
-        this.elapsedTime = elapsedTime;
-        this.firePropertyChange(ELAPSED_TIME_PROPERTY, oldValue, this.elapsedTime);
-    }
-    
-    public int getElapsedTime() {
-        return elapsedTime;
-    }
-
-    public void setDataReceived(double dataReceived) {
-        Double oldValue = this.dataReceived;
-        this.dataReceived = dataReceived;
-        this.firePropertyChange(DATA_RECEIVED_PROPERTY, oldValue, this.dataReceived);
-    }
-    
-    public double getDataReceived() {
-        return dataReceived;
-    }
-
-    public void addDataReceived(double addDataReceived) {
-        this.setDataReceived(dataReceived + addDataReceived);
-    }
-
-    public void setEventNumber(int eventNumber) {
-        Integer oldValue = this.eventNumber;
-        this.eventNumber = eventNumber;
-        this.firePropertyChange(EVENT_NUMBER_PROPERTY, oldValue, this.eventNumber);
-    }
-    
-    public int getEventNumber() {
-        return eventNumber;
-    }
-    
-    public void setDataRate(double dataRate) {
-        Double oldValue = this.dataRate;
-        this.dataRate = dataRate;
-        this.firePropertyChange(DATA_RATE_PROPERTY, oldValue, this.dataRate);
-    }
-    
-    public double getDataRate() {
-        return dataRate;
-    }
-        
-    public void setEventRate(double eventRate) {
-        Double oldValue = this.eventRate;
-        this.eventRate = eventRate;
-        this.firePropertyChange(EVENT_RATE_PROPERTY, oldValue, this.eventRate);
-    }
-    
-    public double getEventRate() {
-        return eventRate;
-    }
-    
     public void reset() {
         setDataReceived(0);
         setElapsedTime(0);
@@ -168,5 +105,71 @@
         setRunNumber(0);
         setStartDate(null);
         setTotalEvents(0);
-    }    
+    }
+
+    public void setDataRate(final double dataRate) {
+        final Double oldValue = this.dataRate;
+        this.dataRate = dataRate;
+        this.firePropertyChange(DATA_RATE_PROPERTY, oldValue, this.dataRate);
+    }
+
+    public void setDataReceived(final double dataReceived) {
+        final Double oldValue = this.dataReceived;
+        this.dataReceived = dataReceived;
+        this.firePropertyChange(DATA_RECEIVED_PROPERTY, oldValue, this.dataReceived);
+    }
+
+    public void setElapsedTime(final int elapsedTime) {
+        final Integer oldValue = this.elapsedTime;
+        this.elapsedTime = elapsedTime;
+        this.firePropertyChange(ELAPSED_TIME_PROPERTY, oldValue, this.elapsedTime);
+    }
+
+    public void setEndDate(final Date endDate) {
+        final Date oldValue = this.endDate;
+        this.endDate = endDate;
+        this.firePropertyChange(END_DATE_PROPERTY, oldValue, this.endDate);
+    }
+
+    public void setEventNumber(final int eventNumber) {
+        final Integer oldValue = this.eventNumber;
+        this.eventNumber = eventNumber;
+        this.firePropertyChange(EVENT_NUMBER_PROPERTY, oldValue, this.eventNumber);
+    }
+
+    public void setEventRate(final double eventRate) {
+        final Double oldValue = this.eventRate;
+        this.eventRate = eventRate;
+        this.firePropertyChange(EVENT_RATE_PROPERTY, oldValue, this.eventRate);
+    }
+
+    public void setEventsReceived(final int eventsReceived) {
+        final Integer oldValue = this.eventsReceived;
+        this.eventsReceived = eventsReceived;
+        this.firePropertyChange(EVENTS_RECEIVED_PROPERTY, oldValue, this.eventsReceived);
+    }
+
+    public void setRunLength(final int runLength) {
+        final Integer oldValue = this.runLength;
+        this.runLength = runLength;
+        this.firePropertyChange(RUN_LENGTH_PROPERTY, oldValue, this.runLength);
+    }
+
+    public void setRunNumber(final int runNumber) {
+        final Integer oldValue = this.runNumber;
+        this.runNumber = runNumber;
+        this.firePropertyChange(RUN_NUMBER_PROPERTY, oldValue, this.runNumber);
+    }
+
+    public void setStartDate(final Date startDate) {
+        final Date oldValue = this.startDate;
+        this.startDate = startDate;
+        this.firePropertyChange(START_DATE_PROPERTY, oldValue, this.startDate);
+    }
+
+    public void setTotalEvents(final int totalEvents) {
+        final Integer oldValue = this.totalEvents;
+        this.totalEvents = totalEvents;
+        this.firePropertyChange(TOTAL_EVENTS_PROPERTY, oldValue, this.totalEvents);
+    }
 }

Modified: java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/model/SteeringType.java
 =============================================================================
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/model/SteeringType.java	(original)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/model/SteeringType.java	Thu Apr  9 19:22:57 2015
@@ -2,8 +2,9 @@
 
 /**
  * The type of steering to use for event processing.
+ *
+ * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a>
  */
 public enum SteeringType {
-    RESOURCE,
-    FILE;
+    FILE, RESOURCE;
 }

Modified: java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/model/SystemStatusTableModel.java
 =============================================================================
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/model/SystemStatusTableModel.java	(original)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/model/SystemStatusTableModel.java	Thu Apr  9 19:22:57 2015
@@ -16,32 +16,47 @@
 
 /**
  * A <code>JTableModel</code> that has a list of {@link org.hps.monitoring.subsys.SystemStatus} objects.
+ *
+ * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a>
  */
 public final class SystemStatusTableModel extends AbstractTableModel implements SystemStatusListener {
 
+    public static final int ACTIVE_COL = 1;
+    public static final int CLEARABLE_COL = 7;
+    static final String[] columnNames = { "Reset", "Active", "Status", "System", "Description", "Message",
+        "Last Changed", "Clearable" };
+    public static final int DESCRIPTION_COL = 4;
+    public static final int LAST_CHANGED_COL = 6;
+    public static final int MESSAGE_COL = 5;
     public static final int RESET_COL = 0;
-    public static final int ACTIVE_COL = 1;
     public static final int STATUS_COL = 2;
+
     public static final int SYSTEM_COL = 3;
-    public static final int DESCRIPTION_COL = 4;
-    public static final int MESSAGE_COL = 5;
-    public static final int LAST_CHANGED_COL = 6;
-    public static final int CLEARABLE_COL = 7;
 
-    static final String[] columnNames = { "Reset", "Active", "Status", "System", "Description", "Message", "Last Changed", "Clearable" };
+    final SimpleDateFormat dateFormat = new SimpleDateFormat("MMMM-dd-yyyy HH:mm:ss.SSS");
+    List<SystemStatus> statuses = new ArrayList<SystemStatus>();
 
-    List<SystemStatus> statuses = new ArrayList<SystemStatus>();
-    final SimpleDateFormat dateFormat = new SimpleDateFormat("MMMM-dd-yyyy HH:mm:ss.SSS");
-
-    public void addSystemStatus(SystemStatus status) {
-        statuses.add(status);
+    public void addSystemStatus(final SystemStatus status) {
+        this.statuses.add(status);
         status.addListener(this);
         fireTableDataChanged();
     }
 
+    public void clear() {
+        this.statuses.clear();
+        fireTableDataChanged();
+    }
+
     @Override
-    public int getRowCount() {
-        return statuses.size();
+    public Class getColumnClass(final int column) {
+        switch (column) {
+        case ACTIVE_COL:
+            return Boolean.class;
+        case LAST_CHANGED_COL:
+            return Date.class;
+        default:
+            return String.class;
+        }
     }
 
     @Override
@@ -50,13 +65,18 @@
     }
 
     @Override
-    public String getColumnName(int col) {
+    public String getColumnName(final int col) {
         return columnNames[col];
     }
 
     @Override
+    public int getRowCount() {
+        return this.statuses.size();
+    }
+
+    @Override
     public Object getValueAt(final int rowIndex, final int columnIndex) {
-        SystemStatus status = statuses.get(rowIndex);
+        final SystemStatus status = this.statuses.get(rowIndex);
         switch (columnIndex) {
         case ACTIVE_COL:
             return status.isActive();
@@ -77,13 +97,14 @@
             if (status.isClearable()) {
                 final JButton button = new JButton();
                 button.addActionListener(new ActionListener() {
-                    public void actionPerformed(ActionEvent e) {
-                        SystemStatus status = statuses.get(rowIndex);
+                    @Override
+                    public void actionPerformed(final ActionEvent e) {
+                        final SystemStatus status = SystemStatusTableModel.this.statuses.get(rowIndex);
                         // Only clearable statuses can have this state set. Check for this
                         // just to be safe, even though no button is available for non-clearable
                         // statuses.
                         if (status.isClearable()) {
-                            StatusCode oldStatusCode = status.getStatusCode();
+                            final StatusCode oldStatusCode = status.getStatusCode();
                             status.setStatus(StatusCode.CLEARED, "Cleared from " + oldStatusCode.name() + " state.");
                         }
                     }
@@ -100,40 +121,24 @@
     }
 
     @Override
-    public Class getColumnClass(int column) {
-        switch (column) {
-        case ACTIVE_COL:
-            return Boolean.class;
-        case LAST_CHANGED_COL:
-            return Date.class;
-        default:
-            return String.class;
+    public boolean isCellEditable(final int row, final int col) {
+        if (col == ACTIVE_COL) {
+            return true;
+        } else {
+            return false;
         }
     }
 
     @Override
-    public boolean isCellEditable(int row, int col) {
-        if (col == ACTIVE_COL)
-            return true;
-        else
-            return false;
+    public void setValueAt(final Object value, final int row, final int col) {
+        if (col == ACTIVE_COL) {
+            this.statuses.get(row).setActive((Boolean) value);
+        }
     }
 
     @Override
-    public void statusChanged(SystemStatus status) {
-        int rowNumber = statuses.indexOf(status);
+    public void statusChanged(final SystemStatus status) {
+        final int rowNumber = this.statuses.indexOf(status);
         fireTableRowsUpdated(rowNumber, rowNumber);
     }
-
-    public void clear() {
-        statuses.clear();
-        fireTableDataChanged();
-    }
-
-    @Override
-    public void setValueAt(Object value, int row, int col) {
-        if (col == ACTIVE_COL) {
-            statuses.get(row).setActive((Boolean) value);
-        }
-    }
 }

Modified: java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/package-info.java
 =============================================================================
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/package-info.java	(original)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/package-info.java	Thu Apr  9 19:22:57 2015
@@ -1,22 +1,19 @@
 /**
- * The Monitoring Application is a flexible framework for monitoring the 
- * event processing chain of the HPS experiment.  It implements the conversion
- * of ET byte buffers to EVIO and then the building of LCIO events from the 
- * raw EVIO data.
- * <p>  
- * It provides three primary GUI components: 
+ * The Monitoring Application is a flexible framework for monitoring the event processing chain of the HPS experiment in
+ * an online environment. It implements the conversion of ET byte buffers to EVIO and then the building of LCIO events
+ * from the raw EVIO data.
+ * <p>
+ * It provides three primary GUI components:
  * <ul>
  * <li>run dashboard showing basic information about data received</li>
- * <li>system status monitor that can monitor the status of specific subsystems</li>
+ * <li>tab panel showing various information panels</li>
  * <li>plotting window that displays any plots generated through the AIDA API</li>
  * </ul>
  * <p>
- * The FreeHep framework is used extensively for the record processing.  Every part
- * of the event processing chain uses the
- * <a href="http://java.freehep.org/freehep-record/">freehep-record</a>
- * module to manage the flow of records and activate any processors that are listening
- * on the record loops.
-
- * @author Jeremy McCormick <[log in to unmask]>
+ * The FreeHep framework is used extensively for the record processing. Every part of the event processing chain uses
+ * the <a href="http://java.freehep.org/freehep-record/">freehep-record</a> module to manage the flow of records and
+ * activate any processors that are listening on the record loops.
+ *
+ * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a>
  */
 package org.hps.monitoring.application;

Modified: java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/util/AIDAServer.java
 =============================================================================
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/util/AIDAServer.java	(original)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/util/AIDAServer.java	Thu Apr  9 19:22:57 2015
@@ -11,69 +11,74 @@
 
 /**
  * AIDA RMI server wrapper.
- * @author Jeremy McCormick <[log in to unmask]>
+ *
+ * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a>
  */
 public class AIDAServer {
-    
+
+    boolean connected = false;
+    String name;
     RmiServerImpl server;
-    String name;
-    boolean connected = false;
-   
+
     /**
-     * Class constructor. 
+     * Class constructor.
+     *
      * @param name The name of the AIDA server.
      */
-    public AIDAServer(String name) {
+    public AIDAServer(final String name) {
         this.name = name;
     }
-    
+
+    /**
+     * True if connected.
+     *
+     * @return True if connected to server.
+     */
+    public boolean connected() {
+        return this.connected;
+    }
+
+    /**
+     * Close the server down by disconnecting it.
+     */
+    public void disconnect() {
+        this.server.disconnect();
+        this.connected = false;
+    }
+
+    public String getName() {
+        try {
+            return InetAddress.getLocalHost().getCanonicalHostName() + this.server.getBindName() + ":"
+                    + RmiRemoteUtils.port;
+        } catch (final Exception e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
     /**
      * Set the name that will be used for the path part of the URL.
+     *
      * @param name The server's name.
      */
-    public void setName(String name) {
+    public void setName(final String name) {
         this.name = name;
     }
 
     /**
      * Start the remote AIDA server.
+     *
      * @return True if server started successfully; false if an error occurred during initialization.
      */
     public boolean start() {
-        RemoteServer treeServer = new RemoteServer((IDevTree) AIDA.defaultInstance().tree());
+        final RemoteServer treeServer = new RemoteServer((IDevTree) AIDA.defaultInstance().tree());
         try {
-            server = new RmiServerImpl(treeServer, "/" + name);
-            connected = true;
+            this.server = new RmiServerImpl(treeServer, "/" + this.name);
+            this.connected = true;
+        } catch (final Exception e) {
+            e.printStackTrace();
+            this.connected = false;
         }
-        catch (Exception e) {
-            e.printStackTrace();
-            connected = false;
-        }
-        return connected;
-    }
-    
-    /** 
-     * Close the server down by disconnecting it.
-     */
-    public void disconnect() {
-        server.disconnect();
-        connected = false;
-    }
-    
-    /**
-     * True if connected.
-     * @return True if connected to server.
-     */
-    public boolean connected() {
-        return connected;
-    }    
-    
-    public String getName() {
-        try {
-            return InetAddress.getLocalHost().getCanonicalHostName() + server.getBindName() + ":" + RmiRemoteUtils.port;
-        } catch (Exception e) {
-            e.printStackTrace();
-        }
-        return null;
+        return this.connected;
     }
 }

Modified: java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/util/DialogUtil.java
 =============================================================================
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/util/DialogUtil.java	(original)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/util/DialogUtil.java	Thu Apr  9 19:22:57 2015
@@ -7,27 +7,90 @@
 import javax.swing.JDialog;
 import javax.swing.JOptionPane;
 import javax.swing.SwingUtilities;
+import javax.swing.WindowConstants;
 
+/**
+ * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a>
+ */
 public final class DialogUtil {
 
     /**
-     * 
+     * @param parent
+     * @param message
+     * @param title
+     * @return
+     */
+    public static int showConfirmationDialog(final Component parent, final String title, final String message) {
+        final Object[] options = { "Yes", "No", "Cancel" };
+        final int result = JOptionPane.showOptionDialog(parent, message, title, JOptionPane.YES_NO_CANCEL_OPTION,
+                JOptionPane.QUESTION_MESSAGE, null, options, options[2]);
+        return result;
+    }
+
+    /**
+     * @param component
+     * @param error
+     * @param title
+     */
+    public static void showErrorDialog(final Component component, final String title, final String message) {
+        final Runnable runnable = new Runnable() {
+            @Override
+            public void run() {
+                JOptionPane.showMessageDialog(component, message, title, JOptionPane.ERROR_MESSAGE);
+            }
+        };
+        SwingUtilities.invokeLater(runnable);
+    }
+
+    /**
+     * @param component
+     * @param error
+     * @param title
+     */
+    public static void showErrorDialog(final Component component, final Throwable error, final String title) {
+        final Runnable runnable = new Runnable() {
+            @Override
+            public void run() {
+                JOptionPane.showMessageDialog(component, error.getMessage(), title, JOptionPane.ERROR_MESSAGE);
+            }
+        };
+        SwingUtilities.invokeLater(runnable);
+    }
+
+    /**
+     * @param component
+     * @param title
+     * @param message
+     */
+    public static void showInfoDialog(final Component component, final String title, final String message) {
+        final Runnable runnable = new Runnable() {
+            @Override
+            public void run() {
+                JOptionPane.showMessageDialog(component, message, title, JOptionPane.INFORMATION_MESSAGE);
+            }
+        };
+        SwingUtilities.invokeLater(runnable);
+    }
+
+    /**
      * @param parentComponent
      * @param title
      * @param message
      * @return
      */
-    public static JDialog showStatusDialog(final Component parentComponent, String title, String message) {
-        final JOptionPane optionPane = new JOptionPane(message, JOptionPane.INFORMATION_MESSAGE, JOptionPane.DEFAULT_OPTION, null, new Object[] {}, null);
+    public static JDialog showStatusDialog(final Component parentComponent, final String title, final String message) {
+        final JOptionPane optionPane = new JOptionPane(message, JOptionPane.INFORMATION_MESSAGE,
+                JOptionPane.DEFAULT_OPTION, null, new Object[] {}, null);
         final JDialog dialog = new JDialog();
         dialog.setContentPane(optionPane);
         dialog.setTitle(title);
         dialog.setAlwaysOnTop(true);
         dialog.setLocationRelativeTo(null);
-        dialog.setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE);
+        dialog.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
         dialog.pack();
         dialog.addWindowListener(new WindowAdapter() {
-            public void windowClosing(WindowEvent e) {
+            @Override
+            public void windowClosing(final WindowEvent e) {
                 dialog.setVisible(false);
                 dialog.dispose();
                 parentComponent.setEnabled(true);
@@ -38,70 +101,4 @@
         dialog.setVisible(true);
         return dialog;
     }
-
-    /**
-     * 
-     * @param component
-     * @param error
-     * @param title
-     */
-    public static void showErrorDialog(final Component component, final Throwable error, final String title) {
-        final Runnable runnable = new Runnable() {
-            public void run() {
-                JOptionPane.showMessageDialog(component, error.getMessage(), title, JOptionPane.ERROR_MESSAGE);
-            }
-        };
-        SwingUtilities.invokeLater(runnable);
-    }
-    
-    /**
-     * 
-     * @param component
-     * @param error
-     * @param title
-     */
-    public static void showErrorDialog(final Component component,  final String title, final String message) {
-        final Runnable runnable = new Runnable() {
-            public void run() {
-                JOptionPane.showMessageDialog(component, message, title, JOptionPane.ERROR_MESSAGE);
-            }
-        };
-        SwingUtilities.invokeLater(runnable);
-    }
-
-    /**
-     * 
-     * @param component
-     * @param title
-     * @param message
-     */
-    public static void showInfoDialog(final Component component, final String title, final String message) {
-        final Runnable runnable = new Runnable() {
-            public void run() {
-                JOptionPane.showMessageDialog(component, message, title, JOptionPane.INFORMATION_MESSAGE);
-            }
-        };
-        SwingUtilities.invokeLater(runnable);
-    }
-    
-    /**
-     * 
-     * @param parent
-     * @param message
-     * @param title
-     * @return
-     */
-    public static int showConfirmationDialog(final Component parent, final String title, final String message) {
-        Object[] options = { "Yes", "No", "Cancel" };
-        int result = JOptionPane.showOptionDialog(
-                parent, 
-                message, 
-                title, 
-                JOptionPane.YES_NO_CANCEL_OPTION, 
-                JOptionPane.QUESTION_MESSAGE, 
-                null, 
-                options, 
-                options[2]);
-        return result;
-    }
 }

Modified: java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/util/ErrorHandler.java
 =============================================================================
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/util/ErrorHandler.java	(original)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/util/ErrorHandler.java	Thu Apr  9 19:22:57 2015
@@ -9,8 +9,8 @@
 
 /**
  * <p>
- * An error handling class which is able to do any of the following, depending on how the users
- * wants to handle the error.
+ * An error handling class which is able to do any of the following, depending on how the users wants to handle the
+ * error.
  * </p>
  * <ul>
  * <li>Print a message</li>
@@ -20,109 +20,27 @@
  * <li>Raise an exception</li>
  * <li>Exit the application</li>
  * </ul>
- * </p> It mostly uses the "builder" pattern so that the various handling methods can be easily
- * chained, where appropriate. Some methods are not available for chaining when it doesn't make
- * sense. </p>
+ * </p> It mostly uses the "builder" pattern so that the various handling methods can be easily chained, where
+ * appropriate. Some methods are not available for chaining when it doesn't make sense. </p>
+ *
+ * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a>
  */
 public final class ErrorHandler {
 
-    Logger logger;
     Component component;
     Throwable error;
+    Logger logger;
     String message;
 
     /**
      * Constructor.
+     *
      * @param component The GUI component to which this object is assigned.
      * @param logger The logger to which messages will be written.
      */
-    public ErrorHandler(Component component, Logger logger) {
+    public ErrorHandler(final Component component, final Logger logger) {
         this.logger = logger;
         this.component = component;
-    }
-
-    /**
-     * Set the error that occurred. This should always be called first in a method chain.
-     * @param error The error which is a <code>Throwable</code>.
-     * @return This object.
-     */
-    public ErrorHandler setError(Throwable error) {
-        this.error = error;
-        this.message = error.getMessage();
-        return this;
-    }
-
-    /**
-     * Set the error message if it differs from the exception's message.
-     * @param message The erro message.
-     * @return This object.
-     */
-    public ErrorHandler setMessage(String message) {
-        this.message = message;
-        return this;
-    }
-
-    /**
-     * Print the full stack trace of the error to System.err.
-     * @return This object.
-     */
-    public ErrorHandler printStackTrace() {
-        error.printStackTrace();
-        return this;
-    }
-
-    /**
-     * Print the error message to System.err.
-     * @return This object.
-     */
-    public ErrorHandler printMessage() {
-        System.err.println(message);
-        return this;
-    }
-
-    /**
-     * Log the error message to the <code>Logger</code>.
-     * @return This object.
-     */
-    public ErrorHandler log() {
-        logger.log(Level.SEVERE, message, error);
-        return this;
-    }
-
-    /**
-     * Show an error dialog with the message.
-     * @return This object.
-     */
-    public ErrorHandler showErrorDialog() {
-        final Runnable runnable = new Runnable() {
-            public void run() {
-                JOptionPane.showMessageDialog(component, error.getMessage(), "Application Error", JOptionPane.ERROR_MESSAGE);
-            }
-        };
-        SwingUtilities.invokeLater(runnable);
-        return this;
-    }
-    
-    /**
-     * Show an error dialog with a custom message and title.
-     * @return This object.
-     */
-    public ErrorHandler showErrorDialog(final String message, final String title) {
-        final Runnable runnable = new Runnable() {
-            public void run() {
-                JOptionPane.showMessageDialog(component, message, title, JOptionPane.ERROR_MESSAGE);
-            }
-        };
-        SwingUtilities.invokeLater(runnable);
-        return this;
-    }
-
-    /**
-     * Rethrow the error as a <code>RuntimeException</code>. Additional methods cannot be chained to
-     * this as they would not be executed.
-     */
-    public void raiseException() {
-        throw new RuntimeException(message, error);
     }
 
     /**
@@ -132,4 +50,98 @@
         System.err.println("Fatal error.  Application will exit.");
         System.exit(1);
     }
+
+    /**
+     * Log the error message to the <code>Logger</code>.
+     *
+     * @return This object.
+     */
+    public ErrorHandler log() {
+        this.logger.log(Level.SEVERE, this.message, this.error);
+        return this;
+    }
+
+    /**
+     * Print the error message to System.err.
+     *
+     * @return This object.
+     */
+    public ErrorHandler printMessage() {
+        System.err.println(this.message);
+        return this;
+    }
+
+    /**
+     * Print the full stack trace of the error to System.err.
+     *
+     * @return This object.
+     */
+    public ErrorHandler printStackTrace() {
+        this.error.printStackTrace();
+        return this;
+    }
+
+    /**
+     * Rethrow the error as a <code>RuntimeException</code>. Additional methods cannot be chained to this as they would
+     * not be executed.
+     */
+    public void raiseException() {
+        throw new RuntimeException(this.message, this.error);
+    }
+
+    /**
+     * Set the error that occurred. This should always be called first in a method chain.
+     *
+     * @param error The error which is a <code>Throwable</code>.
+     * @return This object.
+     */
+    public ErrorHandler setError(final Throwable error) {
+        this.error = error;
+        this.message = error.getMessage();
+        return this;
+    }
+
+    /**
+     * Set the error message if it differs from the exception's message.
+     *
+     * @param message The erro message.
+     * @return This object.
+     */
+    public ErrorHandler setMessage(final String message) {
+        this.message = message;
+        return this;
+    }
+
+    /**
+     * Show an error dialog with the message.
+     *
+     * @return This object.
+     */
+    public ErrorHandler showErrorDialog() {
+        final Runnable runnable = new Runnable() {
+            @Override
+            public void run() {
+                JOptionPane.showMessageDialog(ErrorHandler.this.component, ErrorHandler.this.error.getMessage(),
+                        "Application Error", JOptionPane.ERROR_MESSAGE);
+            }
+        };
+        SwingUtilities.invokeLater(runnable);
+        return this;
+    }
+
+    /**
+     * Show an error dialog with a custom message and title.
+     *
+     * @return This object.
+     */
+    public ErrorHandler showErrorDialog(final String message, final String title) {
+        final Runnable runnable = new Runnable() {
+            @Override
+            public void run() {
+                JOptionPane.showMessageDialog(ErrorHandler.this.component, message, title, JOptionPane.ERROR_MESSAGE);
+            }
+        };
+        SwingUtilities.invokeLater(runnable);
+        return this;
+    }
 }

Modified: java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/util/EtSystemUtil.java
 =============================================================================
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/util/EtSystemUtil.java	(original)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/util/EtSystemUtil.java	Thu Apr  9 19:22:57 2015
@@ -6,28 +6,23 @@
 import org.hps.record.et.EtConnection;
 import org.jlab.coda.et.EtConstants;
 
+/**
+ * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a>
+ */
 public final class EtSystemUtil {
 
-    private EtSystemUtil() {        
+    public static EtConnection createEtConnection(final ConfigurationModel config) {
+        return EtConnection.createConnection(config.getEtName(), config.getHost(), config.getPort(),
+                config.getBlocking(), config.getQueueSize(), config.getPrescale(), config.getStationName(),
+                config.getStationPosition(), config.getWaitMode(), config.getWaitTime(), config.getChunkSize());
     }
-    
-    public static EtConnection createEtConnection(ConfigurationModel config) {
-        return EtConnection.createConnection(config.getEtName(), 
-                config.getHost(), 
-                config.getPort(), 
-                config.getBlocking(), 
-                config.getQueueSize(), 
-                config.getPrescale(), 
-                config.getStationName(), 
-                config.getStationPosition(), 
-                config.getWaitMode(), 
-                config.getWaitTime(), 
-                config.getChunkSize());
+
+    public static int[] createSelectArray() {
+        final int select[] = new int[EtConstants.stationSelectInts];
+        Arrays.fill(select, -1);
+        return select;
     }
-    
-    public static int[] createSelectArray() {
-        int select[] = new int[EtConstants.stationSelectInts];
-        Arrays.fill(select, -1);
-        return select;   
-    }    
+
+    private EtSystemUtil() {
+    }
 }

Modified: java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/util/EvioFileFilter.java
 =============================================================================
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/util/EvioFileFilter.java	(original)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/util/EvioFileFilter.java	Thu Apr  9 19:22:57 2015
@@ -5,24 +5,26 @@
 import javax.swing.filechooser.FileFilter;
 
 /**
- * This is a simple file filter that will accept files with ".evio" anywhere in their name. 
+ * This is a simple file filter that will accept files with ".evio" anywhere in their name.
+ *
+ * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a>
  */
 public final class EvioFileFilter extends FileFilter {
 
-    public EvioFileFilter() {            
+    public EvioFileFilter() {
     }
-    
+
     @Override
-    public boolean accept(File pathname) {
+    public boolean accept(final File pathname) {
         if (pathname.getName().contains(".evio") || pathname.isDirectory()) {
             return true;
         } else {
             return false;
         }
     }
-    
+
     @Override
     public String getDescription() {
         return "EVIO files";
-    }        
+    }
 }

Modified: java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/util/ResourceUtil.java
 =============================================================================
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/util/ResourceUtil.java	(original)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/util/ResourceUtil.java	Thu Apr  9 19:22:57 2015
@@ -19,106 +19,106 @@
 import org.reflections.Reflections;
 
 /**
- * 
- * @author Jeremy McCormick <[log in to unmask]>
- *
+ * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a>
  */
 public final class ResourceUtil {
 
-    private ResourceUtil() {        
-    }
-    
     /**
-     * Get the files with extension 'lcsim' from all loaded jar files.
-     * @param packageName The package name for filtering the resources.
-     * @return A list of embedded steering file resources.
-     */
-    public static String[] findSteeringResources(String packageName) {
-        List<String> resources = new ArrayList<String>();
-        URL url = ResourceUtil.class.getResource("ResourceUtil.class");
-        String scheme = url.getProtocol();
-        if (!"jar".equals(scheme)) {
-            throw new RuntimeException("Unsupported URL protocol: " + url.getProtocol());
-        }
-        try {
-            JarURLConnection con = (JarURLConnection) url.openConnection();
-            JarFile archive = con.getJarFile();
-            Enumeration<JarEntry> entries = archive.entries();
-            while (entries.hasMoreElements()) {
-                JarEntry entry = entries.nextElement();
-                if (entry.getName().endsWith(".lcsim") && entry.getName().contains(packageName)) {
-                    resources.add(entry.getName());
-                }
-            }
-            archive.close();
-        } catch (IOException e) {
-            throw new RuntimeException(e);
-        }
-        java.util.Collections.sort(resources);
-        String[] arr = new String[resources.size()];
-        for (int i = 0; i < arr.length; i++) {
-            arr[i] = resources.get(i);
-        }
-        return arr;
-    }
-    
-    /**
-     * Find all classes that implement {@link org.hps.record.LCSimEventBuilder} and return
-     * a list of their canonical names.
-     * @return The list of classes implementing LCSimEventBuilder.
-     */
-    public static String[] findEventBuilderClassNames() {
-        Reflections reflections = new Reflections("org.hps");
-        Set<Class<? extends LCSimEventBuilder>> subTypes = reflections.getSubTypesOf(LCSimEventBuilder.class);
-        Set<String> classNames = new HashSet<String>();
-        for (Class<? extends LCSimEventBuilder> type : subTypes) {
-            classNames.add(type.getCanonicalName());
-        }
-        return classNames.toArray(new String[classNames.size()]);        
-    }
- 
-    /**
-     * Find a list of available detector names.
-     * Only those detectors that have names starting with "HPS" in their
+     * Find a list of available detector names. Only those detectors that have names starting with "HPS" in their
      * detector.properties files will be returned.
+     *
      * @return The list of available detector names.
      */
     public static String[] findDetectorNames() {
-        ClassLoader classLoader = ResourceUtil.class.getClassLoader();
-        List<String> detectorNames = new ArrayList<String>();
-        URL url = ResourceUtil.class.getResource("ResourceUtil.class");
-        String protocol = url.getProtocol();
+        final ClassLoader classLoader = ResourceUtil.class.getClassLoader();
+        final List<String> detectorNames = new ArrayList<String>();
+        final URL url = ResourceUtil.class.getResource("ResourceUtil.class");
+        final String protocol = url.getProtocol();
         if (!"jar".equals(protocol)) {
             throw new RuntimeException("Unsupported URL protocol: " + url.getProtocol());
         }
         try {
-            JarURLConnection con = (JarURLConnection) url.openConnection();
-            JarFile archive = con.getJarFile();
-            Enumeration<JarEntry> entries = archive.entries();
+            final JarURLConnection con = (JarURLConnection) url.openConnection();
+            final JarFile archive = con.getJarFile();
+            final Enumeration<JarEntry> entries = archive.entries();
             while (entries.hasMoreElements()) {
-                JarEntry entry = entries.nextElement();
+                final JarEntry entry = entries.nextElement();
                 if (entry.getName().endsWith("detector.properties")) {
-                    InputStream inputStream = classLoader.getResourceAsStream(entry.getName());
+                    final InputStream inputStream = classLoader.getResourceAsStream(entry.getName());
                     if (inputStream == null) {
                         throw new RuntimeException("Failed to load jar entry: " + entry.getName());
                     }
-                    Properties properties = new Properties();
+                    final Properties properties = new Properties();
                     properties.load(inputStream);
-                    String detectorName = properties.getProperty("name");
+                    final String detectorName = properties.getProperty("name");
                     if (detectorName.startsWith("HPS")) {
                         detectorNames.add(detectorName);
                     }
                 }
             }
             archive.close();
-        } catch (IOException e) {
+        } catch (final IOException e) {
             throw new RuntimeException(e);
         }
         Collections.sort(detectorNames);
         return detectorNames.toArray(new String[detectorNames.size()]);
-    }        
-    
+    }
+
+    /**
+     * Find all classes that implement {@link org.hps.record.LCSimEventBuilder} and return a list of their canonical
+     * names.
+     *
+     * @return The list of classes implementing LCSimEventBuilder.
+     */
+    public static String[] findEventBuilderClassNames() {
+        final Reflections reflections = new Reflections("org.hps");
+        final Set<Class<? extends LCSimEventBuilder>> subTypes = reflections.getSubTypesOf(LCSimEventBuilder.class);
+        final Set<String> classNames = new HashSet<String>();
+        for (final Class<? extends LCSimEventBuilder> type : subTypes) {
+            classNames.add(type.getCanonicalName());
+        }
+        return classNames.toArray(new String[classNames.size()]);
+    }
+
+    /**
+     * Get the files with extension 'lcsim' from all loaded jar files.
+     *
+     * @param packageName The package name for filtering the resources.
+     * @return A list of embedded steering file resources.
+     */
+    public static String[] findSteeringResources(final String packageName) {
+        final List<String> resources = new ArrayList<String>();
+        final URL url = ResourceUtil.class.getResource("ResourceUtil.class");
+        final String scheme = url.getProtocol();
+        if (!"jar".equals(scheme)) {
+            throw new RuntimeException("Unsupported URL protocol: " + url.getProtocol());
+        }
+        try {
+            final JarURLConnection con = (JarURLConnection) url.openConnection();
+            final JarFile archive = con.getJarFile();
+            final Enumeration<JarEntry> entries = archive.entries();
+            while (entries.hasMoreElements()) {
+                final JarEntry entry = entries.nextElement();
+                if (entry.getName().endsWith(".lcsim") && entry.getName().contains(packageName)) {
+                    resources.add(entry.getName());
+                }
+            }
+            archive.close();
+        } catch (final IOException e) {
+            throw new RuntimeException(e);
+        }
+        java.util.Collections.sort(resources);
+        final String[] arr = new String[resources.size()];
+        for (int i = 0; i < arr.length; i++) {
+            arr[i] = resources.get(i);
+        }
+        return arr;
+    }
+
     public static String[] getConditionsTags() {
         return DatabaseConditionsManager.getInstance().getTags().toArray(new String[] {});
     }
+
+    private ResourceUtil() {
+    }
 }

Modified: java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/util/SyncEventProcessor.java
 =============================================================================
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/util/SyncEventProcessor.java	(original)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/util/SyncEventProcessor.java	Thu Apr  9 19:22:57 2015
@@ -15,11 +15,10 @@
 import org.lcsim.event.base.BaseLCSimEvent;
 
 /**
- * This is an ET event processor that will load DAQ configuration into the global manager 
- * from EVIO physics SYNC events, which have an event type in which bits 6 and 7 are set to 1.
- * 
- * @author Jeremy McCormick <[log in to unmask]>
- * 
+ * This is an ET event processor that will load DAQ configuration into the global manager from EVIO physics SYNC events,
+ * which have an event type in which bits 6 and 7 are set to 1.
+ *
+ * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a>
  * @see org.hps.recon.ecal.daqconfig.ConfigurationManager
  * @see org.hps.recon.ecal.daqconfig.EvioDAQParser
  */
@@ -28,7 +27,8 @@
     private static final String TRIGGER_CONFIG = "TriggerConfig";
     TriggerConfigEvioReader configReader = new TriggerConfigEvioReader();
 
-    public void process(EtEvent event) {
+    @Override
+    public void process(final EtEvent event) {
         EvioEvent evioEvent = null;
         try {
             evioEvent = new EvioReader(event.getDataBuffer()).parseNextEvent();
@@ -37,20 +37,20 @@
         }
         try {
             // Create a dummy LCIO event to satisfy the configuration reader's interface.
-            BaseLCSimEvent dummyLcsimEvent = 
-                    new BaseLCSimEvent(EvioEventUtilities.getRunNumber(evioEvent), evioEvent.getEventNumber(), "DUMMY", 0, false);
-            
+            final BaseLCSimEvent dummyLcsimEvent = new BaseLCSimEvent(EvioEventUtilities.getRunNumber(evioEvent),
+                    evioEvent.getEventNumber(), "DUMMY", 0, false);
+
             // Create the DAQ configuration object in the LCIO event.
-            configReader.getDAQConfig(evioEvent, dummyLcsimEvent);
-            
+            this.configReader.getDAQConfig(evioEvent, dummyLcsimEvent);
+
             // Update the global configuration if a configuration was created.
             if (dummyLcsimEvent.hasCollection(EvioDAQParser.class, TRIGGER_CONFIG)) {
-                List<EvioDAQParser> configList = dummyLcsimEvent.get(EvioDAQParser.class, TRIGGER_CONFIG);
+                final List<EvioDAQParser> configList = dummyLcsimEvent.get(EvioDAQParser.class, TRIGGER_CONFIG);
                 if (!configList.isEmpty()) {
                     ConfigurationManager.updateConfiguration(configList.get(0));
                 }
             }
-        } catch (Exception e) {
+        } catch (final Exception e) {
             System.err.println("Failed to load DAQ config from sync event ...");
             e.printStackTrace();
         }

Modified: java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/util/TableExporter.java
 =============================================================================
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/util/TableExporter.java	(original)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/application/util/TableExporter.java	Thu Apr  9 19:22:57 2015
@@ -8,55 +8,56 @@
 import javax.swing.table.TableModel;
 
 /**
- * This is a utility for exporting a JTable's model data to a text file.
- * Non-numeric fields are all contained in double quotes.
- * 
- * @author Jeremy McCormick <[log in to unmask]>
+ * This is a utility for exporting a JTable's model data to a text file. Non-numeric fields are all contained in double
+ * quotes.
+ *
+ * @author <a href="mailto:[log in to unmask]">Jeremy McCormick</a>
  */
 public final class TableExporter {
-    
-    private TableExporter() {
-    }
-    
+
     /**
      * Export the given table to a text file.
+     *
      * @param table The JTable component.
      * @param path The output file path.
      * @param fieldDelimiter The field delimiter to use.
      * @throws IOException if there are errors writing the file.
      */
-    public static void export(JTable table, String path, char fieldDelimiter) throws IOException {
-        
-        StringBuffer buffer = new StringBuffer();
-        TableModel model = table.getModel();
-        int rowCount = model.getRowCount();
-        int columnCount = model.getColumnCount();
-        
+    public static void export(final JTable table, final String path, final char fieldDelimiter) throws IOException {
+
+        final StringBuffer buffer = new StringBuffer();
+        final TableModel model = table.getModel();
+        final int rowCount = model.getRowCount();
+        final int columnCount = model.getColumnCount();
+
         // Column headers.
         for (int columnIndex = 0; columnIndex < columnCount; columnIndex++) {
             buffer.append("\"" + model.getColumnName(columnIndex) + "\"" + fieldDelimiter);
-        }        
+        }
         buffer.setLength(buffer.length() - 1);
         buffer.append('\n');
-        
+
         // Row data.
         for (int rowIndex = 0; rowIndex < rowCount; rowIndex++) {
             for (int columnIndex = 0; columnIndex < columnCount; columnIndex++) {
-                Object value = model.getValueAt(rowIndex, columnIndex);
+                final Object value = model.getValueAt(rowIndex, columnIndex);
                 if (Number.class.isAssignableFrom(model.getColumnClass(columnIndex))) {
                     buffer.append(value);
                 } else {
                     buffer.append("\"" + value + "\"" + fieldDelimiter);
                 }
-            }    
+            }
             buffer.setLength(buffer.length() - 1);
             buffer.append('\n');
         }
-                        
+
         // Write string buffer to file.
-        BufferedWriter out = new BufferedWriter(new FileWriter(path));
+        final BufferedWriter out = new BufferedWriter(new FileWriter(path));
         out.write(buffer.toString());
         out.flush();
         out.close();
-    }    
+    }
+
+    private TableExporter() {
+    }
 }

Top of Message | Previous Page | Permalink

Advanced Options


Options

Log In

Log In

Get Password

Get Password


Search Archives

Search Archives


Subscribe or Unsubscribe

Subscribe or Unsubscribe


Archives

November 2017
August 2017
July 2017
January 2017
December 2016
November 2016
October 2016
September 2016
August 2016
July 2016
June 2016
May 2016
April 2016
March 2016
February 2016
January 2016
December 2015
November 2015
October 2015
September 2015
August 2015
July 2015
June 2015
May 2015
April 2015
March 2015
February 2015
January 2015
December 2014
November 2014
October 2014
September 2014
August 2014
July 2014
June 2014
May 2014
April 2014
March 2014
February 2014
January 2014
December 2013
November 2013

ATOM RSS1 RSS2



LISTSERV.SLAC.STANFORD.EDU

Secured by F-Secure Anti-Virus CataList Email List Search Powered by the LISTSERV Email List Manager

Privacy Notice, Security Notice and Terms of Use