View Javadoc

1   /*
2    * $Header: /home/projects/jaxen/scm/jaxen/src/java/main/org/jaxen/pattern/PatternParser.java,v 1.14 2003/06/29 18:01:52 ssanders Exp $
3    * $Revision: 1.14 $
4    * $Date: 2003/06/29 18:01:52 $
5    *
6    * ====================================================================
7    *
8    * Copyright (C) 2000-2002 bob mcwhirter & James Strachan.
9    * All rights reserved.
10   *
11   * Redistribution and use in source and binary forms, with or without
12   * modification, are permitted provided that the following conditions
13   * are met:
14   * 
15   * 1. Redistributions of source code must retain the above copyright
16   *    notice, this list of conditions, and the following disclaimer.
17   *
18   * 2. Redistributions in binary form must reproduce the above copyright
19   *    notice, this list of conditions, and the disclaimer that follows 
20   *    these conditions in the documentation and/or other materials 
21   *    provided with the distribution.
22   *
23   * 3. The name "Jaxen" must not be used to endorse or promote products
24   *    derived from this software without prior written permission.  For
25   *    written permission, please contact license@jaxen.org.
26   * 
27   * 4. Products derived from this software may not be called "Jaxen", nor
28   *    may "Jaxen" appear in their name, without prior written permission
29   *    from the Jaxen Project Management (pm@jaxen.org).
30   * 
31   * In addition, we request (but do not require) that you include in the 
32   * end-user documentation provided with the redistribution and/or in the 
33   * software itself an acknowledgement equivalent to the following:
34   *     "This product includes software developed by the
35   *      Jaxen Project (http://www.jaxen.org/)."
36   * Alternatively, the acknowledgment may be graphical using the logos 
37   * available at http://www.jaxen.org/
38   *
39   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
40   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
41   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
42   * DISCLAIMED.  IN NO EVENT SHALL THE Jaxen AUTHORS OR THE PROJECT
43   * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
45   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
46   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
47   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
48   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
49   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
50   * SUCH DAMAGE.
51   *
52   * ====================================================================
53   * This software consists of voluntary contributions made by many 
54   * individuals on behalf of the Jaxen Project and was originally 
55   * created by bob mcwhirter <bob@werken.com> and 
56   * James Strachan <jstrachan@apache.org>.  For more information on the 
57   * Jaxen Project, please see <http://www.jaxen.org/>.
58   * 
59   * $Id: PatternParser.java,v 1.14 2003/06/29 18:01:52 ssanders Exp $
60   */
61  
62  
63  package org.jaxen.pattern;
64  
65  import java.util.Iterator;
66  import java.util.List;
67  import java.util.ListIterator;
68  
69  import org.jaxen.JaxenException;
70  import org.jaxen.JaxenHandler;
71  import org.jaxen.expr.DefaultAllNodeStep;
72  import org.jaxen.expr.DefaultCommentNodeStep;
73  import org.jaxen.expr.DefaultFilterExpr;
74  import org.jaxen.expr.DefaultNameStep;
75  import org.jaxen.expr.DefaultProcessingInstructionNodeStep;
76  import org.jaxen.expr.DefaultStep;
77  import org.jaxen.expr.DefaultTextNodeStep;
78  import org.jaxen.expr.DefaultXPathFactory;
79  import org.jaxen.expr.Expr;
80  import org.jaxen.expr.FilterExpr;
81  import org.jaxen.expr.LocationPath;
82  import org.jaxen.expr.Predicate;
83  import org.jaxen.expr.PredicateSet;
84  import org.jaxen.expr.Step;
85  import org.jaxen.expr.UnionExpr;
86  import org.jaxen.saxpath.Axis;
87  import org.jaxen.saxpath.XPathReader;
88  import org.jaxen.saxpath.helpers.XPathReaderFactory;
89  
90  
91  /*** <code>PatternParser</code> is a helper class for parsing
92    * XSLT patterns
93    *
94    * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
95    */
96  public class PatternParser 
97  {
98      private static final boolean TRACE = false;
99  
100     private static final boolean USE_HANDLER = false;
101 
102     public static Pattern parse(String text) throws JaxenException, org.jaxen.saxpath.SAXPathException
103 
104     {
105 
106         if ( USE_HANDLER )
107 
108         {
109 
110             XPathReader reader = XPathReaderFactory.createReader();
111 
112             PatternHandler handler = new PatternHandler();       
113 
114             
115 
116             handler.setXPathFactory( new DefaultXPathFactory() );            
117 
118             reader.setXPathHandler( handler );
119 
120             reader.parse( text );
121 
122             
123 
124             return handler.getPattern();
125 
126         }
127 
128         else
129 
130         {
131 
132             XPathReader reader = XPathReaderFactory.createReader();
133 
134             JaxenHandler handler = new JaxenHandler();
135 
136             
137 
138             handler.setXPathFactory( new DefaultXPathFactory() );            
139 
140             reader.setXPathHandler( handler );
141 
142             reader.parse( text );
143 
144 
145 
146             Pattern pattern = convertExpr( handler.getXPathExpr().getRootExpr() );
147 
148             return pattern.simplify();
149 
150         }
151 
152     }
153 
154     
155 
156     protected static Pattern convertExpr(Expr expr) throws JaxenException 
157 
158     {
159 
160         if ( TRACE )
161 
162         {
163 
164             System.out.println( "Converting: " + expr + " into a pattern." );
165 
166         }
167 
168         
169 
170         if ( expr instanceof LocationPath )
171 
172         {
173 
174             return convertExpr( (LocationPath) expr );
175 
176         }
177 
178         else if ( expr instanceof FilterExpr )
179 
180         {
181 
182             LocationPathPattern answer = new LocationPathPattern();
183 
184             answer.addFilter( (FilterExpr) expr );
185 
186             return answer;
187 
188         }
189 
190         else if ( expr instanceof UnionExpr )
191 
192         {
193 
194             UnionExpr unionExpr = (UnionExpr) expr;
195 
196             Pattern lhs = convertExpr( unionExpr.getLHS() );
197 
198             Pattern rhs = convertExpr( unionExpr.getRHS() );
199 
200             return new UnionPattern( lhs, rhs );
201 
202         }
203 
204         else 
205 
206         {
207 
208             LocationPathPattern answer = new LocationPathPattern();
209 
210             answer.addFilter( new DefaultFilterExpr( expr,
211                                 new PredicateSet()) );
212 
213             return answer;
214 
215         }
216 
217     }
218 
219     
220 
221     protected static LocationPathPattern convertExpr(LocationPath locationPath) throws JaxenException
222 
223     {
224 
225         LocationPathPattern answer = new LocationPathPattern();        
226 
227         //answer.setAbsolute( locationPath.isAbsolute() );
228 
229         List steps = locationPath.getSteps();
230 
231         
232 
233         // go through steps backwards
234 
235         LocationPathPattern path = answer;
236 
237         boolean first = true;
238 
239         for ( ListIterator iter = steps.listIterator( steps.size() ); iter.hasPrevious(); ) 
240 
241         {
242 
243             Step step = (Step) iter.previous();
244 
245             if ( first )
246 
247             {
248 
249                 first = false;
250 
251                 path = convertStep( path, step );
252 
253             }
254 
255             else
256 
257             {
258 
259                 if ( navigationStep( step ) ) 
260 
261                 {
262 
263                     LocationPathPattern parent = new LocationPathPattern();
264 
265                     int axis = step.getAxis();
266 
267                     if ( axis == Axis.DESCENDANT || axis == Axis.DESCENDANT_OR_SELF )
268 
269                     {
270 
271                         path.setAncestorPattern( parent );
272 
273                     }
274 
275                     else
276 
277                     {
278 
279                         path.setParentPattern( parent );
280 
281                     }
282 
283                     path = parent;
284 
285                 }
286 
287                 path = convertStep( path, step );
288 
289             }
290 
291         }
292 
293         if ( locationPath.isAbsolute() )
294 
295         {
296 
297             LocationPathPattern parent = new LocationPathPattern( NodeTypeTest.DOCUMENT_TEST );
298 
299             path.setParentPattern( parent );
300 
301         }
302 
303         return answer;
304 
305     }   
306 
307     
308 
309     protected static LocationPathPattern convertStep(LocationPathPattern path, Step step) throws JaxenException
310 
311     {
312 
313         if ( step instanceof DefaultAllNodeStep )
314 
315         {
316 
317             int axis = step.getAxis();
318 
319             if ( axis == Axis.ATTRIBUTE )
320 
321             {
322 
323                 path.setNodeTest( NodeTypeTest.ATTRIBUTE_TEST );
324 
325             }
326 
327             else 
328 
329             {
330 
331                 path.setNodeTest( NodeTypeTest.ELEMENT_TEST );
332 
333             }
334 
335         }
336 
337         else if ( step instanceof DefaultCommentNodeStep )
338 
339         {
340 
341             path.setNodeTest( NodeTypeTest.COMMENT_TEST );
342 
343         }
344 
345         else if ( step instanceof DefaultProcessingInstructionNodeStep )
346 
347         {
348 
349             path.setNodeTest( NodeTypeTest.PROCESSING_INSTRUCTION_TEST );
350 
351         }
352 
353         else if ( step instanceof DefaultTextNodeStep )
354 
355         {
356 
357             path.setNodeTest( TextNodeTest.SINGLETON );
358 
359         }
360 
361         else if ( step instanceof DefaultCommentNodeStep )
362 
363         {
364 
365             path.setNodeTest( NodeTypeTest.COMMENT_TEST );
366 
367         }
368 
369         else if ( step instanceof DefaultNameStep )
370 
371         {
372 
373             DefaultNameStep nameStep = (DefaultNameStep) step;
374 
375             String localName = nameStep.getLocalName();
376 
377             String prefix = nameStep.getPrefix();
378 
379             int axis = nameStep.getAxis();
380 
381             short nodeType = Pattern.ELEMENT_NODE;
382 
383             if ( axis == Axis.ATTRIBUTE )
384 
385             {
386 
387                 nodeType = Pattern.ATTRIBUTE_NODE;
388 
389             }
390 
391             if ( nameStep.isMatchesAnyName() )
392 
393             {
394 
395                 if ( prefix.length() == 0 || prefix.equals( "*" ) ) 
396 
397                 {
398 
399                     if ( axis == Axis.ATTRIBUTE )
400 
401                     {
402 
403                         path.setNodeTest( NodeTypeTest.ATTRIBUTE_TEST );
404 
405                     }
406 
407                     else 
408 
409                     {
410 
411                         path.setNodeTest( NodeTypeTest.ELEMENT_TEST );
412 
413                     }
414 
415                 }
416 
417                 else 
418 
419                 {
420 
421                     path.setNodeTest( new NamespaceTest( prefix, nodeType ) );
422 
423                 }
424 
425             }
426 
427             else 
428 
429             {
430 
431                 path.setNodeTest( new NameTest( localName, nodeType ) );
432 
433                 // XXXX: should support namespace in the test too
434 
435             }
436 
437             return convertDefaultStep(path, nameStep);
438 
439         }
440 
441         else if ( step instanceof DefaultStep )
442 
443         {
444 
445             return convertDefaultStep(path, (DefaultStep) step);
446 
447         }
448 
449         else 
450 
451         {
452 
453             throw new JaxenException( "Cannot convert: " + step + " to a Pattern" );            
454 
455         }
456 
457         return path;
458 
459     }
460 
461     
462 
463     protected static LocationPathPattern convertDefaultStep(LocationPathPattern path, DefaultStep step) throws JaxenException
464 
465     {
466 
467         List predicates = step.getPredicates();
468 
469         if ( ! predicates.isEmpty() ) 
470 
471         {
472 
473             DefaultFilterExpr filter = new DefaultFilterExpr(new PredicateSet());
474 
475             for ( Iterator iter = predicates.iterator(); iter.hasNext(); )
476 
477             {
478 
479                 filter.addPredicate( (Predicate) iter.next() );
480 
481             }
482 
483             path.addFilter( filter );
484 
485         }         
486 
487         return path;
488 
489     }
490 
491     
492 
493     protected static boolean navigationStep( Step step )
494 
495     {
496 
497         if ( step instanceof DefaultNameStep )
498 
499         {
500 
501             return true;
502 
503         }
504 
505         else
506 
507         if ( step.getClass().equals( DefaultStep.class ) )
508 
509         {
510 
511             return ! step.getPredicates().isEmpty();
512 
513         }
514 
515         else 
516 
517         {
518 
519             return true;
520 
521         }
522 
523     }
524 
525 }
526