KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > dom4j > DocumentFactory


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 JavaDoc;
11 import java.io.ObjectInputStream JavaDoc;
12 import java.io.Serializable JavaDoc;
13 import java.util.List JavaDoc;
14 import java.util.Map JavaDoc;
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 JavaDoc {
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 JavaDoc xpathNamespaceURIs;
54
55     private static SingletonStrategy createSingleton() {
56         SingletonStrategy result = null;
57         
58         String JavaDoc documentFactoryClassName;
59         try {
60             documentFactoryClassName = System.getProperty("org.dom4j.factory",
61                     "org.dom4j.DocumentFactory");
62         } catch (Exception JavaDoc e) {
63             documentFactoryClassName = "org.dom4j.DocumentFactory";
64         }
65
66         try {
67             String JavaDoc singletonClass = System.getProperty(
68                     "org.dom4j.DocumentFactory.singleton.strategy",
69                     "org.dom4j.util.SimpleSingleton");
70             Class JavaDoc clazz = Class.forName(singletonClass);
71             result = (SingletonStrategy) clazz.newInstance();
72         } catch (Exception JavaDoc e) {
73             result = new SimpleSingleton();
74         }
75
76         result.setSingletonClassName(documentFactoryClassName);
77         
78         return result;
79     }
80
81     public DocumentFactory() {
82         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     public static synchronized DocumentFactory getInstance() {
94         if (singleton == null) {
95             singleton = createSingleton();
96         }
97         return (DocumentFactory) singleton.instance();
98     }
99
100     // Factory methods
101
public Document createDocument() {
102         DefaultDocument answer = new DefaultDocument();
103         answer.setDocumentFactory(this);
104
105         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     public Document createDocument(String JavaDoc 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
Document answer = createDocument();
123
124         if (answer instanceof AbstractDocument) {
125             ((AbstractDocument) answer).setXMLEncoding(encoding);
126         }
127
128         return answer;
129     }
130
131     public Document createDocument(Element rootElement) {
132         Document answer = createDocument();
133         answer.setRootElement(rootElement);
134
135         return answer;
136     }
137
138     public DocumentType createDocType(String JavaDoc name, String JavaDoc publicId,
139             String JavaDoc systemId) {
140         return new DefaultDocumentType(name, publicId, systemId);
141     }
142
143     public Element createElement(QName qname) {
144         return new DefaultElement(qname);
145     }
146
147     public Element createElement(String JavaDoc name) {
148         return createElement(createQName(name));
149     }
150
151     public Element createElement(String JavaDoc qualifiedName, String JavaDoc namespaceURI) {
152         return createElement(createQName(qualifiedName, namespaceURI));
153     }
154
155     public Attribute createAttribute(Element owner, QName qname, String JavaDoc value) {
156         return new DefaultAttribute(qname, value);
157     }
158
159     public Attribute createAttribute(Element owner, String JavaDoc name, String JavaDoc value) {
160         return createAttribute(owner, createQName(name), value);
161     }
162
163     public CDATA createCDATA(String JavaDoc text) {
164         return new DefaultCDATA(text);
165     }
166
167     public Comment createComment(String JavaDoc text) {
168         return new DefaultComment(text);
169     }
170
171     public Text createText(String JavaDoc text) {
172         if (text == null) {
173             String JavaDoc msg = "Adding text to an XML document must not be null";
174             throw new IllegalArgumentException JavaDoc(msg);
175         }
176
177         return new DefaultText(text);
178     }
179
180     public Entity createEntity(String JavaDoc name, String JavaDoc text) {
181         return new DefaultEntity(name, text);
182     }
183
184     public Namespace createNamespace(String JavaDoc prefix, String JavaDoc uri) {
185         return Namespace.get(prefix, uri);
186     }
187
188     public ProcessingInstruction createProcessingInstruction(String JavaDoc target,
189             String JavaDoc data) {
190         return new DefaultProcessingInstruction(target, data);
191     }
192
193     public ProcessingInstruction createProcessingInstruction(String JavaDoc target,
194             Map JavaDoc data) {
195         return new DefaultProcessingInstruction(target, data);
196     }
197
198     public QName createQName(String JavaDoc localName, Namespace namespace) {
199         return cache.get(localName, namespace);
200     }
201
202     public QName createQName(String JavaDoc localName) {
203         return cache.get(localName);
204     }
205
206     public QName createQName(String JavaDoc name, String JavaDoc prefix, String JavaDoc uri) {
207         return cache.get(name, Namespace.get(prefix, uri));
208     }
209
210     public QName createQName(String JavaDoc qualifiedName, String JavaDoc uri) {
211         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     public XPath createXPath(String JavaDoc xpathExpression)
229             throws InvalidXPathException {
230         DefaultXPath xpath = new DefaultXPath(xpathExpression);
231
232         if (xpathNamespaceURIs != null) {
233             xpath.setNamespaceURIs(xpathNamespaceURIs);
234         }
235
236         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     public XPath createXPath(String JavaDoc xpathExpression,
253             VariableContext variableContext) {
254         XPath xpath = createXPath(xpathExpression);
255         xpath.setVariableContext(variableContext);
256
257         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     public NodeFilter createXPathFilter(String JavaDoc xpathFilterExpression,
275             VariableContext variableContext) {
276         XPath answer = createXPath(xpathFilterExpression);
277
278         // DefaultXPath answer = new DefaultXPath( xpathFilterExpression );
279
answer.setVariableContext(variableContext);
280
281         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     public NodeFilter createXPathFilter(String JavaDoc xpathFilterExpression) {
297         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     public Pattern createPattern(String JavaDoc xpathPattern) {
315         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     public List JavaDoc getQNames() {
328         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     public Map JavaDoc getXPathNamespaceURIs() {
341         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     public void setXPathNamespaceURIs(Map JavaDoc namespaceURIs) {
353         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     protected static DocumentFactory createSingleton(String JavaDoc className) {
371         // let's try and class load an implementation?
372
try {
373             // I'll use the current class loader
374
// that loaded me to avoid problems in J2EE and web apps
375
Class JavaDoc theClass = Class.forName(className, true,
376                     DocumentFactory.class.getClassLoader());
377
378             return (DocumentFactory) theClass.newInstance();
379         } catch (Throwable JavaDoc e) {
380             System.out.println("WARNING: Cannot load DocumentFactory: "
381                     + className);
382
383             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     protected QName intern(QName qname) {
397         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     protected QNameCache createQNameCache() {
407         return new QNameCache(this);
408     }
409
410     private void readObject(ObjectInputStream JavaDoc in) throws IOException JavaDoc,
411             ClassNotFoundException JavaDoc {
412         in.defaultReadObject();
413         init();
414     }
415
416     protected void init() {
417         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  */
Popular Tags