Clover coverage report - dom4j - 1.5
Coverage timestamp: vr sep 3 2004 20:47:03 GMT+01:00
file stats: LOC: 431   Methods: 21
NCLOC: 301   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
DOMWriter.java 69,2% 65,6% 71,4% 67,2%
coverage coverage
 1    /*
 2    * Copyright 2001-2004 (C) MetaStuff, Ltd. All Rights Reserved.
 3    *
 4    * This software is open source.
 5    * See the bottom of this file for the licence.
 6    *
 7    * $Id: DOMWriter.java,v 1.15 2004/06/28 14:19:33 maartenc Exp $
 8    */
 9   
 10    package org.dom4j.io;
 11   
 12    import java.util.List;
 13   
 14    import org.dom4j.Attribute;
 15    import org.dom4j.CDATA;
 16    import org.dom4j.Comment;
 17    import org.dom4j.Document;
 18    import org.dom4j.DocumentException;
 19    import org.dom4j.Element;
 20    import org.dom4j.Entity;
 21    import org.dom4j.Namespace;
 22    import org.dom4j.ProcessingInstruction;
 23    import org.dom4j.Text;
 24    import org.dom4j.tree.NamespaceStack;
 25   
 26    /** <p><code>DOMWriter</code> takes a DOM4J tree and outputs
 27    * it as a W3C DOM object</p>
 28    *
 29    * @author <a href="mailto:james.strachan@metastuff.com">James Strachan</a>
 30    * @version $Revision: 1.15 $
 31    */
 32    public class DOMWriter {
 33   
 34    private static boolean loggedWarning = false;
 35    private static final String[] DEFAULT_DOM_DOCUMENT_CLASSES = {
 36    "org.apache.xerces.dom.DocumentImpl", // Xerces
 37    "gnu.xml.dom.DomDocument", // GNU JAXP
 38    "org.apache.crimson.tree.XmlDocument", // Crimson
 39    "com.sun.xml.tree.XmlDocument", // Sun's Project X
 40    "oracle.xml.parser.v2.XMLDocument", // Oracle V2
 41    "oracle.xml.parser.XMLDocument", // Oracle V1
 42    "org.dom4j.dom.DOMDocument" // Internal DOM implementation
 43    };
 44   
 45    // the Class used to create new DOM Document instances
 46    private Class domDocumentClass;
 47   
 48    /** stack of <code>Namespace</code> objects */
 49    private NamespaceStack namespaceStack = new NamespaceStack();
 50   
 51   
 52  28 public DOMWriter() {
 53    }
 54   
 55  4 public DOMWriter(Class domDocumentClass) {
 56  4 this.domDocumentClass = domDocumentClass;
 57    }
 58   
 59  0 public Class getDomDocumentClass() throws DocumentException {
 60  0 Class result = domDocumentClass;
 61   
 62  0 if ( result == null ) {
 63    // lets try and find one in the classpath
 64  0 int size = DEFAULT_DOM_DOCUMENT_CLASSES.length;
 65  0 for ( int i = 0; i < size; i++ ) {
 66  0 try {
 67  0 String name = DEFAULT_DOM_DOCUMENT_CLASSES[i];
 68  0 result = Class.forName(
 69    name,
 70    true,
 71    DOMWriter.class.getClassLoader()
 72    );
 73  0 if ( result != null ) {
 74  0 break;
 75    }
 76    }
 77    catch (Exception e) {
 78    // could not load class correctly
 79    // lets carry on to the next one
 80    }
 81    }
 82    }
 83  0 return result;
 84    }
 85   
 86    /** Sets the DOM {@link org.w3c.dom.Document} implementation
 87    * class used by the writer when creating DOM documents.
 88    *
 89    * @param domDocumentClass is the Class implementing
 90    * the {@link org.w3c.dom.Document} interface
 91    */
 92  0 public void setDomDocumentClass(Class domDocumentClass) {
 93  0 this.domDocumentClass = domDocumentClass;
 94    }
 95   
 96    /** Sets the DOM {@link org.w3c.dom.Document} implementation
 97    * class name used by the writer when creating DOM documents.
 98    *
 99    * @param className is the name of the Class implementing
 100    * the {@link org.w3c.dom.Document} interface
 101    * @throws DocumentException if the class could not be loaded
 102    */
 103  0 public void setDomDocumentClassName(String className) throws DocumentException {
 104  0 try {
 105  0 this.domDocumentClass = Class.forName(
 106    className,
 107    true,
 108    DOMWriter.class.getClassLoader()
 109    );
 110    }
 111    catch (Exception e) {
 112  0 throw new DocumentException(
 113    "Could not load the DOM Document class: " + className, e
 114    );
 115    }
 116    }
 117   
 118   
 119  32 public org.w3c.dom.Document write(Document document) throws DocumentException {
 120  32 if ( document instanceof org.w3c.dom.Document ) {
 121  2 return (org.w3c.dom.Document) document;
 122    }
 123  30 resetNamespaceStack();
 124  30 org.w3c.dom.Document domDocument = createDomDocument(document);
 125  30 appendDOMTree(domDocument, domDocument, document.content());
 126  30 namespaceStack.clear();
 127  30 return domDocument;
 128    }
 129   
 130  0 public org.w3c.dom.Document write(
 131    Document document,
 132    org.w3c.dom.DOMImplementation domImplementation
 133    ) throws DocumentException {
 134  0 if ( document instanceof org.w3c.dom.Document ) {
 135  0 return (org.w3c.dom.Document) document;
 136    }
 137  0 resetNamespaceStack();
 138  0 org.w3c.dom.Document domDocument = createDomDocument(document, domImplementation);
 139  0 appendDOMTree(domDocument, domDocument, document.content());
 140  0 namespaceStack.clear();
 141  0 return domDocument;
 142    }
 143   
 144  9676 protected void appendDOMTree(
 145    org.w3c.dom.Document domDocument,
 146    org.w3c.dom.Node domCurrent,
 147    List content
 148    ) {
 149  9676 int size = content.size();
 150  9676 for ( int i = 0; i < size; i++ ) {
 151  26486 Object object = content.get(i);
 152  26486 if (object instanceof Element) {
 153  9646 appendDOMTree( domDocument, domCurrent, (Element) object);
 154    }
 155  16840 else if ( object instanceof String ) {
 156  0 appendDOMTree( domDocument, domCurrent, (String) object );
 157    }
 158  16840 else if ( object instanceof Text ) {
 159  16574 Text text = (Text) object;
 160  16574 appendDOMTree( domDocument, domCurrent, text.getText() );
 161    }
 162  266 else if ( object instanceof CDATA ) {
 163  60 appendDOMTree( domDocument, domCurrent, (CDATA) object );
 164    }
 165  206 else if ( object instanceof Comment ) {
 166  136 appendDOMTree( domDocument, domCurrent, (Comment) object );
 167    }
 168  70 else if ( object instanceof Entity ) {
 169  0 appendDOMTree( domDocument, domCurrent, (Entity) object );
 170    }
 171  70 else if ( object instanceof ProcessingInstruction ) {
 172  4 appendDOMTree( domDocument, domCurrent, (ProcessingInstruction) object );
 173    }
 174    }
 175    }
 176   
 177  9646 protected void appendDOMTree(
 178    org.w3c.dom.Document domDocument,
 179    org.w3c.dom.Node domCurrent,
 180    Element element
 181    ) {
 182  9646 String elUri = element.getNamespaceURI();
 183  9646 String elName = element.getQualifiedName();
 184  9646 org.w3c.dom.Element domElement = domDocument.createElementNS(elUri, elName);
 185   
 186  9646 int stackSize = namespaceStack.size();
 187   
 188    // add the namespace of the element first
 189  9646 Namespace elementNamespace = element.getNamespace();
 190  9646 if (isNamespaceDeclaration(elementNamespace)) {
 191  54 namespaceStack.push(elementNamespace);
 192  54 writeNamespace(domElement, elementNamespace);
 193    }
 194   
 195    // add the additional declared namespaces
 196  9646 List declaredNamespaces = element.declaredNamespaces();
 197  9646 for ( int i = 0, size = declaredNamespaces.size(); i < size ; i++ ) {
 198  66 Namespace namespace = (Namespace) declaredNamespaces.get(i);
 199  66 if ( isNamespaceDeclaration( namespace ) ) {
 200  12 namespaceStack.push( namespace );
 201  12 writeNamespace( domElement, namespace );
 202    }
 203    }
 204   
 205    // add the attributes
 206  9646 for ( int i = 0, size = element.attributeCount(); i < size ; i++ ) {
 207  4984 Attribute attribute = (Attribute) element.attribute(i);
 208  4984 String attUri = attribute.getNamespaceURI();
 209  4984 String attName = attribute.getQualifiedName();
 210  4984 String value = attribute.getValue();
 211  4984 domElement.setAttributeNS(attUri, attName, value);
 212    }
 213   
 214    // add content
 215  9646 appendDOMTree( domDocument, domElement, element.content() );
 216   
 217  9646 domCurrent.appendChild( domElement );
 218   
 219  9646 while ( namespaceStack.size() > stackSize ) {
 220  66 namespaceStack.pop();
 221    }
 222    }
 223   
 224  60 protected void appendDOMTree(
 225    org.w3c.dom.Document domDocument,
 226    org.w3c.dom.Node domCurrent,
 227    CDATA cdata
 228    ) {
 229  60 org.w3c.dom.CDATASection domCDATA =
 230    domDocument.createCDATASection(cdata.getText());
 231  60 domCurrent.appendChild(domCDATA);
 232    }
 233   
 234  136 protected void appendDOMTree(
 235    org.w3c.dom.Document domDocument,
 236    org.w3c.dom.Node domCurrent,
 237    Comment comment
 238    ) {
 239  136 org.w3c.dom.Comment domComment =
 240    domDocument.createComment(comment.getText());
 241  136 domCurrent.appendChild(domComment);
 242    }
 243   
 244  16574 protected void appendDOMTree(
 245    org.w3c.dom.Document domDocument,
 246    org.w3c.dom.Node domCurrent,
 247    String text
 248    ) {
 249  16574 org.w3c.dom.Text domText = domDocument.createTextNode(text);
 250  16574 domCurrent.appendChild(domText);
 251    }
 252   
 253  0 protected void appendDOMTree(
 254    org.w3c.dom.Document domDocument,
 255    org.w3c.dom.Node domCurrent,
 256    Entity entity
 257    ) {
 258  0 org.w3c.dom.EntityReference domEntity =
 259    domDocument.createEntityReference(entity.getName());
 260  0 domCurrent.appendChild(domEntity);
 261    }
 262   
 263  4 protected void appendDOMTree(
 264    org.w3c.dom.Document domDocument,
 265    org.w3c.dom.Node domCurrent,
 266    ProcessingInstruction pi
 267    ) {
 268  4 org.w3c.dom.ProcessingInstruction domPI =
 269    domDocument.createProcessingInstruction(pi.getTarget(), pi.getText());
 270  4 domCurrent.appendChild(domPI);
 271    }
 272   
 273  66 protected void writeNamespace(
 274    org.w3c.dom.Element domElement,
 275    Namespace namespace
 276    ) {
 277  66 String attributeName = attributeNameForNamespace(namespace);
 278    //domElement.setAttributeNS("", attributeName, namespace.getURI());
 279  66 domElement.setAttribute(attributeName, namespace.getURI());
 280    }
 281   
 282  66 protected String attributeNameForNamespace(Namespace namespace) {
 283  66 String xmlns = "xmlns";
 284  66 String prefix = namespace.getPrefix();
 285  66 if ( prefix.length() > 0 ) {
 286  44 return xmlns + ":" + prefix;
 287    }
 288  22 return xmlns;
 289    }
 290   
 291  30 protected org.w3c.dom.Document createDomDocument(
 292    Document document
 293    ) throws DocumentException {
 294  30 org.w3c.dom.Document result = null;
 295   
 296    // use the given domDocumentClass (if not null)
 297  30 if (domDocumentClass != null) {
 298  4 try {
 299  4 result = (org.w3c.dom.Document) domDocumentClass.newInstance();
 300    }
 301    catch (Exception e) {
 302  0 throw new DocumentException(
 303    "Could not instantiate an instance of DOM Document with class: "
 304    + domDocumentClass.getName(), e
 305    );
 306    }
 307    } else {
 308    // lets try JAXP first before using the hardcoded default parsers
 309  26 result = createDomDocumentViaJAXP();
 310  26 if ( result == null ) {
 311  0 Class theClass = getDomDocumentClass();
 312  0 try {
 313  0 result = (org.w3c.dom.Document) theClass.newInstance();
 314    }
 315    catch (Exception e) {
 316  0 throw new DocumentException(
 317    "Could not instantiate an instance of DOM Document with class: "
 318    + theClass.getName(), e
 319    );
 320    }
 321    }
 322    }
 323   
 324  30 return result;
 325    }
 326   
 327  26 protected org.w3c.dom.Document createDomDocumentViaJAXP() throws DocumentException {
 328  26 try {
 329  26 return JAXPHelper.createDocument( false, true );
 330    }
 331    catch (Throwable e) {
 332  0 if ( ! loggedWarning ) {
 333  0 loggedWarning = true;
 334  0 if ( SAXHelper.isVerboseErrorReporting() ) {
 335    // log all exceptions as warnings and carry
 336    // on as we have a default SAX parser we can use
 337  0 System.out.println(
 338    "Warning: Caught exception attempting to use JAXP to "
 339    + "create a W3C DOM document"
 340    );
 341  0 System.out.println( "Warning: Exception was: " + e );
 342  0 e.printStackTrace();
 343    }
 344    else {
 345  0 System.out.println(
 346    "Warning: Error occurred using JAXP to create a DOM document."
 347    );
 348    }
 349    }
 350    }
 351  0 return null;
 352    }
 353  0 protected org.w3c.dom.Document createDomDocument(
 354    Document document,
 355    org.w3c.dom.DOMImplementation domImplementation
 356    ) throws DocumentException {
 357   
 358  0 String namespaceURI = null;
 359  0 String qualifiedName = null;
 360  0 org.w3c.dom.DocumentType docType = null;
 361  0 return domImplementation.createDocument(
 362    namespaceURI, qualifiedName, docType
 363    );
 364    }
 365   
 366  9712 protected boolean isNamespaceDeclaration( Namespace ns ) {
 367  9712 if (ns != null && ns != Namespace.NO_NAMESPACE && ns != Namespace.XML_NAMESPACE) {
 368  344 String uri = ns.getURI();
 369  344 if ( uri != null && uri.length() > 0 ) {
 370  344 if ( ! namespaceStack.contains( ns ) ) {
 371  66 return true;
 372   
 373    }
 374    }
 375    }
 376  9646 return false;
 377    }
 378   
 379  30 protected void resetNamespaceStack() {
 380  30 namespaceStack.clear();
 381  30 namespaceStack.push( Namespace.XML_NAMESPACE );
 382    }
 383    }
 384   
 385   
 386   
 387   
 388    /*
 389    * Redistribution and use of this software and associated documentation
 390    * ("Software"), with or without modification, are permitted provided
 391    * that the following conditions are met:
 392    *
 393    * 1. Redistributions of source code must retain copyright
 394    * statements and notices. Redistributions must also contain a
 395    * copy of this document.
 396    *
 397    * 2. Redistributions in binary form must reproduce the
 398    * above copyright notice, this list of conditions and the
 399    * following disclaimer in the documentation and/or other
 400    * materials provided with the distribution.
 401    *
 402    * 3. The name "DOM4J" must not be used to endorse or promote
 403    * products derived from this Software without prior written
 404    * permission of MetaStuff, Ltd. For written permission,
 405    * please contact dom4j-info@metastuff.com.
 406    *
 407    * 4. Products derived from this Software may not be called "DOM4J"
 408    * nor may "DOM4J" appear in their names without prior written
 409    * permission of MetaStuff, Ltd. DOM4J is a registered
 410    * trademark of MetaStuff, Ltd.
 411    *
 412    * 5. Due credit should be given to the DOM4J Project -
 413    * http://www.dom4j.org
 414    *
 415    * THIS SOFTWARE IS PROVIDED BY METASTUFF, LTD. AND CONTRIBUTORS
 416    * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
 417    * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
 418    * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
 419    * METASTUFF, LTD. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
 420    * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 421    * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 422    * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 423    * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 424    * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 425    * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 426    * OF THE POSSIBILITY OF SUCH DAMAGE.
 427    *
 428    * Copyright 2001-2004 (C) MetaStuff, Ltd. All Rights Reserved.
 429    *
 430    * $Id: DOMWriter.java,v 1.15 2004/06/28 14:19:33 maartenc Exp $
 431    */