KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jahia > services > search > SearchEngine


1 //
2
// ____.
3
// __/\ ______| |__/\. _______
4
// __ .____| | \ | +----+ \
5
// _______| /--| | | - \ _ | : - \_________
6
// \\______: :---| : : | : | \________>
7
// |__\---\_____________:______: :____|____:_____\
8
// /_____|
9
//
10
// . . . i n j a h i a w e t r u s t . . .
11
//
12
//
13
//
14
//
15

16 package org.jahia.services.search;
17
18 import org.apache.lucene.analysis.Analyzer;
19 import org.apache.lucene.document.Field;
20 import org.apache.lucene.index.IndexReader;
21 import org.apache.lucene.index.Term;
22 import org.apache.lucene.queryParser.QueryParser;
23 import org.apache.lucene.document.Document;
24 import org.apache.lucene.search.*;
25 import org.jahia.data.search.JahiaSearchResult;
26 import org.jahia.exceptions.JahiaException;
27 import org.jahia.params.ParamBean;
28 import org.jahia.registries.ServicesRegistry;
29 import org.jahia.services.fields.ContentField;
30 import org.jahia.services.search.analyzer.SearchQueryParser;
31 import org.jahia.services.version.EntryLoadRequest;
32
33 import java.util.*;
34 import java.io.IOException JavaDoc;
35
36
37 /**
38  * Search engine using Lucene.
39  *
40  * @author Khue Nguyen <a HREF="mailto:khue@jahia.org">khue@jahia.org</a>
41  */

42
43 class SearchEngine {
44
45   /**
46    * Creates an index searcher on the specified reader. The underlying reader is
47    * always closed when the <code>close()</code> method is called.
48    *
49    * @author Sergiy Shyrkov
50    */

51   private class ClosableIndexSearcher extends IndexSearcher
52   {
53     private IndexReader indexReader;
54
55     /**
56      * Initializes an instance of this class.
57      *
58      * @param reader the underlying index reader
59      */

60     protected ClosableIndexSearcher(IndexReader reader)
61     {
62       super(reader);
63       indexReader = reader;
64     }
65
66     /*
67      * (non-Javadoc)
68      *
69      * @see org.apache.lucene.search.IndexSearcher#close()
70      */

71     public void close() throws IOException JavaDoc
72     {
73       indexReader.close();
74     }
75   }
76
77     private static org.apache.log4j.Logger logger =
78             org.apache.log4j.Logger.getLogger (SearchEngine.class);
79
80     private Analyzer analyzer;
81
82     private boolean doAutoAppendWildcards;
83
84     /**
85      * Constructor
86      *
87      * @param theAnalyzer the analyzer.
88      * @param autoAppendWildcards append wildcards to each search term?
89      */

90     public SearchEngine (Analyzer theAnalyzer, IndexReader reader) {
91         analyzer = theAnalyzer;
92         doAutoAppendWildcards = false;
93     }
94
95     //--------------------------------------------------------------------------
96
/**
97      * Return a vector of matching pages.
98      * Perform a search for a given query ( valid lucene query ).
99      *
100      * @param JahiaSearcher jSearcher, the jahia searcher.
101      * @param ParamBean jParams, the param bean.
102      *
103      * @return JahiaSearchResult result, the search result as an JahiaSearchResult object.
104      */

105     public JahiaSearchResult doPageSearch (JahiaSearcher jSearcher,
106                                            ParamBean jParams)
107             throws JahiaException {
108         logger.info ("Started");
109
110         JahiaSearchResultHandlerImpl jahiaSearchResultHandler
111             = new JahiaSearchResultHandlerImpl();
112
113         JahiaSearchResult result = new JahiaSearchResult (new JahiaSearchResultHandlerImpl());
114         
115         MultiSearcher multiSearcher = null;
116
117         if ( jSearcher == null || jSearcher.getQuery () == null)
118             return result;
119
120         try {
121
122             QueryParser parser = new SearchQueryParser(JahiaSearchConstant.FIELD_TEXT,
123               analyzer, doAutoAppendWildcards);
124             parser.setOperator(QueryParser.DEFAULT_OPERATOR_AND);
125   
126             BooleanQuery resultQuery = new BooleanQuery();
127             resultQuery.add(parser.parse(jSearcher.getQuery()), true, false);
128             appendLanguageAndStateQuery(resultQuery, jSearcher, jParams);
129
130             int[] siteIds = jSearcher.getSiteIds();
131             ArrayList sites = new ArrayList(siteIds.length);
132             for ( int i=0; i<siteIds.length; i++ ){
133                 sites.add(new Integer JavaDoc(siteIds[i]));
134             }
135
136             multiSearcher = this.getSearcher(sites);
137
138             // get the search result.
139
Hits hits = null;
140             if ( multiSearcher != null ){
141                 hits = multiSearcher.search(resultQuery);
142             }
143             
144             List parsedObjects = getParsedObjects(hits);
145             if ( parsedObjects == null ){
146                 parsedObjects = Collections.EMPTY_LIST;
147             }
148             result = jahiaSearchResultHandler.buildResult(parsedObjects, jParams);
149
150         } catch (Throwable JavaDoc t) {
151             logger.error (t);
152         } finally {
153           closeSearcher(multiSearcher);
154         }
155         return result;
156     }
157
158     //--------------------------------------------------------------------------
159
/**
160      * Return a vector of matching containers.
161      *
162      * @param JahiaSearcher jSearcher, the jahia searcher.
163      * @param ParamBean jParams, the param bean.
164      *
165      * @return JahiaSearchResult result, the search result as an JahiaSearchResult object.
166      */

167     public JahiaSearchResult doContainerSearch (JahiaSearcher jSearcher,
168                                                 ParamBean jParams)
169             throws JahiaException {
170         logger.debug ("Started");
171
172         JahiaSearchResultHandlerImpl jahiaSearchResultHandler
173             = new JahiaSearchResultHandlerImpl();
174
175         JahiaSearchResult result = new JahiaSearchResult (jahiaSearchResultHandler);
176
177         if (jSearcher == null || jSearcher.getQuery () == null)
178             return result;
179         
180         MultiSearcher multiSearcher = null;
181
182         try {
183
184             ContainerSearcher cSearcher = (ContainerSearcher) jSearcher;
185
186             ServicesRegistry sReg = ServicesRegistry.getInstance ();
187
188             //SCSE: bug fix NOV0095: use AND as the default conjunction operator
189
QueryParser parser = new SearchQueryParser(JahiaSearchConstant.FIELD_TEXT,
190               analyzer, doAutoAppendWildcards);
191             parser.setOperator(QueryParser.DEFAULT_OPERATOR_AND);
192
193             BooleanQuery resultQuery = new BooleanQuery();
194             resultQuery.add(parser.parse(cSearcher.getQuery()), true, false);
195             appendLanguageAndStateQuery(resultQuery, jSearcher, jParams);
196
197             if (!cSearcher.isSiteModeSearching ()) {
198                 // restric result to containers of the ctnlist.
199
// get container list containers.
200
List ctnids = sReg.getJahiaContainersService ().getctnidsInList (
201                         cSearcher.getCtnListID (), jParams.getEntryLoadRequest ());
202                 if (ctnids.size () == 0)
203                     return result;
204                 
205                 BooleanQuery containerQuery = new BooleanQuery();
206                 for (Iterator iter = ctnids.iterator(); iter.hasNext();)
207                 {
208                   containerQuery.add(new TermQuery(new Term(
209                     JahiaSearchConstant.FIELD_CTNID, iter.next().toString())), false,
210                     false);
211                 }
212                 
213                 resultQuery.add(containerQuery, true, false);
214             } else {
215
216                 if (cSearcher.getSiteId () != -1) {
217                   resultQuery.add(new TermQuery(new Term(
218                     JahiaSearchConstant.FIELD_JAHIAID, String.valueOf(cSearcher
219                       .getSiteId()))), true, false);
220                 }
221
222                 if (cSearcher.getContainerDefinitionName () != null
223                         && !"".equals (cSearcher.getContainerDefinitionName().trim ())) {
224                   resultQuery.add(new TermQuery(new Term(
225                     JahiaSearchConstant.CONTAINER_DEFINITION_NAME, cSearcher
226                       .getContainerDefinitionName().toLowerCase())), true, false);
227                 }
228             }
229             
230             if (logger.isDebugEnabled())
231             {
232               logger.debug ("Query is: " + resultQuery.toString());
233             }
234
235             ArrayList sites = new ArrayList(cSearcher.isSiteModeSearching()
236               ? cSearcher.getSiteIds().length : 1);
237             if ( cSearcher.isSiteModeSearching() ){
238                 int[] siteIds = cSearcher.getSiteIds();
239                 for ( int i=0; i<siteIds.length; i++ ){
240                     sites.add(new Integer JavaDoc(siteIds[i]));
241                 }
242             } else {
243                 sites.add(new Integer JavaDoc(jParams.getJahiaID()));
244             }
245
246             multiSearcher = this.getSearcher(sites);
247
248             // get the search result.
249
Hits hits = null;
250             if ( multiSearcher != null ){
251                 hits = multiSearcher.search(resultQuery);
252             }
253
254             if (hits == null || hits.length () == 0)
255                 return result;
256
257             logger.debug ("lucene result : " + hits.length ());
258
259             Vector parsedObjects = getParsedObjects(hits);
260             if ( parsedObjects == null ){
261                 parsedObjects = new Vector();
262             }
263             result = jahiaSearchResultHandler.buildContainerSearchResult(parsedObjects, true, jParams);
264
265             logger.debug ("jahia result : " + result.getHitCount ());
266
267         } catch (Throwable JavaDoc t) {
268             logger.error (t);
269         } finally {
270           closeSearcher(multiSearcher);
271         }
272         return result;
273     }
274
275     private MultiSearcher getSearcher(ArrayList sites) throws IOException JavaDoc, JahiaException {
276
277         JahiaSearchService sServ = ServicesRegistry.getInstance().getJahiaSearchService();
278         Searchable searcher = null;
279         RAMIndexer ramIndexer = sServ.getRAMIndexer();
280         ArrayList searchables = new ArrayList(ramIndexer != null ? sites.size() * 2
281           : sites.size());
282         Integer JavaDoc I = null;
283         IndexReader reader = null;
284         for ( int i=0; i<sites.size(); i++ ){
285             I = (Integer JavaDoc)sites.get(i);
286             reader = sServ.getIndexReader(I.intValue());
287             if (reader != null)
288             {
289               searcher = new ClosableIndexSearcher(reader);
290               searchables.add(searcher);
291             }
292             if ( ramIndexer != null ){
293                 searcher = ramIndexer.getSearcher(I.intValue());
294                 if ( searcher != null ){
295                     searchables.add(searcher);
296                 }
297             }
298         }
299         
300         if (searchables.size() == 0)
301           return null;
302         
303         Searchable[] searchablesAr = new Searchable[searchables.size()];
304         searchables.toArray(searchablesAr);
305         return new MultiSearcher(searchablesAr);
306     }
307
308     /**
309      * Appends multilanguage and staging conditions to query.
310      *
311      * @param query the search query
312      * @param jSearcher
313      * @param jParams
314      */

315     private void appendLanguageAndStateQuery(BooleanQuery query, JahiaSearcher jSearcher, ParamBean jParams) {
316
317       EntryLoadRequest elr = jParams.getEntryLoadRequest();
318       if (elr.isCurrent())
319       {
320         query.add(new TermQuery(new Term(
321           JahiaSearchConstant.FIELD_WORKFLOW_STATE, String
322             .valueOf(EntryLoadRequest.ACTIVE_WORKFLOW_STATE))), true, false);
323       }
324   
325       if (!jSearcher.getLanguageCodes().isEmpty())
326       {
327         // search on specific lang
328
BooleanQuery languageQuery = new BooleanQuery();
329         languageQuery.add(
330           new TermQuery(new Term(JahiaSearchConstant.FIELD_LANGUAGE_CODE,
331             ContentField.SHARED_LANGUAGE)), false, false);
332   
333         Set lngSet = new HashSet();
334         lngSet.add(ContentField.SHARED_LANGUAGE);
335   
336         for (Iterator iter = jSearcher.getLanguageCodes().iterator(); iter
337           .hasNext();)
338         {
339           String JavaDoc lng = (String JavaDoc)iter.next();
340           if (!lngSet.contains(lng))
341           {
342             languageQuery.add(new TermQuery(new Term(
343               JahiaSearchConstant.FIELD_LANGUAGE_CODE, lng)), false, false);
344             lngSet.add(lng);
345           }
346         }
347   
348         query.add(languageQuery, true, false);
349       }
350     }
351
352     /**
353      *
354      * @param hits Hits
355      * @return Vector
356      */

357     private Vector getParsedObjects(Hits hits) throws Exception JavaDoc {
358        Vector parsedObjects = new Vector();
359        if ( hits == null || hits.length()==0 ){
360            return parsedObjects;
361        }
362        int size = hits.length();
363        for ( int i=0; i<size; i++ ){
364            ParsedObjectImpl parsedObject = new ParsedObjectImpl();
365            Hashtable map = new Hashtable();
366            Document doc = hits.doc(i);
367            Enumeration fields = doc.fields();
368            Field field = null;
369            String JavaDoc name = null;
370            while ( fields.hasMoreElements() ){
371                field = (Field)fields.nextElement();
372                name = field.name();
373                if ( !map.contains(name) ){
374                    map.put(name, doc.getValues(name));
375                }
376            }
377            parsedObject.setFields(map);
378            parsedObject.setScore(hits.score(i));
379            parsedObjects.add(parsedObject);
380        }
381        return parsedObjects;
382     }
383     
384     private void closeSearcher(MultiSearcher searcher)
385     {
386       if (searcher != null)
387       {
388         try
389         {
390           searcher.close();
391         }
392         catch (IOException JavaDoc ex)
393         {
394           logger.debug("Error closing searcher", ex);
395         }
396       }
397     }
398 }
399
Popular Tags