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