View Javadoc

1   /*
2    * Copyright 2001,2004 The Apache Software Foundation.
3    * 
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * 
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    * 
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package org.apache.commons.scaffold.lucene;
18  
19  
20  import java.io.IOException;
21  
22  import org.apache.commons.scaffold.lang.ParameterException;
23  import org.apache.commons.scaffold.lang.ResourceException;
24  
25  import org.apache.lucene.analysis.Analyzer;
26  import org.apache.lucene.analysis.StopAnalyzer;
27  import org.apache.lucene.index.IndexReader;
28  import org.apache.lucene.index.IndexWriter;
29  import org.apache.lucene.index.Term;
30  import org.apache.lucene.queryParser.ParseException;
31  import org.apache.lucene.queryParser.QueryParser;
32  import org.apache.lucene.search.Hits;
33  import org.apache.lucene.search.IndexSearcher;
34  import org.apache.lucene.search.Query;
35  import org.apache.lucene.search.Searcher;
36  
37  
38  /**
39   * Search engine methods for Lucene.
40   *
41   * @author Ted Husted
42   * @version $Revision: 155464 $ $Date: 2005-02-26 13:26:54 +0000 (Sat, 26 Feb 2005) $
43   * @todo Make singleton instead of static
44   */
45  public final class Engine {
46  
47  
48      /**
49       * Default path for index ["/var/lucene/scaffold"].
50       * Use the <code>setIndexPath</code> method on startup
51       * to change.
52       * Each application needs its own index path.
53       */
54      private static String indexPath;
55  
56  
57      /**
58       * Return path for index.
59       */
60      public static String getIndexPath() {
61          return indexPath;
62      }
63  
64  
65      /**
66       * Set path for index.
67       * MUST be set at startup before using other methods.
68       */
69      public static void init(String _indexPath) {
70          indexPath = _indexPath;
71      }
72  
73  
74      /**
75       * Performance optimization to ensure JVM doesn't
76       * create a new empty string whenever blankNull
77       * needs one.
78       */
79      private static final String BLANK_STRING = "";
80  
81  
82      /**
83       * Convenience method to use an empty string in place
84       * of a null for indexing.
85       *
86       * @param string The string to test for null
87       * @return A blank String [BLANK_STRING] if string is null
88       */
89      public static final String blankNull(String string) {
90          if (string==null) return BLANK_STRING;
91          else return string;
92      }
93  
94  
95      /**
96       * Return default analyzer for application
97       * A non-English site should use a different analyzer
98       *
99       * @return The default analyzer
100      * @exception Throws ResourceException on IO error
101      */
102     public static final Analyzer getAnalyzer() {
103         return new StopAnalyzer();
104     }
105 
106 
107     /**
108      * Return default searcher for application.
109      *
110      * @exception Throws ResourceException on IO error
111      * @return default searcher
112      */
113     public static final Searcher getSearcher()
114             throws ResourceException {
115 
116         try {
117 
118             return new IndexSearcher(getIndexPath());
119 
120         }
121         catch (IOException e) {
122             throw new ResourceException(e);
123         }
124 
125     } // end getSearcher()
126 
127 
128     /**
129      * Return default writer for application.
130      *
131      * @param Set to true to create a new index; usually false.
132      * @return default writer
133      * @exception Throws ResourceException on IO error
134      */
135     public static final IndexWriter getIndexWriter(boolean create)
136         throws ResourceException {
137 
138         try {
139 
140             return (new IndexWriter(getIndexPath(),
141                 getAnalyzer(),create));
142 
143         }
144         catch (IOException e) {
145             throw new ResourceException(e);
146         }
147 
148     } // end getIndexWriter()
149 
150 
151     /**
152      * Return default reader for application.
153      *
154      * @return default reader
155      * @exception Throws ResourceException on IO error
156      */
157     public static final IndexReader getIndexReader()
158         throws ResourceException {
159 
160         try {
161 
162             return (IndexReader.open(getIndexPath()));
163 
164         }
165         catch (IOException e) {
166             throw new ResourceException(e);
167         }
168 
169     } // end getIndexReader()
170 
171 
172     /**
173      * Return hits for model using default searcher.
174      *
175      * @return hits for model
176      * @param query The query we are processing
177      */
178     public static final Hits getHits(Query query)
179         throws ResourceException {
180 
181         try {
182 
183             return getSearcher().search(query);
184 
185         }
186         catch (IOException e) {
187             throw new ResourceException(e);
188         }
189 
190     } // end getHits()
191 
192 
193     /**
194      * Return hits for value and field
195      *
196      * @param value The term to match ("Smith")
197      * @param field The field to patch ("name")
198      * @return hits for model
199      */
200     public static final Query getQuery(
201             String value,
202             String field) throws ParameterException {
203 
204         try {
205 
206             return QueryParser.parse(value,field, getAnalyzer());
207 
208         }
209         catch (ParseException e) {
210             throw new ParameterException(e);
211         }
212 
213     } // end getQuery()
214 
215 
216     /**
217      * Object for synchronizing deletions to index
218      */
219     private static final Object INDEX_LOCK = new Object();
220 
221 
222     /**
223      * Delete record matching term from default index.
224      * Access to the index is synchronized.
225      *
226      * @param term The term matching the entry to delete
227      * @exception Throws ResourceException on IO error
228      */
229     public static final int deleteTerm(Term term)
230         throws ResourceException {
231 
232         int result = 0;
233         synchronized (INDEX_LOCK) {
234             IndexReader reader = null;
235             try {
236                 reader = getIndexReader();
237                 result = reader.delete(term);
238             }
239             catch (IOException e) {
240                 throw new ResourceException(e);
241             }
242             finally {
243                 try {
244                     if (reader!=null) reader.close();
245                 }
246                 catch (IOException e) {
247                 // do nothing
248                 }
249             }
250         }
251         return result;
252 
253     } // end deleteTerm()
254 
255 
256 } // end Engine
257