KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > columba > core > search > SearchManager


1 package org.columba.core.search;
2
3 import java.util.Collections JavaDoc;
4 import java.util.Hashtable JavaDoc;
5 import java.util.Iterator JavaDoc;
6 import java.util.List JavaDoc;
7 import java.util.Map JavaDoc;
8 import java.util.Vector JavaDoc;
9 import java.util.logging.Logger JavaDoc;
10
11 import javax.swing.SwingUtilities JavaDoc;
12 import javax.swing.event.EventListenerList JavaDoc;
13
14 import org.columba.api.command.IWorkerStatusController;
15 import org.columba.core.command.Command;
16 import org.columba.core.command.CommandProcessor;
17 import org.columba.core.search.api.IResultEvent;
18 import org.columba.core.search.api.IResultListener;
19 import org.columba.core.search.api.ISearchCriteria;
20 import org.columba.core.search.api.ISearchManager;
21 import org.columba.core.search.api.ISearchProvider;
22 import org.columba.core.search.api.ISearchRequest;
23 import org.columba.core.search.api.ISearchResult;
24
25 public class SearchManager implements ISearchManager {
26
27     private static final Logger JavaDoc LOG = Logger
28             .getLogger("org.columba.core.search.SearchManager");
29
30     protected EventListenerList JavaDoc listenerList = new EventListenerList JavaDoc();
31
32     private Map JavaDoc<String JavaDoc, ISearchProvider> providerMap = new Hashtable JavaDoc<String JavaDoc, ISearchProvider>();
33
34     /**
35      * command hashtable used for paging to call the same command several times
36      * for a given <code>startIndex</code> and <code>resultCount</code>
37      */

38     private Map JavaDoc<String JavaDoc, Command> commandMap = new Hashtable JavaDoc<String JavaDoc, Command>();
39
40     public SearchManager() {
41         // ensure map can be used by multiple threads
42
commandMap = Collections.synchronizedMap(commandMap);
43
44     }
45
46     /**
47      * @see org.columba.core.search.api.ISearchManager#executeSearch(java.lang.String,
48      * int, int)
49      */

50     public void executeSearch(String JavaDoc searchTerm, boolean searchInside,
51             int startIndex, int resultCount) {
52         if (searchTerm == null)
53             throw new IllegalArgumentException JavaDoc("searchTerm == null");
54         if (startIndex < 0)
55             throw new IllegalArgumentException JavaDoc("startIndex must be >= 0");
56         if (resultCount <= 0)
57             throw new IllegalArgumentException JavaDoc("resultCount must be > 0");
58
59
60         Command command = new SearchCommand(new SearchCommandReference(searchTerm,
61                 startIndex, resultCount, searchInside));
62         
63         // fire up search command
64
CommandProcessor.getInstance().addOp(command);
65     }
66
67     /**
68      * @see org.columba.core.search.api.ISearchManager#executeSearch(java.lang.String,
69      * java.lang.String, int, int)
70      */

71     public void executeSearch(String JavaDoc searchTerm, String JavaDoc providerName, boolean searchInside,
72             int startIndex, int resultCount) {
73         if (searchTerm == null)
74             throw new IllegalArgumentException JavaDoc("searchTerm == null");
75         if (providerName == null)
76             throw new IllegalArgumentException JavaDoc("providerName == null");
77         if (startIndex < 0)
78             throw new IllegalArgumentException JavaDoc("startIndex must be >= 0");
79         if (resultCount <= 0)
80             throw new IllegalArgumentException JavaDoc("resultCount must be > 0");
81
82     
83         Command command = new SearchCommand(new SearchCommandReference(searchTerm,
84                 providerName, startIndex, resultCount));
85         // fire up search command
86
CommandProcessor.getInstance().addOp(command);
87     }
88
89     public void executeSearch(String JavaDoc searchTerm, String JavaDoc providerName,
90             String JavaDoc criteriaName, boolean searchInside, int startIndex, int resultCount) {
91         if (searchTerm == null)
92             throw new IllegalArgumentException JavaDoc("searchTerm == null");
93         if (providerName == null)
94             throw new IllegalArgumentException JavaDoc("providerName == null");
95         if (criteriaName == null)
96             throw new IllegalArgumentException JavaDoc("criteriaName == null");
97         if (startIndex < 0)
98             throw new IllegalArgumentException JavaDoc("startIndex must be >= 0");
99         if (resultCount <= 0)
100             throw new IllegalArgumentException JavaDoc("resultCount must be > 0");
101
102         Command command = new SearchCommand(new SearchCommandReference(searchTerm,
103                 providerName, criteriaName, searchInside, startIndex, resultCount));
104         
105         // fire up search command
106
CommandProcessor.getInstance().addOp(command);
107     }
108
109     public void executeSearch(List JavaDoc<ISearchRequest> requests,
110             boolean allCriteria, boolean searchInside, int startIndex,
111             int resultCount) {
112         if (requests == null)
113             throw new IllegalArgumentException JavaDoc("requests == null");
114         if (startIndex < 0)
115             throw new IllegalArgumentException JavaDoc("startIndex must be >= 0");
116         if (resultCount <= 0)
117             throw new IllegalArgumentException JavaDoc("resultCount must be > 0");
118
119         Command command = new SearchCommand(new SearchCommandReference(
120                 requests, allCriteria, startIndex, resultCount, searchInside));
121
122         CommandProcessor.getInstance().addOp(command);
123     }
124
125     /**
126      * @see org.columba.core.search.api.ISearchManager#getAllProviders()
127      */

128     public Iterator JavaDoc<ISearchProvider> getAllProviders() {
129         return providerMap.values().iterator();
130     }
131
132     /**
133      * @see org.columba.core.search.api.ISearchManager#clearSearch(java.lang.String)
134      */

135     public void clearSearch(String JavaDoc searchTerm) {
136         // we assume user cancelled search
137
// -> remove cached command
138
if (commandMap.containsKey(searchTerm))
139             commandMap.remove(searchTerm);
140
141         fireClearSearch(searchTerm);
142     }
143
144     public void reset() {
145         fireReset();
146     }
147
148     /**
149      * Propagates an event to all registered listeners notifying them of a item
150      * addition.
151      */

152     protected void fireNewResultArrived(String JavaDoc searchTerm,
153             String JavaDoc providerTechnicalName, ISearchCriteria criteria,
154             List JavaDoc<ISearchResult> result, int totalResultCount) {
155
156         IResultEvent e = new ResultEvent(this, searchTerm,
157                 providerTechnicalName, criteria, result, totalResultCount);
158         // Guaranteed to return a non-null array
159
Object JavaDoc[] listeners = listenerList.getListenerList();
160
161         // Process the listeners last to first, notifying
162
// those that are interested in this event
163
for (int i = listeners.length - 2; i >= 0; i -= 2) {
164             if (listeners[i] == IResultListener.class) {
165                 ((IResultListener) listeners[i + 1]).resultArrived(e);
166             }
167         }
168     }
169
170     protected void fireNewResultArrived(String JavaDoc providerTechnicalName,
171             List JavaDoc<ISearchResult> result, int totalResultCount) {
172
173         IResultEvent e = new ResultEvent(this, providerTechnicalName, result,
174                 totalResultCount);
175         // Guaranteed to return a non-null array
176
Object JavaDoc[] listeners = listenerList.getListenerList();
177
178         // Process the listeners last to first, notifying
179
// those that are interested in this event
180
for (int i = listeners.length - 2; i >= 0; i -= 2) {
181             if (listeners[i] == IResultListener.class) {
182                 ((IResultListener) listeners[i + 1]).resultArrived(e);
183             }
184         }
185     }
186
187     protected void fireFinished() {
188         IResultEvent e = new ResultEvent(this);
189         // Guaranteed to return a non-null array
190
Object JavaDoc[] listeners = listenerList.getListenerList();
191
192         // Process the listeners last to first, notifying
193
// those that are interested in this event
194
for (int i = listeners.length - 2; i >= 0; i -= 2) {
195             if (listeners[i] == IResultListener.class) {
196                 ((IResultListener) listeners[i + 1]).finished(e);
197             }
198         }
199
200     }
201
202     /**
203      * Propagates an event to all registered listeners
204      */

205     protected void fireClearSearch(String JavaDoc searchTerm) {
206
207         IResultEvent e = new ResultEvent(this, searchTerm);
208         // Guaranteed to return a non-null array
209
Object JavaDoc[] listeners = listenerList.getListenerList();
210
211         // Process the listeners last to first, notifying
212
// those that are interested in this event
213
for (int i = listeners.length - 2; i >= 0; i -= 2) {
214             if (listeners[i] == IResultListener.class) {
215                 ((IResultListener) listeners[i + 1]).clearSearch(e);
216             }
217         }
218     }
219
220     protected void fireReset() {
221
222         IResultEvent e = new ResultEvent(this);
223         // Guaranteed to return a non-null array
224
Object JavaDoc[] listeners = listenerList.getListenerList();
225
226         // Process the listeners last to first, notifying
227
// those that are interested in this event
228
for (int i = listeners.length - 2; i >= 0; i -= 2) {
229             if (listeners[i] == IResultListener.class) {
230                 ((IResultListener) listeners[i + 1]).reset(e);
231             }
232         }
233     }
234
235     /**
236      * @see org.columba.core.search.api.ISearchManager#addResultListener(org.columba.core.search.api.IResultListener)
237      */

238     public void addResultListener(IResultListener l) {
239         listenerList.add(IResultListener.class, l);
240
241     }
242
243     /**
244      * @see org.columba.core.search.api.ISearchManager#removeResultListener(org.columba.core.search.api.IResultListener)
245      */

246     public void removeResultListener(IResultListener l) {
247         listenerList.remove(IResultListener.class, l);
248
249     }
250
251     /**
252      * Command executes the search.
253      * <p>
254      * In case new result results arrive, it ensures that all interested
255      * listeners are notified from inside the EDT.
256      * <p>
257      * FIXME: fdietz: No locking of folders currently implemented! TODO: fdietz:
258      * create new Command for every provider to introduce real "parallel" search
259      *
260      * @author fdietz
261      */

262     class SearchCommand extends Command {
263
264         public SearchCommand(SearchCommandReference reference) {
265             super(reference);
266         }
267
268         @Override JavaDoc
269         public void execute(IWorkerStatusController worker) throws Exception JavaDoc {
270             final SearchCommandReference ref = (SearchCommandReference) getReference();
271
272             if (ref.getType().equals(SearchCommandReference.TYPE.SIMPLE_ALL)) {
273                 Iterator JavaDoc<ISearchProvider> it = getAllProviders();
274                 while (it.hasNext()) {
275                     final ISearchProvider p = it.next();
276
277                     // query using all criteria
278
Iterator JavaDoc<ISearchCriteria> it2 = p.getAllCriteria(
279                             ref.getSearchTerm()).iterator();
280                     while (it2.hasNext()) {
281                         ISearchCriteria c = it2.next();
282                         String JavaDoc searchCriteriaTechnicalName = c
283                                 .getTechnicalName();
284                         // execute search
285
doExecute(ref.getSearchTerm(), p,
286                                 searchCriteriaTechnicalName, ref
287                                         .isSearchInside(), ref.getStartIndex(),
288                                 ref.getResultCount());
289                     }
290
291                 }
292             } else if (ref.getType().equals(
293                     SearchCommandReference.TYPE.SIMPLE_SPECIFIC_PROVIDER)) {
294                 String JavaDoc providerTechnicalName = ref.getProviderTechnicalName();
295                 ISearchProvider p = getProvider(providerTechnicalName);
296                 // query using all criteria
297
Iterator JavaDoc<ISearchCriteria> it2 = p.getAllCriteria(
298                         ref.getSearchTerm()).iterator();
299                 while (it2.hasNext()) {
300                     ISearchCriteria c = it2.next();
301                     String JavaDoc searchCriteriaTechnicalName = c.getTechnicalName();
302                     // execute search
303
doExecute(ref.getSearchTerm(), p,
304                             searchCriteriaTechnicalName, ref.isSearchInside(),
305                             ref.getStartIndex(), ref.getResultCount());
306                 }
307             } else if (ref.getType().equals(
308                     SearchCommandReference.TYPE.SIMPLE_SPECIFIC_CRITERIA)) {
309                 String JavaDoc providerTechnicalName = ref.getProviderTechnicalName();
310                 ISearchProvider p = getProvider(providerTechnicalName);
311                 doExecute(ref.getSearchTerm(), p, ref
312                         .getSearchCriteriaTechnicalName(),
313                         ref.isSearchInside(), ref.getStartIndex(), ref
314                                 .getResultCount());
315             } else if (ref.getType()
316                     .equals(SearchCommandReference.TYPE.COMPLEX)) {
317
318                 // first, create bucket for each provider
319
Map JavaDoc<String JavaDoc, Vector JavaDoc<ISearchRequest>> map = new Hashtable JavaDoc<String JavaDoc, Vector JavaDoc<ISearchRequest>>();
320                 Iterator JavaDoc<ISearchRequest> it = ref.getRequest().iterator();
321                 while (it.hasNext()) {
322                     ISearchRequest r = it.next();
323                     String JavaDoc providerName = r.getProvider();
324
325                     if (map.containsKey(providerName)) {
326                         Vector JavaDoc<ISearchRequest> v = map.get(providerName);
327                         v.add(r);
328                     } else {
329                         Vector JavaDoc<ISearchRequest> v = new Vector JavaDoc<ISearchRequest>();
330                         v.add(r);
331                         map.put(providerName, v);
332                     }
333                 }
334
335                 // now search through all buckets
336
Iterator JavaDoc<String JavaDoc> it2 = map.keySet().iterator();
337                 while (it2.hasNext()) {
338                     final String JavaDoc providerName = it2.next();
339                     ISearchProvider p = getProvider(providerName);
340                     Vector JavaDoc<ISearchRequest> v = map.get(providerName);
341                     final List JavaDoc<ISearchResult> resultList = p.query(v, ref
342                             .isMatchAll(), ref.isSearchInside(), ref
343                             .getStartIndex(), ref.getResultCount());
344
345                     final int totalResultCount = p.getTotalResultCount();
346
347                     // notify all listeners that new search results arrived
348

349                     // ensure this is called in the EDT
350
Runnable JavaDoc run = new Runnable JavaDoc() {
351                         public void run() {
352                             fireNewResultArrived(providerName, resultList,
353                                     totalResultCount);
354                         }
355                     };
356                     SwingUtilities.invokeLater(run);
357                 }
358
359             }
360
361             // notify that search is finished
362
Runnable JavaDoc run = new Runnable JavaDoc() {
363                 public void run() {
364                     fireFinished();
365                 }
366             };
367             SwingUtilities.invokeLater(run);
368             
369             // create list of all registered providers
370
// Iterator<ISearchProvider> it = getAllProviders();
371
// while (it.hasNext()) {
372
// final ISearchProvider p = it.next();
373
//
374
// // if providerName specified
375
// // -> skip if this isn't the matching provider
376
// if (providerTechnicalName != null) {
377
// if (!providerTechnicalName.equals(p.getTechnicalName()))
378
// continue;
379
// }
380
//
381
// // keep search history
382
// // SearchHistoryList.getInstance().add(ref.getSearchTerm(), p,
383
// // c);
384
//
385
// if (ref.getSearchCriteriaTechnicalName() == null) {
386
// // query using all criteria
387
// Iterator<ISearchCriteria> it2 = p.getAllCriteria(
388
// ref.getSearchTerm()).iterator();
389
// while (it2.hasNext()) {
390
// ISearchCriteria c = it2.next();
391
// String searchCriteriaTechnicalName = c
392
// .getTechnicalName();
393
// // execute search
394
// doExecute(ref, p, searchCriteriaTechnicalName, ref
395
// .isSearchInside());
396
// }
397
// } else {
398
// // query only a single criteria
399
//
400
// // execute search
401
// doExecute(ref, p, ref.getSearchCriteriaTechnicalName(), ref
402
// .isSearchInside());
403
// }
404
//
405
// }
406

407         }
408
409         private void doExecute(final String JavaDoc searchTerm,
410                 final ISearchProvider p,
411                 final String JavaDoc searchCriteriaTechnicalName,
412                 final boolean searchInside, final int startIndex,
413                 final int resultCount) {
414
415             // query provider
416
final List JavaDoc<ISearchResult> resultList = p.query(searchTerm,
417                     searchCriteriaTechnicalName, searchInside, startIndex,
418                     resultCount);
419
420             // retrieve total result count
421
final int totalResultCount = p.getTotalResultCount();
422
423             // notify all listeners that new search results arrived
424

425             // ensure this is called in the EDT
426
Runnable JavaDoc run = new Runnable JavaDoc() {
427                 public void run() {
428                     
429                     fireNewResultArrived(searchTerm, p.getTechnicalName(), p
430                             .getCriteria(searchCriteriaTechnicalName,
431                                     searchTerm), resultList, totalResultCount);
432                     
433                 }
434             };
435             SwingUtilities.invokeLater(run);
436         }
437
438     }
439
440     /**
441      * @see org.columba.core.search.api.ISearchManager#getProvider(java.lang.String)
442      */

443     public ISearchProvider getProvider(String JavaDoc technicalName) {
444         return providerMap.get(technicalName);
445     }
446
447     public void registerProvider(ISearchProvider p) {
448         providerMap.put(p.getTechnicalName(), p);
449     }
450
451     public void unregisterProvider(ISearchProvider p) {
452         providerMap.remove(p.getTechnicalName());
453     }
454
455 }
456
Popular Tags