Autopsy  4.21.0
Graphical digital forensics platform for The Sleuth Kit and other tools.
ResultsSorter.java
Go to the documentation of this file.
1 /*
2  * Autopsy Forensic Browser
3  *
4  * Copyright 2020 Basis Technology Corp.
5  * Contact: carrier <at> sleuthkit <dot> org
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19 package org.sleuthkit.autopsy.discovery.search;
20 
21 import java.util.ArrayList;
22 import java.util.Arrays;
23 import java.util.Collections;
24 import java.util.Comparator;
25 import java.util.List;
26 import org.openide.util.NbBundle;
27 import org.sleuthkit.datamodel.TskCoreException;
28 
32 public class ResultsSorter implements Comparator<Result> {
33 
34  private final List<Comparator<Result>> comparators = new ArrayList<>();
35 
43  public ResultsSorter(SortingMethod method) {
44 
45  // Set up the primary comparators that should applied to the results
46  switch (method) {
47  case BY_DATA_SOURCE:
48  comparators.add(getDataSourceComparator());
49  break;
50  case BY_FILE_SIZE:
51  comparators.add(getFileSizeComparator());
52  break;
53  case BY_FILE_TYPE:
54  comparators.add(getTypeComparator());
55  comparators.add(getMIMETypeComparator());
56  break;
57  case BY_FREQUENCY:
58  comparators.add(getFrequencyComparator());
59  break;
60  case BY_KEYWORD_LIST_NAMES:
61  comparators.add(getKeywordListNameComparator());
62  break;
63  case BY_FULL_PATH:
64  comparators.add(getParentPathComparator());
65  break;
66  case BY_FILE_NAME:
67  comparators.add(getFileNameComparator());
68  break;
69  case BY_DOMAIN_NAME:
70  comparators.add(getDomainNameComparator());
71  break;
72  case BY_PAGE_VIEWS:
73  comparators.add(getPageViewComparator());
74  break;
75  case BY_LAST_ACTIVITY:
76  comparators.add(getLastActivityDateTimeComparator());
77  break;
78  case BY_DOWNLOADS:
79  comparators.add(getWebDownloadsComparator());
80  break;
81  default:
82  // The default comparator will be added afterward
83  break;
84  }
85 
86  // Add the default comparator to the end. This will ensure a consistent sort
87  // order regardless of the order the results were added to the list.
88  comparators.add(getDefaultComparator());
89  }
90 
91  @Override
92  public int compare(Result result1, Result result2) {
93 
94  int result = 0;
95  for (Comparator<Result> comp : comparators) {
96  result = comp.compare(result1, result2);
97  if (result != 0) {
98  return result;
99  }
100  }
101 
102  // The results are the same
103  return result;
104  }
105 
112  private static Comparator<Result> getDataSourceComparator() {
113  return (Result result1, Result result2) -> Long.compare(result1.getDataSourceObjectId(), result2.getDataSourceObjectId());
114  }
115 
122  private static Comparator<Result> getTypeComparator() {
123  return (Result result1, Result result2) -> Integer.compare(result1.getType().getRanking(), result2.getType().getRanking());
124  }
125 
134  private static Comparator<Result> getKeywordListNameComparator() {
135  return (Result result1, Result result2) -> {
136  // Put empty lists at the bottom
137  if (result1.getType() == SearchData.Type.DOMAIN) {
138  return 0;
139  }
140  ResultFile file1 = (ResultFile) result1;
141  ResultFile file2 = (ResultFile) result2;
142  if (file1.getKeywordListNames().isEmpty()) {
143  if (file2.getKeywordListNames().isEmpty()) {
144  return 0;
145  }
146  return 1;
147  } else if (file2.getKeywordListNames().isEmpty()) {
148  return -1;
149  }
150 
151  String list1 = String.join(",", file1.getKeywordListNames());
152  String list2 = String.join(",", file2.getKeywordListNames());
153  return compareStrings(list1, list2);
154  };
155  }
156 
163  private static Comparator<Result> getParentPathComparator() {
164 
165  return new Comparator<Result>() {
166  @Override
167  public int compare(Result result1, Result result2) {
168  if (result1.getType() == SearchData.Type.DOMAIN) {
169  return 0;
170  }
171  ResultFile file1 = (ResultFile) result1;
172  ResultFile file2 = (ResultFile) result2;
173  String file1ParentPath;
174  try {
175  file1ParentPath = file1.getFirstInstance().getParent().getUniquePath();
176  } catch (TskCoreException ingored) {
177  file1ParentPath = file1.getFirstInstance().getParentPath();
178  }
179  String file2ParentPath;
180  try {
181  file2ParentPath = file2.getFirstInstance().getParent().getUniquePath();
182  } catch (TskCoreException ingored) {
183  file2ParentPath = file2.getFirstInstance().getParentPath();
184  }
185  return compareStrings(file1ParentPath.toLowerCase(), file2ParentPath.toLowerCase());
186  }
187  };
188  }
189 
197  private static Comparator<Result> getFrequencyComparator() {
198  return (Result result1, Result result2) -> Integer.compare(result1.getFrequency().getRanking(), result2.getFrequency().getRanking());
199  }
200 
207  private static Comparator<Result> getMIMETypeComparator() {
208  return (Result result1, Result result2) -> {
209  if (result1.getType() == SearchData.Type.DOMAIN) {
210  return 0;
211  }
212  return compareStrings(((ResultFile) result1).getFirstInstance().getMIMEType(), ((ResultFile) result2).getFirstInstance().getMIMEType());
213  };
214  }
215 
221  private static Comparator<Result> getFileSizeComparator() {
222  return (Result result1, Result result2) -> {
223  if (result1.getType() == SearchData.Type.DOMAIN) {
224  return 0;
225  }
226  return -1 * Long.compare(((ResultFile) result1).getFirstInstance().getSize(), ((ResultFile) result2).getFirstInstance().getSize()); // Sort large to small
227  };
228  }
229 
235  private static Comparator<Result> getFileNameComparator() {
236  return (Result result1, Result result2) -> {
237  if (result1.getType() == SearchData.Type.DOMAIN) {
238  return 0;
239  }
240  return compareStrings(((ResultFile) result1).getFirstInstance().getName().toLowerCase(), (((ResultFile) result2).getFirstInstance().getName().toLowerCase()));
241  };
242  }
243 
249  private static Comparator<Result> getDomainNameComparator() {
250  return (Result domain1, Result domain2) -> {
251  if (domain1.getType() != SearchData.Type.DOMAIN) {
252  return 0;
253  }
254 
255  ResultDomain first = (ResultDomain) domain1;
256  ResultDomain second = (ResultDomain) domain2;
257  return compareStrings(first.getDomain().toLowerCase(), second.getDomain().toLowerCase());
258  };
259  }
260 
266  private static Comparator<Result> getPageViewComparator() {
267  return (Result domain1, Result domain2) -> {
268  if (domain1.getType() != SearchData.Type.DOMAIN
269  || domain2.getType() != SearchData.Type.DOMAIN) {
270  return 0;
271  }
272 
273  ResultDomain first = (ResultDomain) domain1;
274  ResultDomain second = (ResultDomain) domain2;
275 
276  long firstPageViews = first.getTotalPageViews();
277  long secondPageViews = second.getTotalPageViews();
278  return Long.compare(secondPageViews, firstPageViews);
279  };
280  }
281 
286  private static Comparator<Result> getLastActivityDateTimeComparator() {
287  return (Result domain1, Result domain2) -> {
288  if (domain1.getType() != SearchData.Type.DOMAIN
289  || domain2.getType() != SearchData.Type.DOMAIN) {
290  return 0;
291  }
292  ResultDomain first = (ResultDomain) domain1;
293  ResultDomain second = (ResultDomain) domain2;
294 
295  long firstActivityEnd = first.getActivityEnd();
296  long secondActivityEnd = second.getActivityEnd();
297  return Long.compare(secondActivityEnd, firstActivityEnd);
298  };
299  }
300 
305  private static Comparator<Result> getWebDownloadsComparator() {
306  return (Result domain1, Result domain2) -> {
307  if (domain1.getType() != SearchData.Type.DOMAIN
308  || domain2.getType() != SearchData.Type.DOMAIN) {
309  return 0;
310  }
311  ResultDomain first = (ResultDomain) domain1;
312  ResultDomain second = (ResultDomain) domain2;
313 
314  long firstFilesDownloaded = first.getFilesDownloaded();
315  long secondFilesDownloaded = second.getFilesDownloaded();
316  return Long.compare(secondFilesDownloaded, firstFilesDownloaded);
317  };
318  }
319 
328  private static Comparator<Result> getDefaultComparator() {
329  return (Result result1, Result result2) -> {
330  // Compare file names and then object ID (to ensure a consistent sort)
331  if (result1.getType() == SearchData.Type.DOMAIN) {
332  return getFrequencyComparator().compare(result1, result2);
333  } else {
334  ResultFile file1 = (ResultFile) result1;
335  ResultFile file2 = (ResultFile) result2;
336  int result = getFileNameComparator().compare(file1, file2);
337  if (result == 0) {
338  return Long.compare(file1.getFirstInstance().getId(), file2.getFirstInstance().getId());
339  }
340  return result;
341  }
342 
343  };
344  }
345 
354  private static int compareStrings(String s1, String s2) {
355  String string1 = s1 == null ? "" : s1;
356  String string2 = s2 == null ? "" : s2;
357  return string1.compareTo(string2);
358 
359  }
360 
364  @NbBundle.Messages({
365  "FileSorter.SortingMethod.datasource.displayName=Data Source",
366  "FileSorter.SortingMethod.filename.displayName=File Name",
367  "FileSorter.SortingMethod.filesize.displayName=File Size",
368  "FileSorter.SortingMethod.filetype.displayName=File Type",
369  "FileSorter.SortingMethod.frequency.displayName=Central Repo Frequency",
370  "FileSorter.SortingMethod.keywordlist.displayName=Keyword List Names",
371  "FileSorter.SortingMethod.fullPath.displayName=Full Path",
372  "FileSorter.SortingMethod.domain.displayName=Domain Name",
373  "FileSorter.SortingMethod.pageViews.displayName=Page Views",
374  "FileSorter.SortingMethod.downloads.displayName=File Downloads",
375  "FileSorter.SortingMethod.activity.displayName=Last Activity Date"})
376  public enum SortingMethod {
377  BY_FILE_NAME(new ArrayList<>(),
378  Bundle.FileSorter_SortingMethod_filename_displayName()), // Sort alphabetically by file name
379  BY_DATA_SOURCE(new ArrayList<>(),
380  Bundle.FileSorter_SortingMethod_datasource_displayName()), // Sort in increasing order of data source ID
381  BY_FILE_SIZE(new ArrayList<>(),
382  Bundle.FileSorter_SortingMethod_filesize_displayName()), // Sort in decreasing order of size
383  BY_FILE_TYPE(Arrays.asList(new DiscoveryAttributes.FileTypeAttribute()),
384  Bundle.FileSorter_SortingMethod_filetype_displayName()), // Sort in order of file type (defined in FileType enum), with secondary sort on MIME type
385  BY_FREQUENCY(Arrays.asList(new DiscoveryAttributes.FrequencyAttribute()),
386  Bundle.FileSorter_SortingMethod_frequency_displayName()), // Sort by decreasing rarity in the central repository
387  BY_KEYWORD_LIST_NAMES(Arrays.asList(new DiscoveryAttributes.KeywordListAttribute()),
388  Bundle.FileSorter_SortingMethod_keywordlist_displayName()), // Sort alphabetically by list of keyword list names found
389  BY_FULL_PATH(new ArrayList<>(),
390  Bundle.FileSorter_SortingMethod_fullPath_displayName()), // Sort alphabetically by path
391  BY_DOMAIN_NAME(Arrays.asList(new DiscoveryAttributes.DomainCategoryAttribute(), new DiscoveryAttributes.PreviouslyNotableAttribute()), Bundle.FileSorter_SortingMethod_domain_displayName()),
392  BY_PAGE_VIEWS(Arrays.asList(new DiscoveryAttributes.DomainCategoryAttribute(), new DiscoveryAttributes.PreviouslyNotableAttribute()), Bundle.FileSorter_SortingMethod_pageViews_displayName()),
393  BY_DOWNLOADS(Arrays.asList(new DiscoveryAttributes.DomainCategoryAttribute(), new DiscoveryAttributes.PreviouslyNotableAttribute()), Bundle.FileSorter_SortingMethod_downloads_displayName()),
394  BY_LAST_ACTIVITY(Arrays.asList(new DiscoveryAttributes.DomainCategoryAttribute(), new DiscoveryAttributes.PreviouslyNotableAttribute()), Bundle.FileSorter_SortingMethod_activity_displayName());
395 
396  private final String displayName;
398 
406  SortingMethod(List<DiscoveryAttributes.AttributeType> attributes, String displayName) {
407  this.requiredAttributes = attributes;
408  this.displayName = displayName;
409  }
410 
411  @Override
412  public String toString() {
413  return displayName;
414  }
415 
422  return Collections.unmodifiableList(requiredAttributes);
423  }
424 
430  public static List<SortingMethod> getOptionsForOrderingFiles() {
431  return Arrays.asList(BY_FILE_SIZE, BY_FULL_PATH, BY_FILE_NAME, BY_DATA_SOURCE);
432  }
433 
439  public static List<SortingMethod> getOptionsForOrderingDomains() {
440  return Arrays.asList(BY_PAGE_VIEWS, BY_DOWNLOADS, BY_LAST_ACTIVITY, BY_DOMAIN_NAME);
441  }
442 
443  }
444 }
int compare(Result result1, Result result2)
final List< Comparator< Result > > comparators
SortingMethod(List< DiscoveryAttributes.AttributeType > attributes, String displayName)
static Comparator< Result > getLastActivityDateTimeComparator()
static Comparator< Result > getKeywordListNameComparator()
final List< DiscoveryAttributes.AttributeType > requiredAttributes
List< DiscoveryAttributes.AttributeType > getRequiredAttributes()
static Comparator< Result > getWebDownloadsComparator()

Copyright © 2012-2022 Basis Technology. Generated on: Tue Feb 6 2024
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.