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