View Javadoc

    1   /*
    2    * $Header: /home/projects/jaxen/scm/jaxen/src/java/main/org/jaxen/JaxenHandler.java,v 1.11 2005/06/28 13:44:44 elharo Exp $
    3    * $Revision: 1.11 $
    4    * $Date: 2005/06/28 13:44:44 $
    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.11 2005/06/28 13:44:44 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 }