View Javadoc

1   /*
2    $Id: DocumentNavigator.java,v 1.5 2005/01/30 03:09:56 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 class Singleton
87      {
88          /*** Singleton instance.
89           */
90          private static DocumentNavigator instance = new DocumentNavigator();
91      }
92  
93      /*** Retrieve the singleton instance of this <code>DocumentNavigator</code>.
94       */
95      public static Navigator getInstance()
96      {
97          return Singleton.instance;
98      }
99  
100     public boolean isElement(Object obj)
101     {
102         return (obj instanceof Element);
103     }
104 
105     public boolean isComment(Object obj)
106     {
107         return false;
108     }
109 
110     public boolean isText(Object obj)
111     {
112         return ( obj instanceof String );
113     }
114 
115     public boolean isAttribute(Object obj)
116     {
117         return false;
118     }
119 
120     public boolean isProcessingInstruction(Object obj)
121     {
122         return false;
123     }
124 
125     public boolean isDocument(Object obj)
126     {
127         return false;
128     }
129 
130     public boolean isNamespace(Object obj)
131     {
132         return false;
133     }
134 
135     public String getElementName(Object obj)
136     {
137         return ((Element)obj).getName();
138     }
139 
140     public String getElementNamespaceUri(Object obj)
141     {
142         return "";
143     }
144 
145     public String getElementQName(Object obj)
146     {
147         return "";
148     }
149 
150     public String getAttributeName(Object obj)
151     {
152         return "";
153     }
154 
155     public String getAttributeNamespaceUri(Object obj)
156     {
157         return "";
158     }
159 
160     public String getAttributeQName(Object obj)
161     {
162         return "";
163     }
164 
165     public Iterator getChildAxisIterator(Object contextNode)
166     {
167         return JaxenConstants.EMPTY_ITERATOR;
168     }
169 
170     /***
171      * Retrieves an <code>Iterator</code> over the child elements that
172      * match the supplied name.
173      *
174      * @param contextNode  the origin context node
175      * @param localName  the local name of the children to return, always present
176      * @param namespacePrefix  the prefix of the namespace of the children to return
177      * @param namespaceURI  the uri of the namespace of the children to return
178      * @return an Iterator that traverses the named children, or null if none
179      */
180     public Iterator getChildAxisIterator(Object contextNode,
181                                          String localName,
182                                          String namespacePrefix,
183                                          String namespaceURI)
184     {
185         Class cls = ((Element)contextNode).getObject().getClass();
186 
187         String methodName = javacase( localName );
188 
189         Method method = null;
190         
191         try
192         {
193             method = cls.getMethod( "get" + methodName, EMPTY_CLASS_ARRAY );
194         }
195         catch (NoSuchMethodException e)
196         {
197             try
198             {
199                 method = cls.getMethod( "get" + methodName + "s", EMPTY_CLASS_ARRAY );
200             }
201             catch (NoSuchMethodException ee)
202             {
203                 try
204                 {
205                     method = cls.getMethod( localName, EMPTY_CLASS_ARRAY );
206                 }
207                 catch (NoSuchMethodException eee)
208                 {
209                     method = null;
210                 }
211             }
212         }
213 
214         if ( method == null )
215         {
216             return JaxenConstants.EMPTY_ITERATOR;
217         }
218 
219         try
220         {
221             Object result = method.invoke( ((Element)contextNode).getObject(), EMPTY_OBJECT_ARRAY );
222             
223             if ( result == null )
224             {
225                 return JaxenConstants.EMPTY_ITERATOR;
226             } 
227             
228             if ( result instanceof Collection )
229             {
230                 return new ElementIterator( (Element) contextNode, localName, ((Collection)result).iterator() );
231             }
232             
233             if ( result.getClass().isArray() )
234             {
235                 return JaxenConstants.EMPTY_ITERATOR;
236             }
237             
238             return new SingleObjectIterator( new Element( (Element) contextNode, localName, result ) );
239         }
240         catch (IllegalAccessException e)
241         {
242             // swallow
243         }
244         catch (InvocationTargetException e)
245         {
246             // swallow
247         }
248 
249         return JaxenConstants.EMPTY_ITERATOR;
250     }
251 
252     public Iterator getParentAxisIterator(Object contextNode)
253     {
254         if ( contextNode instanceof Element )
255         {
256             return new SingleObjectIterator( ((Element)contextNode).getParent() );
257         }
258 
259         return JaxenConstants.EMPTY_ITERATOR;
260     }
261 
262     public Iterator getAttributeAxisIterator(Object contextNode)
263     {
264         return JaxenConstants.EMPTY_ITERATOR;
265     }
266 
267     /***
268      * Retrieves an <code>Iterator</code> over the attribute elements that
269      * match the supplied name.
270      *
271      * @param contextNode  the origin context node
272      * @param localName  the local name of the attributes to return, always present
273      * @param namespacePrefix  the prefix of the namespace of the attributes to return
274      * @param namespaceURI  the uri of the namespace of the attributes to return
275      * @return an Iterator that traverses the named attributes, not null
276      */
277     public Iterator getAttributeAxisIterator(Object contextNode,
278                                              String localName,
279                                              String namespacePrefix,
280                                              String namespaceURI) {
281         return JaxenConstants.EMPTY_ITERATOR;
282     }
283         
284     public Iterator getNamespaceAxisIterator(Object contextNode)
285     {
286         return JaxenConstants.EMPTY_ITERATOR;
287     }
288 
289     public Object getDocumentNode(Object contextNode)
290     {
291         return null;
292     }
293 
294     public Object getParentNode(Object contextNode)
295     {
296         if ( contextNode instanceof Element )
297         {
298             return ((Element)contextNode).getParent();
299         }
300 
301         return JaxenConstants.EMPTY_ITERATOR;
302     }
303 
304     public String getTextStringValue(Object obj)
305     {
306         if ( obj instanceof Element )
307         {
308             return ((Element)obj).getObject().toString();
309         }
310         return obj.toString();
311     }
312 
313     public String getElementStringValue(Object obj)
314     {
315         if ( obj instanceof Element )
316         {
317             return ((Element)obj).getObject().toString();
318         }
319         return obj.toString();
320     }
321 
322     public String getAttributeStringValue(Object obj)
323     {
324         return obj.toString();
325     }
326 
327     public String getNamespaceStringValue(Object obj)
328     {
329         return obj.toString();
330     }
331 
332     public String getNamespacePrefix(Object obj)
333     {
334         return null;
335     }
336 
337     public String getCommentStringValue(Object obj)
338     {
339         return null;
340     }
341     
342     public String translateNamespacePrefixToUri(String prefix, Object context)
343     {
344         return null;
345     }
346     
347     public short getNodeType(Object node) 
348     {
349         return 0;
350     }
351     
352     public Object getDocument(String uri) throws FunctionCallException
353     {
354         return null;
355     }
356 
357     public String getProcessingInstructionTarget(Object obj)
358     {
359         return null;
360     }
361 
362     public String getProcessingInstructionData(Object obj)
363     {
364         return null;
365     }
366 
367     public XPath parseXPath(String xpath)
368         throws org.jaxen.saxpath.SAXPathException
369     {
370         return new JavaBeanXPath( xpath );
371     }
372 
373     protected String javacase(String name)
374     {
375         if ( name.length() == 0 )
376         {
377             return name;
378         }
379         else if ( name.length() == 1 )
380         {
381             return name.toUpperCase();
382         } 
383 
384         return name.substring( 0, 1 ).toUpperCase() + name.substring( 1 );
385     }
386 }