19 package org.sleuthkit.autopsy.datamodel.accounts;
 
   21 import com.google.common.collect.Range;
 
   22 import com.google.common.collect.RangeMap;
 
   23 import com.google.common.collect.TreeRangeMap;
 
   24 import com.google.common.eventbus.EventBus;
 
   25 import com.google.common.eventbus.Subscribe;
 
   26 import java.awt.event.ActionEvent;
 
   27 import java.beans.PropertyChangeEvent;
 
   28 import java.beans.PropertyChangeListener;
 
   29 import java.sql.ResultSet;
 
   30 import java.sql.SQLException;
 
   31 import java.util.ArrayList;
 
   32 import java.util.Arrays;
 
   33 import java.util.Collection;
 
   34 import java.util.Collections;
 
   35 import java.util.HashSet;
 
   36 import java.util.List;
 
   37 import java.util.Objects;
 
   38 import java.util.Optional;
 
   40 import java.util.function.Function;
 
   41 import java.util.logging.Level;
 
   42 import java.util.logging.Logger;
 
   43 import java.util.stream.Collectors;
 
   44 import java.util.stream.Stream;
 
   45 import javax.annotation.Nonnull;
 
   46 import javax.annotation.concurrent.Immutable;
 
   47 import javax.swing.AbstractAction;
 
   48 import javax.swing.Action;
 
   49 import org.apache.commons.lang3.StringUtils;
 
   50 import org.openide.nodes.Children;
 
   51 import org.openide.nodes.Node;
 
   52 import org.openide.nodes.NodeNotFoundException;
 
   53 import org.openide.nodes.NodeOp;
 
   54 import org.openide.nodes.Sheet;
 
   55 import org.openide.util.NbBundle;
 
   56 import org.openide.util.Utilities;
 
   57 import org.openide.util.lookup.Lookups;
 
   74 import org.
sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
 
   87     private static final Logger 
LOGGER = Logger.getLogger(
Accounts.class.getName());
 
   89     @NbBundle.Messages(
"AccountsRootNode.name=Accounts")
 
   90     final public static String 
NAME = Bundle.AccountsRootNode_name();
 
  117         return v.
visit(
this);
 
  128         return showRejected ? 
" " : 
" AND blackboard_artifacts.review_status_id != " + BlackboardArtifact.ReviewStatus.REJECTED.getID() + 
" "; 
 
  154         abstract protected Collection<X> 
createKeys();
 
  176             super.removeNotify();
 
  191     @NbBundle.Messages({
"Accounts.RootNode.displayName=Accounts"})
 
  203             private final PropertyChangeListener pcl = 
new PropertyChangeListener() {
 
  205                 public void propertyChange(PropertyChangeEvent evt) {
 
  206                     String eventType = evt.getPropertyName();
 
  224                             if (null != eventData
 
  226                                 reviewStatusBus.post(eventData);
 
  228                         } 
catch (IllegalStateException notUsed) {
 
  242                         } 
catch (IllegalStateException notUsed) {
 
  247                         if (evt.getNewValue() == null) {
 
  269                 List<String> list = 
new ArrayList<>();
 
  270                 try (SleuthkitCase.CaseDbQuery executeQuery = skCase.executeQuery(
 
  271                         "SELECT DISTINCT blackboard_attributes.value_text as account_type " 
  272                         + 
" FROM blackboard_attributes " 
  273                         + 
" WHERE blackboard_attributes.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ACCOUNT_TYPE.getTypeID());
 
  274                         ResultSet resultSet = executeQuery.getResultSet()) {
 
  275                     while (resultSet.next()) {
 
  276                         String accountType = resultSet.getString(
"account_type");
 
  277                         list.add(accountType);
 
  279                 } 
catch (TskCoreException | SQLException ex) {
 
  280                     LOGGER.log(Level.SEVERE, 
"Error querying for account_types", ex);
 
  288                     Account.Type accountType = Account.Type.valueOf(key);
 
  289                     switch (accountType) {
 
  295                 } 
catch (IllegalArgumentException ex) {
 
  296                     LOGGER.log(Level.WARNING, 
"Unknown account type: {0}", key);
 
  307                 super.removeNotify();
 
  322             super(Children.LEAF, Lookups.singleton(
Accounts.this));
 
  323             setChildren(Children.createLazy(AccountTypeFactory::new));
 
  325             setDisplayName(Bundle.Accounts_RootNode_displayName());
 
  326             this.setIconBaseWithExtension(
"org/sleuthkit/autopsy/images/accounts.png");    
 
  336             return v.
visit(
this);
 
  355                 List<Long> list = 
new ArrayList<>();
 
  357                         = 
"SELECT blackboard_artifacts.artifact_id "  
  358                         + 
" FROM blackboard_artifacts "  
  359                         + 
"      JOIN blackboard_attributes ON blackboard_artifacts.artifact_id = blackboard_attributes.artifact_id "  
  360                         + 
" WHERE blackboard_artifacts.artifact_type_id = " + BlackboardArtifact.ARTIFACT_TYPE.TSK_ACCOUNT.getTypeID() 
 
  361                         + 
"     AND blackboard_attributes.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ACCOUNT_TYPE.getTypeID() 
 
  362                         + 
"     AND blackboard_attributes.value_text = '" + accountTypeName + 
"'"  
  364                 try (SleuthkitCase.CaseDbQuery results = skCase.executeQuery(query);
 
  365                         ResultSet rs = results.getResultSet();) {
 
  367                         list.add(rs.getLong(
"artifact_id")); 
 
  369                 } 
catch (TskCoreException | SQLException ex) {
 
  370                     LOGGER.log(Level.SEVERE, 
"Error querying for account artifacts.", ex); 
 
  379                 } 
catch (TskCoreException ex) {
 
  380                     LOGGER.log(Level.SEVERE, 
"Error get black board artifact with id " + t, ex);
 
  399             super(Children.LEAF);
 
  401             setChildren(Children.createLazy(DefaultAccountFactory::new));
 
  402             setName(accountTypeName);
 
  403             this.setIconBaseWithExtension(
"org/sleuthkit/autopsy/images/credit-cards.png");   
 
  413             return v.
visit(
this);
 
  467             super(Children.LEAF);
 
  469             setName(Account.Type.CREDIT_CARD.getDisplayName());
 
  470             this.setIconBaseWithExtension(
"org/sleuthkit/autopsy/images/credit-cards.png");   
 
  480             return v.
visit(
this);
 
  509                 List<FileWithCCN> list = 
new ArrayList<>();
 
  511                         = 
"SELECT blackboard_artifacts.obj_id,"  
  512                         + 
"      solr_attribute.value_text AS solr_document_id, "; 
 
  513                 if(skCase.getDatabaseType().equals(DbType.POSTGRESQL)){
 
  514                     query += 
"      string_agg(blackboard_artifacts.artifact_id::character varying, ',') AS artifact_IDs, "  
  515                            + 
"      string_agg(blackboard_artifacts.review_status_id::character varying, ',') AS review_status_ids, ";
 
  517                     query += 
"      GROUP_CONCAT(blackboard_artifacts.artifact_id) AS artifact_IDs, "  
  518                            + 
"      GROUP_CONCAT(blackboard_artifacts.review_status_id) AS review_status_ids, ";
 
  520                 query +=  
"      COUNT( blackboard_artifacts.artifact_id) AS hits  "  
  521                         + 
" FROM blackboard_artifacts "  
  522                         + 
" LEFT JOIN blackboard_attributes as solr_attribute ON blackboard_artifacts.artifact_id = solr_attribute.artifact_id "  
  523                         + 
"                                AND solr_attribute.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD_SEARCH_DOCUMENT_ID.getTypeID() 
 
  524                         + 
" LEFT JOIN blackboard_attributes as account_type ON blackboard_artifacts.artifact_id = account_type.artifact_id "  
  525                         + 
"                                AND account_type.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ACCOUNT_TYPE.getTypeID() 
 
  526                         + 
"                                AND account_type.value_text = '" + Account.Type.CREDIT_CARD.name() + 
"'"  
  527                         + 
" WHERE blackboard_artifacts.artifact_type_id = " + BlackboardArtifact.ARTIFACT_TYPE.TSK_ACCOUNT.getTypeID() 
 
  529                         + 
" GROUP BY blackboard_artifacts.obj_id, solr_document_id "  
  530                         + 
" ORDER BY hits DESC ";  
 
  531                 try (SleuthkitCase.CaseDbQuery results = skCase.executeQuery(query);
 
  532                         ResultSet rs = results.getResultSet();) {
 
  535                                 rs.getLong(
"obj_id"), 
 
  536                                 rs.getString(
"solr_document_id"), 
 
  537                                 unGroupConcat(rs.getString(
"artifact_IDs"), Long::valueOf), 
 
  539                                 new HashSet<>(unGroupConcat(rs.getString(
"review_status_ids"), 
id -> BlackboardArtifact.ReviewStatus.withID(Integer.valueOf(
id))))));  
 
  541                 } 
catch (TskCoreException | SQLException ex) {
 
  542                     LOGGER.log(Level.SEVERE, 
"Error querying for files with ccn hits.", ex); 
 
  552                     List<Object> lookupContents = 
new ArrayList<>();
 
  554                         lookupContents.add(skCase.getBlackboardArtifact(artId));
 
  556                     AbstractFile abstractFileById = skCase.getAbstractFileById(key.
getObjID());
 
  557                     lookupContents.add(abstractFileById);
 
  558                     return new Node[]{
new FileWithCCNNode(key, abstractFileById, lookupContents.toArray())};
 
  559                 } 
catch (TskCoreException ex) {
 
  560                     LOGGER.log(Level.SEVERE, 
"Error getting content for file with ccn hits.", ex); 
 
  567             super(Children.LEAF);
 
  568             setChildren(Children.createLazy(FileWithCCNFactory::new));
 
  571             this.setIconBaseWithExtension(
"org/sleuthkit/autopsy/images/file-icon.png");   
 
  572             reviewStatusBus.register(
this);
 
  576             "# {0} - number of children",
 
  577             "Accounts.ByFileNode.displayName=By File ({0})"})
 
  580                     = 
"SELECT count(*) FROM ( SELECT count(*) AS documents " 
  581                     + 
" FROM blackboard_artifacts "  
  582                     + 
" LEFT JOIN blackboard_attributes as solr_attribute ON blackboard_artifacts.artifact_id = solr_attribute.artifact_id "  
  583                     + 
"                                AND solr_attribute.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD_SEARCH_DOCUMENT_ID.getTypeID() 
 
  584                     + 
" LEFT JOIN blackboard_attributes as account_type ON blackboard_artifacts.artifact_id = account_type.artifact_id "  
  585                     + 
"                                AND account_type.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ACCOUNT_TYPE.getTypeID() 
 
  586                     + 
"                                AND account_type.value_text = '" + Account.Type.CREDIT_CARD.name() + 
"'"  
  587                     + 
" WHERE blackboard_artifacts.artifact_type_id = " + BlackboardArtifact.ARTIFACT_TYPE.TSK_ACCOUNT.getTypeID() 
 
  589                     + 
" GROUP BY blackboard_artifacts.obj_id, solr_attribute.value_text ) AS foo";
 
  590             try (SleuthkitCase.CaseDbQuery results = skCase.executeQuery(query);
 
  591                     ResultSet rs = results.getResultSet();) {
 
  593                     if(skCase.getDatabaseType().equals(DbType.POSTGRESQL)){
 
  594                         setDisplayName(Bundle.Accounts_ByFileNode_displayName(rs.getLong(
"count")));
 
  596                         setDisplayName(Bundle.Accounts_ByFileNode_displayName(rs.getLong(
"count(*)")));
 
  599             } 
catch (TskCoreException | SQLException ex) {
 
  600                 LOGGER.log(Level.SEVERE, 
"Error querying for files with ccn hits.", ex); 
 
  612             return v.
visit(
this);
 
  616         void handleReviewStatusChange(ReviewStatusChangeEvent event) {
 
  651                 List<BinResult> list = 
new ArrayList<>();
 
  653                 RangeMap<Integer, BinResult> binRanges = TreeRangeMap.create();
 
  656                         = 
"SELECT SUBSTR(blackboard_attributes.value_text,1,8) AS BIN, "  
  657                         + 
"     COUNT(blackboard_artifacts.artifact_id) AS count "  
  658                         + 
" FROM blackboard_artifacts "  
  659                         + 
"      JOIN blackboard_attributes ON blackboard_artifacts.artifact_id = blackboard_attributes.artifact_id"  
  660                         + 
" WHERE blackboard_artifacts.artifact_type_id = " + BlackboardArtifact.ARTIFACT_TYPE.TSK_ACCOUNT.getTypeID() 
 
  661                         + 
"     AND blackboard_attributes.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_CARD_NUMBER.getTypeID() 
 
  665                 try (SleuthkitCase.CaseDbQuery results = skCase.executeQuery(query)) {
 
  666                     ResultSet resultSet = results.getResultSet();
 
  668                     while (resultSet.next()) {
 
  669                         final Integer bin = Integer.valueOf(resultSet.getString(
"BIN"));
 
  670                         long count = resultSet.getLong(
"count");
 
  673                         BinResult previousResult = binRanges.get(bin);
 
  675                         if (previousResult != null) {
 
  676                             binRanges.remove(Range.closed(previousResult.getBINStart(), previousResult.getBINEnd()));
 
  677                             count += previousResult.getCount();
 
  680                         if (binRange != null) {
 
  683                             binRanges.put(Range.closed(bin, bin), 
new BinResult(count, bin, bin));
 
  686                     binRanges.asMapOfRanges().values().forEach(list::add);
 
  687                 } 
catch (TskCoreException | SQLException ex) {
 
  688                     LOGGER.log(Level.SEVERE, 
"Error querying for BINs.", ex); 
 
  696                 return new Node[]{
new BINNode(key)};
 
  701             super(Children.LEAF);
 
  702             setChildren(Children.createLazy(BINFactory::new));
 
  705             this.setIconBaseWithExtension(
"org/sleuthkit/autopsy/images/bank.png");   
 
  706             reviewStatusBus.register(
this);
 
  710             "# {0} - number of children",
 
  711             "Accounts.ByBINNode.displayName=By BIN ({0})"})
 
  714                     = 
"SELECT count(distinct SUBSTR(blackboard_attributes.value_text,1,8)) AS BINs "  
  715                     + 
" FROM blackboard_artifacts "  
  716                     + 
"      JOIN blackboard_attributes ON blackboard_artifacts.artifact_id = blackboard_attributes.artifact_id"  
  717                     + 
" WHERE blackboard_artifacts.artifact_type_id = " + BlackboardArtifact.ARTIFACT_TYPE.TSK_ACCOUNT.getTypeID() 
 
  718                     + 
"     AND blackboard_attributes.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_CARD_NUMBER.getTypeID() 
 
  720             try (SleuthkitCase.CaseDbQuery results = skCase.executeQuery(query)) {
 
  721                 ResultSet resultSet = results.getResultSet();
 
  722                 while (resultSet.next()) {
 
  723                     setDisplayName(Bundle.Accounts_ByBINNode_displayName(resultSet.getLong(
"BINs")));
 
  725             } 
catch (TskCoreException | SQLException ex) {
 
  726                 LOGGER.log(Level.SEVERE, 
"Error querying for BINs.", ex); 
 
  737             return v.
visit(
this);
 
  741         void handleReviewStatusChange(ReviewStatusChangeEvent event) {
 
  761             hash = 79 * hash + (int) (this.objID ^ (this.objID >>> 32));
 
  762             hash = 79 * hash + Objects.hashCode(this.keywordSearchDocID);
 
  763             hash = 79 * hash + Objects.hashCode(this.artifactIDs);
 
  764             hash = 79 * hash + (int) (this.hits ^ (this.hits >>> 32));
 
  765             hash = 79 * hash + Objects.hashCode(this.statuses);
 
  777             if (getClass() != obj.getClass()) {
 
  781             if (this.objID != other.
objID) {
 
  784             if (this.hits != other.
hits) {
 
  790             if (!Objects.equals(
this.artifactIDs, other.
artifactIDs)) {
 
  793             if (!Objects.equals(
this.statuses, other.
statuses)) {
 
  803         private final Set<BlackboardArtifact.ReviewStatus> 
statuses;
 
  805         private FileWithCCN(
long objID, String solrDocID, List<Long> artifactIDs, 
long hits, Set<BlackboardArtifact.ReviewStatus> statuses) {
 
  807             this.keywordSearchDocID = solrDocID;
 
  808             this.artifactIDs = artifactIDs;
 
  810             this.statuses = statuses;
 
  829             return keywordSearchDocID;
 
  876     static <X> List<X> unGroupConcat(String groupConcat, Function<String, X> mapper) {
 
  877         return StringUtils.isBlank(groupConcat) ? Collections.emptyList()
 
  878                 : Stream.of(groupConcat.split(
",")) 
 
  880                 .collect(Collectors.toList());
 
  901             "# {0} - raw file name",
 
  902             "# {1} - solr chunk id",
 
  903             "Accounts.FileWithCCNNode.unallocatedSpaceFile.displayName={0}_chunk_{1}"})
 
  905             super(Children.LEAF, Lookups.fixed(lookupContents));
 
  909                     : Bundle.Accounts_FileWithCCNNode_unallocatedSpaceFile_displayName(content.getName(), StringUtils.substringAfter(key.
getkeywordSearchDocID(), 
"_")); 
 
  911             setDisplayName(fileName);
 
  921             return v.
visit(
this);
 
  926             "Accounts.FileWithCCNNode.nameProperty.displayName=File",
 
  927             "Accounts.FileWithCCNNode.accountsProperty.displayName=Accounts",
 
  928             "Accounts.FileWithCCNNode.statusProperty.displayName=Status",
 
  929             "Accounts.FileWithCCNNode.noDescription=no description"})
 
  931             Sheet s = super.createSheet();
 
  932             Sheet.Set ss = s.get(Sheet.PROPERTIES);
 
  934                 ss = Sheet.createPropertiesSet();
 
  938             ss.put(
new NodeProperty<>(Bundle.Accounts_FileWithCCNNode_nameProperty_displayName(),
 
  939                     Bundle.Accounts_FileWithCCNNode_nameProperty_displayName(),
 
  940                     Bundle.Accounts_FileWithCCNNode_noDescription(),
 
  942             ss.put(
new NodeProperty<>(Bundle.Accounts_FileWithCCNNode_accountsProperty_displayName(),
 
  943                     Bundle.Accounts_FileWithCCNNode_accountsProperty_displayName(),
 
  944                     Bundle.Accounts_FileWithCCNNode_noDescription(),
 
  946             ss.put(
new NodeProperty<>(Bundle.Accounts_FileWithCCNNode_statusProperty_displayName(),
 
  947                     Bundle.Accounts_FileWithCCNNode_statusProperty_displayName(),
 
  948                     Bundle.Accounts_FileWithCCNNode_noDescription(),
 
  950                     .map(BlackboardArtifact.ReviewStatus::getDisplayName)
 
  951                     .collect(Collectors.joining(
", ")))); 
 
  958             Action[] actions = super.getActions(context);
 
  959             ArrayList<Action> arrayList = 
new ArrayList<>();
 
  960             arrayList.addAll(Arrays.asList(actions));
 
  963             } 
catch (TskCoreException ex) {
 
  964                 LOGGER.log(Level.SEVERE, 
"Error gettung content by id", ex);
 
  967             arrayList.add(approveActionInstance);
 
  968             arrayList.add(rejectActionInstance);
 
  970             return arrayList.toArray(
new Action[arrayList.size()]);
 
  986                 event.artifacts.stream().map(BlackboardArtifact::getArtifactID).forEach(this::refreshKey);
 
  997                 List<Long> list = 
new ArrayList<>();
 
 1000                         = 
"SELECT blackboard_artifacts.artifact_id "  
 1001                         + 
" FROM blackboard_artifacts "  
 1002                         + 
"      JOIN blackboard_attributes ON blackboard_artifacts.artifact_id = blackboard_attributes.artifact_id "  
 1003                         + 
" WHERE blackboard_artifacts.artifact_type_id = " + BlackboardArtifact.ARTIFACT_TYPE.TSK_ACCOUNT.getTypeID() 
 
 1004                         + 
"     AND blackboard_attributes.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_CARD_NUMBER.getTypeID() 
 
 1005                         + 
"     AND blackboard_attributes.value_text >= '" + bin.getBINStart() + 
"' AND  blackboard_attributes.value_text < '" + (bin.getBINEnd() + 1) + 
"'"  
 1007                         + 
" ORDER BY blackboard_attributes.value_text"; 
 
 1008                 try (SleuthkitCase.CaseDbQuery results = skCase.executeQuery(query);
 
 1009                         ResultSet rs = results.getResultSet();) {
 
 1011                         list.add(rs.getLong(
"artifact_id")); 
 
 1013                 } 
catch (TskCoreException | SQLException ex) {
 
 1014                     LOGGER.log(Level.SEVERE, 
"Error querying for account artifacts.", ex); 
 
 1022                 if (skCase == null) {
 
 1027                     BlackboardArtifact art = skCase.getBlackboardArtifact(artifactID);
 
 1029                 } 
catch (TskCoreException ex) {
 
 1030                     LOGGER.log(Level.WARNING, 
"Error creating BlackboardArtifactNode for artifact with ID " + artifactID, ex);   
 
 1038             super(Children.LEAF);
 
 1039             setChildren(Children.createLazy(CreditCardNumberFactory::new));
 
 1041             setName(getBinRangeString());
 
 1042             updateDisplayName();
 
 1043             this.setIconBaseWithExtension(
"org/sleuthkit/autopsy/images/bank.png");   
 
 1044             reviewStatusBus.register(
this);
 
 1049             updateDisplayName();
 
 1054             updateDisplayName();
 
 1059                     = 
"SELECT count(blackboard_artifacts.artifact_id ) AS count"  
 1060                     + 
" FROM blackboard_artifacts "  
 1061                     + 
"      JOIN blackboard_attributes ON blackboard_artifacts.artifact_id = blackboard_attributes.artifact_id "  
 1062                     + 
" WHERE blackboard_artifacts.artifact_type_id = " + BlackboardArtifact.ARTIFACT_TYPE.TSK_ACCOUNT.getTypeID() 
 
 1063                     + 
"     AND blackboard_attributes.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_CARD_NUMBER.getTypeID() 
 
 1064                     + 
"     AND blackboard_attributes.value_text >= '" + bin.getBINStart() + 
"' AND  blackboard_attributes.value_text < '" + (bin.getBINEnd() + 1) + 
"'"  
 1066             try (SleuthkitCase.CaseDbQuery results = skCase.executeQuery(query);
 
 1067                     ResultSet rs = results.getResultSet();) {
 
 1069                     setDisplayName(getBinRangeString() + 
" (" + rs.getLong(
"count") + 
")"); 
 
 1071             } 
catch (TskCoreException | SQLException ex) {
 
 1072                 LOGGER.log(Level.SEVERE, 
"Error querying for account artifacts.", ex); 
 
 1079             if (bin.getBINStart() == bin.getBINEnd()) {
 
 1080                 return Integer.toString(bin.getBINStart());
 
 1082                 return bin.getBINStart() + 
"-" + StringUtils.difference(bin.getBINStart() + 
"", bin.getBINEnd() + 
"");
 
 1093             return v.
visit(
this);
 
 1097             Sheet.Set ss = s.get(Sheet.PROPERTIES);
 
 1099                 ss = Sheet.createPropertiesSet();
 
 1106         @NbBundle.Messages({
 
 1107             "Accounts.BINNode.binProperty.displayName=Bank Identifier Number",
 
 1108             "Accounts.BINNode.accountsProperty.displayName=Accounts",
 
 1109             "Accounts.BINNode.cardTypeProperty.displayName=Payment Card Type",
 
 1110             "Accounts.BINNode.schemeProperty.displayName=Credit Card Scheme",
 
 1111             "Accounts.BINNode.brandProperty.displayName=Brand",
 
 1112             "Accounts.BINNode.bankProperty.displayName=Bank",
 
 1113             "Accounts.BINNode.bankCityProperty.displayName=Bank City",
 
 1114             "Accounts.BINNode.bankCountryProperty.displayName=Bank Country",
 
 1115             "Accounts.BINNode.bankPhoneProperty.displayName=Bank Phone #",
 
 1116             "Accounts.BINNode.bankURLProperty.displayName=Bank URL",
 
 1117             "Accounts.BINNode.noDescription=no description"})
 
 1119             Sheet sheet = super.createSheet();
 
 1120             Sheet.Set properties = getPropertySet(sheet);
 
 1122             properties.put(
new NodeProperty<>(Bundle.Accounts_BINNode_binProperty_displayName(),
 
 1123                     Bundle.Accounts_BINNode_binProperty_displayName(),
 
 1124                     Bundle.Accounts_BINNode_noDescription(),
 
 1125                     getBinRangeString()));
 
 1126             properties.put(
new NodeProperty<>(Bundle.Accounts_BINNode_accountsProperty_displayName(),
 
 1127                     Bundle.Accounts_BINNode_accountsProperty_displayName(), Bundle.Accounts_BINNode_noDescription(),
 
 1131             if (bin.hasDetails()) {
 
 1132                 bin.
getCardType().ifPresent(cardType -> properties.put(
new NodeProperty<>(Bundle.Accounts_BINNode_cardTypeProperty_displayName(),
 
 1133                         Bundle.Accounts_BINNode_cardTypeProperty_displayName(), Bundle.Accounts_BINNode_noDescription(),
 
 1135                 bin.
getScheme().ifPresent(scheme -> properties.put(
new NodeProperty<>(Bundle.Accounts_BINNode_schemeProperty_displayName(),
 
 1136                         Bundle.Accounts_BINNode_schemeProperty_displayName(), Bundle.Accounts_BINNode_noDescription(),
 
 1138                 bin.
getBrand().ifPresent(brand -> properties.put(
new NodeProperty<>(Bundle.Accounts_BINNode_brandProperty_displayName(),
 
 1139                         Bundle.Accounts_BINNode_brandProperty_displayName(), Bundle.Accounts_BINNode_noDescription(),
 
 1141                 bin.
getBankName().ifPresent(bankName -> properties.put(
new NodeProperty<>(Bundle.Accounts_BINNode_bankProperty_displayName(),
 
 1142                         Bundle.Accounts_BINNode_bankProperty_displayName(), Bundle.Accounts_BINNode_noDescription(),
 
 1144                 bin.
getBankCity().ifPresent(bankCity -> properties.put(
new NodeProperty<>(Bundle.Accounts_BINNode_bankCityProperty_displayName(),
 
 1145                         Bundle.Accounts_BINNode_bankCityProperty_displayName(), Bundle.Accounts_BINNode_noDescription(),
 
 1147                 bin.
getCountry().ifPresent(country -> properties.put(
new NodeProperty<>(Bundle.Accounts_BINNode_bankCountryProperty_displayName(),
 
 1148                         Bundle.Accounts_BINNode_bankCountryProperty_displayName(), Bundle.Accounts_BINNode_noDescription(),
 
 1151                         Bundle.Accounts_BINNode_bankPhoneProperty_displayName(), Bundle.Accounts_BINNode_noDescription(),
 
 1153                 bin.
getBankURL().ifPresent(url -> properties.put(
new NodeProperty<>(Bundle.Accounts_BINNode_bankURLProperty_displayName(),
 
 1154                         Bundle.Accounts_BINNode_bankURLProperty_displayName(), Bundle.Accounts_BINNode_noDescription(),
 
 1171             hash = 97 * hash + this.binEnd;
 
 1172             hash = 97 * hash + this.binStart;
 
 1184             if (getClass() != obj.getClass()) {
 
 1188             if (this.binEnd != other.
binEnd) {
 
 1191             if (this.binStart != other.
binStart) {
 
 1208             this.binRange = binRange;
 
 1209             binStart = binRange.getBINstart();
 
 1210             binEnd = binRange.getBINend();
 
 1215             this.binRange = null;
 
 1232         boolean hasDetails() {
 
 1233             return binRange != null;
 
 1287             super(artifact, 
"org/sleuthkit/autopsy/images/credit-card.png");   
 
 1288             this.artifact = artifact;
 
 1289             setName(
"" + this.artifact.getArtifactID());
 
 1294             List<Action> actionsList = 
new ArrayList<>();
 
 1295             actionsList.addAll(Arrays.asList(super.getActions(context)));
 
 1297             actionsList.add(approveActionInstance);
 
 1298             actionsList.add(rejectActionInstance);
 
 1300             return actionsList.toArray(
new Action[actionsList.size()]);
 
 1305             Sheet sheet = super.createSheet();
 
 1306             Sheet.Set properties = sheet.get(Sheet.PROPERTIES);
 
 1307             if (properties == null) {
 
 1308                 properties = Sheet.createPropertiesSet();
 
 1309                 sheet.put(properties);
 
 1311             properties.put(
new NodeProperty<>(Bundle.Accounts_FileWithCCNNode_statusProperty_displayName(),
 
 1312                     Bundle.Accounts_FileWithCCNNode_statusProperty_displayName(),
 
 1313                     Bundle.Accounts_FileWithCCNNode_noDescription(),
 
 1314                     artifact.getReviewStatus().getDisplayName()));
 
 1322         @NbBundle.Messages(
"ToggleShowRejected.name=Show Rejected Results")
 
 1324             super(Bundle.ToggleShowRejected_name());
 
 1340             this.newStatus = newStatus;
 
 1349             List<String[]> selectedPaths = Utilities.actionsGlobalContext().lookupAll(Node.class).stream()
 
 1351                         String[] createPath;
 
 1357                         if (newStatus == BlackboardArtifact.ReviewStatus.REJECTED && showRejected == 
false) {
 
 1358                             List<Node> siblings = Arrays.asList(node.getParentNode().getChildren().getNodes());
 
 1359                             int indexOf = siblings.indexOf(node);
 
 1361                             Node sibling = indexOf > 0
 
 1362                                     ? siblings.get(indexOf - 1)
 
 1363                                     : siblings.get(indexOf + 1);
 
 1364                             createPath = NodeOp.createPath(sibling, null);
 
 1366                             createPath = NodeOp.createPath(node, null);
 
 1369                         return Arrays.copyOfRange(createPath, 1, createPath.length);
 
 1370                     }).collect(Collectors.toList());
 
 1373             final Collection<? extends BlackboardArtifact> artifacts = Utilities.actionsGlobalContext().lookupAll(BlackboardArtifact.class);
 
 1374             artifacts.forEach(artifact -> {
 
 1376                     skCase.setReviewStatus(artifact, newStatus);
 
 1377                 } 
catch (TskCoreException ex) {
 
 1378                     LOGGER.log(Level.SEVERE, 
"Error changing artifact review status.", ex); 
 
 1385             final Node rootNode = directoryListing.
getRootNode();
 
 1388             List<Node> toArray = 
new ArrayList<>();
 
 1389             selectedPaths.forEach(path -> {
 
 1391                     toArray.add(NodeOp.findPath(rootNode, path));
 
 1392                 } 
catch (NodeNotFoundException ex) {
 
 1397             directoryListing.
setSelectedNodes(toArray.toArray(
new Node[toArray.size()]));
 
 1403         @NbBundle.Messages({
"ApproveAccountsAction.name=Approve Accounts"})
 
 1405             super(Bundle.ApproveAccountsAction_name(), BlackboardArtifact.ReviewStatus.APPROVED);
 
 1411         @NbBundle.Messages({
"RejectAccountsAction.name=Reject Accounts"})
 
 1413             super(Bundle.RejectAccountsAction_name(), BlackboardArtifact.ReviewStatus.REJECTED);
 
 1419         Collection<? extends BlackboardArtifact> artifacts;
 
 1420         BlackboardArtifact.ReviewStatus newReviewStatus;
 
 1422         public ReviewStatusChangeEvent(Collection<? extends BlackboardArtifact> artifacts, BlackboardArtifact.ReviewStatus newReviewStatus) {
 
 1423             this.artifacts = artifacts;
 
 1424             this.newReviewStatus = newReviewStatus;
 
List< CreditCardViewMode > createKeys()
final BlackboardArtifact.ReviewStatus newStatus
BlackboardArtifact.Type getBlackboardArtifactType()
void removeIngestModuleEventListener(final PropertyChangeListener listener)
Optional< Integer > getNumberLength()
Optional< String > getCountry()
Node[] createNodes(FileWithCCN key)
final BlackboardArtifact artifact
abstract Collection< X > createKeys()
static synchronized IngestManager getInstance()
DataResultTopComponent getDirectoryListing()
List< Long > createKeys()
static final Logger LOGGER
Optional< String > getBankPhoneNumber()
Set< BlackboardArtifact.ReviewStatus > getStatuses()
Optional< String > getCountry()
Optional< String > getBankCity()
final String keywordSearchDocID
static List< Action > getActions(File file, boolean isArtifactSource)
Optional< String > getBankName()
static void removePropertyChangeListener(PropertyChangeListener listener)
final EventBus reviewStatusBus
String getRejectedArtifactFilterClause()
final String accountTypeName
Sheet.Set getPropertySet(Sheet s)
final RejectAccounts rejectActionInstance
List< Long > getArtifactIDs()
AccountArtifactNode(BlackboardArtifact artifact)
static synchronized BankIdentificationNumber getBINInfo(int bin)
Action[] getActions(boolean context)
Optional< String > getBankURL()
Node[] createNodes(BinResult key)
final ApproveAccounts approveActionInstance
T visit(DataSourcesNode in)
List< BinResult > createKeys()
void removeIngestJobEventListener(final PropertyChangeListener listener)
Optional< String > getScheme()
Node[] createNodes(String key)
final Set< BlackboardArtifact.ReviewStatus > statuses
Optional< String > getBrand()
Collection< Long > createKeys()
Node[] createNodes(Long t)
boolean equals(Object obj)
CreditCardNumberAccountTypeNode()
void addIngestJobEventListener(final PropertyChangeListener listener)
Optional< String > getBankURL()
String getkeywordSearchDocID()
ReviewStatusChangeEvent(Collection<?extends BlackboardArtifact > artifacts, BlackboardArtifact.ReviewStatus newReviewStatus)
Optional< Integer > getNumberLength()
BinResult(long count,@Nonnull BINRange binRange)
Action newToggleShowRejectedAction()
Optional< String > getBrand()
String getBinRangeString()
static void addPropertyChangeListener(PropertyChangeListener listener)
FileWithCCNNode(FileWithCCN key, Content content, Object[] lookupContents)
Action[] getActions(boolean context)
final List< Long > artifactIDs
DefaultAccountTypeNode(String accountTypeName)
Node[] createNodes(Long artifactID)
FileWithCCN(long objID, String solrDocID, List< Long > artifactIDs, long hits, Set< BlackboardArtifact.ReviewStatus > statuses)
List< FileWithCCN > createKeys()
void actionPerformed(ActionEvent e)
Optional< String > getBankCity()
Node[] createNodes(CreditCardViewMode key)
Optional< String > getCardType()
final FileWithCCN fileKey
BinResult(long count, int start, int end)
void addIngestModuleEventListener(final PropertyChangeListener listener)
static Case getCurrentCase()
List< String > createKeys()
boolean equals(Object obj)
void setSelectedNodes(Node[] selected)
ReviewStatusAction(String displayName, BlackboardArtifact.ReviewStatus newStatus)
static synchronized DirectoryTreeTopComponent findInstance()
void actionPerformed(ActionEvent e)
Optional< String > getScheme()
Optional< String > getBankName()
Optional< String > getBankPhoneNumber()
Optional< String > getCardType()
Accounts(SleuthkitCase skCase)