KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > columba > mail > folder > event > FolderEventDelegator


1 // The contents of this file are subject to the Mozilla Public License Version
2
// 1.1
3
//(the "License"); you may not use this file except in compliance with the
4
//License. You may obtain a copy of the License at http://www.mozilla.org/MPL/
5
//
6
//Software distributed under the License is distributed on an "AS IS" basis,
7
//WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
8
//for the specific language governing rights and
9
//limitations under the License.
10
//
11
//The Original Code is "The Columba Project"
12
//
13
//The Initial Developers of the Original Code are Frederik Dietz and Timo
14
// Stich.
15
//Portions created by Frederik Dietz and Timo Stich are Copyright (C) 2003.
16
//
17
//All Rights Reserved.
18
package org.columba.mail.folder.event;
19
20 import java.awt.event.ActionEvent JavaDoc;
21 import java.awt.event.ActionListener JavaDoc;
22 import java.util.ArrayList JavaDoc;
23 import java.util.Collections JavaDoc;
24 import java.util.Comparator JavaDoc;
25 import java.util.Iterator JavaDoc;
26 import java.util.List JavaDoc;
27
28 import javax.swing.Timer JavaDoc;
29 import javax.swing.event.EventListenerList JavaDoc;
30 import javax.swing.tree.TreeNode JavaDoc;
31
32 import org.columba.core.base.Mutex;
33 import org.columba.mail.folder.IMailFolder;
34 import org.columba.mail.gui.table.model.TableModelChangedEvent;
35 import org.columba.mail.gui.table.model.TableModelChangedListener;
36 import org.columba.mail.gui.tree.FolderTreeModel;
37
38 /**
39  * Collects all folder events generated by AbstractFolder and
40  * AbstractMessageFolder.
41  * <p>
42  * Accumulates matching events to one big event. Afterwards it delegates this
43  * final event to FolderTreeModel and all TableModel objects.
44  * <p>
45  * A swing timer is used to trigger ui updates.
46  *
47  * @author fdietz
48  * @author tstich
49  */

50 public class FolderEventDelegator implements ActionListener JavaDoc, FolderListener {
51
52     private static final int UPDATE_DELAY = 500;
53
54     private static FolderEventDelegator instance;
55
56     private Timer JavaDoc timer;
57
58     private Mutex mutex;
59
60     private List JavaDoc[] messageRemovedList;
61
62     private List JavaDoc[] messageFlagChangedList;
63
64     private List JavaDoc[] messageAddedList;
65
66     private List JavaDoc[] folderAddedList;
67
68     private List JavaDoc[] folderRemovedList;
69
70     private List JavaDoc[] folderPropertyChangedList;
71
72     private int swap = 0;
73
74     protected EventListenerList JavaDoc tableListenerList = new EventListenerList JavaDoc();
75
76     private FolderEventDelegator() {
77         super();
78
79         messageRemovedList = new List JavaDoc[] { new ArrayList JavaDoc(500),
80                 new ArrayList JavaDoc(500) };
81         messageFlagChangedList = new List JavaDoc[] { new ArrayList JavaDoc(500),
82                 new ArrayList JavaDoc(500) };
83         messageAddedList = new List JavaDoc[] { new ArrayList JavaDoc(500), new ArrayList JavaDoc(500) };
84
85         folderAddedList = new List JavaDoc[] { new ArrayList JavaDoc(500), new ArrayList JavaDoc(500) };
86         folderRemovedList = new List JavaDoc[] { new ArrayList JavaDoc(500), new ArrayList JavaDoc(500) };
87         folderPropertyChangedList = new List JavaDoc[] { new ArrayList JavaDoc(500),
88                 new ArrayList JavaDoc(500) };
89
90         mutex = new Mutex();
91
92         timer = new Timer JavaDoc(UPDATE_DELAY, this);
93         timer.start();
94     }
95
96     public static FolderEventDelegator getInstance() {
97         if (instance == null)
98             instance = new FolderEventDelegator();
99
100         return instance;
101     }
102
103     /**
104      * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
105      */

106     public void actionPerformed(ActionEvent JavaDoc arg0) {
107         // process all events collected until now
108
mutex.lock();
109
110         swap = 1 - swap;
111
112         mutex.release();
113
114         processTableEvents();
115
116         processTreeEvents();
117
118         clearAllLists();
119
120     }
121
122     /**
123      *
124      */

125     private void clearAllLists() {
126         messageAddedList[swap].clear();
127         messageRemovedList[swap].clear();
128         messageFlagChangedList[swap].clear();
129
130         folderAddedList[swap].clear();
131         folderRemovedList[swap].clear();
132         folderPropertyChangedList[swap].clear();
133     }
134
135     /**
136      * @param events
137      */

138     private void processTableEvents() {
139
140         if (messageAddedList[swap].size() > 0) {
141
142             // First sort so that Events from one folder stick together
143
Collections.sort(messageAddedList[swap], FolderEventComparator
144                     .getInstance());
145             IMailFolder lastFolder = (IMailFolder) ((FolderEvent) messageAddedList[swap]
146                     .get(0)).getSource();
147
148             fireTableEvent(new TableModelChangedEvent(
149                     TableModelChangedEvent.UPDATE, lastFolder));
150
151             // Process the events
152
for (int i = 1; i < messageAddedList[swap].size(); i++) {
153                 FolderEvent next = (FolderEvent) messageAddedList[swap].get(i);
154                 if (next.getSource() != lastFolder) {
155                     lastFolder = (IMailFolder) next.getSource();
156                     fireTableEvent(new TableModelChangedEvent(
157                             TableModelChangedEvent.UPDATE, lastFolder));
158                 }
159             }
160         }
161
162         if (messageRemovedList[swap].size() > 0) {
163             // First sort so that Events from one folder stick together
164
Collections.sort(messageRemovedList[swap], FolderEventComparator
165                     .getInstance());
166             FolderEvent event = (FolderEvent) messageRemovedList[swap].get(0);
167             IMailFolder lastFolder = (IMailFolder) event.getSource();
168
169             // Collect the uids for one folder
170
List JavaDoc collectedUids = new ArrayList JavaDoc();
171             collectedUids.add(event.getChanges());
172
173             // Process the events
174
for (int i = 1; i < messageRemovedList[swap].size(); i++) {
175                 FolderEvent next = (FolderEvent) messageRemovedList[swap]
176                         .get(i);
177                 if (next.getSource() != lastFolder) {
178                     // new folder, fire to the old folder
179
fireTableEvent(new TableModelChangedEvent(
180                             TableModelChangedEvent.REMOVE, lastFolder,
181                             collectedUids.toArray()));
182
183                     // clear list and collect uids for new folder
184
collectedUids.clear();
185                     collectedUids.add(next.getChanges());
186
187                     lastFolder = (IMailFolder) next.getSource();
188                 } else {
189                     collectedUids.add(next.getChanges());
190                 }
191             }
192
193             fireTableEvent(new TableModelChangedEvent(
194                     TableModelChangedEvent.REMOVE, lastFolder, collectedUids
195                             .toArray()));
196         }
197
198         if (messageFlagChangedList[swap].size() > 0) {
199
200             // First sort so that Events from one folder stick together
201
Collections.sort(messageFlagChangedList[swap],
202                     FolderEventComparator.getInstance());
203             FolderEvent event = (FolderEvent) messageFlagChangedList[swap]
204                     .get(0);
205             IMailFolder lastFolder = (IMailFolder) event.getSource();
206
207             // Collect the uids for one folder
208
List JavaDoc collectedUids = new ArrayList JavaDoc();
209             collectedUids.add(event.getChanges());
210
211             // Process the events
212
for (int i = 1; i < messageFlagChangedList[swap].size(); i++) {
213                 FolderEvent next = (FolderEvent) messageFlagChangedList[swap]
214                         .get(i);
215                 if (next.getSource() != lastFolder) {
216                     // new folder, fire to the old folder
217
fireTableEvent(new TableModelChangedEvent(
218                             TableModelChangedEvent.MARK, lastFolder,
219                             collectedUids.toArray()));
220
221                     // clear list and collect uids for new folder
222
collectedUids.clear();
223                     collectedUids.add(next.getChanges());
224
225                     lastFolder = (IMailFolder) next.getSource();
226                 } else {
227                     collectedUids.add(next.getChanges());
228                 }
229             }
230
231             fireTableEvent(new TableModelChangedEvent(
232                     TableModelChangedEvent.MARK, lastFolder, collectedUids
233                             .toArray()));
234         }
235
236     }
237
238     /**
239      * @param events
240      */

241     private void processTreeEvents() {
242
243         if (folderRemovedList[swap].size() > 0) {
244             IMailFolder lastFolder = null;
245
246             // Process the events
247
for (int i = 0; i < folderRemovedList[swap].size(); i++) {
248                 FolderEvent next = (FolderEvent) folderRemovedList[swap].get(i);
249
250                 lastFolder = (IMailFolder) next.getSource();
251
252                 TreeNode JavaDoc parent = lastFolder.getParent();
253                 lastFolder.removeFromParent();
254                 FolderTreeModel.getInstance().nodeStructureChanged(parent);
255             }
256         }
257
258         if (folderAddedList[swap].size() > 0) {
259
260             // First sort so that Events from one folder stick together
261
Collections.sort(folderAddedList[swap], FolderEventComparator
262                     .getInstance());
263
264             FolderEvent e = (FolderEvent) folderAddedList[swap].get(0);
265
266             IMailFolder lastFolder = (IMailFolder) e.getSource();
267             IMailFolder child = (IMailFolder) e.getChanges();
268
269             // If there is still a parent -> remove it
270
if (child.getParent() != null) {
271                 TreeNode JavaDoc parent = lastFolder.getParent();
272                 child.removeFromParent();
273                 FolderTreeModel.getInstance().nodeStructureChanged(parent);
274             }
275
276             // add child to this node
277
lastFolder.add(child);
278
279             FolderTreeModel.getInstance().nodeStructureChanged(lastFolder);
280
281             // Process the events
282
for (int i = 1; i < folderAddedList[swap].size(); i++) {
283                 FolderEvent next = (FolderEvent) folderAddedList[swap].get(i);
284                 if (next.getSource() != lastFolder) {
285                     lastFolder = (IMailFolder) next.getSource();
286                     FolderTreeModel.getInstance().nodeStructureChanged(
287                             lastFolder);
288                 }
289             }
290         }
291
292         if (folderPropertyChangedList[swap].size() > 0) {
293
294             // First sort so that Events from one folder stick together
295
Collections.sort(folderPropertyChangedList[swap],
296                     FolderEventComparator.getInstance());
297
298             IMailFolder lastFolder = (IMailFolder) ((FolderEvent) folderPropertyChangedList[swap]
299                     .get(0)).getSource();
300
301             FolderTreeModel.getInstance().nodeChanged(lastFolder);
302
303             // Process the events
304
for (int i = 1; i < folderPropertyChangedList[swap].size(); i++) {
305                 FolderEvent next = (FolderEvent) folderPropertyChangedList[swap]
306                         .get(i);
307                 if (next.getSource() != lastFolder) {
308                     lastFolder = (IMailFolder) next.getSource();
309                     FolderTreeModel.getInstance().nodeChanged(lastFolder);
310                 }
311             }
312         }
313
314     }
315
316     /** ********************* Folder Listener *************************** */
317     /**
318      * @see org.columba.mail.folder.event.FolderListener#folderAdded(IFolderEvent)
319      */

320     public void folderAdded(IFolderEvent e) {
321         mutex.lock();
322
323         Iterator JavaDoc it = folderAddedList[1 - swap].iterator();
324         boolean found = false;
325         while (it.hasNext() && !found) {
326             FolderEvent event = (FolderEvent) it.next();
327             found = (event.getSource() == e.getSource());
328         }
329
330         if (!found)
331             folderAddedList[1 - swap].add(e);
332
333         mutex.release();
334     }
335
336     /**
337      * @see org.columba.mail.folder.event.FolderListener#folderRemoved(IFolderEvent)
338      */

339     public void folderRemoved(IFolderEvent e) {
340         mutex.lock();
341
342         Iterator JavaDoc it = folderRemovedList[1 - swap].iterator();
343         boolean found = false;
344         while (it.hasNext() && !found) {
345             FolderEvent event = (FolderEvent) it.next();
346             found = (event.getSource() == e.getSource());
347         }
348
349         if (!found)
350             folderRemovedList[1 - swap].add(e);
351
352         mutex.release();
353     }
354
355     /**
356      * @see org.columba.mail.folder.event.FolderListener#folderPropertyChanged(IFolderEvent)
357      */

358     public void folderPropertyChanged(IFolderEvent e) {
359         mutex.lock();
360
361         Iterator JavaDoc it = folderPropertyChangedList[1 - swap].iterator();
362         boolean found = false;
363         while (it.hasNext() && !found) {
364             FolderEvent event = (FolderEvent) it.next();
365             found = (event.getSource() == e.getSource());
366         }
367
368         if (!found)
369             folderPropertyChangedList[1 - swap].add(e);
370
371         mutex.release();
372
373     }
374
375     /**
376      * @see org.columba.mail.folder.event.FolderListener#messageAdded(IFolderEvent)
377      */

378     public void messageAdded(IFolderEvent e) {
379         mutex.lock();
380
381         Iterator JavaDoc it = messageAddedList[1 - swap].iterator();
382         boolean found = false;
383         while (it.hasNext() && !found) {
384             FolderEvent event = (FolderEvent) it.next();
385             found = (event.getSource() == e.getSource());
386         }
387
388         if (!found)
389             messageAddedList[1 - swap].add(e);
390
391         mutex.release();
392     }
393
394     /**
395      * @see org.columba.mail.folder.event.FolderListener#messageFlagChanged(iFolderEvent)
396      */

397     public void messageFlagChanged(IFolderEvent e) {
398         mutex.lock();
399
400         messageFlagChangedList[1 - swap].add(e);
401
402         mutex.release();
403
404     }
405
406     /**
407      * @see org.columba.mail.folder.event.FolderListener#messageRemoved(IFolderEvent)
408      */

409     public void messageRemoved(IFolderEvent e) {
410         mutex.lock();
411
412         messageRemovedList[1 - swap].add(e);
413
414         mutex.release();
415     }
416
417     /** ********************* Table Listener **************************** */
418
419     /**
420      * Adds a listener.
421      */

422     public void addTableListener(TableModelChangedListener l) {
423         tableListenerList.add(TableModelChangedListener.class, l);
424     }
425
426     /**
427      * Removes a previously registered listener.
428      */

429     public void removeTableListener(TableModelChangedListener l) {
430         tableListenerList.remove(TableModelChangedListener.class, l);
431     }
432
433     private void fireTableEvent(TableModelChangedEvent e) {
434         // Guaranteed to return a non-null array
435
Object JavaDoc[] listeners = tableListenerList.getListenerList();
436
437         // Process the listeners last to first, notifying
438
// those that are interested in this event
439
for (int i = listeners.length - 2; i >= 0; i -= 2) {
440             if (listeners[i] == TableModelChangedListener.class) {
441                 TableModelChangedListener listener = (TableModelChangedListener) listeners[i + 1];
442                 if (listener.isInterestedIn(e.getSrcFolder())) {
443                     listener.tableChanged(e);
444                 }
445             }
446         }
447     }
448
449 }
450
451 class FolderEventComparator implements Comparator JavaDoc {
452
453     private static FolderEventComparator instance = new FolderEventComparator();
454
455     private FolderEventComparator() {
456     }
457
458     public static FolderEventComparator getInstance() {
459         return instance;
460     }
461
462     /**
463      * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object)
464      */

465     public int compare(Object JavaDoc arg0, Object JavaDoc arg1) {
466         FolderEvent a = (FolderEvent) arg0;
467         FolderEvent b = (FolderEvent) arg1;
468
469         return (a.getSource() != b.getSource()) ? 0 : 1;
470     }
471
472 }
Popular Tags