KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > columba > core > xml > XmlElement


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
package org.columba.core.xml;
17
18 /////////////////////////////////////////////////////////////////////////////
19
// IMPORT STATEMENTS //
20
/////////////////////////////////////////////////////////////////////////////
21
import java.util.Enumeration JavaDoc;
22 import java.util.Hashtable JavaDoc;
23 import java.util.Iterator JavaDoc;
24 import java.util.List JavaDoc;
25 import java.util.Observable JavaDoc;
26 import java.util.Vector JavaDoc;
27
28 /////////////////////////////////////////////////////////////////////////////
29
// CODE //
30
/////////////////////////////////////////////////////////////////////////////
31

32 /**
33  * The XmlElement is a generic containment class for elements within an XML
34  * file.
35  * <p>
36  *
37  * It extends Observable which should be used for gui elements which are
38  * interested in configuration changes.
39  * <p>
40  *
41  * Show interested in:
42  *
43  * <pre>
44  * xmlElement.addObserver(yourObserver);
45  * </pre>
46  *
47  * <p>
48  * When making bigger changes on XmlElement and probably its subnodes and/or a
49  * greater number of attributes at once, you should just change XmlElement
50  * directly and manually notify the Observers by calling:
51  * <p>
52  *
53  * <pre>
54  * xmlElement.setChanged();
55  * xmlElement.notifyObservers();
56  * </pre>
57  *
58  * <p>
59  * There a good introduction for the Observable/Observer pattern in
60  * Model/View/Controller based applications at www.javaworld.com: -
61  * http://www.javaworld.com/javaworld/jw-10-1996/jw-10-howto.html
62  *
63  * @see org.columba.mail.gui.config.general.MailOptionsDialog#initObservables()
64  * @see org.columba.mail.gui.message.viewer.MarkAsReadTimer
65  *
66  * @author Tony Parent, fdietz
67  */

68 public class XmlElement extends Observable JavaDoc implements Cloneable JavaDoc {
69     
70     private static final java.util.logging.Logger JavaDoc LOG =
71         java.util.logging.Logger.getLogger("org.columba.core.xml"); //$NON-NLS-1$
72

73     String JavaDoc name;
74
75     String JavaDoc data;
76
77     Hashtable JavaDoc attributes;
78
79     List JavaDoc subElements;
80
81     XmlElement parent;
82
83     /**
84      * **FIXME** This function needs documentation
85      *
86      * Constructor
87      *
88      */

89     public XmlElement() {
90         subElements = new Vector JavaDoc();
91         this.attributes = new Hashtable JavaDoc(10);
92     }
93
94     /**
95      * **FIXME** This function needs documentation
96      *
97      * Constructor
98      *
99      * @param String
100      * Name
101      *
102      */

103     public XmlElement(String JavaDoc name) {
104         this.name = name;
105         this.attributes = new Hashtable JavaDoc(10);
106         subElements = new Vector JavaDoc();
107         data = "";
108     }
109
110     /**
111      * **FIXME** This function needs documentation
112      *
113      * Constructor
114      *
115      * @param String
116      * Name
117      * @param Hashtable
118      * Attributes
119      *
120      */

121     public XmlElement(String JavaDoc name, Hashtable JavaDoc attributes) {
122         this.name = name;
123         this.attributes = attributes;
124         subElements = new Vector JavaDoc();
125     }
126
127     /**
128      * **FIXME** This function needs documentation
129      *
130      * Constructor
131      *
132      * @param Name
133      * String
134      * @param Data
135      * String
136      *
137      */

138     public XmlElement(String JavaDoc name, String JavaDoc data) {
139         this.name = name;
140         this.data = data;
141         subElements = new Vector JavaDoc();
142         this.attributes = new Hashtable JavaDoc(10);
143     }
144
145     /**
146      * Add attribute to this xml element.
147      *
148      * @param name
149      * name of key
150      * @param value
151      * new attribute value
152      * @return old attribute value
153      *
154      */

155     public Object JavaDoc addAttribute(String JavaDoc name, String JavaDoc value) {
156         if ((value != null) && (name != null)) {
157             Object JavaDoc returnValue = (attributes.put(name, value));
158
159             return returnValue;
160         }
161
162         return null;
163     }
164
165     /**
166      * **FIXME** This function needs documentation
167      *
168      * @return String
169      * @param String
170      * Name
171      *
172      */

173     public String JavaDoc getAttribute(String JavaDoc name) {
174         return ((String JavaDoc) attributes.get(name));
175     }
176
177     public String JavaDoc getAttribute(String JavaDoc name, String JavaDoc defaultValue) {
178         if (getAttribute(name) == null) {
179             addAttribute(name, defaultValue);
180         }
181
182         return getAttribute(name);
183     }
184
185     /**
186      * **FIXME** This function needs documentation
187      *
188      * @return String
189      * @param String
190      * Name
191      *
192      */

193     public Hashtable JavaDoc getAttributes() {
194         return attributes;
195     }
196
197     /**
198      * **FIXME** This function needs documentation
199      *
200      *
201      * @param Attrs
202      * Hashtable to use as the attributes
203      *
204      */

205     public void setAttributes(Hashtable JavaDoc attrs) {
206         attributes = attrs;
207     }
208
209     /**
210      * **FIXME** This function needs documentation
211      *
212      * @return Enumeration
213      *
214      */

215     public Enumeration JavaDoc getAttributeNames() {
216         return (attributes.keys());
217     }
218
219     /**
220      * **FIXME** This function needs documentation
221      *
222      * @return boolean
223      * @param XmlElement
224      * E
225      *
226      */

227     public boolean addElement(XmlElement e) {
228         e.setParent(this);
229
230         return (subElements.add(e));
231     }
232
233     public XmlElement removeElement(XmlElement e) {
234         XmlElement child = null;
235
236         for (int i = 0; i < subElements.size(); i++) {
237             child = (XmlElement) subElements.get(i);
238
239             // FIXME -- This will most likely not work.
240
// You want the element removed if the contents are the same
241
// Not just if the element reference is the same.
242
if (child == e) {
243                 subElements.remove(i);
244             }
245         }
246
247         return (child);
248     }
249
250     public XmlElement removeElement(int index) {
251         return (XmlElement) subElements.remove(index);
252     }
253
254     public void removeAllElements() {
255         subElements.clear();
256     }
257
258     /**
259      * convienience method for the TreeView
260      *
261      * this method is modeled after the DefaultMutableTreeNode-class
262      *
263      * DefaultMutableTreeNode wraps XmlElement for this purpose
264      *
265      */

266     public void removeFromParent() {
267         if (parent == null) {
268             return;
269         }
270
271         parent.removeElement(this);
272         parent = null;
273     }
274
275     public void append(XmlElement e) {
276         e.removeFromParent();
277
278         addElement(e);
279     }
280
281     /**
282      *
283      * convienience method for the TreeView
284      *
285      * @param e
286      * @param index
287      */

288     public void insertElement(XmlElement e, int index) {
289         e.removeFromParent();
290
291         subElements.add(index, e);
292         e.setParent(this);
293     }
294
295     /**
296      * **FIXME** This function needs documentation
297      *
298      * @return Vector
299      *
300      */

301     public List JavaDoc getElements() {
302         return subElements;
303     }
304
305     public int count() {
306         return subElements.size();
307     }
308
309     /**
310      * **FIXME** This function needs documentation
311      *
312      * @return XmlElement
313      * @param String
314      * Path
315      *
316      */

317     public XmlElement getElement(String JavaDoc path) {
318         int i = path.indexOf('/');
319         String JavaDoc topName;
320         String JavaDoc subName;
321
322         if (i == 0) {
323             path = path.substring(1);
324             i = path.indexOf('/');
325         }
326
327         if (i > 0) {
328             topName = path.substring(0, i);
329             subName = path.substring(i + 1);
330         } else {
331             topName = path;
332             subName = null;
333         }
334
335         int j;
336
337         for (j = 0; j < subElements.size(); j++) {
338             if (((XmlElement) subElements.get(j)).getName().equals(topName)) {
339                 if (subName != null) {
340                     return (((XmlElement) subElements.get(j))
341                             .getElement(subName));
342                 } else {
343                     return ((XmlElement) subElements.get(j));
344                 }
345             }
346         }
347
348         return null;
349     }
350
351     public XmlElement getElement(int index) {
352         return (XmlElement) subElements.get(index);
353     }
354
355     /**
356      * Adds a sub element to this one
357      *
358      * @return XmlElement
359      * @param Name
360      * The subpath of the sub element to add
361      *
362      */

363     public XmlElement addSubElement(String JavaDoc path) {
364         XmlElement parent = this;
365         XmlElement child;
366         String JavaDoc name;
367
368         while (path.indexOf('/') != -1) {
369             name = path.substring(0, path.indexOf('/'));
370             path = path.substring(path.indexOf('/') + 1);
371
372             // if path startsWith "/" -> skip
373
if (name.length() == 0)
374                 continue;
375
376             if (parent.getElement(name) != null) {
377                 parent = parent.getElement(name);
378             } else {
379                 child = new XmlElement(name);
380
381                 parent.addElement(child);
382                 parent = child;
383             }
384
385         }
386
387         child = new XmlElement(path);
388         parent.addElement(child);
389
390         return child;
391     }
392
393     /**
394      * Adds a sub element to this one
395      *
396      * @return XmlElement
397      * @param element
398      * The XmlElement to add
399      *
400      */

401     public XmlElement addSubElement(XmlElement e) {
402         e.setParent(this);
403         subElements.add(e);
404
405         return e;
406     }
407
408     /**
409      * Adds a sub element to this one
410      *
411      * @return XmlElement
412      * @param Name
413      * The name of the sub element to add
414      * @param Data
415      * String Data for this element
416      */

417     public XmlElement addSubElement(String JavaDoc name, String JavaDoc data) {
418         XmlElement e = new XmlElement(name);
419         e.setData(data);
420         e.setParent(this);
421         subElements.add(e);
422
423         return e;
424     }
425
426     /**
427      * Sets the parent element
428      *
429      * @param Parent
430      * The XmlElement that contains this one
431      *
432      */

433     public void setParent(XmlElement parent) {
434         this.parent = parent;
435     }
436
437     /**
438      * Gives the XmlElement containing the current element
439      *
440      * @return XmlElement
441      *
442      */

443     public XmlElement getParent() {
444         return parent;
445     }
446
447     /**
448      * Sets the data for this element
449      *
450      * @param D
451      * The String representation of the data
452      *
453      */

454     public void setData(String JavaDoc d) {
455         data = d;
456     }
457
458     /**
459      * Returns the data associated with the current Xml element
460      *
461      * @return String
462      *
463      */

464     public String JavaDoc getData() {
465         return data;
466     }
467
468     /**
469      * Returns the name of the current Xml element
470      *
471      * @return String
472      *
473      */

474     public String JavaDoc getName() {
475         return name;
476     }
477
478     /**
479      * **FIXME** This function needs documentation
480      *
481      * @param out
482      * OutputStream to print the data to
483      *
484      */

485
486     /*
487      * public void write(OutputStream out) throws IOException { PrintWriter PW =
488      * new PrintWriter(out); PW.println(" <?xml version=\"1.0\"
489      * encoding=\"UTF-8\"?>"); if (SubElements.size() > 0) { for (int i = 0; i <
490      * SubElements.size(); i++) { ((XmlElement)
491      * SubElements.get(i))._writeSubNode(PW, 4); } } PW.flush(); }
492      */

493
494     /**
495      * Prints sub nodes to the given data stream
496      *
497      * @param out
498      * PrintWriter to use for printing
499      * @param indent
500      * Number of spaces to indent things
501      *
502      */

503
504     /*
505      * private void _writeSubNode(PrintWriter out, int indent) throws
506      * IOException { _writeSpace(out, indent); out.print(" <" + Name); //if (
507      * Attributes.size()>1) out.print(" ");
508      *
509      * for (Enumeration e = Attributes.keys(); e.hasMoreElements();) { String K =
510      * (String) e.nextElement(); out.print(K + "=\"" + Attributes.get(K) + "\"
511      * b");
512      * } out.print(">");
513      *
514      * if (Data != null && !Data.equals("")) { if (Data.length() > 20) {
515      * out.println(""); _writeSpace(out, indent + 2); } out.print(Data); } if
516      * (SubElements.size() > 0) { out.println(""); for (int i = 0; i <
517      * SubElements.size(); i++) { ((XmlElement)
518      * SubElements.get(i))._writeSubNode( out, indent + 4); } _writeSpace(out,
519      * indent); } out.println(" </" + Name + ">");
520      * }
521      */

522
523     /**
524      * Prints out a given number of spaces
525      *
526      * @param out
527      * PrintWriter to use for printing
528      * @param numSpaces
529      * Number of spaces to print
530      *
531      */

532
533     /*
534      * private void _writeSpace(PrintWriter out, int numSpaces) throws
535      * IOException {
536      *
537      * for (int i = 0; i < numSpaces; i++) out.print(" "); }
538      *
539      * public static void printNode(XmlElement Node, String indent) { String
540      * Data = Node.getData(); if (Data == null || Data.equals("")) {
541      * System.out.println(indent + Node.getName()); } else {
542      * System.out.println(indent + Node.getName() + " = '" + Data + "'"); }
543      * Vector Subs = Node.getElements(); int i, j; for (i = 0; i < Subs.size();
544      * i++) { printNode((XmlElement) Subs.get(i), indent + " "); } }
545      */

546     public static void printNode(XmlElement node, String JavaDoc indent) {
547         String JavaDoc data = node.getData();
548
549         if ((data == null) || data.equals("")) {
550             LOG.info(indent + node.getName());
551         } else {
552             LOG.info(indent + node.getName() + " = '" + data + "'"); //$NON-NLS-1$
553
}
554
555         // print attributes
556
for (Enumeration JavaDoc enumeration = node.getAttributes().keys(); enumeration
557                 .hasMoreElements();) {
558             String JavaDoc key = (String JavaDoc) enumeration.nextElement();
559             String JavaDoc value = node.getAttribute(key);
560             LOG.info(indent + key + ":" + value); //$NON-NLS-1$
561
}
562
563         List JavaDoc subs = node.getElements();
564         
565         for (Iterator JavaDoc it = subs.iterator(); it.hasNext();) {
566             printNode((XmlElement) it.next(), indent + " ");
567
568             // for (i = 0; i < subs.size(); i++) {
569
// printNode((XmlElement) subs.get(i), indent + " ");
570
}
571     }
572
573     /** {@inheritDoc} */
574     public Object JavaDoc clone() {
575         try {
576             XmlElement clone = (XmlElement) super.clone(); // creates a shallow
577
// copy of this
578
// object
579

580             if (attributes != null) {
581                 clone.setAttributes((Hashtable JavaDoc) getAttributes().clone());
582             }
583
584             if (subElements != null) {
585                 clone.subElements = new Vector JavaDoc();
586
587                 List JavaDoc childs = getElements();
588                 XmlElement child;
589
590                 for (Iterator JavaDoc it = childs.iterator(); it.hasNext();) {
591                     child = (XmlElement) it.next();
592
593                     // for( int i=0; i<childs.size(); i++ ) {
594
// child = (XmlElement) childs.get(i);
595
clone.addSubElement((XmlElement) child.clone());
596                 }
597             }
598
599             return clone;
600         } catch (CloneNotSupportedException JavaDoc cnse) {
601             throw new InternalError JavaDoc("Could not clone XmlElement: " + cnse);
602         }
603     }
604
605     /**
606      * Sets the name.
607      *
608      * @param name
609      * The name to set
610      */

611     public void setName(String JavaDoc name) {
612         this.name = name;
613     }
614
615     /**
616      * Notify all Observers.
617      *
618      * @see java.util.Observable#notifyObservers()
619      */

620     public void notifyObservers() {
621         setChanged();
622         super.notifyObservers();
623     }
624
625     /**
626      * Returns true if the specified objects are equal. They are equal if they
627      * are both null OR if the <code>equals()</code> method return true. (
628      * <code>obj1.equals(obj2)</code>).
629      *
630      * @param obj1
631      * first object to compare with.
632      * @param obj2
633      * second object to compare with.
634      * @return true if they represent the same object; false if one of them is
635      * null or the <code>equals()</code> method returns false.
636      */

637     private boolean equals(Object JavaDoc obj1, Object JavaDoc obj2) {
638         boolean equal = false;
639
640         if ((obj1 == null) && (obj2 == null)) {
641             equal = true;
642         } else if ((obj1 != null) && (obj2 != null)) {
643             equal = obj1.equals(obj2);
644         }
645
646         return equal;
647     }
648
649     /** {@inheritDoc} */
650     public boolean equals(Object JavaDoc obj) {
651         boolean equal = false;
652
653         if ((obj != null) && (obj instanceof XmlElement)) {
654             XmlElement other = (XmlElement) obj;
655
656             if (equals(attributes, other.attributes)
657                     && equals(data, other.data) && equals(name, other.name)
658                     && equals(subElements, other.subElements)) {
659                 equal = true;
660             }
661         }
662
663         return equal;
664     }
665
666     /** {@inheritDoc} */
667     public int hashCode() {
668         //Hashcode value should be buffered.
669
int hashCode = 23;
670
671         if (attributes != null) {
672             hashCode += (attributes.hashCode() * 13);
673         }
674
675         if (data != null) {
676             hashCode += (data.hashCode() * 17);
677         }
678
679         if (name != null) {
680             hashCode += (name.hashCode() * 29);
681         }
682
683         if (subElements != null) {
684             hashCode += (subElements.hashCode() * 57);
685         }
686
687         return hashCode;
688     }
689
690     /**
691      * @see java.lang.Object#toString()
692      */

693     public String JavaDoc toString() {
694         return getName();
695     }
696 }
697
698 // END public class XmlElement
699
Popular Tags