View Javadoc
1   /*
2    * The baseCode project
3    * 
4    * Copyright (c) 2013 University of British Columbia
5    * 
6    * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
7    * the License. You may obtain a copy of the License at
8    * 
9    * http://www.apache.org/licenses/LICENSE-2.0
10   * 
11   * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
12   * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
13   * specific language governing permissions and limitations under the License.
14   */
15  package ubic.basecode.ontology.search;
16  
17  import java.io.IOException;
18  import java.util.Arrays;
19  import java.util.Iterator;
20  
21  import org.apache.jena.larq.ARQLuceneException;
22  import org.apache.jena.larq.HitLARQ;
23  import org.apache.jena.larq.IndexLARQ;
24  import org.apache.jena.larq.LARQ;
25  import org.apache.lucene.analysis.Analyzer;
26  import org.apache.lucene.index.IndexReader;
27  import org.apache.lucene.index.MultiReader;
28  import org.apache.lucene.search.Filter;
29  import org.apache.lucene.search.IndexSearcher;
30  import org.apache.lucene.search.Query;
31  import org.apache.lucene.search.ScoreDoc;
32  import org.apache.lucene.search.TopDocs;
33  
34  import com.hp.hpl.jena.util.iterator.Map1;
35  import com.hp.hpl.jena.util.iterator.Map1Iterator;
36  
37  /**
38   * Customization to deal with MultiReader and 'open' while indexing is going on ...? Might not be needed.
39   * 
40   * @author  Paul
41   * 
42   */
43  public class SearchIndex extends IndexLARQ {
44  
45      public SearchIndex( IndexReader r ) {
46          super( r );
47      }
48  
49      public SearchIndex( MultiReader r, Analyzer a ) {
50          super( r, a );
51      }
52  
53      @SuppressWarnings("resource")
54      @Override
55      public Iterator<HitLARQ> search( String queryString ) {
56          try {
57              final IndexSearcher s = getIndexSearcher();
58              Query query = getLuceneQueryParser().parse( queryString );
59  
60              TopDocs topDocs = s.search( query, ( Filter ) null, LARQ.NUM_RESULTS );
61  
62              Map1<ScoreDoc, HitLARQ> converter = new Map1<ScoreDoc, HitLARQ>() {
63                  @Override
64                  public HitLARQ map1( ScoreDoc object ) {
65                      return new HitLARQ( s, object );
66                  }
67              };
68              Iterator<ScoreDoc> iterScoreDoc = Arrays.asList( topDocs.scoreDocs ).iterator();
69              Iterator<HitLARQ> iter = new Map1Iterator<>( converter, iterScoreDoc );
70  
71              return iter;
72          } catch ( Exception e ) {
73              throw new ARQLuceneException( "Error during search for '" + queryString + ";", e );
74          }
75      }
76  
77      private synchronized IndexSearcher getIndexSearcher() throws IOException {
78          if ( !reader.isCurrent() ) {
79              // this is the problematic line ... multireader cannot be reopened; was IndexReader newReader =
80              // IndexReader.openIfChanged(reader, true) ;
81  
82              IndexReader newReader = IndexReader.openIfChanged( reader );
83              if ( newReader != null ) {
84                  reader.close();
85                  reader = newReader;
86                  searcher = new IndexSearcher( reader );
87              }
88          }
89  
90          return searcher;
91      }
92  
93  }