Merge pull request #5469 from kellykelly3/5797-highlite-selected-waypoints

5797 highlite selected waypoints
This commit is contained in:
Richard Cordovano 2019-12-06 11:04:17 -05:00 committed by GitHub
commit 4222a004e9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 636 additions and 255 deletions

View File

@ -4,7 +4,6 @@ CTL_GeolocationTopComponent=Geolocation
RefreshPanel.refreshLabel.text=The geolocation data has been updated, the visualization may be out of date.
RefreshPanel.refreshButton.text=Refresh View
RefreshPanel.closeButton.text=
MapPanel.cordLabel.text=
WaypointDetailPanel.closeButton.text=
WaypointDetailPanel.imageLabel.text=
GeoFilterPanel.waypointSettings.border.title=
@ -30,3 +29,5 @@ GeolocationSettingsPanel.osmZipFileField.text=
GeolocationSettingsPanel.osmZipFileBrowseButton.text=Browse
GeolocationSettingsPanel.serverTestButton.text=Test
GeolocationSettingsPanel.osmZipButton.actionCommand=OpenStreeMap tile ZIP file
GeolocationTopComponent.reportButton.text=KML Report
GeolocationTopComponent.coordLabel.text=jLabel1

View File

@ -11,6 +11,9 @@ GeolocationSettingsPanel_osm_server_test_success_message=The provide OSM tile se
GeolocationSettingsPanel_osm_server_test_success_message_title=Success
GeolocationTC_connection_failure_message=Failed to connect to map title source.\nPlease review map source in Options dialog.
GeolocationTC_connection_failure_message_title=Connection Failure
GeolocationTC_empty_waypoint_message=Unable to generate KML report due to a lack of waypoints.\nPlease make sure there are waypoints visible before generating the KML report
GeolocationTC_KML_report_title=KML Report
GeolocationTC_report_progress_title=KML Report Progress
GeoTopComponent_filer_data_invalid_msg=Unable to run waypoint filter.\nPlease select one or more data sources.
GeoTopComponent_filer_data_invalid_Title=Filter Failure
GeoTopComponent_filter_exception_msg=Exception occured during waypoint filtering.
@ -28,7 +31,6 @@ OpenGeolocationAction_name=Geolocation
RefreshPanel.refreshLabel.text=The geolocation data has been updated, the visualization may be out of date.
RefreshPanel.refreshButton.text=Refresh View
RefreshPanel.closeButton.text=
MapPanel.cordLabel.text=
WaypointDetailPanel.closeButton.text=
WaypointDetailPanel.imageLabel.text=
GeoFilterPanel.waypointSettings.border.title=
@ -54,4 +56,6 @@ GeolocationSettingsPanel.osmZipFileField.text=
GeolocationSettingsPanel.osmZipFileBrowseButton.text=Browse
GeolocationSettingsPanel.serverTestButton.text=Test
GeolocationSettingsPanel.osmZipButton.actionCommand=OpenStreeMap tile ZIP file
GeolocationTopComponent.reportButton.text=KML Report
GeolocationTopComponent.coordLabel.text=jLabel1
WaypointExtractAction_label=Extract Files(s)

View File

@ -16,6 +16,63 @@
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout"/>
<SubComponents>
<Container class="org.sleuthkit.autopsy.geolocation.HidingPane" name="filterPane">
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout" value="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout$BorderConstraintsDescription">
<BorderConstraints direction="West"/>
</Constraint>
</Constraints>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout"/>
</Container>
<Container class="javax.swing.JPanel" name="statusBar">
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout" value="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout$BorderConstraintsDescription">
<BorderConstraints direction="South"/>
</Constraint>
</Constraints>
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
<SubComponents>
<Component class="javax.swing.JButton" name="reportButton">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/geolocation/Bundle.properties" key="GeolocationTopComponent.reportButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="reportButtonActionPerformed"/>
</Events>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="2" gridY="0" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="5" insetsLeft="5" insetsBottom="5" insetsRight="5" anchor="17" weightX="0.0" weightY="0.0"/>
</Constraint>
</Constraints>
</Component>
<Component class="javax.swing.JProgressBar" name="progressBar">
<Properties>
<Property name="indeterminate" type="boolean" value="true"/>
</Properties>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="1" gridY="0" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="17" weightX="0.0" weightY="0.0"/>
</Constraint>
</Constraints>
</Component>
<Component class="javax.swing.JLabel" name="coordLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/geolocation/Bundle.properties" key="GeolocationTopComponent.coordLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="0" gridY="0" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="5" insetsLeft="5" insetsBottom="5" insetsRight="0" anchor="17" weightX="1.0" weightY="0.0"/>
</Constraint>
</Constraints>
</Component>
</SubComponents>
</Container>
<Container class="org.sleuthkit.autopsy.geolocation.MapPanel" name="mapPanel">
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout" value="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout$BorderConstraintsDescription">
@ -24,17 +81,6 @@
</Constraints>
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout"/>
<SubComponents>
<Container class="org.sleuthkit.autopsy.geolocation.HidingPane" name="filterPane">
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout" value="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout$BorderConstraintsDescription">
<BorderConstraints direction="Before"/>
</Constraint>
</Constraints>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout"/>
</Container>
</SubComponents>
</Container>
</SubComponents>
</Form>

View File

@ -21,14 +21,22 @@ package org.sleuthkit.autopsy.geolocation;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.EnumSet;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import java.util.logging.Level;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;
import org.openide.filesystems.FileUtil;
import org.openide.util.NbBundle.Messages;
import org.openide.windows.RetainLocation;
import org.openide.windows.TopComponent;
@ -46,6 +54,8 @@ import org.sleuthkit.autopsy.geolocation.datamodel.WaypointBuilder.WaypointFilte
import org.sleuthkit.autopsy.ingest.IngestManager;
import static org.sleuthkit.autopsy.ingest.IngestManager.IngestModuleEvent.DATA_ADDED;
import org.sleuthkit.autopsy.ingest.ModuleDataEvent;
import org.sleuthkit.autopsy.report.ReportProgressPanel;
import org.sleuthkit.autopsy.report.modules.kml.KMLReport;
import org.sleuthkit.datamodel.BlackboardArtifact;
/**
@ -70,6 +80,11 @@ public final class GeolocationTopComponent extends TopComponent {
final RefreshPanel refreshPanel = new RefreshPanel();
private static final String REPORT_PATH_FMT_STR = "%s" + File.separator + "%s %s %s" + File.separator;
// This is the hardcoded report name from KMLReport.java
private static final String REPORT_KML = "ReportKML.kml";
@Messages({
"GLTopComponent_name=Geolocation",
"GLTopComponent_initilzation_error=An error occurred during waypoint initilization. Geolocation data maybe incomplete."
@ -134,6 +149,20 @@ public final class GeolocationTopComponent extends TopComponent {
updateWaypoints();
}
});
mapPanel.addPropertyChangeListener(MapPanel.CURRENT_MOUSE_GEOPOSITION, new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
String label = "";
Object newValue = evt.getNewValue();
if (newValue != null) {
label = newValue.toString();
}
coordLabel.setText(label);
}
});
}
@Override
@ -223,13 +252,51 @@ public final class GeolocationTopComponent extends TopComponent {
return;
}
mapPanel.setWaypointLoading(true);
setWaypointLoading(true);
geoFilterPanel.setEnabled(false);
Thread thread = new Thread(new WaypointRunner(filters));
thread.start();
}
/**
* Show or hide the waypoint loading progress bar.
*
* @param loading
*/
void setWaypointLoading(boolean loading) {
progressBar.setEnabled(true);
progressBar.setVisible(loading);
progressBar.setString("Loading Waypoints");
}
/**
* Create the directory path for the KML report.
*
* This is a modified version of the similar private function from
* KMLReport.
*
* @return Path for the report
*
* @throws IOException
*/
private static String createReportDirectory() throws IOException {
Case currentCase = Case.getCurrentCase();
// Create the root reports directory path of the form: <CASE DIRECTORY>/Reports/<Case fileName> <Timestamp>/
DateFormat dateFormat = new SimpleDateFormat("MM-dd-yyyy-HH-mm-ss", Locale.US);
Date date = new Date();
String dateNoTime = dateFormat.format(date);
String reportPath = String.format(REPORT_PATH_FMT_STR, currentCase.getReportDirectory(), currentCase.getDisplayName(), "Goggle Earth KML", dateNoTime);
// Create the root reports directory.
try {
FileUtil.createFolder(new File(reportPath));
} catch (IOException ex) {
throw new IOException("Failed to make report folder, unable to generate reports.", ex);
}
return reportPath;
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
@ -238,21 +305,86 @@ public final class GeolocationTopComponent extends TopComponent {
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
java.awt.GridBagConstraints gridBagConstraints;
mapPanel = new org.sleuthkit.autopsy.geolocation.MapPanel();
filterPane = new org.sleuthkit.autopsy.geolocation.HidingPane();
statusBar = new javax.swing.JPanel();
reportButton = new javax.swing.JButton();
progressBar = new javax.swing.JProgressBar();
coordLabel = new javax.swing.JLabel();
mapPanel = new org.sleuthkit.autopsy.geolocation.MapPanel();
setLayout(new java.awt.BorderLayout());
add(filterPane, java.awt.BorderLayout.WEST);
mapPanel.add(filterPane, java.awt.BorderLayout.LINE_START);
statusBar.setLayout(new java.awt.GridBagLayout());
org.openide.awt.Mnemonics.setLocalizedText(reportButton, org.openide.util.NbBundle.getMessage(GeolocationTopComponent.class, "GeolocationTopComponent.reportButton.text")); // NOI18N
reportButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
reportButtonActionPerformed(evt);
}
});
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 2;
gridBagConstraints.gridy = 0;
gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
statusBar.add(reportButton, gridBagConstraints);
progressBar.setIndeterminate(true);
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 1;
gridBagConstraints.gridy = 0;
gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
statusBar.add(progressBar, gridBagConstraints);
org.openide.awt.Mnemonics.setLocalizedText(coordLabel, org.openide.util.NbBundle.getMessage(GeolocationTopComponent.class, "GeolocationTopComponent.coordLabel.text")); // NOI18N
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 0;
gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
gridBagConstraints.weightx = 1.0;
gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 0);
statusBar.add(coordLabel, gridBagConstraints);
add(statusBar, java.awt.BorderLayout.SOUTH);
add(mapPanel, java.awt.BorderLayout.CENTER);
}// </editor-fold>//GEN-END:initComponents
@Messages({
"GeolocationTC_empty_waypoint_message=Unable to generate KML report due to a lack of waypoints.\nPlease make sure there are waypoints visible before generating the KML report",
"GeolocationTC_KML_report_title=KML Report",
"GeolocationTC_report_progress_title=KML Report Progress"
})
private void reportButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_reportButtonActionPerformed
List<MapWaypoint> visiblePoints = mapPanel.getVisibleWaypoints();
if (visiblePoints.isEmpty()) {
JOptionPane.showConfirmDialog(this, Bundle.GeolocationTC_empty_waypoint_message(), Bundle.GeolocationTC_KML_report_title(), JOptionPane.OK_OPTION, JOptionPane.INFORMATION_MESSAGE);
return;
}
try {
ReportProgressPanel progressPanel = new ReportProgressPanel();
String reportBaseDir = createReportDirectory();
progressPanel.setLabels(REPORT_KML, reportBaseDir);
KMLReport.getDefault().generateReport(reportBaseDir, progressPanel, MapWaypoint.getDataModelWaypoints(visiblePoints));
JOptionPane.showConfirmDialog(this, progressPanel, Bundle.GeolocationTC_report_progress_title(), JOptionPane.CLOSED_OPTION, JOptionPane.PLAIN_MESSAGE);
} catch (IOException ex) {
logger.log(Level.WARNING, "Unable to create KML report", ex);
}
}//GEN-LAST:event_reportButtonActionPerformed
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JLabel coordLabel;
private org.sleuthkit.autopsy.geolocation.HidingPane filterPane;
private org.sleuthkit.autopsy.geolocation.MapPanel mapPanel;
private javax.swing.JProgressBar progressBar;
private javax.swing.JButton reportButton;
private javax.swing.JPanel statusBar;
// End of variables declaration//GEN-END:variables
/**
@ -321,6 +453,7 @@ public final class GeolocationTopComponent extends TopComponent {
return;
}
mapPanel.setWaypoints(MapWaypoint.getWaypoints(waypoints));
setWaypointLoading(false);
geoFilterPanel.setEnabled(true);
}
});

View File

@ -91,39 +91,5 @@
</Container>
</SubComponents>
</Container>
<Container class="javax.swing.JPanel" name="infoPanel">
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout" value="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout$BorderConstraintsDescription">
<BorderConstraints direction="South"/>
</Constraint>
</Constraints>
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
<SubComponents>
<Component class="javax.swing.JLabel" name="cordLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/geolocation/Bundle.properties" key="MapPanel.cordLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="0" gridY="0" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="5" insetsBottom="0" insetsRight="5" anchor="18" weightX="1.0" weightY="0.0"/>
</Constraint>
</Constraints>
</Component>
<Component class="javax.swing.JProgressBar" name="progressBar">
<Properties>
<Property name="indeterminate" type="boolean" value="true"/>
<Property name="stringPainted" type="boolean" value="true"/>
</Properties>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="1" gridY="0" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="12" weightX="0.0" weightY="0.0"/>
</Constraint>
</Constraints>
</Component>
</SubComponents>
</Container>
</SubComponents>
</Form>

View File

@ -19,6 +19,7 @@
package org.sleuthkit.autopsy.geolocation;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
@ -27,9 +28,12 @@ import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.MouseEvent;
import java.awt.geom.Point2D;
import java.awt.image.BufferedImage;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
@ -46,6 +50,7 @@ import javax.swing.Popup;
import javax.swing.PopupFactory;
import javax.swing.Timer;
import javax.swing.event.MouseInputListener;
import org.jxmapviewer.JXMapViewer;
import org.jxmapviewer.OSMTileFactoryInfo;
import org.jxmapviewer.VirtualEarthTileFactoryInfo;
import org.jxmapviewer.input.CenterMapListener;
@ -57,6 +62,7 @@ import org.jxmapviewer.viewer.TileFactory;
import org.jxmapviewer.viewer.TileFactoryInfo;
import org.jxmapviewer.viewer.Waypoint;
import org.jxmapviewer.viewer.WaypointPainter;
import org.jxmapviewer.viewer.WaypointRenderer;
import org.jxmapviewer.viewer.util.GeoUtil;
import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.core.UserPreferences;
@ -64,12 +70,15 @@ import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
import org.sleuthkit.autopsy.geolocation.datamodel.GeoLocationDataException;
import org.sleuthkit.datamodel.TskCoreException;
import javax.imageio.ImageIO;
import org.jxmapviewer.viewer.DefaultWaypointRenderer;
/**
* The map panel. This panel contains the jxmapviewer MapViewer
*/
final public class MapPanel extends javax.swing.JPanel {
static final String CURRENT_MOUSE_GEOPOSITION = "CURRENT_MOUSE_GEOPOSITION";
private static final Logger logger = Logger.getLogger(MapPanel.class.getName());
private static final long serialVersionUID = 1L;
@ -130,6 +139,27 @@ final public class MapPanel extends javax.swing.JPanel {
});
}
/**
* Get a list of the waypoints that are currently visible in the viewport.
*
* @return A list of waypoints or empty list if none were found.
*/
List<MapWaypoint> getVisibleWaypoints() {
Rectangle viewport = mapViewer.getViewportBounds();
List<MapWaypoint> waypoints = new ArrayList<>();
Iterator<MapWaypoint> iterator = waypointTree.iterator();
while (iterator.hasNext()) {
MapWaypoint waypoint = iterator.next();
if (viewport.contains(mapViewer.getTileFactory().geoToPixel(waypoint.getPosition(), mapViewer.getZoom()))) {
waypoints.add(waypoint);
}
}
return waypoints;
}
/**
* Initialize the map.
*/
@ -160,7 +190,7 @@ final public class MapPanel extends javax.swing.JPanel {
setZoom(tileFactory.getInfo().getMaximumZoomLevel() - 1);
mapViewer.setCenterPosition(new GeoPosition(0,0));
mapViewer.setCenterPosition(new GeoPosition(0, 0));
// Basic painters for the way points.
WaypointPainter<Waypoint> waypointPainter = new WaypointPainter<Waypoint>() {
@ -177,18 +207,14 @@ final public class MapPanel extends javax.swing.JPanel {
}
};
mapViewer.setOverlayPainter(waypointPainter);
try {
waypointPainter.setRenderer(new MapWaypointRenderer());
} catch (IOException ex) {
logger.log(Level.WARNING, "Failed to load waypoint image resource, using DefaultWaypointRenderer", ex);
waypointPainter.setRenderer(new DefaultWaypointRenderer());
}
/**
* Show or hide the waypoint loading progress bar.
*
* @param loading
*/
void setWaypointLoading(boolean loading) {
progressBar.setEnabled(true);
progressBar.setVisible(loading);
progressBar.setString("Loading Waypoints");
mapViewer.setOverlayPainter(waypointPainter);
}
/**
@ -277,7 +303,6 @@ final public class MapPanel extends javax.swing.JPanel {
}
mapViewer.repaint();
setWaypointLoading(false);
}
/**
@ -316,6 +341,7 @@ final public class MapPanel extends javax.swing.JPanel {
if(currentPopup != null) {
showDetailsPopup();
}
mapViewer.repaint();
}
} catch (TskCoreException ex) {
logger.log(Level.WARNING, "Failed to show popup for waypoint", ex);
@ -373,6 +399,8 @@ final public class MapPanel extends javax.swing.JPanel {
currentPopup = popupFactory.getPopup(this, detailPane, popupLocation.x, popupLocation.y);
currentPopup.show();
mapViewer.repaint();
}
}
@ -499,9 +527,6 @@ final public class MapPanel extends javax.swing.JPanel {
mapViewer = new org.jxmapviewer.JXMapViewer();
zoomPanel = new javax.swing.JPanel();
zoomSlider = new javax.swing.JSlider();
infoPanel = new javax.swing.JPanel();
cordLabel = new javax.swing.JLabel();
progressBar = new javax.swing.JProgressBar();
setFocusable(false);
setLayout(new java.awt.BorderLayout());
@ -568,27 +593,6 @@ final public class MapPanel extends javax.swing.JPanel {
mapViewer.add(zoomPanel, gridBagConstraints);
add(mapViewer, java.awt.BorderLayout.CENTER);
infoPanel.setLayout(new java.awt.GridBagLayout());
org.openide.awt.Mnemonics.setLocalizedText(cordLabel, org.openide.util.NbBundle.getMessage(MapPanel.class, "MapPanel.cordLabel.text")); // NOI18N
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 0;
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
gridBagConstraints.weightx = 1.0;
gridBagConstraints.insets = new java.awt.Insets(0, 5, 0, 5);
infoPanel.add(cordLabel, gridBagConstraints);
progressBar.setIndeterminate(true);
progressBar.setStringPainted(true);
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 1;
gridBagConstraints.gridy = 0;
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHEAST;
infoPanel.add(progressBar, gridBagConstraints);
add(infoPanel, java.awt.BorderLayout.SOUTH);
}// </editor-fold>//GEN-END:initComponents
private void zoomSliderStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_zoomSliderStateChanged
@ -611,7 +615,7 @@ final public class MapPanel extends javax.swing.JPanel {
private void mapViewerMouseMoved(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_mapViewerMouseMoved
GeoPosition geopos = mapViewer.getTileFactory().pixelToGeo(evt.getPoint(), mapViewer.getZoom());
cordLabel.setText(geopos.toString());
firePropertyChange(CURRENT_MOUSE_GEOPOSITION, null, geopos);
}//GEN-LAST:event_mapViewerMouseMoved
private void mapViewerMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_mapViewerMouseClicked
@ -623,11 +627,39 @@ final public class MapPanel extends javax.swing.JPanel {
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JLabel cordLabel;
private javax.swing.JPanel infoPanel;
private org.jxmapviewer.JXMapViewer mapViewer;
private javax.swing.JProgressBar progressBar;
private javax.swing.JPanel zoomPanel;
private javax.swing.JSlider zoomSlider;
// End of variables declaration//GEN-END:variables
/**
* Renderer for the map waypoints.
*/
private class MapWaypointRenderer implements WaypointRenderer<Waypoint> {
private final BufferedImage defaultWaypointImage;
private final BufferedImage selectedWaypointImage;
/**
* Construct a WaypointRenederer
*
* @throws IOException
*/
MapWaypointRenderer() throws IOException {
defaultWaypointImage = ImageIO.read(getClass().getResource("/org/sleuthkit/autopsy/images/waypoint_teal.png"));
selectedWaypointImage = ImageIO.read(getClass().getResource("/org/sleuthkit/autopsy/images/waypoint_yellow.png"));
}
@Override
public void paintWaypoint(Graphics2D gd, JXMapViewer jxmv, Waypoint waypoint) {
Point2D point = jxmv.getTileFactory().geoToPixel(waypoint.getPosition(), jxmv.getZoom());
int x = (int)point.getX();
int y = (int)point.getY();
BufferedImage image = (waypoint == currentlySelectedWaypoint ? selectedWaypointImage: defaultWaypointImage);
(gd.create()).drawImage(image, x -image.getWidth() / 2, y -image.getHeight(), null);
}
}
}

View File

@ -102,8 +102,8 @@ final class MapWaypoint extends KdTree.XYZPoint implements org.jxmapviewer.viewe
*
* @param dmWaypoints
*
* @return List of MapWaypoint objects. List will be empty if dmWaypoints was
* empty or null.
* @return List of MapWaypoint objects. List will be empty if dmWaypoints
* was empty or null.
*/
static List<MapWaypoint> getWaypoints(List<Waypoint> dmWaypoints) {
List<MapWaypoint> mapPoints = new ArrayList<>();
@ -118,6 +118,27 @@ final class MapWaypoint extends KdTree.XYZPoint implements org.jxmapviewer.viewe
return mapPoints;
}
/**
* Helper function to get a list of data model waypoints from a list of
* MapWaypoints.
*
* @param mapWaypoints
*
* @return A list of Waypoint objects, or empty list if mapWaypoints was
* null or empty.
*/
static List<Waypoint> getDataModelWaypoints(List<MapWaypoint> mapWaypoints) {
List<Waypoint> waypoints = new ArrayList<>();
if (mapWaypoints != null) {
for (MapWaypoint point : mapWaypoints) {
waypoints.add(point.dataModelWaypoint);
}
}
return waypoints;
}
/**
* Returns a MapWaypoint without a reference to the datamodel waypoint.
*
@ -298,9 +319,9 @@ final class MapWaypoint extends KdTree.XYZPoint implements org.jxmapviewer.viewe
}
List<Waypoint.Property> list = point.getOtherProperties();
for(Waypoint.Property prop: list) {
for (Waypoint.Property prop : list) {
String value = prop.getValue();
if(value != null && !value.isEmpty()) {
if (value != null && !value.isEmpty()) {
result.append(formatAttribute(prop.getDisplayName(), value));
}
}
@ -333,7 +354,6 @@ final class MapWaypoint extends KdTree.XYZPoint implements org.jxmapviewer.viewe
return DATE_FORMAT.format(new java.util.Date(timeStamp * 1000));
}
/**
* An action class for Extracting artifact files.
*/

View File

@ -0,0 +1,78 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2019 Basis Technology Corp.
* contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.geolocation.datamodel;
import java.util.Map;
import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.BlackboardAttribute;
/**
* Class to represent TSK_GPS_BOOKMARK waypoints
*
*/
final class BookmarkWaypoint extends Waypoint {
/**
* Constructs a new BookmarkWaypoint from the given artifact.
*
* @param artifact BlackboardArtifact for this waypoint
*
* @throws GeoLocationDataException
*/
BookmarkWaypoint(BlackboardArtifact artifact) throws GeoLocationDataException {
this(artifact, getAttributesFromArtifactAsMap(artifact));
}
/**
* Constructs a new BookmarkWaypoint.
*
* @param artifact BlackboardArtifact for this waypoint
* @param attributeMap A Map of the BlackboardAttributes for the given
* artifact.
*
* @throws GeoLocationDataException
*/
private BookmarkWaypoint(BlackboardArtifact artifact, Map<BlackboardAttribute.ATTRIBUTE_TYPE, BlackboardAttribute> attributeMap) throws GeoLocationDataException {
super(artifact,
getLabelFromArtifact(attributeMap),
attributeMap.get(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME) != null ? attributeMap.get(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME).getValueLong() : null,
attributeMap.get(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE) != null ? attributeMap.get(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE).getValueDouble() : null,
attributeMap.get(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE) != null ? attributeMap.get(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE).getValueDouble() : null,
attributeMap.get(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_ALTITUDE) != null ? attributeMap.get(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_ALTITUDE).getValueDouble() : null,
null, attributeMap, null);
}
/**
* Gets the label for this waypoint.
*
* @param artifact BlackboardArtifact for waypoint
*
* @return Returns a label for the waypoint, or empty string if no label was
* found.
*/
private static String getLabelFromArtifact(Map<BlackboardAttribute.ATTRIBUTE_TYPE, BlackboardAttribute> attributeMap) {
BlackboardAttribute attribute = attributeMap.get(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME);
if (attribute != null) {
return attribute.getDisplayString();
}
return "";
}
}

View File

@ -50,10 +50,10 @@ public class Waypoint {
final private List<Waypoint.Property> immutablePropertiesList;
/**
* This is a list of attributes that are already being handled by the
* by getter functions.
* This is a list of attributes that are already being handled by the by
* getter functions.
*/
static private BlackboardAttribute.ATTRIBUTE_TYPE[] ALREADY_HANDLED_ATTRIBUTES = {
static final private BlackboardAttribute.ATTRIBUTE_TYPE[] ALREADY_HANDLED_ATTRIBUTES = {
BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME,
BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE,
BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE,
@ -65,19 +65,6 @@ public class Waypoint {
BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE_END,
BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE_END,};
/**
* Construct a waypoint with the given artifact.
*
* @param artifact BlackboardArtifact for this waypoint
*
* @throws GeoLocationDataException Exception will be thrown if artifact did
* not have a valid longitude and latitude.
*/
Waypoint(BlackboardArtifact artifact) throws GeoLocationDataException {
this(artifact,
getAttributesFromArtifactAsMap(artifact));
}
/**
* Constructor that initializes all of the member variables.
*
@ -110,25 +97,6 @@ public class Waypoint {
immutablePropertiesList = Collections.unmodifiableList(createGeolocationProperties(attributeMap));
}
/**
* Constructs a new ArtifactWaypoint.
*
* @param artifact BlackboardArtifact for this waypoint
* @param attributeMap A Map of the BlackboardAttributes for the given
* artifact.
*
* @throws GeoLocationDataException
*/
private Waypoint(BlackboardArtifact artifact, Map<BlackboardAttribute.ATTRIBUTE_TYPE, BlackboardAttribute> attributeMap) throws GeoLocationDataException {
this(artifact,
getLabelFromArtifact(attributeMap),
attributeMap.get(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME) != null ? attributeMap.get(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME).getValueLong() : null,
attributeMap.get(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE) != null ? attributeMap.get(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE).getValueDouble() : null,
attributeMap.get(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE) != null ? attributeMap.get(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE).getValueDouble() : null,
attributeMap.get(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_ALTITUDE) != null ? attributeMap.get(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_ALTITUDE).getValueDouble() : null,
null, attributeMap, null);
}
/**
* Get the BlackboardArtifact that this waypoint represents.
*
@ -209,7 +177,8 @@ public class Waypoint {
/**
* Returns the route that this waypoint is apart of .
*
* @return The waypoint route or null if the waypoint is not apart of a route.
* @return The waypoint route or null if the waypoint is not apart of a
* route.
*/
public Route getRoute() {
return route;

View File

@ -70,8 +70,8 @@ public final class WaypointBuilder {
+ " )";
// Returns a list of artifacts with no time stamp
final static String SELECT_WO_TIMESTAMP =
"SELECT DISTINCT artifact_id, artifact_type_id "
final static String SELECT_WO_TIMESTAMP
= "SELECT DISTINCT artifact_id, artifact_type_id "
+ "FROM blackboard_attributes "
+ "WHERE artifact_id NOT IN (%s) "
+ "AND artifact_id IN (%s)"; //NON-NLS
@ -121,6 +121,25 @@ public final class WaypointBuilder {
return points;
}
/**
* Returns a list of routes from the given list of waypoints.
*
* @param waypoints A list of waypoints
*
* @return A list of routes or an empty list if none were found.
*/
public static List<Route> getRoutes(List<Waypoint> waypoints) {
List<Route> routeList = new ArrayList<>();
for (Waypoint point : waypoints) {
Route route = point.getRoute();
if (route != null && !routeList.contains(route)) {
routeList.add(route);
}
}
return routeList;
}
/**
* Gets a list of Waypoints for TSK_GPS_TRACKPOINT artifacts.
*
@ -150,6 +169,25 @@ public final class WaypointBuilder {
return points;
}
/**
* Returns a list of waypoints that come from TSK_GEO_TRACKPOINT artifacts.
*
* @param waypoints A list of waypoints
*
* @return A list of trackpoint waypoints or empty list if none were found.
*/
public static List<Waypoint> getTrackpointWaypoints(List<Waypoint> waypoints) {
List<Waypoint> specificPoints = new ArrayList<>();
for (Waypoint point : waypoints) {
if (point instanceof TrackpointWaypoint) {
specificPoints.add(point);
}
}
return specificPoints;
}
/**
* Gets a list of Waypoints for TSK_METADATA_EXIF artifacts.
*
@ -183,6 +221,25 @@ public final class WaypointBuilder {
return points;
}
/**
* Returns a list of waypoints that come from TSK_METADATA_EXIF artifacts.
*
* @param waypoints A list of waypoints
*
* @return A list of trackpoint waypoints or empty list if none were found.
*/
public static List<Waypoint> getEXIFWaypoints(List<Waypoint> waypoints) {
List<Waypoint> specificPoints = new ArrayList<>();
for (Waypoint point : waypoints) {
if (point instanceof EXIFWaypoint) {
specificPoints.add(point);
}
}
return specificPoints;
}
/**
* Gets a list of Waypoints for TSK_GPS_SEARCH artifacts.
*
@ -214,6 +271,25 @@ public final class WaypointBuilder {
return points;
}
/**
* Returns a list of waypoints that come from TSK_GPS_SEARCH artifacts.
*
* @param waypoints A list of waypoints
*
* @return A list of trackpoint waypoints or empty list if none were found.
*/
public static List<Waypoint> getSearchWaypoints(List<Waypoint> waypoints) {
List<Waypoint> specificPoints = new ArrayList<>();
for (Waypoint point : waypoints) {
if (point instanceof SearchWaypoint) {
specificPoints.add(point);
}
}
return specificPoints;
}
/**
* Gets a list of Waypoints for TSK_GPS_LAST_KNOWN_LOCATION artifacts.
*
@ -245,6 +321,26 @@ public final class WaypointBuilder {
return points;
}
/**
* Returns a list of waypoints that come from TSK_GPS_LAST_KNOWN_LOCATION
* artifacts.
*
* @param waypoints A list of waypoints
*
* @return A list of trackpoint waypoints or empty list if none were found.
*/
public static List<Waypoint> getLastKnownWaypoints(List<Waypoint> waypoints) {
List<Waypoint> specificPoints = new ArrayList<>();
for (Waypoint point : waypoints) {
if (point instanceof LastKnownWaypoint) {
specificPoints.add(point);
}
}
return specificPoints;
}
/**
* Gets a list of Waypoints for TSK_GPS_BOOKMARK artifacts.
*
@ -266,7 +362,7 @@ public final class WaypointBuilder {
if (artifacts != null) {
for (BlackboardArtifact artifact : artifacts) {
try {
Waypoint point = new Waypoint(artifact);
Waypoint point = new BookmarkWaypoint(artifact);
points.add(point);
} catch (GeoLocationDataException ex) {
logger.log(Level.WARNING, String.format("No longitude or latitude available for TSK_GPS_BOOKMARK artifactID: %d", artifact.getArtifactID()), ex);//NON-NLS
@ -276,6 +372,26 @@ public final class WaypointBuilder {
return points;
}
/**
* Returns a list of waypoints that come from TSK_GPS_LAST_KNOWN_LOCATION
* artifacts.
*
* @param waypoints A list of waypoints
*
* @return A list of trackpoint waypoints or empty list if none were found.
*/
public static List<Waypoint> getBookmarkWaypoints(List<Waypoint> waypoints) {
List<Waypoint> specificPoints = new ArrayList<>();
for (Waypoint point : waypoints) {
if (point instanceof BookmarkWaypoint) {
specificPoints.add(point);
}
}
return specificPoints;
}
/**
* Get a filtered list of waypoints.
*
@ -464,7 +580,7 @@ public final class WaypointBuilder {
waypoints.add(new EXIFWaypoint(artifact));
break;
case TSK_GPS_BOOKMARK:
waypoints.add(new Waypoint(artifact));
waypoints.add(new BookmarkWaypoint(artifact));
break;
case TSK_GPS_TRACKPOINT:
waypoints.add(new TrackpointWaypoint(artifact));
@ -477,8 +593,7 @@ public final class WaypointBuilder {
waypoints.addAll(route.getRoute());
break;
default:
waypoints.add(new Waypoint(artifact));
break;
throw new GeoLocationDataException(String.format("Unable to create waypoint for artifact of type %s", type.toString()));
}
return waypoints;

Binary file not shown.

After

Width:  |  Height:  |  Size: 912 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 891 B

View File

@ -33,6 +33,7 @@ import java.io.OutputStream;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import org.jdom2.Document;
@ -59,7 +60,7 @@ import org.sleuthkit.datamodel.TskCoreException;
/**
* Generates a KML file based on geospatial information from the BlackBoard.
*/
class KMLReport implements GeneralReportModule {
public class KMLReport implements GeneralReportModule {
private static final Logger logger = Logger.getLogger(KMLReport.class.getName());
private static final String KML_STYLE_FILE = "style.kml";
@ -79,6 +80,8 @@ class KMLReport implements GeneralReportModule {
private Element gpsSearchesFolder;
private Element gpsTrackpointsFolder;
private List<Waypoint> waypointList = null;
private enum FeatureColor {
RED("style.kml#redFeature"),
GREEN("style.kml#greenFeature"),
@ -141,6 +144,11 @@ class KMLReport implements GeneralReportModule {
"Route_Details_Header=GPS Route"
})
public void generateReport(String baseReportDir, ReportProgressPanel progressPanel, List<Waypoint> waypointList) {
this.waypointList = waypointList;
generateReport(baseReportDir, progressPanel);
}
@Override
public void generateReport(String baseReportDir, ReportProgressPanel progressPanel) {
try {
@ -298,7 +306,7 @@ class KMLReport implements GeneralReportModule {
* @throws IOException
*/
void addExifMetadataContent(List<Waypoint> points, String baseReportDirectory) throws IOException {
for(Waypoint point: points) {
for (Waypoint point : points) {
Element mapPoint = makePoint(point);
if (mapPoint == null) {
return;
@ -332,23 +340,31 @@ class KMLReport implements GeneralReportModule {
* @throws IOException
*/
void addLocationsToReport(SleuthkitCase skCase, String baseReportDir) throws GeoLocationDataException, IOException {
if (waypointList == null) {
addExifMetadataContent(WaypointBuilder.getEXIFWaypoints(skCase), baseReportDir);
addWaypoints(WaypointBuilder.getBookmarkWaypoints(skCase), gpsBookmarksFolder, FeatureColor.BLUE, Bundle.Waypoint_Bookmark_Display_String());
addWaypoints(WaypointBuilder.getLastKnownWaypoints(skCase), gpsLastKnownLocationFolder, FeatureColor.PURPLE, Bundle.Waypoint_Last_Known_Display_String());
addWaypoints(WaypointBuilder.getSearchWaypoints(skCase), gpsSearchesFolder, FeatureColor.WHITE, Bundle.Waypoint_Search_Display_String());
addWaypoints(WaypointBuilder.getTrackpointWaypoints(skCase), gpsTrackpointsFolder, FeatureColor.WHITE, Bundle.Waypoint_Trackpoint_Display_String());
} else {
addExifMetadataContent(WaypointBuilder.getEXIFWaypoints(waypointList), baseReportDir);
addWaypoints(WaypointBuilder.getBookmarkWaypoints(waypointList), gpsBookmarksFolder, FeatureColor.BLUE, Bundle.Waypoint_Bookmark_Display_String());
addWaypoints(WaypointBuilder.getLastKnownWaypoints(waypointList), gpsLastKnownLocationFolder, FeatureColor.PURPLE, Bundle.Waypoint_Last_Known_Display_String());
addWaypoints(WaypointBuilder.getSearchWaypoints(waypointList), gpsSearchesFolder, FeatureColor.WHITE, Bundle.Waypoint_Search_Display_String());
addWaypoints(WaypointBuilder.getTrackpointWaypoints(waypointList), gpsTrackpointsFolder, FeatureColor.WHITE, Bundle.Waypoint_Trackpoint_Display_String());
}
}
/**
* For each point in the waypoint list an Element to represent the given waypoint
* is created and added it to the given Element folder.
* For each point in the waypoint list an Element to represent the given
* waypoint is created and added it to the given Element folder.
*
* @param points List of waypoints to add to the report
* @param folder The Element folder to add the points to
* @param waypointColor The color the waypoint should appear in the report
*/
void addWaypoints(List<Waypoint> points, Element folder, FeatureColor waypointColor, String headerLabel) {
for(Waypoint point: points) {
for (Waypoint point : points) {
addContent(folder, point.getLabel(), waypointColor, getFormattedDetails(point, headerLabel), point.getTimestamp(), makePoint(point), point.getLatitude(), point.getLongitude());
}
}
@ -366,7 +382,7 @@ class KMLReport implements GeneralReportModule {
* @param longitude Double longitude value
*/
void addContent(Element folder, String waypointLabel, FeatureColor waypointColor, String formattedDetails, Long timestamp, Element point, Double latitude, Double longitude) {
if(folder != null && point != null) {
if (folder != null && point != null) {
String formattedCords = formattedCoordinates(latitude, longitude);
folder.addContent(makePlacemark(waypointLabel, waypointColor, formattedDetails, timestamp, point, formattedCords));
}
@ -380,10 +396,12 @@ class KMLReport implements GeneralReportModule {
* @throws TskCoreException
*/
void makeRoutes(SleuthkitCase skCase) throws GeoLocationDataException {
List<Route> routes = Route.getRoutes(skCase);
List<Route> routes = null;
if(routes == null) {
return;
if (waypointList == null) {
routes = Route.getRoutes(skCase);
} else {
routes = new ArrayList<>();
}
for (Route route : routes) {
@ -712,9 +730,9 @@ class KMLReport implements GeneralReportModule {
}
List<Waypoint.Property> list = point.getOtherProperties();
for(Waypoint.Property prop: list) {
for (Waypoint.Property prop : list) {
String value = prop.getValue();
if(value != null && !value.isEmpty()) {
if (value != null && !value.isEmpty()) {
result.append(formatAttribute(prop.getDisplayName(), value));
}
}
@ -733,7 +751,6 @@ class KMLReport implements GeneralReportModule {
*
* @return A HTML formatted list of the Route attributes
*/
private String getFormattedDetails(Route route) {
List<Waypoint> points = route.getRoute();
StringBuilder result = new StringBuilder(); //NON-NLS
@ -754,7 +771,7 @@ class KMLReport implements GeneralReportModule {
.append(formatAttribute("Start Longitude", start.getLongitude().toString()));
Double altitude = start.getAltitude();
if(altitude != null) {
if (altitude != null) {
result.append(formatAttribute("Start Altitude", altitude.toString()));
}
@ -762,15 +779,15 @@ class KMLReport implements GeneralReportModule {
.append(formatAttribute("End Longitude", end.getLongitude().toString()));
altitude = end.getAltitude();
if(altitude != null) {
if (altitude != null) {
result.append(formatAttribute("End Altitude", altitude.toString()));
}
}
List<Waypoint.Property> list = route.getOtherProperties();
for(Waypoint.Property prop: list) {
for (Waypoint.Property prop : list) {
String value = prop.getValue();
if(value != null && !value.isEmpty()) {
if (value != null && !value.isEmpty()) {
result.append(formatAttribute(prop.getDisplayName(), value));
}
}