diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/CallLogArtifactViewer.java b/Core/src/org/sleuthkit/autopsy/contentviewers/CallLogArtifactViewer.java index ca701d0086..becf098a45 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/CallLogArtifactViewer.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/CallLogArtifactViewer.java @@ -93,6 +93,10 @@ public class CallLogArtifactViewer extends javax.swing.JPanel implements Artifac public void setArtifact(BlackboardArtifact artifact) { resetComponent(); + if (artifact == null) { + return; + } + CallLogViewData callLogViewData = null; try { callLogViewData = getCallLogViewData(artifact); @@ -458,7 +462,9 @@ public class CallLogArtifactViewer extends javax.swing.JPanel implements Artifac @Override public boolean isSupported(BlackboardArtifact artifact) { - return artifact.getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_CALLLOG.getTypeID(); + + return (artifact != null) + && (artifact.getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_CALLLOG.getTypeID()); } /** diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/ContactArtifactViewer.form b/Core/src/org/sleuthkit/autopsy/contentviewers/ContactArtifactViewer.form index 467d3ae72d..806a0e3de5 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/ContactArtifactViewer.form +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/ContactArtifactViewer.form @@ -1,6 +1,9 @@ -
+ + + + @@ -11,217 +14,8 @@ - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/ContactArtifactViewer.java b/Core/src/org/sleuthkit/autopsy/contentviewers/ContactArtifactViewer.java index 0533c6fae4..7e5f346927 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/ContactArtifactViewer.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/ContactArtifactViewer.java @@ -19,9 +19,9 @@ package org.sleuthkit.autopsy.contentviewers; import java.awt.Component; -import java.awt.Font; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; +import java.awt.Insets; import java.awt.event.ActionListener; import java.awt.image.BufferedImage; import java.io.File; @@ -40,11 +40,11 @@ import javax.imageio.ImageIO; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JLabel; -import javax.swing.JPanel; import javax.swing.JScrollPane; -import org.openide.util.lookup.ServiceProvider; import javax.swing.SwingWorker; +import org.apache.commons.lang.StringUtils; import org.openide.util.NbBundle; +import org.openide.util.lookup.ServiceProvider; import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepoAccount; import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepoException; import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository; @@ -64,17 +64,29 @@ import org.sleuthkit.datamodel.TskCoreException; /** * This class displays the TSK_CONTACT artifact. */ -//@ServiceProvider(service = ArtifactContentViewer.class) +@ServiceProvider(service = ArtifactContentViewer.class) public class ContactArtifactViewer extends javax.swing.JPanel implements ArtifactContentViewer { private final static Logger logger = Logger.getLogger(ContactArtifactViewer.class.getName()); private static final long serialVersionUID = 1L; - private static final int TOP_INSET = 4; - private static final int LEFT_INSET = 12; + private GridBagLayout m_gridBagLayout = new GridBagLayout(); + private GridBagConstraints m_constraints = new GridBagConstraints(); - // contact name, if available. + private JLabel personaSearchStatusLabel; + + private BlackboardArtifact contactArtifact; private String contactName; + private String datasourceName; + + private List phoneNumList = new ArrayList<>(); + private List emailList = new ArrayList<>(); + private List nameList = new ArrayList<>(); + private List otherList = new ArrayList<>(); + private List accountAttributesList = new ArrayList<>(); + + private final static String DEFAULT_IMAGE_PATH = "/org/sleuthkit/autopsy/images/defaultContact.png"; + private final ImageIcon defaultImage; // A list of unique accounts matching the attributes of the contact artifact. private final List contactUniqueAccountsList = new ArrayList<>(); @@ -83,11 +95,10 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac // account identifier attributes of the Contact artifact. private final Map> contactUniquePersonasMap = new HashMap<>(); - private final static String DEFAULT_IMAGE_PATH = "/org/sleuthkit/autopsy/images/defaultContact.png"; - private final ImageIcon defaultImage; + private ContactPersonaSearcherTask personaSearchTask; /** - * Creates new form for ContactArtifactViewer + * Creates new form ContactArtifactViewer */ public ContactArtifactViewer() { initComponents(); @@ -103,164 +114,13 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac @SuppressWarnings("unchecked") // //GEN-BEGIN:initComponents private void initComponents() { - java.awt.GridBagConstraints gridBagConstraints; - - namePanel = new javax.swing.JPanel(); - contactNameLabel = new javax.swing.JLabel(); - phonesLabel = new javax.swing.JLabel(); - phoneNumbersPanel = new javax.swing.JPanel(); - emailsLabel = new javax.swing.JLabel(); - emailsPanel = new javax.swing.JPanel(); - othersLabel = new javax.swing.JLabel(); - otherAttrsPanel = new javax.swing.JPanel(); - javax.swing.Box.Filler interPanelfiller = new javax.swing.Box.Filler(new java.awt.Dimension(0, 0), new java.awt.Dimension(0, 0), new java.awt.Dimension(0, 32767)); - personasLabel = new javax.swing.JLabel(); - personasPanel = new javax.swing.JPanel(); - javax.swing.Box.Filler bottomFiller = new javax.swing.Box.Filler(new java.awt.Dimension(0, 0), new java.awt.Dimension(0, 0), new java.awt.Dimension(0, 32767)); - javax.swing.Box.Filler rightFiller = new javax.swing.Box.Filler(new java.awt.Dimension(0, 0), new java.awt.Dimension(0, 0), new java.awt.Dimension(32767, 0)); - contactImage = new javax.swing.JLabel(); + setToolTipText(""); // NOI18N setLayout(new java.awt.GridBagLayout()); - - namePanel.setLayout(new java.awt.GridBagLayout()); - - contactNameLabel.setFont(contactNameLabel.getFont().deriveFont((contactNameLabel.getFont().getStyle() | java.awt.Font.ITALIC) | java.awt.Font.BOLD, contactNameLabel.getFont().getSize()+6)); - org.openide.awt.Mnemonics.setLocalizedText(contactNameLabel, org.openide.util.NbBundle.getMessage(ContactArtifactViewer.class, "ContactArtifactViewer.contactNameLabel.text")); // NOI18N - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 0; - gridBagConstraints.gridy = 0; - gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; - gridBagConstraints.ipadx = 111; - gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; - gridBagConstraints.weightx = 1.0; - namePanel.add(contactNameLabel, gridBagConstraints); - - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 0; - gridBagConstraints.gridy = 1; - gridBagConstraints.gridwidth = 5; - gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; - gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; - gridBagConstraints.weightx = 1.0; - gridBagConstraints.insets = new java.awt.Insets(6, 19, 0, 0); - add(namePanel, gridBagConstraints); - - phonesLabel.setFont(phonesLabel.getFont().deriveFont(phonesLabel.getFont().getStyle() | java.awt.Font.BOLD, phonesLabel.getFont().getSize()+2)); - org.openide.awt.Mnemonics.setLocalizedText(phonesLabel, org.openide.util.NbBundle.getMessage(ContactArtifactViewer.class, "ContactArtifactViewer.phonesLabel.text")); // NOI18N - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 0; - gridBagConstraints.gridy = 2; - gridBagConstraints.gridwidth = 3; - gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; - gridBagConstraints.insets = new java.awt.Insets(6, 19, 0, 0); - add(phonesLabel, gridBagConstraints); - - phoneNumbersPanel.setLayout(new java.awt.GridBagLayout()); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 0; - gridBagConstraints.gridy = 3; - gridBagConstraints.gridwidth = 4; - gridBagConstraints.fill = java.awt.GridBagConstraints.VERTICAL; - gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; - gridBagConstraints.insets = new java.awt.Insets(6, 19, 0, 0); - add(phoneNumbersPanel, gridBagConstraints); - - emailsLabel.setFont(emailsLabel.getFont().deriveFont(emailsLabel.getFont().getStyle() | java.awt.Font.BOLD, emailsLabel.getFont().getSize()+2)); - org.openide.awt.Mnemonics.setLocalizedText(emailsLabel, org.openide.util.NbBundle.getMessage(ContactArtifactViewer.class, "ContactArtifactViewer.emailsLabel.text")); // NOI18N - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 0; - gridBagConstraints.gridy = 4; - gridBagConstraints.gridwidth = 2; - gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; - gridBagConstraints.insets = new java.awt.Insets(6, 19, 0, 0); - add(emailsLabel, gridBagConstraints); - - emailsPanel.setLayout(new java.awt.GridBagLayout()); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 0; - gridBagConstraints.gridy = 5; - gridBagConstraints.gridwidth = 4; - gridBagConstraints.fill = java.awt.GridBagConstraints.VERTICAL; - gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; - gridBagConstraints.insets = new java.awt.Insets(6, 19, 0, 0); - add(emailsPanel, gridBagConstraints); - - othersLabel.setFont(othersLabel.getFont().deriveFont(othersLabel.getFont().getStyle() | java.awt.Font.BOLD, othersLabel.getFont().getSize()+2)); - org.openide.awt.Mnemonics.setLocalizedText(othersLabel, org.openide.util.NbBundle.getMessage(ContactArtifactViewer.class, "ContactArtifactViewer.othersLabel.text")); // NOI18N - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 0; - gridBagConstraints.gridy = 6; - gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; - gridBagConstraints.insets = new java.awt.Insets(6, 19, 0, 0); - add(othersLabel, gridBagConstraints); - - otherAttrsPanel.setLayout(new java.awt.GridBagLayout()); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 0; - gridBagConstraints.gridy = 7; - gridBagConstraints.gridwidth = 4; - gridBagConstraints.fill = java.awt.GridBagConstraints.VERTICAL; - gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; - gridBagConstraints.insets = new java.awt.Insets(6, 19, 0, 0); - add(otherAttrsPanel, gridBagConstraints); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 0; - gridBagConstraints.gridy = 8; - gridBagConstraints.gridheight = 2; - gridBagConstraints.fill = java.awt.GridBagConstraints.VERTICAL; - gridBagConstraints.weighty = 0.1; - add(interPanelfiller, gridBagConstraints); - - personasLabel.setFont(personasLabel.getFont().deriveFont(personasLabel.getFont().getStyle() | java.awt.Font.BOLD, personasLabel.getFont().getSize()+2)); - org.openide.awt.Mnemonics.setLocalizedText(personasLabel, org.openide.util.NbBundle.getMessage(ContactArtifactViewer.class, "ContactArtifactViewer.personasLabel.text")); // NOI18N - personasLabel.setMaximumSize(new java.awt.Dimension(90, 19)); - personasLabel.setMinimumSize(new java.awt.Dimension(90, 19)); - personasLabel.setPreferredSize(new java.awt.Dimension(90, 19)); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 0; - gridBagConstraints.gridy = 9; - gridBagConstraints.gridwidth = 3; - gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; - gridBagConstraints.insets = new java.awt.Insets(6, 19, 0, 0); - add(personasLabel, gridBagConstraints); - - personasPanel.setLayout(new java.awt.GridBagLayout()); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 0; - gridBagConstraints.gridy = 10; - gridBagConstraints.gridwidth = 4; - gridBagConstraints.fill = java.awt.GridBagConstraints.VERTICAL; - gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; - gridBagConstraints.insets = new java.awt.Insets(6, 19, 0, 0); - add(personasPanel, gridBagConstraints); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 0; - gridBagConstraints.gridy = 11; - gridBagConstraints.gridwidth = 4; - gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; - gridBagConstraints.weighty = 1.0; - add(bottomFiller, gridBagConstraints); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 4; - gridBagConstraints.gridy = 3; - gridBagConstraints.gridheight = 8; - gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; - gridBagConstraints.ipadx = 2; - gridBagConstraints.weightx = 1.0; - add(rightFiller, gridBagConstraints); - - contactImage.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/defaultContact.png"))); // NOI18N - org.openide.awt.Mnemonics.setLocalizedText(contactImage, org.openide.util.NbBundle.getMessage(ContactArtifactViewer.class, "ContactArtifactViewer.contactImage.text")); // NOI18N - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 0; - gridBagConstraints.gridy = 0; - gridBagConstraints.insets = new java.awt.Insets(6, 19, 0, 0); - add(contactImage, gridBagConstraints); }// //GEN-END:initComponents @Override public void setArtifact(BlackboardArtifact artifact) { - // Reset the panel. resetComponent(); @@ -268,50 +128,16 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac return; } - List phoneNumList = new ArrayList<>(); - List emailList = new ArrayList<>(); - List nameList = new ArrayList<>(); - List otherList = new ArrayList<>(); - List accountAttributesList = new ArrayList<>(); - try { - // Get all the attributes and group them by the section panels they go in - for (BlackboardAttribute bba : artifact.getAttributes()) { - if (bba.getAttributeType().getTypeName().startsWith("TSK_PHONE")) { - phoneNumList.add(bba); - accountAttributesList.add(bba); - } else if (bba.getAttributeType().getTypeName().startsWith("TSK_EMAIL")) { - emailList.add(bba); - accountAttributesList.add(bba); - } else if (bba.getAttributeType().getTypeName().startsWith("TSK_NAME")) { - nameList.add(bba); - } else { - otherList.add(bba); - if (bba.getAttributeType().getTypeName().equalsIgnoreCase("TSK_ID")) { - accountAttributesList.add(bba); - } - } - } + extractArtifactData(artifact); } catch (TskCoreException ex) { logger.log(Level.SEVERE, String.format("Error getting attributes for artifact (artifact_id=%d, obj_id=%d)", artifact.getArtifactID(), artifact.getObjectID()), ex); - } - // update name section - updateNamePanel(nameList); - - // update contact attributes sections - updateSection(phoneNumList, this.phonesLabel, this.phoneNumbersPanel); - updateSection(emailList, this.emailsLabel, this.emailsPanel); - updateSection(otherList, this.othersLabel, this.otherAttrsPanel); - - try { - initiatePersonasSearch(accountAttributesList); - } catch (CentralRepoException ex) { - logger.log(Level.SEVERE, String.format("Error getting Personas for Contact artifact (artifact_id=%d, obj_id=%d)", artifact.getArtifactID(), artifact.getObjectID()), ex); + return; } - contactImage.setIcon(getImageFromArtifact(artifact)); + updateView(); - // repaint + this.setLayout(this.m_gridBagLayout); this.revalidate(); this.repaint(); } @@ -322,200 +148,255 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac return new JScrollPane(this, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); } - /** - * Checks if the given artifact is supported by this viewer. This viewer - * supports TSK_CONTACT artifacts. - * - * @param artifact artifact to check. - * - * @return True if the artifact is supported, false otherwise. - */ @Override public boolean isSupported(BlackboardArtifact artifact) { - return artifact.getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_CONTACT.getTypeID(); + return (artifact != null) && + (artifact.getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_CONTACT.getTypeID()); } /** - * Clears all artifact specific state. + * Extracts data from the artifact to be displayed in the panel. + * + * @param artifact Artifact to show. + * @throws TskCoreException */ - private void resetComponent() { - contactNameLabel.setVisible(false); - emailsLabel.setVisible(false); - emailsPanel.removeAll(); - //namePanel.removeAll(); // this is not dynamically populated, do not remove. - otherAttrsPanel.removeAll(); - othersLabel.setVisible(false); - personasLabel.setVisible(false); - personasPanel.removeAll(); - phoneNumbersPanel.removeAll(); - phonesLabel.setVisible(false); + private void extractArtifactData(BlackboardArtifact artifact) throws TskCoreException { - contactName = null; - contactUniqueAccountsList.clear(); - contactUniquePersonasMap.clear(); - contactImage.setIcon(defaultImage); + this.contactArtifact = artifact; + + phoneNumList = new ArrayList<>(); + emailList = new ArrayList<>(); + nameList = new ArrayList<>(); + otherList = new ArrayList<>(); + accountAttributesList = new ArrayList<>(); + + // Get all the attributes and group them by the section panels they go in + for (BlackboardAttribute bba : contactArtifact.getAttributes()) { + if (bba.getAttributeType().getTypeName().startsWith("TSK_PHONE")) { + phoneNumList.add(bba); + accountAttributesList.add(bba); + } else if (bba.getAttributeType().getTypeName().startsWith("TSK_EMAIL")) { + emailList.add(bba); + accountAttributesList.add(bba); + } else if (bba.getAttributeType().getTypeName().startsWith("TSK_NAME")) { + nameList.add(bba); + } else { + otherList.add(bba); + if (bba.getAttributeType().getTypeName().equalsIgnoreCase("TSK_ID")) { + accountAttributesList.add(bba); + } + } + } + + datasourceName = contactArtifact.getDataSource().getName(); + } + + /** + * Updates the view with the data extracted from the artifact. + */ + private void updateView() { + + // Update contact name, image, phone numbers + updateContactDetails(); + + // update artifact source panel + updateSource(); + + // show a empty Personas panel and kick off a serch for personas + initiatePersonasSearch(); + + } + + /** + * Updates the view with contact's details. + */ + @NbBundle.Messages({ + "ContactArtifactViewer_phones_header=Phone", + "ContactArtifactViewer_emails_header=Email", + "ContactArtifactViewer_others_header=Other",}) + private void updateContactDetails() { + + // update image and name. + updateContactImage(m_gridBagLayout, m_constraints); + updateContactName(m_gridBagLayout, m_constraints); + + // update contact attributes sections + updateContactMethodSection(phoneNumList, Bundle.ContactArtifactViewer_phones_header(), m_gridBagLayout, m_constraints); + updateContactMethodSection(emailList, Bundle.ContactArtifactViewer_emails_header(), m_gridBagLayout, m_constraints); + updateContactMethodSection(otherList, Bundle.ContactArtifactViewer_others_header(), m_gridBagLayout, m_constraints); + } + + /** + * Updates the contact image in the view. + * + * @param contactPanelLayout Panel layout. + * @param contactPanelConstraints Layout constraints. + * + */ + @NbBundle.Messages({ + "ContactArtifactViewer.contactImage.text=",}) + private void updateContactImage(GridBagLayout contactPanelLayout, GridBagConstraints contactPanelConstraints) { + // place the image on the top right corner + Insets savedInsets = contactPanelConstraints.insets; + contactPanelConstraints.gridy = 0; + contactPanelConstraints.gridx = 0; + contactPanelConstraints.insets = new Insets(0, 0, 0, 0); + + javax.swing.JLabel contactImage = new javax.swing.JLabel(); + contactImage.setIcon(getImageFromArtifact(contactArtifact)); + contactImage.setText(Bundle.ContactArtifactViewer_contactImage_text()); + + // add image to top left corner of the page. + CommunicationArtifactViewerHelper.addComponent(this, contactPanelLayout, contactPanelConstraints, contactImage); + CommunicationArtifactViewerHelper.addLineEndGlue(this, contactPanelLayout, contactPanelConstraints); + contactPanelConstraints.gridy++; + + contactPanelConstraints.insets = savedInsets; } /** * Updates the contact name in the view. * - * @param attributesList + * @param contactPanelLayout Panel layout. + * @param contactPanelConstraints Layout constraints. + * */ - private void updateNamePanel(List attributesList) { - for (BlackboardAttribute bba : attributesList) { - if (bba.getAttributeType().getTypeName().startsWith("TSK_NAME")) { + @NbBundle.Messages({ + "ContactArtifactViewer_contactname_unknown=Unknown",}) + private void updateContactName(GridBagLayout contactPanelLayout, GridBagConstraints contactPanelConstraints) { + + boolean foundName = false; + for (BlackboardAttribute bba : this.nameList) { + if (StringUtils.isEmpty(bba.getValueString()) == false) { contactName = bba.getDisplayString(); - contactNameLabel.setText(contactName); - contactNameLabel.setVisible(true); + + CommunicationArtifactViewerHelper.addHeader(this, contactPanelLayout, contactPanelConstraints, contactName); + foundName = true; break; } } - - contactNameLabel.revalidate(); + if (foundName == false) { + CommunicationArtifactViewerHelper.addHeader(this, contactPanelLayout, contactPanelConstraints, Bundle.ContactArtifactViewer_contactname_unknown()); + } } /** * Updates the view by displaying the given list of attributes in the given * section panel. * - * @param sectionAttributesList list of attributes to display. - * @param sectionLabel section name label. - * @param sectionPanel section panel to display the attributes in. + * @param sectionAttributesList List of attributes to display. + * @param sectionLabel Section name label. + * @param contactPanelLayout Panel layout. + * @param contactPanelConstraints Layout constraints. + * */ - private void updateSection(List sectionAttributesList, JLabel sectionLabel, JPanel sectionPanel) { + @NbBundle.Messages({ + "ContactArtifactViewer_plural_suffix=s",}) + private void updateContactMethodSection(List sectionAttributesList, String sectionHeader, GridBagLayout contactPanelLayout, GridBagConstraints contactPanelConstraints) { - // If there are no attributes for tis section, hide the section panel and the section label + // If there are no attributes for this section, do nothing if (sectionAttributesList.isEmpty()) { - sectionLabel.setVisible(false); - sectionPanel.setVisible(false); return; } - // create a gridbag layout to show each attribute on one line - GridBagLayout gridBagLayout = new GridBagLayout(); - GridBagConstraints constraints = new GridBagConstraints(); - constraints.anchor = GridBagConstraints.FIRST_LINE_START; - constraints.gridy = 0; - constraints.insets = new java.awt.Insets(TOP_INSET, LEFT_INSET, 0, 0); - for (BlackboardAttribute bba : sectionAttributesList) { - constraints.fill = GridBagConstraints.NONE; - constraints.weightx = 0; - - constraints.gridx = 0; - - // Add a label for attribute type - javax.swing.JLabel attrTypeLabel = new javax.swing.JLabel(); - String attrLabel = bba.getAttributeType().getDisplayName(); - attrTypeLabel.setText(attrLabel); - - // make type label bold - uncomment if needed. - //attrTypeLabel.setFont(attrTypeLabel.getFont().deriveFont(Font.BOLD, attrTypeLabel.getFont().getSize() )); - gridBagLayout.setConstraints(attrTypeLabel, constraints); - sectionPanel.add(attrTypeLabel); - - // Add the attribute value - constraints.gridx++; - javax.swing.JLabel attrValueLabel = new javax.swing.JLabel(); - attrValueLabel.setText(bba.getValueString()); - gridBagLayout.setConstraints(attrValueLabel, constraints); - sectionPanel.add(attrValueLabel); - - // add a filler to take up rest of the space - constraints.gridx++; - constraints.weightx = 1.0; - constraints.fill = GridBagConstraints.HORIZONTAL; - sectionPanel.add(new javax.swing.Box.Filler(new java.awt.Dimension(0, 0), new java.awt.Dimension(0, 0), new java.awt.Dimension(32767, 0))); - - constraints.gridy++; + String sectionHeaderString = sectionHeader; + if (sectionAttributesList.size() > 1) { + sectionHeaderString = sectionHeaderString.concat(Bundle.ContactArtifactViewer_plural_suffix()); + } + CommunicationArtifactViewerHelper.addHeader(this, contactPanelLayout, contactPanelConstraints, sectionHeaderString); + for (BlackboardAttribute bba : sectionAttributesList) { + CommunicationArtifactViewerHelper.addKey(this, contactPanelLayout, contactPanelConstraints, bba.getAttributeType().getDisplayName()); + CommunicationArtifactViewerHelper.addValue(this, contactPanelLayout, contactPanelConstraints, bba.getDisplayString()); } - - sectionLabel.setVisible(true); - sectionPanel.setVisible(true); - - sectionPanel.setLayout(gridBagLayout); - sectionPanel.revalidate(); - sectionPanel.repaint(); } /** - * Kicks off a search for personas, based in the list of attributes. + * Updates the source section. + */ + @NbBundle.Messages({ + "ContactArtifactViewer_heading_Source=Source", + "ContactArtifactViewer_label_datasource=Data Source",}) + private void updateSource() { + CommunicationArtifactViewerHelper.addHeader(this, this.m_gridBagLayout, m_constraints, Bundle.ContactArtifactViewer_heading_Source()); + CommunicationArtifactViewerHelper.addKey(this, m_gridBagLayout, m_constraints, Bundle.ContactArtifactViewer_label_datasource()); + CommunicationArtifactViewerHelper.addValue(this, m_gridBagLayout, m_constraints, datasourceName); + } + + /** + * Kicks off a search for personas, based in the given list of attributes. * * @param accountAttributesList a list of account identifying attributes. * * @throws CentralRepoException */ - private void initiatePersonasSearch(List accountAttributesList) throws CentralRepoException { + @NbBundle.Messages({ + "ContactArtifactViewer_persona_header=Persona", + "ContactArtifactViewer_persona_searching=Searching...", + "ContactArtifactViewer_cr_disabled_message=Enable Central Repository to view, create and edit personas.", + "ContactArtifactViewer_persona_unknown=Unknown" + }) - personasLabel.setVisible(true); + /** + * Initiates a search for Personas for the accounts associated with the + * Contact. + * + */ + private void initiatePersonasSearch() { - String personaStatusLabelText = CentralRepository.isEnabled() - ? Bundle.ContactArtifactViewer_persona_searching() + // add a section header + JLabel personaHeader = CommunicationArtifactViewerHelper.addHeader(this, m_gridBagLayout, m_constraints, Bundle.ContactArtifactViewer_persona_header()); + + m_constraints.gridy++; + + // add a status label + String personaStatusLabelText = CentralRepository.isEnabled() + ? Bundle.ContactArtifactViewer_persona_searching() : Bundle.ContactArtifactViewer_persona_unknown(); - - // create a gridbag layout to show each participant on one line - GridBagLayout gridBagLayout = new GridBagLayout(); - GridBagConstraints constraints = new GridBagConstraints(); - constraints.anchor = GridBagConstraints.FIRST_LINE_START; - constraints.gridx = 0; - constraints.gridy = 0; - constraints.insets = new java.awt.Insets(TOP_INSET, LEFT_INSET, 0, 0); - // Add a Persona Name label - constraints.fill = GridBagConstraints.NONE; - constraints.weightx = 0; + this.personaSearchStatusLabel = new javax.swing.JLabel(); + personaSearchStatusLabel.setText(personaStatusLabelText); - //javax.swing.Box.Filler filler1 = this.createFiller(5, 0); - //personasPanel.add(filler1, constraints); - javax.swing.JLabel personaLabel = new javax.swing.JLabel(); - personaLabel.setText(Bundle.ContactArtifactViewer_persona_label()); - personaLabel.setFont(personaLabel.getFont().deriveFont(Font.BOLD, personaLabel.getFont().getSize())); - gridBagLayout.setConstraints(personaLabel, constraints); - personasPanel.add(personaLabel); + m_constraints.gridx = 0; - constraints.gridy++; - javax.swing.JLabel personaStatusLabel = new javax.swing.JLabel(); - personaStatusLabel.setText(personaStatusLabelText); - gridBagLayout.setConstraints(personaStatusLabel, constraints); - personasPanel.add(personaStatusLabel); + CommunicationArtifactViewerHelper.addComponent(this, m_gridBagLayout, m_constraints, personaSearchStatusLabel); - - if (CentralRepository.isEnabled() ) { - personasLabel.setEnabled(true); - + if (CentralRepository.isEnabled()) { // Kick off a background task to serach for personas for the contact - ContactPersonaSearcherTask personaSearchTask = new ContactPersonaSearcherTask(accountAttributesList); + personaSearchTask = new ContactPersonaSearcherTask(accountAttributesList); personaSearchTask.execute(); } else { - personasLabel.setEnabled(false); - personaLabel.setEnabled(false); - personaStatusLabel.setEnabled(false); + personaHeader.setEnabled(false); + personaSearchStatusLabel.setEnabled(false); + + CommunicationArtifactViewerHelper.addBlankLine(this, m_gridBagLayout, m_constraints); + m_constraints.gridy++; + CommunicationArtifactViewerHelper.addMessageRow(this, m_gridBagLayout, m_constraints, Bundle.ContactArtifactViewer_cr_disabled_message()); + m_constraints.gridy++; + + CommunicationArtifactViewerHelper.addPageEndGlue(this, m_gridBagLayout, this.m_constraints); } - personasPanel.setLayout(gridBagLayout); - personasPanel.revalidate(); - personasPanel.repaint(); + //m_constraints.insets = savedInsets; } /** * Updates the Persona panel with the gathered persona information. */ - private void updatePersonasPanel() { - // Clear out the panel - personasPanel.removeAll(); + private void updatePersonas() { - GridBagLayout gridBagLayout = new GridBagLayout(); - GridBagConstraints constraints = new GridBagConstraints(); - constraints.anchor = GridBagConstraints.FIRST_LINE_START; - constraints.gridx = 0; - constraints.gridy = 0; - constraints.insets = new java.awt.Insets(TOP_INSET, LEFT_INSET, 0, 0); + // Remove the "Searching....." label + this.remove(personaSearchStatusLabel); + m_constraints.gridx = 0; if (contactUniquePersonasMap.isEmpty()) { - showPersona(null, Collections.emptyList(), gridBagLayout, constraints); + // No persona found - show a button to create one. + showPersona(null, 0, Collections.emptyList(), this.m_gridBagLayout, this.m_constraints); } else { + int matchCounter = 0; for (Map.Entry> entry : contactUniquePersonasMap.entrySet()) { List missingAccounts = new ArrayList<>(); ArrayList personaAccounts = entry.getValue(); + matchCounter++; // create a list of accounts missing from this persona for (CentralRepoAccount account : contactUniqueAccountsList) { @@ -524,52 +405,51 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac } } - showPersona(entry.getKey(), missingAccounts, gridBagLayout, constraints); - - constraints.gridy += 2; + showPersona(entry.getKey(), matchCounter, missingAccounts, m_gridBagLayout, m_constraints); + m_constraints.gridy += 2; } } - personasPanel.setLayout(gridBagLayout); - personasPanel.setSize(personasPanel.getPreferredSize()); - personasPanel.revalidate(); - personasPanel.repaint(); - } + // add veritcal glue at the end + CommunicationArtifactViewerHelper.addPageEndGlue(this, m_gridBagLayout, this.m_constraints); - @NbBundle.Messages({ - //"ContactArtifactViewer_persona_label=Persona ", - //"ContactArtifactViewer_persona_text_none=None found", - //"ContactArtifactViewer_persona_button_view=View", - //"ContactArtifactViewer_persona_button_new=Create", - //"ContactArtifactViewer_missing_account_label=Missing Account: " - }) + // redraw the panel + this.setLayout(this.m_gridBagLayout); + this.revalidate(); + this.repaint(); + } /** * Displays the given persona in the persona panel. * - * @param persona Persona to display. - * @param missingAccountsList List of accounts this persona may be missing. - * @param gridBagLayout Layout to use. - * @param constraints layout constraints. + * @param persona Persona to display. + * @param missingAccountsList List of contact accounts this persona may be + * missing. + * @param gridBagLayout Layout to use. + * @param constraints layout constraints. * * @throws CentralRepoException */ - private void showPersona(Persona persona, List missingAccountsList, GridBagLayout gridBagLayout, GridBagConstraints constraints) { + @NbBundle.Messages({ + "ContactArtifactViewer_persona_label=Persona ", + "ContactArtifactViewer_persona_no_match=No matches found", + "ContactArtifactViewer_persona_button_view=View", + "ContactArtifactViewer_persona_button_new=Create", + "ContactArtifactViewer_persona_match_num=Match ", + "ContactArtifactViewer_missing_account_label=Missing contact account", + "ContactArtifactViewer_found_all_accounts_label=All accounts found." + }) + private void showPersona(Persona persona, int matchNumber, List missingAccountsList, GridBagLayout gridBagLayout, GridBagConstraints constraints) { - constraints.fill = GridBagConstraints.NONE; - constraints.weightx = 0; + // save the original insets + Insets savedInsets = constraints.insets; + + // some label are indented 2x to appear indented w.r.t column above + Insets extraIndentInsets = new java.awt.Insets(0, 2 * CommunicationArtifactViewerHelper.LEFT_INSET, 0, 0); + + // Add a Match X label in col 0. constraints.gridx = 0; - - //javax.swing.Box.Filler filler1 = createFiller(5, 0); - // gridBagLayout.setConstraints(filler1, constraints); - //personasPanel.add(filler1); - // Add a "Persona" label - //constraints.gridx++; - javax.swing.JLabel personaLabel = new javax.swing.JLabel(); - personaLabel.setText(Bundle.ContactArtifactViewer_persona_label()); - personaLabel.setFont(personaLabel.getFont().deriveFont(Font.BOLD, personaLabel.getFont().getSize())); - gridBagLayout.setConstraints(personaLabel, constraints); - personasPanel.add(personaLabel); + javax.swing.JLabel matchNumberLabel = CommunicationArtifactViewerHelper.addKey(this, gridBagLayout, constraints, String.format("%s %d", Bundle.ContactArtifactViewer_persona_match_num(), matchNumber)); javax.swing.JLabel personaNameLabel = new javax.swing.JLabel(); javax.swing.JButton personaButton = new javax.swing.JButton(); @@ -577,59 +457,110 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac String personaName; String personaButtonText; ActionListener personaButtonListener; - if (persona != null) { personaName = persona.getName(); personaButtonText = Bundle.ContactArtifactViewer_persona_button_view(); - personaButtonListener = new ViewPersonaButtonListener(persona); + personaButtonListener = new ViewPersonaButtonListener(this, persona); } else { - personaName = Bundle.ContactArtifactViewer_persona_text_none(); + matchNumberLabel.setVisible(false); + personaName = Bundle.ContactArtifactViewer_persona_no_match(); personaButtonText = Bundle.ContactArtifactViewer_persona_button_new(); - personaButtonListener = new CreatePersonaButtonListener(new PersonaUIComponents(personaNameLabel, personaButton)); + personaButtonListener = new CreatePersonaButtonListener(this, new PersonaUIComponents(personaNameLabel, personaButton)); } - // Add the label for persona name, - constraints.gridy++; - constraints.gridx = 0; + //constraints.gridwidth = 1; // TBD: this may not be needed if we use single panel + constraints.gridx++; personaNameLabel.setText(personaName); gridBagLayout.setConstraints(personaNameLabel, constraints); - personasPanel.add(personaNameLabel); + CommunicationArtifactViewerHelper.addComponent(this, gridBagLayout, constraints, personaNameLabel); + //personasPanel.add(personaNameLabel); - //constraints.gridx++; - //personasPanel.add(createFiller(5, 0), constraints); // Add a Persona action button constraints.gridx++; + //constraints.gridwidth = 1; personaButton.setText(personaButtonText); personaButton.addActionListener(personaButtonListener); - // no top inset of the button, in order to center align with the labels. - constraints.insets = new java.awt.Insets(0, LEFT_INSET, 0, 0); + // Shirnk the button height. + personaButton.setMargin(new Insets(0, 5, 0, 5)); gridBagLayout.setConstraints(personaButton, constraints); - personasPanel.add(personaButton); + CommunicationArtifactViewerHelper.addComponent(this, gridBagLayout, constraints, personaButton); + CommunicationArtifactViewerHelper.addLineEndGlue(this, gridBagLayout, constraints); - // restore normal inset - constraints.insets = new java.awt.Insets(TOP_INSET, LEFT_INSET, 0, 0); + constraints.insets = savedInsets; - // show missing accounts. - for (CentralRepoAccount missingAccount : missingAccountsList) { - constraints.weightx = 0; - constraints.gridx = 0; - constraints.gridy++; + // if we have a persona, indicate if any of the contact's accounts are missing from it. + if (persona != null) { + if (missingAccountsList.isEmpty()) { + constraints.gridy++; + constraints.gridx = 1; + //constraints.insets = labelInsets; - // Add a "Missing Account: " label - constraints.gridx++; // Ident - javax.swing.JLabel missingAccountLabel = new javax.swing.JLabel(); - missingAccountLabel.setText(Bundle.ContactArtifactViewer_missing_account_label()); - gridBagLayout.setConstraints(missingAccountLabel, constraints); - personasPanel.add(missingAccountLabel); + javax.swing.JLabel accountsStatus = new javax.swing.JLabel(Bundle.ContactArtifactViewer_found_all_accounts_label()); + constraints.insets = extraIndentInsets; + CommunicationArtifactViewerHelper.addComponent(this, gridBagLayout, constraints, accountsStatus); + constraints.insets = savedInsets; - // Add the label for account id, - constraints.gridx++; - javax.swing.JLabel missingAccountIdentifierLabel = new javax.swing.JLabel(); - missingAccountIdentifierLabel.setText(missingAccount.getIdentifier()); - gridBagLayout.setConstraints(missingAccountIdentifierLabel, constraints); - personasPanel.add(missingAccountIdentifierLabel); + CommunicationArtifactViewerHelper.addLineEndGlue(this, gridBagLayout, constraints); + } else { + // show missing accounts. + for (CentralRepoAccount missingAccount : missingAccountsList) { + //constraints.weightx = 0; + constraints.gridx = 0; + constraints.gridy++; + + // this needs an extra indent + constraints.insets = extraIndentInsets; + CommunicationArtifactViewerHelper.addKeyAtCol(this, gridBagLayout, constraints, Bundle.ContactArtifactViewer_missing_account_label(), 1); + constraints.insets = savedInsets; + + CommunicationArtifactViewerHelper.addValueAtCol(this, gridBagLayout, constraints, missingAccount.getIdentifier(), 2); + } + } } + + // restore insets + constraints.insets = savedInsets; + } + + /** + * Resets all artifact specific state. + */ + private void resetComponent() { + + contactArtifact = null; + contactName = null; + datasourceName = null; + + contactUniqueAccountsList.clear(); + contactUniquePersonasMap.clear(); + + phoneNumList.clear(); + emailList.clear(); + nameList.clear(); + otherList.clear(); + accountAttributesList.clear(); + + if (personaSearchTask != null) { + personaSearchTask.cancel(Boolean.TRUE); + personaSearchTask = null; + } + + // clear the panel + this.removeAll(); + this.setLayout(null); + + m_gridBagLayout = new GridBagLayout(); + m_constraints = new GridBagConstraints(); + + m_constraints.anchor = GridBagConstraints.FIRST_LINE_START; + m_constraints.gridy = 0; + m_constraints.gridx = 0; + m_constraints.weighty = 0.0; + m_constraints.weightx = 0.0; // keep components fixed horizontally. + m_constraints.insets = new java.awt.Insets(0, CommunicationArtifactViewerHelper.LEFT_INSET, 0, 0); + m_constraints.fill = GridBagConstraints.NONE; + } /** @@ -638,7 +569,7 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac * @param artifact * * @return Image from a TSK_CONTACT artifact or default image if none was - * found or the artifact is not a TSK_CONTACT + * found or the artifact is not a TSK_CONTACT */ private ImageIcon getImageFromArtifact(BlackboardArtifact artifact) { ImageIcon imageIcon = defaultImage; @@ -662,7 +593,7 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac imageIcon = new ImageIcon(image); break; } catch (IOException ex) { - // ImageIO.read will through an IOException if file is not an image + // ImageIO.read will throw an IOException if file is not an image // therefore we don't need to report this exception just try // the next file. } @@ -688,7 +619,7 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac * Creates a persona searcher task. * * @param accountAttributesList List of attributes that may map to - * accounts. + * accounts. */ ContactPersonaSearcherTask(List accountAttributesList) { this.accountAttributesList = accountAttributesList; @@ -699,6 +630,7 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac Map> uniquePersonas = new HashMap<>(); + // TBD: this search needs to change to use the new method CommunicationsManager.getAccountsRelatedToArtifact for (BlackboardAttribute bba : accountAttributesList) { // Get account, add to accounts list @@ -732,7 +664,6 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac } } } - } return uniquePersonas; @@ -754,7 +685,7 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac contactUniqueAccountsList.clear(); contactUniqueAccountsList.addAll(uniqueAccountsList); - updatePersonasPanel(); + updatePersonas(); } catch (CancellationException ex) { logger.log(Level.INFO, "Persona searching was canceled."); //NON-NLS @@ -779,7 +710,7 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac /** * Constructor. * - * @param personaNameLabel Persona name label. + * @param personaNameLabel Persona name label. * @param personaActionButton Persona action button. */ PersonaUIComponents(JLabel personaNameLabel, JButton personaActionButton) { @@ -811,6 +742,7 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac */ private class CreatePersonaButtonListener implements ActionListener { + private final Component parentComponent; private final PersonaUIComponents personaUIComponents; /** @@ -818,19 +750,20 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac * * @param personaUIComponents UI components. */ - CreatePersonaButtonListener(PersonaUIComponents personaUIComponents) { + CreatePersonaButtonListener(Component parentComponent, PersonaUIComponents personaUIComponents) { this.personaUIComponents = personaUIComponents; + this.parentComponent = parentComponent; } @NbBundle.Messages({ - // "ContactArtifactViewer_persona_account_justification=Account found in Contact artifact" + "ContactArtifactViewer_persona_account_justification=Account found in Contact artifact" }) @Override public void actionPerformed(java.awt.event.ActionEvent evt) { // Launch the Persona Create dialog - do not display immediately - PersonaDetailsDialog createPersonaDialog = new PersonaDetailsDialog(ContactArtifactViewer.this, - PersonaDetailsMode.CREATE, null, new PersonaCreateCallbackImpl(personaUIComponents), false); + PersonaDetailsDialog createPersonaDialog = new PersonaDetailsDialog(parentComponent, + PersonaDetailsMode.CREATE, null, new PersonaCreateCallbackImpl(parentComponent, personaUIComponents), false); // Pre populate the persona name and accounts if we have them. PersonaDetailsPanel personaPanel = createPersonaDialog.getDetailsPanel(); @@ -855,19 +788,21 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac private class ViewPersonaButtonListener implements ActionListener { private final Persona persona; + private final Component parentComponent; /** * Creates listener for View persona button. * * @param persona */ - ViewPersonaButtonListener(Persona persona) { + ViewPersonaButtonListener(Component parentComponent, Persona persona) { this.persona = persona; + this.parentComponent = parentComponent; } @Override public void actionPerformed(java.awt.event.ActionEvent evt) { - new PersonaDetailsDialog(ContactArtifactViewer.this, + new PersonaDetailsDialog(parentComponent, PersonaDetailsMode.VIEW, persona, new PersonaViewCallbackImpl()); } } @@ -877,6 +812,7 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac */ class PersonaCreateCallbackImpl implements PersonaDetailsDialogCallback { + private final Component parentComponent; private final PersonaUIComponents personaUIComponents; /** @@ -884,7 +820,8 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac * * @param personaUIComponents UI Components. */ - PersonaCreateCallbackImpl(PersonaUIComponents personaUIComponents) { + PersonaCreateCallbackImpl(Component parentComponent, PersonaUIComponents personaUIComponents) { + this.parentComponent = parentComponent; this.personaUIComponents = personaUIComponents; } @@ -901,7 +838,7 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac for (ActionListener act : personaButton.getActionListeners()) { personaButton.removeActionListener(act); } - personaButton.addActionListener(new ViewPersonaButtonListener(persona)); + personaButton.addActionListener(new ViewPersonaButtonListener(parentComponent, persona)); } @@ -921,18 +858,6 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac } } - // Variables declaration - do not modify//GEN-BEGIN:variables - private javax.swing.JLabel contactImage; - private javax.swing.JLabel contactNameLabel; - private javax.swing.JLabel emailsLabel; - private javax.swing.JPanel emailsPanel; - private javax.swing.JPanel namePanel; - private javax.swing.JPanel otherAttrsPanel; - private javax.swing.JLabel othersLabel; - private javax.swing.JLabel personasLabel; - private javax.swing.JPanel personasPanel; - private javax.swing.JPanel phoneNumbersPanel; - private javax.swing.JLabel phonesLabel; // End of variables declaration//GEN-END:variables } diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/ContactArtifactViewerNew.form b/Core/src/org/sleuthkit/autopsy/contentviewers/ContactArtifactViewerNew.form deleted file mode 100644 index 806a0e3de5..0000000000 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/ContactArtifactViewerNew.form +++ /dev/null @@ -1,21 +0,0 @@ - - -
- - - - - - - - - - - - - - - - - - diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/ContactArtifactViewerNew.java b/Core/src/org/sleuthkit/autopsy/contentviewers/ContactArtifactViewerNew.java deleted file mode 100644 index c6261bf5ff..0000000000 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/ContactArtifactViewerNew.java +++ /dev/null @@ -1,863 +0,0 @@ -/* - * Autopsy Forensic Browser - * - * Copyright 2020 Basis Technology Corp. - * Contact: carrier sleuthkit org - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.sleuthkit.autopsy.contentviewers; - -import java.awt.Component; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.Insets; -import java.awt.event.ActionListener; -import java.awt.image.BufferedImage; -import java.io.File; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.CancellationException; -import java.util.concurrent.ExecutionException; -import java.util.logging.Level; -import java.util.stream.Collectors; -import javax.imageio.ImageIO; -import javax.swing.ImageIcon; -import javax.swing.JButton; -import javax.swing.JLabel; -import javax.swing.JScrollPane; -import javax.swing.SwingWorker; -import org.apache.commons.lang.StringUtils; -import org.openide.util.NbBundle; -import org.openide.util.lookup.ServiceProvider; -import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepoAccount; -import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepoException; -import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository; -import org.sleuthkit.autopsy.centralrepository.datamodel.Persona; -import org.sleuthkit.autopsy.centralrepository.datamodel.PersonaAccount; -import org.sleuthkit.autopsy.centralrepository.persona.PersonaDetailsDialog; -import org.sleuthkit.autopsy.centralrepository.persona.PersonaDetailsDialogCallback; -import org.sleuthkit.autopsy.centralrepository.persona.PersonaDetailsMode; -import org.sleuthkit.autopsy.centralrepository.persona.PersonaDetailsPanel; -import org.sleuthkit.autopsy.coreutils.Logger; -import org.sleuthkit.datamodel.AbstractFile; -import org.sleuthkit.datamodel.BlackboardArtifact; -import org.sleuthkit.datamodel.BlackboardAttribute; -import org.sleuthkit.datamodel.Content; -import org.sleuthkit.datamodel.TskCoreException; - -/** - * This class displays the TSK_CONTACT artifact. - */ -@ServiceProvider(service = ArtifactContentViewer.class) -public class ContactArtifactViewerNew extends javax.swing.JPanel implements ArtifactContentViewer { - - private final static Logger logger = Logger.getLogger(ContactArtifactViewer.class.getName()); - private static final long serialVersionUID = 1L; - - //private final static int LEFT_INSET = 12; - private GridBagLayout m_gridBagLayout = new GridBagLayout(); - private GridBagConstraints m_constraints = new GridBagConstraints(); - - private JLabel personaSearchStatusLabel; - - private BlackboardArtifact contactArtifact; - private String contactName; - private String datasourceName; - - private List phoneNumList = new ArrayList<>(); - private List emailList = new ArrayList<>(); - private List nameList = new ArrayList<>(); - private List otherList = new ArrayList<>(); - private List accountAttributesList = new ArrayList<>(); - - private final static String DEFAULT_IMAGE_PATH = "/org/sleuthkit/autopsy/images/defaultContact.png"; - private final ImageIcon defaultImage; - - // A list of unique accounts matching the attributes of the contact artifact. - private final List contactUniqueAccountsList = new ArrayList<>(); - - // A list of all unique personas and their account, found by searching on the - // account identifier attributes of the Contact artifact. - private final Map> contactUniquePersonasMap = new HashMap<>(); - - private ContactPersonaSearcherTask personaSearchTask; - - /** - * Creates new form ContactArtifactViewer - */ - public ContactArtifactViewerNew() { - initComponents(); - - defaultImage = new ImageIcon(ContactArtifactViewer.class.getResource(DEFAULT_IMAGE_PATH)); - } - - /** - * This method is called from within the constructor to initialize the form. - * WARNING: Do NOT modify this code. The content of this method is always - * regenerated by the Form Editor. - */ - @SuppressWarnings("unchecked") - // //GEN-BEGIN:initComponents - private void initComponents() { - - setToolTipText(""); // NOI18N - setLayout(new java.awt.GridBagLayout()); - }// //GEN-END:initComponents - - @Override - public void setArtifact(BlackboardArtifact artifact) { - // Reset the panel. - resetComponent(); - - if (artifact == null) { - return; - } - - try { - extractArtifactData(artifact); - } catch (TskCoreException ex) { - logger.log(Level.SEVERE, String.format("Error getting attributes for artifact (artifact_id=%d, obj_id=%d)", artifact.getArtifactID(), artifact.getObjectID()), ex); - return; - } - - updateView(); - - this.setLayout(this.m_gridBagLayout); - this.revalidate(); - this.repaint(); - } - - @Override - public Component getComponent() { - // Slap a vertical scrollbar on the panel. - return new JScrollPane(this, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); - } - - @Override - public boolean isSupported(BlackboardArtifact artifact) { - return artifact.getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_CONTACT.getTypeID(); - } - - /** - * Extracts data from the artifact to be displayed in the panel. - * - * @param artifact Artifact to show. - * @throws TskCoreException - */ - private void extractArtifactData(BlackboardArtifact artifact) throws TskCoreException { - - this.contactArtifact = artifact; - - phoneNumList = new ArrayList<>(); - emailList = new ArrayList<>(); - nameList = new ArrayList<>(); - otherList = new ArrayList<>(); - accountAttributesList = new ArrayList<>(); - - // Get all the attributes and group them by the section panels they go in - for (BlackboardAttribute bba : contactArtifact.getAttributes()) { - if (bba.getAttributeType().getTypeName().startsWith("TSK_PHONE")) { - phoneNumList.add(bba); - accountAttributesList.add(bba); - } else if (bba.getAttributeType().getTypeName().startsWith("TSK_EMAIL")) { - emailList.add(bba); - accountAttributesList.add(bba); - } else if (bba.getAttributeType().getTypeName().startsWith("TSK_NAME")) { - nameList.add(bba); - } else { - otherList.add(bba); - if (bba.getAttributeType().getTypeName().equalsIgnoreCase("TSK_ID")) { - accountAttributesList.add(bba); - } - } - } - - datasourceName = contactArtifact.getDataSource().getName(); - } - - /** - * Updates the view with the data extracted from the artifact. - */ - private void updateView() { - - // Update contact name, image, phone numbers - updateContactDetails(); - - // update artifact source panel - updateSource(); - - // show a empty Personas panel and kick off a serch for personas - initiatePersonasSearch(); - - } - - /** - * Updates the view with contact's details. - */ - @NbBundle.Messages({ - "ContactArtifactViewer_phones_header=Phone", - "ContactArtifactViewer_emails_header=Email", - "ContactArtifactViewer_others_header=Other",}) - private void updateContactDetails() { - - // update image and name. - updateContactImage(m_gridBagLayout, m_constraints); - updateContactName(m_gridBagLayout, m_constraints); - - // update contact attributes sections - updateContactMethodSection(phoneNumList, Bundle.ContactArtifactViewer_phones_header(), m_gridBagLayout, m_constraints); - updateContactMethodSection(emailList, Bundle.ContactArtifactViewer_emails_header(), m_gridBagLayout, m_constraints); - updateContactMethodSection(otherList, Bundle.ContactArtifactViewer_others_header(), m_gridBagLayout, m_constraints); - } - - /** - * Updates the contact image in the view. - * - * @param contactPanelLayout Panel layout. - * @param contactPanelConstraints Layout constraints. - * - */ - @NbBundle.Messages({ - "ContactArtifactViewer.contactImage.text=",}) - private void updateContactImage(GridBagLayout contactPanelLayout, GridBagConstraints contactPanelConstraints) { - // place the image on the top right corner - Insets savedInsets = contactPanelConstraints.insets; - contactPanelConstraints.gridy = 0; - contactPanelConstraints.gridx = 0; - contactPanelConstraints.insets = new Insets(0, 0, 0, 0); - - javax.swing.JLabel contactImage = new javax.swing.JLabel(); - contactImage.setIcon(getImageFromArtifact(contactArtifact)); - contactImage.setText(Bundle.ContactArtifactViewer_contactImage_text()); - - // add image to top left corner of the page. - CommunicationArtifactViewerHelper.addComponent(this, contactPanelLayout, contactPanelConstraints, contactImage); - CommunicationArtifactViewerHelper.addLineEndGlue(this, contactPanelLayout, contactPanelConstraints); - contactPanelConstraints.gridy++; - - contactPanelConstraints.insets = savedInsets; - } - - /** - * Updates the contact name in the view. - * - * @param contactPanelLayout Panel layout. - * @param contactPanelConstraints Layout constraints. - * - */ - @NbBundle.Messages({ - "ContactArtifactViewer_contactname_unknown=Unknown",}) - private void updateContactName(GridBagLayout contactPanelLayout, GridBagConstraints contactPanelConstraints) { - - boolean foundName = false; - for (BlackboardAttribute bba : this.nameList) { - if (StringUtils.isEmpty(bba.getValueString()) == false) { - contactName = bba.getDisplayString(); - - CommunicationArtifactViewerHelper.addHeader(this, contactPanelLayout, contactPanelConstraints, contactName); - foundName = true; - break; - } - } - if (foundName == false) { - CommunicationArtifactViewerHelper.addHeader(this, contactPanelLayout, contactPanelConstraints, Bundle.ContactArtifactViewer_contactname_unknown()); - } - } - - /** - * Updates the view by displaying the given list of attributes in the given - * section panel. - * - * @param sectionAttributesList List of attributes to display. - * @param sectionLabel Section name label. - * @param contactPanelLayout Panel layout. - * @param contactPanelConstraints Layout constraints. - * - */ - @NbBundle.Messages({ - "ContactArtifactViewer_plural_suffix=s",}) - private void updateContactMethodSection(List sectionAttributesList, String sectionHeader, GridBagLayout contactPanelLayout, GridBagConstraints contactPanelConstraints) { - - // If there are no attributes for this section, do nothing - if (sectionAttributesList.isEmpty()) { - return; - } - - String sectionHeaderString = sectionHeader; - if (sectionAttributesList.size() > 1) { - sectionHeaderString = sectionHeaderString.concat(Bundle.ContactArtifactViewer_plural_suffix()); - } - CommunicationArtifactViewerHelper.addHeader(this, contactPanelLayout, contactPanelConstraints, sectionHeaderString); - for (BlackboardAttribute bba : sectionAttributesList) { - CommunicationArtifactViewerHelper.addKey(this, contactPanelLayout, contactPanelConstraints, bba.getAttributeType().getDisplayName()); - CommunicationArtifactViewerHelper.addValue(this, contactPanelLayout, contactPanelConstraints, bba.getDisplayString()); - } - } - - /** - * Updates the source section. - */ - @NbBundle.Messages({ - "ContactArtifactViewer_heading_Source=Source", - "ContactArtifactViewer_label_datasource=Data Source",}) - private void updateSource() { - CommunicationArtifactViewerHelper.addHeader(this, this.m_gridBagLayout, m_constraints, Bundle.ContactArtifactViewer_heading_Source()); - CommunicationArtifactViewerHelper.addKey(this, m_gridBagLayout, m_constraints, Bundle.ContactArtifactViewer_label_datasource()); - CommunicationArtifactViewerHelper.addValue(this, m_gridBagLayout, m_constraints, datasourceName); - } - - /** - * Kicks off a search for personas, based in the given list of attributes. - * - * @param accountAttributesList a list of account identifying attributes. - * - * @throws CentralRepoException - */ - @NbBundle.Messages({ - "ContactArtifactViewer_persona_header=Persona", - "ContactArtifactViewer_persona_searching=Searching...", - "ContactArtifactViewer_cr_disabled_message=Enable Central Repository to view, create and edit personas.", - "ContactArtifactViewer_persona_unknown=Unknown" - }) - - /** - * Initiates a search for Personas for the accounts associated with the - * Contact. - * - */ - private void initiatePersonasSearch() { - - // add a section header - JLabel personaHeader = CommunicationArtifactViewerHelper.addHeader(this, m_gridBagLayout, m_constraints, Bundle.ContactArtifactViewer_persona_header()); - - m_constraints.gridy++; - - // add a status label - String personaStatusLabelText = CentralRepository.isEnabled() - ? Bundle.ContactArtifactViewer_persona_searching() - : Bundle.ContactArtifactViewer_persona_unknown(); - - this.personaSearchStatusLabel = new javax.swing.JLabel(); - personaSearchStatusLabel.setText(personaStatusLabelText); - - m_constraints.gridx = 0; - - CommunicationArtifactViewerHelper.addComponent(this, m_gridBagLayout, m_constraints, personaSearchStatusLabel); - - if (CentralRepository.isEnabled()) { - // Kick off a background task to serach for personas for the contact - personaSearchTask = new ContactPersonaSearcherTask(accountAttributesList); - personaSearchTask.execute(); - } else { - personaHeader.setEnabled(false); - personaSearchStatusLabel.setEnabled(false); - - CommunicationArtifactViewerHelper.addBlankLine(this, m_gridBagLayout, m_constraints); - m_constraints.gridy++; - CommunicationArtifactViewerHelper.addMessageRow(this, m_gridBagLayout, m_constraints, Bundle.ContactArtifactViewer_cr_disabled_message()); - m_constraints.gridy++; - - CommunicationArtifactViewerHelper.addPageEndGlue(this, m_gridBagLayout, this.m_constraints); - } - - //m_constraints.insets = savedInsets; - } - - /** - * Updates the Persona panel with the gathered persona information. - */ - private void updatePersonas() { - - // Remove the "Searching....." label - this.remove(personaSearchStatusLabel); - - m_constraints.gridx = 0; - if (contactUniquePersonasMap.isEmpty()) { - // No persona found - show a button to create one. - showPersona(null, 0, Collections.emptyList(), this.m_gridBagLayout, this.m_constraints); - } else { - int matchCounter = 0; - for (Map.Entry> entry : contactUniquePersonasMap.entrySet()) { - List missingAccounts = new ArrayList<>(); - ArrayList personaAccounts = entry.getValue(); - matchCounter++; - - // create a list of accounts missing from this persona - for (CentralRepoAccount account : contactUniqueAccountsList) { - if (personaAccounts.contains(account) == false) { - missingAccounts.add(account); - } - } - - showPersona(entry.getKey(), matchCounter, missingAccounts, m_gridBagLayout, m_constraints); - m_constraints.gridy += 2; - } - } - - // add veritcal glue at the end - CommunicationArtifactViewerHelper.addPageEndGlue(this, m_gridBagLayout, this.m_constraints); - - // redraw the panel - this.setLayout(this.m_gridBagLayout); - this.revalidate(); - this.repaint(); - } - - /** - * Displays the given persona in the persona panel. - * - * @param persona Persona to display. - * @param missingAccountsList List of contact accounts this persona may be - * missing. - * @param gridBagLayout Layout to use. - * @param constraints layout constraints. - * - * @throws CentralRepoException - */ - @NbBundle.Messages({ - "ContactArtifactViewer_persona_label=Persona ", - "ContactArtifactViewer_persona_no_match=No matches found", - "ContactArtifactViewer_persona_button_view=View", - "ContactArtifactViewer_persona_button_new=Create", - "ContactArtifactViewer_persona_match_num=Match ", - "ContactArtifactViewer_missing_account_label=Missing contact account", - "ContactArtifactViewer_found_all_accounts_label=All accounts found." - }) - private void showPersona(Persona persona, int matchNumber, List missingAccountsList, GridBagLayout gridBagLayout, GridBagConstraints constraints) { - - // save the original insets - Insets savedInsets = constraints.insets; - - // some label are indented 2x to appear indented w.r.t column above - Insets extraIndentInsets = new java.awt.Insets(0, 2 * CommunicationArtifactViewerHelper.LEFT_INSET, 0, 0); - - // Add a Match X label in col 0. - constraints.gridx = 0; - javax.swing.JLabel matchNumberLabel = CommunicationArtifactViewerHelper.addKey(this, gridBagLayout, constraints, String.format("%s %d", Bundle.ContactArtifactViewer_persona_match_num(), matchNumber)); - - javax.swing.JLabel personaNameLabel = new javax.swing.JLabel(); - javax.swing.JButton personaButton = new javax.swing.JButton(); - - String personaName; - String personaButtonText; - ActionListener personaButtonListener; - if (persona != null) { - personaName = persona.getName(); - personaButtonText = Bundle.ContactArtifactViewer_persona_button_view(); - personaButtonListener = new ViewPersonaButtonListener(this, persona); - } else { - matchNumberLabel.setVisible(false); - personaName = Bundle.ContactArtifactViewer_persona_no_match(); - personaButtonText = Bundle.ContactArtifactViewer_persona_button_new(); - personaButtonListener = new CreatePersonaButtonListener(this, new PersonaUIComponents(personaNameLabel, personaButton)); - } - - //constraints.gridwidth = 1; // TBD: this may not be needed if we use single panel - constraints.gridx++; - personaNameLabel.setText(personaName); - gridBagLayout.setConstraints(personaNameLabel, constraints); - CommunicationArtifactViewerHelper.addComponent(this, gridBagLayout, constraints, personaNameLabel); - //personasPanel.add(personaNameLabel); - - // Add a Persona action button - constraints.gridx++; - //constraints.gridwidth = 1; - personaButton.setText(personaButtonText); - personaButton.addActionListener(personaButtonListener); - - // Shirnk the button height. - personaButton.setMargin(new Insets(0, 5, 0, 5)); - gridBagLayout.setConstraints(personaButton, constraints); - CommunicationArtifactViewerHelper.addComponent(this, gridBagLayout, constraints, personaButton); - CommunicationArtifactViewerHelper.addLineEndGlue(this, gridBagLayout, constraints); - - constraints.insets = savedInsets; - - // if we have a persona, indicate if any of the contact's accounts are missing from it. - if (persona != null) { - if (missingAccountsList.isEmpty()) { - constraints.gridy++; - constraints.gridx = 1; - //constraints.insets = labelInsets; - - javax.swing.JLabel accountsStatus = new javax.swing.JLabel(Bundle.ContactArtifactViewer_found_all_accounts_label()); - constraints.insets = extraIndentInsets; - CommunicationArtifactViewerHelper.addComponent(this, gridBagLayout, constraints, accountsStatus); - constraints.insets = savedInsets; - - CommunicationArtifactViewerHelper.addLineEndGlue(this, gridBagLayout, constraints); - } else { - // show missing accounts. - for (CentralRepoAccount missingAccount : missingAccountsList) { - //constraints.weightx = 0; - constraints.gridx = 0; - constraints.gridy++; - - // this needs an extra indent - constraints.insets = extraIndentInsets; - CommunicationArtifactViewerHelper.addKeyAtCol(this, gridBagLayout, constraints, Bundle.ContactArtifactViewer_missing_account_label(), 1); - constraints.insets = savedInsets; - - CommunicationArtifactViewerHelper.addValueAtCol(this, gridBagLayout, constraints, missingAccount.getIdentifier(), 2); - } - } - } - - // restore insets - constraints.insets = savedInsets; - } - - /** - * Resets all artifact specific state. - */ - private void resetComponent() { - - contactArtifact = null; - contactName = null; - datasourceName = null; - - contactUniqueAccountsList.clear(); - contactUniquePersonasMap.clear(); - - phoneNumList.clear(); - emailList.clear(); - nameList.clear(); - otherList.clear(); - accountAttributesList.clear(); - - if (personaSearchTask != null) { - personaSearchTask.cancel(Boolean.TRUE); - personaSearchTask = null; - } - - // clear the panel - this.removeAll(); - this.setLayout(null); - - m_gridBagLayout = new GridBagLayout(); - m_constraints = new GridBagConstraints(); - - m_constraints.anchor = GridBagConstraints.FIRST_LINE_START; - m_constraints.gridy = 0; - m_constraints.gridx = 0; - m_constraints.weighty = 0.0; - m_constraints.weightx = 0.0; // keep components fixed horizontally. - m_constraints.insets = new java.awt.Insets(0, CommunicationArtifactViewerHelper.LEFT_INSET, 0, 0); - m_constraints.fill = GridBagConstraints.NONE; - - } - - /** - * Gets an image from a TSK_CONTACT artifact. - * - * @param artifact - * - * @return Image from a TSK_CONTACT artifact or default image if none was - * found or the artifact is not a TSK_CONTACT - */ - private ImageIcon getImageFromArtifact(BlackboardArtifact artifact) { - ImageIcon imageIcon = defaultImage; - - if (artifact == null) { - return imageIcon; - } - - BlackboardArtifact.ARTIFACT_TYPE artifactType = BlackboardArtifact.ARTIFACT_TYPE.fromID(artifact.getArtifactTypeID()); - if (artifactType != BlackboardArtifact.ARTIFACT_TYPE.TSK_CONTACT) { - return imageIcon; - } - - try { - for (Content content : artifact.getChildren()) { - if (content instanceof AbstractFile) { - AbstractFile file = (AbstractFile) content; - - try { - BufferedImage image = ImageIO.read(new File(file.getLocalAbsPath())); - imageIcon = new ImageIcon(image); - break; - } catch (IOException ex) { - // ImageIO.read will throw an IOException if file is not an image - // therefore we don't need to report this exception just try - // the next file. - } - } - } - } catch (TskCoreException ex) { - logger.log(Level.WARNING, String.format("Unable to load image for contact: %d", artifact.getId()), ex); - } - - return imageIcon; - } - - /** - * Thread to search for a personas for all account identifier attributes for - * a contact. - */ - private class ContactPersonaSearcherTask extends SwingWorker>, Void> { - - private final List accountAttributesList; - private final List uniqueAccountsList = new ArrayList<>(); - - /** - * Creates a persona searcher task. - * - * @param accountAttributesList List of attributes that may map to - * accounts. - */ - ContactPersonaSearcherTask(List accountAttributesList) { - this.accountAttributesList = accountAttributesList; - } - - @Override - protected Map> doInBackground() throws Exception { - - Map> uniquePersonas = new HashMap<>(); - - // TBD: this search needs to change to use the new method CommunicationsManager.getAccountsRelatedToArtifact - for (BlackboardAttribute bba : accountAttributesList) { - - // Get account, add to accounts list - Collection personas; - - Collection accountCandidates - = CentralRepoAccount.getAccountsWithIdentifier(bba.getValueString()); - - if (accountCandidates.isEmpty() == false) { - CentralRepoAccount account = accountCandidates.iterator().next(); - if (uniqueAccountsList.contains(account) == false) { - uniqueAccountsList.add(account); - } - - // get personas for the account - personas = PersonaAccount.getPersonaAccountsForAccount(account.getId()) - .stream() - .map(PersonaAccount::getPersona) - .collect(Collectors.toList()); - - // make a list of unique personas, along with all their accounts - for (Persona persona : personas) { - if (uniquePersonas.containsKey(persona) == false) { - Collection accounts = persona.getPersonaAccounts() - .stream() - .map(PersonaAccount::getAccount) - .collect(Collectors.toList()); - - ArrayList personaAccountsList = new ArrayList<>(accounts); - uniquePersonas.put(persona, personaAccountsList); - } - } - } - } - - return uniquePersonas; - } - - @Override - protected void done() { - - Map> personasMap; - try { - personasMap = super.get(); - - if (this.isCancelled()) { - return; - } - - contactUniquePersonasMap.clear(); - contactUniquePersonasMap.putAll(personasMap); - contactUniqueAccountsList.clear(); - contactUniqueAccountsList.addAll(uniqueAccountsList); - - updatePersonas(); - - } catch (CancellationException ex) { - logger.log(Level.INFO, "Persona searching was canceled."); //NON-NLS - } catch (InterruptedException ex) { - logger.log(Level.INFO, "Persona searching was interrupted."); //NON-NLS - } catch (ExecutionException ex) { - logger.log(Level.SEVERE, "Fatal error during Persona search.", ex); //NON-NLS - } - - } - } - - /** - * A wrapper class that bags the UI components that need to be updated when - * a persona search task or a create dialog returns. - */ - private class PersonaUIComponents { - - private final JLabel personaNameLabel; - private final JButton personaActionButton; - - /** - * Constructor. - * - * @param personaNameLabel Persona name label. - * @param personaActionButton Persona action button. - */ - PersonaUIComponents(JLabel personaNameLabel, JButton personaActionButton) { - this.personaNameLabel = personaNameLabel; - this.personaActionButton = personaActionButton; - } - - /** - * Returns persona name label. - * - * @return Persona name label. - */ - public JLabel getPersonaNameLabel() { - return personaNameLabel; - } - - /** - * Returns persona action button. - * - * @return Persona action button. - */ - public JButton getPersonaActionButton() { - return personaActionButton; - } - } - - /** - * Action listener for Create persona button. - */ - private class CreatePersonaButtonListener implements ActionListener { - - private final Component parentComponent; - private final PersonaUIComponents personaUIComponents; - - /** - * Constructs a listener for Create persona button.. - * - * @param personaUIComponents UI components. - */ - CreatePersonaButtonListener(Component parentComponent, PersonaUIComponents personaUIComponents) { - this.personaUIComponents = personaUIComponents; - this.parentComponent = parentComponent; - } - - @NbBundle.Messages({ - "ContactArtifactViewer_persona_account_justification=Account found in Contact artifact" - }) - - @Override - public void actionPerformed(java.awt.event.ActionEvent evt) { - // Launch the Persona Create dialog - do not display immediately - PersonaDetailsDialog createPersonaDialog = new PersonaDetailsDialog(parentComponent, - PersonaDetailsMode.CREATE, null, new PersonaCreateCallbackImpl(parentComponent, personaUIComponents), false); - - // Pre populate the persona name and accounts if we have them. - PersonaDetailsPanel personaPanel = createPersonaDialog.getDetailsPanel(); - - if (contactName != null) { - personaPanel.setPersonaName(contactName); - } - - // pass the list of accounts to the dialog - for (CentralRepoAccount account : contactUniqueAccountsList) { - personaPanel.addAccount(account, Bundle.ContactArtifactViewer_persona_account_justification(), Persona.Confidence.HIGH); - } - - // display the dialog now - createPersonaDialog.display(); - } - } - - /** - * Action listener for View persona button. - */ - private class ViewPersonaButtonListener implements ActionListener { - - private final Persona persona; - private final Component parentComponent; - - /** - * Creates listener for View persona button. - * - * @param persona - */ - ViewPersonaButtonListener(Component parentComponent, Persona persona) { - this.persona = persona; - this.parentComponent = parentComponent; - } - - @Override - public void actionPerformed(java.awt.event.ActionEvent evt) { - new PersonaDetailsDialog(parentComponent, - PersonaDetailsMode.VIEW, persona, new PersonaViewCallbackImpl()); - } - } - - /** - * Callback method for the create mode of the PersonaDetailsDialog - */ - class PersonaCreateCallbackImpl implements PersonaDetailsDialogCallback { - - private final Component parentComponent; - private final PersonaUIComponents personaUIComponents; - - /** - * Creates a callback to handle new persona creation. - * - * @param personaUIComponents UI Components. - */ - PersonaCreateCallbackImpl(Component parentComponent, PersonaUIComponents personaUIComponents) { - this.parentComponent = parentComponent; - this.personaUIComponents = personaUIComponents; - } - - @Override - public void callback(Persona persona) { - JButton personaButton = personaUIComponents.getPersonaActionButton(); - if (persona != null) { - // update the persona name label with newly created persona, - // and change the button to a "View" button - personaUIComponents.getPersonaNameLabel().setText(persona.getName()); - personaUIComponents.getPersonaActionButton().setText(Bundle.ContactArtifactViewer_persona_button_view()); - - // replace action listener with a View button listener - for (ActionListener act : personaButton.getActionListeners()) { - personaButton.removeActionListener(act); - } - personaButton.addActionListener(new ViewPersonaButtonListener(parentComponent, persona)); - - } - - personaButton.getParent().revalidate(); - personaButton.getParent().repaint(); - } - } - - /** - * Callback method for the view mode of the PersonaDetailsDialog - */ - class PersonaViewCallbackImpl implements PersonaDetailsDialogCallback { - - @Override - public void callback(Persona persona) { - // nothing to do - } - } - - // Variables declaration - do not modify//GEN-BEGIN:variables - // End of variables declaration//GEN-END:variables -}