19 package org.sleuthkit.autopsy.ingest;
 
   21 import java.awt.Color;
 
   22 import java.awt.Component;
 
   23 import java.awt.Cursor;
 
   24 import java.awt.Dimension;
 
   26 import java.awt.Graphics;
 
   27 import java.beans.PropertyChangeEvent;
 
   28 import java.beans.PropertyChangeListener;
 
   29 import java.beans.PropertyChangeSupport;
 
   30 import java.text.DateFormat;
 
   31 import java.text.SimpleDateFormat;
 
   32 import java.util.ArrayList;
 
   33 import java.util.Collections;
 
   34 import java.util.Date;
 
   35 import java.util.HashMap;
 
   36 import java.util.List;
 
   38 import java.util.logging.Level;
 
   39 import javax.swing.DefaultComboBoxModel;
 
   40 import javax.swing.JLabel;
 
   41 import javax.swing.JPanel;
 
   42 import javax.swing.JTable;
 
   43 import javax.swing.ListSelectionModel;
 
   44 import javax.swing.SwingConstants;
 
   45 import javax.swing.event.ListSelectionEvent;
 
   46 import javax.swing.event.ListSelectionListener;
 
   47 import javax.swing.event.TableModelEvent;
 
   48 import javax.swing.event.TableModelListener;
 
   49 import javax.swing.table.AbstractTableModel;
 
   50 import javax.swing.table.DefaultTableCellRenderer;
 
   51 import javax.swing.table.TableCellRenderer;
 
   52 import org.openide.util.NbBundle;
 
   61 @SuppressWarnings(
"PMD.SingularField") 
 
   62 class IngestMessagePanel extends JPanel implements TableModelListener {
 
   64     private final MessageTableModel tableModel;
 
   65     private MessageTableRenderer renderer;
 
   66     private final IngestMessageMainPanel mainPanel;
 
   67     private static final Color ERROR_COLOR = 
new Color(255, 90, 90);
 
   68     private volatile int lastRowSelected = -1;
 
   69     private volatile long totalMessages = 0;
 
   70     private static final Logger logger = Logger.getLogger(IngestMessagePanel.class.getName());
 
   71     private static final PropertyChangeSupport messagePcs = 
new PropertyChangeSupport(IngestMessagePanel.class);
 
   72     static final String TOTAL_NUM_MESSAGES_CHANGED = 
"TOTAL_NUM_MESSAGES_CHANGED"; 
 
   73     static final String MESSAGES_BOX_CLEARED = 
"MESSAGES_BOX_CLEARED"; 
 
   74     static final String TOTAL_NUM_NEW_MESSAGES_CHANGED = 
"TOTAL_NUM_NEW_MESSAGES_CHANGED"; 
 
   79     public IngestMessagePanel(IngestMessageMainPanel mainPanel) {
 
   80         this.mainPanel = mainPanel;
 
   81         tableModel = 
new MessageTableModel();
 
   83         customizeComponents();
 
   86     public void markAllSeen() {
 
   87         tableModel.markAllSeen();
 
   90     int getLastRowSelected() {
 
   91         return this.lastRowSelected;
 
   94     synchronized IngestMessageGroup getSelectedMessage() {
 
   95         if (lastRowSelected < 0) {
 
   99         return tableModel.getMessageGroup(lastRowSelected);
 
  102     synchronized IngestMessageGroup getMessageGroup(
int rowNumber) {
 
  103         return tableModel.getMessageGroup(rowNumber);
 
  106     synchronized static void addPropertyChangeSupportListener(PropertyChangeListener l) {
 
  107         messagePcs.addPropertyChangeListener(l);
 
  115     @SuppressWarnings(
"unchecked")
 
  117     private 
void initComponents() {
 
  119         jScrollPane1 = 
new javax.swing.JScrollPane();
 
  120         messageTable = 
new javax.swing.JTable();
 
  121         controlPanel = 
new javax.swing.JPanel();
 
  122         sortByLabel = 
new javax.swing.JLabel();
 
  123         sortByComboBox = 
new javax.swing.JComboBox<>();
 
  124         totalMessagesNameLabel = 
new javax.swing.JLabel();
 
  125         totalMessagesNameVal = 
new javax.swing.JLabel();
 
  126         totalUniqueMessagesNameLabel = 
new javax.swing.JLabel();
 
  127         totalUniqueMessagesNameVal = 
new javax.swing.JLabel();
 
  131         jScrollPane1.setBorder(javax.swing.BorderFactory.createEmptyBorder(1, 1, 1, 1));
 
  132         jScrollPane1.setOpaque(
false);
 
  133         jScrollPane1.setPreferredSize(
new java.awt.Dimension(32767, 32767));
 
  135         messageTable.setBackground(
new java.awt.Color(221, 221, 235));
 
  136         messageTable.setFont(messageTable.getFont().deriveFont(messageTable.getFont().getStyle() & ~java.awt.Font.BOLD, 12));
 
  137         messageTable.setModel(tableModel);
 
  138         messageTable.setAutoResizeMode(javax.swing.JTable.AUTO_RESIZE_OFF);
 
  139         messageTable.setAutoscrolls(
false);
 
  140         messageTable.setCursor(
new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
 
  141         messageTable.setGridColor(
new java.awt.Color(204, 204, 204));
 
  142         messageTable.setOpaque(
false);
 
  143         messageTable.setSelectionForeground(
new java.awt.Color(0, 0, 0));
 
  144         messageTable.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
 
  145         messageTable.setShowHorizontalLines(
false);
 
  146         messageTable.setShowVerticalLines(
false);
 
  147         messageTable.getTableHeader().setReorderingAllowed(
false);
 
  148         jScrollPane1.setViewportView(messageTable);
 
  150         sortByLabel.setText(
org.openide.util.NbBundle.getMessage(IngestMessagePanel.class, 
"IngestMessagePanel.sortByLabel.text")); 
 
  152         sortByComboBox.setFont(sortByComboBox.getFont().deriveFont(sortByComboBox.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
 
  153         sortByComboBox.setToolTipText(
org.openide.util.NbBundle.getMessage(IngestMessagePanel.class, 
"IngestMessagePanel.sortByComboBox.toolTipText")); 
 
  154         sortByComboBox.addActionListener(
new java.awt.event.ActionListener() {
 
  155             public void actionPerformed(java.awt.event.ActionEvent evt) {
 
  156                 sortByComboBoxActionPerformed(evt);
 
  160         totalMessagesNameLabel.setFont(totalMessagesNameLabel.getFont().deriveFont(totalMessagesNameLabel.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
 
  161         totalMessagesNameLabel.setText(
org.openide.util.NbBundle.getMessage(IngestMessagePanel.class, 
"IngestMessagePanel.totalMessagesNameLabel.text")); 
 
  163         totalMessagesNameVal.setFont(totalMessagesNameVal.getFont().deriveFont(totalMessagesNameVal.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
 
  164         totalMessagesNameVal.setText(
org.openide.util.NbBundle.getMessage(IngestMessagePanel.class, 
"IngestMessagePanel.totalMessagesNameVal.text")); 
 
  166         totalUniqueMessagesNameLabel.setFont(totalUniqueMessagesNameLabel.getFont().deriveFont(totalUniqueMessagesNameLabel.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
 
  167         totalUniqueMessagesNameLabel.setText(
org.openide.util.NbBundle.getMessage(IngestMessagePanel.class, 
"IngestMessagePanel.totalUniqueMessagesNameLabel.text")); 
 
  169         totalUniqueMessagesNameVal.setFont(totalUniqueMessagesNameVal.getFont().deriveFont(totalUniqueMessagesNameVal.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
 
  170         totalUniqueMessagesNameVal.setText(
org.openide.util.NbBundle.getMessage(IngestMessagePanel.class, 
"IngestMessagePanel.totalUniqueMessagesNameVal.text")); 
 
  172         javax.swing.GroupLayout controlPanelLayout = 
new javax.swing.GroupLayout(controlPanel);
 
  173         controlPanel.setLayout(controlPanelLayout);
 
  174         controlPanelLayout.setHorizontalGroup(
 
  175             controlPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 
  176             .addGroup(controlPanelLayout.createSequentialGroup()
 
  178                 .addComponent(sortByLabel)
 
  179                 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
 
  180                 .addComponent(sortByComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
 
  181                 .addGap(101, 101, 101)
 
  182                 .addComponent(totalMessagesNameLabel)
 
  183                 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 
  184                 .addComponent(totalMessagesNameVal, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
 
  186                 .addComponent(totalUniqueMessagesNameLabel)
 
  187                 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 
  188                 .addComponent(totalUniqueMessagesNameVal, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
 
  191         controlPanelLayout.setVerticalGroup(
 
  192             controlPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 
  193             .addGroup(controlPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
 
  194                 .addComponent(sortByComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
 
  195                 .addComponent(sortByLabel)
 
  196                 .addComponent(totalUniqueMessagesNameLabel)
 
  197                 .addComponent(totalUniqueMessagesNameVal)
 
  198                 .addComponent(totalMessagesNameLabel)
 
  199                 .addComponent(totalMessagesNameVal))
 
  202         javax.swing.GroupLayout layout = 
new javax.swing.GroupLayout(
this);
 
  203         this.setLayout(layout);
 
  204         layout.setHorizontalGroup(
 
  205             layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 
  206             .addComponent(controlPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
 
  207             .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 376, Short.MAX_VALUE)
 
  209         layout.setVerticalGroup(
 
  210             layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 
  211             .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
 
  212                 .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 201, Short.MAX_VALUE)
 
  214                 .addComponent(controlPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
 
  218     private void sortByComboBoxActionPerformed(java.awt.event.ActionEvent evt) {
 
  219         synchronized (
this) {
 
  220             if (sortByComboBox.getSelectedIndex() == 0) {
 
  221                 tableModel.reSort(
true);
 
  223                 tableModel.reSort(
false);
 
  228     private javax.swing.JPanel controlPanel;
 
  229     private javax.swing.JScrollPane jScrollPane1;
 
  230     private javax.swing.JTable messageTable;
 
  231     private javax.swing.JComboBox<String> sortByComboBox;
 
  232     private javax.swing.JLabel sortByLabel;
 
  233     private javax.swing.JLabel totalMessagesNameLabel;
 
  234     private javax.swing.JLabel totalMessagesNameVal;
 
  235     private javax.swing.JLabel totalUniqueMessagesNameLabel;
 
  236     private javax.swing.JLabel totalUniqueMessagesNameVal;
 
  239     private void customizeComponents() {
 
  240         mainPanel.setOpaque(
true);
 
  241         jScrollPane1.setOpaque(
true);
 
  242         messageTable.setOpaque(
false);
 
  248         sortByComboBox.setModel(
new DefaultComboBoxModel<>(
new String[] {
 
  249             NbBundle.getMessage(this.getClass(), 
"IngestMessagePanel.sortByComboBox.model.time"), 
 
  250             NbBundle.getMessage(this.getClass(), 
"IngestMessagePanel.sortByComboBox.model.priority")}));
 
  252         jScrollPane1.setWheelScrollingEnabled(
true);
 
  254         messageTable.setAutoscrolls(
false);
 
  255         messageTable.setShowHorizontalLines(
false);
 
  256         messageTable.setShowVerticalLines(
false);
 
  258         messageTable.getParent().setBackground(messageTable.getBackground());
 
  260         renderer = 
new MessageTableRenderer();
 
  261         int numCols = messageTable.getColumnCount();
 
  264         for (
int i = 0; i < numCols; ++i) {
 
  265             messageTable.getColumnModel().getColumn(i).setCellRenderer(renderer);
 
  268         messageTable.setCellSelectionEnabled(
false);
 
  269         messageTable.setColumnSelectionAllowed(
false);
 
  270         messageTable.setRowSelectionAllowed(
true);
 
  271         messageTable.getSelectionModel().addListSelectionListener(
new MessageVisitedSelection());
 
  274         tableModel.addTableModelListener(
this);
 
  278     public void paint(Graphics g) {
 
  282         setTableSize(messageTable.getParent().getSize());
 
  286     public void setPreferredSize(Dimension dmnsn) {
 
  287         super.setPreferredSize(dmnsn);
 
  288         setTableSize(messageTable.getParent().getSize());
 
  291     void setTableSize(Dimension d) {
 
  292         double[] columnWidths = 
new double[]{0.20, 0.08, 0.08, 0.49, 0.15};
 
  293         int numCols = messageTable.getColumnCount();
 
  294         for (
int i = 0; i < numCols; ++i) {
 
  295             messageTable.getColumnModel().getColumn(i).setPreferredWidth((
int) (d.width * columnWidths[i]));
 
  299     public synchronized void addMessage(IngestMessage m) {
 
  300         tableModel.addMessage(m);
 
  304         final int newMsgUnreadUnique = tableModel.getNumberUnreadGroups();
 
  307             messagePcs.firePropertyChange(TOTAL_NUM_MESSAGES_CHANGED, 0, newMsgUnreadUnique);
 
  308         } 
catch (Exception e) {
 
  309             logger.log(Level.SEVERE, 
"IngestMessagePanel listener threw exception", e); 
 
  310             MessageNotifyUtil.Notify.show(NbBundle.getMessage(
this.getClass(), 
"IngestMessagePanel.moduleErr"),
 
  311                     NbBundle.getMessage(
this.getClass(),
 
  312                             "IngestMessagePanel.moduleErr.errListenUpdates.text"),
 
  313                     MessageNotifyUtil.MessageType.ERROR);
 
  317         this.totalMessagesNameVal.setText(Long.toString(totalMessages));
 
  318         final int totalMessagesUnique = tableModel.getNumberGroups();
 
  319         this.totalUniqueMessagesNameVal.setText(Integer.toString(totalMessagesUnique));
 
  322     public synchronized void clearMessages() {
 
  323         final int origMsgGroups = tableModel.getNumberUnreadGroups();
 
  325         tableModel.clearMessages();
 
  326         totalMessagesNameVal.setText(
"-");
 
  327         totalUniqueMessagesNameVal.setText(
"-");
 
  330             messagePcs.firePropertyChange(MESSAGES_BOX_CLEARED, origMsgGroups, 0);
 
  331         } 
catch (Exception e) {
 
  332             logger.log(Level.SEVERE, 
"IngestMessagePanel listener threw exception", e); 
 
  333             MessageNotifyUtil.Notify.show(NbBundle.getMessage(
this.getClass(), 
"IngestMessagePanel.moduleErr"),
 
  334                     NbBundle.getMessage(
this.getClass(),
 
  335                             "IngestMessagePanel.moduleErr.errListenUpdates.text"),
 
  336                     MessageNotifyUtil.MessageType.ERROR);
 
  340     public synchronized int getMessagesCount() {
 
  341         return tableModel.getNumberMessages();
 
  344     private synchronized void setVisited(
int rowNumber) {
 
  345         final int origMsgGroups = tableModel.getNumberUnreadGroups();
 
  346         tableModel.setVisited(rowNumber);
 
  347         lastRowSelected = rowNumber;
 
  350             messagePcs.firePropertyChange(TOOL_TIP_TEXT_KEY, origMsgGroups, tableModel.getNumberUnreadGroups());
 
  351         } 
catch (Exception e) {
 
  352             logger.log(Level.SEVERE, 
"IngestMessagePanel listener threw exception", e); 
 
  353             MessageNotifyUtil.Notify.show(NbBundle.getMessage(
this.getClass(), 
"IngestMessagePanel.moduleErr"),
 
  354                     NbBundle.getMessage(
this.getClass(),
 
  355                             "IngestMessagePanel.moduleErr.errListenUpdates.text"),
 
  356                     MessageNotifyUtil.MessageType.ERROR);
 
  361     public void tableChanged(TableModelEvent e) {
 
  362         int newMessages = tableModel.getNumberNewMessages();
 
  365             messagePcs.firePropertyChange(
new PropertyChangeEvent(tableModel, TOTAL_NUM_NEW_MESSAGES_CHANGED, -1, newMessages));
 
  366         } 
catch (Exception ee) {
 
  367             logger.log(Level.SEVERE, 
"IngestMessagePanel listener threw exception", ee); 
 
  368             MessageNotifyUtil.Notify.show(NbBundle.getMessage(
this.getClass(), 
"IngestMessagePanel.moduleErr"),
 
  369                     NbBundle.getMessage(
this.getClass(),
 
  370                             "IngestMessagePanel.moduleErr.errListenUpdates.text"),
 
  371                     MessageNotifyUtil.MessageType.ERROR);
 
  377         private final String[] columnNames = 
new String[]{
 
  378             NbBundle.getMessage(this.getClass(), 
"IngestMessagePanel.MsgTableMod.colNames.module"),
 
  379             NbBundle.getMessage(this.getClass(), 
"IngestMessagePanel.MsgTableMod.colNames.num"),
 
  380             NbBundle.getMessage(this.getClass(), 
"IngestMessagePanel.MsgTableMod.colNames.new"),
 
  381             NbBundle.getMessage(this.getClass(), 
"IngestMessagePanel.MsgTableMod.colNames.subject"),
 
  382             NbBundle.getMessage(this.getClass(), 
"IngestMessagePanel.MsgTableMod.colNames.timestamp")};
 
  383         private final List<TableEntry> messageData = 
new ArrayList<>();
 
  385         private final Map<String, Map<String, List<IngestMessageGroup>>> groupings = 
new HashMap<>();
 
  386         private boolean chronoSort = 
true; 
 
  387         private static final int MESSAGE_GROUP_THRESH = 3; 
 
  392             return columnNames.length;
 
  397             return getNumberGroups();
 
  401             for (TableEntry entry : messageData) {
 
  402                 entry.hasBeenSeen(
true);
 
  404             fireTableChanged(
new TableModelEvent(
this));
 
  409             for (TableEntry entry : messageData) {
 
  410                 if (!entry.hasBeenSeen()) {
 
  418             return messageData.size();
 
  423             for (TableEntry e : messageData) {
 
  424                 total += e.messageGroup.getCount();
 
  431             for (TableEntry e : messageData) {
 
  432                 if (!e.hasBeenVisited) {
 
  433                     total += e.messageGroup.getCount();
 
  441             for (TableEntry e : messageData) {
 
  442                 if (!e.hasBeenVisited) {
 
  451             return columnNames[column];
 
  455         public synchronized Object 
getValueAt(
int rowIndex, 
int columnIndex) {
 
  458             int numMessages = messageData.size();
 
  459             if (rowIndex > messageData.size() - 1
 
  460                     || columnIndex > columnNames.length - 1) {
 
  463                 logger.log(Level.WARNING, 
"Requested inbox message at" + rowIndex, 
", only have " + numMessages); 
 
  466             TableEntry entry = messageData.get(rowIndex);
 
  468             switch (columnIndex) {
 
  470                     ret = entry.messageGroup.getSource();
 
  473                     ret = entry.messageGroup.getCount();
 
  476                     ret = !entry.hasBeenSeen();
 
  479                     ret = entry.messageGroup.getSubject();
 
  482                     ret = entry.messageGroup.getDatePosted();
 
  485                     logger.log(Level.SEVERE, 
"Invalid table column index: {0}", columnIndex); 
 
  498             return getValueAt(0, c).getClass();
 
  504             for (TableEntry e : messageData) {
 
  505                 if (e.messageGroup.getUniqueKey().equals(uniqueKey)) {
 
  518             IngestMessageGroup messageGroup = null;
 
  521                 if (!groupings.containsKey(moduleName)) {
 
  522                     groupings.put(moduleName, 
new HashMap<>());
 
  524                 final Map<String, List<IngestMessageGroup>> groups = groupings.get(moduleName);
 
  527                 List<IngestMessageGroup> uniqGroups = groups.get(uniqueness);
 
  528                 if (uniqGroups == null) {
 
  530                     uniqGroups = 
new ArrayList<>();
 
  531                     messageGroup = 
new IngestMessageGroup(m);
 
  532                     uniqGroups.add(messageGroup);
 
  533                     groups.put(uniqueness, uniqGroups);
 
  535                     final int uniqueGroupsCount = uniqGroups.size();
 
  536                     if (uniqueGroupsCount > MESSAGE_GROUP_THRESH) {
 
  538                         messageGroup = uniqGroups.get(0);
 
  539                         for (
int i = 1; i < uniqueGroupsCount; ++i) {
 
  540                             messageGroup.addAll(uniqGroups.get(i));
 
  548                         uniqGroups.add(messageGroup);
 
  552                         while ((toRemove = getTableEntryIndex(uniqueness)) != -1) {
 
  553                             messageData.remove(toRemove);
 
  555                             this.fireTableRowsDeleted(toRemove, toRemove);
 
  558                     } 
else if (uniqueGroupsCount == 1) {
 
  559                         IngestMessageGroup first = uniqGroups.get(0);
 
  561                         if (first.getCount() > 1) {
 
  564                             messageGroup = first;
 
  568                             while ((toRemove = getTableEntryIndex(uniqueness)) != -1) {
 
  569                                 messageData.remove(toRemove);
 
  571                                 this.fireTableRowsDeleted(toRemove, toRemove);
 
  577                             messageGroup = 
new IngestMessageGroup(m);
 
  578                             uniqGroups.add(messageGroup);
 
  584                         messageGroup = 
new IngestMessageGroup(m);
 
  585                         uniqGroups.add(messageGroup);
 
  592                 messageGroup = 
new IngestMessageGroup(m);
 
  596             messageData.add(
new TableEntry(messageGroup));
 
  597             int newRowIndex = messageData.size() - 1;
 
  598             fireTableRowsInserted(newRowIndex, newRowIndex);
 
  601             if (chronoSort == 
false) {
 
  602                 Collections.sort(messageData);
 
  603                 fireTableDataChanged();
 
  610             fireTableDataChanged();
 
  614             messageData.get(rowNumber).hasBeenVisited(
true);
 
  616             fireTableCellUpdated(rowNumber, 2);
 
  621             for (TableEntry e : messageData) {
 
  622                 if (!e.hasBeenVisited) {
 
  623                     e.hasBeenVisited(
true);
 
  624                     fireTableCellUpdated(row, 2);
 
  631             if (rowNumber < messageData.size()) {
 
  632                 return messageData.get(rowNumber).hasBeenVisited();
 
  639             if (rowNumber < messageData.size()) {
 
  640                 return messageData.get(rowNumber).messageGroup.getMessageType();
 
  647             if (rowNumber < messageData.size()) {
 
  648                 return messageData.get(rowNumber).messageGroup;
 
  654         public synchronized void reSort(
boolean chronoLogical) {
 
  655             if (chronoSort == chronoLogical) {
 
  659             chronoSort = chronoLogical;
 
  660             Collections.sort(messageData);
 
  661             fireTableDataChanged();
 
  664         class TableEntry 
implements Comparable<TableEntry> {
 
  666             IngestMessageGroup messageGroup;
 
  667             boolean hasBeenVisited = 
false;
 
  668             boolean hasBeenSeen = 
false;
 
  670             public boolean hasBeenVisited() {
 
  671                 return hasBeenVisited;
 
  674             public void hasBeenVisited(
boolean visited) {
 
  675                 hasBeenVisited = visited;
 
  678             public boolean hasBeenSeen() {
 
  682             public void hasBeenSeen(
boolean seen) {
 
  686             TableEntry(IngestMessageGroup messageGroup) {
 
  687                 this.messageGroup = messageGroup;
 
  691             public int compareTo(TableEntry o) {
 
  692                 if (chronoSort == 
true) {
 
  693                     return this.messageGroup.getDatePosted().compareTo(o.messageGroup.getDatePosted());
 
  695                     return messageGroup.getCount() - o.messageGroup.getCount();
 
  703     static class IngestMessageGroup {
 
  705         static final Color VERY_HIGH_PRI_COLOR = 
new Color(164, 164, 202); 
 
  706         static final Color HIGH_PRI_COLOR = 
new Color(180, 180, 211);
 
  707         static final Color MED_PRI_COLOR = 
new Color(199, 199, 222);
 
  708         static final Color LOW_PRI_COLOR = 
new Color(221, 221, 235);
 
  709         private final List<IngestMessage> messages;
 
  711         IngestMessageGroup(IngestMessage message) {
 
  712             messages = 
new ArrayList<>();
 
  713             messages.add(message);
 
  716         private List<IngestMessage> getMessages() {
 
  720         synchronized void add(IngestMessage message) {
 
  721             messages.add(message);
 
  725         synchronized void addAll(IngestMessageGroup group) {
 
  726             for (IngestMessage m : group.getMessages()) {
 
  731         synchronized int getCount() {
 
  732             return messages.size();
 
  735         synchronized String getDetails() {
 
  736             StringBuilder b = 
new StringBuilder(
"");
 
  737             for (IngestMessage m : messages) {
 
  738                 String details = m.getDetails();
 
  739                 if (details == null || details.equals(
"")) {
 
  755         synchronized Color getColor() {
 
  756             int count = messages.size();
 
  758                 return VERY_HIGH_PRI_COLOR;
 
  759             } 
else if (count < 5) {
 
  760                 return HIGH_PRI_COLOR;
 
  761             } 
else if (count < 15) {
 
  762                 return MED_PRI_COLOR;
 
  764                 return LOW_PRI_COLOR;
 
  773         synchronized Date getDatePosted() {
 
  774             return messages.get(messages.size() - 1).getDatePosted();
 
  782         synchronized String getSubject() {
 
  783             return messages.get(0).getSubject();
 
  789         synchronized String getUniqueKey() {
 
  790             return messages.get(0).getUniqueKey();
 
  796         synchronized String getSource() {
 
  797             return messages.get(0).getSource();
 
  803         synchronized BlackboardArtifact getData() {
 
  804             return messages.get(0).getData();
 
  810         synchronized IngestMessage.MessageType getMessageType() {
 
  811             return messages.get(0).getMessageType();
 
  828             this.rowSelected = rowSelected;
 
  833             if (value instanceof Boolean) {
 
  834                 return booleanRenderer.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
 
  835             } 
else if (value instanceof Date) {
 
  836                 return dateRenderer.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
 
  838                 return defaultRenderer.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
 
  848         private final String bulletChar = 
new String(Character.toChars(0x2022));
 
  853             super.setForeground(table.getSelectionForeground());
 
  854             super.setBackground(table.getSelectionBackground());
 
  857             if (value instanceof Boolean) {
 
  858                 boolVal = ((Boolean) value);
 
  860                 throw new RuntimeException(NbBundle.getMessage(
this.getClass(),
 
  861                         "IngestMessagePanel.BooleanRenderer.exception.nonBoolVal.msg"));
 
  864             String aValue = boolVal ? bulletChar : 
"";
 
  866             JLabel cell = (JLabel) super.getTableCellRendererComponent(table, aValue, isSelected, hasFocus, row, column);
 
  869             cell.setHorizontalAlignment(SwingConstants.CENTER);
 
  872             cell.setFont(cell.getFont().deriveFont(Font.PLAIN, 16));
 
  874             final IngestMessageGroup messageGroup = tableModel.getMessageGroup(row);
 
  875             if (messageGroup != null) {
 
  878                     cell.setBackground(ERROR_COLOR);
 
  880                     cell.setBackground(Color.orange);
 
  883                     cell.setBackground(messageGroup.getColor());
 
  898                 JTable table, Object value,
 
  899                 boolean isSelected, 
boolean hasFocus,
 
  900                 int row, 
int column) {
 
  902             Component cell = super.getTableCellRendererComponent(
 
  903                     table, value, 
false, 
false, row, column);
 
  905             Font visitedFont = cell.getFont().deriveFont(Font.PLAIN, 12);
 
  906             Font notVisitedFont = cell.getFont().deriveFont(Font.BOLD, 12);
 
  909                 String subject = (String) value;
 
  910                 setToolTipText(subject);
 
  911                 if (tableModel.isVisited(row)) {
 
  912                     cell.setFont(visitedFont);
 
  914                     cell.setFont(notVisitedFont);
 
  918             final IngestMessageGroup messageGroup = tableModel.getMessageGroup(row);
 
  919             if (messageGroup != null) {
 
  922                     cell.setBackground(ERROR_COLOR);
 
  924                     cell.setBackground(Color.orange);
 
  927                     cell.setBackground(messageGroup.getColor());
 
  939             super.setForeground(table.getSelectionForeground());
 
  940             super.setBackground(table.getSelectionBackground());
 
  942             Object aValue = value;
 
  943             if (value instanceof Date) {
 
  944                 Date date = (Date) value;
 
  945                 DateFormat df = 
new SimpleDateFormat(
"HH:mm:ss");
 
  946                 aValue = df.format(date);
 
  948                 throw new RuntimeException(NbBundle.getMessage(
this.getClass(),
 
  949                         "IngestMessagePanel.DateRenderer.exception.nonDateVal.text"));
 
  952             Component cell = super.getTableCellRendererComponent(table, aValue, isSelected, hasFocus, row, column);
 
  954             final IngestMessageGroup messageGroup = tableModel.getMessageGroup(row);
 
  955             if (messageGroup != null) {
 
  958                     cell.setBackground(ERROR_COLOR);
 
  960                     cell.setBackground(Color.orange);
 
  963                     cell.setBackground(messageGroup.getColor());
 
  978             ListSelectionModel selModel = (ListSelectionModel) e.getSource();
 
  979             if (selModel.isSelectionEmpty() || selModel.getValueIsAdjusting()) {
 
  983             final int minIndex = selModel.getMinSelectionIndex();
 
  984             final int maxIndex = selModel.getMaxSelectionIndex();
 
  986             for (
int i = minIndex; i <= maxIndex; i++) {
 
  987                 if (selModel.isSelectedIndex(i)) {
 
  992             selModel.clearSelection();
 
  993             if (selected != -1) {
 
  994                 setVisited(selected);
 
  995                 messageTable.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
 
  997                 IngestMessageGroup m = getMessageGroup(selected);
 
  999                     String details = m.getDetails();
 
 1000                     if (details != null && !details.equals(
"")) {
 
 1001                         mainPanel.showDetails(selected);
 
 1004                 messageTable.setCursor(null);
 
synchronized int getRowCount()
synchronized int getTableEntryIndex(String uniqueKey)
synchronized IngestMessageGroup getMessageGroup(int rowNumber)
Class<?> getColumnClass(int c)
boolean isCellEditable(int rowIndex, int columnIndex)
synchronized int getNumberNewMessages()
MessageType getMessageType()
synchronized void markAllSeen()
String getColumnName(int column)
synchronized int getNumberUnreadMessages()
synchronized int getNumberUnreadGroups()
Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
void valueChanged(ListSelectionEvent e)
Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
synchronized int getNumberGroups()
Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
synchronized void setVisitedAll()
void setRowSelected(int rowSelected)
synchronized void addMessage(IngestMessage m)
Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
synchronized void clearMessages()
synchronized int getNumberMessages()
synchronized static Logger getLogger(String name)
synchronized boolean isVisited(int rowNumber)
synchronized MessageType getMessageType(int rowNumber)
synchronized Object getValueAt(int rowIndex, int columnIndex)
synchronized void setVisited(int rowNumber)
synchronized void reSort(boolean chronoLogical)