Print

Print


Author: [log in to unmask]
Date: Mon Nov 10 16:42:56 2014
New Revision: 1483

Log:
Change detector field from text to combo box listing all available detectors. HPSJAVA-310

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

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	Mon Nov 10 16:42:56 2014
@@ -15,6 +15,7 @@
     static final String CONNECT = "connect";
     static final String CLEAR_LOG_TABLE = "clearLogTable";
     static final String DATA_SOURCE_TYPE_CHANGED = "dataSourceTypeChanged";
+    static final String DETECTOR_NAME_CHANGED = "detectorNameChanged";
     static final String DISCONNECT = "disconnect";
     static final String DISCONNECT_ON_ERROR_CHANGED = "disconnectOnErrorChanged";
     static final String DISCONNECT_ON_END_RUN_CHANGED = "disconnectOnEndRunChanged";

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	Mon Nov 10 16:42:56 2014
@@ -3,6 +3,7 @@
 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;
@@ -29,12 +30,15 @@
 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;
+import java.util.Collections;
 import java.util.Enumeration;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Properties;
 import java.util.Set;
 import java.util.jar.JarEntry;
 import java.util.jar.JarFile;
@@ -59,17 +63,13 @@
  * 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.
  */
-// TODO: Add validity checks for event builder, lcsim steering files, etc.
-// and revert to old values if new values are invalid.
-// http://docs.oracle.com/javase/7/docs/api/javax/swing/JFormattedTextField.html
 class JobSettingsPanel extends AbstractFieldsPanel {
 
     private JTextField aidaSaveFileNameField;
     private JCheckBox aidaAutoSaveCheckbox;
-    private JTextField detectorNameField;
     private JCheckBox disconnectOnErrorCheckBox;
     private JCheckBox disconnectOnEndRunCheckBox;
-    //private JTextField eventBuilderField;
+    private JComboBox<String> detectorNameComboBox;
     private JComboBox<String> eventBuilderComboBox;
     private JTextField logFileNameField;
     private JComboBox<?> logLevelComboBox;
@@ -81,14 +81,21 @@
     // The package where steering resources must be located.
     static final String STEERING_PACKAGE = "org/hps/steering/monitoring/";
 
-    // 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.LCSimEngRunEventBuilder";
-
-    // This will connect the GUI component to the underlying global configuration model.
+    // This connects the GUI to the global configuration model.
     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(), Level.FINE.toString(), Level.CONFIG.toString(), Level.INFO.toString(), Level.WARNING.toString(), Level.SEVERE.toString(), Level.OFF.toString() };
+    static final String[] LOG_LEVELS = new String[] { 
+        Level.ALL.toString(), 
+        Level.FINEST.toString(), 
+        Level.FINER.toString(), 
+        Level.FINE.toString(), 
+        Level.CONFIG.toString(), 
+        Level.INFO.toString(), 
+        Level.WARNING.toString(), 
+        Level.SEVERE.toString(), 
+        Level.OFF.toString() 
+    };
 
     /**
      * Class constructor.
@@ -121,15 +128,16 @@
         steeringFileButton.setActionCommand(Commands.CHOOSE_STEERING_FILE);
         steeringFileButton.addActionListener(this);
 
-        steeringResourcesComboBox = addComboBoxMultiline("Steering File Resource", getAvailableSteeringFileResources(STEERING_PACKAGE));
+        steeringResourcesComboBox = addComboBoxMultiline("Steering File Resource", findSteeringResources(STEERING_PACKAGE));
         steeringResourcesComboBox.setActionCommand(STEERING_RESOURCE_CHANGED);
         steeringResourcesComboBox.addActionListener(this);
 
-        detectorNameField = addField("Detector Name", 20);
-        detectorNameField.addPropertyChangeListener("value", this);
+        detectorNameComboBox = addComboBox("Detector Name", this.findDetectorNames());
+        detectorNameComboBox.setActionCommand(DETECTOR_NAME_CHANGED);
+        detectorNameComboBox.addActionListener(this);
 
         eventBuilderComboBox = addComboBox("LCSim Event Builder", this.findEventBuilderClassNames());
-        eventBuilderComboBox.setActionCommand(Commands.EVENT_BUILDER_CHANGED);
+        eventBuilderComboBox.setActionCommand(EVENT_BUILDER_CHANGED);
         eventBuilderComboBox.addActionListener(this);
         
         logToFileCheckbox = addCheckBox("Log to File", false, false);
@@ -180,7 +188,6 @@
      * Attaches the ActionListener from the main app to specific GUI components in this class.
      */
     void addActionListener(ActionListener listener) {
-        eventBuilderComboBox.addActionListener(listener);
         logFileNameField.addActionListener(listener);
         logToFileCheckbox.addActionListener(listener);
         steeringResourcesComboBox.addActionListener(listener);
@@ -236,41 +243,8 @@
         Document document = builder.build(file);
         Element rootNode = document.getRootElement();
         if (!rootNode.getName().equals("lcsim")) {
-            throw new IOException("Not an LCSim XML file.");
-        }
-    }
-
-    /**
-     * Get the files with extension "lcsim" from all loaded jar files.
-     * @return A list of embedded steering file resources.
-     */
-    static String[] getAvailableSteeringFileResources(String packageName) {
-        List<String> resources = new ArrayList<String>();
-        URL url = JobSettingsPanel.class.getResource("MonitoringApplication.class");
-        String scheme = url.getProtocol();
-        if (!"jar".equals(scheme)) {
-            throw new IllegalArgumentException("Unsupported scheme.  Only jar is allowed.");
-        }
-        try {
-            JarURLConnection con = (JarURLConnection) url.openConnection();
-            JarFile archive = con.getJarFile();
-            Enumeration<JarEntry> entries = archive.entries();
-            while (entries.hasMoreElements()) {
-                JarEntry entry = entries.nextElement();
-                if (entry.getName().endsWith(".lcsim") && entry.getName().contains(packageName)) {
-                    resources.add(entry.getName());
-                }
-            }
-            archive.close();
-        } catch (IOException e) {
-            throw new RuntimeException(e);
-        }
-        java.util.Collections.sort(resources);
-        String[] arr = new String[resources.size()];
-        for (int i = 0; i < arr.length; i++) {
-            arr[i] = resources.get(i);
-        }
-        return arr;
+            throw new IOException("Not an LCSim XML file: " + file.getPath());
+        }
     }
 
     @Override
@@ -293,6 +267,8 @@
             configurationModel.setAidaAutoSave(aidaAutoSaveCheckbox.isSelected());
         } else if (EVENT_BUILDER_CHANGED.equals(e.getActionCommand())) {
             configurationModel.setEventBuilderClassName((String) eventBuilderComboBox.getSelectedItem());
+        } else if (DETECTOR_NAME_CHANGED.equals(e.getActionCommand())) {
+            configurationModel.setDetectorName((String) detectorNameComboBox.getSelectedItem());
         } 
     }
 
@@ -309,9 +285,7 @@
 
         Object source = evt.getSource();
 
-        if (source == detectorNameField) {
-            configurationModel.setDetectorName(detectorNameField.getText());
-        } else if (source == steeringFileField) {
+        if (source == steeringFileField) {
             configurationModel.setSteeringFile(steeringFileField.getText());
         } else if (source == logFileNameField) {
             configurationModel.setLogFileName(logFileNameField.getText());
@@ -326,7 +300,7 @@
      * 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 {
+    private class JobSettingsChangeListener implements PropertyChangeListener {
         @Override
         public void propertyChange(PropertyChangeEvent evt) {
 
@@ -337,7 +311,7 @@
             Object value = evt.getNewValue();
 
             if (evt.getPropertyName().equals(DETECTOR_NAME_PROPERTY)) {
-                detectorNameField.setText((String) value);
+                detectorNameComboBox.setSelectedItem((String) value);
             } else if (evt.getPropertyName().equals(AIDA_AUTO_SAVE_PROPERTY)) {
                 aidaAutoSaveCheckbox.setSelected((Boolean) value);
             } else if (evt.getPropertyName().equals(AIDA_FILE_NAME_PROPERTY)) {
@@ -364,7 +338,46 @@
         }
     }
     
-    String[] findEventBuilderClassNames() {
+    /**
+     * Get the files with extension 'lcsim' from all loaded jar files.
+     * @param packageName The package name for filtering the resources.
+     * @return A list of embedded steering file resources.
+     */
+    private static String[] findSteeringResources(String packageName) {
+        List<String> resources = new ArrayList<String>();
+        URL url = JobSettingsPanel.class.getResource("MonitoringApplication.class");
+        String scheme = url.getProtocol();
+        if (!"jar".equals(scheme)) {
+            throw new IllegalArgumentException("Unsupported scheme.  Only jar is allowed.");
+        }
+        try {
+            JarURLConnection con = (JarURLConnection) url.openConnection();
+            JarFile archive = con.getJarFile();
+            Enumeration<JarEntry> entries = archive.entries();
+            while (entries.hasMoreElements()) {
+                JarEntry entry = entries.nextElement();
+                if (entry.getName().endsWith(".lcsim") && entry.getName().contains(packageName)) {
+                    resources.add(entry.getName());
+                }
+            }
+            archive.close();
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+        java.util.Collections.sort(resources);
+        String[] arr = new String[resources.size()];
+        for (int i = 0; i < arr.length; i++) {
+            arr[i] = resources.get(i);
+        }
+        return arr;
+    }
+    
+    /**
+     * Find all classes that implement {@link org.hps.evio.LCSimEventBuilder} and return
+     * a list of their canonical names.
+     * @return The list of classes implementing LCSimEventBuilder.
+     */
+    private static String[] findEventBuilderClassNames() {
         Reflections reflections = new Reflections("org.hps");
         Set<Class<? extends LCSimEventBuilder>> subTypes = reflections.getSubTypesOf(LCSimEventBuilder.class);
         Set<String> classNames = new HashSet<String>();
@@ -373,4 +386,45 @@
         }
         return classNames.toArray(new String[classNames.size()]);        
     }
+ 
+    /**
+     * Find a list of available detector names.
+     * Only those detectors that have names starting with "HPS" in their
+     * detector.properties files will be returned.
+     * @return The list of available detector names.
+     */
+    private static String[] findDetectorNames() {
+        ClassLoader classLoader = JobSettingsPanel.class.getClassLoader();
+        List<String> detectorNames = new ArrayList<String>();
+        URL url = JobSettingsPanel.class.getResource("MonitoringApplication.class");
+        String protocol = url.getProtocol();
+        if (!"jar".equals(protocol)) {
+            throw new RuntimeException("Unsupported URL protocol: " + url.getProtocol());
+        }
+        try {
+            JarURLConnection con = (JarURLConnection) url.openConnection();
+            JarFile archive = con.getJarFile();
+            Enumeration<JarEntry> entries = archive.entries();
+            while (entries.hasMoreElements()) {
+                JarEntry entry = entries.nextElement();
+                if (entry.getName().endsWith("detector.properties")) {
+                    InputStream inputStream = classLoader.getResourceAsStream(entry.getName());
+                    if (inputStream == null) {
+                        throw new RuntimeException("Failed to load jar entry: " + entry.getName());
+                    }
+                    Properties properties = new Properties();
+                    properties.load(inputStream);
+                    String detectorName = properties.getProperty("name");
+                    if (detectorName.startsWith("HPS")) {
+                        detectorNames.add(detectorName);
+                    }
+                }
+            }
+            archive.close();
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+        Collections.sort(detectorNames);
+        return detectorNames.toArray(new String[detectorNames.size()]);
+    }
 }