19 package org.sleuthkit.autopsy.datasourcesummary.datamodel;
21 import java.io.IOException;
22 import java.util.ArrayList;
23 import java.util.Arrays;
24 import java.util.Collections;
25 import java.util.HashMap;
26 import java.util.List;
29 import java.util.concurrent.ArrayBlockingQueue;
30 import java.util.concurrent.BlockingQueue;
31 import java.util.stream.Collectors;
32 import java.util.stream.Stream;
33 import org.apache.commons.lang3.tuple.Pair;
41 import org.
sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
138 private final List<CityRecordCount>
counts;
150 this.counts = Collections.unmodifiableList(
new ArrayList<>(counts));
178 private final List<Set<MapWaypoint>>
tracks;
179 private final List<Set<MapWaypoint>>
areas;
190 private GeoResult(Set<MapWaypoint> mapWaypoints, List<Set<MapWaypoint>> tracks, List<Set<MapWaypoint>> areas) {
219 @SuppressWarnings(
"deprecation")
221 BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_BOOKMARK,
222 BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_LAST_KNOWN_LOCATION,
223 BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_ROUTE,
224 BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_SEARCH,
225 BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_TRACK,
226 BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_TRACKPOINT,
227 BlackboardArtifact.ARTIFACT_TYPE.TSK_METADATA_EXIF,
228 BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_AREA
233 .map(artifactType -> artifactType.getTypeID())
234 .collect(Collectors.toSet());
236 private static final Pair<Integer, Integer>
EMPTY_COUNT = Pair.of(0, 0);
301 if (minTime != null && time != null && time >= minTime) {
319 private static Pair<Integer, Integer>
getCounts(List<Long> points, Long minTime) {
320 if (points == null) {
324 return points.stream().reduce(
326 (total, time) -> Pair.of(total.getLeft() + 1, total.getRight() + (
greaterThanOrEqual(minTime, time) ? 1 : 0)),
327 (pair1, pair2) -> Pair.of(pair1.getLeft() + pair2.getLeft(), pair1.getRight() + pair2.getRight()));
348 return Pair.of(city, time);
364 if (points == null) {
365 return Stream.empty();
368 Map<CityRecord, Long> timeMapping =
new HashMap<>();
376 Long prevTime = timeMapping.get(city);
377 Long curTime = pair.getRight();
378 if (prevTime == null || (curTime != null && curTime > prevTime)) {
379 timeMapping.put(city, curTime);
383 return timeMapping.entrySet().stream()
384 .map(e -> Pair.of(e.getKey(), e.getValue()));
401 if (geoResult == null) {
402 return Stream.empty();
405 List<Set<MapWaypoint>> areas = (geoResult.
getAreas() == null) ? Collections.emptyList() : geoResult.
getAreas();
406 List<Set<MapWaypoint>> tracks = (geoResult.
getTracks() == null) ? Collections.emptyList() : geoResult.
getTracks();
408 Stream<Pair<CityRecord, Long>> reducedGroupings = Stream.of(areas, tracks)
409 .flatMap((groupingList) -> groupingList.stream())
412 final Set<MapWaypoint> allTracksAndAreas = Stream.of(areas, tracks)
413 .flatMap((groupingList) -> groupingList.stream())
414 .flatMap((group) -> group.stream())
415 .collect(Collectors.toSet());
418 Stream<Pair<CityRecord, Long>> citiesForPoints = pointSet.stream()
421 .filter(pt -> !allTracksAndAreas.contains(pt))
424 return Stream.concat(reducedGroupings, citiesForPoints);
446 List<Pair<CityRecord, Long>> dataSourcePoints =
processGeoResult(geoResult, closestCityMapper)
447 .collect(Collectors.toList());
449 Map<CityRecord, List<Long>> allCityPoints =
new HashMap<>();
450 List<Long> others =
new ArrayList<>();
451 Long mostRecent = null;
453 for (Pair<CityRecord, Long> pt : dataSourcePoints) {
458 Long curTime = pt.getRight();
459 if (curTime != null && (mostRecent == null || curTime > mostRecent)) {
460 mostRecent = curTime;
467 List<Long> cityPoints = allCityPoints.get(city);
468 if (cityPoints == null) {
469 cityPoints =
new ArrayList<>();
470 allCityPoints.put(city, cityPoints);
473 cityPoints.add(curTime);
477 final Long mostRecentMinTime = (mostRecent == null) ? null : mostRecent - daysCount *
DAY_SECS;
480 Map<CityRecord, Pair<Integer, Integer>> allCityCounts = allCityPoints.entrySet().stream()
481 .collect(Collectors.toMap((e) -> e.getKey(), (e) ->
getCounts(e.getValue(), mostRecentMinTime)));
483 List<CityRecordCount> mostCommonCounts = allCityCounts.entrySet().stream()
485 .sorted((a, b) -> -Integer.compare(a.getCount(), b.getCount()))
487 .collect(Collectors.toList());
489 List<CityRecordCount> mostRecentCounts = allCityCounts.entrySet().stream()
491 .sorted((a, b) -> -Integer.compare(a.getCount(), b.getCount()))
493 .collect(Collectors.toList());
495 Pair<Integer, Integer> otherCounts =
getCounts(others, mostRecentMinTime);
496 int otherMostCommonCount = otherCounts.getLeft();
497 int otherMostRecentCount = otherCounts.getRight();
527 public void handleFilteredWaypointSet(Set<MapWaypoint> mapWaypoints, List<Set<MapWaypoint>> tracks, List<Set<MapWaypoint>> areas,
boolean wasEntirelySuccessful) {
530 asyncResult.put(
new GeoResult(mapWaypoints, tracks, areas));
531 }
catch (InterruptedException ignored) {
548 throws SleuthkitCaseProviderException, GeoLocationDataException, InterruptedException {
552 final BlockingQueue<GeoResult> asyncResult =
new ArrayBlockingQueue<>(1);
557 Arrays.asList(dataSource),
564 return asyncResult.take();
final List< Set< MapWaypoint > > tracks
Pair< CityRecord, Long > getClosestWithTime(ClosestCityMapper cityMapper, MapWaypoint pt)
List< Set< MapWaypoint > > getTracks()
SleuthkitCaseProvider DEFAULT
Stream< Pair< CityRecord, Long > > processGeoResult(GeoResult geoResult, ClosestCityMapper cityMapper)
CityCountsList getMostRecent()
static final Set< Integer > GPS_ARTIFACT_TYPE_IDS
static boolean greaterThanOrEqual(Long minTime, Long time)
final Set< MapWaypoint > mapWaypoints
List< Set< MapWaypoint > > getAreas()
static final long DAY_SECS
final CityCountsList mostRecent
CityData getCityCounts(DataSource dataSource, int daysCount, int maxCount)
GeoResult getGeoResult(DataSource dataSource)
static final Pair< Integer, Integer > EMPTY_COUNT
static Set< Integer > getArtifactTypeIdsForRefresh()
static List< ARTIFACT_TYPE > getGeoTypes()
Stream< Pair< CityRecord, Long > > reduceGrouping(Set< MapWaypoint > points, ClosestCityMapper cityMapper)
final BlockingQueue< GeoResult > asyncResult
final CityCountsList mostCommon
final CityRecord cityRecord
static List< Waypoint > getAllWaypoints(SleuthkitCase skCase)
final List< Set< MapWaypoint > > areas
GeolocationSummary(SupplierWithException< ClosestCityMapper, IOException > cityMapper, SleuthkitCaseProvider provider)
static Pair< Integer, Integer > getCounts(List< Long > points, Long minTime)
final List< CityRecordCount > counts
static final List< ARTIFACT_TYPE > GPS_ARTIFACT_TYPES
final SupplierWithException< ClosestCityMapper, IOException > cityMapper
GeoResult(Set< MapWaypoint > mapWaypoints, List< Set< MapWaypoint >> tracks, List< Set< MapWaypoint >> areas)
final SleuthkitCaseProvider provider
final Long mostRecentSeen
CityRecord getCityRecord()
List< CityRecordCount > getCounts()
CityCountsList getMostCommon()
Set< MapWaypoint > getMapWaypoints()
void handleFilteredWaypointSet(Set< MapWaypoint > mapWaypoints, List< Set< MapWaypoint >> tracks, List< Set< MapWaypoint >> areas, boolean wasEntirelySuccessful)