Print

Print


Author: [log in to unmask]
Date: Tue Dec  9 16:31:46 2014
New Revision: 1664

Log:
Add preliminary support for user specified run numbers in the monitoring app.  Also included are a few fixes and error checks that I am still working on.

Modified:
    java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui/Commands.java
    java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui/JobSettingsPanel.java
    java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui/MonitoringApplication.java
    java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui/model/AbstractModel.java
    java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui/model/Configuration.java
    java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui/model/ConfigurationModel.java

Modified: java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui/Commands.java
 =============================================================================
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui/Commands.java	(original)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui/Commands.java	Tue Dec  9 16:31:46 2014
@@ -21,6 +21,7 @@
     static final String DISCONNECT_ON_END_RUN_CHANGED = "disconnectOnEndRunChanged";
     static final String EVENT_BUILDER_CHANGED = "eventBuilderChanged";
     static final String EXIT = "exit";
+    static final String FREEZE_CONDITIONS_CHANGED = "freezeConditionsChanged";
     static final String LOAD_DEFAULT_CONFIG_FILE = "loadDefaultConfigFile";
     static final String LOG_LEVEL_CHANGED = "logLevelChanged";
     static final String LOG_TO_FILE = "logToFile";
@@ -42,6 +43,7 @@
     static final String SHOW_SETTINGS = "showSettings";
     static final String STEERING_TYPE_CHANGED = "steeringTypeChanged";
     static final String STEERING_RESOURCE_CHANGED = "steeringResourceChanged";
+    static final String USER_RUN_NUMBER_CHANGED = "userRunNumberChanged";
     static final String VERBOSE_CHANGED = "verboseChanged";
     static final String VALIDATE_DATA_FILE = "validateDataFile";
     static final String WAIT_MODE_CHANGED = "waitModeChanged";

Modified: java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui/JobSettingsPanel.java
 =============================================================================
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui/JobSettingsPanel.java	(original)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui/JobSettingsPanel.java	Tue Dec  9 16:31:46 2014
@@ -1,26 +1,7 @@
 package org.hps.monitoring.gui;
 
-import static org.hps.monitoring.gui.Commands.AIDA_AUTO_SAVE_CHANGED;
-import static org.hps.monitoring.gui.Commands.DISCONNECT_ON_END_RUN_CHANGED;
-import static org.hps.monitoring.gui.Commands.DISCONNECT_ON_ERROR_CHANGED;
-import static org.hps.monitoring.gui.Commands.DETECTOR_NAME_CHANGED;
-import static org.hps.monitoring.gui.Commands.EVENT_BUILDER_CHANGED;
-import static org.hps.monitoring.gui.Commands.LOG_LEVEL_CHANGED;
-import static org.hps.monitoring.gui.Commands.LOG_TO_FILE_CHANGED;
-import static org.hps.monitoring.gui.Commands.STEERING_RESOURCE_CHANGED;
-import static org.hps.monitoring.gui.Commands.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_END_RUN_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 static org.hps.monitoring.gui.Commands.*;
+import static org.hps.monitoring.gui.model.ConfigurationModel.*;
 
 import java.awt.GridBagLayout;
 import java.awt.Insets;
@@ -65,19 +46,21 @@
  */
 class JobSettingsPanel extends AbstractFieldsPanel {
 
-    private JTextField aidaSaveFileNameField;
-    private JCheckBox aidaAutoSaveCheckbox;
+    private JComboBox<?> steeringResourcesComboBox;
+    private JTextField steeringFileField;
+    private JComboBox<?> steeringTypeComboBox;
+    private JComboBox<String> detectorNameComboBox;
+    private JComboBox<String> eventBuilderComboBox;
+    private JTextField userRunNumberField;
+    private JCheckBox freezeConditionsCheckBox;    
     private JCheckBox disconnectOnErrorCheckBox;
     private JCheckBox disconnectOnEndRunCheckBox;
-    private JComboBox<String> detectorNameComboBox;
-    private JComboBox<String> eventBuilderComboBox;
+    private JTextField aidaSaveFileNameField;
+    private JCheckBox aidaAutoSaveCheckbox;        
     private JTextField logFileNameField;
     private JComboBox<?> logLevelComboBox;
     private JCheckBox logToFileCheckbox;
-    private JTextField steeringFileField;
-    private JComboBox<?> steeringResourcesComboBox;
-    private JComboBox<?> steeringTypeComboBox;
-
+           
     // The package where steering resources must be located.
     static final String STEERING_PACKAGE = "org/hps/steering/monitoring/";
 
@@ -105,42 +88,52 @@
         super(new Insets(4, 2, 2, 4), true);
         setLayout(new GridBagLayout());
 
-        disconnectOnErrorCheckBox = addCheckBox("Disconnect on error", false, true);
-        disconnectOnErrorCheckBox.setActionCommand(DISCONNECT_ON_ERROR_CHANGED);
-        disconnectOnErrorCheckBox.addActionListener(this);
-
-        disconnectOnEndRunCheckBox = addCheckBox("Disconnect on end run", false, true);
-        disconnectOnEndRunCheckBox.setActionCommand(DISCONNECT_ON_END_RUN_CHANGED);
-        disconnectOnEndRunCheckBox.addActionListener(this);
-
-        logLevelComboBox = addComboBox("Log Level", LOG_LEVELS);
-        logLevelComboBox.setActionCommand(Commands.LOG_LEVEL_CHANGED);
-        logLevelComboBox.addActionListener(this);
-
+        steeringResourcesComboBox = addComboBoxMultiline("Steering File Resource", findSteeringResources(STEERING_PACKAGE));
+        steeringResourcesComboBox.setActionCommand(STEERING_RESOURCE_CHANGED);
+        steeringResourcesComboBox.addActionListener(this);
+        
+        steeringFileField = addField("Steering File", 35);
+        steeringFileField.addPropertyChangeListener("value", this);
+        
+        JButton steeringFileButton = addButton("Select Steering File");
+        steeringFileButton.setActionCommand(Commands.CHOOSE_STEERING_FILE);
+        steeringFileButton.addActionListener(this);
+        
         steeringTypeComboBox = addComboBox("Steering Type", new String[] { SteeringType.RESOURCE.name(), SteeringType.FILE.name() });
         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(Commands.CHOOSE_STEERING_FILE);
-        steeringFileButton.addActionListener(this);
-
-        steeringResourcesComboBox = addComboBoxMultiline("Steering File Resource", findSteeringResources(STEERING_PACKAGE));
-        steeringResourcesComboBox.setActionCommand(STEERING_RESOURCE_CHANGED);
-        steeringResourcesComboBox.addActionListener(this);
-
+        
         detectorNameComboBox = addComboBox("Detector Name", this.findDetectorNames());
         detectorNameComboBox.setActionCommand(DETECTOR_NAME_CHANGED);
         detectorNameComboBox.addActionListener(this);
 
+        userRunNumberField = addField("User Run Number", "", 10, false);
+        userRunNumberField.addPropertyChangeListener("value", this);
+        userRunNumberField.setActionCommand(USER_RUN_NUMBER_CHANGED);
+        userRunNumberField.setEnabled(true);
+        userRunNumberField.setEditable(true);
+        
+        freezeConditionsCheckBox = addCheckBox("Freeze detector conditions", false, true);
+        freezeConditionsCheckBox.addActionListener(this);
+        freezeConditionsCheckBox.setActionCommand(FREEZE_CONDITIONS_CHANGED);
+        
         eventBuilderComboBox = addComboBox("LCSim Event Builder", this.findEventBuilderClassNames());
         eventBuilderComboBox.setSize(24, eventBuilderComboBox.getPreferredSize().height);
         eventBuilderComboBox.setActionCommand(EVENT_BUILDER_CHANGED);
         eventBuilderComboBox.addActionListener(this);
         
+        disconnectOnErrorCheckBox = addCheckBox("Disconnect on error", false, true);
+        disconnectOnErrorCheckBox.setActionCommand(DISCONNECT_ON_ERROR_CHANGED);
+        disconnectOnErrorCheckBox.addActionListener(this);
+
+        disconnectOnEndRunCheckBox = addCheckBox("Disconnect on end run", false, true);
+        disconnectOnEndRunCheckBox.setActionCommand(DISCONNECT_ON_END_RUN_CHANGED);
+        disconnectOnEndRunCheckBox.addActionListener(this);
+
+        logLevelComboBox = addComboBox("Log Level", LOG_LEVELS);
+        logLevelComboBox.setActionCommand(Commands.LOG_LEVEL_CHANGED);
+        logLevelComboBox.addActionListener(this);
+                                            
         logToFileCheckbox = addCheckBox("Log to File", false, false);
         logToFileCheckbox.setEnabled(false);
         logToFileCheckbox.setActionCommand(LOG_TO_FILE_CHANGED);
@@ -154,7 +147,7 @@
         aidaAutoSaveCheckbox.setActionCommand(AIDA_AUTO_SAVE_CHANGED);
 
         aidaSaveFileNameField = addField("AIDA Auto Save File Name", "", 30, false);
-        aidaSaveFileNameField.addPropertyChangeListener("value", this);
+        aidaSaveFileNameField.addPropertyChangeListener("value", this);               
     }
 
     @Override
@@ -192,6 +185,7 @@
         logFileNameField.addActionListener(listener);
         logToFileCheckbox.addActionListener(listener);
         steeringResourcesComboBox.addActionListener(listener);
+        freezeConditionsCheckBox.addActionListener(listener);
     }
 
     /**
@@ -270,7 +264,13 @@
             configurationModel.setEventBuilderClassName((String) eventBuilderComboBox.getSelectedItem());
         } else if (DETECTOR_NAME_CHANGED.equals(e.getActionCommand())) {
             configurationModel.setDetectorName((String) detectorNameComboBox.getSelectedItem());
-        } 
+        } else if (FREEZE_CONDITIONS_CHANGED.equals(e.getActionCommand())) {
+            if (configurationModel.hasPropertyValue(USER_RUN_NUMBER_PROPERTY) && configurationModel.getUserRunNumber() != null) {
+                configurationModel.setFreezeConditions(freezeConditionsCheckBox.isSelected());
+            } else {
+                throw new IllegalArgumentException("Conditions system may only be frozen if there is a valid user run number.");
+            }
+        }
     }
 
     /**
@@ -294,6 +294,27 @@
             configurationModel.setAidaFileName(aidaSaveFileNameField.getText());
         } else if (source == aidaAutoSaveCheckbox) {
             configurationModel.setAidaAutoSave(aidaAutoSaveCheckbox.isSelected());
+        } else if (source == userRunNumberField) {
+            // Is run number being reset to null or empty?
+            if (userRunNumberField.getText() == null || userRunNumberField.getText().isEmpty()) {
+                System.out.println("resetting user run number back to null");
+                // Update the model to null user run number and do not freeze the conditions system.
+                configurationModel.setUserRunNumber(null);
+                configurationModel.setFreezeConditions(false);
+            } else {
+                try {
+                    System.out.println("setting new user run number " + evt.getNewValue());
+                    // Parse the run number.  Need to catch errors because it might be an invalid string.
+                    int userRunNumber = Integer.parseInt(userRunNumberField.getText());
+                    configurationModel.setUserRunNumber(userRunNumber);
+                    configurationModel.setFreezeConditions(true);
+                    System.out.println("successfully set run number to userRunNumber");
+                } catch (NumberFormatException e) {
+                    System.out.println("bad number format so ignoring user run number " + evt.getNewValue());
+                    userRunNumberField.setText((String) evt.getOldValue());
+                    throw new IllegalArgumentException("The value " + evt.getNewValue() + " is not a valid run number.");
+                }                            
+            }
         }
     }
 
@@ -332,9 +353,24 @@
             } else if (evt.getPropertyName().equals(STEERING_TYPE_PROPERTY)) {
                 steeringTypeComboBox.setSelectedIndex(((SteeringType) value).ordinal());
             } else if (evt.getPropertyName().equals(STEERING_FILE_PROPERTY)) {
-                steeringFileField.setText(((File) value).getPath());
+                if (value != null) {                    
+                    steeringFileField.setText(((File) value).getPath());
+                } else {
+                    // A null value here is actually okay and means this field should be reset to have no value.
+                    steeringFileField.setText(null);
+                }
             } else if (evt.getPropertyName().equals(STEERING_RESOURCE_PROPERTY)) {
                 steeringResourcesComboBox.setSelectedItem(value);
+            } else if (evt.getPropertyName().equals(USER_RUN_NUMBER_PROPERTY)) {
+                if (value != null) {
+                    userRunNumberField.setText(Integer.toString((int)value));
+                } else {
+                    userRunNumberField.setText(null);
+                }
+            } else if (evt.getPropertyName().equals(FREEZE_CONDITIONS_PROPERTY)) {
+                if (value != null) {
+                    freezeConditionsCheckBox.setSelected((Boolean) value);
+                }
             }
         }
     }

Modified: java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui/MonitoringApplication.java
 =============================================================================
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui/MonitoringApplication.java	(original)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui/MonitoringApplication.java	Tue Dec  9 16:31:46 2014
@@ -74,6 +74,7 @@
 import javax.swing.table.DefaultTableModel;
 
 import org.freehep.record.loop.RecordLoop.Command;
+import org.hps.conditions.database.DatabaseConditionsManager;
 import org.hps.job.JobManager;
 import org.hps.monitoring.enums.ConnectionStatus;
 import org.hps.monitoring.enums.SteeringType;
@@ -335,7 +336,9 @@
             return;
         Object value = evt.getNewValue();
         if (evt.getPropertyName().equals(SAVE_LAYOUT_PROPERTY)) {
-            saveLayoutItem.setSelected((Boolean) value);
+            if (value != null) {
+                saveLayoutItem.setSelected((Boolean) value);
+            } 
         } else if (evt.getPropertyName().equals(MONITORING_APPLICATION_LAYOUT_PROPERTY)) {
             updateWindowConfiguration(new WindowConfiguration((String) value));
         } else if (evt.getPropertyName().equals(ConfigurationModel.SYSTEM_STATUS_FRAME_LAYOUT_PROPERTY)) {
@@ -351,15 +354,9 @@
                 System.err.println("ERROR: The plotWindow is null!");
             }
         } else if (evt.getPropertyName().equals(ConfigurationModel.LOG_TO_FILE_PROPERTY)) {
-
-            // System.out.println("propertyChange - " + evt.getPropertyName());
-            // System.out.println("  value: " + value);
-
             if ((Boolean) value == true) {
-                // System.out.println("setting logToFile - " + configurationModel.getLogFileName());
                 logToFile(new File(configurationModel.getLogFileName()));
             } else {
-                // System.out.println("setting logToTerminal");
                 logToTerminal();
             }
         }
@@ -552,7 +549,9 @@
         saveLayoutItem.setActionCommand(SAVE_LAYOUT);
         saveLayoutItem.addActionListener(this);
         saveLayoutItem.setToolTipText("Include current GUI layout when saving settings.");
-        saveLayoutItem.setSelected(configurationModel.getSaveLayout());
+        if (configurationModel.hasPropertyValue(ConfigurationModel.SAVE_LAYOUT_PROPERTY)) {
+            saveLayoutItem.setSelected(configurationModel.getSaveLayout());
+        }
         saveLayoutItem.addPropertyChangeListener(this); 
         
         applicationMenu.add(saveLayoutItem);
@@ -651,7 +650,7 @@
             logTableModel.insertRow(logTable.getRowCount(), row);
 
             // Print all messages to System.out so they show up in the terminal or log file output.
-            System.out.println(row[0] + " :: " + this.getClass().getSimpleName() + " :: " + row[1] + " :: " + row[2]);
+            System.out.println(row[0] + " :: " + MonitoringApplication.class.getSimpleName() + " :: " + row[1] + " :: " + row[2]);
         }
 
         public void close() throws SecurityException {
@@ -1109,7 +1108,7 @@
         log(Level.CONFIG, "Set steering to <" + steering + "> with type <" + (steeringType == SteeringType.RESOURCE ? "RESOURCE" : "FILE") + ">");
 
         try {
-            // Create job manager and configure.
+            // Create and the job manager.  The conditions manager is instantiated from this call but not configured.
             jobManager = new JobManager();
             jobManager.setPerformDryRun(true);
             if (steeringType == SteeringType.RESOURCE) {
@@ -1120,6 +1119,24 @@
 
             // Setup the event builder to translate from EVIO to LCIO.
             createEventBuilder();
+            
+            // Is there a user specified run number from the JobPanel?
+            if (configurationModel.hasPropertyValue(ConfigurationModel.USER_RUN_NUMBER_PROPERTY)) {
+                int userRunNumber = configurationModel.getUserRunNumber();
+                String detectorName = configurationModel.getDetectorName();
+                DatabaseConditionsManager conditionsManager = DatabaseConditionsManager.getInstance();
+                logger.config("setting user run number " + userRunNumber + " with detector " + detectorName);
+                conditionsManager.setDetector(configurationModel.getDetectorName(), userRunNumber);
+                if (configurationModel.hasPropertyValue(ConfigurationModel.FREEZE_CONDITIONS_PROPERTY)) {
+                    // Freeze the conditions system to ignore run numbers from the events.  
+                    logger.config("user configured to freeze conditions system from monitoring app");
+                    conditionsManager.freeze();
+                } else {
+                    // Allow run numbers to be picked up from the events.
+                    logger.config("user run number specified but conditions system is NOT frozen");
+                    conditionsManager.unfreeze();
+                }
+            }
 
             log(Level.INFO, "LCSim setup was successful.");
 
@@ -1161,6 +1178,7 @@
         }
 
         // Set the detector name on the event builder so it can find conditions data.
+        // FIXME: This call should be made unnecessary by modifying the EventBuilder API to remove setDetectorName.
         eventBuilder.setDetectorName(configurationModel.getDetectorName());
 
         ConditionsManager.defaultInstance().addConditionsListener(eventBuilder);
@@ -1615,8 +1633,7 @@
      */
     private void loadConfiguration() {
 
-        // Set the Configuration on the ConfigurationModel which will trigger all the
-        // PropertyChangelListeners.
+        // Set the Configuration on the ConfigurationModel which will trigger all the PropertyChangelListeners.
         configurationModel.setConfiguration(configuration);
 
         // Log that a new configuration was loaded.

Modified: java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui/model/AbstractModel.java
 =============================================================================
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui/model/AbstractModel.java	(original)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui/model/AbstractModel.java	Tue Dec  9 16:31:46 2014
@@ -7,13 +7,13 @@
 import java.lang.reflect.Method;
 
 /**
- * Abstract class that updates listeners from property changes in a backing model object.
+ * 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]>
  */
 public abstract class AbstractModel {
 
     protected PropertyChangeSupport propertyChangeSupport;
-    protected boolean listenersEnabled = true;
+    protected boolean listenersEnabled = true;    
 
     public AbstractModel() {
         propertyChangeSupport = new PropertyChangeSupport(this);
@@ -51,7 +51,7 @@
     public void fireAllChanged() {
         if (!listenersEnabled)
             return;
-        for (String property : getPropertyNames()) {
+       propertyLoop: for (String property : getPropertyNames()) {            
             Method getMethod = null;
             for (Method method : getClass().getMethods()) {
                 if (method.getName().equals("get" + property)) {
@@ -64,19 +64,28 @@
                 try {
                     value = getMethod.invoke(this, (Object[]) null);
                 } catch (NullPointerException e) {
-                    throw new RuntimeException("No get method exists for property: " + property, e);
-                }
-                // Is the value non-null?
-                // (Null values are actually okay. It just means the property is not set.)
-                if (value != null) {
-                    firePropertyChange(property, value, value);
-                    for (PropertyChangeListener listener : propertyChangeSupport.getPropertyChangeListeners()) {
-                        // FIXME: For some reason calling the propertyChangeSupport methods directly
-                        // here doesn't work!!!
-                        listener.propertyChange(new PropertyChangeEvent(this, property, value, value));
+                    // 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) {
+                    // Is the cause of the problem an illegal argument to the method?
+                    System.out.println("cause: " + e.getCause().getClass().getCanonicalName());
+                    if (e.getCause() instanceof IllegalArgumentException) {
+                        // 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 {
+                        throw new RuntimeException(e);
                     }
                 }
-            } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
+                // Is the value non-null?  Null values are actually okay.
+                //if (value != null) {
+                firePropertyChange(property, value, value);
+                for (PropertyChangeListener listener : propertyChangeSupport.getPropertyChangeListeners()) {
+                    // FIXME: For some reason calling the propertyChangeSupport methods directly here doesn't work!
+                    listener.propertyChange(new PropertyChangeEvent(this, property, value, value));
+                }
+                //}
+            } catch (IllegalAccessException | IllegalArgumentException e) {
                 throw new RuntimeException(e);
             }
         }

Modified: java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui/model/Configuration.java
 =============================================================================
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui/model/Configuration.java	(original)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui/model/Configuration.java	Tue Dec  9 16:31:46 2014
@@ -9,8 +9,9 @@
 
 /**
  * This class provides a list of key, value pairs backed by a <code>Properties</code> object. The
- * accessor methods to get these values are not public, because the {@link ConfigurationModel}
- * should be used instead.
+ * getter and setter methods for these values are not public, because the 
+ * {@link org.hps.monitoring.gui.model.ConfigurationModel} class should be used instead
+ * to get or set application configuration values.
  */
 public final class Configuration {
 
@@ -83,7 +84,11 @@
      * @return The value or null if does not exist.
      */
     String get(String key) {
-        return properties.getProperty(key);
+        if (checkKey(key)) {
+            return properties.getProperty(key);
+        } else {
+            throw new IllegalArgumentException("The key " + key + " does not exist in this configuration with a valid value.");
+        }
     }
 
     /**
@@ -92,7 +97,11 @@
      * @return The value or null if does not exist.
      */
     Boolean getBoolean(String key) {
-        return Boolean.parseBoolean(properties.getProperty(key));
+        if (checkKey(key)) {
+            return Boolean.parseBoolean(properties.getProperty(key));    
+        } else {
+            return null;
+        }        
     }
 
     /**
@@ -101,7 +110,11 @@
      * @return The value or null if does not exist.
      */
     Double getDouble(String key) {
-        return Double.parseDouble(properties.getProperty(key));
+        if (checkKey(key)) {
+            return Double.parseDouble(properties.getProperty(key));
+        } else {
+            return null;
+        }
     }
 
     /**
@@ -110,7 +123,11 @@
      * @return The value or null if does not exist.
      */
     Integer getInteger(String key) {
-        return Integer.parseInt(properties.getProperty(key));
+        if (checkKey(key)) {
+            return Integer.parseInt(properties.getProperty(key));
+        } else {
+            return null;
+        }
     }
 
     /**
@@ -124,6 +141,15 @@
         } 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.
+     */
+    private boolean checkKey(String key) {
+        return hasKey(key) && properties.getProperty(key) != null;
     }
 
     /**

Modified: java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui/model/ConfigurationModel.java
 =============================================================================
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui/model/ConfigurationModel.java	(original)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui/model/ConfigurationModel.java	Tue Dec  9 16:31:46 2014
@@ -1,7 +1,6 @@
 package org.hps.monitoring.gui.model;
 
 import java.io.File;
-import java.util.List;
 import java.util.logging.Level;
 
 import org.hps.monitoring.enums.SteeringType;
@@ -16,17 +15,21 @@
 // TODO: Should set methods check if new value is equal to old and then ignore if so?
 // FIXME: When the set methods are called, e.g. from GUI updates, this triggers
 // a property change event that pushes the values back to the GUI again.
+// FIXME: Should check if property exists in set methods before retrieving old value for all set methods.
+// FIXME: Should use objects instead of primitive types so that null can be used (e.g. for run number etc.).
+// TODO: How to handle null values?
 public final class ConfigurationModel extends AbstractModel {
 
     Configuration config;
 
-    // Job settings
+    // Job setting properties.
     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 DISCONNECT_ON_END_RUN_PROPERTY = "DisconnectOnEndRun";
     public static final String EVENT_BUILDER_PROPERTY = "EventBuilderClassName";
+    public static final String FREEZE_CONDITIONS_PROPERTY = "FreezeConditions";
     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";
@@ -37,13 +40,14 @@
     public static final String STEERING_TYPE_PROPERTY = "SteeringType";
     public static final String STEERING_FILE_PROPERTY = "SteeringFile";
     public static final String STEERING_RESOURCE_PROPERTY = "SteeringResource";
-
-    // Data source
+    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
+    // 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";
@@ -57,19 +61,50 @@
     public static final String WAIT_TIME_PROPERTY = "WaitTime";
     public static final String PRESCALE_PROPERTY = "Prescale";
 
+    // These key values are primarily used to figure out what properties need to be persisted when
+    // writing to a text file.
     static final String[] CONFIG_PROPERTIES = new String[] {
 
             // Job settings
-            AIDA_AUTO_SAVE_PROPERTY, AIDA_FILE_NAME_PROPERTY, DETECTOR_NAME_PROPERTY, DISCONNECT_ON_ERROR_PROPERTY, DISCONNECT_ON_END_RUN_PROPERTY, EVENT_BUILDER_PROPERTY, LOG_FILE_NAME_PROPERTY, LOG_LEVEL_PROPERTY, LOG_TO_FILE_PROPERTY, STEERING_FILE_PROPERTY, STEERING_RESOURCE_PROPERTY, STEERING_TYPE_PROPERTY,
+            AIDA_AUTO_SAVE_PROPERTY, 
+            AIDA_FILE_NAME_PROPERTY, 
+            DETECTOR_NAME_PROPERTY, 
+            DISCONNECT_ON_ERROR_PROPERTY, 
+            DISCONNECT_ON_END_RUN_PROPERTY, 
+            EVENT_BUILDER_PROPERTY,
+            FREEZE_CONDITIONS_PROPERTY,
+            LOG_FILE_NAME_PROPERTY, 
+            LOG_LEVEL_PROPERTY, 
+            LOG_TO_FILE_PROPERTY, 
+            STEERING_FILE_PROPERTY, 
+            STEERING_RESOURCE_PROPERTY, 
+            STEERING_TYPE_PROPERTY,
+            USER_RUN_NUMBER_PROPERTY,
 
             // Data source
-            DATA_SOURCE_TYPE_PROPERTY, DATA_SOURCE_PATH_PROPERTY, PROCESSING_STAGE_PROPERTY,
+            DATA_SOURCE_TYPE_PROPERTY, 
+            DATA_SOURCE_PATH_PROPERTY, 
+            PROCESSING_STAGE_PROPERTY,
 
             // ET parameters
-            ET_NAME_PROPERTY, HOST_PROPERTY, PORT_PROPERTY, BLOCKING_PROPERTY, VERBOSE_PROPERTY, STATION_NAME_PROPERTY, CHUNK_SIZE_PROPERTY, QUEUE_SIZE_PROPERTY, STATION_POSITION_PROPERTY, WAIT_MODE_PROPERTY, WAIT_TIME_PROPERTY, PRESCALE_PROPERTY,
+            ET_NAME_PROPERTY, 
+            HOST_PROPERTY, 
+            PORT_PROPERTY, 
+            BLOCKING_PROPERTY, 
+            VERBOSE_PROPERTY, 
+            STATION_NAME_PROPERTY, 
+            CHUNK_SIZE_PROPERTY, 
+            QUEUE_SIZE_PROPERTY, 
+            STATION_POSITION_PROPERTY, 
+            WAIT_MODE_PROPERTY, 
+            WAIT_TIME_PROPERTY, 
+            PRESCALE_PROPERTY,
 
             // GUI layout
-            SAVE_LAYOUT_PROPERTY, MONITORING_APPLICATION_LAYOUT_PROPERTY, PLOT_FRAME_LAYOUT_PROPERTY, SYSTEM_STATUS_FRAME_LAYOUT_PROPERTY };
+            SAVE_LAYOUT_PROPERTY, 
+            MONITORING_APPLICATION_LAYOUT_PROPERTY, 
+            PLOT_FRAME_LAYOUT_PROPERTY, 
+            SYSTEM_STATUS_FRAME_LAYOUT_PROPERTY };
 
     String detectorName;
 
@@ -153,7 +188,7 @@
         firePropertyChange(EVENT_BUILDER_PROPERTY, oldValue, getEventBuilderClassName());
     }
 
-    public boolean getLogToFile() {
+    public Boolean getLogToFile() {
         return config.getBoolean(LOG_TO_FILE_PROPERTY);
     }
 
@@ -173,7 +208,7 @@
         firePropertyChange(LOG_FILE_NAME_PROPERTY, oldValue, getLogFileName());
     }
 
-    public boolean getAidaAutoSave() {
+    public Boolean getAidaAutoSave() {
         return config.equals(AIDA_AUTO_SAVE_PROPERTY);
     }
 
@@ -193,7 +228,7 @@
         firePropertyChange(AIDA_FILE_NAME_PROPERTY, oldValue, aidaFileName);
     }
 
-    public boolean getDisconnectOnError() {
+    public Boolean getDisconnectOnError() {
         return config.getBoolean(DISCONNECT_ON_ERROR_PROPERTY);
     }
 
@@ -203,7 +238,7 @@
         firePropertyChange(DISCONNECT_ON_ERROR_PROPERTY, oldValue, getDisconnectOnError());
     }
 
-    public boolean getDisconnectOnEndRun() {
+    public Boolean getDisconnectOnEndRun() {
         return config.getBoolean(DISCONNECT_ON_END_RUN_PROPERTY);
     }
 
@@ -265,7 +300,7 @@
         firePropertyChange(HOST_PROPERTY, oldValue, getHost());
     }
 
-    public int getPort() {
+    public Integer getPort() {
         return config.getInteger(PORT_PROPERTY);
     }
 
@@ -275,7 +310,7 @@
         firePropertyChange(PORT_PROPERTY, oldValue, getPort());
     }
 
-    public boolean getBlocking() {
+    public Boolean getBlocking() {
         return config.getBoolean(BLOCKING_PROPERTY);
     }
 
@@ -285,7 +320,7 @@
         firePropertyChange(BLOCKING_PROPERTY, oldValue, getBlocking());
     }
 
-    public boolean getVerbose() {
+    public Boolean getVerbose() {
         return config.getBoolean(VERBOSE_PROPERTY);
     }
 
@@ -305,7 +340,7 @@
         firePropertyChange(STATION_NAME_PROPERTY, oldValue, getStationName());
     }
 
-    public int getChunkSize() {
+    public Integer getChunkSize() {
         return config.getInteger(CHUNK_SIZE_PROPERTY);
     }
 
@@ -315,7 +350,7 @@
         firePropertyChange(CHUNK_SIZE_PROPERTY, oldValue, getChunkSize());
     }
 
-    public int getQueueSize() {
+    public Integer getQueueSize() {
         return config.getInteger(QUEUE_SIZE_PROPERTY);
     }
 
@@ -325,7 +360,7 @@
         firePropertyChange(QUEUE_SIZE_PROPERTY, oldValue, getQueueSize());
     }
 
-    public int getStationPosition() {
+    public Integer getStationPosition() {
         return config.getInteger(STATION_POSITION_PROPERTY);
     }
 
@@ -345,7 +380,7 @@
         firePropertyChange(WAIT_MODE_PROPERTY, oldValue, getWaitMode());
     }
 
-    public int getWaitTime() {
+    public Integer getWaitTime() {
         return config.getInteger(WAIT_TIME_PROPERTY);
     }
 
@@ -355,7 +390,7 @@
         firePropertyChange(WAIT_TIME_PROPERTY, oldValue, getWaitTime());
     }
 
-    public int getPrescale() {
+    public Integer getPrescale() {
         return config.getInteger(PRESCALE_PROPERTY);
     }
 
@@ -364,8 +399,34 @@
         config.set(PRESCALE_PROPERTY, prescale);
         firePropertyChange(PRESCALE_PROPERTY, oldValue, getPrescale());
     }
-
-    public boolean getSaveLayout() {
+    
+    public void setUserRunNumber(Integer userRunNumber) {
+        Integer oldValue = null;
+        if (hasPropertyValue(USER_RUN_NUMBER_PROPERTY)) {
+            oldValue = getUserRunNumber();
+        }
+        config.set(USER_RUN_NUMBER_PROPERTY, userRunNumber);
+        firePropertyChange(USER_RUN_NUMBER_PROPERTY, oldValue, getUserRunNumber());
+    }
+    
+    public Integer getUserRunNumber() {
+        return config.getInteger(USER_RUN_NUMBER_PROPERTY);
+    }
+    
+    public void setFreezeConditions(boolean freezeConditions) {
+        Boolean oldValue = null;
+        if (hasPropertyValue(FREEZE_CONDITIONS_PROPERTY)) {
+            oldValue = getFreezeConditions();
+        }
+        config.set(FREEZE_CONDITIONS_PROPERTY, freezeConditions);
+        firePropertyChange(FREEZE_CONDITIONS_PROPERTY, oldValue, freezeConditions);
+    }
+    
+    public Boolean getFreezeConditions() {
+        return config.getBoolean(FREEZE_CONDITIONS_PROPERTY);
+    }
+
+    public Boolean getSaveLayout() {
         return config.getBoolean(SAVE_LAYOUT_PROPERTY);
     }
 
@@ -412,7 +473,11 @@
             firePropertyChange(property, oldValue, null);
         }
     }
-
+    
+    public boolean hasPropertyValue(String key) {
+        return config.hasKey(key) ? true : false;
+    }
+        
     @Override
     public String[] getPropertyNames() {
         return CONFIG_PROPERTIES;