19 package org.sleuthkit.autopsy.discovery.search;
 
   21 import java.time.DayOfWeek;
 
   22 import java.time.Instant;
 
   23 import java.time.ZonedDateTime;
 
   24 import java.time.temporal.TemporalAdjusters;
 
   25 import java.util.Collections;
 
   27 import java.util.HashSet;
 
   28 import java.util.List;
 
   29 import java.util.Objects;
 
   30 import java.util.TimeZone;
 
   31 import java.util.logging.Level;
 
   32 import org.openide.util.NbBundle;
 
   53     static class SearchKey 
implements Comparable<SearchKey> {
 
   55         private final String keyString;
 
   59         private final List<AbstractFilter> filters;
 
   78         SearchKey(String userName, List<AbstractFilter> filters,
 
   83             this.groupAttributeType = groupAttributeType;
 
   84             this.groupSortingType = groupSortingType;
 
   85             this.sortingMethod = sortingMethod;
 
   86             this.filters = filters;
 
   87             this.context = context;
 
   89             StringBuilder searchStringBuilder = 
new StringBuilder();
 
   90             searchStringBuilder.append(userName);
 
   92                 searchStringBuilder.append(filter.toString());
 
   94             searchStringBuilder.append(groupAttributeType).append(groupSortingType).append(sortingMethod);
 
   95             keyString = searchStringBuilder.toString();
 
   96             this.sleuthkitCase = sleuthkitCase;
 
   97             this.centralRepository = centralRepository;
 
  110         SearchKey(String userName, List<AbstractFilter> filters,
 
  114             this(userName, filters, groupAttributeType, groupSortingType,
 
  115                     sortingMethod, null, null, null);
 
  120         public int compareTo(SearchKey otherSearchKey) {
 
  121             return getKeyString().compareTo(otherSearchKey.getKeyString());
 
  125         public boolean equals(Object otherKey) {
 
  126             if (otherKey == 
this) {
 
  130             if (!(otherKey instanceof SearchKey)) {
 
  134             SearchKey otherSearchKey = (SearchKey) otherKey;
 
  135             if (this.sleuthkitCase != otherSearchKey.getSleuthkitCase()
 
  136                     || this.centralRepository != otherSearchKey.getCentralRepository()) {
 
  140             return getKeyString().equals(otherSearchKey.getKeyString());
 
  144         public int hashCode() {
 
  146             hash = 79 * hash + Objects.hashCode(getKeyString());
 
  161             if (context == null) {
 
  162                 throw new DiscoveryException(
"The key in use was created without a context and does not support retrieving information from the databases.");
 
  172         String getKeyString() {
 
  181         List<AbstractFilter> getFilters() {
 
  182             return Collections.unmodifiableList(this.filters);
 
  191             return groupSortingType;
 
  200             return groupAttributeType;
 
  209             return sortingMethod;
 
  218             return this.sleuthkitCase;
 
  227             return this.centralRepository;
 
  234     public abstract static class GroupKey implements Comparable<GroupKey> {
 
  242         abstract String getDisplayName();
 
  252         abstract public boolean equals(Object otherKey);
 
  271         int compareClassNames(
GroupKey otherGroupKey) {
 
  272             return this.getClass().getName().compareTo(otherGroupKey.getClass().getName());
 
  277             return getDisplayName();
 
  284     static class FileSizeGroupKey 
extends GroupKey {
 
  293         FileSizeGroupKey(
Result file) {
 
  303         String getDisplayName() {
 
  304             return getFileSize().toString();
 
  308         public int compareTo(GroupKey otherGroupKey) {
 
  309             if (otherGroupKey instanceof FileSizeGroupKey) {
 
  310                 FileSizeGroupKey otherFileSizeGroupKey = (FileSizeGroupKey) otherGroupKey;
 
  311                 return Integer.compare(getFileSize().getRanking(), otherFileSizeGroupKey.getFileSize().getRanking());
 
  313                 return compareClassNames(otherGroupKey);
 
  318         public boolean equals(Object otherKey) {
 
  319             if (otherKey == 
this) {
 
  323             if (!(otherKey instanceof FileSizeGroupKey)) {
 
  327             FileSizeGroupKey otherFileSizeGroupKey = (FileSizeGroupKey) otherKey;
 
  328             return getFileSize().equals(otherFileSizeGroupKey.getFileSize());
 
  332         public int hashCode() {
 
  333             return Objects.hash(getFileSize().getRanking());
 
  341         SearchData.FileSize getFileSize() {
 
  349     static class FileTypeGroupKey 
extends GroupKey {
 
  351         private final SearchData.Type fileType;
 
  358         FileTypeGroupKey(Result file) {
 
  359             fileType = ((ResultFile) file).getFileType();
 
  363         String getDisplayName() {
 
  364             return getFileType().toString();
 
  368         public int compareTo(GroupKey otherGroupKey) {
 
  369             if (otherGroupKey instanceof FileTypeGroupKey) {
 
  370                 FileTypeGroupKey otherFileTypeGroupKey = (FileTypeGroupKey) otherGroupKey;
 
  371                 return Integer.compare(getFileType().getRanking(), otherFileTypeGroupKey.getFileType().getRanking());
 
  373                 return compareClassNames(otherGroupKey);
 
  378         public boolean equals(Object otherKey) {
 
  379             if (otherKey == 
this) {
 
  383             if (!(otherKey instanceof FileTypeGroupKey)) {
 
  387             FileTypeGroupKey otherFileTypeGroupKey = (FileTypeGroupKey) otherKey;
 
  388             return getFileType().equals(otherFileTypeGroupKey.getFileType());
 
  392         public int hashCode() {
 
  393             return Objects.hash(getFileType().getRanking());
 
  401         SearchData.Type getFileType() {
 
  409     static class KeywordListGroupKey 
extends GroupKey {
 
  411         private final List<String> keywordListNames;
 
  412         private final String keywordListNamesString;
 
  420             "DiscoveryKeyUtils.KeywordListGroupKey.noKeywords=None"})
 
  421         KeywordListGroupKey(ResultFile file) {
 
  422             keywordListNames = file.getKeywordListNames();
 
  423             if (keywordListNames.isEmpty()) {
 
  424                 keywordListNamesString = Bundle.DiscoveryKeyUtils_KeywordListGroupKey_noKeywords();
 
  426                 keywordListNamesString = String.join(
",", keywordListNames); 
 
  431         String getDisplayName() {
 
  432             return getKeywordListNamesString();
 
  436         public int compareTo(GroupKey otherGroupKey) {
 
  437             if (otherGroupKey instanceof KeywordListGroupKey) {
 
  438                 KeywordListGroupKey otherKeywordListNamesGroupKey = (KeywordListGroupKey) otherGroupKey;
 
  441                 if (getKeywordListNames().isEmpty()) {
 
  442                     if (otherKeywordListNamesGroupKey.getKeywordListNames().isEmpty()) {
 
  447                 } 
else if (otherKeywordListNamesGroupKey.getKeywordListNames().isEmpty()) {
 
  451                 return getKeywordListNamesString().compareTo(otherKeywordListNamesGroupKey.getKeywordListNamesString());
 
  453                 return compareClassNames(otherGroupKey);
 
  458         public boolean equals(Object otherKey) {
 
  459             if (otherKey == 
this) {
 
  463             if (!(otherKey instanceof KeywordListGroupKey)) {
 
  467             KeywordListGroupKey otherKeywordListGroupKey = (KeywordListGroupKey) otherKey;
 
  468             return getKeywordListNamesString().equals(otherKeywordListGroupKey.getKeywordListNamesString());
 
  472         public int hashCode() {
 
  473             return Objects.hash(getKeywordListNamesString());
 
  481         List<String> getKeywordListNames() {
 
  482             return Collections.unmodifiableList(keywordListNames);
 
  492         String getKeywordListNamesString() {
 
  493             return keywordListNamesString;
 
  500     static class FileTagGroupKey 
extends GroupKey {
 
  502         private final List<String> tagNames;
 
  503         private final String tagNamesString;
 
  511             "DiscoveryKeyUtils.FileTagGroupKey.noSets=None"})
 
  512         FileTagGroupKey(ResultFile file) {
 
  513             tagNames = file.getTagNames();
 
  515             if (tagNames.isEmpty()) {
 
  516                 tagNamesString = Bundle.DiscoveryKeyUtils_FileTagGroupKey_noSets();
 
  518                 tagNamesString = String.join(
",", tagNames); 
 
  523         String getDisplayName() {
 
  524             return getTagNamesString();
 
  528         public int compareTo(GroupKey otherGroupKey) {
 
  529             if (otherGroupKey instanceof FileTagGroupKey) {
 
  530                 FileTagGroupKey otherFileTagGroupKey = (FileTagGroupKey) otherGroupKey;
 
  533                 if (getTagNames().isEmpty()) {
 
  534                     if (otherFileTagGroupKey.getTagNames().isEmpty()) {
 
  539                 } 
else if (otherFileTagGroupKey.getTagNames().isEmpty()) {
 
  543                 return getTagNamesString().compareTo(otherFileTagGroupKey.getTagNamesString());
 
  545                 return compareClassNames(otherGroupKey);
 
  550         public boolean equals(Object otherKey) {
 
  551             if (otherKey == 
this) {
 
  554             if (!(otherKey instanceof FileTagGroupKey)) {
 
  557             FileTagGroupKey otherFileTagGroupKey = (FileTagGroupKey) otherKey;
 
  558             return getTagNamesString().equals(otherFileTagGroupKey.getTagNamesString());
 
  562         public int hashCode() {
 
  563             return Objects.hash(getTagNamesString());
 
  571         List<String> getTagNames() {
 
  572             return Collections.unmodifiableList(tagNames);
 
  582         String getTagNamesString() {
 
  583             return tagNamesString;
 
  590     static class ParentPathGroupKey 
extends GroupKey {
 
  592         private String parentPath;
 
  593         private Long parentID;
 
  600         ParentPathGroupKey(ResultFile file) {
 
  603                 parent = file.getFirstInstance().getParent();
 
  604             } 
catch (TskCoreException ignored) {
 
  608             while (parent != null && parent instanceof AbstractFile && ((AbstractFile) parent).isFile()) {
 
  610                     parent = parent.getParent();
 
  611                 } 
catch (TskCoreException ignored) {
 
  615             setParentPathAndID(parent, file);
 
  624         private void setParentPathAndID(Content parent, ResultFile file) {
 
  625             if (parent != null) {
 
  627                     parentPath = parent.getUniquePath();
 
  628                     parentID = parent.getId();
 
  629                 } 
catch (TskCoreException ignored) {
 
  634             if (parentPath == null) {
 
  635                 if (file.getFirstInstance().getParentPath() != null) {
 
  636                     parentPath = file.getFirstInstance().getParentPath();
 
  645         String getDisplayName() {
 
  646             return getParentPath();
 
  650         public int compareTo(GroupKey otherGroupKey) {
 
  651             if (otherGroupKey instanceof ParentPathGroupKey) {
 
  652                 ParentPathGroupKey otherParentPathGroupKey = (ParentPathGroupKey) otherGroupKey;
 
  653                 int comparisonResult = getParentPath().compareTo(otherParentPathGroupKey.getParentPath());
 
  654                 if (comparisonResult == 0) {
 
  655                     comparisonResult = getParentID().compareTo(otherParentPathGroupKey.getParentID());
 
  657                 return comparisonResult;
 
  659                 return compareClassNames(otherGroupKey);
 
  664         public boolean equals(Object otherKey) {
 
  665             if (otherKey == 
this) {
 
  669             if (!(otherKey instanceof ParentPathGroupKey)) {
 
  673             ParentPathGroupKey otherParentPathGroupKey = (ParentPathGroupKey) otherKey;
 
  674             return getParentPath().equals(otherParentPathGroupKey.getParentPath()) && getParentID().equals(otherParentPathGroupKey.getParentID());
 
  678         public int hashCode() {
 
  680             hashCode = 61 * hashCode + Objects.hash(getParentPath());
 
  681             hashCode = 61 * hashCode + Objects.hash(getParentID());
 
  690         String getParentPath() {
 
  707     static class DataSourceGroupKey 
extends GroupKey {
 
  709         private final long dataSourceID;
 
  710         private String displayName;
 
  718             "# {0} - Data source name",
 
  719             "# {1} - Data source ID",
 
  720             "DiscoveryKeyUtils.DataSourceGroupKey.datasourceAndID={0}(ID: {1})",
 
  721             "# {0} - Data source ID",
 
  722             "DiscoveryKeyUtils.DataSourceGroupKey.idOnly=Data source (ID: {0})"})
 
  723         DataSourceGroupKey(Result result) {
 
  725             dataSourceID = result.getDataSourceObjectId();
 
  728                 Content ds = result.getDataSource();
 
  729                 displayName = Bundle.DiscoveryKeyUtils_DataSourceGroupKey_datasourceAndID(ds.getName(), ds.getId());
 
  730             } 
catch (TskCoreException ex) {
 
  731                 logger.log(Level.WARNING, 
"Error looking up data source with ID " + dataSourceID, ex); 
 
  732                 displayName = Bundle.DiscoveryKeyUtils_DataSourceGroupKey_idOnly(dataSourceID);
 
  737         String getDisplayName() {
 
  742         public int compareTo(GroupKey otherGroupKey) {
 
  743             if (otherGroupKey instanceof DataSourceGroupKey) {
 
  744                 DataSourceGroupKey otherDataSourceGroupKey = (DataSourceGroupKey) otherGroupKey;
 
  745                 return Long.compare(getDataSourceID(), otherDataSourceGroupKey.getDataSourceID());
 
  747                 return compareClassNames(otherGroupKey);
 
  752         public boolean equals(Object otherKey) {
 
  753             if (otherKey == 
this) {
 
  757             if (!(otherKey instanceof DataSourceGroupKey)) {
 
  761             DataSourceGroupKey otherDataSourceGroupKey = (DataSourceGroupKey) otherKey;
 
  762             return getDataSourceID() == otherDataSourceGroupKey.getDataSourceID();
 
  766         public int hashCode() {
 
  767             return Objects.hash(getDataSourceID());
 
  775         long getDataSourceID() {
 
  784     static class NoGroupingGroupKey 
extends GroupKey {
 
  789         NoGroupingGroupKey() {
 
  794             "DiscoveryKeyUtils.NoGroupingGroupKey.allFiles=All Files"})
 
  796         String getDisplayName() {
 
  797             return Bundle.DiscoveryKeyUtils_NoGroupingGroupKey_allFiles();
 
  801         public int compareTo(GroupKey otherGroupKey) {
 
  803             if (otherGroupKey instanceof NoGroupingGroupKey) {
 
  806                 return compareClassNames(otherGroupKey);
 
  811         public boolean equals(Object otherKey) {
 
  812             if (otherKey == 
this) {
 
  816             return otherKey instanceof NoGroupingGroupKey;
 
  820         public int hashCode() {
 
  828     static class DomainCategoryGroupKey 
extends GroupKey {
 
  830         private final Set<String> webCategories = 
new HashSet<>();
 
  831         private final String displayName;
 
  833         DomainCategoryGroupKey(Result result) {
 
  834             if (result instanceof ResultDomain) {
 
  835                 ResultDomain domain = (ResultDomain) result;
 
  836                 this.webCategories.addAll(domain.getWebCategories());
 
  837                 displayName = String.join(
",", webCategories);
 
  839                 throw new IllegalArgumentException(
"Input result should be of type ResultDomain");
 
  844         String getDisplayName() {
 
  846             return this.displayName;
 
  850         public boolean equals(Object otherKey) {
 
  851             if (otherKey instanceof GroupKey) {
 
  852                 return compareTo((GroupKey) otherKey) == 0;
 
  858         public int hashCode() {
 
  859             return Objects.hash(webCategories);
 
  863         public int compareTo(GroupKey otherGroupKey) {
 
  864             if (otherGroupKey instanceof DomainCategoryGroupKey) {
 
  865                 if (webCategories.size() != ((DomainCategoryGroupKey) otherGroupKey).getWebCategories().size()) {
 
  868                 if (webCategories.containsAll(((DomainCategoryGroupKey) otherGroupKey).getWebCategories())) {
 
  874                 return compareClassNames(otherGroupKey);
 
  878         Set<String> getWebCategories() {
 
  879             return Collections.unmodifiableSet(webCategories);
 
  886     static class PreviouslyNotableGroupKey 
extends GroupKey {
 
  888         private final SearchData.PreviouslyNotable notableStatus;
 
  890         PreviouslyNotableGroupKey(Result result) {
 
  891             this.notableStatus = result.getPreviouslyNotableInCR();
 
  895         String getDisplayName() {
 
  896             return this.notableStatus.toString();
 
  900         public boolean equals(Object otherKey) {
 
  901             if (otherKey instanceof GroupKey) {
 
  902                 return compareTo((GroupKey) otherKey) == 0;
 
  908         public int hashCode() {
 
  909             return Objects.hash(getStatus().getRanking());
 
  913         public int compareTo(GroupKey otherGroupKey) {
 
  914             if (otherGroupKey instanceof PreviouslyNotableGroupKey) {
 
  915                 PreviouslyNotableGroupKey otherFrequencyGroupKey = (PreviouslyNotableGroupKey) otherGroupKey;
 
  916                 return Integer.compare(getStatus().getRanking(), otherFrequencyGroupKey.getStatus().getRanking());
 
  918                 return compareClassNames(otherGroupKey);
 
  922         SearchData.PreviouslyNotable getStatus() {
 
  923             return notableStatus;
 
  930     static class FrequencyGroupKey 
extends GroupKey {
 
  932         private final SearchData.Frequency frequency;
 
  939         FrequencyGroupKey(Result result) {
 
  940             frequency = result.getFrequency();
 
  944         String getDisplayName() {
 
  945             return getFrequency().toString();
 
  949         public int compareTo(GroupKey otherGroupKey) {
 
  950             if (otherGroupKey instanceof FrequencyGroupKey) {
 
  951                 FrequencyGroupKey otherFrequencyGroupKey = (FrequencyGroupKey) otherGroupKey;
 
  952                 return Integer.compare(getFrequency().getRanking(), otherFrequencyGroupKey.getFrequency().getRanking());
 
  954                 return compareClassNames(otherGroupKey);
 
  959         public boolean equals(Object otherKey) {
 
  960             if (otherKey == 
this) {
 
  964             if (!(otherKey instanceof FrequencyGroupKey)) {
 
  968             FrequencyGroupKey otherFrequencyGroupKey = (FrequencyGroupKey) otherKey;
 
  969             return getFrequency().equals(otherFrequencyGroupKey.getFrequency());
 
  973         public int hashCode() {
 
  974             return Objects.hash(getFrequency().getRanking());
 
  982         SearchData.Frequency getFrequency() {
 
  990     static class HashHitsGroupKey 
extends GroupKey {
 
  992         private final List<String> hashSetNames;
 
  993         private final String hashSetNamesString;
 
 1000         @NbBundle.Messages({
 
 1001             "DiscoveryKeyUtils.HashHitsGroupKey.noHashHits=None"})
 
 1002         HashHitsGroupKey(ResultFile file) {
 
 1003             hashSetNames = file.getHashSetNames();
 
 1005             if (hashSetNames.isEmpty()) {
 
 1006                 hashSetNamesString = Bundle.DiscoveryKeyUtils_HashHitsGroupKey_noHashHits();
 
 1008                 hashSetNamesString = String.join(
",", hashSetNames); 
 
 1013         String getDisplayName() {
 
 1014             return getHashSetNamesString();
 
 1018         public int compareTo(GroupKey otherGroupKey) {
 
 1019             if (otherGroupKey instanceof HashHitsGroupKey) {
 
 1020                 HashHitsGroupKey otherHashHitsGroupKey = (HashHitsGroupKey) otherGroupKey;
 
 1023                 if (getHashSetNames().isEmpty()) {
 
 1024                     if (otherHashHitsGroupKey.getHashSetNames().isEmpty()) {
 
 1029                 } 
else if (otherHashHitsGroupKey.getHashSetNames().isEmpty()) {
 
 1033                 return getHashSetNamesString().compareTo(otherHashHitsGroupKey.getHashSetNamesString());
 
 1035                 return compareClassNames(otherGroupKey);
 
 1040         public boolean equals(Object otherKey) {
 
 1041             if (otherKey == 
this) {
 
 1045             if (!(otherKey instanceof HashHitsGroupKey)) {
 
 1049             HashHitsGroupKey otherHashHitsGroupKey = (HashHitsGroupKey) otherKey;
 
 1050             return getHashSetNamesString().equals(otherHashHitsGroupKey.getHashSetNamesString());
 
 1054         public int hashCode() {
 
 1055             return Objects.hash(getHashSetNamesString());
 
 1063         List<String> getHashSetNames() {
 
 1064             return Collections.unmodifiableList(hashSetNames);
 
 1072         String getHashSetNamesString() {
 
 1073             return hashSetNamesString;
 
 1080     static class InterestingItemGroupKey 
extends GroupKey {
 
 1082         private final List<String> interestingItemSetNames;
 
 1083         private final String interestingItemSetNamesString;
 
 1090         @NbBundle.Messages({
 
 1091             "DiscoveryKeyUtils.InterestingItemGroupKey.noSets=None"})
 
 1092         InterestingItemGroupKey(ResultFile file) {
 
 1093             interestingItemSetNames = file.getInterestingSetNames();
 
 1095             if (interestingItemSetNames.isEmpty()) {
 
 1096                 interestingItemSetNamesString = Bundle.DiscoveryKeyUtils_InterestingItemGroupKey_noSets();
 
 1098                 interestingItemSetNamesString = String.join(
",", interestingItemSetNames); 
 
 1103         String getDisplayName() {
 
 1104             return getInterestingItemSetNamesString();
 
 1108         public int compareTo(GroupKey otherGroupKey) {
 
 1109             if (otherGroupKey instanceof InterestingItemGroupKey) {
 
 1110                 InterestingItemGroupKey otherInterestingItemGroupKey = (InterestingItemGroupKey) otherGroupKey;
 
 1113                 if (this.getInterestingItemSetNames().isEmpty()) {
 
 1114                     if (otherInterestingItemGroupKey.getInterestingItemSetNames().isEmpty()) {
 
 1119                 } 
else if (otherInterestingItemGroupKey.getInterestingItemSetNames().isEmpty()) {
 
 1123                 return getInterestingItemSetNamesString().compareTo(otherInterestingItemGroupKey.getInterestingItemSetNamesString());
 
 1125                 return compareClassNames(otherGroupKey);
 
 1130         public boolean equals(Object otherKey) {
 
 1131             if (otherKey == 
this) {
 
 1135             if (!(otherKey instanceof InterestingItemGroupKey)) {
 
 1139             InterestingItemGroupKey otherInterestingItemGroupKey = (InterestingItemGroupKey) otherKey;
 
 1140             return getInterestingItemSetNamesString().equals(otherInterestingItemGroupKey.getInterestingItemSetNamesString());
 
 1144         public int hashCode() {
 
 1145             return Objects.hash(getInterestingItemSetNamesString());
 
 1153         List<String> getInterestingItemSetNames() {
 
 1154             return Collections.unmodifiableList(interestingItemSetNames);
 
 1164         String getInterestingItemSetNamesString() {
 
 1165             return interestingItemSetNamesString;
 
 1172     static class LastActivityDateGroupKey 
extends GroupKey {
 
 1174         private ZonedDateTime currentWeekCutOff;
 
 1181         LastActivityDateGroupKey(Result result) {
 
 1182             if (result instanceof ResultDomain) {
 
 1183                 ResultDomain domainResult = ((ResultDomain) result);
 
 1186                 throw new IllegalArgumentException(
"Expected a domain result only.");
 
 1190         @NbBundle.Messages({
 
 1191             "# {0} - month abbreviation",
 
 1192             "# {1} - day of month",
 
 1194             "DiscoveryAttributes.ActivityDateGroupKey.getDisplayNameTemplate=Week of {0} {1}, {2}" 
 1197         String getDisplayName() {
 
 1198             MonthAbbreviation currentCutOffMonth = MonthAbbreviation.fromMonthValue(currentWeekCutOff.getMonthValue());
 
 1199             return Bundle.DiscoveryAttributes_ActivityDateGroupKey_getDisplayNameTemplate(
 
 1200                     currentCutOffMonth.toString(), Integer.toString(currentWeekCutOff.getDayOfMonth()),
 
 1201                     Integer.toString(currentWeekCutOff.getYear()));
 
 1205         public boolean equals(Object otherKey) {
 
 1206             if (otherKey == 
this) {
 
 1210             if (!(otherKey instanceof LastActivityDateGroupKey)) {
 
 1214             LastActivityDateGroupKey dateGroupKey = (LastActivityDateGroupKey) otherKey;
 
 1215             return getDisplayName().equals(dateGroupKey.getDisplayName());
 
 1219         public int hashCode() {
 
 1220             return Objects.hash(getDisplayName());
 
 1224         public int compareTo(GroupKey otherGroupKey) {
 
 1225             if (otherGroupKey instanceof LastActivityDateGroupKey) {
 
 1226                 LastActivityDateGroupKey otherDateGroupKey = (LastActivityDateGroupKey) otherGroupKey;
 
 1227                 return Long.compare(otherDateGroupKey.currentWeekCutOff.toEpochSecond(), currentWeekCutOff.toEpochSecond());
 
 1229                 return compareClassNames(otherGroupKey);
 
 1240         Instant startActivityAsInsant = Instant.ofEpochSecond(epochSeconds);
 
 1245         ZonedDateTime startActivityAsDateTime = ZonedDateTime.ofInstant(startActivityAsInsant, currentTimeZone.toZoneId());
 
 1248         return startActivityAsDateTime.with(TemporalAdjusters.nextOrSame(DayOfWeek.SUNDAY));
 
 1254     static class FirstActivityDateGroupKey 
extends GroupKey {
 
 1256         private ZonedDateTime currentWeekCutOff;
 
 1263         FirstActivityDateGroupKey(
Result result) {
 
 1264             if (result instanceof ResultDomain) {
 
 1265                 ResultDomain domainResult = ((ResultDomain) result);
 
 1268                 throw new IllegalArgumentException(
"Expected a domain result only.");
 
 1273         String getDisplayName() {
 
 1274             MonthAbbreviation currentCutOffMonth = MonthAbbreviation.fromMonthValue(currentWeekCutOff.getMonthValue());
 
 1275             return Bundle.DiscoveryAttributes_ActivityDateGroupKey_getDisplayNameTemplate(
 
 1276                     currentCutOffMonth.toString(), Integer.toString(currentWeekCutOff.getDayOfMonth()),
 
 1277                     Integer.toString(currentWeekCutOff.getYear()));
 
 1281         public boolean equals(Object otherKey) {
 
 1282             if (otherKey == 
this) {
 
 1286             if (!(otherKey instanceof FirstActivityDateGroupKey)) {
 
 1290             FirstActivityDateGroupKey dateGroupKey = (FirstActivityDateGroupKey) otherKey;
 
 1291             return getDisplayName().equals(dateGroupKey.getDisplayName());
 
 1295         public int hashCode() {
 
 1296             return Objects.hash(getDisplayName());
 
 1300         public int compareTo(GroupKey otherGroupKey) {
 
 1301             if (otherGroupKey instanceof FirstActivityDateGroupKey) {
 
 1302                 FirstActivityDateGroupKey otherDateGroupKey = (FirstActivityDateGroupKey) otherGroupKey;
 
 1303                 return Long.compare(otherDateGroupKey.currentWeekCutOff.toEpochSecond(), currentWeekCutOff.toEpochSecond());
 
 1305                 return compareClassNames(otherGroupKey);
 
 1314     static class PageViewsGroupKey 
extends GroupKey {
 
 1316         private final String displayName;
 
 1317         private final PageViews pageViews;
 
 1324         PageViewsGroupKey(Result result) {
 
 1325             if (result instanceof ResultDomain) {
 
 1326                 Long totalPageViews = ((ResultDomain) result).getTotalPageViews();
 
 1327                 if (totalPageViews == null) {
 
 1328                     totalPageViews = 0L;
 
 1330                 pageViews = PageViews.fromPageViewCount(totalPageViews);
 
 1331                 displayName = pageViews.toString();
 
 1333                 throw new IllegalArgumentException(
"Expected a domain instance only.");
 
 1338         String getDisplayName() {
 
 1343         public int hashCode() {
 
 1344             return Objects.hash(displayName);
 
 1352         PageViews getPageViews() {
 
 1357         public boolean equals(Object otherKey) {
 
 1358             if (otherKey == 
this) {
 
 1362             if (!(otherKey instanceof PageViewsGroupKey)) {
 
 1366             PageViewsGroupKey pageViewsKey = (PageViewsGroupKey) otherKey;
 
 1367             return pageViews.equals(pageViewsKey.getPageViews());
 
 1371         public int compareTo(GroupKey otherGroupKey) {
 
 1372             if (otherGroupKey instanceof PageViewsGroupKey) {
 
 1373                 PageViewsGroupKey pageViewsKey = (PageViewsGroupKey) otherGroupKey;
 
 1374                 return getPageViews().compareTo(pageViewsKey.getPageViews());
 
 1376                 return compareClassNames(otherGroupKey);
 
 1384     static class ObjectDetectedGroupKey 
extends GroupKey {
 
 1386         private final List<String> objectDetectedNames;
 
 1387         private final String objectDetectedNamesString;
 
 1394         @NbBundle.Messages({
 
 1395             "DiscoveryKeyUtils.ObjectDetectedGroupKey.noSets=None"})
 
 1396         ObjectDetectedGroupKey(ResultFile file) {
 
 1397             objectDetectedNames = file.getObjectDetectedNames();
 
 1398             if (objectDetectedNames.isEmpty()) {
 
 1399                 objectDetectedNamesString = Bundle.DiscoveryKeyUtils_ObjectDetectedGroupKey_noSets();
 
 1401                 objectDetectedNamesString = String.join(
",", objectDetectedNames); 
 
 1406         String getDisplayName() {
 
 1407             return getObjectDetectedNamesString();
 
 1411         public int compareTo(GroupKey otherGroupKey) {
 
 1412             if (otherGroupKey instanceof ObjectDetectedGroupKey) {
 
 1413                 ObjectDetectedGroupKey otherObjectDetectedGroupKey = (ObjectDetectedGroupKey) otherGroupKey;
 
 1416                 if (this.getObjectDetectedNames().isEmpty()) {
 
 1417                     if (otherObjectDetectedGroupKey.getObjectDetectedNames().isEmpty()) {
 
 1422                 } 
else if (otherObjectDetectedGroupKey.getObjectDetectedNames().isEmpty()) {
 
 1426                 return getObjectDetectedNamesString().compareTo(otherObjectDetectedGroupKey.getObjectDetectedNamesString());
 
 1428                 return compareClassNames(otherGroupKey);
 
 1433         public boolean equals(Object otherKey) {
 
 1434             if (otherKey == 
this) {
 
 1438             if (!(otherKey instanceof ObjectDetectedGroupKey)) {
 
 1442             ObjectDetectedGroupKey otherObjectDetectedGroupKey = (ObjectDetectedGroupKey) otherKey;
 
 1443             return getObjectDetectedNamesString().equals(otherObjectDetectedGroupKey.getObjectDetectedNamesString());
 
 1447         public int hashCode() {
 
 1448             return Objects.hash(getObjectDetectedNamesString());
 
 1456         List<String> getObjectDetectedNames() {
 
 1457             return Collections.unmodifiableList(objectDetectedNames);
 
 1467         String getObjectDetectedNamesString() {
 
 1468             return objectDetectedNamesString;
 
static final Logger logger
static FileSize fromVideoSize(long size)
abstract boolean equals(Object otherKey)
AbstractFile getFirstInstance()
FileSize(int ranking, long minB, long maxB, String displayName, String displaySize)
synchronized static Logger getLogger(String name)
static ZonedDateTime getCurrentWeekCutOff(long epochSeconds, ResultDomain domainResult)
static TimeZone getTimeZone()