KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jibx > extras > Dom4JMapperBase


1 /*
2 Copyright (c) 2004, Dennis M. Sosnoski
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without modification,
6 are permitted provided that the following conditions are met:
7
8  * Redistributions of source code must retain the above copyright notice, this
9    list of conditions and the following disclaimer.
10  * Redistributions in binary form must reproduce the above copyright notice,
11    this list of conditions and the following disclaimer in the documentation
12    and/or other materials provided with the distribution.
13  * Neither the name of JiBX nor the names of its contributors may be used
14    to endorse or promote products derived from this software without specific
15    prior written permission.
16
17 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
18 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
21 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
24 ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */

28
29 package org.jibx.extras;
30
31 import java.io.IOException JavaDoc;
32 import java.util.ArrayList JavaDoc;
33 import java.util.List JavaDoc;
34
35 import org.dom4j.Attribute;
36 import org.dom4j.DocumentFactory;
37 import org.dom4j.Element;
38 import org.dom4j.Namespace;
39 import org.dom4j.Node;
40 import org.dom4j.ProcessingInstruction;
41 import org.dom4j.QName;
42 import org.jibx.runtime.JiBXException;
43 import org.jibx.runtime.impl.UnmarshallingContext;
44
45 /**
46  * <p>Base implementation for custom marshaller/unmarshallers to dom4j
47  * representation. This provides the basic code used for both single element and
48  * content list handling.</p>
49  *
50  * @author Dennis M. Sosnoski
51  * @version 1.0
52  */

53
54 public class Dom4JMapperBase extends DocumentModelMapperBase
55 {
56     /** dom4j component construction factory. */
57     private static DocumentFactory s_factory = DocumentFactory.getInstance();
58     
59     /** Current default namespace URI (<code>null</code> if not determined). */
60     protected String JavaDoc m_defaultNamespaceURI;
61     
62     /** Current default namespace index. */
63     protected int m_defaultNamespaceIndex;
64     
65     /**
66      * Get index number for declared namespace.
67      *
68      * @param ns namespace of interest
69      * @return namespace index number, or <code>-1</code> if not declared or
70      * masked
71      */

72     
73     private int findNamespaceIndex(Namespace ns) {
74         if (Namespace.NO_NAMESPACE.equals(ns)) {
75             return 0;
76         } else if (Namespace.XML_NAMESPACE.equals(ns)) {
77             return 1;
78         } else {
79             String JavaDoc prefix = ns.getPrefix();
80             if (prefix == null || prefix.length() == 0) {
81                 if (m_defaultNamespaceURI == null) {
82                     int index = m_xmlWriter.getPrefixIndex("");
83                     if (index >= 0) {
84                         m_defaultNamespaceURI = getNamespaceUri(index);
85                         m_defaultNamespaceIndex = index;
86                         if (m_defaultNamespaceURI.equals(ns.getURI())) {
87                             return index;
88                         } else {
89                             return -1;
90                         }
91                     } else {
92                         return -1;
93                     }
94                 } else {
95                     return m_defaultNamespaceURI.equals(ns.getURI()) ?
96                         m_defaultNamespaceIndex : -1;
97                 }
98             } else {
99                 int index = m_xmlWriter.getPrefixIndex(prefix);
100                 if (index >= 0) {
101                     return getNamespaceUri(index).equals(ns.getURI()) ?
102                         index : -1;
103                 } else {
104                     return -1;
105                 }
106             }
107         }
108     }
109     
110     /**
111      * Marshal content list.
112      *
113      * @param content list of content items to marshal
114      * @exception JiBXException on error in marshalling
115      * @exception IOException on error writing to output
116      */

117     
118     protected void marshalContent(List JavaDoc content)
119         throws JiBXException, IOException JavaDoc {
120         int size = content.size();
121         for (int i = 0; i < size; i++) {
122             Node node = (Node)content.get(i);
123             switch (node.getNodeType()) {
124                 
125                 case Node.CDATA_SECTION_NODE:
126                     m_xmlWriter.writeCData(node.getText());
127                     break;
128                 
129                 case Node.COMMENT_NODE:
130                     m_xmlWriter.writeComment(node.getText());
131                     break;
132                 
133                 case Node.ELEMENT_NODE:
134                     marshalElement((Element)node);
135                     break;
136                 
137                 case Node.ENTITY_REFERENCE_NODE:
138                     m_xmlWriter.writeEntityRef(node.getName());
139                     break;
140                 
141                 case Node.PROCESSING_INSTRUCTION_NODE:
142                     m_xmlWriter.writePI(((ProcessingInstruction)node).
143                         getTarget(), node.getText());
144                     break;
145                 
146                 case Node.TEXT_NODE:
147                     m_xmlWriter.writeTextContent(node.getText());
148                     break;
149                 
150                 default:
151                     break;
152             }
153         }
154     }
155     
156     /**
157      * Marshal element with all attributes and content.
158      *
159      * @param element element to be marshalled
160      * @exception JiBXException on error in marshalling
161      * @exception IOException on error writing to output
162      */

163     
164     protected void marshalElement(Element element)
165         throws JiBXException, IOException JavaDoc {
166         
167         // accumulate all needed namespace declarations
168
int size = element.nodeCount();
169         Namespace ns = element.getNamespace();
170         int nsi = findNamespaceIndex(ns);
171         ArrayList JavaDoc nss = null;
172         boolean hascontent = false;
173         int defind = -1;
174         String JavaDoc defuri = null;
175         for (int i = 0; i < size; i++) {
176             Node node = element.node(i);
177             if (node instanceof Namespace) {
178                 Namespace dns = (Namespace)node;
179                 if (findNamespaceIndex(dns) < 0) {
180                     if (nss == null) {
181                         nss = new ArrayList JavaDoc();
182                     }
183                     nss.add(dns);
184                     String JavaDoc prefix = dns.getPrefix();
185                     if (prefix == null || prefix.length() == 0) {
186                         defind = nss.size() - 1;
187                         defuri = dns.getURI();
188                     }
189                 }
190             } else {
191                 hascontent = true;
192             }
193         }
194         
195         // check for namespace declarations required
196
String JavaDoc[] uris = null;
197         if (nss == null) {
198             m_xmlWriter.startTagOpen(nsi, element.getName());
199         } else {
200             int base = getNextNamespaceIndex();
201             if (defind >= 0) {
202                 m_defaultNamespaceIndex = base + defind;
203                 m_defaultNamespaceURI = defuri;
204             }
205             uris = new String JavaDoc[nss.size()];
206             int[] nums = new int[nss.size()];
207             String JavaDoc[] prefs = new String JavaDoc[nss.size()];
208             for (int i = 0; i < uris.length; i++) {
209                 Namespace addns = (Namespace)nss.get(i);
210                 uris[i] = addns.getURI();
211                 nums[i] = base + i;
212                 prefs[i] = addns.getPrefix();
213                 if (nsi < 0 && ns.equals(addns)) {
214                     nsi = base + i;
215                 }
216             }
217             m_xmlWriter.pushExtensionNamespaces(uris);
218             m_xmlWriter.startTagNamespaces(nsi, element.getName(), nums, prefs);
219             if (defind >= 0) {
220                 m_defaultNamespaceIndex = defind;
221                 m_defaultNamespaceURI = defuri;
222             }
223         }
224         
225         // add attributes if present
226
if (element.attributeCount() > 0) {
227             for (int i = 0; i < element.attributeCount(); i++) {
228                 Attribute attr = element.attribute(i);
229                 int index = findNamespaceIndex(attr.getNamespace());
230                 m_xmlWriter.addAttribute(index, attr.getName(),
231                      attr.getValue());
232             }
233         }
234         
235         // check for content present
236
if (hascontent) {
237             m_xmlWriter.closeStartTag();
238             marshalContent(element.content());
239             m_xmlWriter.endTag(nsi, element.getName());
240         } else {
241             m_xmlWriter.closeEmptyTag();
242         }
243         
244         // pop namespaces if defined by element
245
if (nss != null) {
246             m_xmlWriter.popExtensionNamespaces();
247             if (defind >= 0) {
248                 m_defaultNamespaceURI = null;
249             }
250         }
251     }
252     
253     /**
254      * Unmarshal element content. This unmarshals everything up to the
255      * containing element close tag, adding each component to the content list
256      * supplied. On return, the parse position will always be at an END_TAG.
257      *
258      * @param content list for unmarshalled content
259      * @exception JiBXException on error in unmarshalling
260      * @exception IOException on error reading input
261      */

262     
263     protected void unmarshalContent(List JavaDoc content)
264         throws JiBXException, IOException JavaDoc {
265         
266         // loop until end of containing element found
267
loop: while (true) {
268             int cev = m_unmarshalContext.currentEvent();
269             switch (cev) {
270                 
271                 case UnmarshallingContext.CDSECT:
272                     content.add(s_factory.
273                         createCDATA(m_unmarshalContext.getText()));
274                     break;
275                 
276                 case UnmarshallingContext.COMMENT:
277                     content.add(s_factory.
278                         createComment(m_unmarshalContext.getText()));
279                     break;
280                 
281                 case UnmarshallingContext.END_TAG:
282                     break loop;
283                 
284                 case UnmarshallingContext.ENTITY_REF:
285                     if (m_unmarshalContext.getText() == null) {
286                         content.add(s_factory.
287                             createEntity(m_unmarshalContext.getName(), null));
288                         break;
289                     } else {
290                         content.add(s_factory.createText(accumulateText()));
291                         continue loop;
292                     }
293                 
294                 case UnmarshallingContext.PROCESSING_INSTRUCTION:
295                     {
296                         String JavaDoc text = m_unmarshalContext.getText();
297                         int index = 0;
298                         while (++index < text.length() &&
299                             !isWhitespace(text.charAt(index)));
300                         if (index < text.length()) {
301                             String JavaDoc target = text.substring(0, index);
302                             while (++index < text.length() &&
303                                 isWhitespace(text.charAt(index)));
304                             String JavaDoc data = text.substring(index);
305                             content.add(s_factory.
306                                 createProcessingInstruction(target, data));
307                         } else {
308                             content.add(s_factory.
309                                 createProcessingInstruction(text, ""));
310                         }
311                     }
312                     break;
313                 
314                 case UnmarshallingContext.START_TAG:
315                     content.add(unmarshalElement());
316                     continue loop;
317                 
318                 case UnmarshallingContext.TEXT:
319                     content.add(s_factory.createText(accumulateText()));
320                     continue loop;
321                     
322             }
323             m_unmarshalContext.nextToken();
324         }
325     }
326     
327     /**
328      * Unmarshal element with all attributes and content. This must be called
329      * with the unmarshalling context positioned at a START_TAG event.
330      *
331      * @return unmarshalled element
332      * @exception JiBXException on error in unmarshalling
333      * @exception IOException on error reading input
334      */

335     
336     protected Element unmarshalElement() throws JiBXException, IOException JavaDoc {
337         
338         // start by creating the actual element
339
QName qname = QName.get(m_unmarshalContext.getName(),
340             m_unmarshalContext.getPrefix(), m_unmarshalContext.getNamespace());
341         Element element = s_factory.createElement(qname);
342         
343         // add all namespace declarations to element
344
int ncount = m_unmarshalContext.getNamespaceCount();
345         for (int i = 0; i < ncount; i++) {
346             String JavaDoc prefix = m_unmarshalContext.getNamespacePrefix(i);
347             String JavaDoc uri = m_unmarshalContext.getNamespaceUri(i);
348             element.addNamespace(prefix, uri);
349         }
350         
351         // add all attributes to element
352
int acount = m_unmarshalContext.getAttributeCount();
353         for (int i = 0; i < acount; i++) {
354             String JavaDoc prefix = m_unmarshalContext.getAttributePrefix(i);
355             String JavaDoc uri = m_unmarshalContext.getAttributeNamespace(i);
356             String JavaDoc name = m_unmarshalContext.getAttributeName(i);
357             String JavaDoc value = m_unmarshalContext.getAttributeValue(i);
358             qname = QName.get(name, prefix, uri);
359             element.addAttribute(qname, value);
360         }
361         
362         // add all content to element
363
int event = m_unmarshalContext.nextToken();
364         if (event != UnmarshallingContext.END_TAG) {
365             unmarshalContent(element.content());
366         }
367         m_unmarshalContext.nextToken();
368         return element;
369     }
370 }
Popular Tags