KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > columba > mail > folder > AbstractFolder


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;
18
19 import java.util.logging.Logger JavaDoc;
20
21 import javax.swing.event.EventListenerList JavaDoc;
22 import javax.swing.tree.DefaultMutableTreeNode JavaDoc;
23 import javax.swing.tree.TreeNode JavaDoc;
24 import javax.swing.tree.TreePath JavaDoc;
25
26 import org.columba.core.base.Lock;
27 import org.columba.core.xml.XmlElement;
28 import org.columba.mail.config.FolderItem;
29 import org.columba.mail.config.IFolderItem;
30 import org.columba.mail.folder.event.FolderEvent;
31 import org.columba.mail.folder.event.FolderEventDelegator;
32 import org.columba.mail.folder.event.IFolderListener;
33
34 /**
35  * Represents a treenode and is the abstract class every folder extends.
36  * <p>
37  * See tree.xml configuration file.
38  *
39  * @author fdietz
40  */

41 public abstract class AbstractFolder extends DefaultMutableTreeNode JavaDoc implements IMailFolder {
42
43     
44     /** JDK 1.4+ logging framework logger, used for logging. */
45     private static final Logger JavaDoc LOG = Logger
46             .getLogger("org.columba.mail.folder");
47
48     // the next new folder will get this UID
49
private static int nextUid = 0;
50
51     // folderitem wraps xml configuration from tree.xml
52
protected IFolderItem node;
53
54     // locking mechanism
55
protected Lock myLock = new Lock();
56
57     // Root folder cache
58
private IMailFolder rootFolder;
59
60     protected EventListenerList JavaDoc listenerList = new EventListenerList JavaDoc();
61
62     public AbstractFolder(String JavaDoc name, String JavaDoc type) {
63         super();
64
65         XmlElement defaultElement = new XmlElement("folder");
66         defaultElement.addAttribute("type", type);
67         defaultElement.addAttribute("uid", Integer.toString(nextUid++));
68         defaultElement.addElement(new XmlElement("property"));
69
70         setConfiguration(new FolderItem(defaultElement));
71         try {
72             setName(name);
73         } catch (Exception JavaDoc e) {
74             LOG.severe(e.getMessage());
75         }
76
77         // register interest on tree node changes
78
addFolderListener(FolderEventDelegator.getInstance());
79     }
80
81     public AbstractFolder() {
82         super();
83
84         // register interest on tree node changes
85
addFolderListener(FolderEventDelegator.getInstance());
86     }
87
88     public AbstractFolder(FolderItem node) {
89         super();
90         setConfiguration(node);
91
92         // register interest on tree node changes
93
addFolderListener(FolderEventDelegator.getInstance());
94     }
95
96     /**
97      * Overwritten DefaultMutableTreeNode.add(MutableTreeNode) in favor of
98      * our interface
99      *
100      * @see org.columba.mail.folder.IMailFolder#add(org.columba.mail.folder.IMailFolder)
101      */

102     public void add(IMailFolder treeNode) {
103         super.add(treeNode);
104     }
105     
106     /**
107      * Adds a listener.
108      */

109     public void addFolderListener(IFolderListener l) {
110         listenerList.add(IFolderListener.class, l);
111     }
112
113     /**
114      * Removes a previously registered listener.
115      */

116     public void removeFolderListener(IFolderListener l) {
117         listenerList.remove(IFolderListener.class, l);
118     }
119
120     /**
121      * Propagates an event to all registered listeners notifying them that this
122      * folder has been renamed.
123      */

124     public void fireFolderPropertyChanged() {
125         FolderEvent e = new FolderEvent(this);
126         // Guaranteed to return a non-null array
127
Object JavaDoc[] listeners = listenerList.getListenerList();
128
129         // Process the listeners last to first, notifying
130
// those that are interested in this event
131
for (int i = listeners.length - 2; i >= 0; i -= 2) {
132             if (listeners[i] == IFolderListener.class) {
133                 ((IFolderListener) listeners[i + 1]).folderPropertyChanged(e);
134             }
135         }
136     }
137
138     /**
139      * Propagates an event to all registered listeners notifying them that a
140      * subfolder has been added to this folder.
141      */

142     public void fireFolderAdded(IMailFolder folder) {
143         FolderEvent e = new FolderEvent(this, folder);
144         // Guaranteed to return a non-null array
145
Object JavaDoc[] listeners = listenerList.getListenerList();
146
147         // Process the listeners last to first, notifying
148
// those that are interested in this event
149
for (int i = listeners.length - 2; i >= 0; i -= 2) {
150             if (listeners[i] == IFolderListener.class) {
151                 ((IFolderListener) listeners[i + 1]).folderAdded(e);
152             }
153         }
154     }
155
156     /**
157      * Propagates an event to all registered listeners notifying them that this
158      * folder has been removed from its parent folder. This method removes all
159      * registered listeners.
160      */

161     public void fireFolderRemoved() {
162         FolderEvent e = new FolderEvent(this, this);
163         // Guaranteed to return a non-null array
164
Object JavaDoc[] listeners = listenerList.getListenerList();
165
166         // Process the listeners last to first, notifying
167
// those that are interested in this event
168
for (int i = listeners.length - 2; i >= 0; i -= 2) {
169             if (listeners[i] == IFolderListener.class) {
170                 ((IFolderListener) listeners[i + 1]).folderRemoved(e);
171                 listenerList.remove(IFolderListener.class,
172                         (IFolderListener) listeners[i + 1]);
173             }
174         }
175     }
176
177     /**
178      * Method getSelectionTreePath.
179      *
180      * @return TreePath
181      */

182     public TreePath JavaDoc getSelectionTreePath() {
183         return new TreePath JavaDoc(getPathToRoot(this, 0));
184     }
185
186     /**
187      * @see javax.swing.tree.DefaultMutableTreeNode#getPathToRoot(TreeNode, int)
188      */

189     protected TreeNode JavaDoc[] getPathToRoot(TreeNode JavaDoc aNode, int depth) {
190         TreeNode JavaDoc[] retNodes;
191
192         if (aNode == null) {
193             if (depth == 0) {
194                 return null;
195             } else {
196                 retNodes = new TreeNode JavaDoc[depth];
197             }
198         } else {
199             depth++;
200             retNodes = getPathToRoot(aNode.getParent(), depth);
201             retNodes[retNodes.length - depth] = aNode;
202         }
203
204         return retNodes;
205     }
206
207     /**
208      * Return tree path as string
209      *
210      * @return String tree path
211      */

212     public String JavaDoc getTreePath() {
213         TreeNode JavaDoc[] treeNode = getPathToRoot(this, 0);
214
215         StringBuffer JavaDoc path = new StringBuffer JavaDoc();
216
217         for (int i = 1; i < treeNode.length; i++) {
218             AbstractFolder folder = (AbstractFolder) treeNode[i];
219             path.append("/" + folder.getName());
220         }
221
222         return path.toString();
223     }
224     
225     /**
226      * Returns the folder's UID.
227      */

228     public String JavaDoc getId() {
229         return node.get("uid");
230     }
231
232     /**
233      * Returns the folder's configuration.
234      */

235     public IFolderItem getConfiguration() {
236         return node;
237     }
238
239     /**
240      * Sets the folder's configuration.
241      */

242     public void setConfiguration(IFolderItem node) {
243         this.node = node;
244
245         try {
246             if (node.getInteger("uid") >= nextUid) {
247                 nextUid = node.getInteger("uid") + 1;
248             }
249         } catch (NumberFormatException JavaDoc ex) {
250             node.setInteger("uid", nextUid++);
251         }
252     }
253
254     public String JavaDoc getType() {
255         IFolderItem item = getConfiguration();
256         
257         return item.get("type");
258     }
259     
260     /**
261      * Returns the folder's name.
262      */

263     public String JavaDoc getName() {
264         String JavaDoc name = null;
265
266         IFolderItem item = getConfiguration();
267         name = item.getString("property", "name");
268
269         //(tstich) it is necessary to return null because imap account
270
//creation needs it!
271
//if ( name == null ) name = "FIXME";
272

273         return name;
274     }
275
276     public String JavaDoc toString() {
277         return getName();
278     }
279
280     /**
281      * Sets the folder's name. This method notifies registered FolderListeners.
282      */

283     public void setName(String JavaDoc newName) throws Exception JavaDoc {
284         IFolderItem item = getConfiguration();
285         item.setString("property", "name", newName);
286         fireFolderPropertyChanged();
287     }
288     
289     /*
290     public MailFolderCommandReference getCommandReference(MailFolderCommandReference r) {
291         return r;
292     }
293     */

294
295     /**
296      * ******************************** locking mechanism
297      * ***************************
298      */

299     public boolean tryToGetLock(Object JavaDoc locker) {
300         return myLock.tryToGetLock(locker);
301     }
302
303     public void releaseLock(Object JavaDoc locker) {
304         myLock.release(locker);
305     }
306
307     /**
308      * ************************** treenode management
309      * ******************************
310      */

311     public void insert(IMailFolder newFolder, int newIndex) {
312         IMailFolder oldParent = (IMailFolder) newFolder.getParent();
313         int oldIndex = oldParent.getIndex(newFolder);
314         oldParent.remove(oldIndex);
315
316         XmlElement oldParentNode = oldParent.getConfiguration().getRoot();
317         XmlElement newChildNode = newFolder.getConfiguration().getRoot();
318         oldParentNode.removeElement(newChildNode);
319
320         newFolder.setParent(this);
321         children.insertElementAt(newFolder, newIndex);
322
323         XmlElement newParentNode = getConfiguration().getRoot();
324
325         int j = -1;
326         boolean inserted = false;
327
328         for (int i = 0; i < newParentNode.count(); i++) {
329             XmlElement n = newParentNode.getElement(i);
330             String JavaDoc name = n.getName();
331
332             if (name.equals("folder")) {
333                 j++;
334             }
335
336             if (j == newIndex) {
337                 newParentNode.insertElement(newChildNode, i);
338                 inserted = true;
339             }
340         }
341
342         if (!inserted) {
343             if ((j + 1) == newIndex) {
344                 newParentNode.append(newChildNode);
345             }
346         }
347     }
348
349     /**
350      * Removes this folder from its parent. This method will notify registered
351      * FolderListeners.
352      */

353     public void removeFolder() throws Exception JavaDoc {
354         // remove XmlElement
355
getConfiguration().getRoot().getParent().removeElement(
356                 getConfiguration().getRoot());
357
358         // notify listeners
359
fireFolderRemoved();
360         
361     }
362
363     /**
364      * Adds a child folder to this folder. This method will notify registered
365      * FolderListeners.
366      */

367     public void addSubfolder(IMailFolder child) throws Exception JavaDoc {
368         getConfiguration().getRoot().addElement(
369                 child.getConfiguration().getRoot());
370         fireFolderAdded(child);
371     }
372
373     public AbstractFolder findChildWithName(String JavaDoc str, boolean recurse) {
374         return findChildWithName(str, recurse, null);
375     }
376
377     public AbstractFolder findChildWithName(String JavaDoc str, boolean recurse, Class JavaDoc type) {
378         for (int i = 0; i < getChildCount(); i++) {
379             AbstractFolder child = (AbstractFolder) getChildAt(i);
380             // Check the type
381
if( type != null && !type.equals(child.getClass()) ) continue;
382             
383             String JavaDoc name = child.getName();
384
385             if (name.equalsIgnoreCase(str)) {
386                 return child;
387             } else if (recurse) {
388                 AbstractFolder subchild = child.findChildWithName(str, true);
389
390                 if (subchild != null) {
391                     return subchild;
392                 }
393             }
394         }
395
396         return null;
397     }
398
399     public AbstractFolder findChildWithUID(String JavaDoc uid, boolean recurse) {
400         for (int i = 0; i < getChildCount(); i++) {
401             AbstractFolder child = (AbstractMessageFolder) getChildAt(i);
402             String JavaDoc childUid = child.getId();
403
404             if (uid.equals(childUid)) {
405                 return child;
406             } else if (recurse) {
407                 AbstractFolder subchild = child.findChildWithUID(uid, true);
408
409                 if (subchild != null) {
410                     return subchild;
411                 }
412             }
413         }
414
415         return null;
416     }
417
418     /**
419      *
420      * AbstractFolder wraps XmlElement
421      *
422      * all treenode manipulation is passed to the corresponding XmlElement
423      */

424     public void moveTo(IMailFolder newParent) {
425         // do the same for the XmlElement node
426
getConfiguration().getRoot().removeFromParent();
427         
428         // do the same for the XmlElement of child
429
newParent.getConfiguration().getRoot().addElement(
430                 getConfiguration().getRoot());
431
432         newParent.fireFolderAdded(this);
433     }
434
435     /** ******************* capabilities ************************************* */
436     /**
437      * Does this treenode support adding messages?
438      *
439      * @return true, if this folder is able to contain messages, false otherwise
440      *
441      */

442     public boolean supportsAddMessage() {
443         return false;
444     }
445
446     /**
447      * Returns true if this folder can have sub folders of the specified type;
448      * false otherwise.
449      *
450      * @param newFolderType
451      * the folder that is going to be inserted as a child.
452      * @return true if this folder can have sub folders; false otherwise.
453      */

454     public boolean supportsAddFolder(String JavaDoc newFolderType) {
455         return false;
456     }
457
458     /**
459      * Returns true if this folder type can be moved around in the folder tree.
460      *
461      * @return true if this folder type can be moved around in the folder tree.
462      */

463     public boolean supportsMove() {
464         return false;
465     }
466
467     /**
468      * Return the root folder of this folder.
469      * <p>
470      * This is especially useful when using IMAP. IMAP has a root folder which
471      * is labelled with the account name.
472      *
473      * @return root parent folder of this folder
474      */

475     public IMailFolder getRootFolder() {
476         // If rootFolder is not cached traverse the tree
477
if (rootFolder == null) {
478             IMailFolder parent = (IMailFolder) getParent();
479
480             // There is no parent
481
if (parent == null) {
482                 return this;
483             }
484
485             if (parent instanceof RootFolder) {
486                 rootFolder = parent;
487             } else {
488                 rootFolder = parent.getRootFolder();
489             }
490         }
491
492         return rootFolder;
493     }
494
495 }
Popular Tags