Clover coverage report - dom4j - 1.6.1
Coverage timestamp: ma mei 16 2005 14:23:01 GMT+01:00
file stats: LOC: 456   Methods: 36
NCLOC: 193   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
DocumentFactory.java 75% 78,9% 86,1% 80,9%
coverage coverage
 1    /*
 2    * Copyright 2001-2005 (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   
 8    package org.dom4j;
 9   
 10    import java.io.IOException;
 11    import java.io.ObjectInputStream;
 12    import java.io.Serializable;
 13    import java.util.List;
 14    import java.util.Map;
 15   
 16    import org.dom4j.rule.Pattern;
 17    import org.dom4j.tree.AbstractDocument;
 18    import org.dom4j.tree.DefaultAttribute;
 19    import org.dom4j.tree.DefaultCDATA;
 20    import org.dom4j.tree.DefaultComment;
 21    import org.dom4j.tree.DefaultDocument;
 22    import org.dom4j.tree.DefaultDocumentType;
 23    import org.dom4j.tree.DefaultElement;
 24    import org.dom4j.tree.DefaultEntity;
 25    import org.dom4j.tree.DefaultProcessingInstruction;
 26    import org.dom4j.tree.DefaultText;
 27    import org.dom4j.tree.QNameCache;
 28    import org.dom4j.util.SimpleSingleton;
 29    import org.dom4j.util.SingletonStrategy;
 30    import org.dom4j.xpath.DefaultXPath;
 31    import org.dom4j.xpath.XPathPattern;
 32    import org.jaxen.VariableContext;
 33   
 34    /**
 35    * <p>
 36    * <code>DocumentFactory</code> is a collection of factory methods to allow
 37    * easy custom building of DOM4J trees. The default tree that is built uses a
 38    * doubly linked tree.
 39    * </p>
 40    *
 41    * <p>
 42    * The tree built allows full XPath expressions from anywhere on the tree.
 43    * </p>
 44    *
 45    * @author <a href="mailto:jstrachan@apache.org">James Strachan </a>
 46    */
 47    public class DocumentFactory implements Serializable {
 48    private static SingletonStrategy singleton = null;
 49   
 50    protected transient QNameCache cache;
 51   
 52    /** Default namespace prefix -> URI mappings for XPath expressions to use */
 53    private Map xpathNamespaceURIs;
 54   
 55  90 private static SingletonStrategy createSingleton() {
 56  90 SingletonStrategy result = null;
 57   
 58  90 String documentFactoryClassName;
 59  90 try {
 60  90 documentFactoryClassName = System.getProperty("org.dom4j.factory",
 61    "org.dom4j.DocumentFactory");
 62    } catch (Exception e) {
 63  0 documentFactoryClassName = "org.dom4j.DocumentFactory";
 64    }
 65   
 66  90 try {
 67  90 String singletonClass = System.getProperty(
 68    "org.dom4j.DocumentFactory.singleton.strategy",
 69    "org.dom4j.util.SimpleSingleton");
 70  90 Class clazz = Class.forName(singletonClass);
 71  90 result = (SingletonStrategy) clazz.newInstance();
 72    } catch (Exception e) {
 73  0 result = new SimpleSingleton();
 74    }
 75   
 76  90 result.setSingletonClassName(documentFactoryClassName);
 77   
 78  90 return result;
 79    }
 80   
 81  541 public DocumentFactory() {
 82  541 init();
 83    }
 84   
 85    /**
 86    * <p>
 87    * Access to singleton implementation of DocumentFactory which is used if no
 88    * DocumentFactory is specified when building using the standard builders.
 89    * </p>
 90    *
 91    * @return the default singleon instance
 92    */
 93  27023 public static synchronized DocumentFactory getInstance() {
 94  27023 if (singleton == null) {
 95  90 singleton = createSingleton();
 96    }
 97  27023 return (DocumentFactory) singleton.instance();
 98    }
 99   
 100    // Factory methods
 101  6270 public Document createDocument() {
 102  6270 DefaultDocument answer = new DefaultDocument();
 103  6270 answer.setDocumentFactory(this);
 104   
 105  6270 return answer;
 106    }
 107   
 108    /**
 109    * DOCUMENT ME!
 110    *
 111    * @param encoding
 112    * DOCUMENT ME!
 113    *
 114    * @return DOCUMENT ME!
 115    *
 116    * @since 1.5
 117    */
 118  5816 public Document createDocument(String encoding) {
 119    // to keep the DocumentFactory backwards compatible, we have to do this
 120    // in this not so nice way, since subclasses only need to extend the
 121    // createDocument() method.
 122  5816 Document answer = createDocument();
 123   
 124  5816 if (answer instanceof AbstractDocument) {
 125  5816 ((AbstractDocument) answer).setXMLEncoding(encoding);
 126    }
 127   
 128  5816 return answer;
 129    }
 130   
 131  2 public Document createDocument(Element rootElement) {
 132  2 Document answer = createDocument();
 133  2 answer.setRootElement(rootElement);
 134   
 135  2 return answer;
 136    }
 137   
 138  11 public DocumentType createDocType(String name, String publicId,
 139    String systemId) {
 140  11 return new DefaultDocumentType(name, publicId, systemId);
 141    }
 142   
 143  94468 public Element createElement(QName qname) {
 144  94468 return new DefaultElement(qname);
 145    }
 146   
 147  465 public Element createElement(String name) {
 148  465 return createElement(createQName(name));
 149    }
 150   
 151  4 public Element createElement(String qualifiedName, String namespaceURI) {
 152  4 return createElement(createQName(qualifiedName, namespaceURI));
 153    }
 154   
 155  14165 public Attribute createAttribute(Element owner, QName qname, String value) {
 156  14165 return new DefaultAttribute(qname, value);
 157    }
 158   
 159  1630 public Attribute createAttribute(Element owner, String name, String value) {
 160  1630 return createAttribute(owner, createQName(name), value);
 161    }
 162   
 163  103 public CDATA createCDATA(String text) {
 164  103 return new DefaultCDATA(text);
 165    }
 166   
 167  503 public Comment createComment(String text) {
 168  503 return new DefaultComment(text);
 169    }
 170   
 171  121456 public Text createText(String text) {
 172  121456 if (text == null) {
 173  0 String msg = "Adding text to an XML document must not be null";
 174  0 throw new IllegalArgumentException(msg);
 175    }
 176   
 177  121456 return new DefaultText(text);
 178    }
 179   
 180  4 public Entity createEntity(String name, String text) {
 181  4 return new DefaultEntity(name, text);
 182    }
 183   
 184  100506 public Namespace createNamespace(String prefix, String uri) {
 185  100506 return Namespace.get(prefix, uri);
 186    }
 187   
 188  16 public ProcessingInstruction createProcessingInstruction(String target,
 189    String data) {
 190  16 return new DefaultProcessingInstruction(target, data);
 191    }
 192   
 193  0 public ProcessingInstruction createProcessingInstruction(String target,
 194    Map data) {
 195  0 return new DefaultProcessingInstruction(target, data);
 196    }
 197   
 198  104391 public QName createQName(String localName, Namespace namespace) {
 199  104391 return cache.get(localName, namespace);
 200    }
 201   
 202  12760 public QName createQName(String localName) {
 203  12760 return cache.get(localName);
 204    }
 205   
 206  16 public QName createQName(String name, String prefix, String uri) {
 207  16 return cache.get(name, Namespace.get(prefix, uri));
 208    }
 209   
 210  30 public QName createQName(String qualifiedName, String uri) {
 211  30 return cache.get(qualifiedName, uri);
 212    }
 213   
 214    /**
 215    * <p>
 216    * <code>createXPath</code> parses an XPath expression and creates a new
 217    * XPath <code>XPath</code> instance.
 218    * </p>
 219    *
 220    * @param xpathExpression
 221    * is the XPath expression to create
 222    *
 223    * @return a new <code>XPath</code> instance
 224    *
 225    * @throws InvalidXPathException
 226    * if the XPath expression is invalid
 227    */
 228  589 public XPath createXPath(String xpathExpression)
 229    throws InvalidXPathException {
 230  589 DefaultXPath xpath = new DefaultXPath(xpathExpression);
 231   
 232  585 if (xpathNamespaceURIs != null) {
 233  3 xpath.setNamespaceURIs(xpathNamespaceURIs);
 234    }
 235   
 236  585 return xpath;
 237    }
 238   
 239    /**
 240    * <p>
 241    * <code>createXPath</code> parses an XPath expression and creates a new
 242    * XPath <code>XPath</code> instance.
 243    * </p>
 244    *
 245    * @param xpathExpression
 246    * is the XPath expression to create
 247    * @param variableContext
 248    * is the variable context to use when evaluating the XPath
 249    *
 250    * @return a new <code>XPath</code> instance
 251    */
 252  1 public XPath createXPath(String xpathExpression,
 253    VariableContext variableContext) {
 254  1 XPath xpath = createXPath(xpathExpression);
 255  1 xpath.setVariableContext(variableContext);
 256   
 257  1 return xpath;
 258    }
 259   
 260    /**
 261    * <p>
 262    * <code>createXPathFilter</code> parses a NodeFilter from the given XPath
 263    * filter expression. XPath filter expressions occur within XPath
 264    * expressions such as <code>self::node()[ filterExpression ]</code>
 265    * </p>
 266    *
 267    * @param xpathFilterExpression
 268    * is the XPath filter expression to create
 269    * @param variableContext
 270    * is the variable context to use when evaluating the XPath
 271    *
 272    * @return a new <code>NodeFilter</code> instance
 273    */
 274  0 public NodeFilter createXPathFilter(String xpathFilterExpression,
 275    VariableContext variableContext) {
 276  0 XPath answer = createXPath(xpathFilterExpression);
 277   
 278    // DefaultXPath answer = new DefaultXPath( xpathFilterExpression );
 279  0 answer.setVariableContext(variableContext);
 280   
 281  0 return answer;
 282    }
 283   
 284    /**
 285    * <p>
 286    * <code>createXPathFilter</code> parses a NodeFilter from the given XPath
 287    * filter expression. XPath filter expressions occur within XPath
 288    * expressions such as <code>self::node()[ filterExpression ]</code>
 289    * </p>
 290    *
 291    * @param xpathFilterExpression
 292    * is the XPath filter expression to create
 293    *
 294    * @return a new <code>NodeFilter</code> instance
 295    */
 296  4 public NodeFilter createXPathFilter(String xpathFilterExpression) {
 297  4 return createXPath(xpathFilterExpression);
 298   
 299    // return new DefaultXPath( xpathFilterExpression );
 300    }
 301   
 302    /**
 303    * <p>
 304    * <code>createPattern</code> parses the given XPath expression to create
 305    * an XSLT style {@link Pattern}instance which can then be used in an XSLT
 306    * processing model.
 307    * </p>
 308    *
 309    * @param xpathPattern
 310    * is the XPath pattern expression to create
 311    *
 312    * @return a new <code>Pattern</code> instance
 313    */
 314  37 public Pattern createPattern(String xpathPattern) {
 315  37 return new XPathPattern(xpathPattern);
 316    }
 317   
 318    // Properties
 319    // -------------------------------------------------------------------------
 320   
 321    /**
 322    * Returns a list of all the QName instances currently used by this document
 323    * factory
 324    *
 325    * @return DOCUMENT ME!
 326    */
 327  1 public List getQNames() {
 328  1 return cache.getQNames();
 329    }
 330   
 331    /**
 332    * DOCUMENT ME!
 333    *
 334    * @return the Map of namespace URIs that will be used by by XPath
 335    * expressions to resolve namespace prefixes into namespace URIs.
 336    * The map is keyed by namespace prefix and the value is the
 337    * namespace URI. This value could well be null to indicate no
 338    * namespace URIs are being mapped.
 339    */
 340  0 public Map getXPathNamespaceURIs() {
 341  0 return xpathNamespaceURIs;
 342    }
 343   
 344    /**
 345    * Sets the namespace URIs to be used by XPath expressions created by this
 346    * factory or by nodes associated with this factory. The keys are namespace
 347    * prefixes and the values are namespace URIs.
 348    *
 349    * @param namespaceURIs
 350    * DOCUMENT ME!
 351    */
 352  2 public void setXPathNamespaceURIs(Map namespaceURIs) {
 353  2 this.xpathNamespaceURIs = namespaceURIs;
 354    }
 355   
 356    // Implementation methods
 357    // -------------------------------------------------------------------------
 358   
 359    /**
 360    * <p>
 361    * <code>createSingleton</code> creates the singleton instance from the
 362    * given class name.
 363    * </p>
 364    *
 365    * @param className
 366    * is the name of the DocumentFactory class to use
 367    *
 368    * @return a new singleton instance.
 369    */
 370  0 protected static DocumentFactory createSingleton(String className) {
 371    // let's try and class load an implementation?
 372  0 try {
 373    // I'll use the current class loader
 374    // that loaded me to avoid problems in J2EE and web apps
 375  0 Class theClass = Class.forName(className, true,
 376    DocumentFactory.class.getClassLoader());
 377   
 378  0 return (DocumentFactory) theClass.newInstance();
 379    } catch (Throwable e) {
 380  0 System.out.println("WARNING: Cannot load DocumentFactory: "
 381    + className);
 382   
 383  0 return new DocumentFactory();
 384    }
 385    }
 386   
 387    /**
 388    * DOCUMENT ME!
 389    *
 390    * @param qname
 391    * DOCUMENT ME!
 392    *
 393    * @return the cached QName instance if there is one or adds the given qname
 394    * to the cache if not
 395    */
 396  0 protected QName intern(QName qname) {
 397  0 return cache.intern(qname);
 398    }
 399   
 400    /**
 401    * Factory method to create the QNameCache. This method should be overloaded
 402    * if you wish to use your own derivation of QName.
 403    *
 404    * @return DOCUMENT ME!
 405    */
 406  544 protected QNameCache createQNameCache() {
 407  544 return new QNameCache(this);
 408    }
 409   
 410  3 private void readObject(ObjectInputStream in) throws IOException,
 411    ClassNotFoundException {
 412  3 in.defaultReadObject();
 413  3 init();
 414    }
 415   
 416  544 protected void init() {
 417  544 cache = createQNameCache();
 418    }
 419    }
 420   
 421    /*
 422    * Redistribution and use of this software and associated documentation
 423    * ("Software"), with or without modification, are permitted provided that the
 424    * following conditions are met:
 425    *
 426    * 1. Redistributions of source code must retain copyright statements and
 427    * notices. Redistributions must also contain a copy of this document.
 428    *
 429    * 2. Redistributions in binary form must reproduce the above copyright notice,
 430    * this list of conditions and the following disclaimer in the documentation
 431    * and/or other materials provided with the distribution.
 432    *
 433    * 3. The name "DOM4J" must not be used to endorse or promote products derived
 434    * from this Software without prior written permission of MetaStuff, Ltd. For
 435    * written permission, please contact dom4j-info@metastuff.com.
 436    *
 437    * 4. Products derived from this Software may not be called "DOM4J" nor may
 438    * "DOM4J" appear in their names without prior written permission of MetaStuff,
 439    * Ltd. DOM4J is a registered trademark of MetaStuff, Ltd.
 440    *
 441    * 5. Due credit should be given to the DOM4J Project - http://www.dom4j.org
 442    *
 443    * THIS SOFTWARE IS PROVIDED BY METASTUFF, LTD. AND CONTRIBUTORS ``AS IS'' AND
 444    * ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 445    * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 446    * ARE DISCLAIMED. IN NO EVENT SHALL METASTUFF, LTD. OR ITS CONTRIBUTORS BE
 447    * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 448    * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 449    * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 450    * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 451    * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 452    * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 453    * POSSIBILITY OF SUCH DAMAGE.
 454    *
 455    * Copyright 2001-2005 (C) MetaStuff, Ltd. All Rights Reserved.
 456    */