##### Coverage Report - org.jaxen.dom4j.DocumentNavigator

Classes in this File | Line Coverage | Branch Coverage | Complexity
DocumentNavigator |
81% |
88% |
| 2.4054054054054053;2.405

1 |  |
     package org.jaxen.dom4j;
2 |  |
3 |  |
     /*
4 |  |
      * $Header: /home/projects/jaxen/scm/jaxen/src/java/main/org/jaxen/dom4j/DocumentNavigator.java,v 1.30 2005/06/28 13:44:45 elharo Exp $
5 |  |
      * $Revision: 1.30 $
6 |  |
      * $Date: 2005/06/28 13:44:45 $
7 |  |
      *
8 |  |
      * ====================================================================
9 |  |
      *
10 |  |
      * Copyright (C) 2000-2005 bob mcwhirter & James Strachan.
11 |  |
      * All rights reserved.
12 |  |
      *
13 |  |
      * Redistribution and use in source and binary forms, with or without
14 |  |
      * modification, are permitted provided that the following conditions
15 |  |
      * are met:
16 |  |
      *
17 |  |
      * 1. Redistributions of source code must retain the above copyright
18 |  |
      *    notice, this list of conditions, and the following disclaimer.
19 |  |
      *
20 |  |
      * 2. Redistributions in binary form must reproduce the above copyright
21 |  |
      *    notice, this list of conditions, and the disclaimer that follows
22 |  |
      *    these conditions in the documentation and/or other materials
23 |  |
      *    provided with the distribution.
24 |  |
      *
25 |  |
      * 3. The name "Jaxen" must not be used to endorse or promote products
26 |  |
      *    derived from this software without prior written permission.  For
27 |  |
      *    written permission, please contact license@jaxen.org.
28 |  |
      *
29 |  |
      * 4. Products derived from this software may not be called "Jaxen", nor
30 |  |
      *    may "Jaxen" appear in their name, without prior written permission
31 |  |
      *    from the Jaxen Project Management (pm@jaxen.org).
32 |  |
      *
33 |  |
      * In addition, we request (but do not require) that you include in the
34 |  |
      * end-user documentation provided with the redistribution and/or in the
35 |  |
      * software itself an acknowledgement equivalent to the following:
36 |  |
      *     "This product includes software developed by the
37 |  |
      *      Jaxen Project <http://www.jaxen.org/>."
38 |  |
      * Alternatively, the acknowledgment may be graphical using the logos
39 |  |
      * available at http://www.jaxen.org/
40 |  |
      *
41 |  |
      * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
42 |  |
      * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
43 |  |
      * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
44 |  |
      * DISCLAIMED.  IN NO EVENT SHALL THE Jaxen AUTHORS OR THE PROJECT
45 |  |
      * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
46 |  |
      * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
47 |  |
      * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
48 |  |
      * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
49 |  |
      * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
50 |  |
      * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
51 |  |
      * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
52 |  |
      * SUCH DAMAGE.
53 |  |
      *
54 |  |
      * ====================================================================
55 |  |
      * This software consists of voluntary contributions made by many
56 |  |
      * individuals on behalf of the Jaxen Project and was originally
57 |  |
      * created by bob mcwhirter <bob@werken.com> and
58 |  |
      * James Strachan <jstrachan@apache.org>.  For more information on the
59 |  |
      * Jaxen Project, please see <http://www.jaxen.org/>.
60 |  |
      *
61 |  |
      * $Id: DocumentNavigator.java,v 1.30 2005/06/28 13:44:45 elharo Exp $
62 |  |
     */
63 |  |
64 |  |
     import java.util.ArrayList;
65 |  |
     import java.util.HashSet;
66 |  |
     import java.util.Iterator;
67 |  |
     import java.util.List;
68 |  |
69 |  |
     import org.dom4j.Attribute;
70 |  |
     import org.dom4j.Branch;
71 |  |
     import org.dom4j.CDATA;
72 |  |
     import org.dom4j.Comment;
73 |  |
     import org.dom4j.Document;
74 |  |
     import org.dom4j.DocumentException;
75 |  |
     import org.dom4j.Element;
76 |  |
     import org.dom4j.Namespace;
77 |  |
     import org.dom4j.Node;
78 |  |
     import org.dom4j.ProcessingInstruction;
79 |  |
     import org.dom4j.QName;
80 |  |
     import org.dom4j.Text;
81 |  |
     import org.dom4j.io.SAXReader;
82 |  |
     import org.jaxen.DefaultNavigator;
83 |  |
     import org.jaxen.FunctionCallException;
84 |  |
     import org.jaxen.NamedAccessNavigator;
85 |  |
     import org.jaxen.Navigator;
86 |  |
     import org.jaxen.XPath;
87 |  |
     import org.jaxen.JaxenConstants;
88 |  |
     import org.jaxen.saxpath.SAXPathException;
89 |  |
     import org.jaxen.util.SingleObjectIterator;
90 |  |
91 |  |
     /**
92 |  |
      * Interface for navigating around the DOM4J object model.
93 |  |
      *
94 |  |
      * <p>
95 |  |
      * This class is not intended for direct usage, but is
96 |  |
      * used by the Jaxen engine during evaluation.
97 |  |
      * </p>
98 |  |
      *
99 |  |
      * @see XPath
100 |  |
      *
101 |  |
      * @author <a href="mailto:bob@werken.com">bob mcwhirter</a>
102 |  |
      * @author Stephen Colebourne
103 |  |
      */
104 | 1668 |
     public class DocumentNavigator extends DefaultNavigator implements NamedAccessNavigator
105 |  |
     {
106 |  |
107 |  |
         private transient SAXReader reader;
108 |  |
109 |  |
         /** Singleton implementation.
110 |  |
          */
111 | 1668 |
         private static class Singleton
112 |  |
         {
113 |  |
             /** Singleton instance.
114 |  |
              */
115 | 12 |
             private static DocumentNavigator instance = new DocumentNavigator();
116 |  |
         }
117 |  |
118 |  |
         /** Retrieve the singleton instance of this <code>DocumentNavigator</code>.
119 |  |
          */
120 |  |
         public static Navigator getInstance()
121 |  |
         {
122 | 84 |
             return Singleton.instance;
123 |  |
         }
124 |  |
125 |  |
         public boolean isElement(Object obj)
126 |  |
         {
127 | 671322 |
             return obj instanceof Element;
128 |  |
         }
129 |  |
130 |  |
         public boolean isComment(Object obj)
131 |  |
         {
132 | 6588 |
             return obj instanceof Comment;
133 |  |
         }
134 |  |
135 |  |
         public boolean isText(Object obj)
136 |  |
         {
137 | 453414 |
             return ( obj instanceof Text
138 |  |
                      ||
139 |  |
                      obj instanceof CDATA );
140 |  |
         }
141 |  |
142 |  |
         public boolean isAttribute(Object obj)
143 |  |
         {
144 | 26394 |
             return obj instanceof Attribute;
145 |  |
         }
146 |  |
147 |  |
         public boolean isProcessingInstruction(Object obj)
148 |  |
         {
149 | 6348 |
             return obj instanceof ProcessingInstruction;
150 |  |
         }
151 |  |
152 |  |
         public boolean isDocument(Object obj)
153 |  |
         {
154 | 6954 |
             return obj instanceof Document;
155 |  |
         }
156 |  |
157 |  |
         public boolean isNamespace(Object obj)
158 |  |
         {
159 | 24090 |
             return obj instanceof Namespace;
160 |  |
         }
161 |  |
162 |  |
         public String getElementName(Object obj)
163 |  |
         {
164 | 222420 |
             Element elem = (Element) obj;
165 |  |
166 | 222420 |
             return elem.getName();
167 |  |
         }
168 |  |
169 |  |
         public String getElementNamespaceUri(Object obj)
170 |  |
         {
171 | 221034 |
             Element elem = (Element) obj;
172 |  |
173 | 221034 |
             String uri = elem.getNamespaceURI();
174 | 221034 |
             if ( uri == null)
175 | 0 |
                 return "";
176 |  |
             else
177 | 221034 |
                 return uri;
178 |  |
         }
179 |  |
180 |  |
         public String getElementQName(Object obj)
181 |  |
         {
182 | 156 |
             Element elem = (Element) obj;
183 |  |
184 | 156 |
             return elem.getQualifiedName();
185 |  |
         }
186 |  |
187 |  |
         public String getAttributeName(Object obj)
188 |  |
         {
189 | 180 |
             Attribute attr = (Attribute) obj;
190 |  |
191 | 180 |
             return attr.getName();
192 |  |
         }
193 |  |
194 |  |
         public String getAttributeNamespaceUri(Object obj)
195 |  |
         {
196 | 180 |
             Attribute attr = (Attribute) obj;
197 |  |
198 | 180 |
             String uri = attr.getNamespaceURI();
199 | 180 |
             if ( uri == null)
200 | 0 |
                 return "";
201 |  |
             else
202 | 180 |
                 return uri;
203 |  |
         }
204 |  |
205 |  |
         public String getAttributeQName(Object obj)
206 |  |
         {
207 | 0 |
             Attribute attr = (Attribute) obj;
208 |  |
209 | 0 |
             return attr.getQualifiedName();
210 |  |
         }
211 |  |
212 |  |
         public Iterator getChildAxisIterator(Object contextNode)
213 |  |
         {
214 | 699954 |
             Iterator result = null;
215 | 699954 |
             if ( contextNode instanceof Branch )
216 |  |
             {
217 | 244110 |
                 Branch node = (Branch) contextNode;
218 | 244110 |
                 result = node.nodeIterator();
219 |  |
             }
220 | 699954 |
             if (result != null) {
221 | 244110 |
                 return result;
222 |  |
             }
223 | 455844 |
             return JaxenConstants.EMPTY_ITERATOR;
224 |  |
         }
225 |  |
226 |  |
         /**
227 |  |
          * Retrieves an <code>Iterator</code> over the child elements that
228 |  |
          * match the supplied name.
229 |  |
          *
230 |  |
          * @param contextNode  the origin context node
231 |  |
          * @param localName  the local name of the children to return, always present
232 |  |
          * @param namespacePrefix  the prefix of the namespace of the children to return
233 |  |
          * @param namespaceURI  the uri of the namespace of the children to return
234 |  |
          * @return an Iterator that traverses the named children, or null if none
235 |  |
          */
236 |  |
         public Iterator getChildAxisIterator(
237 |  |
                 Object contextNode, String localName, String namespacePrefix, String namespaceURI) {
238 |  |
239 | 14148 |
             if ( contextNode instanceof Element ) {
240 | 5598 |
                 Element node = (Element) contextNode;
241 | 5598 |
                 return node.elementIterator(QName.get(localName, namespacePrefix, namespaceURI));
242 |  |
             }
243 | 8550 |
             if ( contextNode instanceof Document ) {
244 | 690 |
                 Document node = (Document) contextNode;
245 | 690 |
                 Element el = node.getRootElement();
246 | 690 |
                 if (el.getName().equals(localName) == false) {
247 | 90 |
                     return JaxenConstants.EMPTY_ITERATOR;
248 |  |
                 }
249 | 600 |
                 if (namespaceURI != null) {
250 | 60 |
                     if (namespaceURI.equals(el.getNamespaceURI()) == false) {
251 | 6 |
                         return JaxenConstants.EMPTY_ITERATOR;
252 |  |
                     }
253 |  |
                 }
254 | 594 |
                 return new SingleObjectIterator(el);
255 |  |
             }
256 |  |
257 | 7860 |
             return JaxenConstants.EMPTY_ITERATOR;
258 |  |
         }
259 |  |
260 |  |
         public Iterator getParentAxisIterator(Object contextNode)
261 |  |
         {
262 | 84 |
             if ( contextNode instanceof Document )
263 |  |
             {
264 | 6 |
                 return JaxenConstants.EMPTY_ITERATOR;
265 |  |
             }
266 |  |
267 | 78 |
             Node node = (Node) contextNode;
268 |  |
269 | 78 |
             Object parent = node.getParent();
270 |  |
271 | 78 |
             if ( parent == null )
272 |  |
             {
273 | 30 |
                 parent = node.getDocument();
274 |  |
             }
275 |  |
276 | 78 |
             return new SingleObjectIterator( parent );
277 |  |
         }
278 |  |
279 |  |
         public Iterator getAttributeAxisIterator(Object contextNode)
280 |  |
         {
281 | 306 |
             if ( ! ( contextNode instanceof Element ) )
282 |  |
             {
283 | 0 |
                 return JaxenConstants.EMPTY_ITERATOR;
284 |  |
             }
285 |  |
286 | 306 |
             Element elem = (Element) contextNode;
287 |  |
288 | 306 |
             return elem.attributeIterator();
289 |  |
         }
290 |  |
291 |  |
         /**
292 |  |
          * Retrieves an <code>Iterator</code> over the attribute elements that
293 |  |
          * match the supplied name.
294 |  |
          *
295 |  |
          * @param contextNode  the origin context node
296 |  |
          * @param localName  the local name of the attributes to return, always present
297 |  |
          * @param namespacePrefix  the prefix of the namespace of the attributes to return
298 |  |
          * @param namespaceURI  the URI of the namespace of the attributes to return
299 |  |
          * @return an Iterator that traverses the named attributes, not null
300 |  |
          */
301 |  |
         public Iterator getAttributeAxisIterator(
302 |  |
                 Object contextNode, String localName, String namespacePrefix, String namespaceURI) {
303 |  |
304 | 3564 |
             if ( contextNode instanceof Element ) {
305 | 3288 |
                 Element node = (Element) contextNode;
306 | 3288 |
                 Attribute attr = node.attribute(QName.get(localName, namespacePrefix, namespaceURI));
307 | 3288 |
                 if (attr == null) {
308 | 1386 |
                     return JaxenConstants.EMPTY_ITERATOR;
309 |  |
                 }
310 | 1902 |
                 return new SingleObjectIterator(attr);
311 |  |
             }
312 | 276 |
             return JaxenConstants.EMPTY_ITERATOR;
313 |  |
         }
314 |  |
315 |  |
         public Iterator getNamespaceAxisIterator(Object contextNode)
316 |  |
         {
317 | 1002 |
             if ( ! ( contextNode instanceof Element ) )
318 |  |
             {
319 | 624 |
                 return JaxenConstants.EMPTY_ITERATOR;
320 |  |
             }
321 |  |
322 | 378 |
             Element element = (Element) contextNode;
323 | 378 |
             List nsList = new ArrayList();
324 | 378 |
             HashSet prefixes = new HashSet();
325 | 1368 |
             for ( Element context = element; context != null; context = context.getParent() ) {
326 | 990 |
                 List declaredNS = new ArrayList(context.declaredNamespaces());
327 | 990 |
                 declaredNS.add(context.getNamespace());
328 |  |
329 | 990 |
                 for ( Iterator iter = context.attributes().iterator(); iter.hasNext(); )
330 |  |
                 {
331 | 492 |
                     Attribute attr = (Attribute) iter.next();
332 | 492 |
                     declaredNS.add(attr.getNamespace());
333 |  |
                 }
334 |  |
335 | 990 |
                 for ( Iterator iter = declaredNS.iterator(); iter.hasNext(); )
336 |  |
                 {
337 | 2118 |
                     Namespace namespace = (Namespace) iter.next();
338 | 2118 |
                     if (namespace != Namespace.NO_NAMESPACE)
339 |  |
                     {
340 | 882 |
                         String prefix = namespace.getPrefix();
341 | 882 |
                         if ( ! prefixes.contains( prefix ) ) {
342 | 666 |
                             prefixes.add( prefix );
343 | 666 |
                             nsList.add( namespace.asXPathResult( element ) );
344 |  |
                         }
345 |  |
                     }
346 |  |
                 }
347 |  |
             }
348 | 378 |
             nsList.add( Namespace.XML_NAMESPACE.asXPathResult( element ) );
349 | 378 |
             return nsList.iterator();
350 |  |
         }
351 |  |
352 |  |
         public Object getDocumentNode(Object contextNode)
353 |  |
         {
354 | 1578 |
             if ( contextNode instanceof Document )
355 |  |
             {
356 | 1170 |
                 return contextNode;
357 |  |
             }
358 | 408 |
             else if ( contextNode instanceof Node )
359 |  |
             {
360 | 408 |
                 Node node = (Node) contextNode;
361 | 408 |
                 return node.getDocument();
362 |  |
             }
363 | 0 |
             return null;
364 |  |
         }
365 |  |
366 |  |
         /** Returns a parsed form of the given xpath string, which will be suitable
367 |  |
          *  for queries on DOM4J documents.
368 |  |
          */
369 |  |
         public XPath parseXPath (String xpath) throws SAXPathException
370 |  |
         {
371 | 42 |
             return new Dom4jXPath(xpath);
372 |  |
         }
373 |  |
374 |  |
         public Object getParentNode(Object contextNode)
375 |  |
         {
376 | 150834 |
             if ( contextNode instanceof Node )
377 |  |
             {
378 | 150834 |
                 Node node = (Node) contextNode;
379 | 150834 |
                 Object answer = node.getParent();
380 | 150834 |
                 if ( answer == null )
381 |  |
                 {
382 | 58992 |
                     answer = node.getDocument();
383 | 58992 |
                     if (answer == contextNode) {
384 | 29388 |
                         return null;
385 |  |
                     }
386 |  |
                 }
387 | 121446 |
                 return answer;
388 |  |
             }
389 | 0 |
             return null;
390 |  |
         }
391 |  |
392 |  |
         public String getTextStringValue(Object obj)
393 |  |
         {
394 | 66 |
             return getNodeStringValue( (Node) obj );
395 |  |
         }
396 |  |
397 |  |
         public String getElementStringValue(Object obj)
398 |  |
         {
399 | 780 |
             return getNodeStringValue( (Node) obj );
400 |  |
         }
401 |  |
402 |  |
         public String getAttributeStringValue(Object obj)
403 |  |
         {
404 | 1722 |
             return getNodeStringValue( (Node) obj );
405 |  |
         }
406 |  |
407 |  |
         private String getNodeStringValue(Node node)
408 |  |
         {
409 | 2568 |
             return node.getStringValue();
410 |  |
         }
411 |  |
412 |  |
         public String getNamespaceStringValue(Object obj)
413 |  |
         {
414 | 0 |
             Namespace ns = (Namespace) obj;
415 |  |
416 | 0 |
             return ns.getURI();
417 |  |
         }
418 |  |
419 |  |
         public String getNamespacePrefix(Object obj)
420 |  |
         {
421 | 702 |
             Namespace ns = (Namespace) obj;
422 |  |
423 | 702 |
             return ns.getPrefix();
424 |  |
         }
425 |  |
426 |  |
         public String getCommentStringValue(Object obj)
427 |  |
         {
428 | 0 |
             Comment cmt = (Comment) obj;
429 |  |
430 | 0 |
             return cmt.getText();
431 |  |
         }
432 |  |
433 |  |
         public String translateNamespacePrefixToUri(String prefix, Object context)
434 |  |
         {
435 | 0 |
             Element element = null;
436 | 0 |
             if ( context instanceof Element )
437 |  |
             {
438 | 0 |
                 element = (Element) context;
439 |  |
             }
440 | 0 |
             else if ( context instanceof Node )
441 |  |
             {
442 | 0 |
                 Node node = (Node) context;
443 | 0 |
                 element = node.getParent();
444 |  |
             }
445 | 0 |
             if ( element != null )
446 |  |
             {
447 | 0 |
                 Namespace namespace = element.getNamespaceForPrefix( prefix );
448 |  |
449 | 0 |
                 if ( namespace != null )
450 |  |
                 {
451 | 0 |
                     return namespace.getURI();
452 |  |
                 }
453 |  |
             }
454 | 0 |
             return null;
455 |  |
         }
456 |  |
457 |  |
         public short getNodeType(Object node)
458 |  |
         {
459 | 150 |
             if ( node instanceof Node )
460 |  |
             {
461 | 150 |
                 return ((Node) node).getNodeType();
462 |  |
             }
463 | 0 |
             return 0;
464 |  |
         }
465 |  |
466 |  |
         public Object getDocument(String uri) throws FunctionCallException
467 |  |
         {
468 |  |
             try
469 |  |
             {
470 | 402 |
                 return getSAXReader().read( uri );
471 |  |
             }
472 | 0 |
             catch (DocumentException e)
473 |  |
             {
474 | 0 |
                 throw new FunctionCallException("Failed to parse document for URI: " + uri, e);
475 |  |
             }
476 |  |
         }
477 |  |
478 |  |
         public String getProcessingInstructionTarget(Object obj)
479 |  |
         {
480 | 36 |
             ProcessingInstruction pi = (ProcessingInstruction) obj;
481 |  |
482 | 36 |
             return pi.getTarget();
483 |  |
         }
484 |  |
485 |  |
         public String getProcessingInstructionData(Object obj)
486 |  |
         {
487 | 18 |
             ProcessingInstruction pi = (ProcessingInstruction) obj;
488 |  |
489 | 18 |
             return pi.getText();
490 |  |
         }
491 |  |
492 |  |
         // Properties
493 |  |
         //-------------------------------------------------------------------------
494 |  |
         public SAXReader getSAXReader()
495 |  |
         {
496 | 402 |
             if ( reader == null )
497 |  |
             {
498 | 396 |
                 reader = new SAXReader();
499 | 396 |
                 reader.setMergeAdjacentText( true );
500 |  |
             }
501 | 402 |
             return reader;
502 |  |
         }
503 |  |
504 |  |
         public void setSAXReader(SAXReader reader)
505 |  |
         {
506 | 0 |
             this.reader = reader;
507 | 0 |
         }
508 |  |
509 |  |
     }