KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > caucho > xpath > XPath


1 /*
2  * Copyright (c) 1998-2006 Caucho Technology -- all rights reserved
3  *
4  * This file is part of Resin(R) Open Source
5  *
6  * Each copy or derived work must preserve the copyright notice and this
7  * notice unmodified.
8  *
9  * Resin Open Source is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * Resin Open Source is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
17  * of NON-INFRINGEMENT. See the GNU General Public License for more
18  * details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with Resin Open Source; if not, write to the
22  * Free SoftwareFoundation, Inc.
23  * 59 Temple Place, Suite 330
24  * Boston, MA 02111-1307 USA
25  *
26  * @author Scott Ferguson
27  */

28
29 package com.caucho.xpath;
30
31 import com.caucho.loader.EnvironmentLocal;
32 import com.caucho.log.Log;
33 import com.caucho.util.LruCache;
34 import com.caucho.xpath.pattern.AbstractPattern;
35 import com.caucho.xpath.pattern.FromContext;
36
37 import org.w3c.dom.Node JavaDoc;
38
39 import java.util.Iterator JavaDoc;
40 import java.util.logging.Level JavaDoc;
41 import java.util.logging.Logger JavaDoc;
42
43 /**
44  * Public facade for selecting nodes and creating match patterns.
45  *
46  * <p>Applications can select nodes directly from the XPath facade.
47  * For example,
48  * <code><pre>
49  * Node verse = XPath.find("chapter/verse", node);
50  * </pre></code>
51  *
52  * <p>For greater efficiency, applications can also precompile the
53  * match patterns.
54  * <code><pre>
55  * Pattern pattern = XPath.parseSelect("chapter/verse");
56  * Node verse = pattern.find(node);
57  * </pre></code>
58  *
59  * <p>XPath can also return values based on XPath expressions, following
60  * the XPath expression syntax. Applications can use the expressions for
61  * the equivalent of xsl:value-of
62  * <code><pre>
63  * Expr expr = XPath.parseExpr("chapter/verse/@id + 1");
64  * double value = expr.evalNumber(node);
65  * </pre></code>
66  *
67  * <p>To support the XPath pattern variables, XPath uses an environment
68  * object. Most applications will not need to use it.
69  */

70 public class XPath {
71   private static final Logger JavaDoc log = Log.open(XPath.class);
72
73   private static EnvironmentLocal<LruCache<String JavaDoc,Pattern>> _matchCache =
74     new EnvironmentLocal<LruCache<String JavaDoc,Pattern>>();
75   
76   private static EnvironmentLocal<LruCache<String JavaDoc,Pattern>> _selectCache =
77     new EnvironmentLocal<LruCache<String JavaDoc,Pattern>>();
78   
79   private static EnvironmentLocal<LruCache<String JavaDoc,Expr>> _exprCache =
80     new EnvironmentLocal<LruCache<String JavaDoc,Expr>>();
81
82   private XPath()
83   {
84   }
85
86   /**
87    * Finds a node based on an XPath pattern. The pattern is relative
88    * to the node so <code>XPath.find("child", node)</code> will find children,
89    * not grandchildren.
90    *
91    * @param query XPath select pattern.
92    * @param node XML node to start searching from.
93    * @return The first matching node in document order.
94    */

95   public static Node JavaDoc find(String JavaDoc query, Node JavaDoc node)
96     throws XPathException
97   {
98     Pattern pattern = parseSelect(query);
99
100     return (Node JavaDoc) pattern.find(node);
101   }
102
103   /**
104    * Selects all node matching an XPath pattern
105    *
106    * @param query XPath select pattern.
107    * @param node XML node to start searching from.
108    * @return An iterator of nodes matching the pattern.
109    */

110   public static Iterator JavaDoc select(String JavaDoc query, Node JavaDoc node)
111     throws XPathException
112   {
113     Pattern pattern = parseSelect(query);
114
115     return pattern.select(node);
116   }
117
118   /**
119    * Create a node selection pattern. The pattern matches relative
120    * to the current node.
121    *
122    * @param query XPath select pattern.
123    * @return a pattern that can later select nodes.
124    */

125   public static Pattern parseSelect(String JavaDoc query)
126     throws XPathParseException
127   {
128     LruCache<String JavaDoc,Pattern> cache = _selectCache.get();
129     if (cache == null)
130       cache = new LruCache<String JavaDoc,Pattern>(128);
131     
132     Pattern pattern = cache.get(query);
133
134     if (pattern == null) {
135       pattern = parseSelect(query, null);
136       cache.put(query, pattern);
137     }
138
139     return pattern;
140   }
141
142   /**
143    * Create a node selection pattern. The pattern matches relative
144    * to the current node.
145    *
146    * <p>XSLT uses this version of parseSelect for proper namespace
147    * matching.
148    *
149    * @param query XPath select pattern.
150    * @param namespace the appropriate namespace mappings
151    *
152    * @return a pattern that can later select nodes.
153    */

154   public static Pattern parseSelect(String JavaDoc query, NamespaceContext namespace)
155     throws XPathParseException
156   {
157     XPathParser parser = new XPathParser(query, namespace);
158
159     AbstractPattern pattern = parser.parseSelect();
160
161     if (log.isLoggable(Level.FINER))
162       log.finest("select: " + pattern);
163
164     return new Pattern(pattern);
165   }
166
167   /**
168    * Create a node match pattern. Match patterns are intended to test
169    * if a node matches the pattern. They do not work well for finding or
170    * selecting patterns. Essentially, a match pattern of 'foo[@bar]' is
171    * equivalent to a select pattern of '//foo[@bar]', but with less overhead.
172    *
173    * @param query XPath match pattern.
174    * @return a pattern that can later be used for isMatch.
175    */

176   public static Pattern parseMatch(String JavaDoc query)
177     throws XPathParseException
178   {
179     LruCache<String JavaDoc,Pattern> cache = _matchCache.get();
180     if (cache == null)
181       cache = new LruCache<String JavaDoc,Pattern>(128);
182     
183     Pattern pattern = cache.get(query);
184
185     if (pattern == null) {
186       pattern = parseMatch(query, null);
187       cache.put(query, pattern);
188     }
189
190     return pattern;
191   }
192
193   /**
194    * Create a node match pattern. Match patterns are intended to test
195    * if a node matches the pattern. They do not work well for finding or
196    * selecting patterns. Essentially, a match pattern of 'foo[@bar]' is
197    * equivalent to a select pattern of '//foo[@bar]', but with less overhead.
198    *
199    * @param query XPath match pattern.
200    * @param namespace the appropriate namespace mappings.
201    *
202    * @return a pattern that can later be used for isMatch.
203    */

204   public static Pattern parseMatch(String JavaDoc query, NamespaceContext namespace)
205     throws XPathParseException
206   {
207     XPathParser parser = new XPathParser(query, namespace);
208
209     AbstractPattern pattern = parser.parseMatch();
210
211     if (log.isLoggable(Level.FINER))
212       log.finest("match: " + pattern);
213
214     return new Pattern(pattern);
215   }
216
217   /**
218    * Evaluates an XPath expression, returning a string. evalString works
219    * like the XSL <code>value-of</code> element.
220    *
221    * <p>For example, to get the value of an attribute use:
222    *
223    * <code><pre>
224    * String value = XPath.evalString("@id", node);
225    * </pre></code>
226    *
227    * @param query XPath expression
228    * @param node the node context
229    *
230    * @return the string result of the expression.
231    */

232   public static String JavaDoc evalString(String JavaDoc query, Node JavaDoc node)
233     throws XPathException
234   {
235     Expr expr = parseExpr(query);
236
237     return expr.evalString(node);
238   }
239
240   /**
241    * Evaluates an XPath expression, returning a double.
242    *
243    * @param query XPath expression
244    * @param node the node context
245    *
246    * @return the number result of the expression.
247    */

248   public static double evalNumber(String JavaDoc query, Node JavaDoc node)
249     throws XPathException
250   {
251     Expr expr = parseExpr(query);
252
253     return expr.evalNumber(node);
254   }
255
256   /**
257    * Evaluates an XPath expression, returning a boolean.
258    *
259    * @param query XPath expression
260    * @param node the node context
261    *
262    * @return the boolean result of the expression.
263    */

264   public static boolean evalBoolean(String JavaDoc query, Node JavaDoc node)
265     throws XPathException
266   {
267     Expr expr = parseExpr(query);
268
269     return expr.evalBoolean(node);
270   }
271
272   /**
273    * Evaluates an XPath expression, returning an object
274    *
275    * @param query XPath expression
276    * @param node the node context
277    *
278    * @return the result of the expression.
279    */

280   public static Object JavaDoc evalObject(String JavaDoc query, Node JavaDoc node)
281     throws XPathException
282   {
283     Expr expr = parseExpr(query);
284
285     return expr.evalObject(node);
286   }
287
288   /**
289    * Parses an XPath expression for later evaluation.
290    *
291    * @param query XPath expression
292    * @return the result of the expression.
293    */

294   public static Expr parseExpr(String JavaDoc query)
295     throws XPathParseException
296   {
297     LruCache<String JavaDoc,Expr> cache = _exprCache.get();
298     if (cache == null)
299       cache = new LruCache<String JavaDoc,Expr>(128);
300     
301     Expr expr = cache.get(query);
302
303     if (expr == null) {
304       expr = parseExpr(query, null);
305       cache.put(query, expr);
306     }
307
308     return expr;
309   }
310
311   /**
312    * Parses an XPath expression for later evaluation.
313    *
314    * @param query XPath expression
315    * @param namespace namespace context
316    *
317    * @return the compiled expression
318    */

319   public static Expr parseExpr(String JavaDoc query, NamespaceContext namespace)
320     throws XPathParseException
321   {
322     XPathParser parser = new XPathParser(query, namespace);
323
324     Expr expr = parser.parseExpr();
325
326     if (log.isLoggable(Level.FINER))
327       log.finest("expr: " + expr);
328
329     return expr;
330   }
331
332   /**
333    * Parses an XPath expression for later evaluation.
334    *
335    * @param query XPath expression
336    * @param namespace namespace context
337    * @param nodeList containing nodeList pattern
338    *
339    * @return the compiled expression
340    */

341   public static Expr parseExpr(String JavaDoc query, NamespaceContext namespace,
342                    AbstractPattern nodeList)
343     throws XPathParseException
344   {
345     XPathParser parser = new XPathParser(query, namespace);
346
347     Expr expr = parser.parseExpr(new FromContext(), nodeList);
348
349     if (expr != null)
350       expr.setListContext(nodeList);
351
352     if (log.isLoggable(Level.FINER))
353       log.finest("expr: " + expr);
354
355     return expr;
356   }
357
358   /**
359    * Creates a new variable environment.
360    */

361   public static Env createEnv()
362   {
363     return Env.create();
364   }
365
366   /**
367    * Creates a new variable environment based on an old environment.
368    *
369    * <p>This lets environments share globals even through function calls.
370    */

371   public static Env createEnv(Env global)
372   {
373     Env env = Env.create();
374
375     env.init(global);
376
377     return env;
378   }
379
380   /**
381    * Creates a new variable environment based on an old environment.
382    *
383    * <p>This lets environments share globals even through function calls.
384    */

385   public static Env createCall(Env parent)
386   {
387     Env env = Env.create();
388
389     env.initMacro(parent);
390
391     return env;
392   }
393
394   /**
395    * Free an environment.
396    */

397   public static void freeEnv(Env env)
398   {
399     // env.free();
400
}
401 }
402
Popular Tags