| /* | ||
| * Copyright 2001-2004 (C) MetaStuff, Ltd. All Rights Reserved. | ||
| * | ||
| * This software is open source. | ||
| * See the bottom of this file for the licence. | ||
| * | ||
| * $Id: DocumentFactory.java,v 1.40 2004/07/11 10:49:36 maartenc Exp $ | ||
| */ | ||
| package org.dom4j; | ||
| import java.io.IOException; | ||
| import java.io.ObjectInputStream; | ||
| import java.io.Serializable; | ||
| import java.util.List; | ||
| import java.util.Map; | ||
| import org.dom4j.rule.Pattern; | ||
| import org.dom4j.tree.DefaultAttribute; | ||
| import org.dom4j.tree.DefaultCDATA; | ||
| import org.dom4j.tree.DefaultComment; | ||
| import org.dom4j.tree.DefaultDocument; | ||
| import org.dom4j.tree.DefaultDocumentType; | ||
| import org.dom4j.tree.DefaultElement; | ||
| import org.dom4j.tree.DefaultEntity; | ||
| import org.dom4j.tree.DefaultProcessingInstruction; | ||
| import org.dom4j.tree.DefaultText; | ||
| import org.dom4j.tree.QNameCache; | ||
| import org.dom4j.xpath.DefaultXPath; | ||
| import org.dom4j.xpath.XPathPattern; | ||
| import org.jaxen.VariableContext; | ||
| /** <p><code>DocumentFactory</code> is a collection of factory methods to allow | ||
| * easy custom building of DOM4J trees. The default tree that is built uses | ||
| * a doubly linked tree. </p> | ||
| * | ||
| * <p>The tree built allows full XPath expressions from anywhere on the | ||
| * tree.</p> | ||
| * | ||
| * @author <a href="mailto:jstrachan@apache.org">James Strachan</a> | ||
| * @version $Revision: 1.40 $ | ||
| */ | ||
| public class DocumentFactory implements Serializable { | ||
| /** The Singleton instance */ | ||
| //private static transient DocumentFactory singleton; | ||
| private final static ThreadLocal singlePerThread=new ThreadLocal(); | ||
| private static String documentFactoryClassName=null; | ||
| protected transient QNameCache cache; | ||
| /** Default namespace prefix -> URI mappings for XPath expressions to use */ | ||
| private Map xpathNamespaceURIs; | ||
| static { | ||
| try { | ||
| documentFactoryClassName = System.getProperty( | ||
| "org.dom4j.factory", | ||
| "org.dom4j.DocumentFactory" | ||
| ); | ||
| } | ||
| catch (Exception e) { | ||
| documentFactoryClassName = "org.dom4j.DocumentFactory"; | ||
| } | ||
| getInstance(); //create first one | ||
| } | ||
| /** <p>Access to singleton implementation of DocumentFactory which | ||
| * is used if no DocumentFactory is specified when building using the | ||
| * standard builders.</p> | ||
| * | ||
| * @return the default singleon instance | ||
| */ | ||
| public static DocumentFactory getInstance() { | ||
| 52458x | DocumentFactory fact = (DocumentFactory)singlePerThread.get(); | |
| 2/2 52458x | if (fact==null) { | |
| 22x | fact=createSingleton( documentFactoryClassName ); //create first instance | |
| 22x | singlePerThread.set(fact); | |
| } | ||
| 52458x | return fact; | |
| } | ||
| 140x | public DocumentFactory() { | |
| 140x | init(); | |
| 140x | } | |
| // Factory methods | ||
| public Document createDocument() { | ||
| 12020x | DefaultDocument answer = new DefaultDocument(); | |
| 12020x | answer.setDocumentFactory( this ); | |
| 12020x | return answer; | |
| } | ||
| /** | ||
| * @since 1.5 | ||
| */ | ||
| public Document createDocument(String encoding) { | ||
| // to keep the DocumentFactory backwards compatible, we have to do this | ||
| // in this not so nice way, since subclasses only need to extend the | ||
| // createDocument() method. | ||
| 11182x | Document answer = createDocument(); | |
| 1/2 11182x | if (answer instanceof DefaultDocument) { | |
| 11182x | ((DefaultDocument) answer).setXMLEncoding(encoding); | |
| } | ||
| 11182x | return answer; | |
| } | ||
| public Document createDocument(Element rootElement) { | ||
| 4x | Document answer = createDocument(); | |
| 4x | answer.setRootElement(rootElement); | |
| 4x | return answer; | |
| } | ||
| public DocumentType createDocType(String name, String publicId, String systemId) { | ||
| 4x | return new DefaultDocumentType( name, publicId, systemId ); | |
| } | ||
| public Element createElement(QName qname) { | ||
| 128152x | return new DefaultElement(qname); | |
| } | ||
| public Element createElement(String name) { | ||
| 892x | return createElement(createQName(name)); | |
| } | ||
| public Element createElement(String qualifiedName, String namespaceURI) { | ||
| 8x | return createElement(createQName(qualifiedName, namespaceURI)); | |
| } | ||
| public Attribute createAttribute(Element owner, QName qname, String value) { | ||
| 3496x | return new DefaultAttribute(qname, value); | |
| } | ||
| public Attribute createAttribute(Element owner, String name, String value) { | ||
| 3148x | return createAttribute(owner, createQName(name), value); | |
| } | ||
| public CDATA createCDATA(String text) { | ||
| 14x | return new DefaultCDATA(text); | |
| } | ||
| public Comment createComment(String text) { | ||
| 16x | return new DefaultComment(text); | |
| } | ||
| public Text createText(String text) { | ||
| 1/2 104416x | if ( text == null ) { | |
| 0x | throw new IllegalArgumentException( "Adding text to an XML document must not be null" ); | |
| } | ||
| 104416x | return new DefaultText(text); | |
| } | ||
| public Entity createEntity(String name, String text) { | ||
| 0x | return new DefaultEntity(name, text); | |
| } | ||
| public Namespace createNamespace(String prefix, String uri) { | ||
| 131352x | return Namespace.get(prefix, uri); | |
| } | ||
| public ProcessingInstruction createProcessingInstruction(String target, String data) { | ||
| 8x | return new DefaultProcessingInstruction(target, data); | |
| } | ||
| public ProcessingInstruction createProcessingInstruction(String target, Map data) { | ||
| 0x | return new DefaultProcessingInstruction(target, data); | |
| } | ||
| public QName createQName(String localName, Namespace namespace) { | ||
| 137870x | return cache.get(localName, namespace); | |
| } | ||
| public QName createQName(String localName) { | ||
| 24102x | return cache.get(localName); | |
| } | ||
| public QName createQName(String name, String prefix, String uri) { | ||
| 4x | return cache.get(name, Namespace.get( prefix, uri )); | |
| } | ||
| public QName createQName(String qualifiedName, String uri) { | ||
| 8x | return cache.get(qualifiedName, uri); | |
| } | ||
| /** <p><code>createXPath</code> parses an XPath expression | ||
| * and creates a new XPath <code>XPath</code> instance.</p> | ||
| * | ||
| * @param xpathExpression is the XPath expression to create | ||
| * @return a new <code>XPath</code> instance | ||
| * @throws InvalidXPathException if the XPath expression is invalid | ||
| */ | ||
| public XPath createXPath(String xpathExpression) throws InvalidXPathException { | ||
| 560x | DefaultXPath xpath = new DefaultXPath( xpathExpression ); | |
| 1/2 552x | if ( xpathNamespaceURIs != null ) { | |
| 0x | xpath.setNamespaceURIs( xpathNamespaceURIs ); | |
| } | ||
| 552x | return xpath; | |
| } | ||
| /** <p><code>createXPath</code> parses an XPath expression | ||
| * and creates a new XPath <code>XPath</code> instance.</p> | ||
| * | ||
| * @param xpathExpression is the XPath expression to create | ||
| * @param variableContext is the variable context to use when evaluating the XPath | ||
| * @return a new <code>XPath</code> instance | ||
| * @throws InvalidXPathException if the XPath expression is invalid | ||
| */ | ||
| public XPath createXPath(String xpathExpression, VariableContext variableContext) { | ||
| 12x | XPath xpath = createXPath( xpathExpression ); | |
| 12x | xpath.setVariableContext( variableContext ); | |
| 12x | return xpath; | |
| } | ||
| /** <p><code>createXPathFilter</code> parses a NodeFilter | ||
| * from the given XPath filter expression. | ||
| * XPath filter expressions occur within XPath expressions such as | ||
| * <code>self::node()[ filterExpression ]</code></p> | ||
| * | ||
| * @param xpathFilterExpression is the XPath filter expression | ||
| * to create | ||
| * @param variableContext is the variable context to use when evaluating the XPath | ||
| * @return a new <code>NodeFilter</code> instance | ||
| */ | ||
| public NodeFilter createXPathFilter(String xpathFilterExpression, VariableContext variableContext) { | ||
| 0x | XPath answer = createXPath( xpathFilterExpression ); | |
| //DefaultXPath answer = new DefaultXPath( xpathFilterExpression ); | ||
| 0x | answer.setVariableContext( variableContext ); | |
| 0x | return answer; | |
| } | ||
| /** <p><code>createXPathFilter</code> parses a NodeFilter | ||
| * from the given XPath filter expression. | ||
| * XPath filter expressions occur within XPath expressions such as | ||
| * <code>self::node()[ filterExpression ]</code></p> | ||
| * | ||
| * @param xpathFilterExpression is the XPath filter expression | ||
| * to create | ||
| * @return a new <code>NodeFilter</code> instance | ||
| */ | ||
| public NodeFilter createXPathFilter(String xpathFilterExpression) { | ||
| 8x | return createXPath( xpathFilterExpression ); | |
| //return new DefaultXPath( xpathFilterExpression ); | ||
| } | ||
| /** <p><code>createPattern</code> parses the given | ||
| * XPath expression to create an XSLT style {@link Pattern} instance | ||
| * which can then be used in an XSLT processing model.</p> | ||
| * | ||
| * @param xpathPattern is the XPath pattern expression | ||
| * to create | ||
| * @return a new <code>Pattern</code> instance | ||
| */ | ||
| public Pattern createPattern(String xpathPattern) { | ||
| 34x | return new XPathPattern( xpathPattern ); | |
| } | ||
| // Properties | ||
| //------------------------------------------------------------------------- | ||
| /** Returns a list of all the QName instances currently used by this document factory | ||
| */ | ||
| public List getQNames() { | ||
| 0x | return cache.getQNames(); | |
| } | ||
| /** @return the Map of namespace URIs that will be used by by XPath expressions | ||
| * to resolve namespace prefixes into namespace URIs. The map is keyed by | ||
| * namespace prefix and the value is the namespace URI. This value could well be | ||
| * null to indicate no namespace URIs are being mapped. | ||
| */ | ||
| public Map getXPathNamespaceURIs() { | ||
| 0x | return xpathNamespaceURIs; | |
| } | ||
| /** Sets the namespace URIs to be used by XPath expressions created by this factory | ||
| * or by nodes associated with this factory. The keys are namespace prefixes and the | ||
| * values are namespace URIs. | ||
| */ | ||
| public void setXPathNamespaceURIs(Map xpathNamespaceURIs) { | ||
| 2x | this.xpathNamespaceURIs = xpathNamespaceURIs; | |
| 2x | } | |
| // Implementation methods | ||
| //------------------------------------------------------------------------- | ||
| /** <p><code>createSingleton</code> creates the singleton instance | ||
| * from the given class name.</p> | ||
| * | ||
| * @param className is the name of the DocumentFactory class to use | ||
| * @return a new singleton instance. | ||
| */ | ||
| protected static DocumentFactory createSingleton(String className) { | ||
| // let's try and class load an implementation? | ||
| try { | ||
| // I'll use the current class loader | ||
| // that loaded me to avoid problems in J2EE and web apps | ||
| 22x | Class theClass = Class.forName( | |
| className, | ||
| true, | ||
| DocumentFactory.class.getClassLoader() | ||
| ); | ||
| 22x | return (DocumentFactory) theClass.newInstance(); | |
| } | ||
| catch (Throwable e) { | ||
| 0x | System.out.println( "WARNING: Cannot load DocumentFactory: " + className ); | |
| 0x | return new DocumentFactory(); | |
| } | ||
| } | ||
| /** @return the cached QName instance if there is one or adds the given | ||
| * qname to the cache if not | ||
| */ | ||
| protected QName intern(QName qname) { | ||
| 0x | return cache.intern(qname); | |
| } | ||
| /** Factory method to create the QNameCache. This method should be overloaded | ||
| * if you wish to use your own derivation of QName. | ||
| */ | ||
| protected QNameCache createQNameCache() { | ||
| 140x | return new QNameCache(this); | |
| } | ||
| private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { | ||
| 0x | in.defaultReadObject(); | |
| 0x | init(); | |
| 0x | } | |
| protected void init() { | ||
| 140x | cache = createQNameCache(); | |
| 140x | } | |
| } | ||
| /* | ||
| * Redistribution and use of this software and associated documentation | ||
| * ("Software"), with or without modification, are permitted provided | ||
| * that the following conditions are met: | ||
| * | ||
| * 1. Redistributions of source code must retain copyright | ||
| * statements and notices. Redistributions must also contain a | ||
| * copy of this document. | ||
| * | ||
| * 2. Redistributions in binary form must reproduce the | ||
| * above copyright notice, this list of conditions and the | ||
| * following disclaimer in the documentation and/or other | ||
| * materials provided with the distribution. | ||
| * | ||
| * 3. The name "DOM4J" must not be used to endorse or promote | ||
| * products derived from this Software without prior written | ||
| * permission of MetaStuff, Ltd. For written permission, | ||
| * please contact dom4j-info@metastuff.com. | ||
| * | ||
| * 4. Products derived from this Software may not be called "DOM4J" | ||
| * nor may "DOM4J" appear in their names without prior written | ||
| * permission of MetaStuff, Ltd. DOM4J is a registered | ||
| * trademark of MetaStuff, Ltd. | ||
| * | ||
| * 5. Due credit should be given to the DOM4J Project - | ||
| * http://www.dom4j.org | ||
| * | ||
| * THIS SOFTWARE IS PROVIDED BY METASTUFF, LTD. AND CONTRIBUTORS | ||
| * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT | ||
| * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND | ||
| * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL | ||
| * METASTUFF, LTD. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, | ||
| * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||
| * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | ||
| * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
| * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | ||
| * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
| * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED | ||
| * OF THE POSSIBILITY OF SUCH DAMAGE. | ||
| * | ||
| * Copyright 2001-2004 (C) MetaStuff, Ltd. All Rights Reserved. | ||
| * | ||
| * $Id: DocumentFactory.java,v 1.40 2004/07/11 10:49:36 maartenc Exp $ | ||
| */ |