add --shared
[pylucene.git] / lucene-java-3.4.0 / lucene / contrib / highlighter / src / test / org / apache / lucene / search / highlight / HighlighterPhraseTest.java
1 package org.apache.lucene.search.highlight;
2
3 /**
4  * Licensed to the Apache Software Foundation (ASF) under one or more
5  * contributor license agreements.  See the NOTICE file distributed with
6  * this work for additional information regarding copyright ownership.
7  * The ASF licenses this file to You under the Apache License, Version 2.0
8  * (the "License"); you may not use this file except in compliance with
9  * the License.  You may obtain a copy of the License at
10  *
11  *     http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19
20 import java.io.IOException;
21
22 import org.apache.lucene.analysis.MockAnalyzer;
23 import org.apache.lucene.analysis.MockTokenizer;
24 import org.apache.lucene.analysis.Token;
25 import org.apache.lucene.analysis.TokenStream;
26 import org.apache.lucene.analysis.tokenattributes.OffsetAttribute;
27 import org.apache.lucene.analysis.tokenattributes.PositionIncrementAttribute;
28 import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
29 import org.apache.lucene.document.Document;
30 import org.apache.lucene.document.Field;
31 import org.apache.lucene.document.Field.Index;
32 import org.apache.lucene.document.Field.Store;
33 import org.apache.lucene.document.Field.TermVector;
34 import org.apache.lucene.index.CorruptIndexException;
35 import org.apache.lucene.index.IndexReader;
36 import org.apache.lucene.index.IndexWriter;
37 import org.apache.lucene.index.Term;
38 import org.apache.lucene.index.TermPositionVector;
39 import org.apache.lucene.search.Collector;
40 import org.apache.lucene.search.IndexSearcher;
41 import org.apache.lucene.search.PhraseQuery;
42 import org.apache.lucene.search.Query;
43 import org.apache.lucene.search.TopDocs;
44
45 import org.apache.lucene.search.spans.SpanNearQuery;
46 import org.apache.lucene.search.spans.SpanQuery;
47 import org.apache.lucene.search.spans.SpanTermQuery;
48 import org.apache.lucene.store.Directory;
49 import org.apache.lucene.store.LockObtainFailedException;
50 import org.apache.lucene.util.LuceneTestCase;
51 import org.apache.lucene.util.FixedBitSet;
52
53 public class HighlighterPhraseTest extends LuceneTestCase {
54   private static final String FIELD = "text";
55   public void testConcurrentPhrase() throws CorruptIndexException,
56       LockObtainFailedException, IOException, InvalidTokenOffsetsException {
57     final String TEXT = "the fox jumped";
58     final Directory directory = newDirectory();
59     final IndexWriter indexWriter = new IndexWriter(directory,
60         newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random, MockTokenizer.WHITESPACE, false)));
61     try {
62       final Document document = new Document();
63       document.add(new Field(FIELD, new TokenStreamConcurrent(),
64           TermVector.WITH_POSITIONS_OFFSETS));
65       indexWriter.addDocument(document);
66     } finally {
67       indexWriter.close();
68     }
69     final IndexReader indexReader = IndexReader.open(directory, true);
70     try {
71       assertEquals(1, indexReader.numDocs());
72       final IndexSearcher indexSearcher = newSearcher(indexReader);
73       try {
74         final PhraseQuery phraseQuery = new PhraseQuery();
75         phraseQuery.add(new Term(FIELD, "fox"));
76         phraseQuery.add(new Term(FIELD, "jumped"));
77         phraseQuery.setSlop(0);
78         TopDocs hits = indexSearcher.search(phraseQuery, 1);
79         assertEquals(1, hits.totalHits);
80         final Highlighter highlighter = new Highlighter(
81             new SimpleHTMLFormatter(), new SimpleHTMLEncoder(),
82             new QueryScorer(phraseQuery));
83
84         final TokenStream tokenStream = TokenSources
85             .getTokenStream((TermPositionVector) indexReader.getTermFreqVector(
86                 0, FIELD), false);
87         assertEquals(highlighter.getBestFragment(new TokenStreamConcurrent(),
88             TEXT), highlighter.getBestFragment(tokenStream, TEXT));
89
90       } finally {
91         indexSearcher.close();
92       }
93     } finally {
94       indexReader.close();
95       directory.close();
96     }
97   }
98
99   public void testConcurrentSpan() throws CorruptIndexException,
100       LockObtainFailedException, IOException, InvalidTokenOffsetsException {
101     final String TEXT = "the fox jumped";
102     final Directory directory = newDirectory();
103     final IndexWriter indexWriter = new IndexWriter(directory,
104         newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random, MockTokenizer.WHITESPACE, false)));
105     try {
106       final Document document = new Document();
107       document.add(new Field(FIELD, new TokenStreamConcurrent(),
108           TermVector.WITH_POSITIONS_OFFSETS));
109       indexWriter.addDocument(document);
110     } finally {
111       indexWriter.close();
112     }
113     final IndexReader indexReader = IndexReader.open(directory, true);
114     try {
115       assertEquals(1, indexReader.numDocs());
116       final IndexSearcher indexSearcher = newSearcher(indexReader);
117       try {
118         final Query phraseQuery = new SpanNearQuery(new SpanQuery[] {
119             new SpanTermQuery(new Term(FIELD, "fox")),
120             new SpanTermQuery(new Term(FIELD, "jumped")) }, 0, true);
121         final FixedBitSet bitset = new FixedBitSet(indexReader.maxDoc());
122         indexSearcher.search(phraseQuery, new Collector() {
123           private int baseDoc;
124
125           @Override
126           public boolean acceptsDocsOutOfOrder() {
127             return true;
128           }
129
130           @Override
131           public void collect(int i) throws IOException {
132             bitset.set(this.baseDoc + i);
133           }
134
135           @Override
136           public void setNextReader(IndexReader indexreader, int i)
137               throws IOException {
138             this.baseDoc = i;
139           }
140
141           @Override
142           public void setScorer(org.apache.lucene.search.Scorer scorer)
143               throws IOException {
144             // Do Nothing
145           }
146         });
147         assertEquals(1, bitset.cardinality());
148         final int maxDoc = indexReader.maxDoc();
149         final Highlighter highlighter = new Highlighter(
150             new SimpleHTMLFormatter(), new SimpleHTMLEncoder(),
151             new QueryScorer(phraseQuery));
152         for (int position = bitset.nextSetBit(0); position >= 0 && position < maxDoc-1; position = bitset
153             .nextSetBit(position + 1)) {
154           assertEquals(0, position);
155           final TokenStream tokenStream = TokenSources.getTokenStream(
156               (TermPositionVector) indexReader.getTermFreqVector(position,
157                   FIELD), false);
158           assertEquals(highlighter.getBestFragment(new TokenStreamConcurrent(),
159               TEXT), highlighter.getBestFragment(tokenStream, TEXT));
160         }
161       } finally {
162         indexSearcher.close();
163       }
164     } finally {
165       indexReader.close();
166       directory.close();
167     }
168   }
169
170   public void testSparsePhrase() throws CorruptIndexException,
171       LockObtainFailedException, IOException, InvalidTokenOffsetsException {
172     final String TEXT = "the fox did not jump";
173     final Directory directory = newDirectory();
174     final IndexWriter indexWriter = new IndexWriter(directory,
175         newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random, MockTokenizer.WHITESPACE, false)));
176     try {
177       final Document document = new Document();
178       document.add(new Field(FIELD, new TokenStreamSparse(),
179           TermVector.WITH_POSITIONS_OFFSETS));
180       indexWriter.addDocument(document);
181     } finally {
182       indexWriter.close();
183     }
184     final IndexReader indexReader = IndexReader.open(directory, true);
185     try {
186       assertEquals(1, indexReader.numDocs());
187       final IndexSearcher indexSearcher = newSearcher(indexReader);
188       try {
189         final PhraseQuery phraseQuery = new PhraseQuery();
190         phraseQuery.add(new Term(FIELD, "did"));
191         phraseQuery.add(new Term(FIELD, "jump"));
192         phraseQuery.setSlop(0);
193         TopDocs hits = indexSearcher.search(phraseQuery, 1);
194         assertEquals(0, hits.totalHits);
195         final Highlighter highlighter = new Highlighter(
196             new SimpleHTMLFormatter(), new SimpleHTMLEncoder(),
197             new QueryScorer(phraseQuery));
198         final TokenStream tokenStream = TokenSources
199             .getTokenStream((TermPositionVector) indexReader.getTermFreqVector(
200                 0, FIELD), false);
201         assertEquals(
202             highlighter.getBestFragment(new TokenStreamSparse(), TEXT),
203             highlighter.getBestFragment(tokenStream, TEXT));
204       } finally {
205         indexSearcher.close();
206       }
207     } finally {
208       indexReader.close();
209       directory.close();
210     }
211   }
212
213   public void testSparsePhraseWithNoPositions() throws CorruptIndexException,
214       LockObtainFailedException, IOException, InvalidTokenOffsetsException {
215     final String TEXT = "the fox did not jump";
216     final Directory directory = newDirectory();
217     final IndexWriter indexWriter = new IndexWriter(directory,
218         newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random, MockTokenizer.WHITESPACE, false)));
219     try {
220       final Document document = new Document();
221       document.add(new Field(FIELD, TEXT, Store.YES, Index.ANALYZED,
222           TermVector.WITH_OFFSETS));
223       indexWriter.addDocument(document);
224     } finally {
225       indexWriter.close();
226     }
227     final IndexReader indexReader = IndexReader.open(directory, true);
228     try {
229       assertEquals(1, indexReader.numDocs());
230       final IndexSearcher indexSearcher = newSearcher(indexReader);
231       try {
232         final PhraseQuery phraseQuery = new PhraseQuery();
233         phraseQuery.add(new Term(FIELD, "did"));
234         phraseQuery.add(new Term(FIELD, "jump"));
235         phraseQuery.setSlop(1);
236         TopDocs hits = indexSearcher.search(phraseQuery, 1);
237         assertEquals(1, hits.totalHits);
238         final Highlighter highlighter = new Highlighter(
239             new SimpleHTMLFormatter(), new SimpleHTMLEncoder(),
240             new QueryScorer(phraseQuery));
241         final TokenStream tokenStream = TokenSources.getTokenStream(
242             (TermPositionVector) indexReader.getTermFreqVector(0, FIELD), true);
243         assertEquals("the fox <B>did</B> not <B>jump</B>", highlighter
244             .getBestFragment(tokenStream, TEXT));
245       } finally {
246         indexSearcher.close();
247       }
248     } finally {
249       indexReader.close();
250       directory.close();
251     }
252   }
253
254   public void testSparseSpan() throws CorruptIndexException,
255       LockObtainFailedException, IOException, InvalidTokenOffsetsException {
256     final String TEXT = "the fox did not jump";
257     final Directory directory = newDirectory();
258     final IndexWriter indexWriter = new IndexWriter(directory,
259         newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random, MockTokenizer.WHITESPACE, false)));
260     try {
261       final Document document = new Document();
262       document.add(new Field(FIELD, new TokenStreamSparse(),
263           TermVector.WITH_POSITIONS_OFFSETS));
264       indexWriter.addDocument(document);
265     } finally {
266       indexWriter.close();
267     }
268     final IndexReader indexReader = IndexReader.open(directory, true);
269     try {
270       assertEquals(1, indexReader.numDocs());
271       final IndexSearcher indexSearcher = newSearcher(indexReader);
272       try {
273         final Query phraseQuery = new SpanNearQuery(new SpanQuery[] {
274             new SpanTermQuery(new Term(FIELD, "did")),
275             new SpanTermQuery(new Term(FIELD, "jump")) }, 0, true);
276
277         TopDocs hits = indexSearcher.search(phraseQuery, 1);
278         assertEquals(0, hits.totalHits);
279         final Highlighter highlighter = new Highlighter(
280             new SimpleHTMLFormatter(), new SimpleHTMLEncoder(),
281             new QueryScorer(phraseQuery));
282         final TokenStream tokenStream = TokenSources
283             .getTokenStream((TermPositionVector) indexReader.getTermFreqVector(
284                 0, FIELD), false);
285         assertEquals(
286             highlighter.getBestFragment(new TokenStreamSparse(), TEXT),
287             highlighter.getBestFragment(tokenStream, TEXT));
288       } finally {
289         indexSearcher.close();
290       }
291     } finally {
292       indexReader.close();
293       directory.close();
294     }
295   }
296
297   private static final class TokenStreamSparse extends TokenStream {
298     private Token[] tokens;
299
300     private int i = -1;
301
302     private final CharTermAttribute termAttribute = addAttribute(CharTermAttribute.class);
303     private final OffsetAttribute offsetAttribute = addAttribute(OffsetAttribute.class);
304     private final PositionIncrementAttribute positionIncrementAttribute = addAttribute(PositionIncrementAttribute.class);
305
306     public TokenStreamSparse() {
307       reset();
308     }
309
310     @Override
311     public boolean incrementToken() throws IOException {
312       this.i++;
313       if (this.i >= this.tokens.length) {
314         return false;
315       }
316       clearAttributes();
317       termAttribute.setEmpty().append(this.tokens[i]);
318       offsetAttribute.setOffset(this.tokens[i].startOffset(), this.tokens[i]
319           .endOffset());
320       positionIncrementAttribute.setPositionIncrement(this.tokens[i]
321           .getPositionIncrement());
322       return true;
323     }
324
325     @Override
326     public void reset() {
327       this.i = -1;
328       this.tokens = new Token[] {
329           new Token(new char[] { 't', 'h', 'e' }, 0, 3, 0, 3),
330           new Token(new char[] { 'f', 'o', 'x' }, 0, 3, 4, 7),
331           new Token(new char[] { 'd', 'i', 'd' }, 0, 3, 8, 11),
332           new Token(new char[] { 'j', 'u', 'm', 'p' }, 0, 4, 16, 20) };
333       this.tokens[3].setPositionIncrement(2);
334     }
335   }
336
337   private static final class TokenStreamConcurrent extends TokenStream {
338     private Token[] tokens;
339
340     private int i = -1;
341
342     private final CharTermAttribute termAttribute = addAttribute(CharTermAttribute.class);
343     private final OffsetAttribute offsetAttribute = addAttribute(OffsetAttribute.class);
344     private final PositionIncrementAttribute positionIncrementAttribute = addAttribute(PositionIncrementAttribute.class);
345
346     public TokenStreamConcurrent() {
347       reset();
348     }
349
350     @Override
351     public boolean incrementToken() throws IOException {
352       this.i++;
353       if (this.i >= this.tokens.length) {
354         return false;
355       }
356       clearAttributes();
357       termAttribute.setEmpty().append(this.tokens[i]);
358       offsetAttribute.setOffset(this.tokens[i].startOffset(), this.tokens[i]
359           .endOffset());
360       positionIncrementAttribute.setPositionIncrement(this.tokens[i]
361           .getPositionIncrement());
362       return true;
363     }
364
365     @Override
366     public void reset() {
367       this.i = -1;
368       this.tokens = new Token[] {
369           new Token(new char[] { 't', 'h', 'e' }, 0, 3, 0, 3),
370           new Token(new char[] { 'f', 'o', 'x' }, 0, 3, 4, 7),
371           new Token(new char[] { 'j', 'u', 'm', 'p' }, 0, 4, 8, 14),
372           new Token(new char[] { 'j', 'u', 'm', 'p', 'e', 'd' }, 0, 6, 8, 14) };
373       this.tokens[3].setPositionIncrement(0);
374     }
375   }
376
377 }