Autopsy  4.19.0
Graphical digital forensics platform for The Sleuth Kit and other tools.
OtherOccurrencesPanel.java
Go to the documentation of this file.
1 /*
2  * Central Repository
3  *
4  * Copyright 2017-2021 Basis Technology Corp.
5  * Contact: carrier <at> sleuthkit <dot> org
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19 package org.sleuthkit.autopsy.centralrepository.contentviewer;
20 
24 import java.awt.Cursor;
25 import java.awt.event.ActionEvent;
26 import java.awt.event.ActionListener;
27 import java.awt.event.ComponentAdapter;
28 import java.awt.event.ComponentEvent;
29 import java.io.File;
30 import java.util.ArrayList;
31 import java.util.Calendar;
32 import java.util.Collection;
33 import java.util.Collections;
34 import java.util.HashMap;
35 import java.util.List;
36 import java.util.Map;
37 import java.util.concurrent.ExecutionException;
38 import java.util.concurrent.ExecutorService;
39 import java.util.concurrent.Executors;
40 import java.util.concurrent.FutureTask;
41 import java.util.logging.Level;
42 import javax.swing.JFileChooser;
43 import javax.swing.JMenuItem;
44 import javax.swing.JOptionPane;
45 import static javax.swing.JOptionPane.DEFAULT_OPTION;
46 import static javax.swing.JOptionPane.ERROR_MESSAGE;
47 import static javax.swing.JOptionPane.PLAIN_MESSAGE;
48 import javax.swing.SwingWorker;
49 import javax.swing.filechooser.FileNameExtensionFilter;
50 import javax.swing.table.TableModel;
51 import javax.swing.table.TableRowSorter;
52 import org.openide.util.NbBundle;
62 import org.sleuthkit.datamodel.AbstractFile;
63 
67 @NbBundle.Messages({
68  "OtherOccurrencesPanel.table.noArtifacts=Item has no attributes with which to search.",
69  "OtherOccurrencesPanel.table.noResultsFound=No results found.",
70  "OtherOccurrencesPanel_table_loadingResults=Loading results"
71 })
72 public final class OtherOccurrencesPanel extends javax.swing.JPanel {
73 
74  private static final CorrelationCaseWrapper NO_ARTIFACTS_CASE = new CorrelationCaseWrapper(Bundle.OtherOccurrencesPanel_table_noArtifacts());
75  private static final CorrelationCaseWrapper NO_RESULTS_CASE = new CorrelationCaseWrapper(Bundle.OtherOccurrencesPanel_table_noResultsFound());
76  private static final Logger logger = Logger.getLogger(OtherOccurrencesPanel.class.getName());
77  private static final long serialVersionUID = 1L;
80  private final OtherOccurrencesDataSourcesTableModel dataSourcesTableModel;
81  private OccurrencePanel occurrencePanel;
82  private final Collection<CorrelationAttributeInstance> correlationAttributes;
83  private String dataSourceName = ""; //the data source of the file which the content viewer is being populated for
84  private String deviceId = ""; //the device id of the data source for the file which the content viewer is being populated for
85  private AbstractFile file = null;
86 
87  private SwingWorker<?, ?> worker;
88 
89  // Initializing the JFileChooser in a thread to prevent a block on the EDT
90  // see https://stackoverflow.com/questions/49792375/jfilechooser-is-very-slow-when-using-windows-look-and-feel
91  private final FutureTask<JFileChooser> futureFileChooser = new FutureTask<>(JFileChooser::new);
92  private JFileChooser CSVFileChooser;
93 
98  this.filesTableModel = new OtherOccurrencesFilesTableModel();
99  this.casesTableModel = new OtherOccurrencesCasesTableModel();
100  this.dataSourcesTableModel = new OtherOccurrencesDataSourcesTableModel();
101  this.correlationAttributes = new ArrayList<>();
102  initComponents();
103  customizeComponents();
104 
105  ExecutorService executor = Executors.newSingleThreadExecutor();
106  executor.execute(futureFileChooser);
107  }
108 
109  private void customizeComponents() {
110  ActionListener actList = (ActionEvent e) -> {
111  JMenuItem jmi = (JMenuItem) e.getSource();
112  if (jmi.equals(showCaseDetailsMenuItem)) {
113  showCaseDetails(filesTable.getSelectedRow());
114  } else if (jmi.equals(exportToCSVMenuItem)) {
115  try {
116  saveToCSV();
117  } catch (NoCurrentCaseException ex) {
118  logger.log(Level.SEVERE, "Exception while getting open case.", ex); // NON-NLS
119  }
120  } else if (jmi.equals(showCommonalityMenuItem)) {
121  showCommonalityDetails();
122  }
123  };
124 
125  exportToCSVMenuItem.addActionListener(actList);
126  showCaseDetailsMenuItem.addActionListener(actList);
127  showCommonalityMenuItem.addActionListener(actList);
128  filesTable.setComponentPopupMenu(rightClickPopupMenu);
129  // Configure column sorting.
130  TableRowSorter<TableModel> sorter = new TableRowSorter<>(filesTable.getModel());
131  filesTable.setRowSorter(sorter);
132 
133  //sort tables alphabetically initially
134  casesTable.getRowSorter().toggleSortOrder(0);
135  dataSourcesTable.getRowSorter().toggleSortOrder(0);
136  filesTable.getRowSorter().toggleSortOrder(0);
137  reset();
138  casesTable.getSelectionModel().addListSelectionListener((e) -> {
139  if (Case.isCaseOpen()) {
140  updateOnCaseSelection();
141  }
142  });
143  dataSourcesTable.getSelectionModel().addListSelectionListener((e) -> {
144  if (Case.isCaseOpen()) {
145  updateOnDataSourceSelection();
146  }
147  });
148 
149  //alows resizing of the 4th section
150  filesTable.getSelectionModel().addListSelectionListener((e) -> {
151  if (Case.isCaseOpen()) {
152  occurrencePanel = new OccurrencePanel();
153  updateOnFileSelection();
154  }
155  });
156  detailsPanelScrollPane.addComponentListener(new ComponentAdapter() {
157  @Override
158  public void componentResized(ComponentEvent componentEvent) {
159  //when its resized make sure the width of the panel resizes to match the scroll pane width to avoid a horizontal scroll bar
160  occurrencePanel.setPreferredSize(new java.awt.Dimension(detailsPanelScrollPane.getPreferredSize().width, occurrencePanel.getPreferredSize().height));
161  detailsPanelScrollPane.setViewportView(occurrencePanel);
162  }
163  });
164 
165  }
166 
167  @NbBundle.Messages({"OtherOccurrencesPanel.correlatedArtifacts.isEmpty=There are no files or artifacts to correlate.",
168  "# {0} - commonality percentage",
169  "# {1} - correlation type",
170  "# {2} - correlation value",
171  "OtherOccurrencesPanel.correlatedArtifacts.byType={0}% of data sources have {2} (type: {1})\n",
172  "OtherOccurrencesPanel.correlatedArtifacts.title=Attribute Frequency",
173  "OtherOccurrencesPanel.correlatedArtifacts.failed=Failed to get frequency details."})
178  private void showCommonalityDetails() {
179  if (correlationAttributes.isEmpty()) {
180  JOptionPane.showConfirmDialog(OtherOccurrencesPanel.this,
181  Bundle.OtherOccurrencesPanel_correlatedArtifacts_isEmpty(),
182  Bundle.OtherOccurrencesPanel_correlatedArtifacts_title(),
183  DEFAULT_OPTION, PLAIN_MESSAGE);
184  } else {
185  StringBuilder msg = new StringBuilder(correlationAttributes.size());
186  int percentage;
187  this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
188  try {
189  // Leaving these calls on the EDT but adding wait cursor
191  for (CorrelationAttributeInstance eamArtifact : correlationAttributes) {
192  try {
193  percentage = dbManager.getFrequencyPercentage(eamArtifact);
194  msg.append(Bundle.OtherOccurrencesPanel_correlatedArtifacts_byType(percentage,
195  eamArtifact.getCorrelationType().getDisplayName(),
196  eamArtifact.getCorrelationValue()));
198  logger.log(Level.WARNING, String.format("Error getting commonality details for artifact with ID: %s.", eamArtifact.getID()), ex);
199  }
200  }
201  this.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
202  JOptionPane.showConfirmDialog(OtherOccurrencesPanel.this,
203  msg.toString(),
204  Bundle.OtherOccurrencesPanel_correlatedArtifacts_title(),
205  DEFAULT_OPTION, PLAIN_MESSAGE);
206  } catch (CentralRepoException ex) {
207  this.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
208  logger.log(Level.SEVERE, "Error getting commonality details.", ex);
209  JOptionPane.showConfirmDialog(OtherOccurrencesPanel.this,
210  Bundle.OtherOccurrencesPanel_correlatedArtifacts_failed(),
211  Bundle.OtherOccurrencesPanel_correlatedArtifacts_title(),
212  DEFAULT_OPTION, ERROR_MESSAGE);
213  }
214  }
215  }
216 
217  @NbBundle.Messages({"OtherOccurrencesPanel.caseDetailsDialog.notSelected=No Row Selected",
218  "OtherOccurrencesPanel.caseDetailsDialog.noDetails=No details for this case.",
219  "OtherOccurrencesPanel.caseDetailsDialog.noDetailsReference=No case details for Global reference properties.",
220  "OtherOccurrencesPanel.caseDetailsDialog.noCaseNameError=Error",
221  "OtherOccurrencesPanel.noOpenCase.errMsg=No open case available."})
222  private void showCaseDetails(int selectedRowViewIdx) {
223  String caseDisplayName = Bundle.OtherOccurrencesPanel_caseDetailsDialog_noCaseNameError();
224  String details = Bundle.OtherOccurrencesPanel_caseDetailsDialog_noDetails();
225  try {
226  if (-1 != selectedRowViewIdx && filesTableModel.getRowCount() > 0) {
228  int selectedRowModelIdx = filesTable.convertRowIndexToModel(selectedRowViewIdx);
229  List<NodeData> rowList = filesTableModel.getListOfNodesForFile(selectedRowModelIdx);
230  if (!rowList.isEmpty()) {
231  CorrelationCase eamCasePartial = rowList.get(0).getCorrelationAttributeInstance().getCorrelationCase();
232  caseDisplayName = eamCasePartial.getDisplayName();
233  // query case details
234  CorrelationCase eamCase = dbManager.getCaseByUUID(eamCasePartial.getCaseUUID());
235  if (eamCase != null) {
236  details = eamCase.getCaseDetailsOptionsPaneDialog();
237  } else {
238  details = Bundle.OtherOccurrencesPanel_caseDetailsDialog_noDetails();
239  }
240  } else {
241  details = Bundle.OtherOccurrencesPanel_caseDetailsDialog_noDetailsReference();
242  }
243  }
244  } catch (CentralRepoException ex) {
245  logger.log(Level.SEVERE, "Error loading case details", ex);
246  } finally {
247  JOptionPane.showConfirmDialog(OtherOccurrencesPanel.this,
248  details,
249  caseDisplayName,
250  DEFAULT_OPTION, PLAIN_MESSAGE);
251  }
252  }
253 
254  private void saveToCSV() throws NoCurrentCaseException {
255  if (casesTableModel.getRowCount() > 0) {
256 
257  if (CSVFileChooser == null) {
258  try {
259  CSVFileChooser = futureFileChooser.get();
260  } catch (InterruptedException | ExecutionException ex) {
261  // If something happened with the thread try and
262  // initalized the chooser now
263  logger.log(Level.WARNING, "A failure occurred in the JFileChooser background thread");
264  CSVFileChooser = new JFileChooser();
265  }
266  }
267 
268  Calendar now = Calendar.getInstance();
269  String fileName = String.format("%1$tY%1$tm%1$te%1$tI%1$tM%1$tS_other_data_sources.csv", now);
270  CSVFileChooser.setCurrentDirectory(new File(Case.getCurrentCaseThrows().getExportDirectory()));
271  CSVFileChooser.setSelectedFile(new File(fileName));
272  CSVFileChooser.setFileFilter(new FileNameExtensionFilter("csv file", "csv"));
273 
274  int returnVal = CSVFileChooser.showSaveDialog(filesTable);
275  if (returnVal == JFileChooser.APPROVE_OPTION) {
276 
277  File selectedFile = CSVFileChooser.getSelectedFile();
278  if (!selectedFile.getName().endsWith(".csv")) { // NON-NLS
279  selectedFile = new File(selectedFile.toString() + ".csv"); // NON-NLS
280  }
281  CSVWorker csvWorker = new CSVWorker(selectedFile, file, dataSourceName, deviceId, Collections.unmodifiableCollection(correlationAttributes));
282  csvWorker.execute();
283  }
284  }
285  }
286 
287  @NbBundle.Messages({"OtherOccurrencesPanel_earliestCaseNotAvailable=Not Available."})
291  public void reset() {
292  // start with empty table
293  casesTableModel.clearTable();
294  dataSourcesTableModel.clearTable();
295  filesTableModel.clearTable();
296  correlationAttributes.clear();
297  earliestCaseDate.setText(Bundle.OtherOccurrencesPanel_earliestCaseNotAvailable());
298  foundInLabel.setText("");
299  //calling getPreferredSize has a side effect of ensuring it has a preferred size which reflects the contents which are visible
300  occurrencePanel = new OccurrencePanel();
301  occurrencePanel.getPreferredSize();
302  detailsPanelScrollPane.setViewportView(occurrencePanel);
303  }
304 
316  if (worker != null) {
317  worker.cancel(true);
318  worker = null;
319  }
320 
321  casesTableModel.addCorrelationCase(NO_ARTIFACTS_CASE);
322 
323  worker = new OtherOccurrenceOneTypeWorker(aType, value, file, deviceId, dataSourceName) {
324  @Override
325  public void done() {
326  try {
327  if (isCancelled()) {
328  return;
329  }
330 
331  casesTableModel.clearTable();
332 
333  OtherOccurrenceOneTypeWorker.OneTypeData data = get();
334  correlationAttributes.addAll(data.getCorrelationAttributesToAdd());
335  for (CorrelationCase corCase : data.getCaseNames().values()) {
336  casesTableModel.addCorrelationCase(new CorrelationCaseWrapper(corCase));
337  }
338  int caseCount = casesTableModel.getRowCount();
339  if (correlationAttributes.isEmpty()) {
340  casesTableModel.addCorrelationCase(NO_ARTIFACTS_CASE);
341  } else if (caseCount == 0) {
342  casesTableModel.addCorrelationCase(NO_RESULTS_CASE);
343  } else {
344  String earliestDate = data.getEarliestCaseDate();
345  earliestCaseDate.setText(earliestDate.isEmpty() ? Bundle.OtherOccurrencesPanel_earliestCaseNotAvailable() : earliestDate);
346  foundInLabel.setText(String.format(Bundle.OtherOccurrencesPanel_foundIn_text(), data.getTotalCount(), caseCount, data.getDataSourceCount()));
347  if (caseCount > 0) {
348  casesTable.setRowSelectionInterval(0, 0);
349  }
350  }
351 
352  } catch (InterruptedException | ExecutionException ex) {
353  logger.log(Level.SEVERE, "Failed to update OtherOccurrence panel", ex);
354  }
355  }
356  };
357 
358  worker.execute();
359  }
360 
364  void showPanelLoadingMessage() {
365  casesTableModel.addCorrelationCase(NO_ARTIFACTS_CASE);
366  }
367 
374  @NbBundle.Messages({
375  "OtherOccurrencesPanel.foundIn.text=Found %d instances in %d cases and %d data sources."
376  })
377  void populateTable(OtherOccurrencesData data) {
378  this.file = data.getFile();
379  this.dataSourceName = data.getDataSourceName();
380  this.deviceId = data.getDeviceId();
381 
382  casesTableModel.clearTable();
383 
384  correlationAttributes.addAll(data.getCorrelationAttributes());
385 
386  for (CorrelationCase corCase : data.getCaseMap().values()) {
387  casesTableModel.addCorrelationCase(new CorrelationCaseWrapper(corCase));
388  }
389  int caseCount = casesTableModel.getRowCount();
390  if (correlationAttributes.isEmpty()) {
391  casesTableModel.addCorrelationCase(NO_ARTIFACTS_CASE);
392  } else if (caseCount == 0) {
393  casesTableModel.addCorrelationCase(NO_RESULTS_CASE);
394  } else {
395  String earliestDate = data.getEarliestCaseDate();
396  earliestCaseDate.setText(earliestDate.isEmpty() ? Bundle.OtherOccurrencesPanel_earliestCaseNotAvailable() : earliestDate);
397  foundInLabel.setText(String.format(Bundle.OtherOccurrencesPanel_foundIn_text(), data.getInstanceDataCount(), caseCount, data.getDataSourceCount()));
398  if (caseCount > 0) {
399  casesTable.setRowSelectionInterval(0, 0);
400  }
401  }
402  }
403 
408  private void updateOnCaseSelection() {
409  if (worker != null) {
410  worker.cancel(true);
411  worker = null;
412  }
413 
414  final int[] selectedCaseIndexes = casesTable.getSelectedRows();
415  dataSourcesTableModel.clearTable();
416  filesTableModel.clearTable();
417 
418  if (selectedCaseIndexes.length == 0) {
419  //special case when no cases are selected
420  occurrencePanel = new OccurrencePanel();
421  occurrencePanel.getPreferredSize();
422  detailsPanelScrollPane.setViewportView(occurrencePanel);
423 
424  return;
425  }
426 
427  setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
428 
429  worker = new SelectionWorker(correlationAttributes, file, deviceId, dataSourceName) {
430  @Override
431  public void done() {
432  if (isCancelled()) {
433  return;
434  }
435 
436  try {
437  Map<UniquePathKey, NodeData> correlatedNodeDataMap = get();
438 
439  String currentCaseName;
440  try {
441  currentCaseName = Case.getCurrentCaseThrows().getName();
442  } catch (NoCurrentCaseException ex) {
443  currentCaseName = null;
444  logger.log(Level.WARNING, "Unable to get current case for other occurrences content viewer", ex);
445  }
446  if (casesTableModel.getRowCount() > 0) {
447  for (NodeData nodeData : correlatedNodeDataMap.values()) {
448  for (int selectedRow : selectedCaseIndexes) {
449  try {
450  if (nodeData.isCentralRepoNode()) {
451  if (casesTableModel.getCorrelationCase(casesTable.convertRowIndexToModel(selectedRow)) != null
452  && casesTableModel.getCorrelationCase(casesTable.convertRowIndexToModel(selectedRow)).getCaseUUID().equals(nodeData.getCorrelationAttributeInstance().getCorrelationCase().getCaseUUID())) {
453  dataSourcesTableModel.addNodeData(nodeData);
454  }
455  } else if (currentCaseName != null && (casesTableModel.getCorrelationCase(casesTable.convertRowIndexToModel(selectedRow)).getCaseUUID().equals(currentCaseName))) {
456  dataSourcesTableModel.addNodeData(nodeData);
457  }
458  } catch (CentralRepoException ex) {
459  logger.log(Level.WARNING, "Unable to get correlation attribute instance from OtherOccurrenceNodeInstanceData for case " + nodeData.getCaseName(), ex);
460  }
461  }
462  }
463  }
464  if (dataSourcesTableModel.getRowCount() > 0) {
465  dataSourcesTable.setRowSelectionInterval(0, 0);
466  }
467 
468  setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
469 
470  } catch (InterruptedException | ExecutionException ex) {
471  logger.log(Level.SEVERE, "Failed to update OtherOccurrencesPanel on data source selection", ex);
472  }
473  }
474  };
475 
476  worker.execute();
477  }
478 
484  if (worker != null) {
485  worker.cancel(true);
486  worker = null;
487  }
488 
489  setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
490 
491  final int[] selectedDataSources = dataSourcesTable.getSelectedRows();
492  filesTableModel.clearTable();
493 
494  worker = new SelectionWorker(correlationAttributes, file, deviceId, dataSourceName) {
495  @Override
496  public void done() {
497  if (isCancelled()) {
498  return;
499  }
500 
501  try {
502  Map<UniquePathKey, NodeData> correlatedNodeDataMap = get();
503  if (dataSourcesTableModel.getRowCount() > 0) {
504  for (NodeData nodeData : correlatedNodeDataMap.values()) {
505  for (int selectedDataSourceRow : selectedDataSources) {
506  int rowModelIndex = dataSourcesTable.convertRowIndexToModel(selectedDataSourceRow);
507  try {
508  if (nodeData.isCentralRepoNode()) {
509  if (dataSourcesTableModel.getCaseUUIDForRow(rowModelIndex).equals(nodeData.getCorrelationAttributeInstance().getCorrelationCase().getCaseUUID())
510  && dataSourcesTableModel.getDeviceIdForRow(rowModelIndex).equals(nodeData.getDeviceID())) {
511  filesTableModel.addNodeData(nodeData);
512  }
513  } else {
514  if (dataSourcesTableModel.getDeviceIdForRow(dataSourcesTable.convertRowIndexToModel(selectedDataSourceRow)).equals(nodeData.getDeviceID())) {
515  filesTableModel.addNodeData(nodeData);
516  }
517  }
518  } catch (CentralRepoException ex) {
519  logger.log(Level.WARNING, "Unable to get correlation attribute instance from OtherOccurrenceNodeInstanceData for case " + nodeData.getCaseName(), ex);
520  }
521  }
522  }
523  }
524 
525  if (filesTableModel.getRowCount() > 0) {
526  filesTable.setRowSelectionInterval(0, 0);
527  }
528  } catch (InterruptedException | ExecutionException ex) {
529  logger.log(Level.SEVERE, "Failed to update OtherOccurrencesPanel on case selection", ex);
530  } finally {
531  setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
532  }
533  }
534  };
535 
536  worker.execute();
537  }
538 
543  private void updateOnFileSelection() {
544  setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
545  try {
546  if (filesTableModel.getRowCount() > 0 && filesTable.getSelectedRowCount() == 1) {
547  //if there is one file selected update the deatils to show the data for that file
548  occurrencePanel = new OccurrencePanel(filesTableModel.getListOfNodesForFile(filesTable.convertRowIndexToModel(filesTable.getSelectedRow())));
549  } else if (dataSourcesTableModel.getRowCount() > 0 && dataSourcesTable.getSelectedRowCount() == 1) {
550  //if no files were selected and only one data source is selected update the information to reflect the data source
551  String caseName = dataSourcesTableModel.getCaseNameForRow(dataSourcesTable.convertRowIndexToModel(dataSourcesTable.getSelectedRow()));
552  String dsName = dataSourcesTableModel.getValueAt(dataSourcesTable.convertRowIndexToModel(dataSourcesTable.getSelectedRow()), 0).toString();
553  String caseCreatedDate = "";
554  if (casesTableModel.getRowCount() > 0) {
555  for (int row : casesTable.getSelectedRows()) {
556  if (casesTableModel.getValueAt(casesTable.convertRowIndexToModel(row), 0).toString().equals(caseName)) {
557  caseCreatedDate = getCaseCreatedDate(row);
558  break;
559  }
560  }
561  }
562  occurrencePanel = new OccurrencePanel(caseName, caseCreatedDate, dsName);
563  } else if (casesTable.getSelectedRowCount() == 1) {
564  //if no files were selected and a number of data source other than 1 are selected
565  //update the information to reflect the case
566  String createdDate;
567  String caseName = "";
568  if (casesTableModel.getRowCount() > 0) {
569  caseName = casesTableModel.getValueAt(casesTable.convertRowIndexToModel(casesTable.getSelectedRow()), 0).toString();
570  }
571  if (caseName.isEmpty()) {
572  occurrencePanel = new OccurrencePanel();
573  } else {
574  createdDate = getCaseCreatedDate(casesTable.getSelectedRow());
575  occurrencePanel = new OccurrencePanel(caseName, createdDate);
576  }
577  } else {
578  //else display an empty details area
579  occurrencePanel = new OccurrencePanel();
580  }
581  //calling getPreferredSize has a side effect of ensuring it has a preferred size which reflects the contents which are visible
582  occurrencePanel.getPreferredSize();
583  detailsPanelScrollPane.setViewportView(occurrencePanel);
584  } finally {
585  setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
586  }
587  }
588 
597  private String getCaseCreatedDate(int caseTableRowIdx) {
598  try {
599  if (CentralRepository.isEnabled() && casesTableModel.getRowCount() > 0) {
600  CorrelationCase partialCase;
601  partialCase = casesTableModel.getCorrelationCase(casesTable.convertRowIndexToModel(caseTableRowIdx));
602  if (partialCase == null) {
603  return "";
604  }
605  return CentralRepository.getInstance().getCaseByUUID(partialCase.getCaseUUID()).getCreationDate();
606  } else {
608  }
609  } catch (CentralRepoException ex) {
610  logger.log(Level.WARNING, "Error getting case created date for row: " + caseTableRowIdx, ex);
611  }
612  return "";
613  }
614 
618  private class SelectionWorker extends SwingWorker<Map<UniquePathKey, NodeData>, Void> {
619 
620  private final Collection<CorrelationAttributeInstance> coAtInstances;
621  private final AbstractFile abstractFile;
622  private final String deviceIdStr;
623  private final String dataSourceNameStr;
624 
633  SelectionWorker(Collection<CorrelationAttributeInstance> coAtInstances, AbstractFile abstractFile, String deviceIdStr, String dataSourceNameStr) {
634  this.coAtInstances = coAtInstances;
635  this.abstractFile = abstractFile;
636  this.dataSourceNameStr = dataSourceNameStr;
637  this.deviceIdStr = deviceIdStr;
638  }
639 
640  @Override
641  protected Map<UniquePathKey, NodeData> doInBackground() throws Exception {
642  Map<UniquePathKey, NodeData> correlatedNodeDataMap = new HashMap<>();
643  for (CorrelationAttributeInstance corAttr : coAtInstances) {
644  correlatedNodeDataMap.putAll(OtherOccurrences.getCorrelatedInstances(abstractFile, deviceIdStr, dataSourceNameStr, corAttr));
645 
646  if (isCancelled()) {
647  return new HashMap<>();
648  }
649  }
650 
651  return correlatedNodeDataMap;
652  }
653  }
654 
658  private class CSVWorker extends SwingWorker<Void, Void> {
659 
660  private final Collection<CorrelationAttributeInstance> correlationAttList;
661  private final String dataSourceName;
662  private final String deviceId;
663  private final File destFile;
664  private final AbstractFile abstractFile;
665 
675  CSVWorker(File destFile, AbstractFile sourceFile, String dataSourceName, String deviceId, Collection<CorrelationAttributeInstance> correlationAttList) {
676  this.destFile = destFile;
677  this.abstractFile = sourceFile;
678  this.dataSourceName = dataSourceName;
679  this.deviceId = deviceId;
680  this.correlationAttList = correlationAttList;
681  }
682 
683  @Override
684  protected Void doInBackground() throws Exception {
685  OtherOccurrences.writeOtherOccurrencesToFileAsCSV(this.destFile, this.abstractFile, this.correlationAttList, this.dataSourceName, this.deviceId);
686  return null;
687  }
688 
689  @Override
690  public void done() {
691  try {
692  get();
693  } catch (InterruptedException | ExecutionException ex) {
694  JOptionPane.showMessageDialog(OtherOccurrencesPanel.this,
695  "Failed to create csv file for Other Occurrences at\n" + destFile.getAbsolutePath(),
696  "Error Creating CSV",
697  JOptionPane.ERROR_MESSAGE);
698 
699  logger.log(Level.SEVERE, "Error writing selected rows to from OtherOccurrencePanel to " + destFile.getAbsolutePath(), ex);
700  }
701  }
702  }
703 
709  @SuppressWarnings("unchecked")
710  // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
711  private void initComponents() {
712  java.awt.GridBagConstraints gridBagConstraints;
713 
714  rightClickPopupMenu = new javax.swing.JPopupMenu();
715  exportToCSVMenuItem = new javax.swing.JMenuItem();
716  showCaseDetailsMenuItem = new javax.swing.JMenuItem();
717  showCommonalityMenuItem = new javax.swing.JMenuItem();
718  tableContainerPanel = new javax.swing.JPanel();
719  tablesViewerSplitPane = new javax.swing.JSplitPane();
720  caseDatasourceFileSplitPane = new javax.swing.JSplitPane();
721  caseDatasourceSplitPane = new javax.swing.JSplitPane();
722  caseScrollPane = new javax.swing.JScrollPane();
723  casesTable = new javax.swing.JTable();
724  dataSourceScrollPane = new javax.swing.JScrollPane();
725  dataSourcesTable = new javax.swing.JTable();
726  filesTableScrollPane = new javax.swing.JScrollPane();
727  filesTable = new javax.swing.JTable();
728  detailsPanelScrollPane = new javax.swing.JScrollPane();
729  jPanel1 = new javax.swing.JPanel();
730  foundInLabel = new javax.swing.JLabel();
731  earliestCaseDate = new javax.swing.JLabel();
732  earliestCaseLabel = new javax.swing.JLabel();
733  filler1 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 0), new java.awt.Dimension(0, 0), new java.awt.Dimension(32767, 0));
734 
735  rightClickPopupMenu.addPopupMenuListener(new javax.swing.event.PopupMenuListener() {
736  public void popupMenuCanceled(javax.swing.event.PopupMenuEvent evt) {
737  }
738  public void popupMenuWillBecomeInvisible(javax.swing.event.PopupMenuEvent evt) {
739  }
740  public void popupMenuWillBecomeVisible(javax.swing.event.PopupMenuEvent evt) {
741  rightClickPopupMenuPopupMenuWillBecomeVisible(evt);
742  }
743  });
744 
745  org.openide.awt.Mnemonics.setLocalizedText(exportToCSVMenuItem, org.openide.util.NbBundle.getMessage(OtherOccurrencesPanel.class, "OtherOccurrencesPanel.exportToCSVMenuItem.text")); // NOI18N
746  rightClickPopupMenu.add(exportToCSVMenuItem);
747 
748  org.openide.awt.Mnemonics.setLocalizedText(showCaseDetailsMenuItem, org.openide.util.NbBundle.getMessage(OtherOccurrencesPanel.class, "OtherOccurrencesPanel.showCaseDetailsMenuItem.text")); // NOI18N
749  rightClickPopupMenu.add(showCaseDetailsMenuItem);
750 
751  org.openide.awt.Mnemonics.setLocalizedText(showCommonalityMenuItem, org.openide.util.NbBundle.getMessage(OtherOccurrencesPanel.class, "OtherOccurrencesPanel.showCommonalityMenuItem.text")); // NOI18N
752  rightClickPopupMenu.add(showCommonalityMenuItem);
753 
754  tableContainerPanel.setPreferredSize(new java.awt.Dimension(600, 63));
755  tableContainerPanel.setRequestFocusEnabled(false);
756 
757  tablesViewerSplitPane.setDividerLocation(450);
758  tablesViewerSplitPane.setResizeWeight(0.75);
759 
760  caseDatasourceFileSplitPane.setDividerLocation(300);
761  caseDatasourceFileSplitPane.setResizeWeight(0.66);
762  caseDatasourceFileSplitPane.setToolTipText(org.openide.util.NbBundle.getMessage(OtherOccurrencesPanel.class, "OtherOccurrencesPanel.caseDatasourceFileSplitPane.toolTipText")); // NOI18N
763 
764  caseDatasourceSplitPane.setDividerLocation(150);
765  caseDatasourceSplitPane.setResizeWeight(0.5);
766 
767  caseScrollPane.setPreferredSize(new java.awt.Dimension(150, 30));
768 
769  casesTable.setAutoCreateRowSorter(true);
770  casesTable.setModel(casesTableModel);
771  caseScrollPane.setViewportView(casesTable);
772 
773  caseDatasourceSplitPane.setLeftComponent(caseScrollPane);
774 
775  dataSourceScrollPane.setPreferredSize(new java.awt.Dimension(150, 30));
776 
777  dataSourcesTable.setAutoCreateRowSorter(true);
778  dataSourcesTable.setModel(dataSourcesTableModel);
779  dataSourceScrollPane.setViewportView(dataSourcesTable);
780 
781  caseDatasourceSplitPane.setRightComponent(dataSourceScrollPane);
782 
783  caseDatasourceFileSplitPane.setLeftComponent(caseDatasourceSplitPane);
784 
785  filesTableScrollPane.setPreferredSize(new java.awt.Dimension(150, 30));
786 
787  filesTable.setAutoCreateRowSorter(true);
788  filesTable.setModel(filesTableModel);
789  filesTable.setToolTipText(org.openide.util.NbBundle.getMessage(OtherOccurrencesPanel.class, "OtherOccurrencesPanel.filesTable.toolTipText")); // NOI18N
790  filesTable.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
791  filesTableScrollPane.setViewportView(filesTable);
792 
793  caseDatasourceFileSplitPane.setRightComponent(filesTableScrollPane);
794 
795  tablesViewerSplitPane.setLeftComponent(caseDatasourceFileSplitPane);
796 
797  detailsPanelScrollPane.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
798  detailsPanelScrollPane.setPreferredSize(new java.awt.Dimension(300, 100));
799  tablesViewerSplitPane.setRightComponent(detailsPanelScrollPane);
800 
801  jPanel1.setPreferredSize(new java.awt.Dimension(576, 22));
802  jPanel1.setLayout(new java.awt.GridBagLayout());
803 
804  foundInLabel.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING);
805  org.openide.awt.Mnemonics.setLocalizedText(foundInLabel, org.openide.util.NbBundle.getMessage(OtherOccurrencesPanel.class, "OtherOccurrencesPanel.foundInLabel.text")); // NOI18N
806  foundInLabel.setPreferredSize(new java.awt.Dimension(400, 16));
807  gridBagConstraints = new java.awt.GridBagConstraints();
808  gridBagConstraints.gridx = 3;
809  gridBagConstraints.gridy = 0;
810  gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
811  gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHEAST;
812  gridBagConstraints.insets = new java.awt.Insets(2, 2, 0, 0);
813  jPanel1.add(foundInLabel, gridBagConstraints);
814 
815  org.openide.awt.Mnemonics.setLocalizedText(earliestCaseDate, org.openide.util.NbBundle.getMessage(OtherOccurrencesPanel.class, "OtherOccurrencesPanel.earliestCaseDate.text")); // NOI18N
816  earliestCaseDate.setMaximumSize(new java.awt.Dimension(200, 16));
817  gridBagConstraints = new java.awt.GridBagConstraints();
818  gridBagConstraints.gridx = 1;
819  gridBagConstraints.gridy = 0;
820  gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
821  gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
822  gridBagConstraints.insets = new java.awt.Insets(0, 7, 0, 0);
823  jPanel1.add(earliestCaseDate, gridBagConstraints);
824 
825  org.openide.awt.Mnemonics.setLocalizedText(earliestCaseLabel, org.openide.util.NbBundle.getMessage(OtherOccurrencesPanel.class, "OtherOccurrencesPanel.earliestCaseLabel.text")); // NOI18N
826  earliestCaseLabel.setToolTipText(org.openide.util.NbBundle.getMessage(OtherOccurrencesPanel.class, "OtherOccurrencesPanel.earliestCaseLabel.toolTipText")); // NOI18N
827  earliestCaseLabel.setMaximumSize(new java.awt.Dimension(260, 16));
828  gridBagConstraints = new java.awt.GridBagConstraints();
829  gridBagConstraints.gridx = 0;
830  gridBagConstraints.gridy = 0;
831  gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
832  gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
833  jPanel1.add(earliestCaseLabel, gridBagConstraints);
834  gridBagConstraints = new java.awt.GridBagConstraints();
835  gridBagConstraints.gridx = 2;
836  gridBagConstraints.gridy = 0;
837  gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
838  gridBagConstraints.weightx = 0.1;
839  jPanel1.add(filler1, gridBagConstraints);
840 
841  javax.swing.GroupLayout tableContainerPanelLayout = new javax.swing.GroupLayout(tableContainerPanel);
842  tableContainerPanel.setLayout(tableContainerPanelLayout);
843  tableContainerPanelLayout.setHorizontalGroup(
844  tableContainerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
845  .addGroup(tableContainerPanelLayout.createSequentialGroup()
846  .addGroup(tableContainerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
847  .addComponent(tablesViewerSplitPane, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)
848  .addComponent(jPanel1, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 516, Short.MAX_VALUE))
849  .addContainerGap())
850  );
851  tableContainerPanelLayout.setVerticalGroup(
852  tableContainerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
853  .addGroup(tableContainerPanelLayout.createSequentialGroup()
854  .addGap(0, 0, 0)
855  .addComponent(tablesViewerSplitPane)
856  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
857  .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
858  .addGap(12, 12, 12))
859  );
860 
861  javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
862  this.setLayout(layout);
863  layout.setHorizontalGroup(
864  layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
865  .addComponent(tableContainerPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 528, Short.MAX_VALUE)
866  );
867  layout.setVerticalGroup(
868  layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
869  .addComponent(tableContainerPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 143, Short.MAX_VALUE)
870  );
871  }// </editor-fold>//GEN-END:initComponents
872 
873  private void rightClickPopupMenuPopupMenuWillBecomeVisible(javax.swing.event.PopupMenuEvent evt) {//GEN-FIRST:event_rightClickPopupMenuPopupMenuWillBecomeVisible
874  boolean enableCentralRepoActions = false;
875  if (CentralRepository.isEnabled() && filesTable.getSelectedRowCount() == 1) {
876  int rowIndex = filesTable.getSelectedRow();
877  List<NodeData> selectedFile = filesTableModel.getListOfNodesForFile(rowIndex);
878  if (!selectedFile.isEmpty() && selectedFile.get(0) instanceof NodeData) {
879  NodeData instanceData = selectedFile.get(0);
880  enableCentralRepoActions = instanceData.isCentralRepoNode();
881  }
882  }
883  showCaseDetailsMenuItem.setVisible(enableCentralRepoActions);
884  showCommonalityMenuItem.setVisible(enableCentralRepoActions);
885  }//GEN-LAST:event_rightClickPopupMenuPopupMenuWillBecomeVisible
886 
887 
888  // Variables declaration - do not modify//GEN-BEGIN:variables
889  private javax.swing.JSplitPane caseDatasourceFileSplitPane;
890  private javax.swing.JSplitPane caseDatasourceSplitPane;
891  private javax.swing.JScrollPane caseScrollPane;
892  private javax.swing.JTable casesTable;
893  private javax.swing.JScrollPane dataSourceScrollPane;
894  private javax.swing.JTable dataSourcesTable;
895  private javax.swing.JScrollPane detailsPanelScrollPane;
896  private javax.swing.JLabel earliestCaseDate;
897  private javax.swing.JLabel earliestCaseLabel;
898  private javax.swing.JMenuItem exportToCSVMenuItem;
899  private javax.swing.JTable filesTable;
900  private javax.swing.JScrollPane filesTableScrollPane;
901  private javax.swing.Box.Filler filler1;
902  private javax.swing.JLabel foundInLabel;
903  private javax.swing.JPanel jPanel1;
904  private javax.swing.JPopupMenu rightClickPopupMenu;
905  private javax.swing.JMenuItem showCaseDetailsMenuItem;
906  private javax.swing.JMenuItem showCommonalityMenuItem;
907  private javax.swing.JPanel tableContainerPanel;
908  private javax.swing.JSplitPane tablesViewerSplitPane;
909  // End of variables declaration//GEN-END:variables
910 }
static void writeOtherOccurrencesToFileAsCSV(File destFile, AbstractFile abstractFile, Collection< CorrelationAttributeInstance > correlationAttList, String dataSourceName, String deviceId)
static Map< UniquePathKey, NodeData > getCorrelatedInstances(AbstractFile file, String deviceId, String dataSourceName, CorrelationAttributeInstance corAttr)
void populateTableForOneType(CorrelationAttributeInstance.Type aType, String value)
int getFrequencyPercentage(CorrelationAttributeInstance corAttr)
synchronized static Logger getLogger(String name)
Definition: Logger.java:124

Copyright © 2012-2021 Basis Technology. Generated on: Fri Aug 6 2021
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.