Clover coverage report - dom4j - 1.6.1 Coverage timestamp: ma mei 16 2005 14:23:01 GMT+01:00 FRAMES NO FRAMES |
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% |

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 |  | */