19 package org.sleuthkit.autopsy.commonfilesearch;
21 import java.awt.Dimension;
22 import java.sql.SQLException;
23 import java.util.ArrayList;
24 import java.util.Collection;
25 import java.util.HashMap;
26 import java.util.List;
28 import java.util.Objects;
29 import java.util.Observable;
30 import java.util.Observer;
31 import java.util.concurrent.ExecutionException;
32 import java.util.logging.Level;
33 import javax.swing.JFrame;
34 import javax.swing.SwingUtilities;
35 import javax.swing.SwingWorker;
36 import javax.swing.event.DocumentEvent;
37 import javax.swing.event.DocumentListener;
38 import org.netbeans.api.progress.ProgressHandle;
39 import org.openide.explorer.ExplorerManager;
40 import org.openide.nodes.Node;
41 import org.openide.util.NbBundle;
42 import org.openide.windows.WindowManager;
63 @SuppressWarnings(
"PMD.SingularField")
64 final class CommonAttributePanel extends javax.swing.JDialog implements Observer {
66 private static final Logger LOGGER = Logger.getLogger(CommonAttributePanel.class.getName());
67 private static final long serialVersionUID = 1L;
69 private static final Long NO_DATA_SOURCE_SELECTED = -1L;
71 private final UserInputErrorManager errorManager;
73 private int percentageThresholdValue = 20;
79 "CommonAttributePanel.title=Common Property Panel",
80 "CommonAttributePanel.exception=Unexpected Exception loading DataSources.",
81 "CommonAttributePanel.frame.title=Find Common Properties",
82 "CommonAttributePanel.frame.msg=Find Common Properties",
83 "CommonAttributePanel.intraCasePanel.title=Curren Case Options"})
84 CommonAttributePanel() {
85 super(
new JFrame(Bundle.CommonAttributePanel_frame_title()),
86 Bundle.CommonAttributePanel_frame_msg(),
true);
88 this.setLocationRelativeTo(WindowManager.getDefault().getMainWindow());
89 this.setupDataSources();
90 intraCasePanel.setVisible(
true);
91 interCasePanel.setVisible(
false);
92 if (CommonAttributePanel.isEamDbAvailableForIntercaseSearch()) {
94 this.interCasePanel.setupCorrelationTypeFilter();
96 this.disableIntercaseSearch();
99 this.updatePercentageOptions(CommonAttributePanel.getNumberOfDataSourcesAvailable());
101 this.errorManager =
new UserInputErrorManager();
103 this.percentageThresholdInputBox.getDocument().addDocumentListener(
new DocumentListener() {
105 private final Dimension preferredSize = CommonAttributePanel.this.percentageThresholdInputBox.getPreferredSize();
107 private void maintainSize() {
108 CommonAttributePanel.this.percentageThresholdInputBox.setSize(preferredSize);
112 public void insertUpdate(DocumentEvent event) {
114 CommonAttributePanel.this.percentageThresholdChanged();
118 public void removeUpdate(DocumentEvent event) {
120 CommonAttributePanel.this.percentageThresholdChanged();
124 public void changedUpdate(DocumentEvent event) {
126 CommonAttributePanel.this.percentageThresholdChanged();
138 static boolean isEamDbAvailableForIntercaseSearch() {
140 return EamDb.isEnabled()
141 && EamDb.getInstance() != null
142 && EamDb.getInstance().getCases().size() > 1
144 && Case.getCurrentCase() != null
145 && EamDb.getInstance().getCase(Case.getCurrentCase()) != null;
146 }
catch (EamDbException ex) {
147 LOGGER.log(Level.SEVERE,
"Unexpected exception while checking for EamDB enabled.", ex);
153 public void update(Observable o, Object arg) {
154 checkFileTypeCheckBoxState();
164 private static Long getNumberOfDataSourcesAvailable() {
166 if (EamDb.isEnabled()
167 && EamDb.getInstance() != null) {
168 return EamDb.getInstance().getCountUniqueDataSources();
170 }
catch (EamDbException ex) {
171 LOGGER.log(Level.SEVERE,
"Unexpected exception while checking for EamDB enabled.", ex);
180 private void disableIntercaseSearch() {
181 this.intraCaseRadio.setSelected(
true);
182 this.interCaseRadio.setEnabled(
false);
189 "CommonAttributePanel.search.results.pathText=Common Property Search Results",
190 "CommonAttributePanel.search.done.searchProgressGathering=Gathering Common Property Search Results.",
191 "CommonAttributePanel.search.done.searchProgressDisplay=Displaying Common Property Search Results.",
192 "CommonAttributePanel.search.done.tskCoreException=Unable to run query against DB.",
193 "CommonAttributePanel.search.done.noCurrentCaseException=Unable to open case file.",
194 "CommonAttributePanel.search.done.exception=Unexpected exception running Common Property Search.",
195 "CommonAttributePanel.search.done.interupted=Something went wrong finding common properties.",
196 "CommonAttributePanel.search.done.sqlException=Unable to query db for properties or data sources.",
197 "CommonAttributePanel.search.done.noResults=No results found."})
198 private void search() {
199 new SwingWorker<CommonAttributeSearchResults, Void>() {
201 private String tabTitle;
202 private ProgressHandle progress;
205 protected CommonAttributeSearchResults doInBackground() throws TskCoreException, NoCurrentCaseException, SQLException, EamDbException {
206 progress = ProgressHandle.createHandle(Bundle.CommonAttributePanel_search_done_searchProgressGathering());
208 progress.switchToIndeterminate();
210 Long dataSourceId = intraCasePanel.getSelectedDataSourceId();
211 Integer caseId = interCasePanel.getSelectedCaseId();
213 AbstractCommonAttributeSearcher builder;
214 CommonAttributeSearchResults metadata;
216 boolean filterByMedia =
false;
217 boolean filterByDocuments =
false;
219 int percentageThreshold = CommonAttributePanel.this.percentageThresholdValue;
221 if (!CommonAttributePanel.this.percentageThresholdCheck.isSelected()) {
223 percentageThreshold = 0;
226 if (CommonAttributePanel.this.interCaseRadio.isSelected()) {
227 CorrelationAttributeInstance.Type corType = interCasePanel.getSelectedCorrelationType();
228 if (interCasePanel.fileCategoriesButtonIsSelected()) {
229 filterByMedia = interCasePanel.pictureVideoCheckboxIsSelected();
230 filterByDocuments = interCasePanel.documentsCheckboxIsSelected();
232 if (corType == null) {
233 corType = CorrelationAttributeInstance.getDefaultCorrelationTypes().get(0);
235 if (caseId == InterCasePanel.NO_CASE_SELECTED) {
236 builder =
new AllInterCaseCommonAttributeSearcher(filterByMedia, filterByDocuments, corType, percentageThreshold);
239 builder =
new SingleInterCaseCommonAttributeSearcher(caseId, filterByMedia, filterByDocuments, corType, percentageThreshold);
243 if (intraCasePanel.fileCategoriesButtonIsSelected()) {
244 filterByMedia = intraCasePanel.pictureVideoCheckboxIsSelected();
245 filterByDocuments = intraCasePanel.documentsCheckboxIsSelected();
247 if (Objects.equals(dataSourceId, CommonAttributePanel.NO_DATA_SOURCE_SELECTED)) {
248 builder =
new AllIntraCaseCommonAttributeSearcher(intraCasePanel.getDataSourceMap(), filterByMedia, filterByDocuments, percentageThreshold);
250 builder =
new SingleIntraCaseCommonAttributeSearcher(dataSourceId, intraCasePanel.getDataSourceMap(), filterByMedia, filterByDocuments, percentageThreshold);
254 metadata = builder.findMatches();
255 this.tabTitle = builder.getTabTitle();
261 protected void done() {
264 CommonAttributeSearchResults metadata = this.
get();
265 boolean noKeysExist =
true;
267 noKeysExist = metadata.getMetadata().keySet().isEmpty();
268 }
catch (EamDbException ex) {
269 LOGGER.log(Level.SEVERE,
"Unable to get keys from metadata", ex);
272 Node commonFilesNode =
new TableFilterNode(
new EmptyNode(Bundle.CommonAttributePanel_search_done_noResults()),
true);
273 progress.setDisplayName(Bundle.CommonAttributePanel_search_done_searchProgressDisplay());
274 DataResultTopComponent.createInstance(tabTitle, Bundle.CommonAttributePanel_search_results_pathText(), commonFilesNode, 1);
277 Node commonFilesNode =
new CommonAttributeSearchResultRootNode(metadata);
278 DataResultFilterNode dataResultFilterNode =
new DataResultFilterNode(commonFilesNode, ExplorerManager.find(CommonAttributePanel.this));
279 TableFilterNode tableFilterWithDescendantsNode =
new TableFilterNode(dataResultFilterNode, 3);
280 DataResultViewerTable table =
new CommonAttributesSearchResultsViewerTable();
281 Collection<DataResultViewer> viewers =
new ArrayList<>(1);
283 progress.setDisplayName(Bundle.CommonAttributePanel_search_done_searchProgressDisplay());
284 DataResultTopComponent.createInstance(tabTitle, Bundle.CommonAttributePanel_search_results_pathText(), tableFilterWithDescendantsNode, metadata.size(), viewers);
287 }
catch (InterruptedException ex) {
288 LOGGER.log(Level.SEVERE,
"Interrupted while loading Common Files", ex);
289 MessageNotifyUtil.Message.error(Bundle.CommonAttributePanel_search_done_interupted());
290 }
catch (ExecutionException ex) {
292 Throwable inner = ex.getCause();
293 if (inner instanceof TskCoreException) {
294 LOGGER.log(Level.SEVERE,
"Failed to load files from database.", ex);
295 errorMessage = Bundle.CommonAttributePanel_search_done_tskCoreException();
296 }
else if (inner instanceof NoCurrentCaseException) {
297 LOGGER.log(Level.SEVERE,
"Current case has been closed.", ex);
298 errorMessage = Bundle.CommonAttributePanel_search_done_noCurrentCaseException();
299 }
else if (inner instanceof SQLException) {
300 LOGGER.log(Level.SEVERE,
"Unable to query db for files.", ex);
301 errorMessage = Bundle.CommonAttributePanel_search_done_sqlException();
303 LOGGER.log(Level.SEVERE,
"Unexpected exception while running Common Files Search.", ex);
304 errorMessage = Bundle.CommonAttributePanel_search_done_exception();
306 MessageNotifyUtil.Message.error(errorMessage);
322 "CommonAttributePanel.setupDataSources.done.tskCoreException=Unable to run query against DB.",
323 "CommonAttributePanel.setupDataSources.done.noCurrentCaseException=Unable to open case file.",
324 "CommonAttributePanel.setupDataSources.done.exception=Unexpected exception loading data sources.",
325 "CommonAttributePanel.setupDataSources.done.interupted=Something went wrong building the Common Files Search dialog box.",
326 "CommonAttributePanel.setupDataSources.done.sqlException=Unable to query db for data sources.",
327 "CommonAttributePanel.setupDataSources.updateUi.noDataSources=No data sources were found."})
329 private void setupDataSources() {
331 new SwingWorker<Map<Long, String>, Void>() {
337 private void updateUi() {
339 final Map<Long, String> dataSourceMap = CommonAttributePanel.this.intraCasePanel.getDataSourceMap();
341 String[] dataSourcesNames =
new String[dataSourceMap.size()];
344 if (dataSourcesNames.length > 0) {
345 dataSourcesNames = dataSourceMap.values().toArray(dataSourcesNames);
346 CommonAttributePanel.this.intraCasePanel.setDatasourceComboboxModel(
new DataSourceComboBoxModel(dataSourcesNames));
348 if (!this.caseHasMultipleSources()) {
349 intraCaseRadio.setEnabled(
false);
350 interCaseRadio.setSelected(
true);
351 intraCasePanel.setVisible(
false);
352 interCasePanel.setVisible(
true);
354 CommonAttributePanel.this.updateErrorTextAndSearchButton();
364 private boolean caseHasMultipleSources() {
365 return CommonAttributePanel.this.intraCasePanel.getDataSourceMap().size() > 1;
369 protected Map<Long, String> doInBackground() throws NoCurrentCaseException, TskCoreException, SQLException {
370 DataSourceLoader loader =
new DataSourceLoader();
371 return loader.getDataSourceMap();
375 protected void done() {
378 CommonAttributePanel.this.intraCasePanel.setDataSourceMap(this.
get());
381 }
catch (InterruptedException ex) {
382 LOGGER.log(Level.SEVERE,
"Interrupted while building Common Files Search dialog.", ex);
383 MessageNotifyUtil.Message.error(Bundle.CommonAttributePanel_setupDataSources_done_interupted());
384 }
catch (ExecutionException ex) {
386 Throwable inner = ex.getCause();
387 if (inner instanceof TskCoreException) {
388 LOGGER.log(Level.SEVERE,
"Failed to load data sources from database.", ex);
389 errorMessage = Bundle.CommonAttributePanel_setupDataSources_done_tskCoreException();
390 }
else if (inner instanceof NoCurrentCaseException) {
391 LOGGER.log(Level.SEVERE,
"Current case has been closed.", ex);
392 errorMessage = Bundle.CommonAttributePanel_setupDataSources_done_noCurrentCaseException();
393 }
else if (inner instanceof SQLException) {
394 LOGGER.log(Level.SEVERE,
"Unable to query db for data sources.", ex);
395 errorMessage = Bundle.CommonAttributePanel_setupDataSources_done_sqlException();
397 LOGGER.log(Level.SEVERE,
"Unexpected exception while building Common Files Search dialog panel.", ex);
398 errorMessage = Bundle.CommonAttributePanel_setupDataSources_done_exception();
400 MessageNotifyUtil.Message.error(errorMessage);
407 "CommonAttributePanel.setupCases.done.interruptedException=Something went wrong building the Common Files Search dialog box.",
408 "CommonAttributePanel.setupCases.done.exeutionException=Unexpected exception loading cases."})
409 private void setupCases() {
411 new SwingWorker<Map<Integer, String>, Void>() {
417 private void updateUi() {
419 final Map<Integer, String> caseMap = CommonAttributePanel.this.interCasePanel.getCaseMap();
421 String[] caseNames =
new String[caseMap.size()];
423 if (caseNames.length > 0) {
424 caseNames = caseMap.values().toArray(caseNames);
425 CommonAttributePanel.this.interCasePanel.setCaseComboboxModel(
new DataSourceComboBoxModel(caseNames));
427 CommonAttributePanel.this.disableIntercaseSearch();
440 private Map<Integer, String> mapCases(List<CorrelationCase> cases)
throws EamDbException {
441 Map<Integer, String> casemap =
new HashMap<>();
442 CorrelationCase currentCorCase = EamDb.getInstance().getCase(Case.getCurrentCase());
443 for (CorrelationCase correlationCase : cases) {
444 if (currentCorCase.getID() != correlationCase.getID()) {
445 casemap.put(correlationCase.getID(), correlationCase.getDisplayName());
452 protected Map<Integer, String> doInBackground() throws EamDbException {
454 List<CorrelationCase> dataSources = EamDb.getInstance().getCases();
455 Map<Integer, String> caseMap = mapCases(dataSources);
461 protected void done() {
463 Map<Integer, String> cases = this.
get();
464 CommonAttributePanel.this.interCasePanel.setCaseMap(cases);
466 }
catch (InterruptedException ex) {
467 LOGGER.log(Level.SEVERE,
"Interrupted while building Common Files Search dialog.", ex);
468 MessageNotifyUtil.Message.error(Bundle.CommonAttributePanel_setupCases_done_interruptedException());
469 }
catch (ExecutionException ex) {
470 LOGGER.log(Level.SEVERE,
"Unexpected exception while building Common Files Search dialog.", ex);
471 MessageNotifyUtil.Message.error(Bundle.CommonAttributePanel_setupCases_done_exeutionException());
483 @SuppressWarnings(
"unchecked")
485 private
void initComponents() {
487 interIntraButtonGroup =
new javax.swing.ButtonGroup();
488 jPanel1 =
new javax.swing.JPanel();
489 scopeLabel =
new javax.swing.JLabel();
490 searchButton =
new javax.swing.JButton();
491 errorText =
new javax.swing.JLabel();
492 commonItemSearchDescription =
new javax.swing.JLabel();
493 intraCaseRadio =
new javax.swing.JRadioButton();
494 interCaseRadio =
new javax.swing.JRadioButton();
495 percentageThresholdCheck =
new javax.swing.JCheckBox();
496 percentageThresholdInputBox =
new javax.swing.JTextField();
497 percentageThresholdTextTwo =
new javax.swing.JLabel();
500 dataSourcesLabel =
new javax.swing.JLabel();
502 setMinimumSize(
new java.awt.Dimension(450, 460));
504 addWindowListener(
new java.awt.event.WindowAdapter() {
505 public void windowClosed(java.awt.event.WindowEvent evt) {
506 formWindowClosed(evt);
510 jPanel1.setMaximumSize(
new java.awt.Dimension(450, 460));
511 jPanel1.setMinimumSize(
new java.awt.Dimension(450, 460));
512 jPanel1.setPreferredSize(
new java.awt.Dimension(450, 460));
513 jPanel1.setRequestFocusEnabled(
false);
515 org.openide.awt.Mnemonics.setLocalizedText(scopeLabel,
org.openide.util.NbBundle.getMessage(CommonAttributePanel.class,
"CommonAttributePanel.scopeLabel.text"));
516 scopeLabel.setFocusable(
false);
518 org.openide.awt.Mnemonics.setLocalizedText(searchButton,
org.openide.util.NbBundle.getMessage(CommonAttributePanel.class,
"CommonAttributePanel.searchButton.text"));
519 searchButton.setEnabled(
false);
520 searchButton.setHorizontalTextPosition(javax.swing.SwingConstants.LEADING);
521 searchButton.addActionListener(
new java.awt.event.ActionListener() {
522 public void actionPerformed(java.awt.event.ActionEvent evt) {
523 searchButtonActionPerformed(evt);
527 errorText.setForeground(
new java.awt.Color(255, 0, 0));
528 org.openide.awt.Mnemonics.setLocalizedText(errorText,
org.openide.util.NbBundle.getMessage(CommonAttributePanel.class,
"CommonAttributePanel.errorText.text"));
529 errorText.setVerticalAlignment(javax.swing.SwingConstants.TOP);
531 org.openide.awt.Mnemonics.setLocalizedText(commonItemSearchDescription,
org.openide.util.NbBundle.getMessage(CommonAttributePanel.class,
"CommonAttributePanel.commonItemSearchDescription.text"));
532 commonItemSearchDescription.setFocusable(
false);
534 interIntraButtonGroup.add(intraCaseRadio);
535 intraCaseRadio.setSelected(
true);
536 org.openide.awt.Mnemonics.setLocalizedText(intraCaseRadio,
org.openide.util.NbBundle.getMessage(CommonAttributePanel.class,
"CommonAttributePanel.intraCaseRadio.text"));
537 intraCaseRadio.addActionListener(
new java.awt.event.ActionListener() {
538 public void actionPerformed(java.awt.event.ActionEvent evt) {
539 intraCaseRadioActionPerformed(evt);
543 interIntraButtonGroup.add(interCaseRadio);
544 org.openide.awt.Mnemonics.setLocalizedText(interCaseRadio,
org.openide.util.NbBundle.getMessage(CommonAttributePanel.class,
"CommonFilesPanel.jRadioButton2.text"));
545 interCaseRadio.addActionListener(
new java.awt.event.ActionListener() {
546 public void actionPerformed(java.awt.event.ActionEvent evt) {
547 interCaseRadioActionPerformed(evt);
551 org.openide.awt.Mnemonics.setLocalizedText(percentageThresholdCheck,
org.openide.util.NbBundle.getMessage(CommonAttributePanel.class,
"CommonAttributePanel.percentageThresholdCheck.text_1_1"));
552 percentageThresholdCheck.addActionListener(
new java.awt.event.ActionListener() {
553 public void actionPerformed(java.awt.event.ActionEvent evt) {
554 percentageThresholdCheckActionPerformed(evt);
558 percentageThresholdInputBox.setHorizontalAlignment(javax.swing.JTextField.TRAILING);
559 percentageThresholdInputBox.setText(
org.openide.util.NbBundle.getMessage(CommonAttributePanel.class,
"CommonAttributePanel.percentageThresholdInputBox.text"));
560 percentageThresholdInputBox.setMaximumSize(
new java.awt.Dimension(40, 24));
561 percentageThresholdInputBox.setMinimumSize(
new java.awt.Dimension(40, 24));
562 percentageThresholdInputBox.setPreferredSize(
new java.awt.Dimension(40, 24));
564 org.openide.awt.Mnemonics.setLocalizedText(percentageThresholdTextTwo,
org.openide.util.NbBundle.getMessage(CommonAttributePanel.class,
"CommonAttributePanel.percentageThresholdTextTwo.text_1"));
566 intraCasePanel.setBorder(javax.swing.BorderFactory.createTitledBorder(
org.openide.util.NbBundle.getMessage(CommonAttributePanel.class,
"CommonAttributePanel.intraCasePanel.border.title")));
567 intraCasePanel.setMaximumSize(
new java.awt.Dimension(32779, 192));
568 intraCasePanel.setMinimumSize(
new java.awt.Dimension(204, 192));
569 intraCasePanel.setPreferredSize(
new java.awt.Dimension(430, 192));
570 intraCasePanel.setVerifyInputWhenFocusTarget(
false);
572 interCasePanel.setBorder(javax.swing.BorderFactory.createTitledBorder(
org.openide.util.NbBundle.getMessage(CommonAttributePanel.class,
"CommonAttributePanel.interCasePanel.border.title")));
573 interCasePanel.setMaximumSize(
new java.awt.Dimension(32779, 230));
574 interCasePanel.setMinimumSize(
new java.awt.Dimension(430, 230));
575 interCasePanel.setPreferredSize(
new java.awt.Dimension(430, 230));
577 javax.swing.GroupLayout jPanel1Layout =
new javax.swing.GroupLayout(jPanel1);
578 jPanel1.setLayout(jPanel1Layout);
579 jPanel1Layout.setHorizontalGroup(
580 jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
581 .addGroup(jPanel1Layout.createSequentialGroup()
583 .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
584 .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup()
585 .addComponent(errorText, javax.swing.GroupLayout.DEFAULT_SIZE, 300, Short.MAX_VALUE)
587 .addComponent(searchButton)
589 .addGroup(jPanel1Layout.createSequentialGroup()
590 .addComponent(scopeLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
592 .addGroup(jPanel1Layout.createSequentialGroup()
593 .addComponent(percentageThresholdCheck)
594 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
595 .addComponent(percentageThresholdInputBox, javax.swing.GroupLayout.PREFERRED_SIZE, 40, javax.swing.GroupLayout.PREFERRED_SIZE)
596 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
597 .addComponent(percentageThresholdTextTwo, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
598 .addGroup(jPanel1Layout.createSequentialGroup()
599 .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
600 .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING,
false)
601 .addComponent(commonItemSearchDescription, javax.swing.GroupLayout.Alignment.LEADING)
602 .addGroup(javax.swing.GroupLayout.Alignment.LEADING, jPanel1Layout.createSequentialGroup()
604 .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING,
false)
605 .addComponent(intraCaseRadio, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
606 .addComponent(interCaseRadio, javax.swing.GroupLayout.DEFAULT_SIZE, 383, Short.MAX_VALUE))))
607 .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING,
false)
608 .addComponent(interCasePanel, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
609 .addComponent(intraCasePanel, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
610 .addGap(0, 0, Short.MAX_VALUE))
611 .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup()
613 .addComponent(dataSourcesLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
614 .addContainerGap())))
616 jPanel1Layout.setVerticalGroup(
617 jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
618 .addGroup(jPanel1Layout.createSequentialGroup()
620 .addComponent(commonItemSearchDescription, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
621 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
622 .addComponent(scopeLabel)
623 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
624 .addComponent(intraCaseRadio)
625 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
626 .addComponent(interCaseRadio)
627 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
628 .addComponent(interCasePanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
630 .addComponent(intraCasePanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
631 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
632 .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
633 .addComponent(percentageThresholdCheck)
634 .addComponent(percentageThresholdInputBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
635 .addComponent(percentageThresholdTextTwo))
636 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
637 .addComponent(dataSourcesLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 14, javax.swing.GroupLayout.PREFERRED_SIZE)
638 .addGap(18, 18, Short.MAX_VALUE)
639 .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
640 .addComponent(searchButton)
641 .addComponent(errorText, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
645 getContentPane().add(jPanel1, java.awt.BorderLayout.CENTER);
648 private void formWindowClosed(java.awt.event.WindowEvent evt) {
649 SwingUtilities.windowForComponent(
this).dispose();
652 private void percentageThresholdCheckActionPerformed(java.awt.event.ActionEvent evt) {
653 if (this.percentageThresholdCheck.isSelected()) {
654 this.percentageThresholdInputBox.setEnabled(
true);
656 this.percentageThresholdInputBox.setEnabled(
false);
659 this.handleFrequencyPercentageState();
662 private void interCaseRadioActionPerformed(java.awt.event.ActionEvent evt) {
663 intraCasePanel.setVisible(
false);
664 interCasePanel.setVisible(
true);
667 private void intraCaseRadioActionPerformed(java.awt.event.ActionEvent evt) {
668 intraCasePanel.setVisible(
true);
669 interCasePanel.setVisible(
false);
672 private void searchButtonActionPerformed(java.awt.event.ActionEvent evt) {
674 SwingUtilities.windowForComponent(
this).dispose();
681 private void percentageThresholdChanged() {
682 String percentageString = this.percentageThresholdInputBox.getText();
685 this.percentageThresholdValue = Integer.parseInt(percentageString);
687 }
catch (NumberFormatException ignored) {
688 this.percentageThresholdValue = -1;
691 this.handleFrequencyPercentageState();
698 private void updateErrorTextAndSearchButton() {
699 if (this.errorManager.anyErrors()) {
700 this.searchButton.setEnabled(
false);
702 this.errorText.setText(this.errorManager.getErrors().get(0));
703 this.errorText.setVisible(
true);
705 this.searchButton.setEnabled(
true);
706 this.errorText.setVisible(
false);
718 "# {0} - number of datasources",
719 "CommonAttributePanel.dataSourcesLabel.text=The current Central Repository contains {0} data source(s)."})
720 private void updatePercentageOptions(Long numberOfDataSources) {
721 boolean enabled = numberOfDataSources > 0L;
722 String numberOfDataSourcesText = enabled ? Bundle.CommonAttributePanel_dataSourcesLabel_text(numberOfDataSources) :
"";
723 this.dataSourcesLabel.setText(numberOfDataSourcesText);
724 this.percentageThresholdInputBox.setEnabled(enabled);
725 this.percentageThresholdCheck.setEnabled(enabled);
726 this.percentageThresholdCheck.setSelected(enabled);
727 this.percentageThresholdTextTwo.setEnabled(enabled);
736 private void handleFrequencyPercentageState() {
737 if (this.percentageThresholdValue > 0 && this.percentageThresholdValue <= 100) {
738 this.errorManager.setError(UserInputErrorManager.FREQUENCY_PERCENTAGE_OUT_OF_RANGE_KEY,
false);
741 this.errorManager.setError(UserInputErrorManager.FREQUENCY_PERCENTAGE_OUT_OF_RANGE_KEY,
true);
743 this.updateErrorTextAndSearchButton();
747 private javax.swing.JLabel commonItemSearchDescription;
748 private javax.swing.JLabel dataSourcesLabel;
749 private javax.swing.JLabel errorText;
751 private javax.swing.JRadioButton interCaseRadio;
752 private javax.swing.ButtonGroup interIntraButtonGroup;
754 private javax.swing.JRadioButton intraCaseRadio;
755 private javax.swing.JPanel jPanel1;
756 private javax.swing.JCheckBox percentageThresholdCheck;
757 private javax.swing.JTextField percentageThresholdInputBox;
758 private javax.swing.JLabel percentageThresholdTextTwo;
759 private javax.swing.JLabel scopeLabel;
760 private javax.swing.JButton searchButton;
767 void observeSubPanels() {
768 intraCasePanel.addObserver(
this);
769 interCasePanel.addObserver(
this);
777 private void checkFileTypeCheckBoxState() {
778 boolean validCheckBoxState =
true;
779 if (CommonAttributePanel.this.interCaseRadio.isSelected()) {
780 if (interCasePanel.fileCategoriesButtonIsSelected()) {
781 validCheckBoxState = interCasePanel.pictureVideoCheckboxIsSelected() || interCasePanel.documentsCheckboxIsSelected();
784 if (intraCasePanel.fileCategoriesButtonIsSelected()) {
785 validCheckBoxState = intraCasePanel.pictureVideoCheckboxIsSelected() || intraCasePanel.documentsCheckboxIsSelected();
788 if (validCheckBoxState) {
789 this.errorManager.setError(UserInputErrorManager.NO_FILE_CATEGORIES_SELECTED_KEY,
false);
791 this.errorManager.setError(UserInputErrorManager.NO_FILE_CATEGORIES_SELECTED_KEY,
true);
793 this.updateErrorTextAndSearchButton();