View Javadoc

    1   /*
    2    * $Header: /home/projects/jaxen/scm/jaxen/src/java/main/org/jaxen/pattern/PatternParser.java,v 1.17 2005/09/25 11:43:14 elharo Exp $
    3    * $Revision: 1.17 $
    4    * $Date: 2005/09/25 11:43:14 $
    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.17 2005/09/25 11:43:14 elharo 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      private static final boolean USE_HANDLER = false;
    100     public static Pattern parse(String text) throws JaxenException, org.jaxen.saxpath.SAXPathException
    101     {
    102         if ( USE_HANDLER )
    103         {
    104             XPathReader reader = XPathReaderFactory.createReader();
    105             PatternHandler handler = new PatternHandler();
    106
    107             handler.setXPathFactory( new DefaultXPathFactory() );
    108             reader.setXPathHandler( handler );
    109             reader.parse( text );
    110
    111             return handler.getPattern();
    112         }
    113         else
    114         {
    115             XPathReader reader = XPathReaderFactory.createReader();
    116             JaxenHandler handler = new JaxenHandler();
    117
    118             handler.setXPathFactory( new DefaultXPathFactory() );
    119             reader.setXPathHandler( handler );
    120             reader.parse( text );
    121
    122             Pattern pattern = convertExpr( handler.getXPathExpr().getRootExpr() );
    123             return pattern.simplify();
    124         }
    125     }
    126
    127     protected static Pattern convertExpr(Expr expr) throws JaxenException
    128     {
    129         if ( TRACE )
    130         {
    131             System.out.println( "Converting: " + expr + " into a pattern." );
    132         }
    133
    134         if ( expr instanceof LocationPath )
    135         {
    136             return convertExpr( (LocationPath) expr );
    137         }
    138         else if ( expr instanceof FilterExpr )
    139         {
    140             LocationPathPattern answer = new LocationPathPattern();
    141             answer.addFilter( (FilterExpr) expr );
    142             return answer;
    143         }
    144         else if ( expr instanceof UnionExpr )
    145         {
    146             UnionExpr unionExpr = (UnionExpr) expr;
    147             Pattern lhs = convertExpr( unionExpr.getLHS() );
    148             Pattern rhs = convertExpr( unionExpr.getRHS() );
    149             return new UnionPattern( lhs, rhs );
    150         }
    151         else
    152         {
    153             LocationPathPattern answer = new LocationPathPattern();
    154             answer.addFilter( new DefaultFilterExpr( expr,
    155                                 new PredicateSet()) );
    156             return answer;
    157         }
    158     }
    159
    160     protected static LocationPathPattern convertExpr(LocationPath locationPath) throws JaxenException
    161     {
    162         LocationPathPattern answer = new LocationPathPattern();
    163         //answer.setAbsolute( locationPath.isAbsolute() );
    164         List steps = locationPath.getSteps();
    165
    166         // go through steps backwards
    167         LocationPathPattern path = answer;
    168         boolean first = true;
    169         for ( ListIterator iter = steps.listIterator( steps.size() ); iter.hasPrevious(); )
    170         {
    171             Step step = (Step) iter.previous();
    172             if ( first )
    173             {
    174                 first = false;
    175                 path = convertStep( path, step );
    176             }
    177             else
    178             {
    179                 if ( navigationStep( step ) )
    180                 {
    181                     LocationPathPattern parent = new LocationPathPattern();
    182                     int axis = step.getAxis();
    183                     if ( axis == Axis.DESCENDANT || axis == Axis.DESCENDANT_OR_SELF )
    184                     {
    185                         path.setAncestorPattern( parent );
    186                     }
    187                     else
    188                     {
    189                         path.setParentPattern( parent );
    190                     }
    191                     path = parent;
    192                 }
    193                 path = convertStep( path, step );
    194             }
    195         }
    196         if ( locationPath.isAbsolute() )
    197         {
    198             LocationPathPattern parent = new LocationPathPattern( NodeTypeTest.DOCUMENT_TEST );
    199             path.setParentPattern( parent );
    200         }
    201         return answer;
    202     }
    203
    204     protected static LocationPathPattern convertStep(LocationPathPattern path, Step step) throws JaxenException
    205     {
    206         if ( step instanceof DefaultAllNodeStep )
    207         {
    208             int axis = step.getAxis();
    209             if ( axis == Axis.ATTRIBUTE )
    210             {
    211                 path.setNodeTest( NodeTypeTest.ATTRIBUTE_TEST );
    212             }
    213             else
    214             {
    215                 path.setNodeTest( NodeTypeTest.ELEMENT_TEST );
    216             }
    217         }
    218         else if ( step instanceof DefaultCommentNodeStep )
    219         {
    220             path.setNodeTest( NodeTypeTest.COMMENT_TEST );
    221         }
    222         else if ( step instanceof DefaultProcessingInstructionNodeStep )
    223         {
    224             path.setNodeTest( NodeTypeTest.PROCESSING_INSTRUCTION_TEST );
    225         }
    226         else if ( step instanceof DefaultTextNodeStep )
    227         {
    228             path.setNodeTest( TextNodeTest.SINGLETON );
    229         }
    230         else if ( step instanceof DefaultCommentNodeStep )
    231         {
    232             path.setNodeTest( NodeTypeTest.COMMENT_TEST );
    233         }
    234         else if ( step instanceof DefaultNameStep )
    235         {
    236             DefaultNameStep nameStep = (DefaultNameStep) step;
    237             String localName = nameStep.getLocalName();
    238             String prefix = nameStep.getPrefix();
    239             int axis = nameStep.getAxis();
    240             short nodeType = Pattern.ELEMENT_NODE;
    241             if ( axis == Axis.ATTRIBUTE )
    242             {
    243                 nodeType = Pattern.ATTRIBUTE_NODE;
    244             }
    245             if ( nameStep.isMatchesAnyName() )
    246             {
    247                 if ( prefix.length() == 0 || prefix.equals( "*" ) )
    248                 {
    249                     if ( axis == Axis.ATTRIBUTE )
    250                     {
    251                         path.setNodeTest( NodeTypeTest.ATTRIBUTE_TEST );
    252                     }
    253                     else
    254                     {
    255                         path.setNodeTest( NodeTypeTest.ELEMENT_TEST );
    256                     }
    257                 }
    258                 else
    259                 {
    260                     path.setNodeTest( new NamespaceTest( prefix, nodeType ) );
    261                 }
    262             }
    263             else
    264             {
    265                 path.setNodeTest( new NameTest( localName, nodeType ) );
    266                 // XXXX: should support namespace in the test too
    267             }
    268             return convertDefaultStep(path, nameStep);
    269         }
    270         else if ( step instanceof DefaultStep )
    271         {
    272             return convertDefaultStep(path, (DefaultStep) step);
    273         }
    274         else
    275         {
    276             throw new JaxenException( "Cannot convert: " + step + " to a Pattern" );
    277         }
    278         return path;
    279     }
    280
    281     protected static LocationPathPattern convertDefaultStep(LocationPathPattern path, DefaultStep step) throws JaxenException
    282     {
    283         List predicates = step.getPredicates();
    284         if ( ! predicates.isEmpty() )
    285         {
    286             FilterExpr filter = new DefaultFilterExpr(new PredicateSet());
    287             for ( Iterator iter = predicates.iterator(); iter.hasNext(); )
    288             {
    289                 filter.addPredicate( (Predicate) iter.next() );
    290             }
    291             path.addFilter( filter );
    292         }
    293         return path;
    294     }
    295
    296     protected static boolean navigationStep( Step step )
    297     {
    298         if ( step instanceof DefaultNameStep )
    299         {
    300             return true;
    301         }
    302         else
    303         if ( step.getClass().equals( DefaultStep.class ) )
    304         {
    305             return ! step.getPredicates().isEmpty();
    306         }
    307         else
    308         {
    309             return true;
    310         }
    311     }
    312
    313 }
    314