Print

Print


Commit in java/trunk/monitoring-app/src/main on MAIN
java/org/hps/monitoring/config/Configurable.java+1831 -> 832
                              /Configuration.java-1831 -> 832
java/org/hps/monitoring/gui/AbstractFieldsPanel.java+7-4831 -> 832
                           /ConnectionSettingsPanel.java-1831 -> 832
                           /JobSettingsPanel.java+218-345831 -> 832
                           /MonitoringApplication.java+81-105831 -> 832
                           /MonitoringCommands.java+10-2831 -> 832
                           /SettingsPanel.java+2-2831 -> 832
                           /SystemStatusFrame.java+7-6831 -> 832
                           /SystemStatusTableModel.java-149831 removed
java/org/hps/monitoring/gui/model/AbstractModel.java+75added 832
                                 /ConfigurationModel.java+172added 832
                                 /HasConfigurationModel.java+9added 832
java/org/hps/monitoring/record/EventProcessingChain.java+14831 -> 832
                              /EvioProcessingStep.java+1831 -> 832
                              /LcioProcessingStep.java+3-1831 -> 832
java/org/hps/monitoring/record/composite/CompositeRecord.java+20-1831 -> 832
                                        /CompositeRecordLoop.java+11-1831 -> 832
                                        /CompositeRecordSource.java+4-1831 -> 832
java/org/hps/monitoring/subsys/SystemStatisticsImpl.java+3-1831 -> 832
resources/org/hps/monitoring/config/default_config.prop+11-11831 -> 832
+649-631
3 added + 1 removed + 17 modified, total 21 files
Checkin on work in progress.

java/trunk/monitoring-app/src/main/java/org/hps/monitoring/config
Configurable.java 831 -> 832
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/config/Configurable.java	2014-07-29 22:02:20 UTC (rev 831)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/config/Configurable.java	2014-07-30 19:56:08 UTC (rev 832)
@@ -6,6 +6,7 @@
  * these operations may vary by type of object.
  * @author Jeremy McCormick <[log in to unmask]>
  */
+// FIXME: This should probably be removed once ConfigurationModel is being used instead.
 public interface Configurable {
     
     /**

java/trunk/monitoring-app/src/main/java/org/hps/monitoring/config
Configuration.java 831 -> 832
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/config/Configuration.java	2014-07-29 22:02:20 UTC (rev 831)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/config/Configuration.java	2014-07-30 19:56:08 UTC (rev 832)
@@ -9,7 +9,6 @@
 
 /**
  * This class provides a list of key, value pairs backed by a <code>Properties</code> object.
- * It can be used to configure objects such as GUI panels.
  * @author Jeremy McCormick <[log in to unmask]>
  */
 public class Configuration {

java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui
AbstractFieldsPanel.java 831 -> 832
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui/AbstractFieldsPanel.java	2014-07-29 22:02:20 UTC (rev 831)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui/AbstractFieldsPanel.java	2014-07-30 19:56:08 UTC (rev 832)
@@ -9,6 +9,7 @@
 import javax.swing.JButton;
 import javax.swing.JCheckBox;
 import javax.swing.JComboBox;
+import javax.swing.JFormattedTextField;
 import javax.swing.JLabel;
 import javax.swing.JPanel;
 import javax.swing.JTextField;
@@ -71,8 +72,8 @@
      * @param editable The editable setting.
      * @return The JTextField component.
      */
-    protected final JTextField addField(String name, String value, String tooltip, int size, boolean editable) {
-        JTextField f = addField(name, value, size, editable);
+    protected final JFormattedTextField addField(String name, String value, String tooltip, int size, boolean editable) {
+        JFormattedTextField f = addField(name, value, size, editable);
         f.setToolTipText(tooltip);
         return f;
     }
@@ -85,7 +86,7 @@
      * @param editable The editable setting.
      * @return The JTextField component.
      */
-    protected final JTextField addField(String name, String value, int size, boolean editable) {
+    protected final JFormattedTextField addField(String name, String value, int size, boolean editable) {
         GridBagConstraints c = new GridBagConstraints();
         c.gridx = 0;
         c.gridy = currY;
@@ -99,7 +100,9 @@
         c.gridy = currY;
         c.insets = insets;
         c.anchor = GridBagConstraints.EAST;
-        JTextField field = new JTextField(value, size);
+        //JFormattedTextField field = new JFormattedTextField(value, size);
+        JFormattedTextField field = new JFormattedTextField(value);
+        field.setColumns(size);
         field.setHorizontalAlignment(JTextField.RIGHT);
         field.setEditable(editable);
         field.setBackground(Color.WHITE);

java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui
ConnectionSettingsPanel.java 831 -> 832
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui/ConnectionSettingsPanel.java	2014-07-29 22:02:20 UTC (rev 831)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui/ConnectionSettingsPanel.java	2014-07-30 19:56:08 UTC (rev 832)
@@ -5,7 +5,6 @@
 
 import javax.swing.JCheckBox;
 import javax.swing.JComboBox;
-import javax.swing.JOptionPane;
 import javax.swing.JTextField;
 
 import org.hps.monitoring.config.Configurable;

java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui
JobSettingsPanel.java 831 -> 832
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui/JobSettingsPanel.java	2014-07-29 22:02:20 UTC (rev 831)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui/JobSettingsPanel.java	2014-07-30 19:56:08 UTC (rev 832)
@@ -1,12 +1,31 @@
 package org.hps.monitoring.gui;
 
+import static org.hps.monitoring.gui.MonitoringCommands.AIDA_AUTO_SAVE_CHANGED;
+import static org.hps.monitoring.gui.MonitoringCommands.DISCONNECT_ON_ERROR_CHANGED;
+import static org.hps.monitoring.gui.MonitoringCommands.LOG_LEVEL_CHANGED;
+import static org.hps.monitoring.gui.MonitoringCommands.LOG_TO_FILE_CHANGED;
+import static org.hps.monitoring.gui.MonitoringCommands.STEERING_RESOURCE_CHANGED;
+import static org.hps.monitoring.gui.MonitoringCommands.STEERING_TYPE_CHANGED;
+import static org.hps.monitoring.gui.model.ConfigurationModel.AIDA_AUTO_SAVE_PROPERTY;
+import static org.hps.monitoring.gui.model.ConfigurationModel.AIDA_FILE_NAME_PROPERTY;
+import static org.hps.monitoring.gui.model.ConfigurationModel.DETECTOR_NAME_PROPERTY;
+import static org.hps.monitoring.gui.model.ConfigurationModel.DISCONNECT_ON_ERROR_PROPERTY;
+import static org.hps.monitoring.gui.model.ConfigurationModel.EVENT_BUILDER_PROPERTY;
+import static org.hps.monitoring.gui.model.ConfigurationModel.LOG_FILE_NAME_PROPERTY;
+import static org.hps.monitoring.gui.model.ConfigurationModel.LOG_LEVEL_PROPERTY;
+import static org.hps.monitoring.gui.model.ConfigurationModel.LOG_TO_FILE_PROPERTY;
+import static org.hps.monitoring.gui.model.ConfigurationModel.STEERING_FILE_PROPERTY;
+import static org.hps.monitoring.gui.model.ConfigurationModel.STEERING_RESOURCE_PROPERTY;
+import static org.hps.monitoring.gui.model.ConfigurationModel.STEERING_TYPE_PROPERTY;
+
 import java.awt.GridBagLayout;
 import java.awt.Insets;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
 import java.io.File;
 import java.io.IOException;
-import java.io.InputStream;
 import java.net.JarURLConnection;
 import java.net.URL;
 import java.util.ArrayList;
@@ -20,49 +39,52 @@
 import javax.swing.JCheckBox;
 import javax.swing.JComboBox;
 import javax.swing.JFileChooser;
-import javax.swing.JOptionPane;
 import javax.swing.JTextField;
 import javax.swing.SwingUtilities;
 
-import org.hps.monitoring.config.Configurable;
-import org.hps.monitoring.config.Configuration;
 import org.hps.monitoring.enums.SteeringType;
+import org.hps.monitoring.gui.model.ConfigurationModel;
+import org.hps.monitoring.gui.model.HasConfigurationModel;
 import org.jdom.Document;
 import org.jdom.Element;
 import org.jdom.JDOMException;
 import org.jdom.input.SAXBuilder;
 
 /**
- * The panel for setting job parameters.
+ * This is the GUI panel for setting job parameters.  It is connected to the global configuration via 
+ * a {@link org.hps.monitoring.model.ConfigurationModel} object.
  */
-class JobSettingsPanel extends AbstractFieldsPanel implements Configurable, ActionListener {
+// TODO: Add validity checks for event builder, lcsim steering files, etc. when edited and revert to old
+//       values if invalid.
+// TODO: Remove default values in components.  These should all come from the default configuration.
+// TODO: Double check that all settings to and from the configuration are working properly.
+// TODO: Add HasErrorHandler implementation and use it for error handling of exceptions.
+class JobSettingsPanel extends AbstractFieldsPanel implements ActionListener, PropertyChangeListener, HasConfigurationModel {
 
+    private JTextField aidaSaveFileNameField;
+    private JCheckBox aidaAutoSaveCheckbox;
     private JTextField detectorNameField;
-    //private JCheckBox disconnectOnErrorCheckBox;
+    private JCheckBox disconnectOnErrorCheckBox;
     private JTextField eventBuilderField;
-    private JComboBox<?> steeringTypeComboBox;
+    private JTextField logFileNameField;
+    private JComboBox<?> logLevelComboBox;
+    private JCheckBox logToFileCheckbox;    
+    private JCheckBox pauseModeCheckBox;
     private JTextField steeringFileField;
     private JComboBox<?> steeringResourcesComboBox;
-    private JCheckBox logCheckBox;
-    private JTextField logFileField;
-    private JCheckBox pauseModeCheckBox;
-    private JComboBox<?> logLevelComboBox;
-    private JTextField aidaSaveField;
-    private JCheckBox aidaSaveCheckBox;
+    private JComboBox<?> steeringTypeComboBox;
+                         
+    // The package where steering resources must be located.
+    static final String STEERING_PACKAGE = "org/hps/steering/monitoring/";
     
-    private String steeringPackage = "org/hps/steering/monitoring/";
-
-    // FIXME: This should probably be in some kind of global config file.
-    private String DEFAULT_EVENT_BUILDER_CLASS_NAME = "org.hps.evio.LCSimTestRunEventBuilder";
-
-    private final static String[] steeringTypes = { SteeringType.RESOURCE.name(), SteeringType.FILE.name()};
-    
-    Configuration config;
-    
-    /**
-     * The available LogLevel settings as an array of strings.
-     */
-    String[] logLevels = new String[] {
+    // FIXME: This should be in the default global config file rather than hard-coded here.
+    static final String DEFAULT_EVENT_BUILDER_CLASS_NAME = "org.hps.evio.LCSimTestRunEventBuilder";
+            
+    // This will connect this GUI component to the underlying global configuration.
+    ConfigurationModel configurationModel;
+                
+    // 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(),
@@ -78,41 +100,83 @@
      * Class constructor.
      */
     JobSettingsPanel() {
-
+        
         super(new Insets(4, 2, 2, 4), true);
         setLayout(new GridBagLayout());
 
+        // FIXME: This shouldn't really be part of this GUI.
         pauseModeCheckBox = addCheckBox("Pause mode", false, true);
-        //disconnectOnErrorCheckBox = addCheckBox("Disconnect on error", false, true);
+        pauseModeCheckBox.addPropertyChangeListener(this);
         
-        logLevelComboBox = addComboBox("Log Level", this.logLevels);
-        logLevelComboBox.setActionCommand(MonitoringCommands.SET_LOG_LEVEL);
+        disconnectOnErrorCheckBox = addCheckBox("Disconnect on error", false, true);
+        disconnectOnErrorCheckBox.addPropertyChangeListener(this);
+        disconnectOnErrorCheckBox.setActionCommand(DISCONNECT_ON_ERROR_CHANGED);
+        disconnectOnErrorCheckBox.addActionListener(this);
         
-        steeringTypeComboBox = addComboBox("Steering Type", steeringTypes);  
+        logLevelComboBox = addComboBox("Log Level", LOG_LEVELS);               
+        logLevelComboBox.setActionCommand(MonitoringCommands.LOG_LEVEL_CHANGED);
+        logLevelComboBox.addActionListener(this);
+        
+        steeringTypeComboBox = addComboBox("Steering Type", 
+                new String[] {SteeringType.RESOURCE.name(), SteeringType.FILE.name()});
+        steeringTypeComboBox.addPropertyChangeListener(this);        
+        steeringTypeComboBox.setActionCommand(STEERING_TYPE_CHANGED);
+        steeringTypeComboBox.addActionListener(this);
+        
         steeringFileField = addField("Steering File", 35);
+        steeringFileField.addPropertyChangeListener("value", this);        
                      
         JButton steeringFileButton = addButton("Select Steering File");
         steeringFileButton.setActionCommand(MonitoringCommands.CHOOSE_STEERING_FILE);
         steeringFileButton.addActionListener(this);
+        steeringFileButton.addPropertyChangeListener("value", this);
         
         steeringResourcesComboBox = addComboBoxMultiline("Steering File Resource", 
-                getAvailableSteeringFileResources(steeringPackage));
-        steeringResourcesComboBox.setActionCommand(MonitoringCommands.SET_STEERING_RESOURCE);
+                getAvailableSteeringFileResources(STEERING_PACKAGE));
+        steeringResourcesComboBox.setActionCommand(STEERING_RESOURCE_CHANGED);
+        steeringResourcesComboBox.addActionListener(this);
         
         detectorNameField = addField("Detector Name", 20);
+        detectorNameField.addPropertyChangeListener("value", this);
         
         eventBuilderField = addField("Event Builder Class", 30);
         eventBuilderField.setActionCommand(MonitoringCommands.SET_EVENT_BUILDER);
+        eventBuilderField.addPropertyChangeListener("value", this);
         
-        logCheckBox = addCheckBox("Log to File", false, false);
-        logCheckBox.setEnabled(false);
+        logToFileCheckbox = addCheckBox("Log to File", false, false);
+        logToFileCheckbox.setEnabled(false);
+        logToFileCheckbox.setActionCommand(LOG_TO_FILE_CHANGED);
+        logToFileCheckbox.addActionListener(this);
         
-        logFileField = addField("Log File", "", "Full path to log file.", 30, false);
+        logFileNameField = addField("Log File", "", "Full path to log file.", 30, false);
+        logFileNameField.addPropertyChangeListener("value", this);
         
-        aidaSaveCheckBox = addCheckBox("Save AIDA at End of Job", false, false);
-        aidaSaveField = addField("AIDA Auto Save File Name", "", 30, false);        
+        aidaAutoSaveCheckbox = addCheckBox("Save AIDA at End of Job", false, false);
+        aidaAutoSaveCheckbox.addActionListener(this);
+        aidaAutoSaveCheckbox.setActionCommand(AIDA_AUTO_SAVE_CHANGED);
+                
+        aidaSaveFileNameField = addField("AIDA Auto Save File Name", "", 30, false);
+        aidaSaveFileNameField.addPropertyChangeListener("value", this);
     }
     
+    @Override
+    public void setConfigurationModel(ConfigurationModel configModel) {
+        
+        // Set the ConfigurationModel reference.
+        this.configurationModel = configModel;
+        
+        // This listener pushes GUI values into the configuration.
+        this.configurationModel.addPropertyChangeListener(this);
+        
+        // This listener updates the GUI from changes in the configuration.
+        this.configurationModel.addPropertyChangeListener(new JobSettingsChangeListener());
+    }
+    
+    @Override
+    public ConfigurationModel getConfigurationModel() {
+        return configurationModel;
+    }    
+       
     /**
      * Enable this component.
      * @param enable Whether to enable or not.
@@ -127,13 +191,13 @@
     }   
     
     /**
-     * Attaches the ActionListener from the main app to GUI components in this class.
+     * Attaches the ActionListener from the main app to specific GUI components in this class.
      */
     void addActionListener(ActionListener listener) {
+        eventBuilderField.addActionListener(listener);        
+        logFileNameField.addActionListener(listener);
+        logToFileCheckbox.addActionListener(listener);
         steeringResourcesComboBox.addActionListener(listener);
-        //logLevelComboBox.addActionListener(listener);
-        logFileField.addActionListener(listener);
-        eventBuilderField.addActionListener(listener);
     }
         
     /**
@@ -150,13 +214,9 @@
             if ((extIndex == -1) || !(fileName.substring(extIndex + 1, fileName.length())).toLowerCase().equals("aida")) {
                 fileName = fileName + ".aida";
             }
-            final String fileName2 = fileName;
-            SwingUtilities.invokeLater(new Runnable() {
-                public void run() {
-                    aidaSaveCheckBox.setSelected(true);
-                    aidaSaveField.setText(fileName2);
-                }
-            });
+            final String finalFileName = fileName;
+            configurationModel.setAutoSaveAida(true);
+            configurationModel.setAidaFileName(finalFileName);                       
         }
     }
 
@@ -172,14 +232,14 @@
             File file = fc.getSelectedFile();
             try {
                 checkSteeringFile(file);
-                setSteeringFile(file);
-            } catch (Exception e) {
-                
+                configurationModel.setSteeringFile(file.getCanonicalPath());
+            } catch (IOException | JDOMException e) {
+                throw new RuntimeException(e);
             }
         }        
     }
     
-    void checkSteeringFile(File file) throws IOException, JDOMException {
+    private void checkSteeringFile(File file) throws IOException, JDOMException {
         SAXBuilder builder = new SAXBuilder();
         Document document = builder.build(file);
         Element rootNode = document.getRootElement();
@@ -193,6 +253,7 @@
      * @return True if builder is setup successfully; false if not.
      */
     // FIXME: This method should throw an exception if an error occurs.
+    /*
     void editEventBuilder() {
         String eventBuilderClassName = eventBuilderField.getText();
         boolean okay = true;
@@ -200,7 +261,9 @@
             // Test that the event builder can be created without throwing any exceptions.
             Class<?> eventBuilderClass = Class.forName(eventBuilderClassName);
             eventBuilderClass.newInstance();
-        } 
+        } catch (Exception e) {
+            throw new RuntimeException("Error setting up event builder.", e);
+        }        
         catch (ClassNotFoundException e) {
             JOptionPane.showMessageDialog(this, "The event builder class does not exist.");
             okay = false;
@@ -217,10 +280,13 @@
         if (!okay)
             resetEventBuilder();
     }
+    */
 
     /**
      * Reset the event builder to the default.
      */
+    // FIXME: Handle this with property change listener and use old value if new one is invalid.
+    /*
     private void resetEventBuilder() {
         SwingUtilities.invokeLater(new Runnable() {
             public void run() {
@@ -228,93 +294,13 @@
             }
         });
     }
-
+    */
+   
     /**
-     * Get the event builder class name.
-     * @return The event builder class name.
-     */
-    String getEventBuilderClassName() {
-        return eventBuilderField.getText();
-    }
-
-    /**
-     * Set the steering file field.
-     * @param steeringFile The path to the file.
-     */
-    void setSteeringFile(final File steeringFile) {
-        SwingUtilities.invokeLater(new Runnable() {
-            public void run() {
-                steeringFileField.setText(steeringFile.getAbsolutePath());
-            }
-        });
-        setSteeringType(SteeringType.FILE);
-    }
-    
-    /**
-     * Set the steering file resource.
-     * @param s The resource path.
-     */
-    void setSteeringResource(final String s) {
-        SwingUtilities.invokeLater(new Runnable() {
-            public void run() {
-                steeringResourcesComboBox.setSelectedItem(s);
-            }
-        });
-        setSteeringType(SteeringType.RESOURCE);
-    }
-
-    /**
-     * Set the name of the detector.
-     * @param detectorName The name of the detector.
-     */
-    void setDetectorName(final String detectorName) {
-        SwingUtilities.invokeLater(new Runnable() {
-            public void run() {
-                detectorNameField.setText(detectorName);
-            }
-        });
-    }
-    
-    String getSteeringResource() {
-        return (String) steeringResourcesComboBox.getSelectedItem();
-    }
-
-    /**
-     * Get the steering file or resource path from the field setting.
-     * @return The steering file or resource path.
-     */
-    String getSteering() {
-        if (getSteeringType().equals(SteeringType.FILE)) {
-            return steeringFileField.getText();
-        }
-        else if (getSteeringType().equals(SteeringType.RESOURCE)) {
-            return (String) steeringResourcesComboBox.getSelectedItem();
-        }
-        else {
-            return null;
-        }
-    }
-
-    /**
-     * Get the type of steering, file or resource.
-     * @return The type of steering.
-     */
-    SteeringType getSteeringType() {
-        return SteeringType.values()[steeringTypeComboBox.getSelectedIndex()];
-    }
-
-    /**
-     * Get the name of the detector.
-     * @return The name of the detector.
-     */
-    String getDetectorName() {
-        return detectorNameField.getText();
-    }
-  
-    /**
      * Check if pause mode is selected.
      * @return True if pause mode is enabled; false if not.
      */
+    // FIXME: Should not be here.
     boolean pauseMode() {
         return this.pauseModeCheckBox.isSelected();
     }
@@ -323,6 +309,7 @@
      * Set the pause mode.
      * @param p The pause mode; true for on; false for off.
      */
+    // FIXME: Should not be here.  This has nothing to do with the GUI.
     void enablePauseMode(final boolean p) {
         SwingUtilities.invokeLater(new Runnable() {
             public void run() {
@@ -330,214 +317,10 @@
             }
         });
     }
-
+                        
+          
     /**
-     * Get the log level from the combo box. 
-     * @return The log level.
-     */
-    Level getLogLevel() {
-        return Level.parse((String) logLevelComboBox.getSelectedItem());
-    }
-    
-    /**
-     * Get the disconnect on error setting from the check box.
-     * @return The disconnect on error setting.
-     */
-    //boolean disconnectOnError() {
-    //    return disconnectOnErrorCheckBox.isSelected();
-    //}
-        
-    /**
-     * Get the log to file setting.
-     * @return The log to file setting.
-     */
-    boolean isLogToFileEnabled() {
-        return logCheckBox.isSelected();
-    }
-    
-    /**
-     * Get the log file name.
-     * @return The log file name.
-     */
-    String getLogFileName() {
-        return logFileField.getText();
-    }    
-        
-    /**
-     * Get whether AIDA autosave is enabled.
-     * @return True if AIDA autosave is enabled; false if not.
-     */
-    boolean isAidaAutoSaveEnabled() {
-        return aidaSaveCheckBox.isSelected();
-    }
-    
-    /**
-     * Get the AIDA autosave file name.
-     * @return The AIDA autosave file name.
-     */
-    String getAidaAutoSaveFileName() {
-        return aidaSaveField.getText();
-    }
-                      
-    /**
-     * Set whether to disconnect if errors occur.
-     * @param b The disconnect on error setting.
-     */
-    //private void setDisconnectOnError(final boolean b) {
-    //    SwingUtilities.invokeLater(new Runnable() {
-    //        public void run() {
-    //            disconnectOnErrorCheckBox.setSelected(b);
-    //        }
-    //    });        
-    //}
-        
-    /**
-     * Set the steering type.
-     * @param t The steering type.
-     */
-    void setSteeringType(final SteeringType steeringType) {
-        SwingUtilities.invokeLater(new Runnable() {
-            public void run() {
-                steeringTypeComboBox.setSelectedIndex(steeringType.ordinal());
-            }
-        });        
-    }
-    
-    /**
-     * Set the log level.
-     * @param level The log level.
-     */
-    private void setLogLevel(final Level level) {
-        SwingUtilities.invokeLater(new Runnable() {
-            public void run() {
-                logLevelComboBox.setSelectedItem(level.toString());
-            }
-        });               
-    }
-    
-    /**
-     * Set the fully qualified class name of the event builder.
-     * @param c The class name of the event builder.
-     */
-    private void setEventBuilder(final String c) {
-        SwingUtilities.invokeLater(new Runnable() {
-            public void run() {
-                eventBuilderField.setText(c);
-            }
-        });        
-    }
-    
-    /**
-     * Set whether to log to a file.
-     * @param b The log to file setting.
-     */
-    void setLogToFile(final boolean b) {
-        SwingUtilities.invokeLater(new Runnable() {
-            public void run() {
-                logCheckBox.setSelected(b);
-            }
-        });
-    }
-    
-    /**
-     * Set the log file name.
-     * @param s The log file name.
-     */
-    void setLogFile(final File file) {
-        SwingUtilities.invokeLater(new Runnable() {
-            public void run() {
-                logFileField.setText(file.getAbsolutePath());
-                setLogToFile(true);
-            }
-        });        
-    }
-    
-    /**
-     * Set AIDA autosave.
-     * @param b The AIDA autosave setting.
-     */
-    private void enableAidaAutoSave(final boolean b) {
-        SwingUtilities.invokeLater(new Runnable() {
-            public void run() {
-                aidaSaveCheckBox.setSelected(b);
-            }
-        });
-    }
-    
-    /**
-     * Set the AIDA autosave file name.
-     * @param s The AIDA autosave file name.
-     */
-    private void setAidaAutoSaveFileName(final String s) {
-        SwingUtilities.invokeLater(new Runnable() {
-            public void run() {
-                aidaSaveField.setText(s);
-            }
-        });
-    }
-             
-    /**
-     * Get the path to the steering file path.
-     * @return The steering file path.
-     */
-    private String getSteeringFile() {
-        return steeringFileField.getText();
-    }
-                 
-    @Override
-    public void load(Configuration config) {
-        enablePauseMode(config.getBoolean("pauseMode"));
-        setLogLevel(Level.parse(config.get("logLevel")));  
-        setSteeringType(SteeringType.valueOf(config.get("steeringType")));
-        if (config.hasKey("steeringFile"))
-            setSteeringFile(new File(config.get("steeringFile")));
-        if (config.hasKey("steeringResource")) {
-            setSteeringResource(config.get("steeringResource"));
-        }
-        setDetectorName(config.get("detectorName"));
-        setEventBuilder(config.get("eventBuilderClassName"));
-        setLogToFile(config.getBoolean("logToFile"));
-        setLogFile(new File(config.get("logFileName")));
-        enableAidaAutoSave(config.getBoolean("autoSaveAida"));
-        setAidaAutoSaveFileName(config.get("autoSaveAidaFileName"));
-    }
-    
-    @Override
-    public void save(Configuration config) {
-        config.set("pauseMode", pauseMode());
-        config.set("logLevel", getLogLevel().getName());
-        config.set("steeringType", getSteeringType().name());
-        config.set("steeringFile", getSteeringFile());
-        config.set("steeringResource", getSteeringResource());
-        config.set("detectorName", getDetectorName());
-        config.set("eventBuilderClassName", getEventBuilderClassName());
-        config.set("logToFile", isLogToFileEnabled());
-        config.set("logFileName", getLogFileName());
-        config.set("autoSaveAida", isAidaAutoSaveEnabled());
-        config.set("autoSaveAidaFileName", getAidaAutoSaveFileName());
-    }
-    
-    public void save() {
-        save(config);
-    }
-    
-    @Override
-    public void set(Configuration config) {
-        load(config);
-        this.config = config;
-    }
-
-    @Override
-    public void reset() {
-        load(config);        
-    }
-    
-    public Configuration getConfiguration() {
-        return config;
-    }
-      
-    /**
-     * Get the files that end in .lcsim from all loaded jar files.
+     * Get the files with extension "lcsim" from all loaded jar files.
      * @return A list of embedded steering file resources.
      */
     public static String[] getAvailableSteeringFileResources(String packageName) {
@@ -574,7 +357,97 @@
     public void actionPerformed(ActionEvent e) {
         if (e.getActionCommand().equals(MonitoringCommands.CHOOSE_STEERING_FILE)) {
             this.chooseSteeringFile();
+        } else if (DISCONNECT_ON_ERROR_CHANGED.equals(e.getActionCommand())) {
+            configurationModel.setDisconnectOnError(disconnectOnErrorCheckBox.isSelected());
+        } else if (STEERING_TYPE_CHANGED.equals(e.getActionCommand())) {
+            configurationModel.setSteeringType(SteeringType.valueOf((String) steeringTypeComboBox.getSelectedItem())); 
+        } else if (STEERING_RESOURCE_CHANGED.equals(e.getActionCommand())) {
+            configurationModel.setSteeringResource((String) steeringResourcesComboBox.getSelectedItem());
+        } else if (LOG_TO_FILE_CHANGED.equals(e.getActionCommand())) {
+            configurationModel.setLogToFile(logToFileCheckbox.isSelected());
+        } else if (LOG_LEVEL_CHANGED.equals(e.getActionCommand())) {
+            configurationModel.setLogLevel(Level.parse((String) logLevelComboBox.getSelectedItem()));
+        } else if (AIDA_AUTO_SAVE_CHANGED.equals(e.getActionCommand())) {
+            configurationModel.setAutoSaveAida(aidaAutoSaveCheckbox.isSelected());
         }
     }
+
+    /**
+     * Updates the configuration with changes from the GUI component values.
+     * The changes from the GUI are distinguishable by their component object.
+     */
+    @Override
+    public void propertyChange(PropertyChangeEvent evt) {
+        
+        if (evt.getPropertyName().equals("ancestor"))
+            return;
+        
+        //System.out.println("JobSettingsPanel.propertyChange");
+        //System.out.println("  source: " + evt.getSource().getClass().getCanonicalName());
+        //System.out.println("  propertyName: " + evt.getPropertyName());
+        //System.out.println("  newValue: " + evt.getNewValue());
+        //System.out.println("  oldValue: " + evt.getOldValue());
+
+        Object source = evt.getSource();
+
+        if (source == detectorNameField) {
+            configurationModel.setDetectorName(detectorNameField.getText());
+        } else if (source == eventBuilderField) {
+            configurationModel.setEventBuilderClassName(eventBuilderField.getText());
+        } else if (source == steeringFileField) {
+            configurationModel.setSteeringFile(steeringFileField.getText());
+        } else if (source == logFileNameField) {
+            configurationModel.setLogFileName(logFileNameField.getText());
+        } else if (source == aidaSaveFileNameField) {
+            configurationModel.setAidaFileName(aidaSaveFileNameField.getText());
+        } /* TODO */ else if (source == aidaAutoSaveCheckbox) {
+            configurationModel.setAutoSaveAida(aidaAutoSaveCheckbox.isSelected());
+        }
+    }
     
+    /**
+     * Update the GUI from changes in the underlying configuration.
+     * The changes from the configuration are distinguishable by their 
+     * property name.
+     */
+    public class JobSettingsChangeListener implements PropertyChangeListener {
+        @Override
+        public void propertyChange(PropertyChangeEvent evt) {
+            
+            if (evt.getPropertyName().equals("ancestor"))
+                return;
+            
+            //System.out.println("JobSettingsChangeListener.propertyChange");
+            //System.out.println("  source: " + evt.getSource().getClass().getCanonicalName());
+            //System.out.println("  propertyName: " + evt.getPropertyName());
+            //System.out.println("  newValue: " + evt.getNewValue());
+            //System.out.println("  oldValue: " + evt.getOldValue());
+            
+            Object value = evt.getNewValue();
+            
+            if (evt.getPropertyName().equals(DETECTOR_NAME_PROPERTY)) {
+                detectorNameField.setText((String) value); 
+            } if (evt.getPropertyName().equals(AIDA_AUTO_SAVE_PROPERTY)) {
+                aidaAutoSaveCheckbox.setSelected((Boolean) value);
+            } if (evt.getPropertyName().equals(AIDA_FILE_NAME_PROPERTY)) {
+                aidaSaveFileNameField.setText((String) value);
+            } if (evt.getPropertyName().equals(DISCONNECT_ON_ERROR_PROPERTY)) {
+                disconnectOnErrorCheckBox.setSelected((Boolean) value);
+            } if (evt.getPropertyName().equals(EVENT_BUILDER_PROPERTY)) {
+                eventBuilderField.setText((String) value);                
+            } if (evt.getPropertyName().equals(LOG_FILE_NAME_PROPERTY)) {
+                logFileNameField.setText((String) value);                
+            } if (evt.getPropertyName().equals(LOG_LEVEL_PROPERTY)) {
+                logLevelComboBox.setSelectedItem(value.toString());
+            } if (evt.getPropertyName().equals(LOG_TO_FILE_PROPERTY)) {
+                logToFileCheckbox.setSelected((Boolean) value);
+            } if (evt.getPropertyName().equals(STEERING_TYPE_PROPERTY)) {
+                steeringTypeComboBox.setSelectedIndex(((SteeringType)value).ordinal());
+            } if (evt.getPropertyName().equals(STEERING_FILE_PROPERTY)) {
+                steeringFileField.setText((String) value);
+            } if (evt.getPropertyName().equals(STEERING_RESOURCE_PROPERTY)) {
+                steeringResourcesComboBox.setSelectedItem(value);
+            }                                          
+        }
+    }   
 }
\ No newline at end of file

java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui
MonitoringApplication.java 831 -> 832
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui/MonitoringApplication.java	2014-07-29 22:02:20 UTC (rev 831)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui/MonitoringApplication.java	2014-07-30 19:56:08 UTC (rev 832)
@@ -54,6 +54,7 @@
 import org.hps.monitoring.enums.ConnectionStatus;
 import org.hps.monitoring.enums.DataSourceType;
 import org.hps.monitoring.enums.SteeringType;
+import org.hps.monitoring.gui.model.ConfigurationModel;
 import org.hps.monitoring.plotting.MonitoringAnalysisFactory;
 import org.hps.monitoring.plotting.MonitoringPlotFactory;
 import org.hps.monitoring.record.EventProcessingChain;
@@ -70,9 +71,9 @@
 import org.lcsim.util.loop.LCIOEventSource;
 
 /**
- * Monitoring application for HPS, which can run LCSim steering files on data converted
- * from the ET server.
+ * This class is the implementation of the GUI for the Monitoring Application.
  */
+// FIXME: The log to file or terminal is probably broken with changes to JobSettingsPanel.
 public class MonitoringApplication extends JFrame implements ActionListener, Configurable {
 
     // Top-level Swing components.
@@ -98,7 +99,6 @@
     ErrorHandler errorHandler;
 
     // ET connection parameters and state.
-    //private EtConnectionParameters connectionParameters;
     private EtConnection connection;
     private ConnectionStatus connectionStatus = ConnectionStatus.DISCONNECTED;
 
@@ -136,6 +136,7 @@
     static final String DEFAULT_CONFIG_RESOURCE = "/org/hps/monitoring/config/default_config.prop";
     
     Configuration config = new Configuration(DEFAULT_CONFIG_RESOURCE);
+    ConfigurationModel configModel;
     
     // List of GUI objects to which configuration should be pushed.
     List<Configurable> configurables = new ArrayList<Configurable>();
@@ -143,8 +144,7 @@
     /**
      * Constructor for the monitoring application.
      */
-    public MonitoringApplication() {        
-        //initialize();
+    public MonitoringApplication() {
     }
         
     /**
@@ -188,7 +188,8 @@
         // Add configurable objects to list.
         addConfigurables();
         
-        // Load configuration from properties file.
+        // Load configuration from properties file.
+        set(config);
         load(config);
 
         // Log that the application started successfully.
@@ -202,7 +203,10 @@
     private void setupExceptionHandler() {
         Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {            
             public void uncaughtException(Thread thread, Throwable exception) {
-               MonitoringApplication.this.errorHandler.setError(exception).log().printStackTrace().showErrorDialog();
+               MonitoringApplication.this.errorHandler.setError(exception)
+                   .log()
+                   .printStackTrace()
+                   .showErrorDialog();
             }
         });
     }
@@ -398,7 +402,7 @@
     private class MonitoringApplicationLogHandler extends Handler {
 
         /**
-         * Puts log messages into the application's log table GUI component.
+         * Puts log messages into the log table.
          */
         public void publish(LogRecord record) {
             Object[] row = new Object[] { /* record.getLoggerName(), */ // source
@@ -416,7 +420,7 @@
     }
 
     /**
-     * Creates the application's log table GUI component, which is a JTable containing messages
+     * Creates the log table component, which is a JTable containing messages
      * from the logger.
      */
     private void createLogTable() {
@@ -454,7 +458,7 @@
      * @param e The event to handle.
      */
     // FIXME: Review all these commands to see which need to have menu items added back,
-    //        which should be removed, etc.
+    //        which should be removed, those that are duplicated, etc.
     public void actionPerformed(ActionEvent e) {
         String cmd = e.getActionCommand();
         if (CONNECT.equals(cmd)) {
@@ -475,9 +479,9 @@
             savePlots();
         } else if (CHOOSE_LOG_FILE.equals(cmd)) {
             chooseLogFile();
-        } else if (LOG_TO_TERMINAL.equals(cmd)) {
+        } /*else if (LOG_TO_TERMINAL.equals(cmd)) {
             logToTerminal();
-        } else if (SCREENSHOT.equals(cmd)) {
+        }*/ else if (SCREENSHOT.equals(cmd)) {
             chooseScreenshot();
         } else if (EXIT.equals(cmd)) {
             exit();
@@ -485,21 +489,21 @@
             saveLogTableToFile();
         } else if (CLEAR_LOG_TABLE.equals(cmd)) {
             clearLogTable();
-        } else if (SET_EVENT_BUILDER.equals(cmd)) {
+        } /*else if (SET_EVENT_BUILDER.equals(cmd)) {
             getJobSettingsPanel().editEventBuilder();
-        } else if (PAUSE.equals(cmd)) {
+        }*/ else if (PAUSE.equals(cmd)) {
             pauseEventProcessing();
         } else if (NEXT.equals(cmd)) {
             nextEvent();
         } else if (RESUME.equals(cmd)) {
             resumeEventProcessing();
-        } else if (SET_LOG_LEVEL.equals(cmd)) {
+        } else if (LOG_LEVEL_CHANGED.equals(cmd)) {
             setLogLevel();
         } else if (AIDA_AUTO_SAVE.equals(cmd)) {
             getJobSettingsPanel().chooseAidaAutoSaveFile();
-        } else if (SET_STEERING_RESOURCE.equals(cmd)) {
+        } /*else if (SET_STEERING_RESOURCE.equals(cmd)) {
             steeringResourceSelected();
-        } else if (SHOW_SETTINGS.equals(cmd)) {
+        }*/ else if (SHOW_SETTINGS.equals(cmd)) {
             showSettingsWindow();
         } else if (SELECT_CONFIG_FILE.equals(cmd)) {
             chooseConfigFile();
@@ -507,6 +511,9 @@
             saveConfigFile();
         } else if (LOAD_DEFAULT_CONFIG_FILE.equals(cmd)) {
             loadDefaultConfigFile();
+        } else if (LOG_TO_FILE_CHANGED.equals(cmd)) {
+            if (!configModel.getLogToFile())
+                logToTerminal();
         }
     }
 
@@ -516,24 +523,16 @@
     private void showSettingsWindow() {
         settingsDialog.setVisible(true);
     }
-
-    /**
-     * This fires when a steering resource file is selected from the combo box. The Job Settings
-     * are changed to use a resource type.
-     */
-    private void steeringResourceSelected() {
-        getJobSettingsPanel().setSteeringType(SteeringType.RESOURCE);
-    }
        
     /**
      * Set a new log level for the application.  If the new log level is the same as the old one, 
      * a new log level will NOT be set.
      */
     private void setLogLevel() {
-        Level newLevel = getJobSettingsPanel().getLogLevel();
+        Level newLevel = configModel.getLogLevel();
         if (logger.getLevel() != newLevel) {
             logger.setLevel(newLevel);
-            log(Level.INFO, "Log Level was changed to <" + getJobSettingsPanel().getLogLevel().toString() + ">");
+            log(Level.INFO, "Log Level was changed to <" + configModel.getLogLevel().toString() + ">");
         }
     }
 
@@ -565,7 +564,7 @@
     }
         
     /**
-     * Save plots to a selected output file using a file chooser.
+     * Immediately save all plots to a selected output file using a file chooser.
      */
     private void savePlots() {
         JFileChooser fc = new JFileChooser();
@@ -642,7 +641,9 @@
         System.setErr(sysErr);
         SwingUtilities.invokeLater(new Runnable() {
             public void run() {
-                getJobSettingsPanel().setLogToFile(false);
+                configModel.setLogToFile(false);
+                
+                // These should be toggled via a PropertyChangeListener or ActionEvent.
                 terminalItem.setEnabled(false);
                 logItem.setEnabled(true);
             }
@@ -688,7 +689,6 @@
                 buttonsPanel.enableNextEventsButton(false);
 
                 // Toggle connection button to proper setting.
-                //buttonsPanel.toggleConnectButton();
                 buttonsPanel.setConnected(false);
             }
         });
@@ -717,7 +717,6 @@
                 buttonsPanel.setPauseModeState(getJobSettingsPanel().pauseMode());
 
                 // Toggle connection button to proper settings.
-                //buttonsPanel.toggleConnectButton();
                 buttonsPanel.setConnected(true);
             }
         });
@@ -732,7 +731,9 @@
         }
         if (plotFrame.isVisible())
             plotFrame.setVisible(false);
-        this.setVisible(false);
+        if (systemStatusFrame.isVisible())
+            systemStatusFrame.setVisible(false);
+        setVisible(false);
         System.exit(0);
     }
 
@@ -776,23 +777,6 @@
     }
 
     /**
-     * Get the fully qualified class name of the current event builder 
-     * that will be used to convert EVIO to LCIO.
-     * @return The class name of the event builder.
-     */
-    private String getEventBuilderClassName() {
-        return getJobSettingsPanel().getEventBuilderClassName();
-    }
-
-    /**
-     * Get the type of steering file being used.
-     * @return The type of the steering file.
-     */
-    private SteeringType getSteeringType() {
-        return getJobSettingsPanel().getSteeringType();
-    }
-
-    /**
      * Start a new monitoring session.  This method is executed in a separate thread from the EDT
      * within {@link #actionPerformed(ActionEvent)} so GUI updates are not blocked while the session 
      * is being setup.
@@ -882,23 +866,7 @@
             this.setConnectionStatus(ConnectionStatus.CONNECTED);
         }
     }
-
-    /**
-     * Get the steering parameter, which is either a file path or resource string.
-     * @return The steering parameter.
-     */
-    private String getSteering() {
-        return getJobSettingsPanel().getSteering();
-    }
-
-    /**
-     * Get the name of the detector for conditions data.
-     * @return The name of the detector.
-     */
-    private String getDetectorName() {
-        return getJobSettingsPanel().getDetectorName();
-    }
-      
+       
     private ConnectionSettingsPanel getConnectionPanel() {
         return settingsDialog.getSettingsPanel().getConnectionPanel();
     }
@@ -911,14 +879,6 @@
         return settingsDialog.getSettingsPanel().getDataSourcePanel();
     }
 
-    /**
-     * Get whether errors in event processing will cause automatic disconnect.
-     * @return True if disconnect on event processing error; false to continue.
-     */
-    //private boolean disconnectOnError() {
-    //    return getJobPanel().disconnectOnError();
-    //}
-
     private void disconnect() {
         disconnect(ConnectionStatus.DISCONNECTING);
     }
@@ -967,8 +927,17 @@
         log(Level.INFO, "Setting up LCSim.");
 
         // Get steering resource or file as a String parameter.
-        String steering = getSteering();
-        SteeringType steeringType = getJobSettingsPanel().getSteeringType();
+        String steering = null;
+        SteeringType steeringType = configModel.getSteeringType(); 
+        if (steeringType.equals(SteeringType.FILE))
+            try {
+                steering = configModel.getSteeringFile().getCanonicalPath();
+            } catch (IOException e) {
+                throw new RuntimeException(e);
+            }
+        else 
+            steering = configModel.getSteeringResource();
+
         log(Level.CONFIG, "Set LCSim steering to <" + steering + "> with type <" + (steeringType == SteeringType.RESOURCE ? "RESOURCE" : "FILE") + ">");
 
         try {
@@ -977,7 +946,7 @@
             jobManager.setPerformDryRun(true);
             if (steeringType == SteeringType.RESOURCE) {
                 setupSteeringResource(steering);
-            } else if (getSteeringType() == SteeringType.FILE) {
+            } else if (steeringType.equals(SteeringType.FILE)) {
                 setupSteeringFile(steering);
             }
 
@@ -1014,21 +983,22 @@
      */
     private void createEventBuilder() {
 
-        // Setup the EventBuilder class.
-        String eventBuilderClassName = getEventBuilderClassName();
+        // Get the class for the event builder.
+        String eventBuilderClassName = configModel.getEventBuilderClassName();
 
         log(Level.FINE, "Initializing event builder <" + eventBuilderClassName + ">");
 
         try {
+            // Create a new instance of the builder class.
             eventBuilder = (LCSimEventBuilder) Class.forName(eventBuilderClassName).newInstance();
         } catch (Exception e) {
-            throw new RuntimeException("Failed to create LCSimEventBuilder class.", e);
+            throw new RuntimeException("Failed to create LCSimEventBuilder.", e);
         }
 
         // Set the detector name on the event builder so it can find conditions data.
-        eventBuilder.setDetectorName(getDetectorName());
+        eventBuilder.setDetectorName(configModel.getDetectorName());
 
-        log(Level.INFO, "Successfully initialized event builder <" + eventBuilderClassName + ">");
+        log(Level.CONFIG, "Successfully initialized event builder <" + eventBuilderClassName + ">");
     }
 
     /**
@@ -1129,19 +1099,20 @@
         // Toggle job panel setting.
         getJobSettingsPanel().enablePauseMode(false);
 
-        log(Level.FINE, "Resuming event processing after pause.");
+        log(Level.FINEST, "Resuming event processing after pause.");
     }
 
     /**
      * Notify the event processor to start pause mode, which will pause between events.
      */
     private void pauseEventProcessing() {
-        //if (connected()) {
-            // Pause event processing.
+       
         eventProcessing.pause();
 
         // Set GUI state.
         buttonsPanel.setPauseModeState(true);
+        
+        // FIXME: Remove this.
         getJobSettingsPanel().enablePauseMode(false);
 
         log(Level.FINEST, "Event processing was paused.");
@@ -1189,7 +1160,7 @@
         eventProcessing.setEventBuilder(eventBuilder);
         
         // Set the detector name for LCSim conditions system.
-        eventProcessing.setDetectorName(getDetectorName());
+        eventProcessing.setDetectorName(configModel.getDetectorName());
         
         // Get a list of Drivers to execute from the JobManager which was
         // already configured.
@@ -1225,12 +1196,12 @@
     }
     
     private boolean usingEtServer() {
-        // FIXME: Should check configuration instead.
+        // FIXME: Should check the configuration instead.
         return this.getDataSourcePanel().getDataSourceType().equals(DataSourceType.ET_SERVER);
     }
     
     private boolean usingEvioFile() {
-        // FIXME: Should check configuration instead.
+        // FIXME: Should check the configuration instead.
         return this.getDataSourcePanel().getDataSourceType().equals(DataSourceType.EVIO_FILE);
     }
     
@@ -1285,15 +1256,15 @@
     }
 
     /**
-     * End the current job.
+     * Save the plots to an AIDA output file at the end of the job.
      */
     private void saveAidaFile() {
 
         // Save final AIDA file if option is selected.
-        if (getJobSettingsPanel().isAidaAutoSaveEnabled()) {
-            log(Level.INFO, "Saving AIDA file <" + getJobSettingsPanel().getAidaAutoSaveFileName() + ">");
+        if (configModel.getAidaAutoSave()) {
+            log(Level.INFO, "Saving AIDA file <" + configModel.getAidaFileName() + ">");
             try {
-                AIDA.defaultInstance().saveAs(getJobSettingsPanel().getAidaAutoSaveFileName());
+                AIDA.defaultInstance().saveAs(configModel.getAidaFileName());
             } catch (IOException e) {
                 errorHandler.setError(e)
                     .setMessage("Error saving AIDA file.")
@@ -1345,7 +1316,7 @@
      * @param visible Whether it should be immediately visible.
      * @return The JDialog that was created.
      */
-    JDialog showStatusDialog(String title, String message, boolean visible) {
+    private JDialog showStatusDialog(String title, String message, boolean visible) {
         final JOptionPane optionPane = new JOptionPane(
                 message, 
                 JOptionPane.INFORMATION_MESSAGE,
@@ -1470,8 +1441,14 @@
                 // This should trigger an action event that performs the actual config
                 // of the log file.
                 //System.out.println("setting log file to " + file.getAbsolutePath());
-                getJobSettingsPanel().setLogToFile(true);
-                getJobSettingsPanel().setLogFile(file);
+                //getJobSettingsPanel().setLogToFile(true);
+                //getJobSettingsPanel().setLogFile(file);
+                configModel.setLogToFile(true);
+                try {
+                    configModel.setLogFileName(file.getCanonicalPath());
+                } catch (IOException e) {
+                    errorHandler.setError(e).log().printStackTrace().showErrorDialog();
+                }
                 logToFile(file);
             }            
         }
@@ -1506,18 +1483,12 @@
 
     @Override
     public void load(Configuration config) {
-                                
+                
         for (Configurable configurable : configurables) {
             configurable.set(config);
         }
-       
-        // FIXME: Hack to make this work properly when a new config is loaded.  
-        //        This should really be done with a proper MVC structure using a model.
-        if (getJobSettingsPanel().isLogToFileEnabled()) {
-            logToFile(new File(getJobSettingsPanel().getLogFileName()));
-        } else {
-            logToTerminal();
-        }
+                             
+        configModel.fireAllChanged();
         
         if (config.getFile() != null)
             log(Level.CONFIG, "Loaded config from file <" + config.getFile().getPath() + ">");
@@ -1526,7 +1497,6 @@
     }
 
     private void addConfigurables() {
-        configurables.add(this.getJobSettingsPanel());
         configurables.add(this.getConnectionPanel());
         configurables.add(this.getDataSourcePanel());
     }
@@ -1551,6 +1521,12 @@
     @Override
     public void set(Configuration config) {
         this.config = config;
+        if (configModel == null) {
+            configModel = new ConfigurationModel(config);
+            getJobSettingsPanel().setConfigurationModel(configModel);
+        } else {
+            configModel.setConfiguration(config);
+        }
     }
 
     @Override

java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui
MonitoringCommands.java 831 -> 832
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui/MonitoringCommands.java	2014-07-29 22:02:20 UTC (rev 831)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui/MonitoringCommands.java	2014-07-30 19:56:08 UTC (rev 832)
@@ -5,6 +5,14 @@
  * A few commands handled only by sub-components are not listed here.
  */
 final class MonitoringCommands {
+    
+    static final String DISCONNECT_ON_ERROR_CHANGED = "disconnectOnErrorChanged";
+    static final String STEERING_TYPE_CHANGED = "steeringTypeChanged";
+    static final String STEERING_RESOURCE_CHANGED = "steeringResourceChanged";
+    static final String LOG_TO_FILE_CHANGED = "logToFileChanged";
+    static final String AIDA_AUTO_SAVE_CHANGED = "aidaAutoSaveChanged";
+    static final String LOG_LEVEL_CHANGED = "logLevelChanged";    
+       
     static final String AIDA_AUTO_SAVE = "aidaAutoSave";
     static final String CLEAR_LOG_TABLE = "clearLogTable";
     static final String CHOOSE_LOG_FILE = "chooseLogFile";
@@ -22,8 +30,8 @@
     static final String SAVE_PLOTS = "savePlots";
     static final String SCREENSHOT = "screenshot";
     static final String SAVE_CONFIG_FILE = "saveConfigFile";
-    static final String SET_EVENT_BUILDER = "setEventBuilder";
-    static final String SET_LOG_LEVEL = "setLogLevel";
+    static final String SET_EVENT_BUILDER = "setEventBuilder";    
+
     static final String SET_STEERING_RESOURCE = "setSteeringResource";            
     static final String SELECT_CONFIG_FILE = "selectConfigFile";
     static final String SELECT_LOG_FILE = "logToFile";

java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui
SettingsPanel.java 831 -> 832
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui/SettingsPanel.java	2014-07-29 22:02:20 UTC (rev 831)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui/SettingsPanel.java	2014-07-30 19:56:08 UTC (rev 832)
@@ -83,7 +83,7 @@
      */
     void save() {
         connectionPanel.save();
-        jobPanel.save();
+        //jobPanel.save();
         dataSourcePanel.save();
     }
     
@@ -92,7 +92,7 @@
      */
     void reset() {
         connectionPanel.reset();
-        jobPanel.reset();
+        //jobPanel.reset();
         dataSourcePanel.reset();
     }
     

java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui
SystemStatusFrame.java 831 -> 832
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui/SystemStatusFrame.java	2014-07-29 22:02:20 UTC (rev 831)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui/SystemStatusFrame.java	2014-07-30 19:56:08 UTC (rev 832)
@@ -1,11 +1,11 @@
 package org.hps.monitoring.gui;
 
-import static org.hps.monitoring.gui.SystemStatusTableModel.ACTIVE_COL;
-import static org.hps.monitoring.gui.SystemStatusTableModel.CLEARABLE_COL;
-import static org.hps.monitoring.gui.SystemStatusTableModel.LAST_CHANGED_COL;
-import static org.hps.monitoring.gui.SystemStatusTableModel.RESET_COL;
-import static org.hps.monitoring.gui.SystemStatusTableModel.STATUS_COL;
-import static org.hps.monitoring.gui.SystemStatusTableModel.SYSTEM_COL;
+import static org.hps.monitoring.gui.model.SystemStatusTableModel.ACTIVE_COL;
+import static org.hps.monitoring.gui.model.SystemStatusTableModel.CLEARABLE_COL;
+import static org.hps.monitoring.gui.model.SystemStatusTableModel.LAST_CHANGED_COL;
+import static org.hps.monitoring.gui.model.SystemStatusTableModel.RESET_COL;
+import static org.hps.monitoring.gui.model.SystemStatusTableModel.STATUS_COL;
+import static org.hps.monitoring.gui.model.SystemStatusTableModel.SYSTEM_COL;
 
 import java.awt.Color;
 import java.awt.Component;
@@ -24,6 +24,7 @@
 import javax.swing.table.TableCellRenderer;
 
 import org.hps.monitoring.enums.StatusCode;
+import org.hps.monitoring.gui.model.SystemStatusTableModel;
 
 /**
  * A GUI window for showing changes to {@link org.hps.monitoring.subsys.SystemStatus} objects.

java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui
SystemStatusTableModel.java removed after 831
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui/SystemStatusTableModel.java	2014-07-29 22:02:20 UTC (rev 831)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui/SystemStatusTableModel.java	2014-07-30 19:56:08 UTC (rev 832)
@@ -1,149 +0,0 @@
-package org.hps.monitoring.gui;
-
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.text.SimpleDateFormat;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.List;
-
-import javax.swing.JButton;
-import javax.swing.table.AbstractTableModel;
-
-import org.hps.monitoring.enums.StatusCode;
-import org.hps.monitoring.subsys.SystemStatus;
-import org.hps.monitoring.subsys.SystemStatusListener;
-
-/**
- * A <code>JTableModel</code> that has a backing list of 
- * {@link org.hps.monitoring.subsys.SystemStatus} objects.
- */
-public class SystemStatusTableModel extends AbstractTableModel implements SystemStatusListener {
-
-    static final int RESET_COL = 0;
-    static final int ACTIVE_COL = 1;
-    static final int STATUS_COL = 2;
-    static final int SYSTEM_COL = 3;
-    static final int DESCRIPTION_COL = 4;
-    static final int MESSAGE_COL = 5;
-    static final int LAST_CHANGED_COL = 6;
-    static final int CLEARABLE_COL = 7;
-            
-    static final String[] columnNames = {
-            "Reset",
-            "Active",
-            "Status",
-            "System",       
-            "Description",
-            "Message", 
-            "Last Changed",
-            "Clearable"
-    };
-    
-    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);
-        status.addListener(this);
-        fireTableDataChanged();
-    }
-        
-    @Override
-    public int getRowCount() {
-        return statuses.size();
-    }
-
-    @Override
-    public int getColumnCount() {
-        return columnNames.length;
-    }
-    
-    @Override
-    public String getColumnName(int col) {        
-        return columnNames[col];
-    }
-
-    @Override
-    public Object getValueAt(final int rowIndex, final int columnIndex) {
-        SystemStatus status = statuses.get(rowIndex);
-        switch (columnIndex) {
-            case ACTIVE_COL:
-                return status.isActive();
-            case STATUS_COL:
-                return status.getStatusCode().name();
-            case SYSTEM_COL:
-                return status.getSubsystem().name();
-            case DESCRIPTION_COL:
-                return status.getDescription();
-            case MESSAGE_COL:
-                return status.getMessage();
-            case LAST_CHANGED_COL:
-                return new Date(status.getLastChangedMillis());
-            case RESET_COL:
-                // If the status is clearable, then it has a button that can be used to
-                // manually set the state to CLEARED.  If the status is not clearable,
-                // then nothing is rendered in this cell.
-                if (status.isClearable()) {
-                    final JButton button = new JButton();
-                    button.addActionListener(new ActionListener() {
-                        public void actionPerformed(ActionEvent e) {                            
-                            SystemStatus status = 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();
-                                status.setStatus(StatusCode.CLEARED, "Cleared from " + oldStatusCode.name() + " state.");
-                            }
-                        }
-                    });
-                    return button;
-                } else {
-                    return null;
-                }                
-            case CLEARABLE_COL:
-                return status.isClearable();
-            default:
-                return null;
-        }
-    }
-    
-    @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;
-        }                    
-    }
-    
-    @Override
-    public boolean isCellEditable(int row, int col) {
-        if (col == ACTIVE_COL)
-            return true;        
-        else 
-            return false;
-    }
-    
-    @Override
-    public void statusChanged(SystemStatus status) {
-        int rowNumber = statuses.indexOf(status);
-        this.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);
-        }
-    }    
-}

java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui/model
AbstractModel.java added at 832
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui/model/AbstractModel.java	                        (rev 0)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui/model/AbstractModel.java	2014-07-30 19:56:08 UTC (rev 832)
@@ -0,0 +1,75 @@
+package org.hps.monitoring.gui.model;
+
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.beans.PropertyChangeSupport;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+/**
+ * Abstract class that updates listeners of property changes in backing model.
+ * @author Jeremy McCormick <[log in to unmask]>
+ */
+public abstract class AbstractModel {
+
+    protected PropertyChangeSupport propertyChangeSupport;
+
+    public AbstractModel() {
+        propertyChangeSupport = new PropertyChangeSupport(this);
+    }
+    
+    public void addPropertyChangeListener(PropertyChangeListener listener) {
+        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);
+    }
+    
+    protected void firePropertyChange(PropertyChangeEvent evt) {
+        propertyChangeSupport.firePropertyChange(evt);
+    }
+    
+    abstract public String[] getProperties();
+    
+    public void fireAllChanged() {
+        //System.out.println("AbstractModel.fireAllChanged");
+        //System.out.println("  listeners: ");
+        //for (PropertyChangeListener listener : propertyChangeSupport.getPropertyChangeListeners()) {
+        //    System.out.print(listener.getClass().getCanonicalName() + " ");
+        //}
+        System.out.println();
+        for (String property : getProperties()) {
+            Method getMethod = null;
+            for (Method method : getClass().getMethods()) {
+                if (method.getName().equals("get" + property)) {
+                    getMethod = method;
+                    break;
+                }
+            }
+            try {
+                //System.out.println("firePropertyChange");
+                //System.out.println("  property: " + property);
+                //System.out.println("  getMethod: " + getMethod.getName());
+                Object value = getMethod.invoke(this, null);
+                //System.out.println("  value: " + value);
+                if (value != null) {
+                    firePropertyChange(property, value, value);                    
+                    for (PropertyChangeListener listener : propertyChangeSupport.getPropertyChangeListeners()) {
+                        //System.out.println("  propertyChange: " + listener.getClass().getCanonicalName());
+                        listener.propertyChange(new PropertyChangeEvent(this, property, value, value));
+                    }
+                    //firePropertyChange(new PropertyChangeEvent(this, property, value, value));
+                } else {
+                    System.err.println("WARNING: AbstractModel.fireAllChanged - missing property " + property);
+                }
+            } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
+                throw new RuntimeException(e);
+            }            
+        }
+    }        
+}
\ No newline at end of file

java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui/model
ConfigurationModel.java added at 832
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui/model/ConfigurationModel.java	                        (rev 0)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui/model/ConfigurationModel.java	2014-07-30 19:56:08 UTC (rev 832)
@@ -0,0 +1,172 @@
+package org.hps.monitoring.gui.model;
+
+import java.io.File;
+import java.util.logging.Level;
+
+import org.hps.monitoring.config.Configuration;
+import org.hps.monitoring.enums.SteeringType;
+
+/**
+ * A model of the global configuration parameters that can be
+ * used to automatically update the GUI or push changes in GUI
+ * component values into the configuration.
+ * @author Jeremy McCormick <[log in to unmask]>
+ */
+public final class ConfigurationModel extends AbstractModel {
+    
+    Configuration config;
+    
+    public static final String AIDA_AUTO_SAVE_PROPERTY = "AidaAutoSave";
+    public static final String AIDA_FILE_NAME_PROPERTY = "AidaFileName";   
+    public static final String DETECTOR_NAME_PROPERTY = "DetectorName";
+    public static final String DISCONNECT_ON_ERROR_PROPERTY = "DisconnectOnError";
+    public static final String EVENT_BUILDER_PROPERTY = "EventBuilderClassName";
+    public static final String LOG_FILE_NAME_PROPERTY = "LogFileName";
+    public static final String LOG_LEVEL_PROPERTY = "LogLevel";
+    public static final String LOG_TO_FILE_PROPERTY = "LogToFile";    
+    public static final String STEERING_TYPE_PROPERTY = "SteeringType";
+    public static final String STEERING_FILE_PROPERTY = "SteeringFile";
+    public static final String STEERING_RESOURCE_PROPERTY = "SteeringResource";    
+               
+    static final String[] CONFIG_PROPERTIES = new String[] {
+            AIDA_AUTO_SAVE_PROPERTY,
+            AIDA_FILE_NAME_PROPERTY,
+            DETECTOR_NAME_PROPERTY,
+            DISCONNECT_ON_ERROR_PROPERTY,
+            EVENT_BUILDER_PROPERTY,
+            LOG_FILE_NAME_PROPERTY,
+            LOG_LEVEL_PROPERTY,
+            LOG_TO_FILE_PROPERTY,
+            STEERING_FILE_PROPERTY,
+            STEERING_RESOURCE_PROPERTY,
+            STEERING_TYPE_PROPERTY,
+    };        
+    
+    String detectorName;
+            
+    public ConfigurationModel(Configuration config) {
+        this.config = config;
+    }
+    
+    public void setConfiguration(Configuration config) {
+        this.config = config;
+    }
+           
+    public Level getLogLevel() {
+        return Level.parse(config.get(LOG_LEVEL_PROPERTY));        
+    }
+    
+    public void setLogLevel(Level level) {
+        Level oldValue = getLogLevel();
+        config.set(LOG_LEVEL_PROPERTY, level.getName());
+        firePropertyChange(LOG_LEVEL_PROPERTY, oldValue, getLogLevel());
+    }
+    
+    public SteeringType getSteeringType() {        
+        return SteeringType.valueOf(config.get(STEERING_TYPE_PROPERTY));
+    }
+    
+    public void setSteeringType(SteeringType steeringType) {
+        SteeringType oldValue = getSteeringType();
+        config.set(STEERING_TYPE_PROPERTY, steeringType.name());
+        firePropertyChange(STEERING_TYPE_PROPERTY, oldValue, getSteeringType());
+    }
+    
+    public File getSteeringFile() {
+        if (config.hasKey(STEERING_FILE_PROPERTY))
+            return new File(config.get(STEERING_FILE_PROPERTY));
+        else
+            return null;
+    }
+    
+    public void setSteeringFile(String steeringFile) {
+        File oldValue = getSteeringFile();
+        config.set(STEERING_FILE_PROPERTY, steeringFile);
+        firePropertyChange(STEERING_FILE_PROPERTY, oldValue, getSteeringFile().getPath());
+    }
+    
+    public String getSteeringResource() {
+        return config.get(STEERING_RESOURCE_PROPERTY);
+    }        
+    
+    public void setSteeringResource(String steeringResource) {
+        String oldValue = getSteeringResource();
+        config.set(STEERING_RESOURCE_PROPERTY, steeringResource);
+        firePropertyChange(STEERING_RESOURCE_PROPERTY, oldValue, steeringResource);
+    }
+    
+    public String getDetectorName() {
+        return config.get(DETECTOR_NAME_PROPERTY);
+    }
+    
+    public void setDetectorName(String detectorName) {
+        String oldValue = getDetectorName();
+        config.set(DETECTOR_NAME_PROPERTY, detectorName);
+        firePropertyChange(DETECTOR_NAME_PROPERTY, oldValue, getDetectorName());
+    }
+    
+    public String getEventBuilderClassName() {
+        return config.get(EVENT_BUILDER_PROPERTY);    
+    }         
+    
+    public void setEventBuilderClassName(String eventBuilderClassName) {
+        String oldValue = getEventBuilderClassName();
+        config.set(EVENT_BUILDER_PROPERTY, eventBuilderClassName);
+        firePropertyChange(EVENT_BUILDER_PROPERTY, oldValue, getEventBuilderClassName());
+    }
+    
+    public boolean getLogToFile() {
+        return config.getBoolean(LOG_TO_FILE_PROPERTY);
+    }
+    
+    public void setLogToFile(boolean logToFile) {
+        boolean oldValue = getLogToFile();
+        config.set(LOG_TO_FILE_PROPERTY, logToFile);
+        firePropertyChange(LOG_TO_FILE_PROPERTY, oldValue, getLogToFile());
+    }
+    
+    public String getLogFileName() {
+        return config.get(LOG_FILE_NAME_PROPERTY);
+    }
+    
+    public void setLogFileName(String logFileName) {
+        String oldValue = getLogFileName();
+        config.set(LOG_FILE_NAME_PROPERTY, logFileName);
+        firePropertyChange(LOG_FILE_NAME_PROPERTY, oldValue, getLogFileName());
+    }
+    
+    public boolean getAidaAutoSave() {
+        return config.equals(AIDA_AUTO_SAVE_PROPERTY);
+    }
+    
+    public void setAutoSaveAida(boolean aidaAutoSave) {
+        boolean oldValue = getAidaAutoSave();
+        config.set(AIDA_AUTO_SAVE_PROPERTY, aidaAutoSave);
+        firePropertyChange(AIDA_AUTO_SAVE_PROPERTY, oldValue, aidaAutoSave);
+    }
+    
+    public String getAidaFileName() {
+        return config.get(AIDA_FILE_NAME_PROPERTY);
+    }
+    
+    public void setAidaFileName(String aidaFileName) {
+        String oldValue = getAidaFileName();
+        config.set(AIDA_FILE_NAME_PROPERTY, aidaFileName);
+        firePropertyChange(AIDA_FILE_NAME_PROPERTY, oldValue, aidaFileName);
+    }
+    
+    public boolean getDisconnectOnError() {
+        return config.getBoolean(DISCONNECT_ON_ERROR_PROPERTY);
+    }    
+    
+    public void setDisconnectOnError(boolean disconnectOnError) {
+        boolean oldValue = getDisconnectOnError();
+        config.set(DISCONNECT_ON_ERROR_PROPERTY, disconnectOnError);
+        firePropertyChange(DISCONNECT_ON_ERROR_PROPERTY, oldValue, getDisconnectOnError());
+    }        
+    
+    @Override
+    public String[] getProperties() {
+        return CONFIG_PROPERTIES;
+    }
+}
\ No newline at end of file

java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui/model
HasConfigurationModel.java added at 832
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui/model/HasConfigurationModel.java	                        (rev 0)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui/model/HasConfigurationModel.java	2014-07-30 19:56:08 UTC (rev 832)
@@ -0,0 +1,9 @@
+package org.hps.monitoring.gui.model;
+
+
+public interface HasConfigurationModel {
+    
+    void setConfigurationModel(ConfigurationModel configurationModel);
+    
+    ConfigurationModel getConfigurationModel();
+}

java/trunk/monitoring-app/src/main/java/org/hps/monitoring/record
EventProcessingChain.java 831 -> 832
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/record/EventProcessingChain.java	2014-07-29 22:02:20 UTC (rev 831)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/record/EventProcessingChain.java	2014-07-30 19:56:08 UTC (rev 832)
@@ -63,6 +63,7 @@
     private boolean done;
     private boolean paused;
     private boolean wasSetup;
+    private boolean stopOnErrors = true;
     
     private EtProcessingStep etStep = new EtProcessingStep();
     private EvioProcessingStep evioStep = new EvioProcessingStep();
@@ -127,6 +128,8 @@
             compositeLoop.addProcessor(lcioStep);
         }
         
+        compositeLoop.setStopOnErrors(stopOnErrors);
+        
         wasSetup = true;
     }
     
@@ -329,6 +332,17 @@
     }
     
     /**
+     * Set whether processing will stop when errors occur.
+     * Only specific types of non-fatal errors are affected by this.
+     * For instance, <code>NoSuchRecordException</code> is never 
+     * ignored and always causes processing to stop.
+     * @param stopOnErrors True if processing should stop on errors. 
+     */
+    public void setStopOnErrors(boolean stopOnErrors) {
+        this.stopOnErrors = stopOnErrors;
+    }
+    
+    /**
      * Exception thrown if the loop is not in the correct state
      * when a certain method is called.
      */

java/trunk/monitoring-app/src/main/java/org/hps/monitoring/record
EvioProcessingStep.java 831 -> 832
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/record/EvioProcessingStep.java	2014-07-29 22:02:20 UTC (rev 831)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/record/EvioProcessingStep.java	2014-07-30 19:56:08 UTC (rev 832)
@@ -107,6 +107,7 @@
             throw new NoSuchRecordException("No current EVIO event.");
         
         record.setEvioEvent(nextEvioEvent);
+        record.setEventNumber(nextEvioEvent.getEventNumber());
         
         // Encountered an end of run record.
         if (EventConstants.isEndEvent(nextEvioEvent))

java/trunk/monitoring-app/src/main/java/org/hps/monitoring/record
LcioProcessingStep.java 831 -> 832
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/record/LcioProcessingStep.java	2014-07-29 22:02:20 UTC (rev 831)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/record/LcioProcessingStep.java	2014-07-30 19:56:08 UTC (rev 832)
@@ -93,7 +93,6 @@
             throw new NoSuchRecordException("No next LCIO event.");
         
         // Load the next LCIO event.
-        // FIXME: Why does this work even if the event source says it doesn't have a next record?!
         loop.execute(NEXT);
                       
         // The last call to the loop did not create a current record.
@@ -106,6 +105,9 @@
                 
         // Update the CompositeRecord with reference to the LCIO event.
         record.setLcioEvent(lcioEvent);
+        if (record.getEvioEvent() == null) {
+            record.setEventNumber(lcioEvent.getEventNumber());
+        }
     }
     
     /**

java/trunk/monitoring-app/src/main/java/org/hps/monitoring/record/composite
CompositeRecord.java 831 -> 832
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/record/composite/CompositeRecord.java	2014-07-29 22:02:20 UTC (rev 831)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/record/composite/CompositeRecord.java	2014-07-30 19:56:08 UTC (rev 832)
@@ -14,12 +14,23 @@
     EvioEvent evioEvent;
     EventHeader lcioEvent;
     
+    int sequenceNumber = -1;
+    int eventNumber = -1;
+    
+    public void setSequenceNumber(int sequenceNumber) {
+        this.sequenceNumber = sequenceNumber;
+    }
+    
+    public void setEventNumber(int eventNumber) {
+        this.eventNumber = eventNumber;
+    }
+    
     public void setEtEvent(EtEvent etEvent) {
         this.etEvent = etEvent;
     }
     
     public void setEvioEvent(EvioEvent evioEvent) {
-        this.evioEvent = evioEvent;
+        this.evioEvent = evioEvent;        
     }
     
     public void setLcioEvent(EventHeader lcioEvent) {
@@ -37,4 +48,12 @@
     public EventHeader getLcioEvent() {
         return lcioEvent;
     }
+    
+    public int getSequenceNumber() {
+        return sequenceNumber;
+    }
+    
+    public int getEventNumber() {
+        return eventNumber;
+    }
 }

java/trunk/monitoring-app/src/main/java/org/hps/monitoring/record/composite
CompositeRecordLoop.java 831 -> 832
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/record/composite/CompositeRecordLoop.java	2014-07-29 22:02:20 UTC (rev 831)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/record/composite/CompositeRecordLoop.java	2014-07-30 19:56:08 UTC (rev 832)
@@ -1,6 +1,7 @@
 package org.hps.monitoring.record.composite;
 
 import org.freehep.record.loop.DefaultRecordLoop;
+import org.freehep.record.source.NoSuchRecordException;
 import org.freehep.record.source.RecordSource;
 
 /**
@@ -11,6 +12,7 @@
 
     CompositeRecordSource recordSource = new CompositeRecordSource();
     CompositeRecordLoopAdapter adapter = new CompositeRecordLoopAdapter();
+    boolean stopOnErrors = true;
     
     public CompositeRecordLoop() {
         setRecordSource(recordSource);
@@ -18,6 +20,10 @@
         addRecordListener(adapter);
     }
     
+    public void setStopOnErrors(boolean stopOnErrors) {
+        this.stopOnErrors = stopOnErrors;
+    }
+    
     /**
      * Set the <code>RecordSource</code> which provides <code>CompositeRecord</code> objects.
      */
@@ -38,7 +44,11 @@
     }
     
     protected void handleClientError(Throwable x) {
-        throw new RuntimeException("Error during event processing.", x);
+        if (stopOnErrors || x instanceof NoSuchRecordException) {
+            throw new RuntimeException("Error during event processing.", x);
+        } else {
+            x.printStackTrace();
+        }        
     }
 
     protected void handleSourceError(Throwable x) {

java/trunk/monitoring-app/src/main/java/org/hps/monitoring/record/composite
CompositeRecordSource.java 831 -> 832
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/record/composite/CompositeRecordSource.java	2014-07-29 22:02:20 UTC (rev 831)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/record/composite/CompositeRecordSource.java	2014-07-30 19:56:08 UTC (rev 832)
@@ -11,9 +11,12 @@
 public class CompositeRecordSource extends AbstractRecordSource {
 
     CompositeRecord currentRecord;
+    int sequenceNumber = 0;
             
     public void next() throws IOException, NoSuchRecordException {
         currentRecord = new CompositeRecord();
+        currentRecord.setSequenceNumber(sequenceNumber);
+        ++sequenceNumber;
     }
             
     @Override
@@ -58,7 +61,7 @@
 
     @Override
     public boolean hasNext() {
-        // FIXME: Not sure about this.
+        // FIXME: Not sure about this one.
         return true;
     }
 }

java/trunk/monitoring-app/src/main/java/org/hps/monitoring/subsys
SystemStatisticsImpl.java 831 -> 832
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/subsys/SystemStatisticsImpl.java	2014-07-29 22:02:20 UTC (rev 831)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/subsys/SystemStatisticsImpl.java	2014-07-30 19:56:08 UTC (rev 832)
@@ -149,8 +149,10 @@
     @Override
     public void stop() { 
         // Kill the Timer.
-        if (timer != null)
+        if (timer != null) {
             timer.cancel();
+            timer.purge();
+        }
         
         // Set stop time.
         stopTimeMillis = System.currentTimeMillis();

java/trunk/monitoring-app/src/main/resources/org/hps/monitoring/config
default_config.prop 831 -> 832
--- java/trunk/monitoring-app/src/main/resources/org/hps/monitoring/config/default_config.prop	2014-07-29 22:02:20 UTC (rev 831)
+++ java/trunk/monitoring-app/src/main/resources/org/hps/monitoring/config/default_config.prop	2014-07-30 19:56:08 UTC (rev 832)
@@ -2,17 +2,17 @@
 # Monitoring Application configuration
 
 # job settings
-autoSaveAida=true
-autoSaveAidaFileName=monitoringPlots.aida
-detectorName=HPS-TestRun-v5
-disconnectOnError=true
-eventBuilderClassName=org.hps.evio.LCSimTestRunEventBuilder
-logFileName=
-logLevel=ALL
-logToFile=false
-#steeringFile=
-steeringResource=/org/hps/steering/monitoring/TestRunMonitoring.lcsim
-steeringType=RESOURCE
+AutoSaveAida=true
+AidaFileName=monitoringPlots.aida
+DetectorName=HPS-TestRun-v5
+DisconnectOnError=true
+EventBuilderClassName=org.hps.evio.LCSimTestRunEventBuilder
+#logFileName=
+LogLevel=ALL
+LogToFile=false
+#SteeringFile=
+SteeringResource=/org/hps/steering/monitoring/TestRunMonitoring.lcsim
+SteeringType=RESOURCE
 
 # event source
 dataSourceType=ET_SERVER
SVNspam 0.1