KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > columba > mail > folder > search > DefaultSearchEngine


1 //The contents of this file are subject to the Mozilla Public License Version 1.1
2
//(the "License"); you may not use this file except in compliance with the
3
//License. You may obtain a copy of the License at http://www.mozilla.org/MPL/
4
//
5
//Software distributed under the License is distributed on an "AS IS" basis,
6
//WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
7
//for the specific language governing rights and
8
//limitations under the License.
9
//
10
//The Original Code is "The Columba Project"
11
//
12
//The Initial Developers of the Original Code are Frederik Dietz and Timo Stich.
13
//Portions created by Frederik Dietz and Timo Stich are Copyright (C) 2003.
14
//
15
//All Rights Reserved.
16

17 package org.columba.mail.folder.search;
18
19 import java.util.Arrays JavaDoc;
20 import java.util.Hashtable JavaDoc;
21 import java.util.LinkedList JavaDoc;
22 import java.util.List JavaDoc;
23 import java.util.ListIterator JavaDoc;
24 import java.util.logging.Logger JavaDoc;
25
26 import javax.swing.JOptionPane JavaDoc;
27
28 import org.columba.api.command.IStatusObservable;
29 import org.columba.api.plugin.IExtension;
30 import org.columba.api.plugin.IExtensionHandler;
31 import org.columba.core.base.ListTools;
32 import org.columba.core.filter.AbstractFilter;
33 import org.columba.core.filter.Filter;
34 import org.columba.core.filter.FilterCriteria;
35 import org.columba.core.filter.FilterRule;
36 import org.columba.core.filter.IFilter;
37 import org.columba.core.filter.IFilterCriteria;
38 import org.columba.core.filter.IFilterRule;
39 import org.columba.core.plugin.PluginManager;
40 import org.columba.mail.folder.AbstractMessageFolder;
41 import org.columba.mail.folder.event.FolderListener;
42 import org.columba.mail.folder.event.IFolderEvent;
43 import org.columba.mail.plugin.IExtensionHandlerKeys;
44 import org.columba.mail.util.MailResourceLoader;
45
46 /**
47  * Divides search requests and passes them along to the optimized
48  * {@link QueryEngine} for execution.
49  * <p>
50  * Search requests which can't be performed by the {@link QueryEngine}, are
51  * executed by DefaultSearchEngine using the plugin mechanism.
52  *
53  * @author tstich, fdietz
54  */

55 public class DefaultSearchEngine {
56     /** JDK 1.4+ logging framework logger, used for logging. */
57     private static final Logger JavaDoc LOG = Logger
58             .getLogger("org.columba.mail.folder.search");
59
60     
61     /**
62      * Filter plugins are cached and reused, instead of re-instanciated all the
63      * time
64      */

65     private static Hashtable JavaDoc filterCache;
66
67     /**
68      * AbstractMessageFolder on which the search is applied
69      */

70     private AbstractMessageFolder folder;
71
72     /**
73      * The default query engine used by the search-engine
74      */

75     private QueryEngine nonDefaultEngine;
76
77     /**
78      * Constructor
79      *
80      * @param folder
81      * folder on which the search is applied
82      */

83     public DefaultSearchEngine(AbstractMessageFolder folder) {
84         this.folder = folder;
85         filterCache = new Hashtable JavaDoc();
86         nonDefaultEngine = new DummyQueryEngine();
87         folder.addFolderListener(new FolderListener() {
88             public void messageAdded(IFolderEvent e) {
89                 try {
90                     getNonDefaultEngine().messageAdded(e.getChanges());
91                 } catch (Exception JavaDoc ex) {
92                 }
93             }
94
95             public void messageRemoved(IFolderEvent e) {
96                 try {
97                     getNonDefaultEngine().messageRemoved(e.getChanges());
98                 } catch (Exception JavaDoc ex) {
99                 }
100             }
101
102             public void folderPropertyChanged(IFolderEvent e) {
103             }
104
105             public void folderAdded(IFolderEvent e) {
106             }
107
108             public void folderRemoved(IFolderEvent e) {
109             }
110
111             public void messageFlagChanged(IFolderEvent e) {
112                 // not needed
113

114             }
115         });
116     }
117
118     public IStatusObservable getObservable() {
119         return folder.getObservable();
120     }
121
122     protected synchronized AbstractFilter getFilter(
123             IFilterCriteria filterCriteria, String JavaDoc type) {
124         // try to re-use already instanciated class
125
if (filterCache.containsKey(type) == true) {
126             AbstractFilter f = (AbstractFilter) filterCache.get(type);
127
128             // setup filter configuration
129
f.setUp(filterCriteria);
130
131             return f;
132         }
133
134         AbstractFilter instance = null;
135
136         try {
137             IExtensionHandler handler = PluginManager
138                     .getInstance().getExtensionHandler(IExtensionHandlerKeys.ORG_COLUMBA_MAIL_FILTER);
139             IExtension extension = handler.getExtension(type);
140
141             instance = (AbstractFilter) extension.instanciateExtension(null);
142         } catch (Exception JavaDoc ex) {
143             JOptionPane.showMessageDialog(null,
144                     "Error while trying to load filter plugin =" + type);
145             ex.printStackTrace();
146         }
147
148         // setup filter configuration
149
instance.setUp(filterCriteria);
150
151         if (instance != null) {
152             filterCache.put(type, instance);
153         }
154
155         return instance;
156     }
157
158     protected boolean processRule(Object JavaDoc uid, IFilterCriteria criteria,
159             String JavaDoc type) throws Exception JavaDoc {
160         if (type == null) {
161             JOptionPane.showMessageDialog(null,
162                     "Filter type couldn't been found", "Error occured",
163                     JOptionPane.ERROR_MESSAGE);
164
165             return false;
166         }
167
168         AbstractFilter instance = getFilter(criteria, type);
169
170         if (instance == null) {
171             return false;
172         }
173
174         return instance.process(folder, uid);
175     }
176
177     protected List JavaDoc processCriteria(IFilterRule rule, List JavaDoc uids) throws Exception JavaDoc {
178         LinkedList JavaDoc result = new LinkedList JavaDoc();
179         boolean b;
180
181         int match = rule.getConditionInt();
182
183         ListIterator JavaDoc it = uids.listIterator();
184
185         Object JavaDoc uid;
186
187         // MATCH_ALL
188
if (match == FilterRule.MATCH_ALL) {
189             while (it.hasNext()) {
190                 b = true;
191                 uid = it.next();
192
193                 for (int i = 0; (i < rule.count()) && b; i++) {
194                     IFilterCriteria criteria = rule.get(i);
195
196                     String JavaDoc type = criteria.getTypeString();
197
198                     b &= processRule(uid, criteria, type);
199                 }
200
201                 if (b) {
202                     result.add(uid);
203                 }
204             }
205         } else { // MATCH ANY
206

207             while (it.hasNext()) {
208                 b = false;
209                 uid = it.next();
210
211                 for (int i = 0; (i < rule.count()) && !b; i++) {
212                     IFilterCriteria criteria = rule.get(i);
213
214                     String JavaDoc type = criteria.getTypeString();
215
216                     b = processRule(uid, criteria, type);
217                 }
218
219                 if (b) {
220                     result.add(uid);
221                 }
222             }
223         }
224
225         // result = mergeFilterResult(v, uids, match);
226
// only for debugging purpose
227
// printList( result );
228
return result;
229     }
230
231     protected void divideFilterRule(IFilterRule filterRule,
232             IFilterRule notDefaultEngine, IFilterRule defaultEngine) {
233         IFilterCriteria actCriteria;
234
235         String JavaDoc[] caps = getNonDefaultEngine().getCaps();
236
237         List JavaDoc capList = Arrays.asList(caps);
238
239         notDefaultEngine.setCondition(filterRule.getCondition());
240         defaultEngine.setCondition(filterRule.getCondition());
241
242         for (int i = 0; i < filterRule.count(); i++) {
243             actCriteria = filterRule.get(i);
244
245             if (capList.contains(actCriteria.getTypeString())) {
246                 // search request isn't covered by query engine
247
// -> fall back to default search engine
248
defaultEngine.add(actCriteria);
249             } else {
250                 // this search request is covered by the query engine
251
notDefaultEngine.add(actCriteria);
252             }
253         }
254     }
255
256     /**
257      * @see org.columba.mail.folder.SearchEngineInterface#searchMessages(org.columba.mail.filter.Filter,
258      * java.lang.Object, org.columba.api.command.IWorkerStatusController)
259      */

260     public Object JavaDoc[] searchMessages(IFilter filter, Object JavaDoc[] uids)
261             throws Exception JavaDoc {
262         if (!filter.getEnabled()) {
263             // filter is disabled
264
return new Object JavaDoc[] {};
265         }
266
267         List JavaDoc notDefaultEngineResult = null;
268         List JavaDoc defaultEngineResult = new LinkedList JavaDoc();
269
270         IFilterRule filterRule = filter.getFilterRule();
271
272         IFilterRule notDefaultEngine = new FilterRule();
273         IFilterRule defaultEngine = new FilterRule();
274
275         divideFilterRule(filterRule, notDefaultEngine, defaultEngine);
276
277         if (defaultEngine.count() > 0) {
278             try {
279                 if (uids != null) {
280                     defaultEngineResult = getNonDefaultEngine().queryEngine(
281                             defaultEngine, uids);
282                 } else {
283                     defaultEngineResult = getNonDefaultEngine().queryEngine(
284                             defaultEngine);
285                 }
286             } catch (Exception JavaDoc e) {
287                 e.printStackTrace();
288                 LOG.warning("NonDefaultSearch engine "+ nonDefaultEngine.toString()+"reported an error: falling back to default search:\n"+e.getMessage());
289                 defaultEngine = new FilterRule();
290                 notDefaultEngine = filter.getFilterRule();
291             }
292         }
293
294         if (notDefaultEngine.count() == 0) {
295             notDefaultEngineResult = defaultEngineResult;
296         } else {
297             // MATCH_ALL
298
if (filterRule.getConditionInt() == FilterRule.MATCH_ALL) {
299                 if (defaultEngine.count() > 0) {
300                     notDefaultEngineResult = processCriteria(notDefaultEngine,
301                             defaultEngineResult);
302                 } else {
303                     if (uids != null) {
304                         notDefaultEngineResult = processCriteria(
305                                 notDefaultEngine, Arrays.asList(uids));
306                     } else {
307                         notDefaultEngineResult = processCriteria(
308                                 notDefaultEngine, Arrays.asList(folder
309                                         .getUids()));
310                     }
311                 }
312             }
313             // MATCH_ANY
314
else {
315                 if (uids != null) {
316                     List JavaDoc uidList = new LinkedList JavaDoc(Arrays.asList(uids));
317                     ListTools.substract(uidList, defaultEngineResult);
318
319                     notDefaultEngineResult = processCriteria(notDefaultEngine,
320                             uidList);
321
322                     notDefaultEngineResult.addAll(defaultEngineResult);
323                 } else {
324                     notDefaultEngineResult = processCriteria(notDefaultEngine,
325                             Arrays.asList(folder.getUids()));
326                 }
327             }
328         }
329
330         /*
331          * worker.setDisplayText( "Search Result: " +
332          * notDefaultEngineResult.size() + " messages found in " +
333          * (System.currentTimeMillis() - startTime) + " ms");
334          */

335         return notDefaultEngineResult.toArray();
336     }
337
338     /**
339      * @see org.columba.mail.folder.SearchEngineInterface#searchMessages(org.columba.mail.filter.Filter,
340      * org.columba.api.command.IWorkerStatusController)
341      */

342     public Object JavaDoc[] searchMessages(IFilter filter) throws Exception JavaDoc {
343         if (getObservable() != null) {
344             getObservable().setMessage(
345                     MailResourceLoader.getString("statusbar", "message",
346                             "search"));
347         }
348
349         // return searchMessages(filter, null);
350
Object JavaDoc[] result = searchMessages(filter, null);
351
352         if (getObservable() != null) {
353             // clear status bar message now we are done (with a delay)
354
getObservable().clearMessageWithDelay();
355         }
356
357         return result;
358     }
359
360     /**
361      * @see org.columba.mail.folder.DefaultSearchEngine#queryEngine(org.columba.mail.filter.FilterRule,
362      * java.lang.Object, org.columba.api.command.IWorkerStatusController)
363      */

364     protected List JavaDoc queryEngine(IFilterRule filter, Object JavaDoc[] uids)
365             throws Exception JavaDoc {
366         return processCriteria(filter, Arrays.asList(uids));
367     }
368
369     /**
370      * @see org.columba.mail.folder.DefaultSearchEngine#queryEngine(org.columba.mail.filter.FilterRule,
371      * org.columba.api.command.IWorkerStatusController)
372      */

373     protected List JavaDoc queryEngine(IFilterRule filter) throws Exception JavaDoc {
374         Object JavaDoc[] uids = folder.getUids();
375
376         return processCriteria(filter, Arrays.asList(uids));
377     }
378
379     /**
380      * @return
381      */

382     public QueryEngine getNonDefaultEngine() {
383         return nonDefaultEngine;
384     }
385
386     /**
387      * @param engine
388      */

389     public void setNonDefaultEngine(QueryEngine engine) {
390         nonDefaultEngine = engine;
391     }
392
393     public void sync() throws Exception JavaDoc {
394         getNonDefaultEngine().sync();
395     }
396
397     public void save() {
398         getNonDefaultEngine().save();
399     }
400 }
401
Popular Tags