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

Classes in this File | Line Coverage | Branch Coverage | Complexity
DocumentNavigator |
74% |
69% |
| 1.8;1.8

1 |  |
     /*
2 |  |
      * $Header: /home/projects/jaxen/scm/jaxen/src/java/main/org/jaxen/xom/DocumentNavigator.java,v 1.6 2005/06/28 13:44:46 elharo Exp $
3 |  |
      * $Revision: 1.6 $
4 |  |
      * $Date: 2005/06/28 13:44:46 $
5 |  |
      *
6 |  |
      * ====================================================================
7 |  |
      *
8 |  |
      * Copyright (C) 2000-2003 bob mcwhirter & James Strachan.
9 |  |
      * All rights reserved.
10 |  |
      *
11 |  |
      * Redistribution and use in source and binary forms, with or without
12 |  |
      * modification, are permitted provided that the following conditions
13 |  |
      * are met:
14 |  |
      *
15 |  |
      * 1. Redistributions of source code must retain the above copyright
16 |  |
      *    notice, this list of conditions, and the following disclaimer.
17 |  |
      *
18 |  |
      * 2. Redistributions in binary form must reproduce the above copyright
19 |  |
      *    notice, this list of conditions, and the disclaimer that follows
20 |  |
      *    these conditions in the documentation and/or other materials
21 |  |
      *    provided with the distribution.
22 |  |
      *
23 |  |
      * 3. The name "Jaxen" must not be used to endorse or promote products
24 |  |
      *    derived from this software without prior written permission.  For
25 |  |
      *    written permission, please contact license@jaxen.org.
26 |  |
      *
27 |  |
      * 4. Products derived from this software may not be called "Jaxen", nor
28 |  |
      *    may "Jaxen" appear in their name, without prior written permission
29 |  |
      *    from the Jaxen Project Management (pm@jaxen.org).
30 |  |
      *
31 |  |
      * In addition, we request (but do not require) that you include in the
32 |  |
      * end-user documentation provided with the redistribution and/or in the
33 |  |
      * software itself an acknowledgement equivalent to the following:
34 |  |
      *     "This product includes software developed by the
35 |  |
      *      Jaxen Project <http://www.jaxen.org/>."
36 |  |
      * Alternatively, the acknowledgment may be graphical using the logos
37 |  |
      * available at http://www.jaxen.org/
38 |  |
      *
39 |  |
      * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
40 |  |
      * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
41 |  |
      * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
42 |  |
      * DISCLAIMED.  IN NO EVENT SHALL THE Jaxen AUTHORS OR THE PROJECT
43 |  |
      * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44 |  |
      * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
45 |  |
      * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
46 |  |
      * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
47 |  |
      * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
48 |  |
      * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
49 |  |
      * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
50 |  |
      * SUCH DAMAGE.
51 |  |
      *
52 |  |
      * ====================================================================
53 |  |
      * This software consists of voluntary contributions made by many
54 |  |
      * individuals on behalf of the Jaxen Project and was originally
55 |  |
      * created by bob mcwhirter <bob@werken.com> and
56 |  |
      * James Strachan <jstrachan@apache.org>.  For more information on the
57 |  |
      * Jaxen Project, please see <http://www.jaxen.org/>.
58 |  |
      *
59 |  |
      * $Id: DocumentNavigator.java,v 1.6 2005/06/28 13:44:46 elharo Exp $
60 |  |
      */
61 |  |
62 |  |
63 |  |
     package org.jaxen.xom;
64 |  |
65 |  |
66 |  |
     import nu.xom.Attribute;
67 |  |
     import nu.xom.Comment;
68 |  |
     import nu.xom.Document;
69 |  |
     import nu.xom.Element;
70 |  |
     import nu.xom.ProcessingInstruction;
71 |  |
     import nu.xom.Text;
72 |  |
     import nu.xom.Node;
73 |  |
     import nu.xom.Builder;
74 |  |
     import nu.xom.NodeFactory;
75 |  |
     import nu.xom.ParentNode;
76 |  |
77 |  |
     import org.jaxen.XPath;
78 |  |
     import org.jaxen.UnsupportedAxisException;
79 |  |
     import org.jaxen.FunctionCallException;
80 |  |
     import org.jaxen.BaseXPath;
81 |  |
     import org.jaxen.JaxenConstants;
82 |  |
     import org.jaxen.util.SingleObjectIterator;
83 |  |
84 |  |
     import org.jaxen.saxpath.SAXPathException;
85 |  |
86 |  |
     import java.util.Iterator;
87 |  |
     import java.util.HashMap;
88 |  |
     import java.util.Map;
89 |  |
90 |  |
     /**
91 |  |
      * Interface for navigating around the XOM object model.
92 |  |
      *
93 |  |
      * <p>
94 |  |
      * This class is not intended for direct usage, but is
95 |  |
      * used by the Jaxen engine during evaluation.
96 |  |
      * </p>
97 |  |
      *
98 |  |
      * @see XPath
99 |  |
      *
100 |  |
      */
101 | 1662 |
     public class DocumentNavigator extends org.jaxen.DefaultNavigator
102 |  |
     {
103 |  |
         public boolean isAttribute(Object o) {
104 | 39384 |
             return o instanceof Attribute;
105 |  |
         }
106 |  |
107 |  |
         public boolean isComment(Object o) {
108 | 6660 |
             return o instanceof Comment;
109 |  |
         }
110 |  |
111 |  |
         public boolean isDocument(Object o) {
112 | 7254 |
             return o instanceof Document;
113 |  |
         }
114 |  |
115 |  |
         public boolean isElement(Object o) {
116 | 1913226 |
             return o instanceof Element;
117 |  |
         }
118 |  |
119 |  |
         public boolean isNamespace(Object o) {
120 | 26658 |
             return o instanceof XPathNamespace;
121 |  |
         }
122 |  |
123 |  |
         public boolean isProcessingInstruction(Object o) {
124 | 6480 |
             return o instanceof ProcessingInstruction;
125 |  |
         }
126 |  |
127 |  |
         public boolean isText(Object o) {
128 | 478770 |
             return o instanceof Text;
129 |  |
         }
130 |  |
131 |  |
         //
132 |  |
133 |  |
         public String getAttributeName(Object o) {
134 | 2730 |
             return (isAttribute(o) ? ((Attribute)o).getLocalName() : null);
135 |  |
         }
136 |  |
137 |  |
         public String getAttributeNamespaceUri(Object o) {
138 | 2730 |
             return (isAttribute(o) ? ((Attribute)o).getNamespaceURI() : null);
139 |  |
         }
140 |  |
141 |  |
         public String getAttributeQName(Object o) {
142 | 0 |
             return (isAttribute(o) ? ((Attribute)o).getQualifiedName() : null);
143 |  |
         }
144 |  |
145 |  |
         public String getAttributeStringValue(Object o) {
146 | 1722 |
             return (isAttribute(o) ? ((Attribute)o).getValue() : null);
147 |  |
         }
148 |  |
149 |  |
         //
150 |  |
151 |  |
         public String getCommentStringValue(Object o) {
152 | 0 |
             return (isComment(o) ? ((Comment)o).getValue() : null);
153 |  |
         }
154 |  |
155 |  |
         public String getElementName(Object o) {
156 | 240456 |
             return (isElement(o) ? ((Element)o).getLocalName() : null);
157 |  |
         }
158 |  |
159 |  |
         public String getElementNamespaceUri(Object o) {
160 | 239070 |
             return (isElement(o) ? ((Element)o).getNamespaceURI() : null);
161 |  |
         }
162 |  |
163 |  |
         public String getElementQName(Object o) {
164 | 156 |
             return (isElement(o) ? ((Element)o).getQualifiedName() : null);
165 |  |
         }
166 |  |
167 |  |
         public String getElementStringValue(Object o) {
168 | 774 |
             return (o instanceof Node ? ((Node)o).getValue() : null);
169 |  |
         }
170 |  |
171 |  |
         //
172 |  |
173 |  |
         public String getNamespacePrefix(Object o) {
174 | 702 |
             if (isElement(o)) {
175 | 0 |
                 return ((Element)o).getNamespacePrefix();
176 | 702 |
             } else if (isAttribute(o)) {
177 | 0 |
                 return ((Attribute)o).getNamespacePrefix();
178 | 702 |
             } else if (o instanceof XPathNamespace) {
179 | 702 |
                 return ((XPathNamespace)o).getNamespacePrefix();
180 |  |
             }
181 | 0 |
             return null;
182 |  |
         }
183 |  |
184 |  |
         public String getNamespaceStringValue(Object o) {
185 | 0 |
             if (isElement(o)) {
186 | 0 |
                 return ((Element)o).getNamespaceURI();
187 | 0 |
             } else if (isAttribute(o)) {
188 | 0 |
                 return ((Attribute)o).getNamespaceURI();
189 | 0 |
             } else if (o instanceof XPathNamespace) {
190 | 0 |
                 return ((XPathNamespace)o).getNamespaceURI();
191 |  |
             }
192 | 0 |
             return null;
193 |  |
         }
194 |  |
195 |  |
         //
196 |  |
197 |  |
         public String getTextStringValue(Object o) {
198 | 66 |
             return (o instanceof Text ? ((Text)o).getValue() : null);
199 |  |
         }
200 |  |
201 |  |
         //
202 |  |
203 |  |
         public Object getDocument(String s) throws FunctionCallException {
204 |  |
             try {
205 | 396 |
                 return new Builder(new NodeFactory()).build(s);
206 | 0 |
             } catch (Exception pe) {
207 | 0 |
                 throw new FunctionCallException(pe);
208 |  |
             }
209 |  |
         }
210 |  |
211 |  |
         public Object getDocumentNode(Object o) {
212 | 1560 |
             ParentNode parent = null;
213 | 1560 |
             if (o instanceof ParentNode) {
214 | 1560 |
                 parent = (ParentNode)o;
215 | 0 |
             } else if (o instanceof Node) {
216 | 0 |
                 parent = ((Node)o).getParent();
217 |  |
             }
218 | 1560 |
             return parent.getDocument();
219 |  |
         }
220 |  |
221 |  |
         //
222 |  |
223 |  |
         private abstract static class IndexIterator implements Iterator {
224 | 253650 |
             private Object o = null;
225 | 253650 |
             private int pos = 0, end = -1;
226 | 253650 |
             public IndexIterator(Object o, int pos, int end) {
227 | 253650 |
                 this.o = o;
228 | 253650 |
                 this.pos = pos;
229 | 253650 |
                 this.end = end;
230 | 253650 |
             }
231 |  |
             public boolean hasNext() {
232 | 2113932 |
                 return pos < end;
233 |  |
             }
234 |  |
             public abstract Object get(Object o, int i);
235 |  |
236 |  |
             public Object next() {
237 | 1189170 |
                 return get(o, pos++);
238 |  |
             }
239 |  |
240 |  |
             public void remove() {
241 | 0 |
                 throw new UnsupportedOperationException();
242 |  |
             }
243 |  |
         }
244 |  |
245 |  |
         //
246 |  |
247 |  |
         public Iterator getAttributeAxisIterator(Object o) {
248 | 3870 |
             if (isElement(o)) {
249 | 3594 |
                 return new IndexIterator(o, 0, ((Element)o).getAttributeCount()) {
250 | 3594 |
                     public Object get(Object o, int i) {
251 | 2730 |
                         return ((Element)o).getAttribute(i);
252 |  |
                     }
253 |  |
                 };
254 |  |
             }
255 | 276 |
             return JaxenConstants.EMPTY_ITERATOR;
256 |  |
         }
257 |  |
258 |  |
         public Iterator getChildAxisIterator(Object o) {
259 | 713490 |
             if (isElement(o) || (o instanceof Document)) {
260 | 250056 |
                 return new IndexIterator(o, 0, ((ParentNode)o).getChildCount()) {
261 | 250056 |
                     public Object get(Object o, int i) {
262 | 1186440 |
                         return ((ParentNode)o).getChild(i);
263 |  |
                     }
264 |  |
                 };
265 |  |
             }
266 | 463434 |
             return JaxenConstants.EMPTY_ITERATOR;
267 |  |
         }
268 |  |
269 |  |
         //
270 |  |
271 |  |
         public Iterator getParentAxisIterator(Object o) {
272 | 84 |
             Object parent = null;
273 | 84 |
             if (o instanceof Node) {
274 | 72 |
                 parent = ((Node)o).getParent();
275 | 12 |
             } else if (isNamespace(o)) {
276 | 12 |
                 parent = ((XPathNamespace)o).getElement();
277 |  |
             }
278 | 84 |
             return (parent != null ? new SingleObjectIterator(parent) : null);
279 |  |
         }
280 |  |
281 |  |
         public Object getParentNode(Object o)  {
282 | 144618 |
             return (o instanceof Node ? ((Node)o).getParent() : null);
283 |  |
         }
284 |  |
285 |  |
         //
286 |  |
287 |  |
         public Iterator getPrecedingAxisIterator(Object o) throws UnsupportedAxisException {
288 | 108 |
             return super.getPrecedingAxisIterator(o);
289 |  |
         }
290 |  |
291 |  |
         public Iterator getPrecedingSiblingAxisIterator(Object o) throws UnsupportedAxisException {
292 | 66 |
             return super.getPrecedingSiblingAxisIterator(o);
293 |  |
         }
294 |  |
295 |  |
         //
296 |  |
297 |  |
         public String getProcessingInstructionData(Object o) {
298 | 18 |
             return (o instanceof ProcessingInstruction ? ((ProcessingInstruction)o).getValue() : null);
299 |  |
         }
300 |  |
301 |  |
         public String getProcessingInstructionTarget(Object o) {
302 | 36 |
             return (o instanceof ProcessingInstruction ? ((ProcessingInstruction)o).getTarget() : null);
303 |  |
         }
304 |  |
305 |  |
         //
306 |  |
307 |  |
         public String translateNamespacePrefixToUri(String s, Object o) {
308 | 0 |
             Element element = null;
309 | 0 |
             if (o instanceof Element) {
310 | 0 |
                 element = (Element) o;
311 | 0 |
             } else if (o instanceof ParentNode) {
312 |  |
             }
313 | 0 |
             else if (o instanceof Node) {
314 | 0 |
                 element = (Element)((Node)o).getParent();
315 |  |
             }
316 | 0 |
             else if (o instanceof XPathNamespace)
317 |  |
             {
318 | 0 |
                 element = ((XPathNamespace)o).getElement();
319 |  |
             }
320 | 0 |
             if (element != null) {
321 | 0 |
                 return element.getNamespaceURI(s);
322 |  |
             }
323 | 0 |
             return null;
324 |  |
         }
325 |  |
326 |  |
         //
327 |  |
328 |  |
         public XPath parseXPath(String s) throws SAXPathException {
329 | 42 |
             return new BaseXPath(s, this);
330 |  |
         }
331 |  |
332 |  |
         //
333 |  |
334 |  |
         /** Wrapper for XOM namespace nodes to give them a parent,
335 |  |
          * as required by the XPath data model.
336 |  |
          *
337 |  |
          *  @author Erwin Bolwidt
338 |  |
          */
339 | 1662 |
         private static class XPathNamespace
340 |  |
         {
341 |  |
             private Element element;
342 |  |
343 |  |
             private String uri, prefix;
344 |  |
345 |  |
             public XPathNamespace(Element elt, String uri, String prefix)
346 | 852 |
             {
347 | 852 |
                 element = elt;
348 | 852 |
                 this.uri = uri;
349 | 852 |
                 this.prefix = prefix;
350 | 852 |
             }
351 |  |
352 |  |
             /** Returns the XOM element from which this namespace node has been
353 |  |
              *  retrieved. The result may be null when the namespace node has not yet
354 |  |
              *  been assigned to an element.
355 |  |
              */
356 |  |
             public Element getElement()
357 |  |
             {
358 | 12 |
                 return element;
359 |  |
             }
360 |  |
361 |  |
             public String getNamespaceURI()
362 |  |
             {
363 | 0 |
                 return uri;
364 |  |
             }
365 |  |
366 |  |
             public String getNamespacePrefix()
367 |  |
             {
368 | 702 |
                 return prefix;
369 |  |
             }
370 |  |
371 |  |
             public String toString()
372 |  |
             {
373 | 0 |
                 return ( "[xmlns:" + prefix + "=\"" +
374 |  |
                         uri + "\", element=" +
375 |  |
                         element.getLocalName() + "]" );
376 |  |
             }
377 |  |
         }
378 |  |
379 |  |
         //
380 |  |
381 |  |
         private boolean addNamespaceForElement(Element elt, String uri, String prefix, Map map)
382 |  |
         {
383 | 2496 |
             if (uri != null && uri.length() > 0 && (! map.containsKey(prefix))) {
384 | 852 |
                 map.put(prefix, new XPathNamespace(elt, uri, prefix));
385 | 852 |
                 return true;
386 |  |
             }
387 | 1644 |
             return false;
388 |  |
         }
389 |  |
390 |  |
         public Iterator getNamespaceAxisIterator(Object o)
391 |  |
         {
392 | 750 |
             if (! isElement(o)) {
393 | 438 |
                 return JaxenConstants.EMPTY_ITERATOR;
394 |  |
             }
395 | 312 |
             Map nsMap = new HashMap();
396 | 312 |
             Element elt = (Element)o;
397 | 312 |
             ParentNode parent = elt;
398 |  |
399 | 1134 |
             while (parent instanceof Element) {
400 | 822 |
                 elt = (Element)parent;
401 | 822 |
                 String uri    = elt.getNamespaceURI();
402 | 822 |
                 String prefix = elt.getNamespacePrefix();
403 | 822 |
                 addNamespaceForElement(elt, uri, prefix, nsMap);
404 | 822 |
                 int count = elt.getNamespaceDeclarationCount();
405 | 2184 |
                 for (int i = 0; i < count; i++) {
406 | 1362 |
                     prefix = elt.getNamespacePrefix(i);
407 | 1362 |
                     uri    = elt.getNamespaceURI(prefix);
408 | 1362 |
                     addNamespaceForElement(elt, uri, prefix, nsMap);
409 |  |
                 }
410 | 822 |
                 parent = elt.getParent();
411 |  |
             }
412 | 312 |
             addNamespaceForElement(elt, "http://www.w3.org/XML/1998/namespace", "xml", nsMap);
413 |  |
414 | 312 |
             return nsMap.values().iterator();
415 |  |
         }
416 |  |
     }