View Javadoc

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