Autopsy  4.9.1
Graphical digital forensics platform for The Sleuth Kit and other tools.
CommonAttributePanel.java
Go to the documentation of this file.
1 /*
2  * Autopsy Forensic Browser
3  *
4  * Copyright 2018 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.commonfilesearch;
20 
23 import java.awt.Dimension;
24 import java.sql.SQLException;
25 import java.util.ArrayList;
26 import java.util.Collection;
27 import java.util.HashMap;
28 import java.util.List;
29 import java.util.Map;
30 import java.util.Objects;
31 import java.util.Observable;
32 import java.util.Observer;
33 import java.util.concurrent.ExecutionException;
34 import java.util.logging.Level;
35 import javax.swing.JPanel;
36 import javax.swing.SwingWorker;
37 import javax.swing.event.DocumentEvent;
38 import javax.swing.event.DocumentListener;
39 import org.netbeans.api.progress.ProgressHandle;
40 import org.openide.DialogDisplayer;
41 import org.openide.NotifyDescriptor;
42 import org.openide.explorer.ExplorerManager;
43 import org.openide.nodes.Node;
44 import org.openide.util.NbBundle;
45 import org.openide.util.NbBundle.Messages;
46 import org.openide.windows.WindowManager;
63 import org.sleuthkit.datamodel.DataSource;
64 import org.sleuthkit.datamodel.IngestJobInfo;
65 import org.sleuthkit.datamodel.IngestModuleInfo;
66 import org.sleuthkit.datamodel.SleuthkitCase;
67 import org.sleuthkit.datamodel.TskCoreException;
68 
73 @SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
74 final class CommonAttributePanel extends javax.swing.JDialog implements Observer {
75 
76  private static final Logger LOGGER = Logger.getLogger(CommonAttributePanel.class.getName());
77  private static final long serialVersionUID = 1L;
78 
79  private static final Long NO_DATA_SOURCE_SELECTED = -1L;
80 
81  private final UserInputErrorManager errorManager;
82 
83  private int percentageThresholdValue = 20;
84 
85  private final IntraCasePanel intraCasePanel;
86  private final InterCasePanel interCasePanel;
87 
91  @NbBundle.Messages({
92  "CommonAttributePanel.title=Common Property Panel",
93  "CommonAttributePanel.exception=Unexpected Exception loading DataSources.",
94  "CommonAttributePanel.frame.title=Find Common Properties",
95  "CommonAttributePanel.intraCasePanel.title=Curren Case Options"})
96  CommonAttributePanel() {
97  super(WindowManager.getDefault().getMainWindow(), Bundle.CommonAttributePanel_frame_title(), true);
98  initComponents();
99  this.setLocationRelativeTo(WindowManager.getDefault().getMainWindow());
100 
101  interCasePanel = new InterCasePanel();
102  interCasePanel.setVisible(true);
103  interCasePanel.setSize((int) containerPanel.getPreferredSize().getWidth(), (int) containerPanel.getPreferredSize().getHeight());
104 
105  intraCasePanel = new IntraCasePanel();
106  intraCasePanel.setVisible(true);
107  intraCasePanel.setSize((int) containerPanel.getPreferredSize().getWidth(), (int) containerPanel.getPreferredSize().getHeight());
108 
109  this.setupDataSources();
110 
111  if (CommonAttributePanel.isEamDbAvailableForIntercaseSearch()) {
112  this.setupCases();
113  this.interCasePanel.setupCorrelationTypeFilter();
114  this.interCaseRadio.setSelected(true);
115  switchInnerPanel(interCasePanel);
116  } else {
117  this.disableIntercaseSearch();
118  this.intraCaseRadio.setSelected(true);
119  switchInnerPanel(intraCasePanel);
120  }
121  this.revalidate();
122  this.repaint();
123 
124  this.updatePercentageOptions(CommonAttributePanel.getNumberOfDataSourcesAvailable());
125 
126  this.errorManager = new UserInputErrorManager();
127 
128  this.percentageThresholdInputBox.getDocument().addDocumentListener(new DocumentListener() {
129 
130  private final Dimension preferredSize = CommonAttributePanel.this.percentageThresholdInputBox.getPreferredSize();
131 
132  private void maintainSize() {
133  CommonAttributePanel.this.percentageThresholdInputBox.setSize(preferredSize);
134  }
135 
136  @Override
137  public void insertUpdate(DocumentEvent event) {
138  this.maintainSize();
139  CommonAttributePanel.this.percentageThresholdChanged();
140  }
141 
142  @Override
143  public void removeUpdate(DocumentEvent event) {
144  this.maintainSize();
145  CommonAttributePanel.this.percentageThresholdChanged();
146  }
147 
148  @Override
149  public void changedUpdate(DocumentEvent event) {
150  this.maintainSize();
151  CommonAttributePanel.this.percentageThresholdChanged();
152  }
153  });
154  }
155 
163  static boolean isEamDbAvailableForIntercaseSearch() {
164  try {
165  return EamDb.isEnabled()
166  && EamDb.getInstance() != null
167  && EamDb.getInstance().getCases().size() > 1
168  && Case.isCaseOpen()
169  && Case.getCurrentCase() != null
170  && EamDb.getInstance().getCase(Case.getCurrentCase()) != null;
171  } catch (EamDbException ex) {
172  LOGGER.log(Level.SEVERE, "Unexpected exception while checking for EamDB enabled.", ex);
173  }
174  return false;
175  }
176 
177  @Override
178  public void update(Observable o, Object arg) {
179  checkFileTypeCheckBoxState();
180  }
181 
189  private static Long getNumberOfDataSourcesAvailable() {
190  try {
191  if (EamDb.isEnabled()
192  && EamDb.getInstance() != null) {
193  return EamDb.getInstance().getCountUniqueDataSources();
194  }
195  } catch (EamDbException ex) {
196  LOGGER.log(Level.SEVERE, "Unexpected exception while checking for EamDB enabled.", ex);
197  }
198  return 0L;
199  }
200 
205  private void disableIntercaseSearch() {
206  this.intraCaseRadio.setSelected(true);
207  this.interCaseRadio.setEnabled(false);
208  }
209 
213  @NbBundle.Messages({
214  "CommonAttributePanel.search.results.pathText=Common Properties Results",
215  "CommonAttributePanel.search.done.searchProgressGathering=Gathering Common Properties Results.",
216  "CommonAttributePanel.search.done.searchProgressDisplay=Displaying Common Properties Results.",
217  "CommonAttributePanel.search.done.tskCoreException=Unable to run query against DB.",
218  "CommonAttributePanel.search.done.noCurrentCaseException=Unable to open case file.",
219  "CommonAttributePanel.search.done.exception=Unexpected exception running Find Common Properties.",
220  "CommonAttributePanel.search.done.interupted=Something went wrong finding common properties.",
221  "CommonAttributePanel.search.done.sqlException=Unable to query db for properties or data sources.",
222  "CommonAttributePanel.search.done.noResults=No results found."})
223  private void searchByCount() {
224  new SwingWorker<CommonAttributeCountSearchResults, Void>() {
225 
226  private String tabTitle;
227  private ProgressHandle progress;
228 
229  @Override
230  protected CommonAttributeCountSearchResults doInBackground() throws TskCoreException, NoCurrentCaseException, SQLException, EamDbException {
231  progress = ProgressHandle.createHandle(Bundle.CommonAttributePanel_search_done_searchProgressGathering());
232  progress.start();
233  progress.switchToIndeterminate();
234 
235  Long dataSourceId = intraCasePanel.getSelectedDataSourceId();
236  Integer caseId = interCasePanel.getSelectedCaseId();
237 
238  AbstractCommonAttributeSearcher builder;
239  CommonAttributeCountSearchResults metadata;
240 
241  boolean filterByMedia = false;
242  boolean filterByDocuments = false;
243 
244  int percentageThreshold = CommonAttributePanel.this.percentageThresholdValue;
245 
246  if (!CommonAttributePanel.this.percentageThresholdCheck.isSelected()) {
247  //0 has the effect of disabling the feature
248  percentageThreshold = 0;
249  }
250 
251  if (CommonAttributePanel.this.interCaseRadio.isSelected()) {
252  CorrelationAttributeInstance.Type corType = interCasePanel.getSelectedCorrelationType();
253  if (interCasePanel.fileCategoriesButtonIsSelected()) {
254  filterByMedia = interCasePanel.pictureVideoCheckboxIsSelected();
255  filterByDocuments = interCasePanel.documentsCheckboxIsSelected();
256  }
257  if (corType == null) {
258  corType = CorrelationAttributeInstance.getDefaultCorrelationTypes().get(0);
259  }
260  if (caseId == InterCasePanel.NO_CASE_SELECTED) {
261  builder = new AllInterCaseCommonAttributeSearcher(filterByMedia, filterByDocuments, corType, percentageThreshold);
262  } else {
263 
264  builder = new SingleInterCaseCommonAttributeSearcher(caseId, filterByMedia, filterByDocuments, corType, percentageThreshold);
265  }
266 
267  } else {
268  if (intraCasePanel.fileCategoriesButtonIsSelected()) {
269  filterByMedia = intraCasePanel.pictureVideoCheckboxIsSelected();
270  filterByDocuments = intraCasePanel.documentsCheckboxIsSelected();
271  }
272  if (Objects.equals(dataSourceId, CommonAttributePanel.NO_DATA_SOURCE_SELECTED)) {
273  builder = new AllIntraCaseCommonAttributeSearcher(intraCasePanel.getDataSourceMap(), filterByMedia, filterByDocuments, percentageThreshold);
274  } else {
275  builder = new SingleIntraCaseCommonAttributeSearcher(dataSourceId, intraCasePanel.getDataSourceMap(), filterByMedia, filterByDocuments, percentageThreshold);
276  }
277 
278  }
279  metadata = builder.findMatchesByCount();
280  this.tabTitle = builder.getTabTitle();
281  return metadata;
282  }
283 
284  @Override
285  protected void done() {
286  try {
287  super.done();
288  CommonAttributeCountSearchResults metadata = this.get();
289  boolean noKeysExist = metadata.getMetadata().keySet().isEmpty();
290  if (noKeysExist) {
291  Node commonFilesNode = new TableFilterNode(new EmptyNode(Bundle.CommonAttributePanel_search_done_noResults()), true);
292  progress.setDisplayName(Bundle.CommonAttributePanel_search_done_searchProgressDisplay());
293  DataResultTopComponent.createInstance(tabTitle, Bundle.CommonAttributePanel_search_results_pathText(), commonFilesNode, 1);
294  } else {
295  // -3969
296  Node commonFilesNode = new CommonAttributeSearchResultRootNode(metadata);
297  DataResultFilterNode dataResultFilterNode = new DataResultFilterNode(commonFilesNode, ExplorerManager.find(CommonAttributePanel.this));
298  TableFilterNode tableFilterWithDescendantsNode = new TableFilterNode(dataResultFilterNode, 3);
299  DataResultViewerTable table = new CommonAttributesSearchResultsViewerTable();
300  Collection<DataResultViewer> viewers = new ArrayList<>(1);
301  viewers.add(table);
302  progress.setDisplayName(Bundle.CommonAttributePanel_search_done_searchProgressDisplay());
303  DataResultTopComponent.createInstance(tabTitle, Bundle.CommonAttributePanel_search_results_pathText(), tableFilterWithDescendantsNode, metadata.size(), viewers);
304  }
305 
306  } catch (InterruptedException ex) {
307  LOGGER.log(Level.SEVERE, "Interrupted while loading Common Files", ex);
308  MessageNotifyUtil.Message.error(Bundle.CommonAttributePanel_search_done_interupted());
309  } catch (ExecutionException ex) {
310  String errorMessage;
311  Throwable inner = ex.getCause();
312  if (inner instanceof TskCoreException) {
313  LOGGER.log(Level.SEVERE, "Failed to load files from database.", ex);
314  errorMessage = Bundle.CommonAttributePanel_search_done_tskCoreException();
315  } else if (inner instanceof NoCurrentCaseException) {
316  LOGGER.log(Level.SEVERE, "Current case has been closed.", ex);
317  errorMessage = Bundle.CommonAttributePanel_search_done_noCurrentCaseException();
318  } else if (inner instanceof SQLException) {
319  LOGGER.log(Level.SEVERE, "Unable to query db for files.", ex);
320  errorMessage = Bundle.CommonAttributePanel_search_done_sqlException();
321  } else {
322  LOGGER.log(Level.SEVERE, "Unexpected exception while running Common Files Search.", ex);
323  errorMessage = Bundle.CommonAttributePanel_search_done_exception();
324  }
325  MessageNotifyUtil.Message.error(errorMessage);
326  } finally {
327  progress.finish();
328  }
329  }
330  }.execute();
331  }
332 
336  private void searchByCase() {
337  new SwingWorker<CommonAttributeCaseSearchResults, Void>() {
338  private String tabTitle;
339  private ProgressHandle progress;
340 
341  @Override
342  protected CommonAttributeCaseSearchResults doInBackground() throws TskCoreException, NoCurrentCaseException, SQLException, EamDbException {
343  progress = ProgressHandle.createHandle(Bundle.CommonAttributePanel_search_done_searchProgressGathering());
344  progress.start();
345  progress.switchToIndeterminate();
346  Long dataSourceId = intraCasePanel.getSelectedDataSourceId();
347  Integer caseId = interCasePanel.getSelectedCaseId();
348  AbstractCommonAttributeSearcher builder;
349  CommonAttributeCaseSearchResults metadata;
350  boolean filterByMedia = false;
351  boolean filterByDocuments = false;
352  int percentageThreshold = CommonAttributePanel.this.percentageThresholdValue;
353  if (!CommonAttributePanel.this.percentageThresholdCheck.isSelected()) {
354  //0 has the effect of disabling the feature
355  percentageThreshold = 0;
356  }
357  if (CommonAttributePanel.this.interCaseRadio.isSelected()) {
358  CorrelationAttributeInstance.Type corType = interCasePanel.getSelectedCorrelationType();
359  if (interCasePanel.fileCategoriesButtonIsSelected()) {
360  filterByMedia = interCasePanel.pictureVideoCheckboxIsSelected();
361  filterByDocuments = interCasePanel.documentsCheckboxIsSelected();
362  }
363  if (corType == null) {
364  corType = CorrelationAttributeInstance.getDefaultCorrelationTypes().get(0);
365  }
366  if (caseId == InterCasePanel.NO_CASE_SELECTED) {
367  builder = new AllInterCaseCommonAttributeSearcher(filterByMedia, filterByDocuments, corType, percentageThreshold);
368  } else {
369  builder = new SingleInterCaseCommonAttributeSearcher(caseId, filterByMedia, filterByDocuments, corType, percentageThreshold);
370  }
371  } else {
372  if (intraCasePanel.fileCategoriesButtonIsSelected()) {
373  filterByMedia = intraCasePanel.pictureVideoCheckboxIsSelected();
374  filterByDocuments = intraCasePanel.documentsCheckboxIsSelected();
375  }
376  if (Objects.equals(dataSourceId, CommonAttributePanel.NO_DATA_SOURCE_SELECTED)) {
377  builder = new AllIntraCaseCommonAttributeSearcher(intraCasePanel.getDataSourceMap(), filterByMedia, filterByDocuments, percentageThreshold);
378  } else {
379  builder = new SingleIntraCaseCommonAttributeSearcher(dataSourceId, intraCasePanel.getDataSourceMap(), filterByMedia, filterByDocuments, percentageThreshold);
380  }
381  }
382  metadata = builder.findMatchesByCase();
383  this.tabTitle = builder.getTabTitle();
384  return metadata;
385  }
386 
387  @Override
388  protected void done() {
389  try {
390  super.done();
391  CommonAttributeCaseSearchResults metadata = this.get();
392  if (metadata.getMetadata().keySet().isEmpty()) {
393  Node commonFilesNode = new TableFilterNode(new EmptyNode(Bundle.CommonAttributePanel_search_done_noResults()), true);
394  progress.setDisplayName(Bundle.CommonAttributePanel_search_done_searchProgressDisplay());
395  DataResultTopComponent.createInstance(tabTitle, Bundle.CommonAttributePanel_search_results_pathText(), commonFilesNode, 1);
396  } else {
397  // -3969
398  Node commonFilesNode = new CommonAttributeSearchResultRootNode(metadata);
399  DataResultFilterNode dataResultFilterNode = new DataResultFilterNode(commonFilesNode, ExplorerManager.find(CommonAttributePanel.this));
400  TableFilterNode tableFilterWithDescendantsNode = new TableFilterNode(dataResultFilterNode, 3);
401  DataResultViewerTable table = new CommonAttributesSearchResultsViewerTable();
402  Collection<DataResultViewer> viewers = new ArrayList<>(1);
403  viewers.add(table);
404  progress.setDisplayName(Bundle.CommonAttributePanel_search_done_searchProgressDisplay());
405  //0 passed as arguement due to JIRA-4502 ensuring the value is never displayed JIRA-TODO
406  DataResultTopComponent.createInstance(tabTitle, Bundle.CommonAttributePanel_search_results_pathText(), tableFilterWithDescendantsNode, 0, viewers);
407  }
408  } catch (InterruptedException ex) {
409  LOGGER.log(Level.SEVERE, "Interrupted while loading Common Files", ex);
410  MessageNotifyUtil.Message.error(Bundle.CommonAttributePanel_search_done_interupted());
411  } catch (ExecutionException ex) {
412  String errorMessage;
413  Throwable inner = ex.getCause();
414  if (inner instanceof TskCoreException) {
415  LOGGER.log(Level.SEVERE, "Failed to load files from database.", ex);
416  errorMessage = Bundle.CommonAttributePanel_search_done_tskCoreException();
417  } else if (inner instanceof NoCurrentCaseException) {
418  LOGGER.log(Level.SEVERE, "Current case has been closed.", ex);
419  errorMessage = Bundle.CommonAttributePanel_search_done_noCurrentCaseException();
420  } else if (inner instanceof SQLException) {
421  LOGGER.log(Level.SEVERE, "Unable to query db for files.", ex);
422  errorMessage = Bundle.CommonAttributePanel_search_done_sqlException();
423  } else {
424  LOGGER.log(Level.SEVERE, "Unexpected exception while running Common Files Search.", ex);
425  errorMessage = Bundle.CommonAttributePanel_search_done_exception();
426  }
427  MessageNotifyUtil.Message.error(errorMessage);
428  } finally {
429  progress.finish();
430  }
431  }
432  }.execute();
433  }
434 
442  @NbBundle.Messages({
443  "CommonAttributePanel.setupDataSources.done.tskCoreException=Unable to run query against DB.",
444  "CommonAttributePanel.setupDataSources.done.noCurrentCaseException=Unable to open case file.",
445  "CommonAttributePanel.setupDataSources.done.exception=Unexpected exception loading data sources.",
446  "CommonAttributePanel.setupDataSources.done.interupted=Something went wrong building the Common Files Search dialog box.",
447  "CommonAttributePanel.setupDataSources.done.sqlException=Unable to query db for data sources.",
448  "CommonAttributePanel.setupDataSources.updateUi.noDataSources=No data sources were found."})
449 
450  private void setupDataSources() {
451 
452  new SwingWorker<Map<Long, String>, Void>() {
453 
458  private void updateUi() {
459 
460  final Map<Long, String> dataSourceMap = CommonAttributePanel.this.intraCasePanel.getDataSourceMap();
461 
462  String[] dataSourcesNames = new String[dataSourceMap.size()];
463 
464  //only enable all this stuff if we actually have datasources
465  if (dataSourcesNames.length > 0) {
466  dataSourcesNames = dataSourceMap.values().toArray(dataSourcesNames);
467  CommonAttributePanel.this.intraCasePanel.setDatasourceComboboxModel(new DataSourceComboBoxModel(dataSourcesNames));
468 
469  if (!this.caseHasMultipleSources()) { //disable intra case search when only 1 data source in current case
470  intraCaseRadio.setEnabled(false);
471  interCaseRadio.setSelected(true);
472  }
473  CommonAttributePanel.this.updateErrorTextAndSearchButton();
474  }
475  }
476 
483  private boolean caseHasMultipleSources() {
484  return CommonAttributePanel.this.intraCasePanel.getDataSourceMap().size() > 1;
485  }
486 
487  @Override
488  protected Map<Long, String> doInBackground() throws NoCurrentCaseException, TskCoreException, SQLException {
489  DataSourceLoader loader = new DataSourceLoader();
490  return loader.getDataSourceMap();
491  }
492 
493  @Override
494  protected void done() {
495 
496  try {
497  CommonAttributePanel.this.intraCasePanel.setDataSourceMap(this.get());
498  updateUi();
499 
500  } catch (InterruptedException ex) {
501  LOGGER.log(Level.SEVERE, "Interrupted while building Common Files Search dialog.", ex);
502  MessageNotifyUtil.Message.error(Bundle.CommonAttributePanel_setupDataSources_done_interupted());
503  } catch (ExecutionException ex) {
504  String errorMessage;
505  Throwable inner = ex.getCause();
506  if (inner instanceof TskCoreException) {
507  LOGGER.log(Level.SEVERE, "Failed to load data sources from database.", ex);
508  errorMessage = Bundle.CommonAttributePanel_setupDataSources_done_tskCoreException();
509  } else if (inner instanceof NoCurrentCaseException) {
510  LOGGER.log(Level.SEVERE, "Current case has been closed.", ex);
511  errorMessage = Bundle.CommonAttributePanel_setupDataSources_done_noCurrentCaseException();
512  } else if (inner instanceof SQLException) {
513  LOGGER.log(Level.SEVERE, "Unable to query db for data sources.", ex);
514  errorMessage = Bundle.CommonAttributePanel_setupDataSources_done_sqlException();
515  } else {
516  LOGGER.log(Level.SEVERE, "Unexpected exception while building Common Files Search dialog panel.", ex);
517  errorMessage = Bundle.CommonAttributePanel_setupDataSources_done_exception();
518  }
519  MessageNotifyUtil.Message.error(errorMessage);
520  }
521  }
522  }.execute();
523  }
524 
530  private void switchInnerPanel(JPanel panel) {
531  containerPanel.removeAll();
532  containerPanel.add(panel);
533  caseResultsRadioButton.setVisible(this.interCaseRadio.isSelected());
534  countResultsRadioButton.setVisible(this.interCaseRadio.isSelected());
535  displayResultsLabel.setVisible(this.interCaseRadio.isSelected());
536  this.revalidate();
537  this.repaint();
538  }
539 
540  @NbBundle.Messages({
541  "CommonAttributePanel.setupCases.done.interruptedException=Something went wrong building the Common Files Search dialog box.",
542  "CommonAttributePanel.setupCases.done.exeutionException=Unexpected exception loading cases."})
543  private void setupCases() {
544 
545  new SwingWorker<Map<Integer, String>, Void>() {
546 
551  private void updateUi() {
552 
553  final Map<Integer, String> caseMap = CommonAttributePanel.this.interCasePanel.getCaseMap();
554 
555  String[] caseNames = new String[caseMap.size()];
556 
557  if (caseNames.length > 0) {
558  caseNames = caseMap.values().toArray(caseNames);
559  CommonAttributePanel.this.interCasePanel.setCaseComboboxModel(new DataSourceComboBoxModel(caseNames));
560  } else {
561  CommonAttributePanel.this.disableIntercaseSearch();
562  }
563  }
564 
574  private Map<Integer, String> mapCases(List<CorrelationCase> cases) throws EamDbException {
575  Map<Integer, String> casemap = new HashMap<>();
576  CorrelationCase currentCorCase = EamDb.getInstance().getCase(Case.getCurrentCase());
577  for (CorrelationCase correlationCase : cases) {
578  if (currentCorCase.getID() != correlationCase.getID()) { // if not the current Case
579  casemap.put(correlationCase.getID(), correlationCase.getDisplayName());
580  }
581  }
582  return casemap;
583  }
584 
585  @Override
586  protected Map<Integer, String> doInBackground() throws EamDbException {
587 
588  List<CorrelationCase> dataSources = EamDb.getInstance().getCases();
589  Map<Integer, String> caseMap = mapCases(dataSources);
590 
591  return caseMap;
592  }
593 
594  @Override
595  protected void done() {
596  try {
597  Map<Integer, String> cases = this.get();
598  CommonAttributePanel.this.interCasePanel.setCaseMap(cases);
599  this.updateUi();
600  } catch (InterruptedException ex) {
601  LOGGER.log(Level.SEVERE, "Interrupted while building Common Files Search dialog.", ex);
602  MessageNotifyUtil.Message.error(Bundle.CommonAttributePanel_setupCases_done_interruptedException());
603  } catch (ExecutionException ex) {
604  LOGGER.log(Level.SEVERE, "Unexpected exception while building Common Files Search dialog.", ex);
605  MessageNotifyUtil.Message.error(Bundle.CommonAttributePanel_setupCases_done_exeutionException());
606  }
607  }
608 
609  }.execute();
610  }
611 
617  @SuppressWarnings("unchecked")
618  // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
619  private void initComponents() {
620 
621  interIntraButtonGroup = new javax.swing.ButtonGroup();
622  displayResultsButtonGroup = new javax.swing.ButtonGroup();
623  jPanel1 = new javax.swing.JPanel();
624  commonItemSearchDescription = new javax.swing.JLabel();
625  scopeLabel = new javax.swing.JLabel();
626  intraCaseRadio = new javax.swing.JRadioButton();
627  interCaseRadio = new javax.swing.JRadioButton();
628  containerPanel = new javax.swing.JPanel();
629  percentageThresholdCheck = new javax.swing.JCheckBox();
630  percentageThresholdInputBox = new javax.swing.JTextField();
631  percentageThresholdTextTwo = new javax.swing.JLabel();
632  dataSourcesLabel = new javax.swing.JLabel();
633  errorText = new javax.swing.JLabel();
634  searchButton = new javax.swing.JButton();
635  caseResultsRadioButton = new javax.swing.JRadioButton();
636  countResultsRadioButton = new javax.swing.JRadioButton();
637  displayResultsLabel = new javax.swing.JLabel();
638 
639  setMinimumSize(new java.awt.Dimension(450, 570));
640  setResizable(false);
641  addWindowListener(new java.awt.event.WindowAdapter() {
642  public void windowClosed(java.awt.event.WindowEvent evt) {
643  formWindowClosed(evt);
644  }
645  });
646 
647  jPanel1.setMaximumSize(null);
648  jPanel1.setPreferredSize(new java.awt.Dimension(450, 646));
649  jPanel1.setRequestFocusEnabled(false);
650 
651  org.openide.awt.Mnemonics.setLocalizedText(commonItemSearchDescription, org.openide.util.NbBundle.getMessage(CommonAttributePanel.class, "CommonAttributePanel.commonItemSearchDescription.text")); // NOI18N
652  commonItemSearchDescription.setFocusable(false);
653 
654  org.openide.awt.Mnemonics.setLocalizedText(scopeLabel, org.openide.util.NbBundle.getMessage(CommonAttributePanel.class, "CommonAttributePanel.scopeLabel.text")); // NOI18N
655  scopeLabel.setFocusable(false);
656 
657  interIntraButtonGroup.add(intraCaseRadio);
658  intraCaseRadio.setSelected(true);
659  org.openide.awt.Mnemonics.setLocalizedText(intraCaseRadio, org.openide.util.NbBundle.getMessage(CommonAttributePanel.class, "CommonAttributePanel.intraCaseRadio.text")); // NOI18N
660  intraCaseRadio.addActionListener(new java.awt.event.ActionListener() {
661  public void actionPerformed(java.awt.event.ActionEvent evt) {
662  intraCaseRadioActionPerformed(evt);
663  }
664  });
665 
666  interIntraButtonGroup.add(interCaseRadio);
667  org.openide.awt.Mnemonics.setLocalizedText(interCaseRadio, org.openide.util.NbBundle.getMessage(CommonAttributePanel.class, "CommonFilesPanel.jRadioButton2.text")); // NOI18N
668  interCaseRadio.addActionListener(new java.awt.event.ActionListener() {
669  public void actionPerformed(java.awt.event.ActionEvent evt) {
670  interCaseRadioActionPerformed(evt);
671  }
672  });
673 
674  containerPanel.setBackground(new java.awt.Color(0, 0, 0));
675  containerPanel.setOpaque(false);
676 
677  javax.swing.GroupLayout containerPanelLayout = new javax.swing.GroupLayout(containerPanel);
678  containerPanel.setLayout(containerPanelLayout);
679  containerPanelLayout.setHorizontalGroup(
680  containerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
681  .addGap(0, 430, Short.MAX_VALUE)
682  );
683  containerPanelLayout.setVerticalGroup(
684  containerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
685  .addGap(0, 326, Short.MAX_VALUE)
686  );
687 
688  org.openide.awt.Mnemonics.setLocalizedText(percentageThresholdCheck, org.openide.util.NbBundle.getMessage(CommonAttributePanel.class, "CommonAttributePanel.percentageThresholdCheck.text_1_1")); // NOI18N
689  percentageThresholdCheck.addActionListener(new java.awt.event.ActionListener() {
690  public void actionPerformed(java.awt.event.ActionEvent evt) {
691  percentageThresholdCheckActionPerformed(evt);
692  }
693  });
694 
695  percentageThresholdInputBox.setHorizontalAlignment(javax.swing.JTextField.TRAILING);
696  percentageThresholdInputBox.setText(org.openide.util.NbBundle.getMessage(CommonAttributePanel.class, "CommonAttributePanel.percentageThresholdInputBox.text")); // NOI18N
697  percentageThresholdInputBox.setMaximumSize(new java.awt.Dimension(40, 24));
698  percentageThresholdInputBox.setMinimumSize(new java.awt.Dimension(40, 24));
699  percentageThresholdInputBox.setPreferredSize(new java.awt.Dimension(40, 24));
700 
701  org.openide.awt.Mnemonics.setLocalizedText(percentageThresholdTextTwo, org.openide.util.NbBundle.getMessage(CommonAttributePanel.class, "CommonAttributePanel.percentageThresholdTextTwo.text_1")); // NOI18N
702 
703  org.openide.awt.Mnemonics.setLocalizedText(dataSourcesLabel, org.openide.util.NbBundle.getMessage(CommonAttributePanel.class, "CommonAttributePanel.dataSourcesLabel.text")); // NOI18N
704 
705  errorText.setForeground(new java.awt.Color(255, 0, 0));
706  org.openide.awt.Mnemonics.setLocalizedText(errorText, org.openide.util.NbBundle.getMessage(CommonAttributePanel.class, "CommonAttributePanel.errorText.text")); // NOI18N
707  errorText.setVerticalAlignment(javax.swing.SwingConstants.TOP);
708 
709  org.openide.awt.Mnemonics.setLocalizedText(searchButton, org.openide.util.NbBundle.getMessage(CommonAttributePanel.class, "CommonAttributePanel.searchButton.text")); // NOI18N
710  searchButton.setEnabled(false);
711  searchButton.setHorizontalTextPosition(javax.swing.SwingConstants.LEADING);
712  searchButton.addActionListener(new java.awt.event.ActionListener() {
713  public void actionPerformed(java.awt.event.ActionEvent evt) {
714  searchButtonActionPerformed(evt);
715  }
716  });
717 
718  displayResultsButtonGroup.add(caseResultsRadioButton);
719  caseResultsRadioButton.setSelected(true);
720  org.openide.awt.Mnemonics.setLocalizedText(caseResultsRadioButton, org.openide.util.NbBundle.getMessage(CommonAttributePanel.class, "CommonAttributePanel.caseResultsRadioButton.text")); // NOI18N
721  caseResultsRadioButton.addActionListener(new java.awt.event.ActionListener() {
722  public void actionPerformed(java.awt.event.ActionEvent evt) {
723  caseResultsRadioButtonActionPerformed(evt);
724  }
725  });
726 
727  displayResultsButtonGroup.add(countResultsRadioButton);
728  org.openide.awt.Mnemonics.setLocalizedText(countResultsRadioButton, org.openide.util.NbBundle.getMessage(CommonAttributePanel.class, "CommonAttributePanel.countResultsRadioButton.text")); // NOI18N
729 
730  org.openide.awt.Mnemonics.setLocalizedText(displayResultsLabel, org.openide.util.NbBundle.getMessage(CommonAttributePanel.class, "CommonAttributePanel.displayResultsLabel.text_2")); // NOI18N
731 
732  javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
733  jPanel1.setLayout(jPanel1Layout);
734  jPanel1Layout.setHorizontalGroup(
735  jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
736  .addGroup(jPanel1Layout.createSequentialGroup()
737  .addContainerGap()
738  .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
739  .addGroup(jPanel1Layout.createSequentialGroup()
740  .addComponent(dataSourcesLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
741  .addContainerGap())
742  .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup()
743  .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
744  .addGroup(jPanel1Layout.createSequentialGroup()
745  .addGap(0, 0, Short.MAX_VALUE)
746  .addComponent(intraCaseRadio, javax.swing.GroupLayout.PREFERRED_SIZE, 383, javax.swing.GroupLayout.PREFERRED_SIZE))
747  .addComponent(scopeLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
748  .addGap(37, 37, 37))
749  .addGroup(jPanel1Layout.createSequentialGroup()
750  .addComponent(percentageThresholdCheck)
751  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
752  .addComponent(percentageThresholdInputBox, javax.swing.GroupLayout.PREFERRED_SIZE, 40, javax.swing.GroupLayout.PREFERRED_SIZE)
753  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
754  .addComponent(percentageThresholdTextTwo, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
755  .addContainerGap())
756  .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup()
757  .addComponent(errorText, javax.swing.GroupLayout.PREFERRED_SIZE, 330, javax.swing.GroupLayout.PREFERRED_SIZE)
758  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
759  .addComponent(searchButton)
760  .addContainerGap())
761  .addGroup(jPanel1Layout.createSequentialGroup()
762  .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
763  .addComponent(containerPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
764  .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
765  .addComponent(commonItemSearchDescription, javax.swing.GroupLayout.Alignment.LEADING)
766  .addGroup(javax.swing.GroupLayout.Alignment.LEADING, jPanel1Layout.createSequentialGroup()
767  .addGap(20, 20, 20)
768  .addComponent(interCaseRadio, javax.swing.GroupLayout.PREFERRED_SIZE, 383, javax.swing.GroupLayout.PREFERRED_SIZE))))
769  .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))))
770  .addGroup(jPanel1Layout.createSequentialGroup()
771  .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
772  .addGroup(jPanel1Layout.createSequentialGroup()
773  .addContainerGap()
774  .addComponent(displayResultsLabel))
775  .addGroup(jPanel1Layout.createSequentialGroup()
776  .addGap(30, 30, 30)
777  .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
778  .addComponent(caseResultsRadioButton, javax.swing.GroupLayout.PREFERRED_SIZE, 410, javax.swing.GroupLayout.PREFERRED_SIZE)
779  .addComponent(countResultsRadioButton, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))))
780  .addGap(10, 10, 10))
781  );
782  jPanel1Layout.setVerticalGroup(
783  jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
784  .addGroup(jPanel1Layout.createSequentialGroup()
785  .addContainerGap()
786  .addComponent(commonItemSearchDescription, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
787  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
788  .addComponent(scopeLabel)
789  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
790  .addComponent(intraCaseRadio)
791  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
792  .addComponent(interCaseRadio)
793  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
794  .addComponent(containerPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
795  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
796  .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
797  .addComponent(percentageThresholdCheck)
798  .addComponent(percentageThresholdInputBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
799  .addComponent(percentageThresholdTextTwo))
800  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
801  .addComponent(displayResultsLabel)
802  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
803  .addComponent(caseResultsRadioButton)
804  .addGap(0, 0, 0)
805  .addComponent(countResultsRadioButton)
806  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
807  .addComponent(dataSourcesLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 14, javax.swing.GroupLayout.PREFERRED_SIZE)
808  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
809  .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
810  .addComponent(searchButton)
811  .addComponent(errorText, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
812  .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
813  );
814 
815  getContentPane().add(jPanel1, java.awt.BorderLayout.CENTER);
816  }// </editor-fold>//GEN-END:initComponents
817 
818  private void formWindowClosed(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_formWindowClosed
819  this.dispose();
820  }//GEN-LAST:event_formWindowClosed
821 
822  private void percentageThresholdCheckActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_percentageThresholdCheckActionPerformed
823  if (this.percentageThresholdCheck.isSelected()) {
824  this.percentageThresholdInputBox.setEnabled(true);
825  } else {
826  this.percentageThresholdInputBox.setEnabled(false);
827  }
828 
829  this.handleFrequencyPercentageState();
830  }//GEN-LAST:event_percentageThresholdCheckActionPerformed
831 
832  private void interCaseRadioActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_interCaseRadioActionPerformed
833  switchInnerPanel(interCasePanel);
834  }//GEN-LAST:event_interCaseRadioActionPerformed
835 
836  private void intraCaseRadioActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_intraCaseRadioActionPerformed
837  switchInnerPanel(intraCasePanel);
838  }//GEN-LAST:event_intraCaseRadioActionPerformed
839 
840  private void searchButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_searchButtonActionPerformed
841  checkDataSourcesAndSearch();
842  this.dispose();
843  }//GEN-LAST:event_searchButtonActionPerformed
844 
845  private void caseResultsRadioButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_caseResultsRadioButtonActionPerformed
846  // TODO add your handling code here:
847  }//GEN-LAST:event_caseResultsRadioButtonActionPerformed
848 
863  @Messages({"CommonAttributePanel.incompleteResults.introText=Results may be incomplete. Not all data sources in the current case were ingested into the current Central Repository. The following data sources have not been processed:",
864  "CommonAttributePanel.incompleteResults.continueText=\n\n Continue with search anyway?",
865  "CommonAttributePanel.incompleteResults.title=Search may be incomplete"
866  })
867  private void checkDataSourcesAndSearch() {
868  new SwingWorker<List<String>, Void>() {
869 
870  @Override
871  protected List<String> doInBackground() throws Exception {
872  List<String> unCorrelatedDataSources = new ArrayList<>();
873  if (!interCaseRadio.isSelected() || !EamDb.isEnabled() || EamDb.getInstance() == null) {
874  return unCorrelatedDataSources;
875  }
876  //if the eamdb is enabled and an instance is able to be retrieved check if each data source has been processed into the cr
877  HashMap<DataSource, CorrelatedStatus> dataSourceCorrelationMap = new HashMap<>(); //keep track of the status of all data sources that have been ingested
878  String correlationEngineModuleName = CentralRepoIngestModuleFactory.getModuleName();
879  SleuthkitCase skCase = Case.getCurrentCaseThrows().getSleuthkitCase();
880  List<CorrelationDataSource> correlatedDataSources = EamDb.getInstance().getDataSources();
881  List<IngestJobInfo> ingestJobs = skCase.getIngestJobs();
882  for (IngestJobInfo jobInfo : ingestJobs) {
883  //get the data source for each ingest job
884  DataSource dataSource = skCase.getDataSource(jobInfo.getObjectId());
885  String deviceID = dataSource.getDeviceId();
886  //add its status as not_correlated for now if this is the first time the data source was processed
887  dataSourceCorrelationMap.putIfAbsent(dataSource, CorrelatedStatus.NOT_CORRELATED);
888  if (dataSourceCorrelationMap.get(dataSource) == CorrelatedStatus.NOT_CORRELATED) {
889  //if the datasource was previously processed we do not need to perform this check
890  for (CorrelationDataSource correlatedDataSource : correlatedDataSources) {
891  if (deviceID.equals(correlatedDataSource.getDeviceID())) {
892  //if the datasource exists in the central repository it may of been processed with the correlation engine
893  dataSourceCorrelationMap.put(dataSource, CorrelatedStatus.IN_CENTRAL_REPO);
894  break;
895  }
896  }
897  }
898  if (dataSourceCorrelationMap.get(dataSource) == CorrelatedStatus.IN_CENTRAL_REPO) {
899  //if the data source was in the central repository check if any of the modules run on it were the correlation engine
900  for (IngestModuleInfo ingestModuleInfo : jobInfo.getIngestModuleInfo()) {
901  if (correlationEngineModuleName.equals(ingestModuleInfo.getDisplayName())) {
902  dataSourceCorrelationMap.put(dataSource, CorrelatedStatus.CORRELATED);
903  break;
904  }
905  }
906  }
907  }
908  //convert the keys of the map which have not been correlated to a list
909  for (DataSource dataSource : dataSourceCorrelationMap.keySet()) {
910  if (dataSourceCorrelationMap.get(dataSource) != CorrelatedStatus.CORRELATED) {
911  unCorrelatedDataSources.add(dataSource.getName());
912  }
913  }
914  return unCorrelatedDataSources;
915  }
916 
917  @Override
918  protected void done() {
919  super.done();
920  try {
921  List<String> unProcessedDataSources = get();
922  boolean performSearch = true;
923  if (!unProcessedDataSources.isEmpty()) {
924  String warning = Bundle.CommonAttributePanel_incompleteResults_introText();
925  warning = unProcessedDataSources.stream().map((dataSource) -> "\n - " + dataSource).reduce(warning, String::concat);
926  warning += Bundle.CommonAttributePanel_incompleteResults_continueText();
927  //let user know which data sources in the current case were not processed into a central repository
928  NotifyDescriptor descriptor = new NotifyDescriptor.Confirmation(warning, Bundle.CommonAttributePanel_incompleteResults_title(), NotifyDescriptor.YES_NO_OPTION);
929  performSearch = DialogDisplayer.getDefault().notify(descriptor) == NotifyDescriptor.YES_OPTION;
930  }
931  if (performSearch) {
932  if (interCaseRadio.isSelected() && caseResultsRadioButton.isSelected()) {
933  searchByCase();
934  } else {
935  searchByCount();
936  }
937  }
938  } catch (InterruptedException | ExecutionException ex) {
939  LOGGER.log(Level.SEVERE, "Unexpected exception while looking for common properties", ex); //NON-NLS
940  }
941  }
942  }.execute();
943  }
944 
949  private void percentageThresholdChanged() {
950  String percentageString = this.percentageThresholdInputBox.getText();
951 
952  try {
953  this.percentageThresholdValue = Integer.parseInt(percentageString);
954 
955  } catch (NumberFormatException ignored) {
956  this.percentageThresholdValue = -1;
957  }
958 
959  this.handleFrequencyPercentageState();
960  }
961 
966  private void updateErrorTextAndSearchButton() {
967  if (this.errorManager.anyErrors()) {
968  this.searchButton.setEnabled(false);
969  //grab the first error error and show it
970  this.errorText.setText(this.errorManager.getErrors().get(0));
971  this.errorText.setVisible(true);
972  } else {
973  this.searchButton.setEnabled(true);
974  this.errorText.setVisible(false);
975  }
976  }
977 
985  @NbBundle.Messages({
986  "# {0} - number of datasources",
987  "CommonAttributePanel.dataSourcesLabel.text=The current Central Repository contains {0} data source(s)."})
988  private void updatePercentageOptions(Long numberOfDataSources) {
989  boolean enabled = numberOfDataSources > 0L;
990  String numberOfDataSourcesText = enabled ? Bundle.CommonAttributePanel_dataSourcesLabel_text(numberOfDataSources) : "";
991  this.dataSourcesLabel.setText(numberOfDataSourcesText);
992  this.percentageThresholdInputBox.setEnabled(enabled);
993  this.percentageThresholdCheck.setEnabled(enabled);
994  this.percentageThresholdCheck.setSelected(enabled);
995  this.percentageThresholdTextTwo.setEnabled(enabled);
996 
997  }
998 
1004  private void handleFrequencyPercentageState() {
1005  if (this.percentageThresholdValue > 0 && this.percentageThresholdValue <= 100) {
1006  this.errorManager.setError(UserInputErrorManager.FREQUENCY_PERCENTAGE_OUT_OF_RANGE_KEY, false);
1007  } else {
1008 
1009  this.errorManager.setError(UserInputErrorManager.FREQUENCY_PERCENTAGE_OUT_OF_RANGE_KEY, true);
1010  }
1011  this.updateErrorTextAndSearchButton();
1012  }
1013 
1014  // Variables declaration - do not modify//GEN-BEGIN:variables
1015  private javax.swing.JRadioButton caseResultsRadioButton;
1016  private javax.swing.JLabel commonItemSearchDescription;
1017  private javax.swing.JPanel containerPanel;
1018  private javax.swing.JRadioButton countResultsRadioButton;
1019  private javax.swing.JLabel dataSourcesLabel;
1020  private javax.swing.ButtonGroup displayResultsButtonGroup;
1021  private javax.swing.JLabel displayResultsLabel;
1022  private javax.swing.JLabel errorText;
1023  private javax.swing.JRadioButton interCaseRadio;
1024  private javax.swing.ButtonGroup interIntraButtonGroup;
1025  private javax.swing.JRadioButton intraCaseRadio;
1026  private javax.swing.JPanel jPanel1;
1027  private javax.swing.JCheckBox percentageThresholdCheck;
1028  private javax.swing.JTextField percentageThresholdInputBox;
1029  private javax.swing.JLabel percentageThresholdTextTwo;
1030  private javax.swing.JLabel scopeLabel;
1031  private javax.swing.JButton searchButton;
1032  // End of variables declaration//GEN-END:variables
1033 
1038  void observeSubPanels() {
1039  intraCasePanel.addObserver(this);
1040  interCasePanel.addObserver(this);
1041  }
1042 
1048  private void checkFileTypeCheckBoxState() {
1049  boolean validCheckBoxState = true;
1050  if (CommonAttributePanel.this.interCaseRadio.isSelected()) {
1051  if (interCasePanel.fileCategoriesButtonIsSelected()) {
1052  validCheckBoxState = interCasePanel.pictureVideoCheckboxIsSelected() || interCasePanel.documentsCheckboxIsSelected();
1053  }
1054  } else {
1055  if (intraCasePanel.fileCategoriesButtonIsSelected()) {
1056  validCheckBoxState = intraCasePanel.pictureVideoCheckboxIsSelected() || intraCasePanel.documentsCheckboxIsSelected();
1057  }
1058  }
1059  if (validCheckBoxState) {
1060  this.errorManager.setError(UserInputErrorManager.NO_FILE_CATEGORIES_SELECTED_KEY, false);
1061  } else {
1062  this.errorManager.setError(UserInputErrorManager.NO_FILE_CATEGORIES_SELECTED_KEY, true);
1063  }
1064  this.updateErrorTextAndSearchButton();
1065  }
1066 
1071  private enum CorrelatedStatus {
1074  CORRELATED
1075  }
1076 }

Copyright © 2012-2018 Basis Technology. Generated on: Tue Dec 18 2018
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.