Autopsy 4.22.1
Graphical digital forensics platform for The Sleuth Kit and other tools.
DiscoveryKeyUtils.java
Go to the documentation of this file.
1/*
2 * Autopsy
3 *
4 * Copyright 2020-2021 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 */
19package org.sleuthkit.autopsy.discovery.search;
20
21import java.time.DayOfWeek;
22import java.time.Instant;
23import java.time.ZonedDateTime;
24import java.time.temporal.TemporalAdjusters;
25import java.util.Collections;
26import java.util.Set;
27import java.util.HashSet;
28import java.util.List;
29import java.util.Objects;
30import java.util.TimeZone;
31import java.util.logging.Level;
32import org.openide.util.NbBundle;
33import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository;
34import org.sleuthkit.autopsy.coreutils.Logger;
35import org.sleuthkit.autopsy.coreutils.TimeZoneUtils;
36import org.sleuthkit.autopsy.discovery.search.SearchData.PageViews;
37import org.sleuthkit.autopsy.discovery.ui.MonthAbbreviation;
38import org.sleuthkit.datamodel.AbstractFile;
39import org.sleuthkit.datamodel.Content;
40import org.sleuthkit.datamodel.SleuthkitCase;
41import org.sleuthkit.datamodel.TskCoreException;
42
46public class DiscoveryKeyUtils {
47
48 private final static Logger logger = Logger.getLogger(DiscoveryKeyUtils.class.getName());
49
53 static class SearchKey implements Comparable<SearchKey> {
54
55 private final String keyString;
56 private final Group.GroupSortingAlgorithm groupSortingType;
57 private final DiscoveryAttributes.AttributeType groupAttributeType;
58 private final ResultsSorter.SortingMethod sortingMethod;
59 private final List<AbstractFilter> filters;
60 private final SleuthkitCase sleuthkitCase;
61 private final CentralRepository centralRepository;
62 private final SearchContext context;
63
78 SearchKey(String userName, List<AbstractFilter> filters,
79 DiscoveryAttributes.AttributeType groupAttributeType,
80 Group.GroupSortingAlgorithm groupSortingType,
81 ResultsSorter.SortingMethod sortingMethod,
82 SleuthkitCase sleuthkitCase, CentralRepository centralRepository, SearchContext context) {
83 this.groupAttributeType = groupAttributeType;
84 this.groupSortingType = groupSortingType;
85 this.sortingMethod = sortingMethod;
86 this.filters = filters;
87 this.context = context;
88
89 StringBuilder searchStringBuilder = new StringBuilder();
90 searchStringBuilder.append(userName);
91 for (AbstractFilter filter : filters) {
92 searchStringBuilder.append(filter.toString());
93 }
94 searchStringBuilder.append(groupAttributeType).append(groupSortingType).append(sortingMethod);
95 keyString = searchStringBuilder.toString();
96 this.sleuthkitCase = sleuthkitCase;
97 this.centralRepository = centralRepository;
98 }
99
110 SearchKey(String userName, List<AbstractFilter> filters,
111 DiscoveryAttributes.AttributeType groupAttributeType,
112 Group.GroupSortingAlgorithm groupSortingType,
113 ResultsSorter.SortingMethod sortingMethod) {
114 this(userName, filters, groupAttributeType, groupSortingType,
115 sortingMethod, null, null, null);
116 //this constructor should only be used putting things directly into a map or getting if present since casedb, cr, and search context will be null
117 }
118
119 @Override
120 public int compareTo(SearchKey otherSearchKey) {
121 return getKeyString().compareTo(otherSearchKey.getKeyString());
122 }
123
124 @Override
125 public boolean equals(Object otherKey) {
126 if (otherKey == this) {
127 return true;
128 }
129
130 if (!(otherKey instanceof SearchKey)) {
131 return false;
132 }
133
134 SearchKey otherSearchKey = (SearchKey) otherKey;
135 if (this.sleuthkitCase != otherSearchKey.getSleuthkitCase()
136 || this.centralRepository != otherSearchKey.getCentralRepository()) {
137 return false;
138 }
139
140 return getKeyString().equals(otherSearchKey.getKeyString());
141 }
142
143 @Override
144 public int hashCode() {
145 int hash = 5;
146 hash = 79 * hash + Objects.hashCode(getKeyString());
147 return hash;
148 }
149
160 SearchContext getContext() throws DiscoveryException {
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.");
163 }
164 return context;
165 }
166
172 String getKeyString() {
173 return keyString;
174 }
175
181 List<AbstractFilter> getFilters() {
182 return Collections.unmodifiableList(this.filters);
183 }
184
190 Group.GroupSortingAlgorithm getGroupSortingType() {
191 return groupSortingType;
192 }
193
199 DiscoveryAttributes.AttributeType getGroupAttributeType() {
200 return groupAttributeType;
201 }
202
208 ResultsSorter.SortingMethod getFileSortingMethod() {
209 return sortingMethod;
210 }
211
217 SleuthkitCase getSleuthkitCase() {
218 return this.sleuthkitCase;
219 }
220
226 CentralRepository getCentralRepository() {
227 return this.centralRepository;
228 }
229 }
230
234 public abstract static class GroupKey implements Comparable<GroupKey> {
235
242 abstract String getDisplayName();
243
251 @Override
252 abstract public boolean equals(Object otherKey);
253
259 @Override
260 abstract public int hashCode();
261
271 int compareClassNames(GroupKey otherGroupKey) {
272 return this.getClass().getName().compareTo(otherGroupKey.getClass().getName());
273 }
274
275 @Override
276 public String toString() {
277 return getDisplayName();
278 }
279 }
280
284 static class FileSizeGroupKey extends GroupKey {
285
286 private final SearchData.FileSize fileSize;
287
293 FileSizeGroupKey(Result file) {
294 ResultFile resultFile = (ResultFile) file;
295 if (resultFile.getFileType() == SearchData.Type.VIDEO) {
296 fileSize = SearchData.FileSize.fromVideoSize(resultFile.getFirstInstance().getSize());
297 } else {
298 fileSize = SearchData.FileSize.fromImageSize(resultFile.getFirstInstance().getSize());
299 }
300 }
301
302 @Override
303 String getDisplayName() {
304 return getFileSize().toString();
305 }
306
307 @Override
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());
312 } else {
313 return compareClassNames(otherGroupKey);
314 }
315 }
316
317 @Override
318 public boolean equals(Object otherKey) {
319 if (otherKey == this) {
320 return true;
321 }
322
323 if (!(otherKey instanceof FileSizeGroupKey)) {
324 return false;
325 }
326
327 FileSizeGroupKey otherFileSizeGroupKey = (FileSizeGroupKey) otherKey;
328 return getFileSize().equals(otherFileSizeGroupKey.getFileSize());
329 }
330
331 @Override
332 public int hashCode() {
333 return Objects.hash(getFileSize().getRanking());
334 }
335
341 SearchData.FileSize getFileSize() {
342 return fileSize;
343 }
344 }
345
349 static class FileTypeGroupKey extends GroupKey {
350
351 private final SearchData.Type fileType;
352
358 FileTypeGroupKey(Result file) {
359 fileType = ((ResultFile) file).getFileType();
360 }
361
362 @Override
363 String getDisplayName() {
364 return getFileType().toString();
365 }
366
367 @Override
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());
372 } else {
373 return compareClassNames(otherGroupKey);
374 }
375 }
376
377 @Override
378 public boolean equals(Object otherKey) {
379 if (otherKey == this) {
380 return true;
381 }
382
383 if (!(otherKey instanceof FileTypeGroupKey)) {
384 return false;
385 }
386
387 FileTypeGroupKey otherFileTypeGroupKey = (FileTypeGroupKey) otherKey;
388 return getFileType().equals(otherFileTypeGroupKey.getFileType());
389 }
390
391 @Override
392 public int hashCode() {
393 return Objects.hash(getFileType().getRanking());
394 }
395
401 SearchData.Type getFileType() {
402 return fileType;
403 }
404 }
405
409 static class KeywordListGroupKey extends GroupKey {
410
411 private final List<String> keywordListNames;
412 private final String keywordListNamesString;
413
419 @NbBundle.Messages({
420 "DiscoveryKeyUtils.KeywordListGroupKey.noKeywords=None"})
421 KeywordListGroupKey(ResultFile file) {
422 keywordListNames = file.getKeywordListNames();
423 if (keywordListNames.isEmpty()) {
424 keywordListNamesString = Bundle.DiscoveryKeyUtils_KeywordListGroupKey_noKeywords();
425 } else {
426 keywordListNamesString = String.join(",", keywordListNames); // NON-NLS
427 }
428 }
429
430 @Override
431 String getDisplayName() {
432 return getKeywordListNamesString();
433 }
434
435 @Override
436 public int compareTo(GroupKey otherGroupKey) {
437 if (otherGroupKey instanceof KeywordListGroupKey) {
438 KeywordListGroupKey otherKeywordListNamesGroupKey = (KeywordListGroupKey) otherGroupKey;
439
440 // Put the empty list at the end
441 if (getKeywordListNames().isEmpty()) {
442 if (otherKeywordListNamesGroupKey.getKeywordListNames().isEmpty()) {
443 return 0;
444 } else {
445 return 1;
446 }
447 } else if (otherKeywordListNamesGroupKey.getKeywordListNames().isEmpty()) {
448 return -1;
449 }
450
451 return getKeywordListNamesString().compareTo(otherKeywordListNamesGroupKey.getKeywordListNamesString());
452 } else {
453 return compareClassNames(otherGroupKey);
454 }
455 }
456
457 @Override
458 public boolean equals(Object otherKey) {
459 if (otherKey == this) {
460 return true;
461 }
462
463 if (!(otherKey instanceof KeywordListGroupKey)) {
464 return false;
465 }
466
467 KeywordListGroupKey otherKeywordListGroupKey = (KeywordListGroupKey) otherKey;
468 return getKeywordListNamesString().equals(otherKeywordListGroupKey.getKeywordListNamesString());
469 }
470
471 @Override
472 public int hashCode() {
473 return Objects.hash(getKeywordListNamesString());
474 }
475
481 List<String> getKeywordListNames() {
482 return Collections.unmodifiableList(keywordListNames);
483 }
484
492 String getKeywordListNamesString() {
493 return keywordListNamesString;
494 }
495 }
496
500 static class FileTagGroupKey extends GroupKey {
501
502 private final List<String> tagNames;
503 private final String tagNamesString;
504
510 @NbBundle.Messages({
511 "DiscoveryKeyUtils.FileTagGroupKey.noSets=None"})
512 FileTagGroupKey(ResultFile file) {
513 tagNames = file.getTagNames();
514
515 if (tagNames.isEmpty()) {
516 tagNamesString = Bundle.DiscoveryKeyUtils_FileTagGroupKey_noSets();
517 } else {
518 tagNamesString = String.join(",", tagNames); // NON-NLS
519 }
520 }
521
522 @Override
523 String getDisplayName() {
524 return getTagNamesString();
525 }
526
527 @Override
528 public int compareTo(GroupKey otherGroupKey) {
529 if (otherGroupKey instanceof FileTagGroupKey) {
530 FileTagGroupKey otherFileTagGroupKey = (FileTagGroupKey) otherGroupKey;
531
532 // Put the empty list at the end
533 if (getTagNames().isEmpty()) {
534 if (otherFileTagGroupKey.getTagNames().isEmpty()) {
535 return 0;
536 } else {
537 return 1;
538 }
539 } else if (otherFileTagGroupKey.getTagNames().isEmpty()) {
540 return -1;
541 }
542
543 return getTagNamesString().compareTo(otherFileTagGroupKey.getTagNamesString());
544 } else {
545 return compareClassNames(otherGroupKey);
546 }
547 }
548
549 @Override
550 public boolean equals(Object otherKey) {
551 if (otherKey == this) {
552 return true;
553 }
554 if (!(otherKey instanceof FileTagGroupKey)) {
555 return false;
556 }
557 FileTagGroupKey otherFileTagGroupKey = (FileTagGroupKey) otherKey;
558 return getTagNamesString().equals(otherFileTagGroupKey.getTagNamesString());
559 }
560
561 @Override
562 public int hashCode() {
563 return Objects.hash(getTagNamesString());
564 }
565
571 List<String> getTagNames() {
572 return Collections.unmodifiableList(tagNames);
573 }
574
582 String getTagNamesString() {
583 return tagNamesString;
584 }
585 }
586
590 static class ParentPathGroupKey extends GroupKey {
591
592 private String parentPath;
593 private Long parentID;
594
600 ParentPathGroupKey(ResultFile file) {
601 Content parent;
602 try {
603 parent = file.getFirstInstance().getParent();
604 } catch (TskCoreException ignored) {
605 parent = null;
606 }
607 //Find the directory this file is in if it is an embedded file
608 while (parent != null && parent instanceof AbstractFile && ((AbstractFile) parent).isFile()) {
609 try {
610 parent = parent.getParent();
611 } catch (TskCoreException ignored) {
612 parent = null;
613 }
614 }
615 setParentPathAndID(parent, file);
616 }
617
624 private void setParentPathAndID(Content parent, ResultFile file) {
625 if (parent != null) {
626 try {
627 parentPath = parent.getUniquePath();
628 parentID = parent.getId();
629 } catch (TskCoreException ignored) {
630 //catch block left blank purposefully next if statement will handle case when exception takes place as well as when parent is null
631 }
632
633 }
634 if (parentPath == null) {
635 if (file.getFirstInstance().getParentPath() != null) {
636 parentPath = file.getFirstInstance().getParentPath();
637 } else {
638 parentPath = ""; // NON-NLS
639 }
640 parentID = -1L;
641 }
642 }
643
644 @Override
645 String getDisplayName() {
646 return getParentPath();
647 }
648
649 @Override
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());
656 }
657 return comparisonResult;
658 } else {
659 return compareClassNames(otherGroupKey);
660 }
661 }
662
663 @Override
664 public boolean equals(Object otherKey) {
665 if (otherKey == this) {
666 return true;
667 }
668
669 if (!(otherKey instanceof ParentPathGroupKey)) {
670 return false;
671 }
672
673 ParentPathGroupKey otherParentPathGroupKey = (ParentPathGroupKey) otherKey;
674 return getParentPath().equals(otherParentPathGroupKey.getParentPath()) && getParentID().equals(otherParentPathGroupKey.getParentID());
675 }
676
677 @Override
678 public int hashCode() {
679 int hashCode = 11;
680 hashCode = 61 * hashCode + Objects.hash(getParentPath());
681 hashCode = 61 * hashCode + Objects.hash(getParentID());
682 return hashCode;
683 }
684
690 String getParentPath() {
691 return parentPath;
692 }
693
699 Long getParentID() {
700 return parentID;
701 }
702 }
703
707 static class DataSourceGroupKey extends GroupKey {
708
709 private final long dataSourceID;
710 private String displayName;
711
717 @NbBundle.Messages({
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) {
724 //get the id first so that it can be used when logging if necessary
725 dataSourceID = result.getDataSourceObjectId();
726 try {
727 // The data source should be cached so this won't actually be a database query.
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); // NON-NLS
732 displayName = Bundle.DiscoveryKeyUtils_DataSourceGroupKey_idOnly(dataSourceID);
733 }
734 }
735
736 @Override
737 String getDisplayName() {
738 return displayName;
739 }
740
741 @Override
742 public int compareTo(GroupKey otherGroupKey) {
743 if (otherGroupKey instanceof DataSourceGroupKey) {
744 DataSourceGroupKey otherDataSourceGroupKey = (DataSourceGroupKey) otherGroupKey;
745 return Long.compare(getDataSourceID(), otherDataSourceGroupKey.getDataSourceID());
746 } else {
747 return compareClassNames(otherGroupKey);
748 }
749 }
750
751 @Override
752 public boolean equals(Object otherKey) {
753 if (otherKey == this) {
754 return true;
755 }
756
757 if (!(otherKey instanceof DataSourceGroupKey)) {
758 return false;
759 }
760
761 DataSourceGroupKey otherDataSourceGroupKey = (DataSourceGroupKey) otherKey;
762 return getDataSourceID() == otherDataSourceGroupKey.getDataSourceID();
763 }
764
765 @Override
766 public int hashCode() {
767 return Objects.hash(getDataSourceID());
768 }
769
775 long getDataSourceID() {
776 return dataSourceID;
777 }
778 }
779
784 static class NoGroupingGroupKey extends GroupKey {
785
789 NoGroupingGroupKey() {
790 // Nothing to save - all files will get the same GroupKey
791 }
792
793 @NbBundle.Messages({
794 "DiscoveryKeyUtils.NoGroupingGroupKey.allFiles=All Files"})
795 @Override
796 String getDisplayName() {
797 return Bundle.DiscoveryKeyUtils_NoGroupingGroupKey_allFiles();
798 }
799
800 @Override
801 public int compareTo(GroupKey otherGroupKey) {
802 // As long as the other key is the same type, they are equal
803 if (otherGroupKey instanceof NoGroupingGroupKey) {
804 return 0;
805 } else {
806 return compareClassNames(otherGroupKey);
807 }
808 }
809
810 @Override
811 public boolean equals(Object otherKey) {
812 if (otherKey == this) {
813 return true;
814 }
815 // As long as the other key is the same type, they are equal
816 return otherKey instanceof NoGroupingGroupKey;
817 }
818
819 @Override
820 public int hashCode() {
821 return 0;
822 }
823 }
824
828 static class DomainCategoryGroupKey extends GroupKey {
829
830 private final Set<String> webCategories = new HashSet<>();
831 private final String displayName;
832
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);
838 } else {
839 throw new IllegalArgumentException("Input result should be of type ResultDomain");
840 }
841 }
842
843 @Override
844 String getDisplayName() {
845
846 return this.displayName;
847 }
848
849 @Override
850 public boolean equals(Object otherKey) {
851 if (otherKey instanceof GroupKey) {
852 return compareTo((GroupKey) otherKey) == 0;
853 }
854 return false;
855 }
856
857 @Override
858 public int hashCode() {
859 return Objects.hash(webCategories);
860 }
861
862 @Override
863 public int compareTo(GroupKey otherGroupKey) {
864 if (otherGroupKey instanceof DomainCategoryGroupKey) {
865 if (webCategories.size() != ((DomainCategoryGroupKey) otherGroupKey).getWebCategories().size()) {
866 return 1;
867 }
868 if (webCategories.containsAll(((DomainCategoryGroupKey) otherGroupKey).getWebCategories())) {
869 return 0;
870 } else {
871 return -1;
872 }
873 } else {
874 return compareClassNames(otherGroupKey);
875 }
876 }
877
878 Set<String> getWebCategories() {
879 return Collections.unmodifiableSet(webCategories);
880 }
881 }
882
886 static class PreviouslyNotableGroupKey extends GroupKey {
887
888 private final SearchData.PreviouslyNotable notableStatus;
889
890 PreviouslyNotableGroupKey(Result result) {
891 this.notableStatus = result.getPreviouslyNotableInCR();
892 }
893
894 @Override
895 String getDisplayName() {
896 return this.notableStatus.toString();
897 }
898
899 @Override
900 public boolean equals(Object otherKey) {
901 if (otherKey instanceof GroupKey) {
902 return compareTo((GroupKey) otherKey) == 0;
903 }
904 return false;
905 }
906
907 @Override
908 public int hashCode() {
909 return Objects.hash(getStatus().getRanking());
910 }
911
912 @Override
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());
917 } else {
918 return compareClassNames(otherGroupKey);
919 }
920 }
921
922 SearchData.PreviouslyNotable getStatus() {
923 return notableStatus;
924 }
925 }
926
930 static class FrequencyGroupKey extends GroupKey {
931
932 private final SearchData.Frequency frequency;
933
939 FrequencyGroupKey(Result result) {
940 frequency = result.getFrequency();
941 }
942
943 @Override
944 String getDisplayName() {
945 return getFrequency().toString();
946 }
947
948 @Override
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());
953 } else {
954 return compareClassNames(otherGroupKey);
955 }
956 }
957
958 @Override
959 public boolean equals(Object otherKey) {
960 if (otherKey == this) {
961 return true;
962 }
963
964 if (!(otherKey instanceof FrequencyGroupKey)) {
965 return false;
966 }
967
968 FrequencyGroupKey otherFrequencyGroupKey = (FrequencyGroupKey) otherKey;
969 return getFrequency().equals(otherFrequencyGroupKey.getFrequency());
970 }
971
972 @Override
973 public int hashCode() {
974 return Objects.hash(getFrequency().getRanking());
975 }
976
982 SearchData.Frequency getFrequency() {
983 return frequency;
984 }
985 }
986
990 static class HashHitsGroupKey extends GroupKey {
991
992 private final List<String> hashSetNames;
993 private final String hashSetNamesString;
994
1000 @NbBundle.Messages({
1001 "DiscoveryKeyUtils.HashHitsGroupKey.noHashHits=None"})
1002 HashHitsGroupKey(ResultFile file) {
1003 hashSetNames = file.getHashSetNames();
1004
1005 if (hashSetNames.isEmpty()) {
1006 hashSetNamesString = Bundle.DiscoveryKeyUtils_HashHitsGroupKey_noHashHits();
1007 } else {
1008 hashSetNamesString = String.join(",", hashSetNames); // NON-NLS
1009 }
1010 }
1011
1012 @Override
1013 String getDisplayName() {
1014 return getHashSetNamesString();
1015 }
1016
1017 @Override
1018 public int compareTo(GroupKey otherGroupKey) {
1019 if (otherGroupKey instanceof HashHitsGroupKey) {
1020 HashHitsGroupKey otherHashHitsGroupKey = (HashHitsGroupKey) otherGroupKey;
1021
1022 // Put the empty list at the end
1023 if (getHashSetNames().isEmpty()) {
1024 if (otherHashHitsGroupKey.getHashSetNames().isEmpty()) {
1025 return 0;
1026 } else {
1027 return 1;
1028 }
1029 } else if (otherHashHitsGroupKey.getHashSetNames().isEmpty()) {
1030 return -1;
1031 }
1032
1033 return getHashSetNamesString().compareTo(otherHashHitsGroupKey.getHashSetNamesString());
1034 } else {
1035 return compareClassNames(otherGroupKey);
1036 }
1037 }
1038
1039 @Override
1040 public boolean equals(Object otherKey) {
1041 if (otherKey == this) {
1042 return true;
1043 }
1044
1045 if (!(otherKey instanceof HashHitsGroupKey)) {
1046 return false;
1047 }
1048
1049 HashHitsGroupKey otherHashHitsGroupKey = (HashHitsGroupKey) otherKey;
1050 return getHashSetNamesString().equals(otherHashHitsGroupKey.getHashSetNamesString());
1051 }
1052
1053 @Override
1054 public int hashCode() {
1055 return Objects.hash(getHashSetNamesString());
1056 }
1057
1063 List<String> getHashSetNames() {
1064 return Collections.unmodifiableList(hashSetNames);
1065 }
1066
1072 String getHashSetNamesString() {
1073 return hashSetNamesString;
1074 }
1075 }
1076
1080 static class InterestingItemGroupKey extends GroupKey {
1081
1082 private final List<String> interestingItemSetNames;
1083 private final String interestingItemSetNamesString;
1084
1090 @NbBundle.Messages({
1091 "DiscoveryKeyUtils.InterestingItemGroupKey.noSets=None"})
1092 InterestingItemGroupKey(ResultFile file) {
1093 interestingItemSetNames = file.getInterestingSetNames();
1094
1095 if (interestingItemSetNames.isEmpty()) {
1096 interestingItemSetNamesString = Bundle.DiscoveryKeyUtils_InterestingItemGroupKey_noSets();
1097 } else {
1098 interestingItemSetNamesString = String.join(",", interestingItemSetNames); // NON-NLS
1099 }
1100 }
1101
1102 @Override
1103 String getDisplayName() {
1104 return getInterestingItemSetNamesString();
1105 }
1106
1107 @Override
1108 public int compareTo(GroupKey otherGroupKey) {
1109 if (otherGroupKey instanceof InterestingItemGroupKey) {
1110 InterestingItemGroupKey otherInterestingItemGroupKey = (InterestingItemGroupKey) otherGroupKey;
1111
1112 // Put the empty list at the end
1113 if (this.getInterestingItemSetNames().isEmpty()) {
1114 if (otherInterestingItemGroupKey.getInterestingItemSetNames().isEmpty()) {
1115 return 0;
1116 } else {
1117 return 1;
1118 }
1119 } else if (otherInterestingItemGroupKey.getInterestingItemSetNames().isEmpty()) {
1120 return -1;
1121 }
1122
1123 return getInterestingItemSetNamesString().compareTo(otherInterestingItemGroupKey.getInterestingItemSetNamesString());
1124 } else {
1125 return compareClassNames(otherGroupKey);
1126 }
1127 }
1128
1129 @Override
1130 public boolean equals(Object otherKey) {
1131 if (otherKey == this) {
1132 return true;
1133 }
1134
1135 if (!(otherKey instanceof InterestingItemGroupKey)) {
1136 return false;
1137 }
1138
1139 InterestingItemGroupKey otherInterestingItemGroupKey = (InterestingItemGroupKey) otherKey;
1140 return getInterestingItemSetNamesString().equals(otherInterestingItemGroupKey.getInterestingItemSetNamesString());
1141 }
1142
1143 @Override
1144 public int hashCode() {
1145 return Objects.hash(getInterestingItemSetNamesString());
1146 }
1147
1153 List<String> getInterestingItemSetNames() {
1154 return Collections.unmodifiableList(interestingItemSetNames);
1155 }
1156
1164 String getInterestingItemSetNamesString() {
1165 return interestingItemSetNamesString;
1166 }
1167 }
1168
1172 static class LastActivityDateGroupKey extends GroupKey {
1173
1174 private ZonedDateTime currentWeekCutOff;
1175
1181 LastActivityDateGroupKey(Result result) {
1182 if (result instanceof ResultDomain) {
1183 ResultDomain domainResult = ((ResultDomain) result);
1184 currentWeekCutOff = getCurrentWeekCutOff(domainResult.getActivityEnd(), domainResult);
1185 } else {
1186 throw new IllegalArgumentException("Expected a domain result only.");
1187 }
1188 }
1189
1190 @NbBundle.Messages({
1191 "# {0} - month abbreviation",
1192 "# {1} - day of month",
1193 "# {2} - year",
1194 "DiscoveryAttributes.ActivityDateGroupKey.getDisplayNameTemplate=Week of {0} {1}, {2}"
1195 })
1196 @Override
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()));
1202 }
1203
1204 @Override
1205 public boolean equals(Object otherKey) {
1206 if (otherKey == this) {
1207 return true;
1208 }
1209
1210 if (!(otherKey instanceof LastActivityDateGroupKey)) {
1211 return false;
1212 }
1213
1214 LastActivityDateGroupKey dateGroupKey = (LastActivityDateGroupKey) otherKey;
1215 return getDisplayName().equals(dateGroupKey.getDisplayName());
1216 }
1217
1218 @Override
1219 public int hashCode() {
1220 return Objects.hash(getDisplayName());
1221 }
1222
1223 @Override
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());
1228 } else {
1229 return compareClassNames(otherGroupKey);
1230 }
1231 }
1232 }
1233
1239 private static ZonedDateTime getCurrentWeekCutOff(long epochSeconds, ResultDomain domainResult) {
1240 Instant startActivityAsInsant = Instant.ofEpochSecond(epochSeconds);
1241 // Determines the timezone using the settings panel or value parsed from the
1242 // parent data source
1243 TimeZone currentTimeZone = TimeZoneUtils.getTimeZone();
1244 // Convert to a datetime using epoch and timezone.
1245 ZonedDateTime startActivityAsDateTime = ZonedDateTime.ofInstant(startActivityAsInsant, currentTimeZone.toZoneId());
1246 // Get the closest Sunday, which is the cut off for the current week.
1247 // Use this cut off to perform grouping and comparing.
1248 return startActivityAsDateTime.with(TemporalAdjusters.nextOrSame(DayOfWeek.SUNDAY));
1249 }
1250
1254 static class FirstActivityDateGroupKey extends GroupKey {
1255
1256 private ZonedDateTime currentWeekCutOff;
1257
1263 FirstActivityDateGroupKey(Result result) {
1264 if (result instanceof ResultDomain) {
1265 ResultDomain domainResult = ((ResultDomain) result);
1266 currentWeekCutOff = getCurrentWeekCutOff(domainResult.getActivityStart(), domainResult);
1267 } else {
1268 throw new IllegalArgumentException("Expected a domain result only.");
1269 }
1270 }
1271
1272 @Override
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()));
1278 }
1279
1280 @Override
1281 public boolean equals(Object otherKey) {
1282 if (otherKey == this) {
1283 return true;
1284 }
1285
1286 if (!(otherKey instanceof FirstActivityDateGroupKey)) {
1287 return false;
1288 }
1289
1290 FirstActivityDateGroupKey dateGroupKey = (FirstActivityDateGroupKey) otherKey;
1291 return getDisplayName().equals(dateGroupKey.getDisplayName());
1292 }
1293
1294 @Override
1295 public int hashCode() {
1296 return Objects.hash(getDisplayName());
1297 }
1298
1299 @Override
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());
1304 } else {
1305 return compareClassNames(otherGroupKey);
1306 }
1307 }
1308 }
1309
1314 static class PageViewsGroupKey extends GroupKey {
1315
1316 private final String displayName;
1317 private final PageViews pageViews;
1318
1324 PageViewsGroupKey(Result result) {
1325 if (result instanceof ResultDomain) {
1326 Long totalPageViews = ((ResultDomain) result).getTotalPageViews();
1327 if (totalPageViews == null) {
1328 totalPageViews = 0L;
1329 }
1330 pageViews = PageViews.fromPageViewCount(totalPageViews);
1331 displayName = pageViews.toString();
1332 } else {
1333 throw new IllegalArgumentException("Expected a domain instance only.");
1334 }
1335 }
1336
1337 @Override
1338 String getDisplayName() {
1339 return displayName;
1340 }
1341
1342 @Override
1343 public int hashCode() {
1344 return Objects.hash(displayName);
1345 }
1346
1352 PageViews getPageViews() {
1353 return pageViews;
1354 }
1355
1356 @Override
1357 public boolean equals(Object otherKey) {
1358 if (otherKey == this) {
1359 return true;
1360 }
1361
1362 if (!(otherKey instanceof PageViewsGroupKey)) {
1363 return false;
1364 }
1365
1366 PageViewsGroupKey pageViewsKey = (PageViewsGroupKey) otherKey;
1367 return pageViews.equals(pageViewsKey.getPageViews());
1368 }
1369
1370 @Override
1371 public int compareTo(GroupKey otherGroupKey) {
1372 if (otherGroupKey instanceof PageViewsGroupKey) {
1373 PageViewsGroupKey pageViewsKey = (PageViewsGroupKey) otherGroupKey;
1374 return getPageViews().compareTo(pageViewsKey.getPageViews());
1375 } else {
1376 return compareClassNames(otherGroupKey);
1377 }
1378 }
1379 }
1380
1384 static class ObjectDetectedGroupKey extends GroupKey {
1385
1386 private final List<String> objectDetectedNames;
1387 private final String objectDetectedNamesString;
1388
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();
1400 } else {
1401 objectDetectedNamesString = String.join(",", objectDetectedNames); // NON-NLS
1402 }
1403 }
1404
1405 @Override
1406 String getDisplayName() {
1407 return getObjectDetectedNamesString();
1408 }
1409
1410 @Override
1411 public int compareTo(GroupKey otherGroupKey) {
1412 if (otherGroupKey instanceof ObjectDetectedGroupKey) {
1413 ObjectDetectedGroupKey otherObjectDetectedGroupKey = (ObjectDetectedGroupKey) otherGroupKey;
1414
1415 // Put the empty list at the end
1416 if (this.getObjectDetectedNames().isEmpty()) {
1417 if (otherObjectDetectedGroupKey.getObjectDetectedNames().isEmpty()) {
1418 return 0;
1419 } else {
1420 return 1;
1421 }
1422 } else if (otherObjectDetectedGroupKey.getObjectDetectedNames().isEmpty()) {
1423 return -1;
1424 }
1425
1426 return getObjectDetectedNamesString().compareTo(otherObjectDetectedGroupKey.getObjectDetectedNamesString());
1427 } else {
1428 return compareClassNames(otherGroupKey);
1429 }
1430 }
1431
1432 @Override
1433 public boolean equals(Object otherKey) {
1434 if (otherKey == this) {
1435 return true;
1436 }
1437
1438 if (!(otherKey instanceof ObjectDetectedGroupKey)) {
1439 return false;
1440 }
1441
1442 ObjectDetectedGroupKey otherObjectDetectedGroupKey = (ObjectDetectedGroupKey) otherKey;
1443 return getObjectDetectedNamesString().equals(otherObjectDetectedGroupKey.getObjectDetectedNamesString());
1444 }
1445
1446 @Override
1447 public int hashCode() {
1448 return Objects.hash(getObjectDetectedNamesString());
1449 }
1450
1456 List<String> getObjectDetectedNames() {
1457 return Collections.unmodifiableList(objectDetectedNames);
1458 }
1459
1467 String getObjectDetectedNamesString() {
1468 return objectDetectedNamesString;
1469 }
1470 }
1471
1476 //private constructor in a utility class intentionally left blank
1477 }
1478}
synchronized static Logger getLogger(String name)
Definition Logger.java:124
static ZonedDateTime getCurrentWeekCutOff(long epochSeconds, ResultDomain domainResult)

Copyright © 2012-2024 Sleuth Kit Labs. Generated on:
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.