Index: lucene/highlighter/src/test/org/apache/lucene/search/postingshighlight/TestPostingsHighlighter.java
===================================================================
--- lucene/highlighter/src/test/org/apache/lucene/search/postingshighlight/TestPostingsHighlighter.java (revision 1458944)
+++ lucene/highlighter/src/test/org/apache/lucene/search/postingshighlight/TestPostingsHighlighter.java (working copy)
@@ -457,7 +457,7 @@
iw.close();
IndexSearcher searcher = newSearcher(ir);
- PostingsHighlighter highlighter = new PostingsHighlighter(10000, null, new PassageScorer(), new PassageFormatter());
+ PostingsHighlighter highlighter = new PostingsHighlighter(10000, null);
Query query = new TermQuery(new Term("body", "test"));
TopDocs topDocs = searcher.search(query, null, 10, Sort.INDEXORDER);
assertEquals(1, topDocs.totalHits);
@@ -527,7 +527,7 @@
IndexSearcher searcher = newSearcher(ir);
- PostingsHighlighter highlighter = new PostingsHighlighter(10000, null, new PassageScorer(), new PassageFormatter()) {
+ PostingsHighlighter highlighter = new PostingsHighlighter(10000, null) {
@Override
protected String[][] loadFieldValues(IndexSearcher searcher, String[] fields, int[] docids, int maxLength) throws IOException {
assert fields.length == 1;
@@ -636,7 +636,7 @@
iw.close();
IndexSearcher searcher = newSearcher(ir);
- PostingsHighlighter highlighter = new PostingsHighlighter(10000, null, new PassageScorer(), new PassageFormatter());
+ PostingsHighlighter highlighter = new PostingsHighlighter(10000, null);
Query query = new TermQuery(new Term("body", "highlighting"));
int[] docIDs = new int[] {0};
String snippets[] = highlighter.highlightFields(new String[] {"body"}, query, searcher, docIDs, 2).get("body");
Index: lucene/highlighter/src/test/org/apache/lucene/search/postingshighlight/TestPostingsHighlighterRanking.java
===================================================================
--- lucene/highlighter/src/test/org/apache/lucene/search/postingshighlight/TestPostingsHighlighterRanking.java (revision 1458942)
+++ lucene/highlighter/src/test/org/apache/lucene/search/postingshighlight/TestPostingsHighlighterRanking.java (working copy)
@@ -112,16 +112,24 @@
private void checkQuery(IndexSearcher is, Query query, int doc, int maxTopN) throws IOException {
for (int n = 1; n < maxTopN; n++) {
- FakePassageFormatter f1 = new FakePassageFormatter();
+ final FakePassageFormatter f1 = new FakePassageFormatter();
PostingsHighlighter p1 = new PostingsHighlighter(Integer.MAX_VALUE-1,
- BreakIterator.getSentenceInstance(Locale.ROOT),
- new PassageScorer(),
- f1);
- FakePassageFormatter f2 = new FakePassageFormatter();
+ BreakIterator.getSentenceInstance(Locale.ROOT)) {
+ @Override
+ protected PassageFormatter getFormatter(String field) {
+ return f1;
+ }
+ };
+
+ final FakePassageFormatter f2 = new FakePassageFormatter();
PostingsHighlighter p2 = new PostingsHighlighter(Integer.MAX_VALUE-1,
- BreakIterator.getSentenceInstance(Locale.ROOT),
- new PassageScorer(),
- f2);
+ BreakIterator.getSentenceInstance(Locale.ROOT)) {
+ @Override
+ protected PassageFormatter getFormatter(String field) {
+ return f2;
+ }
+ };
+
BooleanQuery bq = new BooleanQuery(false);
bq.add(query, BooleanClause.Occur.MUST);
bq.add(new TermQuery(new Term("id", Integer.toString(doc))), BooleanClause.Occur.MUST);
@@ -262,9 +270,12 @@
IndexSearcher searcher = newSearcher(ir);
PostingsHighlighter highlighter = new PostingsHighlighter(10000,
- BreakIterator.getSentenceInstance(Locale.ROOT),
- new PassageScorer(1.2f, 0, 87),
- new PassageFormatter());
+ BreakIterator.getSentenceInstance(Locale.ROOT)) {
+ @Override
+ protected PassageScorer getScorer(String field) {
+ return new PassageScorer(1.2f, 0, 87);
+ }
+ };
Query query = new TermQuery(new Term("body", "test"));
TopDocs topDocs = searcher.search(query, null, 10, Sort.INDEXORDER);
assertEquals(1, topDocs.totalHits);
@@ -299,9 +310,12 @@
IndexSearcher searcher = newSearcher(ir);
PostingsHighlighter highlighter = new PostingsHighlighter(10000,
- BreakIterator.getSentenceInstance(Locale.ROOT),
- new PassageScorer(0, 0.75f, 87),
- new PassageFormatter());
+ BreakIterator.getSentenceInstance(Locale.ROOT)) {
+ @Override
+ protected PassageScorer getScorer(String field) {
+ return new PassageScorer(0, 0.75f, 87);
+ }
+ };
BooleanQuery query = new BooleanQuery();
query.add(new TermQuery(new Term("body", "foo")), BooleanClause.Occur.SHOULD);
query.add(new TermQuery(new Term("body", "bar")), BooleanClause.Occur.SHOULD);
Index: lucene/highlighter/src/java/org/apache/lucene/search/postingshighlight/PostingsHighlighter.java
===================================================================
--- lucene/highlighter/src/java/org/apache/lucene/search/postingshighlight/PostingsHighlighter.java (revision 1458950)
+++ lucene/highlighter/src/java/org/apache/lucene/search/postingshighlight/PostingsHighlighter.java (working copy)
@@ -97,8 +97,6 @@
private final int maxLength;
private final BreakIterator breakIterator;
- private final PassageScorer scorer;
- private final PassageFormatter formatter;
/**
* Creates a new highlighter with default parameters.
@@ -113,7 +111,7 @@
* @throws IllegalArgumentException if maxLength is negative or Integer.MAX_VALUE
*/
public PostingsHighlighter(int maxLength) {
- this(maxLength, BreakIterator.getSentenceInstance(Locale.ROOT), new PassageScorer(), new PassageFormatter());
+ this(maxLength, BreakIterator.getSentenceInstance(Locale.ROOT));
}
/**
@@ -122,11 +120,9 @@
* @param breakIterator used for finding passage
* boundaries; pass null to highlight the entire
* content as a single Passage.
- * @param scorer used for ranking passages.
- * @param formatter used for formatting passages into highlighted snippets.
* @throws IllegalArgumentException if maxLength is negative or Integer.MAX_VALUE
*/
- public PostingsHighlighter(int maxLength, BreakIterator breakIterator, PassageScorer scorer, PassageFormatter formatter) {
+ public PostingsHighlighter(int maxLength, BreakIterator breakIterator) {
if (maxLength < 0 || maxLength == Integer.MAX_VALUE) {
// two reasons: no overflow problems in BreakIterator.preceding(offset+1),
// our sentinel in the offsets queue uses this value to terminate.
@@ -135,15 +131,28 @@
if (breakIterator == null) {
breakIterator = new WholeBreakIterator();
}
- if (scorer == null || formatter == null) {
- throw new NullPointerException();
- }
this.maxLength = maxLength;
this.breakIterator = breakIterator;
- this.scorer = scorer;
- this.formatter = formatter;
}
+ /** Returns the {@link PassageFormatter} to use for
+ * formatting passages into highlighted snippets. This
+ * returns a new {@code PassageFormatter} by default;
+ * subclasses can override to customize. */
+ protected PassageFormatter getFormatter(String field) {
+ // nocommit can we do this just once & reuse across fields?
+ return new PassageFormatter();
+ }
+
+ /** Returns the {@link PassageScorer} to use for
+ * ranking passages. This
+ * returns a new {@code PassageScorer} by default;
+ * subclasses can override to customize. */
+ protected PassageScorer getScorer(String field) {
+ // nocommit can we do this just once & reuse across fields?
+ return new PassageScorer();
+ }
+
/**
* Highlights the top passages from a single field.
*
@@ -341,6 +350,11 @@
TermsEnum termsEnum = null;
int lastLeaf = -1;
+ PassageFormatter fieldFormatter = getFormatter(field);
+ if (fieldFormatter == null) {
+ throw new NullPointerException("PassageFormatter cannot be null");
+ }
+
for (int i = 0; i < docids.length; i++) {
String content = contents[i];
if (content.length() == 0) {
@@ -366,7 +380,7 @@
if (passages.length > 0) {
// otherwise a null snippet (eg if field is missing
// entirely from the doc)
- highlights.put(doc, formatter.format(passages, content));
+ highlights.put(doc, fieldFormatter.format(passages, content));
}
lastLeaf = leaf;
}
@@ -379,6 +393,7 @@
// score each sentence as norm(sentenceStartOffset) * sum(weight * tf(freq))
private Passage[] highlightDoc(String field, Term terms[], int contentLength, BreakIterator bi, int doc,
TermsEnum termsEnum, DocsAndPositionsEnum[] postings, int n) throws IOException {
+ PassageScorer scorer = getScorer(field);
PriorityQueue pq = new PriorityQueue();
float weights[] = new float[terms.length];
// initialize postings