Print

Print


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() {
+    }
 }