19 package org.sleuthkit.autopsy.commonfilesearch;
 
   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 EamDb.isEnabled()
 
  166                     && EamDb.getInstance() != null
 
  167                     && EamDb.getInstance().getCases().size() > 1
 
  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);
 
  178     public void update(Observable o, Object arg) {
 
  179         checkFileTypeCheckBoxState();
 
  189     private static Long getNumberOfDataSourcesAvailable() {
 
  191             if (EamDb.isEnabled()
 
  192                     && EamDb.getInstance() != null) {
 
  193                 return EamDb.getInstance().getCountUniqueDataSources();
 
  195         } 
catch (EamDbException 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, EamDbException {
 
  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 = CorrelationAttributeInstance.getDefaultCorrelationTypes().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                 this.tabTitle = builder.getTabTitle();
 
  285             protected void done() {
 
  288                     CommonAttributeCountSearchResults metadata = this.
get();
 
  289                     boolean noKeysExist = metadata.getMetadata().keySet().isEmpty();
 
  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);
 
  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);
 
  302                         progress.setDisplayName(Bundle.CommonAttributePanel_search_done_searchProgressDisplay());
 
  303                         DataResultTopComponent.createInstance(tabTitle, Bundle.CommonAttributePanel_search_results_pathText(), tableFilterWithDescendantsNode, metadata.size(), viewers);
 
  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) {
 
  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();
 
  322                         LOGGER.log(Level.SEVERE, 
"Unexpected exception while running Common Files Search.", ex);
 
  323                         errorMessage = Bundle.CommonAttributePanel_search_done_exception();
 
  325                     MessageNotifyUtil.Message.error(errorMessage);
 
  336     private void searchByCase() {
 
  337         new SwingWorker<CommonAttributeCaseSearchResults, Void>() {
 
  338             private String tabTitle;
 
  339             private ProgressHandle progress;
 
  342             protected CommonAttributeCaseSearchResults doInBackground() throws TskCoreException, NoCurrentCaseException, SQLException, EamDbException {
 
  343                 progress = ProgressHandle.createHandle(Bundle.CommonAttributePanel_search_done_searchProgressGathering());
 
  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()) {
 
  355                     percentageThreshold = 0;
 
  357                 if (CommonAttributePanel.this.interCaseRadio.isSelected()) {
 
  358                     CorrelationAttributeInstance.Type corType = interCasePanel.getSelectedCorrelationType();
 
  359                     if (interCasePanel.fileCategoriesButtonIsSelected()) {
 
  360                         filterByMedia = interCasePanel.pictureVideoCheckboxIsSelected();
 
  361                         filterByDocuments = interCasePanel.documentsCheckboxIsSelected();
 
  363                     if (corType == null) {
 
  364                         corType = CorrelationAttributeInstance.getDefaultCorrelationTypes().get(0);
 
  366                     if (caseId == InterCasePanel.NO_CASE_SELECTED) {
 
  367                         builder = 
new AllInterCaseCommonAttributeSearcher(filterByMedia, filterByDocuments, corType, percentageThreshold);
 
  369                         builder = 
new SingleInterCaseCommonAttributeSearcher(caseId, filterByMedia, filterByDocuments, corType, percentageThreshold);
 
  372                     if (intraCasePanel.fileCategoriesButtonIsSelected()) {
 
  373                         filterByMedia = intraCasePanel.pictureVideoCheckboxIsSelected();
 
  374                         filterByDocuments = intraCasePanel.documentsCheckboxIsSelected();
 
  376                     if (Objects.equals(dataSourceId, CommonAttributePanel.NO_DATA_SOURCE_SELECTED)) {
 
  377                         builder = 
new AllIntraCaseCommonAttributeSearcher(intraCasePanel.getDataSourceMap(), filterByMedia, filterByDocuments, percentageThreshold);
 
  379                         builder = 
new SingleIntraCaseCommonAttributeSearcher(dataSourceId, intraCasePanel.getDataSourceMap(), filterByMedia, filterByDocuments, percentageThreshold);
 
  382                 metadata = builder.findMatchesByCase();
 
  383                 this.tabTitle = builder.getTabTitle();
 
  388             protected void 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);
 
  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);
 
  404                         progress.setDisplayName(Bundle.CommonAttributePanel_search_done_searchProgressDisplay());
 
  406                         DataResultTopComponent.createInstance(tabTitle, Bundle.CommonAttributePanel_search_results_pathText(), tableFilterWithDescendantsNode, 0, viewers);
 
  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) {
 
  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();
 
  424                         LOGGER.log(Level.SEVERE, 
"Unexpected exception while running Common Files Search.", ex);
 
  425                         errorMessage = Bundle.CommonAttributePanel_search_done_exception();
 
  427                     MessageNotifyUtil.Message.error(errorMessage);
 
  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."})
 
  450     private void setupDataSources() {
 
  452         new SwingWorker<Map<Long, String>, Void>() {
 
  458             private void updateUi() {
 
  460                 final Map<Long, String> dataSourceMap = CommonAttributePanel.this.intraCasePanel.getDataSourceMap();
 
  462                 String[] dataSourcesNames = 
new String[dataSourceMap.size()];
 
  465                 if (dataSourcesNames.length > 0) {
 
  466                     dataSourcesNames = dataSourceMap.values().toArray(dataSourcesNames);
 
  467                     CommonAttributePanel.this.intraCasePanel.setDatasourceComboboxModel(
new DataSourceComboBoxModel(dataSourcesNames));
 
  469                     if (!this.caseHasMultipleSources()) { 
 
  470                         intraCaseRadio.setEnabled(
false);
 
  471                         interCaseRadio.setSelected(
true);
 
  473                     CommonAttributePanel.this.updateErrorTextAndSearchButton();
 
  483             private boolean caseHasMultipleSources() {
 
  484                 return CommonAttributePanel.this.intraCasePanel.getDataSourceMap().size() > 1;
 
  488             protected Map<Long, String> doInBackground() throws NoCurrentCaseException, TskCoreException, SQLException {
 
  489                 DataSourceLoader loader = 
new DataSourceLoader();
 
  490                 return loader.getDataSourceMap();
 
  494             protected void done() {
 
  497                     CommonAttributePanel.this.intraCasePanel.setDataSourceMap(this.
get());
 
  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) {
 
  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();
 
  516                         LOGGER.log(Level.SEVERE, 
"Unexpected exception while building Common Files Search dialog panel.", ex);
 
  517                         errorMessage = Bundle.CommonAttributePanel_setupDataSources_done_exception();
 
  519                     MessageNotifyUtil.Message.error(errorMessage);
 
  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());
 
  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() {
 
  545         new SwingWorker<Map<Integer, String>, Void>() {
 
  551             private void updateUi() {
 
  553                 final Map<Integer, String> caseMap = CommonAttributePanel.this.interCasePanel.getCaseMap();
 
  555                 String[] caseNames = 
new String[caseMap.size()];
 
  557                 if (caseNames.length > 0) {
 
  558                     caseNames = caseMap.values().toArray(caseNames);
 
  559                     CommonAttributePanel.this.interCasePanel.setCaseComboboxModel(
new DataSourceComboBoxModel(caseNames));
 
  561                     CommonAttributePanel.this.disableIntercaseSearch();
 
  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()) { 
 
  579                         casemap.put(correlationCase.getID(), correlationCase.getDisplayName());
 
  586             protected Map<Integer, String> doInBackground() throws EamDbException {
 
  588                 List<CorrelationCase> dataSources = EamDb.getInstance().getCases();
 
  589                 Map<Integer, String> caseMap = mapCases(dataSources);
 
  595             protected void done() {
 
  597                     Map<Integer, String> cases = this.
get();
 
  598                     CommonAttributePanel.this.interCasePanel.setCaseMap(cases);
 
  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());
 
  617     @SuppressWarnings(
"unchecked")
 
  619     private 
void initComponents() {
 
  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();
 
  639         setMinimumSize(
new java.awt.Dimension(450, 570));
 
  641         addWindowListener(
new java.awt.event.WindowAdapter() {
 
  642             public void windowClosed(java.awt.event.WindowEvent evt) {
 
  643                 formWindowClosed(evt);
 
  647         jPanel1.setMaximumSize(null);
 
  648         jPanel1.setPreferredSize(
new java.awt.Dimension(450, 646));
 
  649         jPanel1.setRequestFocusEnabled(
false);
 
  651         org.openide.awt.Mnemonics.setLocalizedText(commonItemSearchDescription, 
org.openide.util.NbBundle.getMessage(CommonAttributePanel.class, 
"CommonAttributePanel.commonItemSearchDescription.text")); 
 
  652         commonItemSearchDescription.setFocusable(
false);
 
  654         org.openide.awt.Mnemonics.setLocalizedText(scopeLabel, 
org.openide.util.NbBundle.getMessage(CommonAttributePanel.class, 
"CommonAttributePanel.scopeLabel.text")); 
 
  655         scopeLabel.setFocusable(
false);
 
  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")); 
 
  660         intraCaseRadio.addActionListener(
new java.awt.event.ActionListener() {
 
  661             public void actionPerformed(java.awt.event.ActionEvent evt) {
 
  662                 intraCaseRadioActionPerformed(evt);
 
  666         interIntraButtonGroup.add(interCaseRadio);
 
  667         org.openide.awt.Mnemonics.setLocalizedText(interCaseRadio, 
org.openide.util.NbBundle.getMessage(CommonAttributePanel.class, 
"CommonFilesPanel.jRadioButton2.text")); 
 
  668         interCaseRadio.addActionListener(
new java.awt.event.ActionListener() {
 
  669             public void actionPerformed(java.awt.event.ActionEvent evt) {
 
  670                 interCaseRadioActionPerformed(evt);
 
  674         containerPanel.setBackground(
new java.awt.Color(0, 0, 0));
 
  675         containerPanel.setOpaque(
false);
 
  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)
 
  683         containerPanelLayout.setVerticalGroup(
 
  684             containerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 
  685             .addGap(0, 326, Short.MAX_VALUE)
 
  688         org.openide.awt.Mnemonics.setLocalizedText(percentageThresholdCheck, 
org.openide.util.NbBundle.getMessage(CommonAttributePanel.class, 
"CommonAttributePanel.percentageThresholdCheck.text_1_1")); 
 
  689         percentageThresholdCheck.addActionListener(
new java.awt.event.ActionListener() {
 
  690             public void actionPerformed(java.awt.event.ActionEvent evt) {
 
  691                 percentageThresholdCheckActionPerformed(evt);
 
  695         percentageThresholdInputBox.setHorizontalAlignment(javax.swing.JTextField.TRAILING);
 
  696         percentageThresholdInputBox.setText(
org.openide.util.NbBundle.getMessage(CommonAttributePanel.class, 
"CommonAttributePanel.percentageThresholdInputBox.text")); 
 
  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));
 
  701         org.openide.awt.Mnemonics.setLocalizedText(percentageThresholdTextTwo, 
org.openide.util.NbBundle.getMessage(CommonAttributePanel.class, 
"CommonAttributePanel.percentageThresholdTextTwo.text_1")); 
 
  703         org.openide.awt.Mnemonics.setLocalizedText(dataSourcesLabel, 
org.openide.util.NbBundle.getMessage(CommonAttributePanel.class, 
"CommonAttributePanel.dataSourcesLabel.text")); 
 
  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")); 
 
  707         errorText.setVerticalAlignment(javax.swing.SwingConstants.TOP);
 
  709         org.openide.awt.Mnemonics.setLocalizedText(searchButton, 
org.openide.util.NbBundle.getMessage(CommonAttributePanel.class, 
"CommonAttributePanel.searchButton.text")); 
 
  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);
 
  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")); 
 
  721         caseResultsRadioButton.addActionListener(
new java.awt.event.ActionListener() {
 
  722             public void actionPerformed(java.awt.event.ActionEvent evt) {
 
  723                 caseResultsRadioButtonActionPerformed(evt);
 
  727         displayResultsButtonGroup.add(countResultsRadioButton);
 
  728         org.openide.awt.Mnemonics.setLocalizedText(countResultsRadioButton, 
org.openide.util.NbBundle.getMessage(CommonAttributePanel.class, 
"CommonAttributePanel.countResultsRadioButton.text")); 
 
  730         org.openide.awt.Mnemonics.setLocalizedText(displayResultsLabel, 
org.openide.util.NbBundle.getMessage(CommonAttributePanel.class, 
"CommonAttributePanel.displayResultsLabel.text_2")); 
 
  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()
 
  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)
 
  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))
 
  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)
 
  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)
 
  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()
 
  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()
 
  774                         .addComponent(displayResultsLabel))
 
  775                     .addGroup(jPanel1Layout.createSequentialGroup()
 
  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))))
 
  782         jPanel1Layout.setVerticalGroup(
 
  783             jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 
  784             .addGroup(jPanel1Layout.createSequentialGroup()
 
  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)
 
  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))
 
  815         getContentPane().add(jPanel1, java.awt.BorderLayout.CENTER);
 
  818     private void formWindowClosed(java.awt.event.WindowEvent evt) {
 
  822     private void percentageThresholdCheckActionPerformed(java.awt.event.ActionEvent evt) {
 
  823         if (this.percentageThresholdCheck.isSelected()) {
 
  824             this.percentageThresholdInputBox.setEnabled(
true);
 
  826             this.percentageThresholdInputBox.setEnabled(
false);
 
  829         this.handleFrequencyPercentageState();
 
  832     private void interCaseRadioActionPerformed(java.awt.event.ActionEvent evt) {
 
  833         switchInnerPanel(interCasePanel);
 
  836     private void intraCaseRadioActionPerformed(java.awt.event.ActionEvent evt) {
 
  837         switchInnerPanel(intraCasePanel);
 
  840     private void searchButtonActionPerformed(java.awt.event.ActionEvent evt) {
 
  841         checkDataSourcesAndSearch();
 
  845     private void caseResultsRadioButtonActionPerformed(java.awt.event.ActionEvent evt) {
 
  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" 
  867     private void checkDataSourcesAndSearch() {
 
  868         new SwingWorker<List<String>, Void>() {
 
  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;
 
  877                 HashMap<DataSource, CorrelatedStatus> dataSourceCorrelationMap = 
new HashMap<>(); 
 
  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) {
 
  884                     DataSource dataSource = skCase.getDataSource(jobInfo.getObjectId());
 
  885                     String deviceID = dataSource.getDeviceId();
 
  887                     dataSourceCorrelationMap.putIfAbsent(dataSource, CorrelatedStatus.NOT_CORRELATED);
 
  888                     if (dataSourceCorrelationMap.get(dataSource) == CorrelatedStatus.NOT_CORRELATED) {
 
  890                         for (CorrelationDataSource correlatedDataSource : correlatedDataSources) {
 
  891                             if (deviceID.equals(correlatedDataSource.getDeviceID())) {
 
  893                                 dataSourceCorrelationMap.put(dataSource, CorrelatedStatus.IN_CENTRAL_REPO);
 
  898                     if (dataSourceCorrelationMap.get(dataSource) == CorrelatedStatus.IN_CENTRAL_REPO) {
 
  900                         for (IngestModuleInfo ingestModuleInfo : jobInfo.getIngestModuleInfo()) {
 
  901                             if (correlationEngineModuleName.equals(ingestModuleInfo.getDisplayName())) {
 
  902                                 dataSourceCorrelationMap.put(dataSource, CorrelatedStatus.CORRELATED);
 
  909                 for (DataSource dataSource : dataSourceCorrelationMap.keySet()) {
 
  910                     if (dataSourceCorrelationMap.get(dataSource) != CorrelatedStatus.CORRELATED) {
 
  911                         unCorrelatedDataSources.add(dataSource.getName());
 
  914                 return unCorrelatedDataSources;
 
  918             protected void done() {
 
  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();
 
  928                         NotifyDescriptor descriptor = 
new NotifyDescriptor.Confirmation(warning, Bundle.CommonAttributePanel_incompleteResults_title(), NotifyDescriptor.YES_NO_OPTION);
 
  929                         performSearch = DialogDisplayer.getDefault().notify(descriptor) == NotifyDescriptor.YES_OPTION;
 
  932                         if (interCaseRadio.isSelected() && caseResultsRadioButton.isSelected()) {
 
  938                 } 
catch (InterruptedException | ExecutionException ex) {
 
  939                     LOGGER.log(Level.SEVERE, 
"Unexpected exception while looking for common properties", ex); 
 
  949     private void percentageThresholdChanged() {
 
  950         String percentageString = this.percentageThresholdInputBox.getText();
 
  953             this.percentageThresholdValue = Integer.parseInt(percentageString);
 
  955         } 
catch (NumberFormatException ignored) {
 
  956             this.percentageThresholdValue = -1;
 
  959         this.handleFrequencyPercentageState();
 
  966     private void updateErrorTextAndSearchButton() {
 
  967         if (this.errorManager.anyErrors()) {
 
  968             this.searchButton.setEnabled(
false);
 
  970             this.errorText.setText(this.errorManager.getErrors().get(0));
 
  971             this.errorText.setVisible(
true);
 
  973             this.searchButton.setEnabled(
true);
 
  974             this.errorText.setVisible(
false);
 
  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);
 
 1004     private void handleFrequencyPercentageState() {
 
 1005         if (this.percentageThresholdValue > 0 && this.percentageThresholdValue <= 100) {
 
 1006             this.errorManager.setError(UserInputErrorManager.FREQUENCY_PERCENTAGE_OUT_OF_RANGE_KEY, 
false);
 
 1009             this.errorManager.setError(UserInputErrorManager.FREQUENCY_PERCENTAGE_OUT_OF_RANGE_KEY, 
true);
 
 1011         this.updateErrorTextAndSearchButton();
 
 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;
 
 1038     void observeSubPanels() {
 
 1039         intraCasePanel.addObserver(
this);
 
 1040         interCasePanel.addObserver(
this);
 
 1048     private void checkFileTypeCheckBoxState() {
 
 1049         boolean validCheckBoxState = 
true;
 
 1050         if (CommonAttributePanel.this.interCaseRadio.isSelected()) {
 
 1051             if (interCasePanel.fileCategoriesButtonIsSelected()) {
 
 1052                 validCheckBoxState = interCasePanel.pictureVideoCheckboxIsSelected() || interCasePanel.documentsCheckboxIsSelected();
 
 1055             if (intraCasePanel.fileCategoriesButtonIsSelected()) {
 
 1056                 validCheckBoxState = intraCasePanel.pictureVideoCheckboxIsSelected() || intraCasePanel.documentsCheckboxIsSelected();
 
 1059         if (validCheckBoxState) {
 
 1060             this.errorManager.setError(UserInputErrorManager.NO_FILE_CATEGORIES_SELECTED_KEY, 
false);
 
 1062             this.errorManager.setError(UserInputErrorManager.NO_FILE_CATEGORIES_SELECTED_KEY, 
true);
 
 1064         this.updateErrorTextAndSearchButton();