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