Autopsy  4.17.0
Graphical digital forensics platform for The Sleuth Kit and other tools.
ContactArtifactViewer.java
Go to the documentation of this file.
1 /*
2  * Autopsy Forensic Browser
3  *
4  * Copyright 2020 Basis Technology Corp.
5  * Contact: carrier <at> sleuthkit <dot> org
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19 package org.sleuthkit.autopsy.contentviewers.artifactviewers;
20 
21 import java.awt.Component;
22 import java.awt.GridBagConstraints;
23 import java.awt.GridBagLayout;
24 import java.awt.Insets;
25 import java.awt.event.ActionListener;
26 import java.awt.image.BufferedImage;
27 import java.io.File;
28 import java.io.IOException;
29 import java.util.ArrayList;
30 import java.util.Collection;
31 import java.util.Collections;
32 import java.util.HashMap;
33 import java.util.List;
34 import java.util.Map;
35 import java.util.concurrent.CancellationException;
36 import java.util.concurrent.ExecutionException;
37 import java.util.logging.Level;
38 import java.util.stream.Collectors;
39 import javax.imageio.ImageIO;
40 import javax.swing.ImageIcon;
41 import javax.swing.JButton;
42 import javax.swing.JLabel;
43 import javax.swing.JOptionPane;
44 import javax.swing.JScrollPane;
45 import javax.swing.SwingWorker;
46 import org.apache.commons.lang.StringUtils;
47 import org.openide.util.NbBundle;
48 import org.openide.util.lookup.ServiceProvider;
60 import org.sleuthkit.datamodel.AbstractFile;
61 import org.sleuthkit.datamodel.Account;
62 import org.sleuthkit.datamodel.BlackboardArtifact;
63 import org.sleuthkit.datamodel.BlackboardAttribute;
64 import org.sleuthkit.datamodel.CommunicationsManager;
65 import org.sleuthkit.datamodel.Content;
66 import org.sleuthkit.datamodel.TskCoreException;
67 
71 @ServiceProvider(service = ArtifactContentViewer.class)
72 public class ContactArtifactViewer extends javax.swing.JPanel implements ArtifactContentViewer {
73 
74  private final static Logger logger = Logger.getLogger(ContactArtifactViewer.class.getName());
75  private static final long serialVersionUID = 1L;
76 
77  private GridBagLayout m_gridBagLayout = new GridBagLayout();
78  private GridBagConstraints m_constraints = new GridBagConstraints();
79 
80  private JLabel personaSearchStatusLabel;
81 
82  private BlackboardArtifact contactArtifact;
83  private String contactName;
84  private String datasourceName;
85 
86  private List<BlackboardAttribute> phoneNumList = new ArrayList<>();
87  private List<BlackboardAttribute> emailList = new ArrayList<>();
88  private List<BlackboardAttribute> nameList = new ArrayList<>();
89  private List<BlackboardAttribute> otherList = new ArrayList<>();
90  private List<BlackboardAttribute> accountAttributesList = new ArrayList<>();
91 
92  private final static String DEFAULT_IMAGE_PATH = "/org/sleuthkit/autopsy/images/defaultContact.png";
93  private final ImageIcon defaultImage;
94 
95  // A list of unique accounts matching the attributes of the contact artifact.
96  private final List<CentralRepoAccount> contactUniqueAccountsList = new ArrayList<>();
97 
98  // A list of all unique personas and their account, found by searching on the
99  // account identifier attributes of the Contact artifact.
100  private final Map<Persona, ArrayList<CentralRepoAccount>> contactUniquePersonasMap = new HashMap<>();
101 
103 
108  initComponents();
109 
110  defaultImage = new ImageIcon(ContactArtifactViewer.class.getResource(DEFAULT_IMAGE_PATH));
111  }
112 
118  @SuppressWarnings("unchecked")
119  // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
120  private void initComponents() {
121 
122  setToolTipText(""); // NOI18N
123  setLayout(new java.awt.GridBagLayout());
124  }// </editor-fold>//GEN-END:initComponents
125 
126  @Override
127  public void setArtifact(BlackboardArtifact artifact) {
128  // Reset the panel.
129  resetComponent();
130 
131  if (artifact == null) {
132  return;
133  }
134 
135  try {
136  extractArtifactData(artifact);
137  } catch (TskCoreException ex) {
138  logger.log(Level.SEVERE, String.format("Error getting attributes for artifact (artifact_id=%d, obj_id=%d)", artifact.getArtifactID(), artifact.getObjectID()), ex);
139  return;
140  }
141 
142  updateView();
143 
144  this.setLayout(this.m_gridBagLayout);
145  this.revalidate();
146  this.repaint();
147  }
148 
149  @Override
150  public Component getComponent() {
151  // Slap a vertical scrollbar on the panel.
152  return new JScrollPane(this, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
153  }
154 
155  @Override
156  public boolean isSupported(BlackboardArtifact artifact) {
157  return (artifact != null)
158  && (artifact.getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_CONTACT.getTypeID());
159  }
160 
167  private void extractArtifactData(BlackboardArtifact artifact) throws TskCoreException {
168 
169  this.contactArtifact = artifact;
170 
171  phoneNumList = new ArrayList<>();
172  emailList = new ArrayList<>();
173  nameList = new ArrayList<>();
174  otherList = new ArrayList<>();
175  accountAttributesList = new ArrayList<>();
176 
177  // Get all the attributes and group them by the section panels they go in
178  for (BlackboardAttribute bba : contactArtifact.getAttributes()) {
179  if (bba.getAttributeType().getTypeName().startsWith("TSK_PHONE")) {
180  phoneNumList.add(bba);
181  accountAttributesList.add(bba);
182  } else if (bba.getAttributeType().getTypeName().startsWith("TSK_EMAIL")) {
183  emailList.add(bba);
184  accountAttributesList.add(bba);
185  } else if (bba.getAttributeType().getTypeName().startsWith("TSK_NAME")) {
186  nameList.add(bba);
187  } else {
188  otherList.add(bba);
189  if (bba.getAttributeType().getTypeName().equalsIgnoreCase("TSK_ID")) {
190  accountAttributesList.add(bba);
191  }
192  }
193  }
194 
195  datasourceName = contactArtifact.getDataSource().getName();
196  }
197 
201  private void updateView() {
202 
203  // Update contact name, image, phone numbers
204  updateContactDetails();
205 
206  // update artifact source panel
207  updateSource();
208 
209  // show a empty Personas panel and kick off a serch for personas
210  initiatePersonasSearch();
211 
212  }
213 
217  @NbBundle.Messages({
218  "ContactArtifactViewer_phones_header=Phone",
219  "ContactArtifactViewer_emails_header=Email",
220  "ContactArtifactViewer_others_header=Other",})
221  private void updateContactDetails() {
222 
223  // update image and name.
224  updateContactImage(m_gridBagLayout, m_constraints);
225  updateContactName(m_gridBagLayout, m_constraints);
226 
227  // update contact attributes sections
228  updateContactMethodSection(phoneNumList, Bundle.ContactArtifactViewer_phones_header(), m_gridBagLayout, m_constraints);
229  updateContactMethodSection(emailList, Bundle.ContactArtifactViewer_emails_header(), m_gridBagLayout, m_constraints);
230  updateContactMethodSection(otherList, Bundle.ContactArtifactViewer_others_header(), m_gridBagLayout, m_constraints);
231  }
232 
240  @NbBundle.Messages({
241  "ContactArtifactViewer.contactImage.text=",})
242  private void updateContactImage(GridBagLayout contactPanelLayout, GridBagConstraints contactPanelConstraints) {
243  // place the image on the top right corner
244  Insets savedInsets = contactPanelConstraints.insets;
245  contactPanelConstraints.gridy = 0;
246  contactPanelConstraints.gridx = 0;
247  contactPanelConstraints.insets = new Insets(0, 0, 0, 0);
248 
249  javax.swing.JLabel contactImage = new javax.swing.JLabel();
250  contactImage.setIcon(getImageFromArtifact(contactArtifact));
251  contactImage.setText(Bundle.ContactArtifactViewer_contactImage_text());
252 
253  // add image to top left corner of the page.
254  CommunicationArtifactViewerHelper.addComponent(this, contactPanelLayout, contactPanelConstraints, contactImage);
255  CommunicationArtifactViewerHelper.addLineEndGlue(this, contactPanelLayout, contactPanelConstraints);
256  contactPanelConstraints.gridy++;
257 
258  contactPanelConstraints.insets = savedInsets;
259  }
260 
268  @NbBundle.Messages({
269  "ContactArtifactViewer_contactname_unknown=Unknown",})
270  private void updateContactName(GridBagLayout contactPanelLayout, GridBagConstraints contactPanelConstraints) {
271 
272  boolean foundName = false;
273  for (BlackboardAttribute bba : this.nameList) {
274  if (StringUtils.isEmpty(bba.getValueString()) == false) {
275  contactName = bba.getDisplayString();
276 
277  CommunicationArtifactViewerHelper.addHeader(this, contactPanelLayout, contactPanelConstraints, contactName);
278  foundName = true;
279  break;
280  }
281  }
282  if (foundName == false) {
283  CommunicationArtifactViewerHelper.addHeader(this, contactPanelLayout, contactPanelConstraints, Bundle.ContactArtifactViewer_contactname_unknown());
284  }
285  }
286 
297  private void updateContactMethodSection(List<BlackboardAttribute> sectionAttributesList, String sectionHeader, GridBagLayout contactPanelLayout, GridBagConstraints contactPanelConstraints) {
298 
299  // If there are no attributes for this section, do nothing
300  if (sectionAttributesList.isEmpty()) {
301  return;
302  }
303 
304  CommunicationArtifactViewerHelper.addHeader(this, contactPanelLayout, contactPanelConstraints, sectionHeader);
305  for (BlackboardAttribute bba : sectionAttributesList) {
306  CommunicationArtifactViewerHelper.addKey(this, contactPanelLayout, contactPanelConstraints, bba.getAttributeType().getDisplayName());
307  CommunicationArtifactViewerHelper.addValue(this, contactPanelLayout, contactPanelConstraints, bba.getDisplayString());
308  }
309  }
310 
314  @NbBundle.Messages({
315  "ContactArtifactViewer_heading_Source=Source",
316  "ContactArtifactViewer_label_datasource=Data Source",})
317  private void updateSource() {
318  CommunicationArtifactViewerHelper.addHeader(this, this.m_gridBagLayout, m_constraints, Bundle.ContactArtifactViewer_heading_Source());
319  CommunicationArtifactViewerHelper.addKey(this, m_gridBagLayout, m_constraints, Bundle.ContactArtifactViewer_label_datasource());
320  CommunicationArtifactViewerHelper.addValue(this, m_gridBagLayout, m_constraints, datasourceName);
321  }
322 
328  @NbBundle.Messages({
329  "ContactArtifactViewer_persona_header=Persona",
330  "ContactArtifactViewer_persona_searching=Searching...",
331  "ContactArtifactViewer_cr_disabled_message=Enable Central Repository to view, create and edit personas.",
332  "ContactArtifactViewer_persona_unknown=Unknown"
333  })
334  private void initiatePersonasSearch() {
335 
336  // add a section header
337  JLabel personaHeader = CommunicationArtifactViewerHelper.addHeader(this, m_gridBagLayout, m_constraints, Bundle.ContactArtifactViewer_persona_header());
338 
339  m_constraints.gridy++;
340 
341  // add a status label
342  String personaStatusLabelText = CentralRepository.isEnabled()
343  ? Bundle.ContactArtifactViewer_persona_searching()
344  : Bundle.ContactArtifactViewer_persona_unknown();
345 
346  this.personaSearchStatusLabel = new javax.swing.JLabel();
347  personaSearchStatusLabel.setText(personaStatusLabelText);
348 
349  m_constraints.gridx = 0;
350 
351  CommunicationArtifactViewerHelper.addComponent(this, m_gridBagLayout, m_constraints, personaSearchStatusLabel);
352 
354  // Kick off a background task to serach for personas for the contact
355  personaSearchTask = new ContactPersonaSearcherTask(contactArtifact);
356  personaSearchTask.execute();
357  } else {
358  personaHeader.setEnabled(false);
359  personaSearchStatusLabel.setEnabled(false);
360 
361  CommunicationArtifactViewerHelper.addBlankLine(this, m_gridBagLayout, m_constraints);
362  m_constraints.gridy++;
363  CommunicationArtifactViewerHelper.addMessageRow(this, m_gridBagLayout, m_constraints, Bundle.ContactArtifactViewer_cr_disabled_message());
364  m_constraints.gridy++;
365 
366  CommunicationArtifactViewerHelper.addPageEndGlue(this, m_gridBagLayout, this.m_constraints);
367  }
368 
369  }
370 
374  private void updatePersonas() {
375 
376  // Remove the "Searching....." label
377  this.remove(personaSearchStatusLabel);
378 
379  m_constraints.gridx = 0;
380  if (contactUniquePersonasMap.isEmpty()) {
381  // No persona found - show a button to create one.
382  showPersona(null, 0, Collections.emptyList(), this.m_gridBagLayout, this.m_constraints);
383  } else {
384  int matchCounter = 0;
385  for (Map.Entry<Persona, ArrayList<CentralRepoAccount>> entry : contactUniquePersonasMap.entrySet()) {
386  List<CentralRepoAccount> missingAccounts = new ArrayList<>();
387  ArrayList<CentralRepoAccount> personaAccounts = entry.getValue();
388  matchCounter++;
389 
390  // create a list of accounts missing from this persona
391  for (CentralRepoAccount account : contactUniqueAccountsList) {
392  if (personaAccounts.contains(account) == false) {
393  missingAccounts.add(account);
394  }
395  }
396 
397  showPersona(entry.getKey(), matchCounter, missingAccounts, m_gridBagLayout, m_constraints);
398  m_constraints.gridy += 2;
399  }
400  }
401 
402  // add veritcal glue at the end
403  CommunicationArtifactViewerHelper.addPageEndGlue(this, m_gridBagLayout, this.m_constraints);
404 
405  // redraw the panel
406  this.setLayout(this.m_gridBagLayout);
407  this.revalidate();
408  this.repaint();
409  }
410 
423  @NbBundle.Messages({
424  "ContactArtifactViewer_persona_label=Persona ",
425  "ContactArtifactViewer_persona_no_match=No matches found",
426  "ContactArtifactViewer_persona_button_view=View",
427  "ContactArtifactViewer_persona_button_new=Create",
428  "ContactArtifactViewer_persona_match_num=Match ",
429  "ContactArtifactViewer_missing_account_label=Missing contact account",
430  "ContactArtifactViewer_found_all_accounts_label=All accounts found."
431  })
432  private void showPersona(Persona persona, int matchNumber, List<CentralRepoAccount> missingAccountsList, GridBagLayout gridBagLayout, GridBagConstraints constraints) {
433 
434  // save the original insets
435  Insets savedInsets = constraints.insets;
436 
437  // some label are indented 2x to appear indented w.r.t column above
438  Insets extraIndentInsets = new java.awt.Insets(0, 2 * CommunicationArtifactViewerHelper.LEFT_INSET, 0, 0);
439 
440  // Add a Match X label in col 0.
441  constraints.gridx = 0;
442  javax.swing.JLabel matchNumberLabel = CommunicationArtifactViewerHelper.addKey(this, gridBagLayout, constraints, String.format("%s %d", Bundle.ContactArtifactViewer_persona_match_num(), matchNumber));
443 
444  javax.swing.JLabel personaNameLabel = new javax.swing.JLabel();
445  javax.swing.JButton personaButton = new javax.swing.JButton();
446 
447  String personaName;
448  String personaButtonText;
449  ActionListener personaButtonListener;
450  if (persona != null) {
451  personaName = persona.getName();
452  personaButtonText = Bundle.ContactArtifactViewer_persona_button_view();
453  personaButtonListener = new ViewPersonaButtonListener(this, persona);
454  } else {
455  matchNumberLabel.setVisible(false);
456  personaName = Bundle.ContactArtifactViewer_persona_no_match();
457  personaButtonText = Bundle.ContactArtifactViewer_persona_button_new();
458  personaButtonListener = new CreatePersonaButtonListener(this, new PersonaUIComponents(personaNameLabel, personaButton));
459  }
460 
461  //constraints.gridwidth = 1; // TBD: this may not be needed if we use single panel
462  constraints.gridx++;
463  personaNameLabel.setText(personaName);
464  gridBagLayout.setConstraints(personaNameLabel, constraints);
465  CommunicationArtifactViewerHelper.addComponent(this, gridBagLayout, constraints, personaNameLabel);
466  //personasPanel.add(personaNameLabel);
467 
468  // Add a Persona action button
469  constraints.gridx++;
470  //constraints.gridwidth = 1;
471  personaButton.setText(personaButtonText);
472  personaButton.addActionListener(personaButtonListener);
473 
474  // Shirnk the button height.
475  personaButton.setMargin(new Insets(0, 5, 0, 5));
476  gridBagLayout.setConstraints(personaButton, constraints);
477  CommunicationArtifactViewerHelper.addComponent(this, gridBagLayout, constraints, personaButton);
478  CommunicationArtifactViewerHelper.addLineEndGlue(this, gridBagLayout, constraints);
479 
480  constraints.insets = savedInsets;
481 
482  // if we have a persona, indicate if any of the contact's accounts are missing from it.
483  if (persona != null) {
484  if (missingAccountsList.isEmpty()) {
485  constraints.gridy++;
486  constraints.gridx = 1;
487  //constraints.insets = labelInsets;
488 
489  javax.swing.JLabel accountsStatus = new javax.swing.JLabel(Bundle.ContactArtifactViewer_found_all_accounts_label());
490  constraints.insets = extraIndentInsets;
491  CommunicationArtifactViewerHelper.addComponent(this, gridBagLayout, constraints, accountsStatus);
492  constraints.insets = savedInsets;
493 
494  CommunicationArtifactViewerHelper.addLineEndGlue(this, gridBagLayout, constraints);
495  } else {
496  // show missing accounts.
497  for (CentralRepoAccount missingAccount : missingAccountsList) {
498  //constraints.weightx = 0;
499  constraints.gridx = 0;
500  constraints.gridy++;
501 
502  // this needs an extra indent
503  constraints.insets = extraIndentInsets;
504  CommunicationArtifactViewerHelper.addKeyAtCol(this, gridBagLayout, constraints, Bundle.ContactArtifactViewer_missing_account_label(), 1);
505  constraints.insets = savedInsets;
506 
507  CommunicationArtifactViewerHelper.addValueAtCol(this, gridBagLayout, constraints, missingAccount.getIdentifier(), 2);
508  }
509  }
510  }
511 
512  // restore insets
513  constraints.insets = savedInsets;
514  }
515 
519  private void resetComponent() {
520 
521  contactArtifact = null;
522  contactName = null;
523  datasourceName = null;
524 
525  contactUniqueAccountsList.clear();
526  contactUniquePersonasMap.clear();
527 
528  phoneNumList.clear();
529  emailList.clear();
530  nameList.clear();
531  otherList.clear();
532  accountAttributesList.clear();
533 
534  if (personaSearchTask != null) {
535  personaSearchTask.cancel(Boolean.TRUE);
536  personaSearchTask = null;
537  }
538 
539  // clear the panel
540  this.removeAll();
541  this.setLayout(null);
542 
543  m_gridBagLayout = new GridBagLayout();
544  m_constraints = new GridBagConstraints();
545 
546  m_constraints.anchor = GridBagConstraints.FIRST_LINE_START;
547  m_constraints.gridy = 0;
548  m_constraints.gridx = 0;
549  m_constraints.weighty = 0.0;
550  m_constraints.weightx = 0.0; // keep components fixed horizontally.
551  m_constraints.insets = new java.awt.Insets(0, CommunicationArtifactViewerHelper.LEFT_INSET, 0, 0);
552  m_constraints.fill = GridBagConstraints.NONE;
553 
554  }
555 
564  private ImageIcon getImageFromArtifact(BlackboardArtifact artifact) {
565  ImageIcon imageIcon = defaultImage;
566 
567  if (artifact == null) {
568  return imageIcon;
569  }
570 
571  BlackboardArtifact.ARTIFACT_TYPE artifactType = BlackboardArtifact.ARTIFACT_TYPE.fromID(artifact.getArtifactTypeID());
572  if (artifactType != BlackboardArtifact.ARTIFACT_TYPE.TSK_CONTACT) {
573  return imageIcon;
574  }
575 
576  try {
577  for (Content content : artifact.getChildren()) {
578  if (content instanceof AbstractFile) {
579  AbstractFile file = (AbstractFile) content;
580 
581  try {
582  BufferedImage image = ImageIO.read(new File(file.getLocalAbsPath()));
583  imageIcon = new ImageIcon(image);
584  break;
585  } catch (IOException ex) {
586  // ImageIO.read will throw an IOException if file is not an image
587  // therefore we don't need to report this exception just try
588  // the next file.
589  }
590  }
591  }
592  } catch (TskCoreException ex) {
593  logger.log(Level.WARNING, String.format("Unable to load image for contact: %d", artifact.getId()), ex);
594  }
595 
596  return imageIcon;
597  }
598 
603  private class ContactPersonaSearcherTask extends SwingWorker<Map<Persona, ArrayList<CentralRepoAccount>>, Void> {
604 
605  private final BlackboardArtifact artifact;
606  private final List<CentralRepoAccount> uniqueAccountsList = new ArrayList<>();
607 
614  ContactPersonaSearcherTask(BlackboardArtifact artifact) {
615  this.artifact = artifact;
616  }
617 
618  @Override
619  protected Map<Persona, ArrayList<CentralRepoAccount>> doInBackground() throws Exception {
620 
621  Map<Persona, ArrayList<CentralRepoAccount>> uniquePersonas = new HashMap<>();
622 
623  CommunicationsManager commManager = Case.getCurrentCase().getSleuthkitCase().getCommunicationsManager();
624  List<Account> contactAccountsList = commManager.getAccountsRelatedToArtifact(artifact);
625 
626  for (Account account : contactAccountsList) {
627  if (isCancelled()) {
628  return new HashMap<>();
629  }
630 
631  // make a list of all unique accounts for this contact
632  if (!account.getAccountType().equals(Account.Type.DEVICE)) {
633  CentralRepoAccount.CentralRepoAccountType crAccountType = CentralRepository.getInstance().getAccountTypeByName(account.getAccountType().getTypeName());
634  CentralRepoAccount crAccount = CentralRepository.getInstance().getAccount(crAccountType, account.getTypeSpecificID());
635 
636  if (crAccount != null && uniqueAccountsList.contains(crAccount) == false) {
637  uniqueAccountsList.add(crAccount);
638  }
639  }
640 
641  Collection<PersonaAccount> personaAccounts = PersonaAccount.getPersonaAccountsForAccount(account);
642  if (personaAccounts != null && !personaAccounts.isEmpty()) {
643  // get personas for the account
644  Collection<Persona> personas
645  = personaAccounts
646  .stream()
648  .collect(Collectors.toList());
649 
650  // make a list of unique personas, along with all their accounts
651  for (Persona persona : personas) {
652  if (uniquePersonas.containsKey(persona) == false) {
653  Collection<CentralRepoAccount> accounts = persona.getPersonaAccounts()
654  .stream()
656  .collect(Collectors.toList());
657 
658  ArrayList<CentralRepoAccount> personaAccountsList = new ArrayList<>(accounts);
659  uniquePersonas.put(persona, personaAccountsList);
660  }
661  }
662  }
663  }
664 
665  return uniquePersonas;
666  }
667 
668  @Override
669  protected void done() {
670 
671  Map<Persona, ArrayList<CentralRepoAccount>> personasMap;
672  try {
673  personasMap = super.get();
674 
675  if (this.isCancelled()) {
676  return;
677  }
678 
679  contactUniquePersonasMap.clear();
680  contactUniquePersonasMap.putAll(personasMap);
681  contactUniqueAccountsList.clear();
682  contactUniqueAccountsList.addAll(uniqueAccountsList);
683 
684  updatePersonas();
685 
686  } catch (CancellationException ex) {
687  logger.log(Level.INFO, "Persona searching was canceled."); //NON-NLS
688  } catch (InterruptedException ex) {
689  logger.log(Level.INFO, "Persona searching was interrupted."); //NON-NLS
690  } catch (ExecutionException ex) {
691  logger.log(Level.SEVERE, "Fatal error during Persona search.", ex); //NON-NLS
692  }
693 
694  }
695  }
696 
701  private class PersonaUIComponents {
702 
703  private final JLabel personaNameLabel;
704  private final JButton personaActionButton;
705 
712  PersonaUIComponents(JLabel personaNameLabel, JButton personaActionButton) {
713  this.personaNameLabel = personaNameLabel;
714  this.personaActionButton = personaActionButton;
715  }
716 
722  public JLabel getPersonaNameLabel() {
723  return personaNameLabel;
724  }
725 
731  public JButton getPersonaActionButton() {
732  return personaActionButton;
733  }
734  }
735 
739  private class CreatePersonaButtonListener implements ActionListener {
740 
741  private final Component parentComponent;
743 
749  CreatePersonaButtonListener(Component parentComponent, PersonaUIComponents personaUIComponents) {
750  this.personaUIComponents = personaUIComponents;
751  this.parentComponent = parentComponent;
752  }
753 
754  @NbBundle.Messages({
755  "ContactArtifactViewer_persona_account_justification=Account found in Contact artifact",
756  "# {0} - accountIdentifer",
757  "ContactArtifactViewer_id_not_found_in_cr=Unable to find account(s) associated with contact {0} in the Central Repository."
758  })
759 
760  @Override
761  public void actionPerformed(java.awt.event.ActionEvent evt) {
762  // Launch the Persona Create dialog - do not display immediately
763  PersonaDetailsDialog createPersonaDialog = new PersonaDetailsDialog(parentComponent,
764  PersonaDetailsMode.CREATE, null, new PersonaCreateCallbackImpl(parentComponent, personaUIComponents), false);
765 
766  // Pre populate the persona name and accounts if we have them.
767  PersonaDetailsPanel personaPanel = createPersonaDialog.getDetailsPanel();
768 
769  if (contactName != null) {
770  personaPanel.setPersonaName(contactName);
771  }
772 
773  // pass the list of accounts to the dialog
774  for (CentralRepoAccount account : contactUniqueAccountsList) {
775  personaPanel.addAccount(account, Bundle.ContactArtifactViewer_persona_account_justification(), Persona.Confidence.HIGH);
776  }
777 
778  if(contactName != null && contactUniqueAccountsList.isEmpty()) {
779  createPersonaDialog.setStartupPopupMessage(Bundle.ContactArtifactViewer_id_not_found_in_cr(contactName));
780  }
781 
782  // display the dialog now
783  createPersonaDialog.display();
784  }
785  }
786 
790  private class ViewPersonaButtonListener implements ActionListener {
791 
792  private final Persona persona;
793  private final Component parentComponent;
794 
800  ViewPersonaButtonListener(Component parentComponent, Persona persona) {
801  this.persona = persona;
802  this.parentComponent = parentComponent;
803  }
804 
805  @Override
806  public void actionPerformed(java.awt.event.ActionEvent evt) {
807  new PersonaDetailsDialog(parentComponent,
808  PersonaDetailsMode.VIEW, persona, new PersonaViewCallbackImpl());
809  }
810  }
811 
815  class PersonaCreateCallbackImpl implements PersonaDetailsDialogCallback {
816 
817  private final Component parentComponent;
818  private final PersonaUIComponents personaUIComponents;
819 
825  PersonaCreateCallbackImpl(Component parentComponent, PersonaUIComponents personaUIComponents) {
826  this.parentComponent = parentComponent;
827  this.personaUIComponents = personaUIComponents;
828  }
829 
830  @Override
831  public void callback(Persona persona) {
832  JButton personaButton = personaUIComponents.getPersonaActionButton();
833  if (persona != null) {
834  // update the persona name label with newly created persona,
835  // and change the button to a "View" button
836  personaUIComponents.getPersonaNameLabel().setText(persona.getName());
837  personaUIComponents.getPersonaActionButton().setText(Bundle.ContactArtifactViewer_persona_button_view());
838 
839  // replace action listener with a View button listener
840  for (ActionListener act : personaButton.getActionListeners()) {
841  personaButton.removeActionListener(act);
842  }
843  personaButton.addActionListener(new ViewPersonaButtonListener(parentComponent, persona));
844 
845  }
846 
847  personaButton.getParent().revalidate();
848  personaButton.getParent().repaint();
849  }
850  }
851 
855  class PersonaViewCallbackImpl implements PersonaDetailsDialogCallback {
856 
857  @Override
858  public void callback(Persona persona) {
859  // nothing to do
860  }
861  }
862 
863  // Variables declaration - do not modify//GEN-BEGIN:variables
864  // End of variables declaration//GEN-END:variables
865 }
boolean addAccount(CentralRepoAccount account, String justification, Persona.Confidence confidence)
static Collection< PersonaAccount > getPersonaAccountsForAccount(long accountId)
void showPersona(Persona persona, int matchNumber, List< CentralRepoAccount > missingAccountsList, GridBagLayout gridBagLayout, GridBagConstraints constraints)
CentralRepoAccount getAccount(CentralRepoAccount.CentralRepoAccountType crAccountType, String accountUniqueID)
void updateContactName(GridBagLayout contactPanelLayout, GridBagConstraints contactPanelConstraints)
void updateContactImage(GridBagLayout contactPanelLayout, GridBagConstraints contactPanelConstraints)
void updateContactMethodSection(List< BlackboardAttribute > sectionAttributesList, String sectionHeader, GridBagLayout contactPanelLayout, GridBagConstraints contactPanelConstraints)
synchronized static Logger getLogger(String name)
Definition: Logger.java:124
CentralRepoAccountType getAccountTypeByName(String accountTypeName)

Copyright © 2012-2021 Basis Technology. Generated on: Tue Jan 19 2021
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.