KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > enhydra > xml > xmlc > metadata > MetaDataElement


1 /*
2  * Enhydra Java Application Server Project
3  *
4  * The contents of this file are subject to the Enhydra Public License
5  * Version 1.1 (the "License"); you may not use this file except in
6  * compliance with the License. You may obtain a copy of the License on
7  * the Enhydra web site ( http://www.enhydra.org/ ).
8  *
9  * Software distributed under the License is distributed on an "AS IS"
10  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
11  * the License for the specific terms governing rights and limitations
12  * under the License.
13  *
14  * The Initial Developer of the Enhydra Application Server is Lutris
15  * Technologies, Inc. The Enhydra Application Server and portions created
16  * by Lutris Technologies, Inc. are Copyright Lutris Technologies, Inc.
17  * All Rights Reserved.
18  *
19  * Contributor(s):
20  *
21  * $Id: MetaDataElement.java,v 1.3 2005/01/26 08:29:24 jkjome Exp $
22  */

23
24 package org.enhydra.xml.xmlc.metadata;
25
26 import java.lang.reflect.Array JavaDoc;
27 import java.util.StringTokenizer JavaDoc;
28
29 import org.enhydra.apache.xerces.dom.DocumentImpl;
30 import org.enhydra.apache.xerces.dom.ElementImpl;
31 import org.enhydra.xml.xmlc.XMLCException;
32 import org.w3c.dom.Attr JavaDoc;
33 import org.w3c.dom.Document JavaDoc;
34 import org.w3c.dom.Element JavaDoc;
35 import org.w3c.dom.NamedNodeMap JavaDoc;
36 import org.w3c.dom.Node JavaDoc;
37
38 /**
39  * Base DOM class for all XMLC metadata element classes. This provides
40  * methods to implement attribute and child lookup
41  */

42 public class MetaDataElement extends ElementImpl {
43     /**
44      * An empty string array.
45      */

46     private static final String JavaDoc[] emptyStringArray = new String JavaDoc[0];
47
48     /**
49      * This is the change counter of the object taken when it was
50      * marked as being allDefaults. This is used to determine if
51      * a node as any custom values in or are only defaults.
52      * FIXME: implement
53      */

54
55     /**
56      * Constructor.
57      */

58     protected MetaDataElement(Document JavaDoc ownerDoc,
59                               String JavaDoc name) {
60         super((DocumentImpl)ownerDoc, name);
61     }
62
63     /**
64      * Get the metadata document object.
65      */

66     public MetaDataDocument getDocument() {
67         return (MetaDataDocument)getOwnerDocument();
68     }
69
70     /**
71      * Get the metadata root element object.
72      */

73     public MetaData getMetaData() {
74         return getDocument().getMetaData();
75     }
76
77     // FIXME: the mechanism for defaulting children and the creation
78
// on the fly of needed children may have some undesriable
79
// side affects (if one child updates another). What really
80
// needs to happen is that the defaulted child are all created
81
// initialally and marked as defaulted.
82

83     /**
84      * Locate a child element given its class. This is used when only
85      * a single instance of an element can be a child.
86      *
87      * @return The first child elment of the specified class.
88      */

89     protected MetaDataElement getCreateChild(Class JavaDoc elementClass) {
90         Node JavaDoc child = getChild(elementClass);
91         if (child == null) {
92             // Need to create
93
child = getDocument().createElement(elementClass);
94             appendChild(child);
95         }
96         return (MetaDataElement)child;
97     }
98
99     /**
100      * Locate a child element given its class, creating if if it doesn't
101      * exist.
102      *
103      * @return The first child elment of the specified class or null
104      * in no child element implements the class.
105      */

106     protected MetaDataElement getChild(Class JavaDoc elementClass) {
107         for (Node JavaDoc child = getFirstChild(); child != null;
108              child = child.getNextSibling()) {
109             if (elementClass.isInstance(child)) {
110                 return (MetaDataElement)child;
111             }
112         }
113         return null;
114     }
115
116     /**
117      * Add or replace a child element. This is used when only
118      * a single instance of an element can be a child.
119      */

120     protected void setChild(MetaDataElement element) {
121         Node JavaDoc current = getChild(element.getClass());
122         if (current == null) {
123             appendChild(element);
124         } else {
125             replaceChild(element, current);
126         }
127     }
128
129     /**
130      * Delete a child element given its class. This is used when only
131      * a single instance of an element can be a child. If the element
132      * does not exist, the call is ignored.
133      */

134     protected void deleteChild(Class JavaDoc elementClass) {
135         Node JavaDoc current = getChild(elementClass.getClass());
136         if (current != null) {
137             removeChild(current);
138         }
139     }
140
141     /**
142      * Get all children of the specified class.
143      */

144     protected Node JavaDoc[] getChildren(Class JavaDoc elementClass) {
145         // Count
146
int numChildren = 0;
147         for (Node JavaDoc child = getFirstChild(); child != null;
148              child = child.getNextSibling()) {
149             if (elementClass.isInstance(child)) {
150                 numChildren++;
151             }
152         }
153         
154         // Create array of the children
155
Node JavaDoc[] children = (Node JavaDoc[])Array.newInstance(elementClass, numChildren);
156         int idx = 0;
157         for (Node JavaDoc child = getFirstChild();
158              (child != null) && (idx < numChildren);
159              child = child.getNextSibling()) {
160             if (elementClass.isInstance(child)) {
161                 children[idx++] = child;
162             }
163         }
164         return children;
165     }
166
167
168     /**
169      * Determine if an attribute is specified.
170      */

171     protected boolean isAttributeSpecified(String JavaDoc attrName) {
172         Attr JavaDoc attr = getAttributeNode(attrName);
173         if (attr == null) {
174             return false;
175         } else {
176             return attr.getSpecified();
177         }
178     }
179     
180
181     /**
182      * Get the value of a boolean object attribute. Boolean objects
183      * are used ot value that can be true, false, or unspecified.
184      *
185      * @param attrName The name of the attribute.
186      * @return The value of the object, or null if it doesn't exists.
187      */

188     protected Boolean JavaDoc getBooleanObjectAttribute(String JavaDoc attrName) {
189         String JavaDoc attrValue = getAttributeNull(attrName);
190         if (attrValue == null) {
191             return null;
192         } else {
193             if (attrValue.equalsIgnoreCase("true")
194                 || attrValue.equalsIgnoreCase("yes")) {
195                 return Boolean.TRUE;
196             } else {
197                 return Boolean.FALSE;
198             }
199         }
200     }
201
202     /**
203      * Set or delete the value of a boolean object attribute. Boolean objects
204      * are used for value that can be true, false, or unspecified.
205      *
206      * @param attrName The name of the attribute.
207      * @param value The value of the attribute, or null to delete.
208      */

209     protected void setBooleanObjectAttribute(String JavaDoc attrName,
210                                              Boolean JavaDoc value) {
211         if (value == null) {
212             removeAttribute(attrName);
213         } else {
214             setAttribute(attrName, value.toString());
215         }
216     }
217
218     /**
219      * Get the value of a boolean primitive attribute.
220      *
221      * @param attrName The name of the attribute.
222      * @param defaultValue Value to return if attribute doesn't exist.
223      * @return The value of the object.
224      */

225     protected boolean getBooleanAttribute(String JavaDoc attrName,
226                                           boolean defaultValue) {
227         String JavaDoc attrValue = getAttributeNull(attrName);
228         if (attrValue == null) {
229             return defaultValue;
230         } else {
231             if (attrValue.equalsIgnoreCase("true")
232                 || attrValue.equalsIgnoreCase("yes")) {
233                 return true;
234             } else {
235                 return false;
236             }
237         }
238     }
239
240     /**
241      * Get the value of a boolean primitive attribute, with the default
242      * being false.
243      *
244      * @param attrName The name of the attribute.
245      * @return The value of the object.
246      */

247     protected boolean getBooleanAttribute(String JavaDoc attrName) {
248         return getBooleanAttribute(attrName, false);
249     }
250
251     /**
252      * Set the value of a boolean primitive attribute.
253      *
254      * @param attrName The name of the attribute.
255      * @param value The value of the attribute.
256      * @param defaultValue The default value for the attribute.
257      * If the value matches the default value, the attribute
258      * is removed rather than set. This must match the default
259      * passed to get.
260      */

261     protected void setBooleanAttribute(String JavaDoc attrName,
262                                        boolean value,
263                                        boolean defaultValue) {
264         if (value == defaultValue) {
265             removeAttribute(attrName);
266         } else {
267             setAttribute(attrName, (value ? "true" : "false"));
268         }
269     }
270
271     /**
272      * Set the value of a boolean primitive attribute, with a
273      * default of false.
274      *
275      * @param attrName The name of the attribute.
276      * @param value The value of the attribute.
277      */

278     protected void setBooleanAttribute(String JavaDoc attrName,
279                                        boolean value) {
280         setBooleanAttribute(attrName, value, false);
281     }
282
283     /**
284      * Get the value of a string attribute, or null if its not defined.
285      */

286     protected String JavaDoc getAttributeNull(String JavaDoc attrName) {
287         Attr JavaDoc attr = getAttributeNode(attrName);
288         if (attr == null) {
289             return null;
290         } else {
291             return attr.getValue();
292         }
293     }
294
295     /**
296      * Set or remove a string attribute. If the value is null, it is removed.
297      */

298     protected void setRemoveAttribute(String JavaDoc attrName,
299                                       String JavaDoc value) {
300         if (value == null) {
301             removeAttribute(attrName);
302         } else {
303             setAttribute(attrName, value);
304         }
305     }
306
307     /**
308      * Get the value of a String array attribute.
309      */

310     protected String JavaDoc[] getStringArrayAttribute(String JavaDoc attrName) {
311         String JavaDoc value = getAttributeNull(attrName);
312         String JavaDoc[] values;
313         if (value == null) {
314             values = emptyStringArray;
315         } else {
316             // Parse into tokens
317
StringTokenizer JavaDoc tokenizer = new StringTokenizer JavaDoc(value);
318             values = new String JavaDoc[tokenizer.countTokens()];
319             for (int idx = 0; idx < values.length; idx++) {
320                 values[idx] = tokenizer.nextToken();
321             }
322         }
323         return values;
324     }
325
326     /**
327      * Set or remove a String array attribute. If the values is null, it is
328      * removed.
329      */

330     protected void setRemoveStringArrayAttribute(String JavaDoc attrName,
331                                                  String JavaDoc[] values) {
332         if (values == null) {
333             removeAttribute(attrName);
334         } else {
335             // Join into a string.
336
StringBuffer JavaDoc value = new StringBuffer JavaDoc();
337             for (int idx = 0; idx < values.length; idx++) {
338                 if (idx > 0) {
339                     value.append(' ');
340                 }
341                 value.append(values[idx]);
342             }
343             setAttribute(attrName, value.toString());
344         }
345     }
346
347     /**
348      * Add a addtribute to a String array attribute.
349      */

350     protected void addStringArrayAttribute(String JavaDoc attrName,
351                                            String JavaDoc value) {
352         String JavaDoc currentValue = getAttributeNull(attrName);
353         if (currentValue == null) {
354             currentValue = "";
355         }
356         StringBuffer JavaDoc currentBuf = new StringBuffer JavaDoc(currentValue);
357         if (currentBuf.length() > 0) {
358             currentBuf.append(' ');
359         }
360         currentBuf.append(value);
361         setAttribute(attrName, currentBuf.toString());
362     }
363
364     /**
365      * Complete modifications to DOM. This method is called on all elements
366      * in the DOM in a bottom-first manner once a read or set of modifications
367      * are complete. Elements should override this method if they need to do
368      * any processing. Normally, they will call super.completeModifications()
369      * first to traverse the subtree, then do their work. This is also useful
370      * in report errors upfront rather than at access time.
371      */

372     protected void completeModifications() throws XMLCException {
373         for (Node JavaDoc child = getFirstChild();
374              child != null;
375              child = child.getNextSibling()) {
376             if (child instanceof MetaDataElement) {
377                 ((MetaDataElement)child).completeModifications();
378             }
379         }
380     }
381
382     /**
383      * Merge attributes from another element into this element,
384      * with the other element overriding current attributes.
385      */

386     protected void mergeAttributes(Element JavaDoc srcElement) {
387         Document JavaDoc doc = getOwnerDocument();
388         NamedNodeMap JavaDoc attrs = srcElement.getAttributes();
389         int len = attrs.getLength();
390         for (int idx = 0; idx < len; idx++) {
391             Attr JavaDoc attr = (Attr JavaDoc)attrs.item(idx);
392             if (attr.getSpecified()) {
393                 setAttributeNode((Attr JavaDoc)doc.importNode(attr, true));
394             }
395         }
396     }
397     
398     /**
399      * Merge a specified singleton child node, if it exists, otherwise
400      * clone it (if it exists).
401      */

402     protected void mergeSingletonChild(Class JavaDoc childClass,
403                                        MetaDataElement srcElement) {
404         MetaDataElement srcChild = srcElement.getChild(childClass);
405         if (srcChild != null) {
406             MetaDataElement destChild = getChild(childClass);
407             if (destChild != null) {
408                 destChild.mergeElement(srcChild);
409             } else {
410                 appendChild(getOwnerDocument().importNode(srcChild, true));
411             }
412         }
413     }
414     
415     /**
416      * Merge another element into this element. This merges the attributes,
417      * the children and then appends clones the children. This
418      * maybe overriden. In particular, calling mergeElement to
419      * merge children is desired if there should only be one child of
420      * a particular type.
421      */

422     protected void mergeElement(MetaDataElement srcElement) {
423         mergeAttributes(srcElement);
424
425         Document JavaDoc document = getOwnerDocument();
426         for (Node JavaDoc child = srcElement.getFirstChild();
427              child != null;
428              child = child.getNextSibling()) {
429             appendChild(document.importNode(child, true));
430         }
431     }
432 }
433
Popular Tags