001 /*
002 * Copyright 2001,2004 The Apache Software Foundation.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017 package org.apache.commons.scaffold.lucene;
018
019
020 import java.io.IOException;
021
022 import org.apache.commons.scaffold.lang.ParameterException;
023 import org.apache.commons.scaffold.lang.ResourceException;
024
025 import org.apache.lucene.analysis.Analyzer;
026 import org.apache.lucene.analysis.StopAnalyzer;
027 import org.apache.lucene.index.IndexReader;
028 import org.apache.lucene.index.IndexWriter;
029 import org.apache.lucene.index.Term;
030 import org.apache.lucene.queryParser.ParseException;
031 import org.apache.lucene.queryParser.QueryParser;
032 import org.apache.lucene.search.Hits;
033 import org.apache.lucene.search.IndexSearcher;
034 import org.apache.lucene.search.Query;
035 import org.apache.lucene.search.Searcher;
036
037
038 /**
039 * Search engine methods for Lucene.
040 *
041 * @author Ted Husted
042 * @version $Revision: 155464 $ $Date: 2005-02-26 13:26:54 +0000 (Sat, 26 Feb 2005) $
043 * @todo Make singleton instead of static
044 */
045 public final class Engine {
046
047
048 /**
049 * Default path for index ["/var/lucene/scaffold"].
050 * Use the <code>setIndexPath</code> method on startup
051 * to change.
052 * Each application needs its own index path.
053 */
054 private static String indexPath;
055
056
057 /**
058 * Return path for index.
059 */
060 public static String getIndexPath() {
061 return indexPath;
062 }
063
064
065 /**
066 * Set path for index.
067 * MUST be set at startup before using other methods.
068 */
069 public static void init(String _indexPath) {
070 indexPath = _indexPath;
071 }
072
073
074 /**
075 * Performance optimization to ensure JVM doesn't
076 * create a new empty string whenever blankNull
077 * needs one.
078 */
079 private static final String BLANK_STRING = "";
080
081
082 /**
083 * Convenience method to use an empty string in place
084 * of a null for indexing.
085 *
086 * @param string The string to test for null
087 * @return A blank String [BLANK_STRING] if string is null
088 */
089 public static final String blankNull(String string) {
090 if (string==null) return BLANK_STRING;
091 else return string;
092 }
093
094
095 /**
096 * Return default analyzer for application
097 * A non-English site should use a different analyzer
098 *
099 * @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