Print

Print


Commit in java/trunk/monitoring-app/src/main/java/org/hps/monitoring on MAIN
gui/MonitoringApplication.java+2-3765 -> 766
   /SystemStatusFrame.java+61-131765 -> 766
   /SystemStatusTableModel.java+125added 766
subsys/SystemStatus.java+18-32765 -> 766
      /SystemStatusImpl.java+5-5765 -> 766
subsys/et/EtSystemMonitor.java+35-3765 -> 766
+246-174
1 added + 5 modified, total 6 files
Use a proper TableModel implementation for the system status monitor.  Make the EtSystemMonitor do something actually somewhat useful.  Make description and system name of SystemStatus immutable.

java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui
MonitoringApplication.java 765 -> 766
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui/MonitoringApplication.java	2014-07-14 18:36:00 UTC (rev 765)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui/MonitoringApplication.java	2014-07-14 22:00:35 UTC (rev 766)
@@ -95,7 +95,6 @@
  */
 // TODO: Test all application error handling!
 // TODO: Review GUI size settings.
-// TODO: Add handler for uncaught exceptions.
 // TODO: Add back option to continue if event processing errors occur.  
 //       Fatal errors like the ET system being down should still cause an automatic disconnect.
 // FIXME: Review use of the watchdog thread for automatic disconnect.  It may be overcomplicated.
@@ -1448,10 +1447,10 @@
     }
     
     private void setupSystemStatusMonitor() {
-        systemStatusFrame.clear();
+        systemStatusFrame.getTableModel().clear();
         SystemStatusRegistry registry = SystemStatusRegistry.getSystemStatusRegistery();
         for (SystemStatus systemStatus : registry.getSystemStatuses()) {
-            systemStatusFrame.addSystemStatus(systemStatus);
+            systemStatusFrame.getTableModel().addSystemStatus(systemStatus);
         }
     }
 

java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui
SystemStatusFrame.java 765 -> 766
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui/SystemStatusFrame.java	2014-07-14 18:36:00 UTC (rev 765)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui/SystemStatusFrame.java	2014-07-14 22:00:35 UTC (rev 766)
@@ -1,178 +1,104 @@
 package org.hps.monitoring.gui;
 
+import static org.hps.monitoring.gui.SystemStatusTableModel.ACTIVE_COL;
+import static org.hps.monitoring.gui.SystemStatusTableModel.LAST_CHANGED_COL;
+import static org.hps.monitoring.gui.SystemStatusTableModel.STATUS_COL;
+import static org.hps.monitoring.gui.SystemStatusTableModel.SYSTEM_COL;
+import static org.hps.monitoring.subsys.SystemStatus.StatusCode.OFFLINE;
+import static org.hps.monitoring.subsys.SystemStatus.StatusCode.OKAY;
+import static org.hps.monitoring.subsys.SystemStatus.StatusCode.UNKNOWN;
+import static org.hps.monitoring.subsys.SystemStatus.StatusCode.WARNING;
+
 import java.awt.Color;
 import java.awt.Component;
 import java.awt.Dimension;
 import java.text.SimpleDateFormat;
-import java.util.ArrayList;
 import java.util.Date;
-import java.util.List;
 
 import javax.swing.JFrame;
 import javax.swing.JLabel;
 import javax.swing.JScrollPane;
 import javax.swing.JTable;
-import javax.swing.event.TableModelEvent;
-import javax.swing.event.TableModelListener;
 import javax.swing.table.DefaultTableCellRenderer;
-import javax.swing.table.DefaultTableModel;
 
 import org.hps.monitoring.subsys.SystemStatus;
 import org.hps.monitoring.subsys.SystemStatus.StatusCode;
-import org.hps.monitoring.subsys.SystemStatusListener;
 
 /**
  * A GUI window for showing changes to {@link org.hps.monitoring.subsys.SystemStatus} objects.
  * @author Jeremy McCormick <[log in to unmask]>
  */
-// TODO: Add custom table model.
-public class SystemStatusFrame extends JFrame implements SystemStatusListener, TableModelListener, HasErrorHandler {
+public class SystemStatusFrame extends JFrame implements HasErrorHandler {
 
-    private static final int ACTIVE_COL = 0;
-    private static final int STATUS_COL = 1;
-    private static final int SYSTEM_COL = 2;
-    private static final int DESCRIPTION_COL = 3;
-    private static final int MESSAGE_COL = 4;
-    private static final int LAST_CHANGED_COL = 5;
-            
-    String[] columnNames = {
-            "Active",
-            "Status",
-            "System",       
-            "Description",
-            "Message", 
-            "Last Changed"
-    };
-           
     JTable table;
-    DefaultTableModel tableModel;
-    List<SystemStatus> systemStatuses = new ArrayList<SystemStatus>();
-    final SimpleDateFormat dateFormat = new SimpleDateFormat("MMMM-dd-yyyy HH:mm:ss.SSS");
     ErrorHandler errorHandler;
-    
+
     int WIDTH = 650;
     int HEIGHT = ScreenUtil.getScreenHeight() / 2;
-    
+
     SystemStatusFrame() {
-         
-        String data[][] = new String[0][0];
-        tableModel = new DefaultTableModel(data, columnNames) {
-                public Class getColumnClass(int column) {
-                    switch (column) {
-                        case ACTIVE_COL:
-                            return Boolean.class;
-                        default:
-                            return String.class;
-                    }                    
+        table = new JTable(new SystemStatusTableModel());
+        table.getColumnModel().getColumn(SystemStatusTableModel.STATUS_COL).setCellRenderer(new DefaultTableCellRenderer() {
+
+            @Override
+            public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int col) {
+
+                // Cells are by default rendered as a JLabel.
+                JLabel label = (JLabel) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, col);
+
+                // Color code the cell by its status.
+                SystemStatus.StatusCode statusCode = SystemStatus.StatusCode.valueOf((String) value);
+                if (statusCode.ordinal() >= StatusCode.ERROR.ordinal()) {
+                    // Any type of error is red.
+                    label.setBackground(Color.RED);
+                } else if (statusCode.ordinal() == WARNING.ordinal()) {
+                    // Warnings are yellow.
+                    label.setBackground(Color.YELLOW);
+                } else if (statusCode.ordinal() == OKAY.ordinal()) {
+                    // Okay is green.
+                    label.setBackground(Color.GREEN);
+                } else if (statusCode.ordinal() == OFFLINE.ordinal()) {
+                    // Offline is orange.
+                    label.setBackground(Color.ORANGE);
+                } else if (statusCode.ordinal() == UNKNOWN.ordinal()) {
+                    // Unknown is gray.
+                    label.setBackground(Color.GRAY);
+                } else {
+                    // Default is white, though this shouldn't ever happen!
+                    label.setBackground(Color.WHITE);
                 }
-                
-                public boolean isCellEditable(int row, int col) {
-                    if (col == ACTIVE_COL)
-                        return true;
-                    else 
-                        return false;
-                }
-        };        
-        tableModel.addTableModelListener(this);
-        table = new JTable(tableModel);
-        table.getColumnModel().getColumn(STATUS_COL).setCellRenderer(
-                new DefaultTableCellRenderer() {                    
-                    @Override
-                    public Component getTableCellRendererComponent(
-                            JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int col) {
+                return label;
+            }
+        });
+        table.getColumnModel().getColumn(LAST_CHANGED_COL).setCellRenderer(new DefaultTableCellRenderer() {
 
-                        // Cells are by default rendered as a JLabel.
-                        JLabel label = (JLabel) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, col);
+            final SimpleDateFormat dateFormat = new SimpleDateFormat("MMMM-dd-yyyy HH:mm:ss.SSS");
 
-                        // Color code the cell by its status.
-                        SystemStatus.StatusCode statusCode = SystemStatus.StatusCode.valueOf((String) value);
-                        if (statusCode.ordinal() >= StatusCode.ERROR.ordinal()) {
-                            // Any type of error is red.
-                            label.setBackground(Color.RED);
-                        } else if (statusCode.ordinal() == StatusCode.WARNING.ordinal()) {
-                            // Warnings are yellow.
-                            label.setBackground(Color.YELLOW);
-                        } else if (statusCode.ordinal() == StatusCode.OKAY.ordinal()) {
-                            // Okay is green.
-                            label.setBackground(Color.GREEN);
-                        } else if (statusCode.ordinal() == StatusCode.OFFLINE.ordinal()) {
-                            // Offline is orange.
-                            label.setBackground(Color.ORANGE);
-                        } else if (statusCode.ordinal() == StatusCode.UNKNOWN.ordinal()) {
-                            // Unknown is gray.
-                            label.setBackground(Color.GRAY);
-                        } else {
-                            // Default is white, though this shouldn't ever happen!
-                            label.setBackground(Color.WHITE);
-                        }
-                        return label;                    
-                    }
+            @Override
+            public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
+                if (value instanceof Date) {
+                    value = dateFormat.format(value);
                 }
-        );
+                return super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
+            }
+        });
         table.getColumnModel().getColumn(ACTIVE_COL).setPreferredWidth(8);
         table.getColumnModel().getColumn(STATUS_COL).setPreferredWidth(10);
         table.getColumnModel().getColumn(SYSTEM_COL).setPreferredWidth(10);
         // TODO: Add widths for every column.
-        
+
         JScrollPane scrollPane = new JScrollPane(table);
         scrollPane.setOpaque(true);
-        
+
         setMinimumSize(new Dimension(WIDTH, HEIGHT));
         setTitle("System Status Monitor");
         setContentPane(scrollPane);
         setResizable(true);
         setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
-        pack();        
-    }        
-    
-    void addSystemStatus(SystemStatus status) {        
-        
-        // Insert row data into table.
-        Object[] record = new Object[] {
-                (Boolean)status.isActive(),
-                status.getStatusCode().name(),
-                status.getSystemName(),                
-                status.getStatusCode().description(),
-                status.getMessage(),
-                new Date(status.getLastChangedMillis())
-        };
-        tableModel.insertRow(table.getRowCount(), record);
-        
-        // Add to list for easily finding its row number later.
-        systemStatuses.add(status);
-        
-        // Add this class as a listener to get notification of status changes.
-        status.addListener(this);
+        pack();
     }
 
     @Override
-    public void statusChanged(SystemStatus status) {
-        int rowNumber = systemStatuses.indexOf(status);
-        tableModel.setValueAt(status.isActive(), rowNumber, ACTIVE_COL);
-        tableModel.setValueAt(status.getStatusCode().name(), rowNumber, STATUS_COL);
-        tableModel.setValueAt(status.getSystemName(), rowNumber, SYSTEM_COL);        
-        tableModel.setValueAt(status.getStatusCode().description(), rowNumber, DESCRIPTION_COL);
-        tableModel.setValueAt(status.getMessage(), rowNumber, MESSAGE_COL);
-        tableModel.setValueAt(dateFormat.format(new Date(status.getLastChangedMillis())), rowNumber, LAST_CHANGED_COL);
-    }
-    
-    public void clear() {
-        tableModel.setNumRows(0);
-        systemStatuses.clear();
-    }
-
-    @Override
-    public void tableChanged(TableModelEvent e) {
-        int col = e.getColumn();
-        if (col == ACTIVE_COL) {
-            int row = e.getFirstRow();
-            SystemStatus status = this.systemStatuses.get(row);
-            boolean active = (Boolean)tableModel.getValueAt(row, col);
-            status.setActive(active);
-        }
-    }
-
-    @Override
     public void setErrorHandler(ErrorHandler errorHandler) {
         this.errorHandler = errorHandler;
     }
@@ -181,4 +107,8 @@
     public ErrorHandler getErrorHandler() {
         return errorHandler;
     }
-}
+
+    public SystemStatusTableModel getTableModel() {
+        return (SystemStatusTableModel) table.getModel();
+    }
+}
\ No newline at end of file

java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui
SystemStatusTableModel.java added at 766
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui/SystemStatusTableModel.java	                        (rev 0)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui/SystemStatusTableModel.java	2014-07-14 22:00:35 UTC (rev 766)
@@ -0,0 +1,125 @@
+package org.hps.monitoring.gui;
+
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+import javax.swing.table.AbstractTableModel;
+
+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.
+ * @author Jeremy McCormick <[log in to unmask]>
+ */
+public class SystemStatusTableModel extends AbstractTableModel implements SystemStatusListener {
+
+    static final int ACTIVE_COL = 0;
+    static final int STATUS_COL = 1;
+    static final int SYSTEM_COL = 2;
+    static final int DESCRIPTION_COL = 3;
+    static final int MESSAGE_COL = 4;
+    static final int LAST_CHANGED_COL = 5;
+            
+    static final String[] columnNames = {
+            "Active",
+            "Status",
+            "System",       
+            "Description",
+            "Message", 
+            "Last Changed"
+    };
+    
+    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();
+    }
+    
+    /*
+    public SystemStatus getSystemStatus(int row) {
+        return statuses.get(row);
+    }
+    */
+    
+    @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(int rowIndex, 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.getSystemName().name();
+            case DESCRIPTION_COL:
+                return status.getDescription();
+            case MESSAGE_COL:
+                return status.getMessage();
+            case LAST_CHANGED_COL:
+                return new Date(status.getLastChangedMillis());
+            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/subsys
SystemStatus.java 765 -> 766
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/subsys/SystemStatus.java	2014-07-14 18:36:00 UTC (rev 765)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/subsys/SystemStatus.java	2014-07-14 22:00:35 UTC (rev 766)
@@ -20,31 +20,16 @@
      * Code that represents the status of the monitoring quantity.    
      */
     enum StatusCode {
-        
-        /** Status encodings with a string name and descriptor. */
-        OKAY   ("System appears to be working."),
-        UNKNOWN("Status is not known."),
-        OFFLINE("System is currently offline."),               
-        WARNING("There is a non-fatal warning."),
-        ERROR  ("A serious error has occurred."),
-        ALARM  ("A fatal error has tripped an alarm."),
-        HALT   ("The system should be immediately halted.");
-        
-        String description;
-        
-        StatusCode(String description) {
-            this.description = description;
-        }
-                                
-        /**
-         * Get the description of the status.
-         * @return The description of the status.
-         */
-        public String description() {
-            return description;
-        }
+        OKAY, 
+        UNKNOWN,
+        OFFLINE,               
+        WARNING,
+        ERROR,
+        ALARM,
+        HALT;        
     }
     
+    /** Names of valid subsystems that can be monitored. */
     enum SystemName {        
         ET,
         ECAL,
@@ -55,7 +40,7 @@
     /**
      * Get the name of the sub-system e.g. "SVT".
      */
-    String getSystemName();
+    SystemName getSystemName();
     
     /**
      * Get the current status code.
@@ -64,20 +49,20 @@
     StatusCode getStatusCode();
     
     /**
-     * Get the current message.
-     * @return The current message
-     */
-    String getMessage();
-    
-    /**
      * Get the description of the system status.
      * This is used to differentiate multiple monitoring points
      * on the same sub-system so it could be something like "SVT occupancy rates".
      * @return The description of the system status.
      */
     String getDescription();
-
+    
     /**
+     * Get the current message.
+     * @return The current message
+     */
+    String getMessage();
+    
+    /**
      * Set the current status code, which will cause the last changed 
      * time to be set and the listeners to be notified.
      * @param code The new status code.
@@ -98,7 +83,8 @@
     void addListener(SystemStatusListener listener);
     
     /**
-     * Set whether this status is active.  
+     * Set whether this status is active.  Inactive statuses will not be
+     * updated in the GUI.  This can be changed "on the fly" in the system status panel.
      * Listeners will not be notified of state changes when active is <code>False</code>.     
      */
     void setActive(boolean active);

java/trunk/monitoring-app/src/main/java/org/hps/monitoring/subsys
SystemStatusImpl.java 765 -> 766
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/subsys/SystemStatusImpl.java	2014-07-14 18:36:00 UTC (rev 765)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/subsys/SystemStatusImpl.java	2014-07-14 22:00:35 UTC (rev 766)
@@ -7,17 +7,17 @@
  * The implementation of {@link SystemStatus}.
  * @author Jeremy McCormick <[log in to unmask]>
  */
-public class SystemStatusImpl implements SystemStatus {
+public final class SystemStatusImpl implements SystemStatus {
 
     StatusCode code = SystemStatus.StatusCode.UNKNOWN;
     long lastChangedMillis;
     String message;
     List<SystemStatusListener> listeners = new ArrayList<SystemStatusListener>();
-    String systemName = "";
-    String description = "";
+    final SystemName systemName;
+    final String description;
     boolean active = true;
     
-    public SystemStatusImpl(String systemName, String description) {
+    public SystemStatusImpl(SystemName systemName, String description) {
         this.systemName = systemName;
         this.description = description;
         setLastChangedTime();
@@ -25,7 +25,7 @@
     }
     
     @Override
-    public String getSystemName() {
+    public SystemName getSystemName() {
         return systemName;
     }
     

java/trunk/monitoring-app/src/main/java/org/hps/monitoring/subsys/et
EtSystemMonitor.java 765 -> 766
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/subsys/et/EtSystemMonitor.java	2014-07-14 18:36:00 UTC (rev 765)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/subsys/et/EtSystemMonitor.java	2014-07-14 22:00:35 UTC (rev 766)
@@ -1,5 +1,10 @@
 package org.hps.monitoring.subsys.et;
 
+import static org.hps.monitoring.subsys.SystemStatus.SystemName.ET;
+
+import java.util.Timer;
+import java.util.TimerTask;
+
 import org.hps.monitoring.record.etevent.EtEventProcessor;
 import org.hps.monitoring.subsys.HasSystemStatus;
 import org.hps.monitoring.subsys.SystemStatus;
@@ -15,22 +20,49 @@
 public class EtSystemMonitor extends EtEventProcessor implements HasSystemStatus {
 
     SystemStatus systemStatus;
-    int events = 0;
+    int events = 0;    
+    long eventReceivedMillis = 0;
+    long warningIntervalMillis = 1000; /* default of 1 second */
+    Timer timer = new Timer("ET Event Monitor");
     
     public EtSystemMonitor() {
-        systemStatus = new SystemStatusImpl(SystemStatus.SystemName.ET.name(), "Example ET Monitor");
+        systemStatus = new SystemStatusImpl(ET, "Example ET Monitor");
         systemStatus.setStatusCode(StatusCode.UNKNOWN, "System is not active yet.");
     }
     
+    public void setWarningIntervalMillis(long warningIntervalMillis) {
+        this.warningIntervalMillis = warningIntervalMillis;
+    }
+    
     public void startJob() {
         systemStatus.setStatusCode(StatusCode.OKAY, "ET job started.");
+        TimerTask task = new TimerTask() {                    
+            long startedMillis = 0;
+            public void run() {
+                if (startedMillis == 0)
+                    startedMillis = System.currentTimeMillis();
+                long elapsedMillis = 0;
+                if (eventReceivedMillis == 0)
+                    elapsedMillis = System.currentTimeMillis() - startedMillis;
+                else
+                    elapsedMillis = System.currentTimeMillis() - eventReceivedMillis;                
+                if (elapsedMillis > warningIntervalMillis) 
+                    systemStatus.setStatusCode(StatusCode.WARNING, "No ET events received for " + elapsedMillis + " millis.");
+                else
+                    systemStatus.setStatusCode(StatusCode.OKAY, "ET events received.");
+            }            
+        };
+        
+        timer.schedule(task, 0, 1000);
     }
                    
     public void processEvent(EtEvent event) {
-        //systemStatus.setStatusCode(StatusCode.WARNING, "Just a dummy warning message.");
+        eventReceivedMillis = System.currentTimeMillis();
     }
     
     public void endJob() {
+        timer.cancel();
+        timer.purge();
         systemStatus.setStatusCode(StatusCode.OFFLINE, "ET job ended.");
     }
         
SVNspam 0.1