Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
Engine |
|
| 3.1;3.1 |
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 | 0 | 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 | 0 | 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 | 0 | indexPath = _indexPath; |
71 | 0 | } |
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 | 0 | if (string==null) return BLANK_STRING; |
91 | 0 | 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 | 0 | 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 | 0 | return new IndexSearcher(getIndexPath()); |
119 | ||
120 | } | |
121 | 0 | catch (IOException e) { |
122 | 0 | 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 | 0 | return (new IndexWriter(getIndexPath(), |
141 | getAnalyzer(),create)); | |
142 | ||
143 | } | |
144 | 0 | catch (IOException e) { |
145 | 0 | 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 | 0 | return (IndexReader.open(getIndexPath())); |
163 | ||
164 | } | |
165 | 0 | catch (IOException e) { |
166 | 0 | 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 | 0 | return getSearcher().search(query); |
184 | ||
185 | } | |
186 | 0 | catch (IOException e) { |
187 | 0 | 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 | 0 | return QueryParser.parse(value,field, getAnalyzer()); |
207 | ||
208 | } | |
209 | 0 | catch (ParseException e) { |
210 | 0 | throw new ParameterException(e); |
211 | } | |
212 | ||
213 | } // end getQuery() | |
214 | ||
215 | ||
216 | /** | |
217 | * Object for synchronizing deletions to index | |
218 | */ | |
219 | 0 | 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 | 0 | int result = 0; |
233 | 0 | synchronized (INDEX_LOCK) { |
234 | 0 | IndexReader reader = null; |
235 | try { | |
236 | 0 | reader = getIndexReader(); |
237 | 0 | result = reader.delete(term); |
238 | } | |
239 | 0 | catch (IOException e) { |
240 | 0 | throw new ResourceException(e); |
241 | } | |
242 | finally { | |
243 | 0 | try { |
244 | 0 | if (reader!=null) reader.close(); |
245 | } | |
246 | 0 | catch (IOException e) { |
247 | // do nothing | |
248 | 0 | } |
249 | 0 | } |
250 | 0 | } |
251 | 0 | return result; |
252 | ||
253 | } // end deleteTerm() | |
254 | ||
255 | ||
256 | } // end Engine | |
257 |