19 package org.sleuthkit.autopsy.communications.relationships;
 
   21 import java.util.Comparator;
 
   22 import java.util.HashMap;
 
   23 import java.util.List;
 
   26 import java.util.logging.Level;
 
   27 import javax.swing.Action;
 
   28 import org.openide.nodes.AbstractNode;
 
   29 import org.openide.nodes.ChildFactory;
 
   30 import org.openide.nodes.Children;
 
   31 import org.openide.nodes.Node;
 
   32 import org.openide.nodes.Sheet;
 
   45 final class ThreadChildNodeFactory 
extends ChildFactory<BlackboardArtifact> {
 
   47     private static final Logger logger = Logger.getLogger(ThreadChildNodeFactory.class.getName());
 
   49     private SelectionInfo selectionInfo;
 
   51     private final Action preferredAction;
 
   60     ThreadChildNodeFactory(Action preferredAction) {
 
   61         this.preferredAction = preferredAction;
 
   69     public void refresh(SelectionInfo selectionInfo) {
 
   70         this.selectionInfo = selectionInfo;
 
   83     protected boolean createKeys(List<BlackboardArtifact> list) {
 
   84         if(selectionInfo == null) {
 
   89             final Set<Content> relationshipSources = selectionInfo.getRelationshipSources();
 
   90             createRootMessageKeys(list, relationshipSources) ;
 
   91         } 
catch (TskCoreException ex) {
 
   92             logger.log(Level.SEVERE, 
"Failed to load relationship sources.", ex); 
 
  110     private boolean createRootMessageKeys(List<BlackboardArtifact> list, Set<Content> relationshipSources) 
throws TskCoreException{
 
  111         Map<String, BlackboardArtifact> rootMessageMap = 
new HashMap<>();
 
  112         for(Content content: relationshipSources) {
 
  113             if(!(content instanceof BlackboardArtifact)) {
 
  117             BlackboardArtifact bba = (BlackboardArtifact) content;
 
  118             BlackboardArtifact.ARTIFACT_TYPE fromID = BlackboardArtifact.ARTIFACT_TYPE.fromID(bba.getArtifactTypeID());
 
  120             if (fromID == BlackboardArtifact.ARTIFACT_TYPE.TSK_EMAIL_MSG
 
  121                     || fromID == BlackboardArtifact.ARTIFACT_TYPE.TSK_MESSAGE) {
 
  126                 String threadID = MessageNode.UNTHREADED_ID;
 
  128                 BlackboardAttribute attribute = bba.getAttribute(
new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_THREAD_ID));
 
  130                 if(attribute != null) {
 
  131                     threadID = attribute.getValueString();
 
  134                 BlackboardArtifact tableArtifact = rootMessageMap.get(threadID);
 
  135                 if(tableArtifact == null) {
 
  136                     rootMessageMap.put(threadID, bba);          
 
  139                     BlackboardAttribute tableAttribute = null;
 
  142                             tableAttribute = tableArtifact.getAttribute(
new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_SENT));
 
  143                             attribute = bba.getAttribute(
new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_SENT));
 
  145                             if(tableAttribute != null 
 
  147                                     && tableAttribute.getValueLong() > attribute.getValueLong()) {
 
  148                                 rootMessageMap.put(threadID, bba);
 
  152                             tableAttribute = tableArtifact.getAttribute(
new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME));
 
  153                             attribute = bba.getAttribute(
new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME));
 
  155                             if(tableAttribute != null 
 
  157                                     && tableAttribute.getValueLong() < attribute.getValueLong()) {
 
  158                                 rootMessageMap.put(threadID, bba);
 
  162                             tableAttribute = tableArtifact.getAttribute(
new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_START));
 
  163                             attribute = bba.getAttribute(
new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_START));
 
  165                             if(tableAttribute != null 
 
  167                                     && tableAttribute.getValueLong() > attribute.getValueLong()) {
 
  168                                 rootMessageMap.put(threadID, bba);
 
  178         for(BlackboardArtifact bba: rootMessageMap.values()) {
 
  182         list.sort(
new ThreadDateComparator());
 
  188     protected Node createNodeForKey(BlackboardArtifact bba) {
 
  189         BlackboardAttribute attribute = null;
 
  191             attribute = bba.getAttribute(
new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_THREAD_ID)); 
 
  192         } 
catch (TskCoreException ex) {
 
  193             logger.log(Level.WARNING, String.format(
"Unable to get threadID for artifact: %s", bba.getName()), ex);
 
  196         if (attribute != null) {
 
  197             return new ThreadNode(bba, attribute.getValueString(), preferredAction);
 
  200             return new UnthreadedNode();
 
  207     final class UnthreadedNode 
extends AbstractNode {
 
  212             super(Children.LEAF);
 
  213             setDisplayName(
"Unthreaded");
 
  214             this.setIconBaseWithExtension(
"org/sleuthkit/autopsy/communications/images/unthreaded.png" );
 
  218         protected Sheet createSheet() {
 
  219             Sheet sheet = super.createSheet();
 
  220             Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
 
  221             if (sheetSet == null) {
 
  222                 sheetSet = Sheet.createPropertiesSet();
 
  227             sheetSet.put(
new NodeProperty<>(
"ThreadID", 
"ThreadID",
"",MessageNode.UNTHREADED_ID));
 
  240     class ThreadDateComparator 
implements Comparator<BlackboardArtifact> {
 
  243         public int compare(BlackboardArtifact bba1, BlackboardArtifact bba2) {
 
  244             BlackboardAttribute attribute1 = null;
 
  245             BlackboardAttribute attribute2 = null;
 
  249             long dateTime1 = Long.MAX_VALUE;
 
  250             long dateTime2 = Long.MAX_VALUE;
 
  253                 BlackboardArtifact.ARTIFACT_TYPE fromID = BlackboardArtifact.ARTIFACT_TYPE.fromID(bba1.getArtifactTypeID());
 
  254                 if (fromID != null) {
 
  258                                 attribute1 = bba1.getAttribute(
new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_SENT));
 
  262                                 attribute1 = bba1.getAttribute(
new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME));
 
  266                                 attribute1 = bba1.getAttribute(
new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_START));
 
  270                     } 
catch (TskCoreException ex) {
 
  271                         logger.log(Level.WARNING, String.format(
"Unable to compare attributes for artifact %d", bba1.getArtifactID()), ex);
 
  277                 BlackboardArtifact.ARTIFACT_TYPE fromID = BlackboardArtifact.ARTIFACT_TYPE.fromID(bba2.getArtifactTypeID());
 
  278                 if (fromID != null) {
 
  282                                 attribute2 = bba2.getAttribute(
new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_SENT));
 
  285                                 attribute2 = bba2.getAttribute(
new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME));
 
  288                                 attribute2 = bba2.getAttribute(
new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_START));
 
  291                     } 
catch (TskCoreException ex) {
 
  292                         logger.log(Level.WARNING, String.format(
"Unable to compare attributes for artifact %d", bba2.getArtifactID()), ex);
 
  297             if (attribute1 != null) {
 
  298                 dateTime1 = attribute1.getValueLong();
 
  301             if (attribute2 != null) {
 
  302                 dateTime2 = attribute2.getValueLong();
 
  305             return Long.compare(dateTime1, dateTime2) * -1;