From 3c8a6a05c547f5d4146ffc1ab292d0c590b82ac3 Mon Sep 17 00:00:00 2001 From: millmanorama Date: Fri, 28 Apr 2017 13:20:19 +0200 Subject: [PATCH 1/2] use a range set to do highlighting in two steps. --- .../keywordsearch/HighlightedText.java | 57 ++++++++++--------- 1 file changed, 31 insertions(+), 26 deletions(-) diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/HighlightedText.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/HighlightedText.java index 1aedca4939..744fdb6b31 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/HighlightedText.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/HighlightedText.java @@ -19,6 +19,9 @@ package org.sleuthkit.autopsy.keywordsearch; import com.google.common.collect.Iterators; +import com.google.common.collect.Range; +import com.google.common.collect.RangeSet; +import com.google.common.collect.TreeRangeSet; import java.util.Arrays; import java.util.Collection; import java.util.HashMap; @@ -63,6 +66,7 @@ class HighlightedText implements IndexedText { private static final String HIGHLIGHT_PRE = ""; //NON-NLS private static final String HIGHLIGHT_POST = ""; //NON-NLS + private static final int HIGHLIGHT_MARKUP_LENGTH = HIGHLIGHT_PRE.length() + HIGHLIGHT_POST.length(); private static final String ANCHOR_PREFIX = HighlightedText.class.getName() + "_"; //NON-NLS final private Server solrServer = KeywordSearch.getServer(); @@ -460,8 +464,7 @@ class HighlightedText implements IndexedText { */ static String attemptManualHighlighting(SolrDocumentList solrDocumentList, String highlightField, Collection keywords) { if (solrDocumentList.isEmpty()) { - return NbBundle.getMessage(HighlightedText.class, - "HighlightedMatchesSource.getMarkup.noMatchMsg"); + return NbBundle.getMessage(HighlightedText.class, "HighlightedMatchesSource.getMarkup.noMatchMsg"); } // It doesn't make sense for there to be more than a single document in @@ -476,39 +479,41 @@ class HighlightedText implements IndexedText { // not see highlighted text in the content viewer. text = StringEscapeUtils.escapeHtml(text); - StringBuilder highlightedText = new StringBuilder(""); + TreeRangeSet highlights = TreeRangeSet.create(); //do a highlighting pass for each keyword for (String keyword : keywords) { - //we also need to escape the keyword so that it matches the escpared text + //we also need to escape the keyword so that it matches the escaped text final String escapedKeyword = StringEscapeUtils.escapeHtml(keyword); - int textOffset = 0; - int hitOffset = StringUtils.indexOfIgnoreCase(text, escapedKeyword, textOffset); + int searchOffset = 0; + int hitOffset = StringUtils.indexOfIgnoreCase(text, escapedKeyword, searchOffset); while (hitOffset != -1) { - // Append the portion of text up to (but not including) the hit. - highlightedText.append(text.substring(textOffset, hitOffset)); - // Add in the highlighting around the keyword. - highlightedText.append(HIGHLIGHT_PRE); - highlightedText.append(keyword); - highlightedText.append(HIGHLIGHT_POST); + // Advance the search offset past the keyword. + searchOffset = hitOffset + escapedKeyword.length(); - // Advance the text offset past the keyword. - textOffset = hitOffset + escapedKeyword.length(); + //record the location of th hir, possibly merging it with other hits + highlights.add(Range.closedOpen(hitOffset, searchOffset)); - hitOffset = StringUtils.indexOfIgnoreCase(text, escapedKeyword, textOffset); + //look for next hit + hitOffset = StringUtils.indexOfIgnoreCase(text, escapedKeyword, searchOffset); } - // Append the remainder of text field - highlightedText.append(text.substring(textOffset, text.length())); - - if (highlightedText.length() == 0) { - return NbBundle.getMessage(HighlightedText.class, - "HighlightedMatchesSource.getMarkup.noMatchMsg"); - } - //reset for next pass - text = highlightedText.toString(); - highlightedText = new StringBuilder(""); } - return text; + + StringBuilder highlightedText = new StringBuilder(text); + int totalHighLightLengthInserted = 0; + //for each range to be highlighted... + for (Range highlightRange : highlights.asRanges()) { + int hStart = highlightRange.lowerEndpoint(); + int hEnd = highlightRange.upperEndpoint(); + + //insert the pre and post tag, adjusting indices for previously added tags + highlightedText.insert(hStart + totalHighLightLengthInserted, HIGHLIGHT_PRE); + totalHighLightLengthInserted += HIGHLIGHT_PRE.length(); + highlightedText.insert(hEnd + totalHighLightLengthInserted, HIGHLIGHT_POST); + totalHighLightLengthInserted += HIGHLIGHT_POST.length(); + } + + return highlightedText.toString(); } /** From 168875074932a4cc056994abe4bd8466aec70ca0 Mon Sep 17 00:00:00 2001 From: millmanorama Date: Fri, 28 Apr 2017 13:21:44 +0200 Subject: [PATCH 2/2] cleanup and comments --- .../sleuthkit/autopsy/keywordsearch/HighlightedText.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/HighlightedText.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/HighlightedText.java index 744fdb6b31..541b9a373c 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/HighlightedText.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/HighlightedText.java @@ -66,7 +66,6 @@ class HighlightedText implements IndexedText { private static final String HIGHLIGHT_PRE = ""; //NON-NLS private static final String HIGHLIGHT_POST = ""; //NON-NLS - private static final int HIGHLIGHT_MARKUP_LENGTH = HIGHLIGHT_PRE.length() + HIGHLIGHT_POST.length(); private static final String ANCHOR_PREFIX = HighlightedText.class.getName() + "_"; //NON-NLS final private Server solrServer = KeywordSearch.getServer(); @@ -459,7 +458,7 @@ class HighlightedText implements IndexedText { * to a Solr query. We expect there to only ever be * a single document. * - * @return Either a string with the keyword highlighted or a string + * @return Either a string with the keyword highlighted via HTML span tags or a string * indicating that we did not find a hit in the document. */ static String attemptManualHighlighting(SolrDocumentList solrDocumentList, String highlightField, Collection keywords) { @@ -481,7 +480,7 @@ class HighlightedText implements IndexedText { TreeRangeSet highlights = TreeRangeSet.create(); - //do a highlighting pass for each keyword + //for each keyword find the locations of hits and record them in the RangeSet for (String keyword : keywords) { //we also need to escape the keyword so that it matches the escaped text final String escapedKeyword = StringEscapeUtils.escapeHtml(keyword); @@ -491,7 +490,7 @@ class HighlightedText implements IndexedText { // Advance the search offset past the keyword. searchOffset = hitOffset + escapedKeyword.length(); - //record the location of th hir, possibly merging it with other hits + //record the location of the hir, possibly merging it with other hits highlights.add(Range.closedOpen(hitOffset, searchOffset)); //look for next hit