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;
42 import org.
sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
139 private final List<CityRecordCount>
counts;
151 this.counts = Collections.unmodifiableList(
new ArrayList<>(counts));
179 private final List<Set<MapWaypoint>>
tracks;
180 private final List<Set<MapWaypoint>>
areas;
191 private GeoResult(Set<MapWaypoint> mapWaypoints, List<Set<MapWaypoint>> tracks, List<Set<MapWaypoint>> areas) {
220 @SuppressWarnings(
"deprecation")
222 BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_BOOKMARK,
223 BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_LAST_KNOWN_LOCATION,
224 BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_ROUTE,
225 BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_SEARCH,
226 BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_TRACK,
227 BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_TRACKPOINT,
228 BlackboardArtifact.ARTIFACT_TYPE.TSK_METADATA_EXIF,
229 BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_AREA
234 .map(artifactType -> artifactType.getTypeID())
235 .collect(Collectors.toSet());
237 private static final Pair<Integer, Integer>
EMPTY_COUNT = Pair.of(0, 0);
301 if (minTime != null && time != null && time >= minTime) {
318 private Pair<Integer, Integer>
getCounts(List<Long> points, Long minTime) {
319 if (points == null) {
323 return points.stream().reduce(
325 (total, time) -> Pair.of(total.getLeft() + 1, total.getRight() + (
greaterThanOrEqual(minTime, time) ? 1 : 0)),
326 (pair1, pair2) -> Pair.of(pair1.getLeft() + pair2.getLeft(), pair1.getRight() + pair2.getRight()));
346 return Pair.of(city, time);
360 if (points == null) {
361 return Stream.empty();
364 Map<CityRecord, Long> timeMapping =
new HashMap<>();
372 Long prevTime = timeMapping.get(city);
373 Long curTime = pair.getRight();
374 if (prevTime == null || (curTime != null && curTime > prevTime)) {
375 timeMapping.put(city, curTime);
379 return timeMapping.entrySet().stream()
380 .map(e -> Pair.of(e.getKey(), e.getValue()));
395 if (geoResult == null) {
396 return Stream.empty();
399 List<Set<MapWaypoint>> areas = (geoResult.
getAreas() == null) ? Collections.emptyList() : geoResult.
getAreas();
400 List<Set<MapWaypoint>> tracks = (geoResult.
getTracks() == null) ? Collections.emptyList() : geoResult.
getTracks();
402 Stream<Pair<CityRecord, Long>> reducedGroupings = Stream.of(areas, tracks)
403 .flatMap((groupingList) -> groupingList.stream())
406 final Set<MapWaypoint> allTracksAndAreas = Stream.of(areas, tracks)
407 .flatMap((groupingList) -> groupingList.stream())
408 .flatMap((group) -> group.stream())
409 .collect(Collectors.toSet());
412 Stream<Pair<CityRecord, Long>> citiesForPoints = pointSet.stream()
415 .filter(pt -> !allTracksAndAreas.contains(pt))
418 return Stream.concat(reducedGroupings, citiesForPoints);
440 List<Pair<CityRecord, Long>> dataSourcePoints =
processGeoResult(geoResult, closestCityMapper)
441 .collect(Collectors.toList());
443 Map<CityRecord, List<Long>> allCityPoints =
new HashMap<>();
444 List<Long> others =
new ArrayList<>();
445 Long mostRecent = null;
447 for (Pair<CityRecord, Long> pt : dataSourcePoints) {
452 Long curTime = pt.getRight();
453 if (curTime != null && (mostRecent == null || curTime > mostRecent)) {
454 mostRecent = curTime;
461 List<Long> cityPoints = allCityPoints.get(city);
462 if (cityPoints == null) {
463 cityPoints =
new ArrayList<>();
464 allCityPoints.put(city, cityPoints);
467 cityPoints.add(curTime);
471 final Long mostRecentMinTime = (mostRecent == null) ? null : mostRecent - daysCount *
DAY_SECS;
474 Map<CityRecord, Pair<Integer, Integer>> allCityCounts = allCityPoints.entrySet().stream()
475 .collect(Collectors.toMap((e) -> e.getKey(), (e) ->
getCounts(e.getValue(), mostRecentMinTime)));
477 List<CityRecordCount> mostCommonCounts = allCityCounts.entrySet().stream()
479 .sorted((a, b) -> -Integer.compare(a.getCount(), b.getCount()))
481 .collect(Collectors.toList());
483 List<CityRecordCount> mostRecentCounts = allCityCounts.entrySet().stream()
485 .sorted((a, b) -> -Integer.compare(a.getCount(), b.getCount()))
487 .collect(Collectors.toList());
489 Pair<Integer, Integer> otherCounts =
getCounts(others, mostRecentMinTime);
490 int otherMostCommonCount = otherCounts.getLeft();
491 int otherMostRecentCount = otherCounts.getRight();
520 public void handleFilteredWaypointSet(Set<MapWaypoint> mapWaypoints, List<Set<MapWaypoint>> tracks, List<Set<MapWaypoint>> areas,
boolean wasEntirelySuccessful) {
523 asyncResult.put(
new GeoResult(mapWaypoints, tracks, areas));
524 }
catch (InterruptedException ignored) {
540 throws SleuthkitCaseProviderException, GeoLocationDataException, InterruptedException {
544 final BlockingQueue<GeoResult> asyncResult =
new ArrayBlockingQueue<>(1);
549 Arrays.asList(dataSource),
556 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()
PointFetcher(BlockingQueue< GeoResult > asyncResult, GeoFilter filters)
static final Set< Integer > GPS_ARTIFACT_TYPE_IDS
final Set< MapWaypoint > mapWaypoints
List< Set< MapWaypoint > > getAreas()
static final long DAY_SECS
Set< Integer > getArtifactTypeIdsForRefresh()
final CityCountsList mostRecent
CityData getCityCounts(DataSource dataSource, int daysCount, int maxCount)
GeoResult getGeoResult(DataSource dataSource)
static final Pair< Integer, Integer > EMPTY_COUNT
Stream< Pair< CityRecord, Long > > reduceGrouping(Set< MapWaypoint > points, ClosestCityMapper cityMapper)
final BlockingQueue< GeoResult > asyncResult
final CityCountsList mostCommon
boolean greaterThanOrEqual(Long minTime, Long time)
final CityRecord cityRecord
static List< Waypoint > getAllWaypoints(SleuthkitCase skCase)
Pair< Integer, Integer > getCounts(List< Long > points, Long minTime)
final List< Set< MapWaypoint > > areas
GeolocationSummary(SupplierWithException< ClosestCityMapper, IOException > cityMapper, SleuthkitCaseProvider provider)
List< ARTIFACT_TYPE > getGeoTypes()
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)