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