19 package org.sleuthkit.autopsy.report.modules.datasourcesummaryexport;
 
   21 import java.util.ArrayList;
 
   22 import java.util.Arrays;
 
   23 import java.util.Collections;
 
   24 import java.util.List;
 
   25 import java.util.stream.Collectors;
 
   26 import java.util.stream.Stream;
 
   27 import org.apache.commons.lang3.StringUtils;
 
   28 import org.apache.commons.lang3.tuple.Pair;
 
   29 import org.openide.util.NbBundle.Messages;
 
   44     "ExportGeolocation_cityColumn_title=Closest City",
 
   45     "ExportGeolocation_countColumn_title=Count",
 
   46     "ExportGeolocation_unknownRow_title=Unknown",
 
   47     "ExportGeolocation_mostCommon_tabName=Most Common Cities",
 
   48     "ExportGeolocation_mostRecent_tabName=Most Recent Cities",})
 
   49 class ExportGeolocation {
 
   51     private final GeolocationSummary geoSummary;
 
   69         GeolocationData(List<Pair<String, Integer>> mostRecentData, List<Pair<String, Integer>> mostCommonData) {
 
   70             this.mostRecentData = mostRecentData;
 
   71             this.mostCommonData = mostCommonData;
 
   79         List<Pair<String, Integer>> getMostRecentData() {
 
   80             return mostRecentData;
 
   88         List<Pair<String, Integer>> getMostCommonData() {
 
   89             return mostCommonData;
 
   93     private static final int DAYS_COUNT = 30;
 
   94     private static final int MAX_COUNT = 10;
 
   97     private static final ColumnModel<Pair<String, Integer>, DefaultCellModel<?>> CITY_COL = 
new ColumnModel<>(
 
   98             Bundle.ExportGeolocation_cityColumn_title(),
 
   99             (pair) -> 
new DefaultCellModel<>(pair.getLeft()),
 
  104     private static final ColumnModel<Pair<String, Integer>, DefaultCellModel<?>> COUNT_COL = 
new ColumnModel<>(
 
  105             Bundle.ExportGeolocation_countColumn_title(),
 
  106             (pair) -> 
new DefaultCellModel<>(pair.getRight()),
 
  110     private static final List<ColumnModel<Pair<String, Integer>, DefaultCellModel<?>>> DEFAULT_TEMPLATE = Arrays.asList(
 
  115     ExportGeolocation() {
 
  116         geoSummary = 
new GeolocationSummary();
 
  126     private static String getCityName(CityRecord record) {
 
  127         if (record == null) {
 
  131         List<String> cityIdentifiers = Stream.of(record.getCityName(), record.getState(), record.getCountry())
 
  132                 .filter(StringUtils::isNotBlank)
 
  133                 .collect(Collectors.toList());
 
  135         if (cityIdentifiers.size() == 1) {
 
  136             return cityIdentifiers.get(0);
 
  137         } 
else if (cityIdentifiers.size() == 2) {
 
  138             return String.format(
"%s, %s", cityIdentifiers.get(0), cityIdentifiers.get(1));
 
  139         } 
else if (cityIdentifiers.size() >= 3) {
 
  140             return String.format(
"%s, %s; %s", cityIdentifiers.get(0), cityIdentifiers.get(1), cityIdentifiers.get(2));
 
  154     private static Pair<String, Integer> formatRecord(CityRecordCount cityCount) {
 
  155         if (cityCount == null) {
 
  159         String cityName = getCityName(cityCount.getCityRecord());
 
  160         int count = cityCount.getCount();
 
  161         return Pair.of(cityName, count);
 
  174     private static List<Pair<String, Integer>> formatList(CityCountsList countsList) {
 
  175         if (countsList == null) {
 
  176             return Collections.emptyList();
 
  179         Stream<CityRecordCount> countsStream = ((countsList.getCounts() == null)
 
  180                 ? 
new ArrayList<CityRecordCount>()
 
  181                 : countsList.getCounts()).stream();
 
  183         Stream<Pair<String, Integer>> pairStream = countsStream.map((r) -> formatRecord(r));
 
  185         Pair<String, Integer> unknownRecord = Pair.of(Bundle.ExportGeolocation_unknownRow_title(), countsList.getOtherCount());
 
  187         return Stream.concat(pairStream, Stream.of(unknownRecord))
 
  188                 .filter((p) -> p != null && p.getRight() != null && p.getRight() > 0)
 
  189                 .sorted((a, b) -> -Integer.compare(a.getRight(), b.getRight()))
 
  191                 .collect(Collectors.toList());
 
  202     private static GeolocationData convertToViewModel(CityData cityData) {
 
  203         if (cityData == null) {
 
  204             return new GeolocationData(Collections.emptyList(), Collections.emptyList());
 
  206             return new GeolocationData(formatList(cityData.getMostRecent()), formatList(cityData.getMostCommon()));
 
  210     List<ExcelExport.ExcelSheetExport> getExports(DataSource dataSource) {
 
  212         DataFetcher<DataSource, GeolocationData> geolocationFetcher = (ds) -> convertToViewModel(geoSummary.getCityCounts(ds, DAYS_COUNT, MAX_COUNT));
 
  214         GeolocationData model
 
  215                 = getFetchResult(geolocationFetcher, 
"Geolocation sheets", dataSource);
 
  217             return Collections.emptyList();
 
  220         return Arrays.asList(getTableExport(DEFAULT_TEMPLATE,
 
  221                 Bundle.ExportGeolocation_mostRecent_tabName(), model.getMostRecentData()),
 
  222                 getTableExport(DEFAULT_TEMPLATE,
 
  223                         Bundle.ExportGeolocation_mostCommon_tabName(), model.getMostCommonData())
 
final List< Pair< String, Integer > > mostCommonData
final List< Pair< String, Integer > > mostRecentData