19 package org.sleuthkit.autopsy.centralrepository.persona;
 
   21 import java.awt.event.ActionEvent;
 
   22 import java.awt.event.ActionListener;
 
   23 import java.awt.event.ComponentAdapter;
 
   24 import java.awt.event.ComponentEvent;
 
   25 import java.util.ArrayList;
 
   26 import java.util.Collection;
 
   27 import java.util.List;
 
   28 import java.util.logging.Level;
 
   29 import javax.swing.JOptionPane;
 
   30 import javax.swing.JTable;
 
   31 import javax.swing.ListSelectionModel;
 
   32 import javax.swing.event.AncestorListener;
 
   33 import javax.swing.event.AncestorEvent;
 
   34 import javax.swing.event.ListSelectionEvent;
 
   35 import javax.swing.event.ListSelectionListener;
 
   36 import javax.swing.table.DefaultTableModel;
 
   37 import org.openide.DialogDisplayer;
 
   38 import org.openide.NotifyDescriptor;
 
   39 import org.openide.util.NbBundle.Messages;
 
   40 import org.openide.windows.RetainLocation;
 
   41 import org.openide.windows.TopComponent;
 
   42 import org.openide.windows.WindowManager;
 
   52 @TopComponent.Description(preferredID = 
"PersonasTopComponent", persistenceType = TopComponent.PERSISTENCE_NEVER)
 
   53 @TopComponent.Registration(mode = 
"personas", openAtStartup = 
false)
 
   54 @RetainLocation(
"personas")
 
   55 @SuppressWarnings(
"PMD.SingularField")
 
   58     private static final long serialVersionUID = 1L;
 
   62     private List<Persona> currentResults = null;
 
   66         "PersonasTopComponent_Name=Personas",
 
   67         "PersonasTopComponent_delete_exception_Title=Delete failure",
 
   68         "PersonasTopComponent_delete_exception_msg=Failed to delete persona.",
 
   69         "PersonasTopComponent_delete_confirmation_Title=Are you sure?",
 
   70         "PersonasTopComponent_delete_confirmation_msg=Are you sure you want to delete this persona?",})
 
   73         setName(Bundle.PersonasTopComponent_Name());
 
   75         searchBtn.addActionListener(
new ActionListener() {
 
   77             public void actionPerformed(ActionEvent e) {
 
   82         editBtn.addActionListener(
new ActionListener() {
 
   84             public void actionPerformed(ActionEvent e) {
 
   90         createBtn.addActionListener(
new ActionListener() {
 
   92             public void actionPerformed(ActionEvent e) {
 
   98         deleteBtn.addActionListener(
new ActionListener() {
 
  100             public void actionPerformed(ActionEvent e) {
 
  101                 NotifyDescriptor confirm = 
new NotifyDescriptor.Confirmation(
 
  102                         Bundle.PersonasTopComponent_delete_confirmation_msg(),
 
  103                         Bundle.PersonasTopComponent_delete_confirmation_Title(),
 
  104                         NotifyDescriptor.YES_NO_OPTION);
 
  105                 DialogDisplayer.getDefault().notify(confirm);
 
  106                 if (confirm.getValue().equals(NotifyDescriptor.YES_OPTION)) {
 
  108                         if (selectedPersona != null) {
 
  112                         logger.log(Level.SEVERE, 
"Failed to delete persona: " + selectedPersona.
getName(), ex);
 
  114                                 Bundle.PersonasTopComponent_delete_exception_msg(),
 
  115                                 Bundle.PersonasTopComponent_delete_exception_Title(),
 
  116                                 JOptionPane.ERROR_MESSAGE);
 
  125         resultsTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
 
  126         resultsTable.getSelectionModel().addListSelectionListener(
new ListSelectionListener() {
 
  128             public void valueChanged(ListSelectionEvent e) {
 
  129                 handleSelectionChange(e);
 
  133         createAccountBtn.addActionListener(
new ActionListener() {
 
  135             public void actionPerformed(ActionEvent e) {
 
  144         addComponentListener(
new ComponentAdapter() {
 
  146             public void componentShown(ComponentEvent e) {
 
  147                 resetSearchControls();
 
  148                 setKeywordSearchEnabled(
false, 
true);
 
  159         public void callback(
Persona persona) {
 
  160             if (persona != null) {
 
  161                 searchField.setText(
"");
 
  163                 int personaRow = currentResults.indexOf(persona);
 
  164                 resultsTable.getSelectionModel().setSelectionInterval(personaRow, personaRow);
 
  165                 handleSelectionChange();
 
  167             createBtn.setEnabled(
true);
 
  175         searchField.setText(
"");
 
  176         searchNameRadio.setSelected(
true);
 
  177         searchAccountRadio.setSelected(
false);
 
  188         if (setFilterCb && cbFilterByKeyword.isSelected() != selected) {
 
  189             cbFilterByKeyword.setSelected(selected);
 
  192         searchField.setEnabled(selected);
 
  193         searchNameRadio.setEnabled(selected);
 
  194         searchAccountRadio.setEnabled(selected);
 
  199     void setPersona(
int index) {
 
  200         Persona persona = currentResults.get(index);
 
  201         selectedPersona = persona;
 
  202         editBtn.setEnabled(
true);
 
  203         deleteBtn.setEnabled(
true);
 
  209     final class PersonaFilterTableModel 
extends DefaultTableModel {
 
  211         private static final long serialVersionUID = 1L;
 
  213         PersonaFilterTableModel(Object[][] rows, String[] colNames) {
 
  214             super(rows, colNames);
 
  218         public boolean isCellEditable(
int row, 
int column) {
 
  224         if (e.getValueIsAdjusting()) {
 
  227         handleSelectionChange();
 
  231         int selectedRow = resultsTable.getSelectedRow();
 
  232         if (selectedRow != -1) {
 
  233             setPersona(resultsTable.getSelectedRow());
 
  236             detailsPanel.clear();
 
  241         Object[][] rows = 
new Object[results.size()][2];
 
  243         for (
Persona result : results) {
 
  244             rows[i] = 
new Object[]{result.getId(), result.getName()};
 
  247         PersonaFilterTableModel updatedTableModel = 
new PersonaFilterTableModel(
 
  249                 new String[]{
"ID", 
"Name"}
 
  252         resultsTable.setModel(updatedTableModel);
 
  253         currentResults = 
new ArrayList<>(results);
 
  256         resultsTable.getColumnModel().getColumn(0).setMaxWidth(100);
 
  257         resultsTable.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS);
 
  261         "PersonasTopComponent_search_exception_Title=There was a failure during the search.  Try opening a case to fully initialize the central repository database.",
 
  262         "PersonasTopComponent_search_exception_msg=Failed to search personas.",
 
  263         "PersonasTopComponent_noCR_msg=Central Repository is not enabled.",})
 
  267             logger.log(Level.SEVERE, 
"Central Repository is not enabled, but execute search was called.");
 
  268             JOptionPane.showMessageDialog(
this,
 
  269                     Bundle.PersonasTopComponent_search_exception_Title(),
 
  270                     Bundle.PersonasTopComponent_noCR_msg(),
 
  271                     JOptionPane.ERROR_MESSAGE);
 
  275         Collection<Persona> results;
 
  277             if (cbFilterByKeyword.isSelected()) {
 
  278                 if (searchNameRadio.isSelected()) {
 
  287             logger.log(Level.SEVERE, 
"Failed to search personas", ex);
 
  288             JOptionPane.showMessageDialog(
this,
 
  289                     Bundle.PersonasTopComponent_search_exception_Title(),
 
  290                     Bundle.PersonasTopComponent_search_exception_msg(),
 
  291                     JOptionPane.ERROR_MESSAGE);
 
  295         resultsTable.clearSelection();
 
  296         updateResultsTable(results);
 
  297         editBtn.setEnabled(
false);
 
  298         deleteBtn.setEnabled(
false);
 
  303         super.componentOpened();
 
  304         WindowManager.getDefault().setTopComponentFloating(
this, 
true);
 
  315         searchButtonGroup = 
new javax.swing.ButtonGroup();
 
  316         introTextScrollPane = 
new javax.swing.JScrollPane();
 
  317         introText = 
new javax.swing.JTextArea();
 
  318         mainSplitPane = 
new javax.swing.JSplitPane();
 
  319         searchPanel = 
new javax.swing.JPanel();
 
  320         searchField = 
new javax.swing.JTextField();
 
  321         searchNameRadio = 
new javax.swing.JRadioButton();
 
  322         searchAccountRadio = 
new javax.swing.JRadioButton();
 
  323         searchBtn = 
new javax.swing.JButton();
 
  324         resultsPane = 
new javax.swing.JScrollPane();
 
  325         resultsTable = 
new javax.swing.JTable();
 
  326         createAccountBtn = 
new javax.swing.JButton();
 
  327         editBtn = 
new javax.swing.JButton();
 
  328         deleteBtn = 
new javax.swing.JButton();
 
  329         createButtonSeparator = 
new javax.swing.JSeparator();
 
  330         createBtn = 
new javax.swing.JButton();
 
  331         cbFilterByKeyword = 
new javax.swing.JCheckBox();
 
  332         detailsScrollPane = 
new javax.swing.JScrollPane();
 
  337         introTextScrollPane.setVerticalScrollBarPolicy(javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER);
 
  339         introText.setBackground(getBackground());
 
  340         introText.setColumns(20);
 
  341         introText.setLineWrap(
true);
 
  342         introText.setRows(5);
 
  343         introText.setText(
org.openide.util.NbBundle.getMessage(
PersonasTopComponent.class, 
"PersonasTopComponent.introText.text")); 
 
  344         introText.setWrapStyleWord(
true);
 
  345         introText.setFocusable(
false);
 
  346         introTextScrollPane.setViewportView(introText);
 
  348         mainSplitPane.setDividerLocation(400);
 
  350         searchField.setText(
org.openide.util.NbBundle.getMessage(
PersonasTopComponent.class, 
"PersonasTopComponent.searchField.text")); 
 
  352         searchButtonGroup.add(searchNameRadio);
 
  353         searchNameRadio.setSelected(
true);
 
  354         org.openide.awt.Mnemonics.setLocalizedText(searchNameRadio, 
org.openide.util.NbBundle.getMessage(
PersonasTopComponent.class, 
"PersonasTopComponent.searchNameRadio.text")); 
 
  356         searchButtonGroup.add(searchAccountRadio);
 
  357         org.openide.awt.Mnemonics.setLocalizedText(searchAccountRadio, 
org.openide.util.NbBundle.getMessage(
PersonasTopComponent.class, 
"PersonasTopComponent.searchAccountRadio.text")); 
 
  359         org.openide.awt.Mnemonics.setLocalizedText(searchBtn, 
org.openide.util.NbBundle.getMessage(
PersonasTopComponent.class, 
"PersonasTopComponent.searchBtn.text")); 
 
  361         resultsTable.setToolTipText(
org.openide.util.NbBundle.getMessage(
PersonasTopComponent.class, 
"PersonasTopComponent.resultsTable.toolTipText")); 
 
  362         resultsTable.getTableHeader().setReorderingAllowed(
false);
 
  363         resultsPane.setViewportView(resultsTable);
 
  364         if (resultsTable.getColumnModel().getColumnCount() > 0) {
 
  365             resultsTable.getColumnModel().getColumn(0).setMaxWidth(25);
 
  366             resultsTable.getColumnModel().getColumn(0).setHeaderValue(
org.openide.util.NbBundle.getMessage(
PersonasTopComponent.class, 
"PersonasTopComponent.resultsTable.columnModel.title0")); 
 
  367             resultsTable.getColumnModel().getColumn(1).setHeaderValue(
org.openide.util.NbBundle.getMessage(
PersonasTopComponent.class, 
"PersonasTopComponent.resultsTable.columnModel.title1")); 
 
  370         org.openide.awt.Mnemonics.setLocalizedText(createAccountBtn, 
org.openide.util.NbBundle.getMessage(
PersonasTopComponent.class, 
"PersonasTopComponent.createAccountBtn.text")); 
 
  372         org.openide.awt.Mnemonics.setLocalizedText(editBtn, 
org.openide.util.NbBundle.getMessage(
PersonasTopComponent.class, 
"PersonasTopComponent.editBtn.text")); 
 
  373         editBtn.setEnabled(
false);
 
  375         org.openide.awt.Mnemonics.setLocalizedText(deleteBtn, 
org.openide.util.NbBundle.getMessage(
PersonasTopComponent.class, 
"PersonasTopComponent.deleteBtn.text")); 
 
  376         deleteBtn.setEnabled(
false);
 
  378         org.openide.awt.Mnemonics.setLocalizedText(createBtn, 
org.openide.util.NbBundle.getMessage(
PersonasTopComponent.class, 
"PersonasTopComponent.createBtn.text")); 
 
  380         org.openide.awt.Mnemonics.setLocalizedText(cbFilterByKeyword, 
org.openide.util.NbBundle.getMessage(
PersonasTopComponent.class, 
"PersonasTopComponent.cbFilterByKeyword.text")); 
 
  381         cbFilterByKeyword.addActionListener(
new java.awt.event.ActionListener() {
 
  382             public void actionPerformed(java.awt.event.ActionEvent evt) {
 
  383                 cbFilterByKeywordActionPerformed(evt);
 
  387         javax.swing.GroupLayout searchPanelLayout = 
new javax.swing.GroupLayout(searchPanel);
 
  388         searchPanel.setLayout(searchPanelLayout);
 
  389         searchPanelLayout.setHorizontalGroup(
 
  390             searchPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 
  391             .addGroup(searchPanelLayout.createSequentialGroup()
 
  393                 .addGroup(searchPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 
  394                     .addComponent(createButtonSeparator)
 
  395                     .addComponent(resultsPane, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)
 
  396                     .addComponent(searchField)
 
  397                     .addGroup(searchPanelLayout.createSequentialGroup()
 
  398                         .addComponent(searchNameRadio)
 
  399                         .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 
  400                         .addComponent(searchAccountRadio)
 
  401                         .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
 
  402                         .addComponent(searchBtn))
 
  403                     .addGroup(searchPanelLayout.createSequentialGroup()
 
  404                         .addGroup(searchPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 
  405                             .addComponent(createAccountBtn)
 
  406                             .addGroup(searchPanelLayout.createSequentialGroup()
 
  407                                 .addComponent(createBtn)
 
  408                                 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 
  409                                 .addComponent(editBtn)
 
  410                                 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 
  411                                 .addComponent(deleteBtn))
 
  412                             .addComponent(cbFilterByKeyword))
 
  413                         .addGap(0, 50, Short.MAX_VALUE)))
 
  416         searchPanelLayout.setVerticalGroup(
 
  417             searchPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 
  418             .addGroup(searchPanelLayout.createSequentialGroup()
 
  419                 .addComponent(cbFilterByKeyword)
 
  421                 .addComponent(searchField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
 
  422                 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 
  423                 .addGroup(searchPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
 
  424                     .addComponent(searchNameRadio)
 
  425                     .addComponent(searchAccountRadio)
 
  426                     .addComponent(searchBtn))
 
  427                 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 
  428                 .addComponent(resultsPane, javax.swing.GroupLayout.PREFERRED_SIZE, 302, javax.swing.GroupLayout.PREFERRED_SIZE)
 
  429                 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 
  430                 .addGroup(searchPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
 
  431                     .addComponent(editBtn)
 
  432                     .addComponent(createBtn)
 
  433                     .addComponent(deleteBtn))
 
  434                 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 
  435                 .addComponent(createButtonSeparator, javax.swing.GroupLayout.PREFERRED_SIZE, 4, javax.swing.GroupLayout.PREFERRED_SIZE)
 
  436                 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 
  437                 .addComponent(createAccountBtn, javax.swing.GroupLayout.PREFERRED_SIZE, 32, javax.swing.GroupLayout.PREFERRED_SIZE)
 
  441         mainSplitPane.setLeftComponent(searchPanel);
 
  443         detailsScrollPane.setViewportView(detailsPanel);
 
  445         mainSplitPane.setRightComponent(detailsScrollPane);
 
  447         javax.swing.GroupLayout layout = 
new javax.swing.GroupLayout(
this);
 
  448         this.setLayout(layout);
 
  449         layout.setHorizontalGroup(
 
  450             layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 
  451             .addComponent(introTextScrollPane)
 
  452             .addComponent(mainSplitPane, javax.swing.GroupLayout.DEFAULT_SIZE, 724, Short.MAX_VALUE)
 
  454         layout.setVerticalGroup(
 
  455             layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 
  456             .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
 
  457                 .addComponent(introTextScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 49, javax.swing.GroupLayout.PREFERRED_SIZE)
 
  458                 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 
  459                 .addComponent(mainSplitPane, javax.swing.GroupLayout.DEFAULT_SIZE, 489, Short.MAX_VALUE))
 
  464         setKeywordSearchEnabled(cbFilterByKeyword.isSelected(), 
false);
 
javax.swing.JRadioButton searchNameRadio
javax.swing.JCheckBox cbFilterByKeyword
javax.swing.JPanel searchPanel
void handleSelectionChange()
void handleSelectionChange(ListSelectionEvent e)
javax.swing.JButton createAccountBtn
javax.swing.JSplitPane mainSplitPane
static Collection< Persona > getPersonaByName(String partialName)
javax.swing.JScrollPane introTextScrollPane
javax.swing.JTextField searchField
javax.swing.JScrollPane resultsPane
void cbFilterByKeywordActionPerformed(java.awt.event.ActionEvent evt)
javax.swing.JButton searchBtn
javax.swing.JSeparator createButtonSeparator
javax.swing.JButton editBtn
javax.swing.JScrollPane detailsScrollPane
javax.swing.JTable resultsTable
javax.swing.JButton deleteBtn
void resetSearchControls()
void setKeywordSearchEnabled(boolean selected, boolean setFilterCb)
javax.swing.ButtonGroup searchButtonGroup
javax.swing.JTextArea introText
synchronized static Logger getLogger(String name)
org.sleuthkit.autopsy.centralrepository.persona.PersonaDetailsPanel detailsPanel
void updateResultsTable(Collection< Persona > results)
javax.swing.JButton createBtn
static Collection< Persona > getPersonaByAccountIdentifierLike(String partialName)
javax.swing.JRadioButton searchAccountRadio
static boolean isEnabled()