diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/analysisresults/AnalysisResultsContentPanel.java b/Core/src/org/sleuthkit/autopsy/contentviewers/analysisresults/AnalysisResultsContentPanel.java
index 3a5a670f49..f365e8392e 100644
--- a/Core/src/org/sleuthkit/autopsy/contentviewers/analysisresults/AnalysisResultsContentPanel.java
+++ b/Core/src/org/sleuthkit/autopsy/contentviewers/analysisresults/AnalysisResultsContentPanel.java
@@ -26,20 +26,22 @@ import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.openide.util.NbBundle;
+import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.contentviewers.analysisresults.AnalysisResultsViewModel.NodeResults;
import org.sleuthkit.autopsy.contentviewers.analysisresults.AnalysisResultsViewModel.ResultDisplayAttributes;
import org.sleuthkit.autopsy.contentviewers.layout.ContentViewerHtmlStyles;
import org.sleuthkit.autopsy.coreutils.EscapeUtil;
import org.sleuthkit.datamodel.AnalysisResult;
+import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.Score;
/**
* Displays a list of analysis results in a panel.
*/
public class AnalysisResultsContentPanel extends javax.swing.JPanel {
-
+
private static final long serialVersionUID = 1L;
-
+
private static final String EMPTY_HTML = "
";
// Anchors are inserted into the navigation so that the viewer can navigate to a selection.
@@ -80,27 +82,18 @@ public class AnalysisResultsContentPanel extends javax.swing.JPanel {
*
* @param nodeResults The analysis results data to display.
*/
- @NbBundle.Messages("AnalysisResultsContentPanel_aggregateScore_displayKey=Aggregate Score")
void displayResults(NodeResults nodeResults) {
Document document = Jsoup.parse(EMPTY_HTML);
Element body = document.getElementsByTag("body").first();
- // if there is an aggregate score, append a section with the value
- Optional aggregateScore = nodeResults.getAggregateScore();
- if (aggregateScore.isPresent()) {
- appendSection(body,
- MessageFormat.format("{0}: {1}",
- Bundle.AnalysisResultsContentPanel_aggregateScore_displayKey(),
- aggregateScore.get().getSignificance().getDisplayName()),
- Optional.empty());
- }
+ Optional panelHeader = appendPanelHeader(body, nodeResults.getContent(), nodeResults.getAggregateScore());
// for each analysis result item, display the data.
List displayAttributes = nodeResults.getAnalysisResults();
for (int idx = 0; idx < displayAttributes.size(); idx++) {
AnalysisResultsViewModel.ResultDisplayAttributes resultAttrs = displayAttributes.get(idx);
Element sectionDiv = appendResult(body, idx, resultAttrs);
- if (idx > 0 || aggregateScore.isPresent()) {
+ if (idx > 0 || panelHeader.isPresent()) {
sectionDiv.attr("class", ContentViewerHtmlStyles.getSpacedSectionClassName());
}
}
@@ -119,6 +112,48 @@ public class AnalysisResultsContentPanel extends javax.swing.JPanel {
}
}
+ /**
+ * Appends the header to the panel.
+ *
+ * @param parent The parent html element.
+ * @param content The content whose name will be added if present.
+ * @param score The aggregate score whose significance will be added if
+ * present.
+ *
+ * @return The html element.
+ */
+ @Messages({
+ "AnalysisResultsContentPanel_aggregateScore_displayKey=Aggregate Score",
+ "AnalysisResultsContentPanel_content_displayKey=Item"
+ })
+ private Optional appendPanelHeader(Element parent, Optional content, Optional score) {
+ if (!content.isPresent() || !score.isPresent()) {
+ return Optional.empty();
+ }
+
+ Element container = parent.appendElement("div");
+
+ // if there is content append the name
+ content.ifPresent((c) -> {
+ container.appendElement("p")
+ .attr("class", ContentViewerHtmlStyles.getTextClassName())
+ .text(MessageFormat.format("{0}: {1}",
+ Bundle.AnalysisResultsContentPanel_content_displayKey(),
+ c.getName()));
+ });
+
+ // if there is an aggregate score, append the value
+ score.ifPresent((s) -> {
+ container.appendElement("p")
+ .attr("class", ContentViewerHtmlStyles.getTextClassName())
+ .text(MessageFormat.format("{0}: {1}",
+ Bundle.AnalysisResultsContentPanel_aggregateScore_displayKey(),
+ s.getSignificance().getDisplayName()));
+ });
+
+ return Optional.ofNullable(container);
+ }
+
/**
* Returns the anchor id to use with the analysis result (based on the id).
*
@@ -151,7 +186,7 @@ public class AnalysisResultsContentPanel extends javax.swing.JPanel {
// create a table
Element table = sectionDiv.appendElement("table");
table.attr("class", ContentViewerHtmlStyles.getIndentedClassName());
-
+
Element tableBody = table.appendElement("tbody");
// append a row for each item
@@ -160,7 +195,7 @@ public class AnalysisResultsContentPanel extends javax.swing.JPanel {
String keyString = keyVal.getKey() == null ? "" : keyVal.getKey() + ":";
Element keyTd = row.appendElement("td")
.attr("class", ContentViewerHtmlStyles.getTextClassName());
-
+
keyTd.appendElement("span")
.text(keyString)
.attr("class", ContentViewerHtmlStyles.getKeyColumnClassName());
@@ -170,7 +205,7 @@ public class AnalysisResultsContentPanel extends javax.swing.JPanel {
.text(valueString)
.attr("class", ContentViewerHtmlStyles.getTextClassName());
}
-
+
return sectionDiv;
}
@@ -199,7 +234,7 @@ public class AnalysisResultsContentPanel extends javax.swing.JPanel {
header = (anchorEl == null)
? sectionDiv.appendElement("h1")
: anchorEl.appendElement("h1");
-
+
header.text(headerText);
header.attr("class", ContentViewerHtmlStyles.getHeaderClassName());
header.attr("style", "display: inline-block");
diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/analysisresults/AnalysisResultsViewModel.java b/Core/src/org/sleuthkit/autopsy/contentviewers/analysisresults/AnalysisResultsViewModel.java
index 8ba7308eb4..00cc170b14 100644
--- a/Core/src/org/sleuthkit/autopsy/contentviewers/analysisresults/AnalysisResultsViewModel.java
+++ b/Core/src/org/sleuthkit/autopsy/contentviewers/analysisresults/AnalysisResultsViewModel.java
@@ -94,6 +94,7 @@ public class AnalysisResultsViewModel {
private final List analysisResults;
private final Optional selectedResult;
private final Optional aggregateScore;
+ private final Optional content;
/**
* Constructor.
@@ -102,11 +103,13 @@ public class AnalysisResultsViewModel {
* @param selectedResult The selected analysis result or empty if none
* selected.
* @param aggregateScore The aggregate score or empty if no score.
+ * @param content The content associated with these results.
*/
- NodeResults(List analysisResults, Optional selectedResult, Optional aggregateScore) {
+ NodeResults(List analysisResults, Optional selectedResult, Optional aggregateScore, Optional content) {
this.analysisResults = analysisResults;
this.selectedResult = selectedResult;
this.aggregateScore = aggregateScore;
+ this.content = content;
}
/**
@@ -135,6 +138,17 @@ public class AnalysisResultsViewModel {
Optional getAggregateScore() {
return aggregateScore;
}
+
+ /**
+ * Returns the content associated with these results or empty if not
+ * present.
+ *
+ * @return The content associated with these results or empty if not
+ * present.
+ */
+ Optional getContent() {
+ return content;
+ }
}
/**
@@ -221,10 +235,11 @@ public class AnalysisResultsViewModel {
*/
NodeResults getAnalysisResults(Node node) {
if (node == null) {
- return new NodeResults(Collections.emptyList(), Optional.empty(), Optional.empty());
+ return new NodeResults(Collections.emptyList(), Optional.empty(), Optional.empty(), Optional.empty());
}
Optional aggregateScore = Optional.empty();
+ Optional nodeContent = Optional.empty();
// maps id of analysis result to analysis result to prevent duplication
Map allAnalysisResults = new HashMap<>();
Optional selectedResult = Optional.empty();
@@ -236,6 +251,8 @@ public class AnalysisResultsViewModel {
}
try {
+ nodeContent = Optional.of(content);
+
// get the aggregate score of that content
aggregateScore = Optional.ofNullable(content.getAggregateScore());
@@ -273,6 +290,6 @@ public class AnalysisResultsViewModel {
// get view model representation
List displayAttributes = getOrderedDisplayAttributes(allAnalysisResults.values());
- return new NodeResults(displayAttributes, selectedResult, aggregateScore);
+ return new NodeResults(displayAttributes, selectedResult, aggregateScore, nodeContent);
}
}