View Javadoc

1   /*
2    $Id: DocumentNavigator.java,v 1.6 2005/04/20 22:41:38 elharo Exp $
3   
4    Copyright 2003 (C) The Werken Company. All Rights Reserved.
5    
6    Redistribution and use of this software and associated documentation
7    ("Software"), with or without modification, are permitted provided
8    that the following conditions are met:
9   
10   1. Redistributions of source code must retain copyright
11      statements and notices.  Redistributions must also contain a
12      copy of this document.
13   
14   2. Redistributions in binary form must reproduce the
15      above copyright notice, this list of conditions and the
16      following disclaimer in the documentation and/or other
17      materials provided with the distribution.
18   
19   3. The name "jaxen" must not be used to endorse or promote
20      products derived from this Software without prior written
21      permission of The Werken Company.  For written permission,
22      please contact bob@werken.com.
23   
24   4. Products derived from this Software may not be called "jaxen"
25      nor may "jaxen" appear in their names without prior written
26      permission of The Werken Company. "jaxen" is a registered
27      trademark of The Werken Company.
28   
29   5. Due credit should be given to The Werken Company.
30      (http://jaxen.werken.com/).
31   
32   THIS SOFTWARE IS PROVIDED BY THE WERKEN COMPANY AND CONTRIBUTORS
33   ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
34   NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
35   FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
36   THE WERKEN COMPANY OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
37   INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
38   (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
39   SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
40   HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
41   STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
42   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
43   OF THE POSSIBILITY OF SUCH DAMAGE.
44  
45   */
46  package org.jaxen.javabean;
47  
48  import java.lang.reflect.Method;
49  import java.lang.reflect.InvocationTargetException;
50  import java.util.Iterator;
51  import java.util.Collection;
52  
53  import org.jaxen.DefaultNavigator;
54  import org.jaxen.FunctionCallException;
55  import org.jaxen.NamedAccessNavigator;
56  import org.jaxen.Navigator;
57  import org.jaxen.XPath;
58  import org.jaxen.JaxenConstants;
59  import org.jaxen.util.SingleObjectIterator;
60  
61  /*** 
62   * Interface for navigating around a JavaBean object model.
63   *
64   * <p>
65   * This class is not intended for direct usage, but is
66   * used by the Jaxen engine during evaluation.
67   * </p>
68   *
69   * @see XPath
70   *
71   * @author <a href="mailto:bob@werken.com">bob mcwhirter</a>
72   */
73  public class DocumentNavigator
74      extends DefaultNavigator
75      implements NamedAccessNavigator
76  {
77  
78      /*** Empty Class array. */
79      private static final Class[] EMPTY_CLASS_ARRAY = new Class[0];
80  
81      /*** Empty Object array. */
82      private static final Object[] EMPTY_OBJECT_ARRAY = new Object[0];
83  
84      /*** Singleton implementation.
85       */
86      private static final DocumentNavigator instance = new DocumentNavigator();
87  
88      /*** Retrieve the singleton instance of this <code>DocumentNavigator</code>.
89       */
90      public static Navigator getInstance()
91      {
92          return instance;
93      }
94  
95      public boolean isElement(Object obj)
96      {
97          return (obj instanceof Element);
98      }
99  
100     public boolean isComment(Object obj)
101     {
102         return false;
103     }
104 
105     public boolean isText(Object obj)
106     {
107         return ( obj instanceof String );
108     }
109 
110     public boolean isAttribute(Object obj)
111     {
112         return false;
113     }
114 
115     public boolean isProcessingInstruction(Object obj)
116     {
117         return false;
118     }
119 
120     public boolean isDocument(Object obj)
121     {
122         return false;
123     }
124 
125     public boolean isNamespace(Object obj)
126     {
127         return false;
128     }
129 
130     public String getElementName(Object obj)
131     {
132         return ((Element)obj).getName();
133     }
134 
135     public String getElementNamespaceUri(Object obj)
136     {
137         return "";
138     }
139 
140     public String getElementQName(Object obj)
141     {
142         return "";
143     }
144 
145     public String getAttributeName(Object obj)
146     {
147         return "";
148     }
149 
150     public String getAttributeNamespaceUri(Object obj)
151     {
152         return "";
153     }
154 
155     public String getAttributeQName(Object obj)
156     {
157         return "";
158     }
159 
160     public Iterator getChildAxisIterator(Object contextNode)
161     {
162         return JaxenConstants.EMPTY_ITERATOR;
163     }
164 
165     /***
166      * Retrieves an <code>Iterator</code> over the child elements that
167      * match the supplied name.
168      *
169      * @param contextNode  the origin context node
170      * @param localName  the local name of the children to return, always present
171      * @param namespacePrefix  the prefix of the namespace of the children to return
172      * @param namespaceURI  the namespace URI of the children to return
173      * @return an Iterator that traverses the named children, or null if none
174      */
175     public Iterator getChildAxisIterator(Object contextNode,
176                                          String localName,
177                                          String namespacePrefix,
178                                          String namespaceURI)
179     {
180         Class cls = ((Element)contextNode).getObject().getClass();
181 
182         String methodName = javacase( localName );
183 
184         Method method = null;
185         
186         try
187         {
188             method = cls.getMethod( "get" + methodName, EMPTY_CLASS_ARRAY );
189         }
190         catch (NoSuchMethodException e)
191         {
192             try
193             {
194                 method = cls.getMethod( "get" + methodName + "s", EMPTY_CLASS_ARRAY );
195             }
196             catch (NoSuchMethodException ee)
197             {
198                 try
199                 {
200                     method = cls.getMethod( localName, EMPTY_CLASS_ARRAY );
201                 }
202                 catch (NoSuchMethodException eee)
203                 {
204                     method = null;
205                 }
206             }
207         }
208 
209         if ( method == null )
210         {
211             return JaxenConstants.EMPTY_ITERATOR;
212         }
213 
214         try
215         {
216             Object result = method.invoke( ((Element)contextNode).getObject(), EMPTY_OBJECT_ARRAY );
217             
218             if ( result == null )
219             {
220                 return JaxenConstants.EMPTY_ITERATOR;
221             } 
222             
223             if ( result instanceof Collection )
224             {
225                 return new ElementIterator( (Element) contextNode, localName, ((Collection)result).iterator() );
226             }
227             
228             if ( result.getClass().isArray() )
229             {
230                 return JaxenConstants.EMPTY_ITERATOR;
231             }
232             
233             return new SingleObjectIterator( new Element( (Element) contextNode, localName, result ) );
234         }
235         catch (IllegalAccessException e)
236         {
237             // swallow
238         }
239         catch (InvocationTargetException e)
240         {
241             // swallow
242         }
243 
244         return JaxenConstants.EMPTY_ITERATOR;
245     }
246 
247     public Iterator getParentAxisIterator(Object contextNode)
248     {
249         if ( contextNode instanceof Element )
250         {
251             return new SingleObjectIterator( ((Element)contextNode).getParent() );
252         }
253 
254         return JaxenConstants.EMPTY_ITERATOR;
255     }
256 
257     public Iterator getAttributeAxisIterator(Object contextNode)
258     {
259         return JaxenConstants.EMPTY_ITERATOR;
260     }
261 
262     /***
263      * Retrieves an <code>Iterator</code> over the attribute elements that
264      * match the supplied name.
265      *
266      * @param contextNode  the origin context node
267      * @param localName  the local name of the attributes to return, always present
268      * @param namespacePrefix  the prefix of the namespace of the attributes to return
269      * @param namespaceURI  the namespace URI of the attributes to return
270      * @return an Iterator that traverses the named attributes, not null
271      */
272     public Iterator getAttributeAxisIterator(Object contextNode,
273                                              String localName,
274                                              String namespacePrefix,
275                                              String namespaceURI) {
276         return JaxenConstants.EMPTY_ITERATOR;
277     }
278         
279     public Iterator getNamespaceAxisIterator(Object contextNode)
280     {
281         return JaxenConstants.EMPTY_ITERATOR;
282     }
283 
284     public Object getDocumentNode(Object contextNode)
285     {
286         return null;
287     }
288 
289     public Object getParentNode(Object contextNode)
290     {
291         if ( contextNode instanceof Element )
292         {
293             return ((Element)contextNode).getParent();
294         }
295 
296         return JaxenConstants.EMPTY_ITERATOR;
297     }
298 
299     public String getTextStringValue(Object obj)
300     {
301         if ( obj instanceof Element )
302         {
303             return ((Element)obj).getObject().toString();
304         }
305         return obj.toString();
306     }
307 
308     public String getElementStringValue(Object obj)
309     {
310         if ( obj instanceof Element )
311         {
312             return ((Element)obj).getObject().toString();
313         }
314         return obj.toString();
315     }
316 
317     public String getAttributeStringValue(Object obj)
318     {
319         return obj.toString();
320     }
321 
322     public String getNamespaceStringValue(Object obj)
323     {
324         return obj.toString();
325     }
326 
327     public String getNamespacePrefix(Object obj)
328     {
329         return null;
330     }
331 
332     public String getCommentStringValue(Object obj)
333     {
334         return null;
335     }
336     
337     public String translateNamespacePrefixToUri(String prefix, Object context)
338     {
339         return null;
340     }
341     
342     public short getNodeType(Object node) 
343     {
344         return 0;
345     }
346     
347     public Object getDocument(String uri) throws FunctionCallException
348     {
349         return null;
350     }
351 
352     public String getProcessingInstructionTarget(Object obj)
353     {
354         return null;
355     }
356 
357     public String getProcessingInstructionData(Object obj)
358     {
359         return null;
360     }
361 
362     public XPath parseXPath(String xpath)
363         throws org.jaxen.saxpath.SAXPathException
364     {
365         return new JavaBeanXPath( xpath );
366     }
367 
368     protected String javacase(String name)
369     {
370         if ( name.length() == 0 )
371         {
372             return name;
373         }
374         else if ( name.length() == 1 )
375         {
376             return name.toUpperCase();
377         } 
378 
379         return name.substring( 0, 1 ).toUpperCase() + name.substring( 1 );
380     }
381 }