/* * ALMA - Atacama Large Millimiter Array (c) European Southern Observatory, 2009 * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2.1 of the License, or (at your option) * any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, Inc., * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ package alma.acsplugins.alarmsystem.gui.detail; import java.awt.FontMetrics; import java.awt.Graphics2D; import java.awt.image.BufferedImage; import java.text.SimpleDateFormat; import java.util.Properties; import java.util.Set; import java.util.Vector; import javax.swing.JLabel; import javax.swing.JTable; import javax.swing.table.AbstractTableModel; import javax.swing.table.TableColumn; import alma.acs.util.IsoDateFormat; import alma.acs.gui.util.threadsupport.EDTExecutor; import alma.acsplugins.alarmsystem.gui.table.AlarmTableModel; import cern.laser.client.data.Alarm; import cern.laser.client.data.ResponsiblePerson; import cern.laser.client.data.Status; import cern.laser.client.data.Triplet; /** * The table with the details of an alarm * <P> * The table has two columns, one with the name of the field and the second with * its value. * The number of rows can change because the alarm might have user properties. * * @author acaproni * */ public class AlarmDetailTable extends JTable { /** * The tiltes of the rows that appear on the left side * of the table. * <i>Note</i>: to change the order of the row, change the declaration * order of the items of this enumerated. * * @author acaproni * */ public enum RowTitles { COMPONENT("Component"), // FM TIMESTAMP("Source timestamp "), CAUSE("Cause"), PRIORITY("Priority"), DESCRIPTION("Description"), ACTION("Action"), CONSEQUENCE("Consequence"), STATUS("Status"), HOST("Host"), URL("Help page:"), RESPONSIBLE("Contact"), EMAIL("Email"), GSM("GSM"), CODE("Code"), FAMILY("Family"), TRIPLET("Triplet"), ID("ID"); /** * The tile of the row */ private final String title; /** * The title of the row in HTML, bold. */ private final String htmlTitle; /** * Constructor * * @param The title of the row */ private RowTitles(String title) { this.title=title; this.htmlTitle="<HTML><B>"+title+"</B></HTML>"; } } /** * The model for this table: it display the details of one alarm. * <P> * When the table does not display an alarm, it is blank * * @author acaproni */ public class AlarmDetailTableModel extends AbstractTableModel { /** * The date format */ private SimpleDateFormat dateFormat = new IsoDateFormat(); /** * The string shown when there is no alarm */ private final String blankStr=""; @Override public int getColumnCount() { return 2; } @Override public int getRowCount() { int ret= RowTitles.values().length; if (alarm!=null) { Properties props=alarm.getStatus().getUserProperties(); if (props!=null) { ret+=props.size(); } } return ret; } @Override public Object getValueAt(int rowIndex, int columnIndex) { // Titles if (columnIndex==0) { if (rowIndex<RowTitles.values().length) { return RowTitles.values()[rowIndex].htmlTitle; } else { // Titles of properties return propertyNames.get(rowIndex-RowTitles.values().length); } } if (alarm==null) { return blankStr; } if (rowIndex>=RowTitles.values().length) { String key = propertyNames.get(rowIndex-RowTitles.values().length); return alarm.getStatus().getUserProperties().getProperty(key); } switch (RowTitles.values()[rowIndex]) { case COMPONENT: return alarm.getTriplet().getFaultMember(); case CAUSE: return alarm.getCause(); case DESCRIPTION: return alarm.getProblemDescription(); case ACTION: return alarm.getAction(); case CONSEQUENCE: return alarm.getConsequence(); case EMAIL: return alarm.getPiquetEmail(); case GSM: return alarm.getPiquetGSM(); case HOST: { Status status= alarm.getStatus(); if (status!=null) { return status.getSourceHostname(); } else { return blankStr; } } case ID: return alarm.getAlarmId(); case RESPONSIBLE: { ResponsiblePerson responsible= alarm.getResponsiblePerson(); if (responsible!=null) { return responsible.getFirstName()+ " "+responsible.getFamilyName(); } else { return blankStr; } } case STATUS: { Status st = alarm.getStatus(); if (st!=null) { if (st.isActive()) { return "Active"; } else { return "Cleared"; } } else { return blankStr; } } case TRIPLET: { Triplet triplet = alarm.getTriplet(); if (triplet!=null) { StringBuilder str = new StringBuilder("<"); str.append(triplet.getFaultFamily()); str.append(", "); str.append(triplet.getFaultMember()); str.append(", "); str.append(triplet.getFaultCode()); str.append(">"); return str.toString(); } else { return "Cleared"; } } case URL: return alarm.getHelpURL(); case PRIORITY: { int priority=alarm.getPriority().intValue(); return AlarmTableModel.PriorityLabel.fromPriorityNumber(priority); } case TIMESTAMP: { return dateFormat.format(alarm.getStatus().getSourceTimestamp()); } case FAMILY: return alarm.getTriplet().getFaultFamily(); case CODE: return alarm.getTriplet().getFaultCode(); } return blankStr; } } /** * The model of the table. */ private final AlarmDetailTableModel model = new AlarmDetailTableModel(); /** * The alarm to which this table shows the details. * <P> * If <code>null</code> tha table is cleared. */ private Alarm alarm=null; /** * The name of the user properties are stored in a Vector that * is easier to manipulate from the point of view of the table model. * <P> * It is <code>null</code> if the alarm contains no properties i.e. * it is <code>null</code> ir its size is greater then 0. */ private Vector<String> propertyNames=null; /** * The renderer for the table value */ private final JLabel renderer = new JLabel(); /** * Constructor */ public AlarmDetailTable() { super(); setModel(model); initialize(); } /** * Init the GUI */ private void initialize() { setAutoResizeMode(JTable.AUTO_RESIZE_LAST_COLUMN); setTitleColumnSize(null); // Remove the table header TableColumn col0=getColumnModel().getColumn(0); col0.setHeaderValue("Field"); TableColumn col1=getColumnModel().getColumn(1); col1.setHeaderValue("Value"); } /** * Calculate the width of the first column to be at least wide * enough to contain the titles in {@link RowTitles}. * <P> * The width of the column is the greatest between the width needed * to show the title or the passed width * * @param sz A vector of string (can be <code>null</code>) * @return The width of the first column */ private int setTitleColumnSize(Vector<String> strings) { BufferedImage bImg = new BufferedImage(100,100,BufferedImage.TYPE_INT_RGB); Graphics2D g2D= bImg.createGraphics(); FontMetrics fm=g2D.getFontMetrics(); int sz=0; for (RowTitles row: RowTitles.values()) { if (sz<fm.stringWidth(row.title)) { sz=fm.stringWidth(row.title); } } if (strings!=null) { for (String str: strings) { if (sz<fm.stringWidth(str)) { sz=fm.stringWidth(str); } } } sz+=20; TableColumn col=getColumnModel().getColumn(0); col.setPreferredWidth(sz); col.setMinWidth(sz); col.setMaxWidth(sz); col.setWidth(sz); col.setResizable(false); col=getColumnModel().getColumn(1); col.setResizable(true); return sz; } @Override public String getColumnName(int column) { if (column==0) { return "Field"; } else { return "Value"; } } /** * Set the content of the view with the details of the * passed alarm. * * @param alarm The alarm to which display the details; * if <code>null</code> the table will be cleared */ public void showAlarmDetails(Alarm alarm) { this.alarm=alarm; Status st=alarm.getStatus(); if (st==null) { propertyNames=null; } else { Properties props = st.getUserProperties(); if (props==null || props.isEmpty()) { propertyNames=null; } else { propertyNames=new Vector<String>(); Set<String> keys=props.stringPropertyNames(); for (String key: keys) { propertyNames.add(key); } } } EDTExecutor.instance().execute(new Runnable() { public void run() { setTitleColumnSize(propertyNames); model.fireTableDataChanged(); } }); } }