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