View Javadoc

1   /*
2    * $Header: /home/projects/jaxen/scm/jaxen/src/java/main/org/jaxen/JaxenHandler.java,v 1.10 2005/06/01 11:21:07 elharo Exp $
3    * $Revision: 1.10 $
4    * $Date: 2005/06/01 11:21:07 $
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: JaxenHandler.java,v 1.10 2005/06/01 11:21:07 elharo Exp $
60   */
61  
62  
63  
64  package org.jaxen;
65  
66  import java.util.Iterator;
67  import java.util.LinkedList;
68  
69  import org.jaxen.expr.DefaultXPathFactory;
70  import org.jaxen.expr.Expr;
71  import org.jaxen.expr.FilterExpr;
72  import org.jaxen.expr.FunctionCallExpr;
73  import org.jaxen.expr.LocationPath;
74  import org.jaxen.expr.Predicate;
75  import org.jaxen.expr.Predicated;
76  import org.jaxen.expr.Step;
77  import org.jaxen.expr.XPathExpr;
78  import org.jaxen.expr.XPathFactory;
79  import org.jaxen.saxpath.Operator;
80  import org.jaxen.saxpath.XPathHandler;
81  
82  /*** SAXPath <code>XPathHandler</code> implementation capable
83   *  of building Jaxen expression trees which can walk various
84   *  different object models.
85   *
86   *  @author bob mcwhirter (bob@werken.com)
87   */
88  public class JaxenHandler implements XPathHandler
89  {
90      private XPathFactory xpathFactory;
91      private XPathExpr    xpath;
92      
93      /***
94       * ????
95       */
96      protected boolean simplified;
97  
98      /***
99       * ????
100      */
101     protected LinkedList stack;
102 
103     /*** Constructor
104      */
105     public JaxenHandler()
106     {
107         this.stack        = new LinkedList();
108         this.xpathFactory = new DefaultXPathFactory();
109     }
110     
111     /*** Set the Jaxen <code>XPathFactory</code> to use
112      *  during the parse to construct the XPath expression tree.
113      *
114      *  @param xpathFactory the factory to use during the parse
115      */
116     public void setXPathFactory(XPathFactory xpathFactory)
117     {
118         this.xpathFactory = xpathFactory;
119     }
120 
121     /*** Retrieve the Jaxen <code>XPathFactory</code> used
122      *  during the parse to construct the XPath expression tree.
123      *
124      *  @return the <code>XPathFactory</code> used during the parse.
125      */
126     public XPathFactory getXPathFactory()
127     {
128         return this.xpathFactory;
129     }
130 
131     /*** Retrieve the simplified Jaxen XPath expression tree.
132      *
133      *  <p>
134      *  This method is only valid once <code>XPathReader.parse(...)</code>
135      *  successfully returned.
136      *  </p>
137      *
138      *  @return the XPath expression tree
139      */
140     public XPathExpr getXPathExpr()
141     {
142         return getXPathExpr( true );
143     }
144 
145     /*** Retrieve the Jaxen XPath expression tree, optionally
146      *  simplified.
147      *
148      *  <p>
149      *  This method is only valid once <code>XPathReader.parse(...)</code>
150      *  successfully returned.
151      *  </p>
152      *
153      *  @return the XPath expression tree
154      */
155     public XPathExpr getXPathExpr(boolean shouldSimplify)
156     {
157         if ( shouldSimplify && ! this.simplified )
158         {
159             this.xpath.simplify();
160             this.simplified = true;
161         }
162 
163         return this.xpath;
164     }
165 
166     public void startXPath() throws JaxenException
167     {
168         this.simplified = false;
169         pushFrame();
170     }
171     
172     public void endXPath() throws JaxenException
173     {
174         this.xpath = getXPathFactory().createXPath( (Expr) pop() );
175         popFrame();
176     }
177 
178     public void startPathExpr() throws JaxenException
179     {
180         pushFrame();
181     }
182 
183     public void endPathExpr() throws JaxenException
184     {
185 
186         // PathExpr ::=   LocationPath
187         //              | FilterExpr
188         //              | FilterExpr / RelativeLocationPath
189         //              | FilterExpr // RelativeLocationPath
190         //
191         // If the current stack-frame has two items, it's a
192         // FilterExpr and a LocationPath (of some flavor).
193         //
194         // If the current stack-frame has one item, it's simply
195         // a FilterExpr, and more than likely boils down to a
196         // primary expr of some flavor.  But that's for another
197         // method...
198 
199         FilterExpr   filterExpr;
200         LocationPath locationPath;
201 
202         Object       popped;
203 
204         if ( stackSize() == 2 )
205         {
206             locationPath = (LocationPath) pop();
207             filterExpr   = (FilterExpr) pop();
208         }
209         else
210         {
211             popped = pop();
212 
213             if ( popped instanceof LocationPath )
214             {
215                 locationPath = (LocationPath) popped;
216                 filterExpr   = null;
217             }
218             else
219             {
220                 locationPath = null;
221                 filterExpr   = (FilterExpr) popped;
222             }
223         }
224         popFrame();
225 
226         push( getXPathFactory().createPathExpr( filterExpr,
227                                                locationPath ) );
228     }
229 
230     public void startAbsoluteLocationPath() throws JaxenException
231     {
232         pushFrame();
233 
234         push( getXPathFactory().createAbsoluteLocationPath() );
235     }
236 
237     public void endAbsoluteLocationPath() throws JaxenException
238     {
239         endLocationPath();
240     }
241 
242     public void startRelativeLocationPath() throws JaxenException
243     {
244         pushFrame();
245 
246         push( getXPathFactory().createRelativeLocationPath() );
247     }
248 
249     public void endRelativeLocationPath() throws JaxenException
250     {
251         endLocationPath();
252     }
253 
254     protected void endLocationPath() throws JaxenException
255     {
256         LocationPath path = (LocationPath) peekFrame().removeFirst();
257 
258         addSteps( path,
259                   popFrame().iterator() );
260 
261         push( path );
262     }
263 
264     protected void addSteps(LocationPath locationPath,
265                           Iterator stepIter)
266     {
267         while ( stepIter.hasNext() )
268         {
269             locationPath.addStep( (Step) stepIter.next() );
270         }
271     }
272 
273     public void startNameStep(int axis,
274                               String prefix,
275                               String localName) throws JaxenException
276     {
277         pushFrame();
278 
279         push( getXPathFactory().createNameStep( axis,
280                                                prefix,
281                                                localName ) );
282     }
283 
284     public void endNameStep() throws JaxenException
285     {
286         endStep();
287     }
288     
289     public void startTextNodeStep(int axis) throws JaxenException
290     {
291         //System.err.println("startTextNodeStep()");
292         pushFrame();
293         
294         push( getXPathFactory().createTextNodeStep( axis ) );
295     }
296     
297     public void endTextNodeStep() throws JaxenException
298     {
299         endStep();
300     }
301 
302     public void startCommentNodeStep(int axis) throws JaxenException
303     {
304         pushFrame();
305 
306         push( getXPathFactory().createCommentNodeStep( axis ) );
307     }
308 
309     public void endCommentNodeStep() throws JaxenException
310     {
311         endStep();
312     }
313         
314     public void startAllNodeStep(int axis) throws JaxenException
315     {
316         pushFrame();
317 
318         push( getXPathFactory().createAllNodeStep( axis ) );
319     }
320 
321     public void endAllNodeStep() throws JaxenException
322     {
323         endStep();
324     }
325 
326     public void startProcessingInstructionNodeStep(int axis,
327                                                    String name) throws JaxenException
328     {
329         pushFrame();
330 
331         push( getXPathFactory().createProcessingInstructionNodeStep( axis,
332                                                                     name ) );
333     }
334     
335     public void endProcessingInstructionNodeStep() throws JaxenException
336     {
337         endStep();
338     }
339 
340     protected void endStep()
341     {
342         Step step = (Step) peekFrame().removeFirst();
343 
344         addPredicates( step,
345                        popFrame().iterator() );
346 
347         push( step );
348     }
349     
350     public void startPredicate() throws JaxenException
351     {
352         pushFrame();
353     }
354     
355     public void endPredicate() throws JaxenException
356     {
357         Predicate predicate = getXPathFactory().createPredicate( (Expr) pop() );
358 
359         popFrame();
360 
361         push( predicate );
362     }
363 
364     public void startFilterExpr() throws JaxenException
365     {
366         pushFrame();
367     }
368 
369     public void endFilterExpr() throws JaxenException
370     {
371         Expr expr = (Expr) peekFrame().removeFirst();
372         
373         FilterExpr filter = getXPathFactory().createFilterExpr( expr );
374 
375         Iterator predIter = popFrame().iterator();
376 
377         addPredicates( filter,
378                        predIter );
379 
380         push( filter );
381     }
382 
383     protected void addPredicates(Predicated obj,
384                                Iterator predIter)
385     {
386         while ( predIter.hasNext() )
387         {
388             obj.addPredicate( (Predicate) predIter.next() );
389         }
390     }
391 
392     protected void returnExpr()
393     {
394         Expr expr = (Expr) pop();
395         popFrame();
396         push( expr );
397     }
398 
399     public void startOrExpr() throws JaxenException
400     {
401     }
402 
403     public void endOrExpr(boolean create) throws JaxenException
404     {
405 
406         if ( create )
407         {
408             Expr rhs = (Expr) pop();
409             Expr lhs = (Expr) pop();
410 
411             push( getXPathFactory().createOrExpr( lhs,
412                                                  rhs ) );
413         }
414     }
415 
416     public void startAndExpr() throws JaxenException
417     {
418     }
419 
420     public void endAndExpr(boolean create) throws JaxenException
421     {
422 
423         if ( create )
424         {
425 
426             Expr rhs = (Expr) pop();
427             Expr lhs = (Expr) pop();
428 
429             push( getXPathFactory().createAndExpr( lhs,
430                                                   rhs ) );
431         }
432     }
433 
434     public void startEqualityExpr() throws JaxenException
435     {
436     }
437 
438     public void endEqualityExpr(int operator) throws JaxenException
439     {
440 
441         if ( operator != Operator.NO_OP )
442         {
443             
444             Expr rhs = (Expr) pop();
445             Expr lhs = (Expr) pop();
446             
447             push( getXPathFactory().createEqualityExpr( lhs,
448                                                         rhs,
449                                                         operator ) );
450         }
451     }
452 
453     public void startRelationalExpr() throws JaxenException
454     {
455     }
456 
457     public void endRelationalExpr(int operator) throws JaxenException
458     {
459 
460         if ( operator != Operator.NO_OP )
461         {
462 
463             Expr rhs = (Expr) pop();
464             Expr lhs = (Expr) pop();
465 
466             push( getXPathFactory().createRelationalExpr( lhs,
467                                                          rhs,
468                                                          operator ) );
469         }
470     }
471 
472     public void startAdditiveExpr() throws JaxenException
473     {
474     }
475 
476     public void endAdditiveExpr(int operator) throws JaxenException
477     {
478 
479         if ( operator != Operator.NO_OP )
480         {
481             
482             Expr rhs = (Expr) pop();
483             Expr lhs = (Expr) pop();
484             
485             push( getXPathFactory().createAdditiveExpr( lhs,
486                                                         rhs,
487                                                         operator ) );
488         }
489     }
490 
491     public void startMultiplicativeExpr() throws JaxenException
492     {
493     }
494 
495     public void endMultiplicativeExpr(int operator) throws JaxenException
496     {
497 
498         if ( operator != Operator.NO_OP )
499         {
500 
501             Expr rhs = (Expr) pop();
502             Expr lhs = (Expr) pop();
503             
504             push( getXPathFactory().createMultiplicativeExpr( lhs,
505                                                              rhs,
506                                                              operator ) );
507         }
508     }
509 
510     public void startUnaryExpr() throws JaxenException
511     {
512      }
513 
514     public void endUnaryExpr(int operator) throws JaxenException
515     {
516 
517         if ( operator != Operator.NO_OP )
518         {
519             push( getXPathFactory().createUnaryExpr( (Expr) pop(),
520                                                     operator ) );
521         }
522     }
523 
524     public void startUnionExpr() throws JaxenException
525     {
526     }
527 
528     public void endUnionExpr(boolean create) throws JaxenException
529     {
530 
531         if ( create )
532         {
533 
534             Expr rhs = (Expr) pop();
535             Expr lhs = (Expr) pop();
536 
537             push( getXPathFactory().createUnionExpr( lhs,
538                                                     rhs ) );
539         }
540     }
541 
542     public void number(int number) throws JaxenException
543     {
544         push( getXPathFactory().createNumberExpr( number ) );
545     }
546 
547     public void number(double number) throws JaxenException
548     {
549         push( getXPathFactory().createNumberExpr( number ) );
550     }
551 
552     public void literal(String literal) throws JaxenException
553     {
554         push( getXPathFactory().createLiteralExpr( literal ) );
555     }
556 
557     public void variableReference(String prefix,
558                                   String variableName) throws JaxenException
559     {
560         push( getXPathFactory().createVariableReferenceExpr( prefix,
561                                                              variableName ) );
562     }
563 
564     public void startFunction(String prefix,
565                               String functionName) throws JaxenException
566     {
567         pushFrame();
568         push( getXPathFactory().createFunctionCallExpr( prefix,
569                                                         functionName ) );
570     }
571 
572     public void endFunction() throws JaxenException
573     {
574         FunctionCallExpr function = (FunctionCallExpr) peekFrame().removeFirst();
575 
576         addParameters( function,
577                        popFrame().iterator() );
578 
579         push( function );
580     }
581 
582     protected void addParameters(FunctionCallExpr function,
583                                Iterator paramIter)
584     {
585         while ( paramIter.hasNext() )
586         {
587             function.addParameter( (Expr) paramIter.next() );
588         }
589     }
590 
591     protected int stackSize()
592     {
593         return peekFrame().size();
594     }
595 
596     protected void push(Object obj)
597     {
598         peekFrame().addLast( obj );
599     }
600 
601     protected Object pop()
602     {
603         return peekFrame().removeLast();
604     }
605 
606     protected boolean canPop()
607     {
608         return ( peekFrame().size() > 0 );
609     }
610 
611     protected void pushFrame()
612     {
613         this.stack.addLast( new LinkedList() );
614     }
615 
616     protected LinkedList popFrame()
617     {
618         return (LinkedList) this.stack.removeLast();
619     }
620 
621     protected LinkedList peekFrame()
622     {
623         return (LinkedList) this.stack.getLast();
624     }
625 }