change in analysis results header attributes

This commit is contained in:
Greg DiCristofaro 2021-06-09 15:45:13 -04:00
parent 630d259653
commit c26efab04d
2 changed files with 72 additions and 20 deletions

View File

@ -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 = "<html><head></head><body></body></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<Score> aggregateScore = nodeResults.getAggregateScore();
if (aggregateScore.isPresent()) {
appendSection(body,
MessageFormat.format("{0}: {1}",
Bundle.AnalysisResultsContentPanel_aggregateScore_displayKey(),
aggregateScore.get().getSignificance().getDisplayName()),
Optional.empty());
}
Optional<Element> panelHeader = appendPanelHeader(body, nodeResults.getContent(), nodeResults.getAggregateScore());
// for each analysis result item, display the data.
List<ResultDisplayAttributes> 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<Element> appendPanelHeader(Element parent, Optional<Content> content, Optional<Score> 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");

View File

@ -94,6 +94,7 @@ public class AnalysisResultsViewModel {
private final List<ResultDisplayAttributes> analysisResults;
private final Optional<AnalysisResult> selectedResult;
private final Optional<Score> aggregateScore;
private final Optional<Content> 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<ResultDisplayAttributes> analysisResults, Optional<AnalysisResult> selectedResult, Optional<Score> aggregateScore) {
NodeResults(List<ResultDisplayAttributes> analysisResults, Optional<AnalysisResult> selectedResult, Optional<Score> aggregateScore, Optional<Content> content) {
this.analysisResults = analysisResults;
this.selectedResult = selectedResult;
this.aggregateScore = aggregateScore;
this.content = content;
}
/**
@ -135,6 +138,17 @@ public class AnalysisResultsViewModel {
Optional<Score> 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<Content> 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<Score> aggregateScore = Optional.empty();
Optional<Content> nodeContent = Optional.empty();
// maps id of analysis result to analysis result to prevent duplication
Map<Long, AnalysisResult> allAnalysisResults = new HashMap<>();
Optional<AnalysisResult> 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<ResultDisplayAttributes> displayAttributes = getOrderedDisplayAttributes(allAnalysisResults.values());
return new NodeResults(displayAttributes, selectedResult, aggregateScore);
return new NodeResults(displayAttributes, selectedResult, aggregateScore, nodeContent);
}
}