KickJava   Java API By Example, From Geeks To Geeks.

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


1 package org.jahia.services.search;
2
3 import org.jahia.exceptions.JahiaException;
4 import org.jahia.data.search.JahiaSearchResult;
5 import org.jahia.data.search.JahiaSearchHit;
6 import org.jahia.params.ParamBean;
7
8 import java.util.*;
9
10 /**
11  *
12  */

13 public class ChainedJahiaSearcher extends JahiaSearcher
14 {
15
16     private static org.apache.log4j.Logger logger =
17             org.apache.log4j.Logger.getLogger (ChainedJahiaSearcher.class);
18
19     private static String JavaDoc CHAINED_JAHIA_SEARCHER = "chainedJahiaSearcher";
20
21     private String JavaDoc name = CHAINED_JAHIA_SEARCHER;
22
23     /**
24      * {@link java.util.BitSet#or}.
25      */

26     public static final int OR = 0;
27
28     /**
29      * {@link java.util.BitSet#and}.
30      */

31     public static final int AND = 1;
32
33     /**
34      * {@link java.util.BitSet#andNot}.
35      */

36     public static final int ANDNOT = 2;
37
38     /**
39      * {@link java.util.BitSet#xor}.
40      */

41     public static final int XOR = 3;
42
43     /**
44      * Logical operation when none is declared. Defaults to
45      * {@link java.util.BitSet#or}.
46      */

47     public static int DEFAULT = OR;
48
49     /** The searcher chain */
50     private JahiaSearcher[] chain = null;
51
52     private int[] logicArray;
53
54     private int logic = -1;
55
56     /**
57      * Ctor.
58      * @param chain The chain of filters
59      */

60     public ChainedJahiaSearcher(JahiaSearcher[] chain)
61     {
62         this.chain = chain;
63     }
64
65     /**
66      * Ctor.
67      * @param chain The chain of filters
68      * @param logicArray Logical operations to apply between filters
69      */

70     public ChainedJahiaSearcher(JahiaSearcher[] chain, int[] logicArray)
71     {
72         this.chain = chain;
73         this.logicArray = logicArray;
74     }
75
76     /**
77      * Ctor.
78      * @param chain The chain of filters
79      * @param logic Logicial operation to apply to ALL filters
80      */

81     public ChainedJahiaSearcher(JahiaSearcher[] chain, int logic)
82     {
83         this.chain = chain;
84         this.logic = logic;
85     }
86
87
88     /**
89      * Return the array of sites on which to perform search.
90      * Actually, returns the values of the first searcher in the chain.
91      *
92      * @return
93      */

94     public int[] getSiteIds (){
95         int[] siteIds = new int[]{};
96         if ( this.chain.length>0 ){
97             siteIds = ((JahiaSearcher)this.chain[0]).getSiteIds();
98         }
99         return siteIds;
100     }
101
102     public String JavaDoc getName (){
103         return this.name;
104     }
105
106     //--------------------------------------------------------------------------
107
/**
108      * Perform the search for a given query as String.
109      * Return the results as a Object instance.
110      *
111      * @param query a valid query.
112      * @param jParams the param bean.
113      *
114      * @return JahiaSearchResult result.
115      */

116     public JahiaSearchResult search (String JavaDoc query, ParamBean jParams)
117     throws JahiaException{
118
119         // Must set the query first.
120
setQuery (query);
121
122         JahiaSearchResult result = this.bits(jParams);
123
124         this.setResult(result);
125         return (JahiaSearchResult)this.getResult();
126     }
127
128     public JahiaSearcher[] getChain() {
129         return chain;
130     }
131
132     public void setChain(JahiaSearcher[] chain) {
133         this.chain = chain;
134     }
135
136
137     //--------------------------------------------------------------------------
138
/**
139      * @return the list of languages code to search.
140      * Actually return the array of the first searcher in the chain
141      */

142     public ArrayList getLanguageCodes (){
143         ArrayList langCodes = new ArrayList();
144         if ( this.chain.length>0 ){
145             langCodes = ((JahiaSearcher)this.chain[0]).getLanguageCodes();
146         }
147         return langCodes;
148     }
149
150     public String JavaDoc getQuery() {
151         if ( chain == null ){
152             return "";
153         }
154         StringBuffer JavaDoc buff = new StringBuffer JavaDoc();
155         JahiaSearcher searcher = null;
156         String JavaDoc val = "";
157         for ( int i=0; i<chain.length; i++ ){
158             searcher = (JahiaSearcher)chain[i];
159             val = searcher.getQuery();
160             if ( val != null ){
161                 if (i > 0) {
162                     int logop = (this.logic != -1) ? this.logic :
163                                 this.logicArray[i-1];
164                     switch (logop) {
165                         case OR:
166                             buff.append(" UNION ");
167                             break;
168                         case AND:
169                             buff.append(" INTERSECT ");
170                             break;
171                         case XOR:
172                             buff.append(" XOR "); //probably not supported in SQL but this SQL statement is not executed anyway, just used as ID for caching
173
break;
174                         case ANDNOT:
175                             buff.append(" ANDNOT "); //probably not supported in SQL but this SQL statement is not executed anyway, just used as ID for caching
176
break;
177                         default:
178                             buff.append(" DEFAULT_OPERATOR ");//probably not supported in SQL but this SQL statement is not executed anyway, just used as ID for caching
179
break;
180                     }
181                 }
182
183                 buff.append(val);
184             }
185         }
186         return buff.toString();
187     }
188
189     private JahiaSearchResult bits(ParamBean jParams) throws JahiaException
190     {
191         if (logic != -1)
192             return bitsFromLogic(logic, jParams);
193         else if (logicArray != null)
194             return bits(logicArray, jParams);
195         else
196             return bitsFromLogic(DEFAULT, jParams);
197     }
198
199     /**
200      * Delegates to each filter in the chain.
201      * @param logic Logical operation
202      * @return JahiaSearchResult
203      */

204     private JahiaSearchResult bitsFromLogic(int logic, ParamBean jParams)
205     throws JahiaException {
206         JahiaSearchResult result;
207         int i = 0;
208
209         /**
210          * First AND operation takes place against a completely false
211          * bitset and will always return zero results. Thanks to
212          * Daniel Armbrust for pointing this out and suggesting workaround.
213          */

214
215         if (logic == AND)
216         {
217             result = (JahiaSearchResult) chain[i].search(chain[i].getQuery(),jParams);
218             ++i;
219         }
220         else
221         {
222             result = new JahiaSearchResult(new JahiaSearchResultHandlerImpl());
223         }
224
225         HashMap hitsMap = new HashMap();
226         JahiaSearchHit hit = null;
227         Vector hits = result.results();
228         Vector v = null;
229         int size = hits.size();
230         for ( i=0; i<size; i++ ){
231             hit = (JahiaSearchHit)hits.get(i);
232             v = (Vector) hitsMap.get(new Integer JavaDoc(hit.id));
233             if ( v == null ){
234                 v = new Vector();
235                 hitsMap.put(new Integer JavaDoc(hit.id),v);
236             }
237             v.add(hit);
238         }
239
240         i=0;
241         for (; i < chain.length; i++)
242         {
243             doChain(hitsMap, logic, chain[i], jParams);
244         }
245
246         return buildResultFromHitsMap(hitsMap);
247     }
248
249     /**
250      * Delegates to each filter in the chain.
251      * @param logic Logical operation
252      * @return JahiaSearchResult
253      */

254     private JahiaSearchResult bits(int[] logic, ParamBean jParams)
255     throws JahiaException {
256         if (logic.length < chain.length-1)
257             throw new IllegalArgumentException JavaDoc("Invalid number of elements in logic array");
258
259         JahiaSearchResult result = chain[0].search(chain[0].getQuery(),jParams);
260
261         HashMap hitsMap = new HashMap();
262         JahiaSearchHit hit = null;
263         Vector hits = result.results();
264         Vector v = null;
265         int size = hits.size();
266         for ( int i=0; i<size; i++ ){
267             hit = (JahiaSearchHit)hits.get(i);
268             v = (Vector) hitsMap.get(new Integer JavaDoc(hit.id));
269             if ( v == null ){
270                 v = new Vector();
271                 hitsMap.put(new Integer JavaDoc(hit.id),v);
272             }
273             v.add(hit);
274         }
275
276         for (int i=1; i < chain.length; i++)
277         {
278             doChain(hitsMap, logic[i-1], chain[i], jParams);
279         }
280         return buildResultFromHitsMap(hitsMap);
281     }
282
283     private JahiaSearchResult buildResultFromHitsMap(HashMap hitsMap){
284         JahiaSearchResult result = new JahiaSearchResult(new JahiaSearchResultHandlerImpl());
285         Iterator iterator = hitsMap.values().iterator();
286         Vector v = null;
287         Vector parsedObjects = new Vector();
288         JahiaSearchHit hit = null;
289         JahiaSearchHit hit2 = null;
290         while ( iterator.hasNext() ){
291             v = (Vector)iterator.next();
292             hit = null;
293             for ( int i=0; i<v.size(); i++ ){
294                 hit2 = (JahiaSearchHit)v.get(i);
295                 if ( hit == null || hit.getScore()<hit2.getScore() ){
296                     hit = hit2;
297                 }
298             }
299             parsedObjects.add(hit.getParsedObject());
300             result.addHit(hit);
301         }
302         result.setParsedObjects(parsedObjects);
303         result.pages = result.results();
304         result.pagecount = result.getHitCount();
305
306         return result;
307     }
308
309     private void doChain(HashMap hitsMap, int logic, JahiaSearcher searcher,
310                          ParamBean jParams) throws JahiaException
311     {
312         switch (logic)
313         {
314             case OR:
315                 mergeResults(hitsMap, logic, searcher, jParams);
316                 break;
317             case AND:
318                 mergeResults(hitsMap, logic, searcher, jParams);
319                 break;
320             case ANDNOT:
321                 mergeResults(hitsMap, logic, searcher, jParams);
322                 break;
323             case XOR:
324                 mergeResults(hitsMap, logic, searcher, jParams);
325                 break;
326             default:
327                 doChain(hitsMap, DEFAULT, searcher, jParams);
328                 break;
329         }
330     }
331
332     private void mergeResults(HashMap hitsMap, int logic,
333                               JahiaSearcher searcher, ParamBean jParams)
334     throws JahiaException {
335
336         JahiaSearchResult result = new JahiaSearchResult(new JahiaSearchResultHandlerImpl());
337
338         JahiaSearchResult result2 = searcher.search(searcher.getQuery(),jParams);
339         Vector hits2 = null;
340         JahiaSearchHit newHit = null;
341         int size = 0;
342
343         hits2 = result2.results();
344         Vector v = null;
345         size = hits2.size();
346
347         for( int i=0; i<size; i++ ){
348             newHit = (JahiaSearchHit)hits2.get(i);
349             v = (Vector)hitsMap.get(new Integer JavaDoc(newHit.id));
350             switch (logic)
351             {
352                 case OR:
353                     if ( v == null ){
354                         v = new Vector();
355                         hitsMap.put(new Integer JavaDoc(newHit.id),v);
356                     }
357                     v.add(newHit);
358                     break;
359                 case AND:
360                     if ( v != null ){
361                         v.add(newHit);
362                     }
363                     break;
364                 case ANDNOT:
365                     newHit = (JahiaSearchHit)hits2.get(i);
366                     hitsMap.remove(new Integer JavaDoc(newHit.id));
367                     break;
368                 case XOR:
369                     newHit = (JahiaSearchHit)hits2.get(i);
370                     if ( hitsMap.containsKey(new Integer JavaDoc(newHit.id)) ){
371                         hitsMap.remove(new Integer JavaDoc(newHit.id));
372                     }
373                     break;
374             }
375         }
376
377         if ( logic == AND ){
378             Iterator iterator = hitsMap.keySet().iterator();
379             Integer JavaDoc I = null;
380             v = new Vector();
381             while ( iterator.hasNext() ){
382                 I = (Integer JavaDoc)iterator.next();
383                 if ( !result2.bits().get(I.intValue()) ){
384                     v.add(I);
385                 }
386             }
387             Enumeration col = v.elements();
388             while ( col.hasMoreElements() ){
389                 I = (Integer JavaDoc)col.nextElement();
390                 hitsMap.remove(I);
391             }
392         }
393     }
394
395     public String JavaDoc toString()
396     {
397         StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
398         sb.append("ChainedJahiaSearcher: [");
399         for (int i = 0; i < chain.length; i++)
400         {
401             if (i>0) {
402                 int logop = (this.logic != -1) ? this.logic : this.logicArray[i-1] ;
403                 switch (logop) {
404                     case OR:
405                         sb.append(" OR ");
406                         break;
407                     case AND:
408                         sb.append(" AND ");
409                         break;
410                     case XOR:
411                         sb.append(" XOR ");
412                         break;
413                     case ANDNOT:
414                         sb.append(" XOR ");
415                         break;
416                     default:
417                         sb.append(" OR ");
418                         break;
419                 }
420             }
421             sb.append(chain[i]);
422             sb.append(' ');
423         }
424         sb.append(']');
425         return sb.toString();
426     }
427
428
429 }
430
Popular Tags