19 package org.sleuthkit.autopsy.commonpropertiessearch;
 
   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;
 
   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;
 
   73 @SuppressWarnings(
"PMD.SingularField") 
 
   74 final class CommonAttributePanel extends javax.swing.JDialog implements Observer {
 
   76     private static final Logger LOGGER = Logger.getLogger(CommonAttributePanel.class.getName());
 
   77     private static final long serialVersionUID = 1L;
 
   79     private static final Long NO_DATA_SOURCE_SELECTED = -1L;
 
   81     private final UserInputErrorManager errorManager;
 
   83     private int percentageThresholdValue = 20;
 
   85     private final IntraCasePanel intraCasePanel;
 
   86     private final InterCasePanel interCasePanel;
 
   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);
 
   99         this.setLocationRelativeTo(WindowManager.getDefault().getMainWindow());
 
  101         interCasePanel = 
new InterCasePanel();
 
  102         interCasePanel.setVisible(
true);
 
  103         interCasePanel.setSize((
int) containerPanel.getPreferredSize().getWidth(), (int) containerPanel.getPreferredSize().getHeight());
 
  105         intraCasePanel = 
new IntraCasePanel();
 
  106         intraCasePanel.setVisible(
true);
 
  107         intraCasePanel.setSize((
int) containerPanel.getPreferredSize().getWidth(), (int) containerPanel.getPreferredSize().getHeight());
 
  109         this.setupDataSources();
 
  111         if (CommonAttributePanel.isEamDbAvailableForIntercaseSearch()) {
 
  113             this.interCasePanel.setupCorrelationTypeFilter();
 
  114             this.interCaseRadio.setSelected(
true);
 
  115             switchInnerPanel(interCasePanel);
 
  117             this.disableIntercaseSearch();
 
  118             this.intraCaseRadio.setSelected(
true);
 
  119             switchInnerPanel(intraCasePanel);
 
  124         this.updatePercentageOptions(CommonAttributePanel.getNumberOfDataSourcesAvailable());
 
  126         this.errorManager = 
new UserInputErrorManager();
 
  128         this.percentageThresholdInputBox.getDocument().addDocumentListener(
new DocumentListener() {
 
  130             private final Dimension preferredSize = CommonAttributePanel.this.percentageThresholdInputBox.getPreferredSize();
 
  132             private void maintainSize() {
 
  133                 CommonAttributePanel.this.percentageThresholdInputBox.setSize(preferredSize);
 
  137             public void insertUpdate(DocumentEvent event) {
 
  139                 CommonAttributePanel.this.percentageThresholdChanged();
 
  143             public void removeUpdate(DocumentEvent event) {
 
  145                 CommonAttributePanel.this.percentageThresholdChanged();
 
  149             public void changedUpdate(DocumentEvent event) {
 
  151                 CommonAttributePanel.this.percentageThresholdChanged();
 
  163     static boolean isEamDbAvailableForIntercaseSearch() {
 
  165             return CentralRepository.isEnabled()
 
  166                     && CentralRepository.getInstance() != null
 
  167                     && CentralRepository.getInstance().getCases().size() > 1
 
  169                     && Case.getCurrentCase() != null
 
  170                     && CentralRepository.getInstance().getCase(Case.getCurrentCase()) != null;
 
  171         } 
catch (CentralRepoException ex) {
 
  172             LOGGER.log(Level.SEVERE, 
"Unexpected exception while  checking for EamDB enabled.", ex);
 
  178     public void update(Observable o, Object arg) {
 
  179         checkFileTypeCheckBoxState();
 
  189     private static Long getNumberOfDataSourcesAvailable() {
 
  191             if (CentralRepository.isEnabled()
 
  192                     && CentralRepository.getInstance() != null) {
 
  193                 return CentralRepository.getInstance().getCountUniqueDataSources();
 
  195         } 
catch (CentralRepoException ex) {
 
  196             LOGGER.log(Level.SEVERE, 
"Unexpected exception while  checking for EamDB enabled.", ex);
 
  205     private void disableIntercaseSearch() {
 
  206         this.intraCaseRadio.setSelected(
true);
 
  207         this.interCaseRadio.setEnabled(
false);
 
  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>() {
 
  226             private String tabTitle;
 
  227             private ProgressHandle progress;
 
  230             protected CommonAttributeCountSearchResults doInBackground() throws TskCoreException, NoCurrentCaseException, SQLException, CentralRepoException {
 
  231                 progress = ProgressHandle.createHandle(Bundle.CommonAttributePanel_search_done_searchProgressGathering());
 
  233                 progress.switchToIndeterminate();
 
  235                 Long dataSourceId = intraCasePanel.getSelectedDataSourceId();
 
  236                 Integer caseId = interCasePanel.getSelectedCaseId();
 
  238                 AbstractCommonAttributeSearcher builder;
 
  239                 CommonAttributeCountSearchResults metadata;
 
  241                 boolean filterByMedia = 
false;
 
  242                 boolean filterByDocuments = 
false;
 
  244                 int percentageThreshold = CommonAttributePanel.this.percentageThresholdValue;
 
  246                 if (!CommonAttributePanel.this.percentageThresholdCheck.isSelected()) {
 
  248                     percentageThreshold = 0;
 
  251                 if (CommonAttributePanel.this.interCaseRadio.isSelected()) {
 
  252                     CorrelationAttributeInstance.Type corType = interCasePanel.getSelectedCorrelationType();
 
  253                     if (interCasePanel.fileCategoriesButtonIsSelected()) {
 
  254                         filterByMedia = interCasePanel.pictureVideoCheckboxIsSelected();
 
  255                         filterByDocuments = interCasePanel.documentsCheckboxIsSelected();
 
  257                     if (corType == null) {
 
  258                         corType = CentralRepository.getInstance().getDefinedCorrelationTypes().get(0);
 
  260                     if (caseId == InterCasePanel.NO_CASE_SELECTED) {
 
  261                         builder = 
new AllInterCaseCommonAttributeSearcher(filterByMedia, filterByDocuments, corType, percentageThreshold);
 
  264                         builder = 
new SingleInterCaseCommonAttributeSearcher(caseId, filterByMedia, filterByDocuments, corType, percentageThreshold);
 
  268                     if (intraCasePanel.fileCategoriesButtonIsSelected()) {
 
  269                         filterByMedia = intraCasePanel.pictureVideoCheckboxIsSelected();
 
  270                         filterByDocuments = intraCasePanel.documentsCheckboxIsSelected();
 
  272                     if (Objects.equals(dataSourceId, CommonAttributePanel.NO_DATA_SOURCE_SELECTED)) {
 
  273                         builder = 
new AllIntraCaseCommonAttributeSearcher(intraCasePanel.getDataSourceMap(), filterByMedia, filterByDocuments, percentageThreshold);
 
  275                         builder = 
new SingleIntraCaseCommonAttributeSearcher(dataSourceId, intraCasePanel.getDataSourceMap(), filterByMedia, filterByDocuments, percentageThreshold);
 
  279                 metadata = builder.findMatchesByCount();
 
  280                 metadata.filterMetadata();
 
  281                 this.tabTitle = builder.getTabTitle();
 
  286             protected void done() {
 
  289                     CommonAttributeCountSearchResults metadata = this.
get();
 
  290                     boolean noKeysExist = metadata.getMetadata().keySet().isEmpty();
 
  292                         Node commonFilesNode = 
new TableFilterNode(
new EmptyNode(Bundle.CommonAttributePanel_search_done_noResults()), 
true);
 
  293                         progress.setDisplayName(Bundle.CommonAttributePanel_search_done_searchProgressDisplay());
 
  294                         DataResultTopComponent.createInstance(tabTitle, Bundle.CommonAttributePanel_search_results_pathText(), commonFilesNode, 1);
 
  297                         CorrelationAttributeInstance.Type correlationType = null;
 
  298                         if (interCaseRadio.isSelected()){
 
  299                             correlationType = interCasePanel.getSelectedCorrelationType();
 
  301                         Node commonFilesNode = 
new CommonAttributeSearchResultRootNode(metadata, correlationType);
 
  302                         DataResultFilterNode dataResultFilterNode = 
new DataResultFilterNode(commonFilesNode, ExplorerManager.find(CommonAttributePanel.this));
 
  303                         TableFilterNode tableFilterWithDescendantsNode = 
new TableFilterNode(dataResultFilterNode, 3);
 
  304                         DataResultViewerTable table = 
new CommonAttributesSearchResultsViewerTable();
 
  305                         Collection<DataResultViewer> viewers = 
new ArrayList<>(1);
 
  307                         progress.setDisplayName(Bundle.CommonAttributePanel_search_done_searchProgressDisplay());
 
  308                         DataResultTopComponent.createInstance(tabTitle, Bundle.CommonAttributePanel_search_results_pathText(), tableFilterWithDescendantsNode, metadata.size(), viewers);
 
  311                 } 
catch (InterruptedException ex) {
 
  312                     LOGGER.log(Level.SEVERE, 
"Interrupted while loading Common Files", ex);
 
  313                     MessageNotifyUtil.Message.error(Bundle.CommonAttributePanel_search_done_interupted());
 
  314                 } 
catch (ExecutionException ex) {
 
  316                     Throwable inner = ex.getCause();
 
  317                     if (inner instanceof TskCoreException) {
 
  318                         LOGGER.log(Level.SEVERE, 
"Failed to load files from database.", ex);
 
  319                         errorMessage = Bundle.CommonAttributePanel_search_done_tskCoreException();
 
  320                     } 
else if (inner instanceof NoCurrentCaseException) {
 
  321                         LOGGER.log(Level.SEVERE, 
"Current case has been closed.", ex);
 
  322                         errorMessage = Bundle.CommonAttributePanel_search_done_noCurrentCaseException();
 
  323                     } 
else if (inner instanceof SQLException) {
 
  324                         LOGGER.log(Level.SEVERE, 
"Unable to query db for files.", ex);
 
  325                         errorMessage = Bundle.CommonAttributePanel_search_done_sqlException();
 
  327                         LOGGER.log(Level.SEVERE, 
"Unexpected exception while running Common Files Search.", ex);
 
  328                         errorMessage = Bundle.CommonAttributePanel_search_done_exception();
 
  330                     MessageNotifyUtil.Message.error(errorMessage);
 
  341     private void searchByCase() {
 
  342         new SwingWorker<CommonAttributeCaseSearchResults, Void>() {
 
  343             private String tabTitle;
 
  344             private ProgressHandle progress;
 
  347             protected CommonAttributeCaseSearchResults doInBackground() throws TskCoreException, NoCurrentCaseException, SQLException, CentralRepoException {
 
  348                 progress = ProgressHandle.createHandle(Bundle.CommonAttributePanel_search_done_searchProgressGathering());
 
  350                 progress.switchToIndeterminate();
 
  351                 Long dataSourceId = intraCasePanel.getSelectedDataSourceId();
 
  352                 Integer caseId = interCasePanel.getSelectedCaseId();
 
  353                 AbstractCommonAttributeSearcher builder;
 
  354                 CommonAttributeCaseSearchResults metadata;
 
  355                 boolean filterByMedia = 
false;
 
  356                 boolean filterByDocuments = 
false;
 
  357                 int percentageThreshold = CommonAttributePanel.this.percentageThresholdValue;
 
  358                 if (!CommonAttributePanel.this.percentageThresholdCheck.isSelected()) {
 
  360                     percentageThreshold = 0;
 
  362                 if (CommonAttributePanel.this.interCaseRadio.isSelected()) {
 
  363                     CorrelationAttributeInstance.Type corType = interCasePanel.getSelectedCorrelationType();
 
  364                     if (interCasePanel.fileCategoriesButtonIsSelected()) {
 
  365                         filterByMedia = interCasePanel.pictureVideoCheckboxIsSelected();
 
  366                         filterByDocuments = interCasePanel.documentsCheckboxIsSelected();
 
  368                     if (corType == null) {
 
  369                         corType = CentralRepository.getInstance().getDefinedCorrelationTypes().get(0);
 
  371                     if (caseId == InterCasePanel.NO_CASE_SELECTED) {
 
  372                         builder = 
new AllInterCaseCommonAttributeSearcher(filterByMedia, filterByDocuments, corType, percentageThreshold);
 
  374                         builder = 
new SingleInterCaseCommonAttributeSearcher(caseId, filterByMedia, filterByDocuments, corType, percentageThreshold);
 
  377                     if (intraCasePanel.fileCategoriesButtonIsSelected()) {
 
  378                         filterByMedia = intraCasePanel.pictureVideoCheckboxIsSelected();
 
  379                         filterByDocuments = intraCasePanel.documentsCheckboxIsSelected();
 
  381                     if (Objects.equals(dataSourceId, CommonAttributePanel.NO_DATA_SOURCE_SELECTED)) {
 
  382                         builder = 
new AllIntraCaseCommonAttributeSearcher(intraCasePanel.getDataSourceMap(), filterByMedia, filterByDocuments, percentageThreshold);
 
  384                         builder = 
new SingleIntraCaseCommonAttributeSearcher(dataSourceId, intraCasePanel.getDataSourceMap(), filterByMedia, filterByDocuments, percentageThreshold);
 
  387                 metadata = builder.findMatchesByCase();
 
  388                 this.tabTitle = builder.getTabTitle();
 
  393             protected void done() {
 
  396                     CommonAttributeCaseSearchResults metadata = this.
get();
 
  397                     if (metadata.getMetadata().keySet().isEmpty()) {
 
  398                         Node commonFilesNode = 
new TableFilterNode(
new EmptyNode(Bundle.CommonAttributePanel_search_done_noResults()), 
true);
 
  399                         progress.setDisplayName(Bundle.CommonAttributePanel_search_done_searchProgressDisplay());
 
  400                         DataResultTopComponent.createInstance(tabTitle, Bundle.CommonAttributePanel_search_results_pathText(), commonFilesNode, 1);
 
  403                         Node commonFilesNode = 
new CommonAttributeSearchResultRootNode(metadata);
 
  404                         DataResultFilterNode dataResultFilterNode = 
new DataResultFilterNode(commonFilesNode, ExplorerManager.find(CommonAttributePanel.this));
 
  405                         TableFilterNode tableFilterWithDescendantsNode = 
new TableFilterNode(dataResultFilterNode, 3);
 
  406                         DataResultViewerTable table = 
new CommonAttributesSearchResultsViewerTable();
 
  407                         Collection<DataResultViewer> viewers = 
new ArrayList<>(1);
 
  409                         progress.setDisplayName(Bundle.CommonAttributePanel_search_done_searchProgressDisplay());
 
  411                         DataResultTopComponent.createInstance(tabTitle, Bundle.CommonAttributePanel_search_results_pathText(), tableFilterWithDescendantsNode, 0, viewers);
 
  413                 } 
catch (InterruptedException ex) {
 
  414                     LOGGER.log(Level.SEVERE, 
"Interrupted while loading Common Files", ex);
 
  415                     MessageNotifyUtil.Message.error(Bundle.CommonAttributePanel_search_done_interupted());
 
  416                 } 
catch (ExecutionException ex) {
 
  418                     Throwable inner = ex.getCause();
 
  419                     if (inner instanceof TskCoreException) {
 
  420                         LOGGER.log(Level.SEVERE, 
"Failed to load files from database.", ex);
 
  421                         errorMessage = Bundle.CommonAttributePanel_search_done_tskCoreException();
 
  422                     } 
else if (inner instanceof NoCurrentCaseException) {
 
  423                         LOGGER.log(Level.SEVERE, 
"Current case has been closed.", ex);
 
  424                         errorMessage = Bundle.CommonAttributePanel_search_done_noCurrentCaseException();
 
  425                     } 
else if (inner instanceof SQLException) {
 
  426                         LOGGER.log(Level.SEVERE, 
"Unable to query db for files.", ex);
 
  427                         errorMessage = Bundle.CommonAttributePanel_search_done_sqlException();
 
  429                         LOGGER.log(Level.SEVERE, 
"Unexpected exception while running Common Files Search.", ex);
 
  430                         errorMessage = Bundle.CommonAttributePanel_search_done_exception();
 
  432                     MessageNotifyUtil.Message.error(errorMessage);
 
  448         "CommonAttributePanel.setupDataSources.done.tskCoreException=Unable to run query against DB.",
 
  449         "CommonAttributePanel.setupDataSources.done.noCurrentCaseException=Unable to open case file.",
 
  450         "CommonAttributePanel.setupDataSources.done.exception=Unexpected exception loading data sources.",
 
  451         "CommonAttributePanel.setupDataSources.done.interupted=Something went wrong building the Common Files Search dialog box.",
 
  452         "CommonAttributePanel.setupDataSources.done.sqlException=Unable to query db for data sources.",
 
  453         "CommonAttributePanel.setupDataSources.updateUi.noDataSources=No data sources were found."})
 
  455     private void setupDataSources() {
 
  457         new SwingWorker<Map<Long, String>, Void>() {
 
  463             private void updateUi() {
 
  465                 final Map<Long, String> dataSourceMap = CommonAttributePanel.this.intraCasePanel.getDataSourceMap();
 
  467                 String[] dataSourcesNames = 
new String[dataSourceMap.size()];
 
  470                 if (dataSourcesNames.length > 0) {
 
  471                     dataSourcesNames = dataSourceMap.values().toArray(dataSourcesNames);
 
  472                     CommonAttributePanel.this.intraCasePanel.setDatasourceComboboxModel(
new DataSourceComboBoxModel(dataSourcesNames));
 
  474                     if (!this.caseHasMultipleSources()) { 
 
  475                         intraCaseRadio.setEnabled(
false);
 
  476                         interCaseRadio.setSelected(
true);
 
  478                     CommonAttributePanel.this.updateErrorTextAndSearchButton();
 
  488             private boolean caseHasMultipleSources() {
 
  489                 return CommonAttributePanel.this.intraCasePanel.getDataSourceMap().size() > 1;
 
  493             protected Map<Long, String> doInBackground() throws NoCurrentCaseException, TskCoreException, SQLException {
 
  494                 return DataSourceLoader.getAllDataSources();
 
  498             protected void done() {
 
  501                     CommonAttributePanel.this.intraCasePanel.setDataSourceMap(this.
get());
 
  504                 } 
catch (InterruptedException ex) {
 
  505                     LOGGER.log(Level.SEVERE, 
"Interrupted while building Common Files Search dialog.", ex);
 
  506                     MessageNotifyUtil.Message.error(Bundle.CommonAttributePanel_setupDataSources_done_interupted());
 
  507                 } 
catch (ExecutionException ex) {
 
  509                     Throwable inner = ex.getCause();
 
  510                     if (inner instanceof TskCoreException) {
 
  511                         LOGGER.log(Level.SEVERE, 
"Failed to load data sources from database.", ex);
 
  512                         errorMessage = Bundle.CommonAttributePanel_setupDataSources_done_tskCoreException();
 
  513                     } 
else if (inner instanceof NoCurrentCaseException) {
 
  514                         LOGGER.log(Level.SEVERE, 
"Current case has been closed.", ex);
 
  515                         errorMessage = Bundle.CommonAttributePanel_setupDataSources_done_noCurrentCaseException();
 
  516                     } 
else if (inner instanceof SQLException) {
 
  517                         LOGGER.log(Level.SEVERE, 
"Unable to query db for data sources.", ex);
 
  518                         errorMessage = Bundle.CommonAttributePanel_setupDataSources_done_sqlException();
 
  520                         LOGGER.log(Level.SEVERE, 
"Unexpected exception while building Common Files Search dialog panel.", ex);
 
  521                         errorMessage = Bundle.CommonAttributePanel_setupDataSources_done_exception();
 
  523                     MessageNotifyUtil.Message.error(errorMessage);
 
  534     private void switchInnerPanel(JPanel panel) {
 
  535         containerPanel.removeAll();
 
  536         containerPanel.add(panel);
 
  537         caseResultsRadioButton.setVisible(this.interCaseRadio.isSelected());
 
  538         countResultsRadioButton.setVisible(this.interCaseRadio.isSelected());
 
  539         displayResultsLabel.setVisible(this.interCaseRadio.isSelected());
 
  545         "CommonAttributePanel.setupCases.done.interruptedException=Something went wrong building the Common Files Search dialog box.",
 
  546         "CommonAttributePanel.setupCases.done.exeutionException=Unexpected exception loading cases."})
 
  547     private void setupCases() {
 
  549         new SwingWorker<Map<Integer, String>, Void>() {
 
  555             private void updateUi() {
 
  557                 final Map<Integer, String> caseMap = CommonAttributePanel.this.interCasePanel.getCaseMap();
 
  559                 String[] caseNames = 
new String[caseMap.size()];
 
  561                 if (caseNames.length > 0) {
 
  562                     caseNames = caseMap.values().toArray(caseNames);
 
  563                     CommonAttributePanel.this.interCasePanel.setCaseComboboxModel(
new DataSourceComboBoxModel(caseNames));
 
  565                     CommonAttributePanel.this.disableIntercaseSearch();
 
  578             private Map<Integer, String> mapCases(List<CorrelationCase> cases) 
throws CentralRepoException {
 
  579                 Map<Integer, String> casemap = 
new HashMap<>();
 
  580                 CorrelationCase currentCorCase = CentralRepository.getInstance().getCase(Case.getCurrentCase());
 
  581                 for (CorrelationCase correlationCase : cases) {
 
  582                     if (currentCorCase.getID() != correlationCase.getID()) { 
 
  583                         casemap.put(correlationCase.getID(), correlationCase.getDisplayName());
 
  590             protected Map<Integer, String> doInBackground() throws CentralRepoException {
 
  592                 List<CorrelationCase> dataSources = CentralRepository.getInstance().getCases();
 
  593                 Map<Integer, String> caseMap = mapCases(dataSources);
 
  599             protected void done() {
 
  601                     Map<Integer, String> cases = this.
get();
 
  602                     CommonAttributePanel.this.interCasePanel.setCaseMap(cases);
 
  604                 } 
catch (InterruptedException ex) {
 
  605                     LOGGER.log(Level.SEVERE, 
"Interrupted while building Common Files Search dialog.", ex);
 
  606                     MessageNotifyUtil.Message.error(Bundle.CommonAttributePanel_setupCases_done_interruptedException());
 
  607                 } 
catch (ExecutionException ex) {
 
  608                     LOGGER.log(Level.SEVERE, 
"Unexpected exception while building Common Files Search dialog.", ex);
 
  609                     MessageNotifyUtil.Message.error(Bundle.CommonAttributePanel_setupCases_done_exeutionException());
 
  621     @SuppressWarnings(
"unchecked")
 
  623     private 
void initComponents() {
 
  625         interIntraButtonGroup = 
new javax.swing.ButtonGroup();
 
  626         displayResultsButtonGroup = 
new javax.swing.ButtonGroup();
 
  627         jPanel1 = 
new javax.swing.JPanel();
 
  628         commonItemSearchDescription = 
new javax.swing.JLabel();
 
  629         scopeLabel = 
new javax.swing.JLabel();
 
  630         intraCaseRadio = 
new javax.swing.JRadioButton();
 
  631         interCaseRadio = 
new javax.swing.JRadioButton();
 
  632         containerPanel = 
new javax.swing.JPanel();
 
  633         percentageThresholdCheck = 
new javax.swing.JCheckBox();
 
  634         percentageThresholdInputBox = 
new javax.swing.JTextField();
 
  635         percentageThresholdTextTwo = 
new javax.swing.JLabel();
 
  636         dataSourcesLabel = 
new javax.swing.JLabel();
 
  637         errorText = 
new javax.swing.JLabel();
 
  638         searchButton = 
new javax.swing.JButton();
 
  639         caseResultsRadioButton = 
new javax.swing.JRadioButton();
 
  640         countResultsRadioButton = 
new javax.swing.JRadioButton();
 
  641         displayResultsLabel = 
new javax.swing.JLabel();
 
  643         setMaximumSize(
new java.awt.Dimension(499, 646));
 
  644         setMinimumSize(
new java.awt.Dimension(499, 646));
 
  646         addWindowListener(
new java.awt.event.WindowAdapter() {
 
  647             public void windowClosed(java.awt.event.WindowEvent evt) {
 
  648                 formWindowClosed(evt);
 
  652         jPanel1.setMaximumSize(
new java.awt.Dimension(499, 646));
 
  653         jPanel1.setMinimumSize(
new java.awt.Dimension(499, 646));
 
  654         jPanel1.setPreferredSize(
new java.awt.Dimension(499, 646));
 
  655         jPanel1.setRequestFocusEnabled(
false);
 
  657         org.openide.awt.Mnemonics.setLocalizedText(commonItemSearchDescription, 
org.openide.util.NbBundle.getMessage(CommonAttributePanel.class, 
"CommonAttributePanel.commonItemSearchDescription.text")); 
 
  658         commonItemSearchDescription.setFocusable(
false);
 
  660         org.openide.awt.Mnemonics.setLocalizedText(scopeLabel, 
org.openide.util.NbBundle.getMessage(CommonAttributePanel.class, 
"CommonAttributePanel.scopeLabel.text")); 
 
  661         scopeLabel.setFocusable(
false);
 
  663         interIntraButtonGroup.add(intraCaseRadio);
 
  664         intraCaseRadio.setSelected(
true);
 
  665         org.openide.awt.Mnemonics.setLocalizedText(intraCaseRadio, 
org.openide.util.NbBundle.getMessage(CommonAttributePanel.class, 
"CommonAttributePanel.intraCaseRadio.text")); 
 
  666         intraCaseRadio.addActionListener(
new java.awt.event.ActionListener() {
 
  667             public void actionPerformed(java.awt.event.ActionEvent evt) {
 
  668                 intraCaseRadioActionPerformed(evt);
 
  672         interIntraButtonGroup.add(interCaseRadio);
 
  673         org.openide.awt.Mnemonics.setLocalizedText(interCaseRadio, 
org.openide.util.NbBundle.getMessage(CommonAttributePanel.class, 
"CommonFilesPanel.jRadioButton2.text")); 
 
  674         interCaseRadio.addActionListener(
new java.awt.event.ActionListener() {
 
  675             public void actionPerformed(java.awt.event.ActionEvent evt) {
 
  676                 interCaseRadioActionPerformed(evt);
 
  680         containerPanel.setBackground(
new java.awt.Color(0, 0, 0));
 
  681         containerPanel.setOpaque(
false);
 
  682         containerPanel.setPreferredSize(
new java.awt.Dimension(477, 326));
 
  684         javax.swing.GroupLayout containerPanelLayout = 
new javax.swing.GroupLayout(containerPanel);
 
  685         containerPanel.setLayout(containerPanelLayout);
 
  686         containerPanelLayout.setHorizontalGroup(
 
  687             containerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 
  688             .addGap(0, 0, Short.MAX_VALUE)
 
  690         containerPanelLayout.setVerticalGroup(
 
  691             containerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 
  692             .addGap(0, 326, Short.MAX_VALUE)
 
  695         org.openide.awt.Mnemonics.setLocalizedText(percentageThresholdCheck, 
org.openide.util.NbBundle.getMessage(CommonAttributePanel.class, 
"CommonAttributePanel.percentageThresholdCheck.text_1_1")); 
 
  696         percentageThresholdCheck.addActionListener(
new java.awt.event.ActionListener() {
 
  697             public void actionPerformed(java.awt.event.ActionEvent evt) {
 
  698                 percentageThresholdCheckActionPerformed(evt);
 
  702         percentageThresholdInputBox.setHorizontalAlignment(javax.swing.JTextField.TRAILING);
 
  703         percentageThresholdInputBox.setText(
org.openide.util.NbBundle.getMessage(CommonAttributePanel.class, 
"CommonAttributePanel.percentageThresholdInputBox.text")); 
 
  704         percentageThresholdInputBox.setMaximumSize(
new java.awt.Dimension(40, 24));
 
  705         percentageThresholdInputBox.setMinimumSize(
new java.awt.Dimension(40, 24));
 
  706         percentageThresholdInputBox.setPreferredSize(
new java.awt.Dimension(40, 24));
 
  708         org.openide.awt.Mnemonics.setLocalizedText(percentageThresholdTextTwo, 
org.openide.util.NbBundle.getMessage(CommonAttributePanel.class, 
"CommonAttributePanel.percentageThresholdTextTwo.text_1")); 
 
  709         percentageThresholdTextTwo.setMaximumSize(
new java.awt.Dimension(260, 16));
 
  711         org.openide.awt.Mnemonics.setLocalizedText(dataSourcesLabel, 
org.openide.util.NbBundle.getMessage(CommonAttributePanel.class, 
"CommonAttributePanel.dataSourcesLabel.text")); 
 
  713         errorText.setForeground(
new java.awt.Color(255, 0, 0));
 
  714         org.openide.awt.Mnemonics.setLocalizedText(errorText, 
org.openide.util.NbBundle.getMessage(CommonAttributePanel.class, 
"CommonAttributePanel.errorText.text")); 
 
  715         errorText.setVerticalAlignment(javax.swing.SwingConstants.TOP);
 
  717         org.openide.awt.Mnemonics.setLocalizedText(searchButton, 
org.openide.util.NbBundle.getMessage(CommonAttributePanel.class, 
"CommonAttributePanel.searchButton.text")); 
 
  718         searchButton.setEnabled(
false);
 
  719         searchButton.setHorizontalTextPosition(javax.swing.SwingConstants.LEADING);
 
  720         searchButton.setMaximumSize(
new java.awt.Dimension(100, 25));
 
  721         searchButton.setMinimumSize(
new java.awt.Dimension(100, 25));
 
  722         searchButton.setPreferredSize(
new java.awt.Dimension(100, 25));
 
  723         searchButton.addActionListener(
new java.awt.event.ActionListener() {
 
  724             public void actionPerformed(java.awt.event.ActionEvent evt) {
 
  725                 searchButtonActionPerformed(evt);
 
  729         displayResultsButtonGroup.add(caseResultsRadioButton);
 
  730         caseResultsRadioButton.setSelected(
true);
 
  731         org.openide.awt.Mnemonics.setLocalizedText(caseResultsRadioButton, 
org.openide.util.NbBundle.getMessage(CommonAttributePanel.class, 
"CommonAttributePanel.caseResultsRadioButton.text")); 
 
  732         caseResultsRadioButton.addActionListener(
new java.awt.event.ActionListener() {
 
  733             public void actionPerformed(java.awt.event.ActionEvent evt) {
 
  734                 caseResultsRadioButtonActionPerformed(evt);
 
  738         displayResultsButtonGroup.add(countResultsRadioButton);
 
  739         org.openide.awt.Mnemonics.setLocalizedText(countResultsRadioButton, 
org.openide.util.NbBundle.getMessage(CommonAttributePanel.class, 
"CommonAttributePanel.countResultsRadioButton.text")); 
 
  741         org.openide.awt.Mnemonics.setLocalizedText(displayResultsLabel, 
org.openide.util.NbBundle.getMessage(CommonAttributePanel.class, 
"CommonAttributePanel.displayResultsLabel.text_2")); 
 
  743         javax.swing.GroupLayout jPanel1Layout = 
new javax.swing.GroupLayout(jPanel1);
 
  744         jPanel1.setLayout(jPanel1Layout);
 
  745         jPanel1Layout.setHorizontalGroup(
 
  746             jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 
  747             .addGroup(jPanel1Layout.createSequentialGroup()
 
  749                 .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 
  750                     .addGroup(jPanel1Layout.createSequentialGroup()
 
  751                         .addComponent(dataSourcesLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
 
  753                     .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup()
 
  754                         .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
 
  755                             .addGroup(jPanel1Layout.createSequentialGroup()
 
  757                                 .addComponent(intraCaseRadio, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
 
  758                             .addComponent(scopeLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
 
  760                     .addGroup(jPanel1Layout.createSequentialGroup()
 
  761                         .addComponent(percentageThresholdCheck, javax.swing.GroupLayout.DEFAULT_SIZE, 184, Short.MAX_VALUE)
 
  763                         .addComponent(percentageThresholdInputBox, javax.swing.GroupLayout.PREFERRED_SIZE, 40, javax.swing.GroupLayout.PREFERRED_SIZE)
 
  764                         .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 
  765                         .addComponent(percentageThresholdTextTwo, javax.swing.GroupLayout.DEFAULT_SIZE, 247, Short.MAX_VALUE)
 
  767                     .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup()
 
  768                         .addComponent(errorText)
 
  770                         .addComponent(searchButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
 
  772                     .addGroup(jPanel1Layout.createSequentialGroup()
 
  773                         .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
 
  774                             .addComponent(commonItemSearchDescription, javax.swing.GroupLayout.Alignment.LEADING)
 
  775                             .addGroup(javax.swing.GroupLayout.Alignment.LEADING, jPanel1Layout.createSequentialGroup()
 
  777                                 .addComponent(interCaseRadio, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
 
  779                     .addGroup(jPanel1Layout.createSequentialGroup()
 
  780                         .addComponent(containerPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
 
  781                         .addContainerGap())))
 
  782             .addGroup(jPanel1Layout.createSequentialGroup()
 
  784                 .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 
  785                     .addGroup(jPanel1Layout.createSequentialGroup()
 
  786                         .addComponent(caseResultsRadioButton, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
 
  788                     .addComponent(countResultsRadioButton, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
 
  790             .addGroup(jPanel1Layout.createSequentialGroup()
 
  792                 .addComponent(displayResultsLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 225, javax.swing.GroupLayout.PREFERRED_SIZE)
 
  793                 .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
 
  795         jPanel1Layout.setVerticalGroup(
 
  796             jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 
  797             .addGroup(jPanel1Layout.createSequentialGroup()
 
  799                 .addComponent(commonItemSearchDescription, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
 
  800                 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
 
  801                 .addComponent(scopeLabel)
 
  802                 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
 
  803                 .addComponent(intraCaseRadio)
 
  804                 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 
  805                 .addComponent(interCaseRadio)
 
  806                 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 
  807                 .addComponent(containerPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
 
  808                 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
 
  809                 .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
 
  810                     .addComponent(percentageThresholdCheck)
 
  811                     .addComponent(percentageThresholdInputBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
 
  812                     .addComponent(percentageThresholdTextTwo, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
 
  813                 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
 
  814                 .addComponent(displayResultsLabel)
 
  815                 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
 
  816                 .addComponent(caseResultsRadioButton)
 
  818                 .addComponent(countResultsRadioButton)
 
  819                 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
 
  820                 .addComponent(dataSourcesLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 14, javax.swing.GroupLayout.PREFERRED_SIZE)
 
  821                 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
 
  822                 .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
 
  823                     .addComponent(searchButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
 
  824                     .addComponent(errorText, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
 
  828         getContentPane().add(jPanel1, java.awt.BorderLayout.CENTER);
 
  831     private void formWindowClosed(java.awt.event.WindowEvent evt) {
 
  835     private void percentageThresholdCheckActionPerformed(java.awt.event.ActionEvent evt) {
 
  836         if (this.percentageThresholdCheck.isSelected()) {
 
  837             this.percentageThresholdInputBox.setEnabled(
true);
 
  839             this.percentageThresholdInputBox.setEnabled(
false);
 
  842         this.handleFrequencyPercentageState();
 
  845     private void interCaseRadioActionPerformed(java.awt.event.ActionEvent evt) {
 
  846         switchInnerPanel(interCasePanel);
 
  849     private void intraCaseRadioActionPerformed(java.awt.event.ActionEvent evt) {
 
  850         switchInnerPanel(intraCasePanel);
 
  853     private void searchButtonActionPerformed(java.awt.event.ActionEvent evt) {
 
  854         checkDataSourcesAndSearch();
 
  858     private void caseResultsRadioButtonActionPerformed(java.awt.event.ActionEvent evt) {
 
  876     @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:",
 
  877         "CommonAttributePanel.incompleteResults.continueText=\n\n Continue with search anyway?",
 
  878         "CommonAttributePanel.incompleteResults.title=Search may be incomplete" 
  880     private void checkDataSourcesAndSearch() {
 
  881         new SwingWorker<List<String>, Void>() {
 
  884             protected List<String> doInBackground() throws Exception {
 
  885                 List<String> unCorrelatedDataSources = 
new ArrayList<>();
 
  886                 if (!interCaseRadio.isSelected() || !CentralRepository.isEnabled() || CentralRepository.getInstance() == null) {
 
  887                     return unCorrelatedDataSources;
 
  890                 HashMap<DataSource, CorrelatedStatus> dataSourceCorrelationMap = 
new HashMap<>(); 
 
  891                 String correlationEngineModuleName = CentralRepoIngestModuleFactory.getModuleName();
 
  892                 SleuthkitCase skCase = Case.getCurrentCaseThrows().getSleuthkitCase();
 
  893                 List<CorrelationDataSource> correlatedDataSources = CentralRepository.getInstance().getDataSources();
 
  894                 List<IngestJobInfo> ingestJobs = skCase.getIngestJobs();
 
  895                 for (IngestJobInfo jobInfo : ingestJobs) {
 
  897                     DataSource dataSource = skCase.getDataSource(jobInfo.getObjectId());
 
  898                     String deviceID = dataSource.getDeviceId();
 
  900                     dataSourceCorrelationMap.putIfAbsent(dataSource, CorrelatedStatus.NOT_CORRELATED);
 
  901                     if (dataSourceCorrelationMap.get(dataSource) == CorrelatedStatus.NOT_CORRELATED) {
 
  903                         for (CorrelationDataSource correlatedDataSource : correlatedDataSources) {
 
  904                             if (deviceID.equals(correlatedDataSource.getDeviceID())) {
 
  906                                 dataSourceCorrelationMap.put(dataSource, CorrelatedStatus.IN_CENTRAL_REPO);
 
  911                     if (dataSourceCorrelationMap.get(dataSource) == CorrelatedStatus.IN_CENTRAL_REPO) {
 
  913                         for (IngestModuleInfo ingestModuleInfo : jobInfo.getIngestModuleInfo()) {
 
  914                             if (correlationEngineModuleName.equals(ingestModuleInfo.getDisplayName())) {
 
  915                                 dataSourceCorrelationMap.put(dataSource, CorrelatedStatus.CORRELATED);
 
  922                 for (DataSource dataSource : dataSourceCorrelationMap.keySet()) {
 
  923                     if (dataSourceCorrelationMap.get(dataSource) != CorrelatedStatus.CORRELATED) {
 
  924                         unCorrelatedDataSources.add(dataSource.getName());
 
  927                 return unCorrelatedDataSources;
 
  931             protected void done() {
 
  934                     List<String> unProcessedDataSources = 
get();
 
  935                     boolean performSearch = 
true;
 
  936                     if (!unProcessedDataSources.isEmpty()) {
 
  937                         String warning = Bundle.CommonAttributePanel_incompleteResults_introText();
 
  938                         warning = unProcessedDataSources.stream().map((dataSource) -> 
"\n  - " + dataSource).reduce(warning, String::concat);
 
  939                         warning += Bundle.CommonAttributePanel_incompleteResults_continueText();
 
  941                         NotifyDescriptor descriptor = 
new NotifyDescriptor.Confirmation(warning, Bundle.CommonAttributePanel_incompleteResults_title(), NotifyDescriptor.YES_NO_OPTION);
 
  942                         performSearch = DialogDisplayer.getDefault().notify(descriptor) == NotifyDescriptor.YES_OPTION;
 
  945                         if (interCaseRadio.isSelected() && caseResultsRadioButton.isSelected()) {
 
  951                 } 
catch (InterruptedException | ExecutionException ex) {
 
  952                     LOGGER.log(Level.SEVERE, 
"Unexpected exception while looking for common properties", ex); 
 
  962     private void percentageThresholdChanged() {
 
  963         String percentageString = this.percentageThresholdInputBox.getText();
 
  966             this.percentageThresholdValue = Integer.parseInt(percentageString);
 
  968         } 
catch (NumberFormatException ignored) {
 
  969             this.percentageThresholdValue = -1;
 
  972         this.handleFrequencyPercentageState();
 
  979     private void updateErrorTextAndSearchButton() {
 
  980         if (this.errorManager.anyErrors()) {
 
  981             this.searchButton.setEnabled(
false);
 
  983             this.errorText.setText(this.errorManager.getErrors().get(0));
 
  984             this.errorText.setVisible(
true);
 
  986             this.searchButton.setEnabled(
true);
 
  987             this.errorText.setVisible(
false);
 
  999         "# {0} - number of datasources",
 
 1000         "CommonAttributePanel.dataSourcesLabel.text=The current Central Repository contains {0} data source(s)."})
 
 1001     private void updatePercentageOptions(Long numberOfDataSources) {
 
 1002         boolean enabled = numberOfDataSources > 0L;
 
 1003         String numberOfDataSourcesText = enabled ? Bundle.CommonAttributePanel_dataSourcesLabel_text(numberOfDataSources) : 
"";
 
 1004         this.dataSourcesLabel.setText(numberOfDataSourcesText);
 
 1005         this.percentageThresholdInputBox.setEnabled(enabled);
 
 1006         this.percentageThresholdCheck.setEnabled(enabled);
 
 1007         this.percentageThresholdCheck.setSelected(enabled);
 
 1008         this.percentageThresholdTextTwo.setEnabled(enabled);
 
 1017     private void handleFrequencyPercentageState() {
 
 1018         if (this.percentageThresholdValue > 0 && this.percentageThresholdValue <= 100) {
 
 1019             this.errorManager.setError(UserInputErrorManager.FREQUENCY_PERCENTAGE_OUT_OF_RANGE_KEY, 
false);
 
 1022             this.errorManager.setError(UserInputErrorManager.FREQUENCY_PERCENTAGE_OUT_OF_RANGE_KEY, 
true);
 
 1024         this.updateErrorTextAndSearchButton();
 
 1028     private javax.swing.JRadioButton caseResultsRadioButton;
 
 1029     private javax.swing.JLabel commonItemSearchDescription;
 
 1030     private javax.swing.JPanel containerPanel;
 
 1031     private javax.swing.JRadioButton countResultsRadioButton;
 
 1032     private javax.swing.JLabel dataSourcesLabel;
 
 1033     private javax.swing.ButtonGroup displayResultsButtonGroup;
 
 1034     private javax.swing.JLabel displayResultsLabel;
 
 1035     private javax.swing.JLabel errorText;
 
 1036     private javax.swing.JRadioButton interCaseRadio;
 
 1037     private javax.swing.ButtonGroup interIntraButtonGroup;
 
 1038     private javax.swing.JRadioButton intraCaseRadio;
 
 1039     private javax.swing.JPanel jPanel1;
 
 1040     private javax.swing.JCheckBox percentageThresholdCheck;
 
 1041     private javax.swing.JTextField percentageThresholdInputBox;
 
 1042     private javax.swing.JLabel percentageThresholdTextTwo;
 
 1043     private javax.swing.JLabel scopeLabel;
 
 1044     private javax.swing.JButton searchButton;
 
 1051     void observeSubPanels() {
 
 1052         intraCasePanel.addObserver(
this);
 
 1053         interCasePanel.addObserver(
this);
 
 1061     private void checkFileTypeCheckBoxState() {
 
 1062         boolean validCheckBoxState = 
true;
 
 1063         if (CommonAttributePanel.this.interCaseRadio.isSelected()) {
 
 1064             if (interCasePanel.fileCategoriesButtonIsSelected()) {
 
 1065                 validCheckBoxState = interCasePanel.pictureVideoCheckboxIsSelected() || interCasePanel.documentsCheckboxIsSelected();
 
 1068             if (intraCasePanel.fileCategoriesButtonIsSelected()) {
 
 1069                 validCheckBoxState = intraCasePanel.pictureVideoCheckboxIsSelected() || intraCasePanel.documentsCheckboxIsSelected();
 
 1072         if (validCheckBoxState) {
 
 1073             this.errorManager.setError(UserInputErrorManager.NO_FILE_CATEGORIES_SELECTED_KEY, 
false);
 
 1075             this.errorManager.setError(UserInputErrorManager.NO_FILE_CATEGORIES_SELECTED_KEY, 
true);
 
 1077         this.updateErrorTextAndSearchButton();