comparison NGSrich_0.5.5/src/org/jdom/xpath/XPath.java @ 0:89ad0a9cca52 default tip

Uploaded
author pfrommolt
date Mon, 21 Nov 2011 08:12:19 -0500
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:89ad0a9cca52
1 /*--
2
3 $Id: XPath.java,v 1.17 2007/11/10 05:29:02 jhunter Exp $
4
5 Copyright (C) 2000-2007 Jason Hunter & Brett McLaughlin.
6 All rights reserved.
7
8 Redistribution and use in source and binary forms, with or without
9 modification, are permitted provided that the following conditions
10 are met:
11
12 1. Redistributions of source code must retain the above copyright
13 notice, this list of conditions, and the following disclaimer.
14
15 2. Redistributions in binary form must reproduce the above copyright
16 notice, this list of conditions, and the disclaimer that follows
17 these conditions in the documentation and/or other materials
18 provided with the distribution.
19
20 3. The name "JDOM" must not be used to endorse or promote products
21 derived from this software without prior written permission. For
22 written permission, please contact <request_AT_jdom_DOT_org>.
23
24 4. Products derived from this software may not be called "JDOM", nor
25 may "JDOM" appear in their name, without prior written permission
26 from the JDOM Project Management <request_AT_jdom_DOT_org>.
27
28 In addition, we request (but do not require) that you include in the
29 end-user documentation provided with the redistribution and/or in the
30 software itself an acknowledgement equivalent to the following:
31 "This product includes software developed by the
32 JDOM Project (http://www.jdom.org/)."
33 Alternatively, the acknowledgment may be graphical using the logos
34 available at http://www.jdom.org/images/logos.
35
36 THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
37 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39 DISCLAIMED. IN NO EVENT SHALL THE JDOM AUTHORS OR THE PROJECT
40 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
42 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
43 USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
44 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
45 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
46 OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
47 SUCH DAMAGE.
48
49 This software consists of voluntary contributions made by many
50 individuals on behalf of the JDOM Project and was originally
51 created by Jason Hunter <jhunter_AT_jdom_DOT_org> and
52 Brett McLaughlin <brett_AT_jdom_DOT_org>. For more information
53 on the JDOM Project, please see <http://www.jdom.org/>.
54
55 */
56
57 package org.jdom.xpath;
58
59
60 import java.io.*;
61 import java.lang.reflect.*;
62 import java.util.*;
63
64 import org.jdom.*;
65
66
67 /**
68 * A utility class for performing XPath calls on JDOM nodes, with a factory
69 * interface for obtaining a first XPath instance. Users operate against this
70 * class while XPath vendors can plug-in implementations underneath. Users
71 * can choose an implementation using either {@link #setXPathClass} or
72 * the system property "org.jdom.xpath.class".
73 *
74 * @version $Revision: 1.17 $, $Date: 2007/11/10 05:29:02 $
75 * @author Laurent Bihanic
76 */
77 public abstract class XPath implements Serializable {
78
79 private static final String CVS_ID =
80 "@(#) $RCSfile: XPath.java,v $ $Revision: 1.17 $ $Date: 2007/11/10 05:29:02 $ $Name: jdom_1_1_1 $";
81
82 /**
83 * The name of the system property from which to retrieve the
84 * name of the implementation class to use.
85 * <p>
86 * The property name is:
87 * "<code>org.jdom.xpath.class</code>".</p>
88 */
89 private final static String XPATH_CLASS_PROPERTY = "org.jdom.xpath.class";
90
91 /**
92 * The default implementation class to use if none was configured.
93 */
94 private final static String DEFAULT_XPATH_CLASS =
95 "org.jdom.xpath.JaxenXPath";
96
97 /**
98 * The string passable to the JAXP 1.3 XPathFactory isObjectModelSupported()
99 * method to query an XPath engine regarding its support for JDOM. Defined
100 * to be the well-known URI "http://jdom.org/jaxp/xpath/jdom".
101 */
102 public final static String JDOM_OBJECT_MODEL_URI =
103 "http://jdom.org/jaxp/xpath/jdom";
104
105 /**
106 * The constructor to instanciate a new XPath concrete
107 * implementation.
108 *
109 * @see #newInstance
110 */
111 private static Constructor constructor = null;
112
113 /**
114 * Creates a new XPath wrapper object, compiling the specified
115 * XPath expression.
116 *
117 * @param path the XPath expression to wrap.
118 *
119 * @throws JDOMException if the XPath expression is invalid.
120 */
121 public static XPath newInstance(String path) throws JDOMException {
122 try {
123 if (constructor == null) {
124 // First call => Determine implementation.
125 String className;
126 try {
127 className = System.getProperty(XPATH_CLASS_PROPERTY,
128 DEFAULT_XPATH_CLASS);
129 }
130 catch (SecurityException ex1) {
131 // Access to system property denied. => Use default impl.
132 className = DEFAULT_XPATH_CLASS;
133 }
134 setXPathClass(Class.forName(className));
135 }
136 // Allocate and return new implementation instance.
137 return (XPath)constructor.newInstance(new Object[] { path });
138 }
139 catch (JDOMException ex1) {
140 throw ex1;
141 }
142 catch (InvocationTargetException ex2) {
143 // Constructor threw an error on invocation.
144 Throwable t = ex2.getTargetException();
145
146 throw (t instanceof JDOMException)? (JDOMException)t:
147 new JDOMException(t.toString(), t);
148 }
149 catch (Exception ex3) {
150 // Any reflection error (probably due to a configuration mistake).
151 throw new JDOMException(ex3.toString(), ex3);
152 }
153 }
154
155 /**
156 * Sets the concrete XPath subclass to use when allocating XPath
157 * instances.
158 *
159 * @param aClass the concrete subclass of XPath.
160 *
161 * @throws IllegalArgumentException if <code>aClass</code> is
162 * <code>null</code>.
163 * @throws JDOMException if <code>aClass</code> is
164 * not a concrete subclass
165 * of XPath.
166 */
167 public static void setXPathClass(Class aClass) throws JDOMException {
168 if (aClass == null) {
169 throw new IllegalArgumentException("aClass");
170 }
171
172 try {
173 if ((XPath.class.isAssignableFrom(aClass)) &&
174 (Modifier.isAbstract(aClass.getModifiers()) == false)) {
175 // Concrete subclass of XPath => Get constructor
176 constructor = aClass.getConstructor(new Class[] { String.class });
177 }
178 else {
179 throw new JDOMException(aClass.getName() +
180 " is not a concrete JDOM XPath implementation");
181 }
182 }
183 catch (JDOMException ex1) {
184 throw ex1;
185 }
186 catch (Exception ex2) {
187 // Any reflection error (probably due to a configuration mistake).
188 throw new JDOMException(ex2.toString(), ex2);
189 }
190 }
191
192 /**
193 * Evaluates the wrapped XPath expression and returns the list
194 * of selected items.
195 *
196 * @param context the node to use as context for evaluating
197 * the XPath expression.
198 *
199 * @return the list of selected items, which may be of types: {@link Element},
200 * {@link Attribute}, {@link Text}, {@link CDATA},
201 * {@link Comment}, {@link ProcessingInstruction}, Boolean,
202 * Double, or String.
203 *
204 * @throws JDOMException if the evaluation of the XPath
205 * expression on the specified context
206 * failed.
207 */
208 abstract public List selectNodes(Object context) throws JDOMException;
209
210 /**
211 * Evaluates the wrapped XPath expression and returns the first
212 * entry in the list of selected nodes (or atomics).
213 *
214 * @param context the node to use as context for evaluating
215 * the XPath expression.
216 *
217 * @return the first selected item, which may be of types: {@link Element},
218 * {@link Attribute}, {@link Text}, {@link CDATA},
219 * {@link Comment}, {@link ProcessingInstruction}, Boolean,
220 * Double, String, or <code>null</code> if no item was selected.
221 *
222 * @throws JDOMException if the evaluation of the XPath
223 * expression on the specified context
224 * failed.
225 */
226 abstract public Object selectSingleNode(Object context) throws JDOMException;
227
228 /**
229 * Returns the string value of the first node selected by applying
230 * the wrapped XPath expression to the given context.
231 *
232 * @param context the element to use as context for evaluating
233 * the XPath expression.
234 *
235 * @return the string value of the first node selected by applying
236 * the wrapped XPath expression to the given context.
237 *
238 * @throws JDOMException if the XPath expression is invalid or
239 * its evaluation on the specified context
240 * failed.
241 */
242 abstract public String valueOf(Object context) throws JDOMException;
243
244 /**
245 * Returns the number value of the first node selected by applying
246 * the wrapped XPath expression to the given context.
247 *
248 * @param context the element to use as context for evaluating
249 * the XPath expression.
250 *
251 * @return the number value of the first node selected by applying
252 * the wrapped XPath expression to the given context,
253 * <code>null</code> if no node was selected or the
254 * special value {@link java.lang.Double#NaN}
255 * (Not-a-Number) if the selected value can not be
256 * converted into a number value.
257 *
258 * @throws JDOMException if the XPath expression is invalid or
259 * its evaluation on the specified context
260 * failed.
261 */
262 abstract public Number numberValueOf(Object context) throws JDOMException;
263
264 /**
265 * Defines an XPath variable and sets its value.
266 *
267 * @param name the variable name.
268 * @param value the variable value.
269 *
270 * @throws IllegalArgumentException if <code>name</code> is not
271 * a valid XPath variable name
272 * or if the value type is not
273 * supported by the underlying
274 * implementation
275 */
276 abstract public void setVariable(String name, Object value);
277
278 /**
279 * Adds a namespace definition to the list of namespaces known of
280 * this XPath expression.
281 * <p>
282 * <strong>Note</strong>: In XPath, there is no such thing as a
283 * 'default namespace'. The empty prefix <b>always</b> resolves
284 * to the empty namespace URI.</p>
285 *
286 * @param namespace the namespace.
287 */
288 abstract public void addNamespace(Namespace namespace);
289
290 /**
291 * Adds a namespace definition (prefix and URI) to the list of
292 * namespaces known of this XPath expression.
293 * <p>
294 * <strong>Note</strong>: In XPath, there is no such thing as a
295 * 'default namespace'. The empty prefix <b>always</b> resolves
296 * to the empty namespace URI.</p>
297 *
298 * @param prefix the namespace prefix.
299 * @param uri the namespace URI.
300 *
301 * @throws IllegalNameException if the prefix or uri are null or
302 * empty strings or if they contain
303 * illegal characters.
304 */
305 public void addNamespace(String prefix, String uri) {
306 addNamespace(Namespace.getNamespace(prefix, uri));
307 }
308
309 /**
310 * Returns the wrapped XPath expression as a string.
311 *
312 * @return the wrapped XPath expression as a string.
313 */
314 abstract public String getXPath();
315
316
317 /**
318 * Evaluates an XPath expression and returns the list of selected
319 * items.
320 * <p>
321 * <strong>Note</strong>: This method should not be used when the
322 * same XPath expression needs to be applied several times (on the
323 * same or different contexts) as it requires the expression to be
324 * compiled before being evaluated. In such cases,
325 * {@link #newInstance allocating} an XPath wrapper instance and
326 * {@link #selectNodes(java.lang.Object) evaluating} it several
327 * times is way more efficient.
328 * </p>
329 *
330 * @param context the node to use as context for evaluating
331 * the XPath expression.
332 * @param path the XPath expression to evaluate.
333 *
334 * @return the list of selected items, which may be of types: {@link Element},
335 * {@link Attribute}, {@link Text}, {@link CDATA},
336 * {@link Comment}, {@link ProcessingInstruction}, Boolean,
337 * Double, or String.
338 *
339 * @throws JDOMException if the XPath expression is invalid or
340 * its evaluation on the specified context
341 * failed.
342 */
343 public static List selectNodes(Object context, String path)
344 throws JDOMException {
345 return newInstance(path).selectNodes(context);
346 }
347
348 /**
349 * Evaluates the wrapped XPath expression and returns the first
350 * entry in the list of selected nodes (or atomics).
351 * <p>
352 * <strong>Note</strong>: This method should not be used when the
353 * same XPath expression needs to be applied several times (on the
354 * same or different contexts) as it requires the expression to be
355 * compiled before being evaluated. In such cases,
356 * {@link #newInstance allocating} an XPath wrapper instance and
357 * {@link #selectSingleNode(java.lang.Object) evaluating} it
358 * several times is way more efficient.
359 * </p>
360 *
361 * @param context the element to use as context for evaluating
362 * the XPath expression.
363 * @param path the XPath expression to evaluate.
364 *
365 * @return the first selected item, which may be of types: {@link Element},
366 * {@link Attribute}, {@link Text}, {@link CDATA},
367 * {@link Comment}, {@link ProcessingInstruction}, Boolean,
368 * Double, String, or <code>null</code> if no item was selected.
369 *
370 * @throws JDOMException if the XPath expression is invalid or
371 * its evaluation on the specified context
372 * failed.
373 */
374 public static Object selectSingleNode(Object context, String path)
375 throws JDOMException {
376 return newInstance(path).selectSingleNode(context);
377 }
378
379
380 //-------------------------------------------------------------------------
381 // Serialization support
382 //-------------------------------------------------------------------------
383
384 /**
385 * <i>[Serialization support]</i> Returns the alternative object
386 * to write to the stream when serializing this object. This
387 * method returns an instance of a dedicated nested class to
388 * serialize XPath expressions independently of the concrete
389 * implementation being used.
390 * <p>
391 * <strong>Note</strong>: Subclasses are not allowed to override
392 * this method to ensure valid serialization of all
393 * implementations.</p>
394 *
395 * @return an XPathString instance configured with the wrapped
396 * XPath expression.
397 *
398 * @throws ObjectStreamException never.
399 */
400 protected final Object writeReplace() throws ObjectStreamException {
401 return new XPathString(this.getXPath());
402 }
403
404 /**
405 * The XPathString is dedicated to serialize instances of
406 * XPath subclasses in a implementation-independent manner.
407 * <p>
408 * XPathString ensures that only string data are serialized. Upon
409 * deserialization, XPathString relies on XPath factory method to
410 * to create instances of the concrete XPath wrapper currently
411 * configured.</p>
412 */
413 private final static class XPathString implements Serializable {
414 /**
415 * The XPath expression as a string.
416 */
417 private String xPath = null;
418
419 /**
420 * Creates a new XPathString instance from the specified
421 * XPath expression.
422 *
423 * @param xpath the XPath expression.
424 */
425 public XPathString(String xpath) {
426 super();
427
428 this.xPath = xpath;
429 }
430
431 /**
432 * <i>[Serialization support]</i> Resolves the read XPathString
433 * objects into XPath implementations.
434 *
435 * @return an instance of a concrete implementation of
436 * XPath.
437 *
438 * @throws ObjectStreamException if no XPath could be built
439 * from the read object.
440 */
441 private Object readResolve() throws ObjectStreamException {
442 try {
443 return XPath.newInstance(this.xPath);
444 }
445 catch (JDOMException ex1) {
446 throw new InvalidObjectException(
447 "Can't create XPath object for expression \"" +
448 this.xPath + "\": " + ex1.toString());
449 }
450 }
451 }
452 }
453