Coverage Report - org.jaxen.pattern.PatternParser
 
Classes in this File Line Coverage Branch Coverage Complexity
PatternParser
81%
82/101
92%
23/25
6.833
 
 1  
 /*
 2  
  * $Header: /home/projects/jaxen/scm/jaxen/src/java/main/org/jaxen/pattern/PatternParser.java,v 1.18 2006/02/05 21:47:42 elharo Exp $
 3  
  * $Revision: 1.18 $
 4  
  * $Date: 2006/02/05 21:47:42 $
 5  
  *
 6  
  * ====================================================================
 7  
  *
 8  
  * Copyright 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 are
 13  
  * met:
 14  
  * 
 15  
  *   * Redistributions of source code must retain the above copyright
 16  
  *     notice, this list of conditions and the following disclaimer.
 17  
  * 
 18  
  *   * Redistributions in binary form must reproduce the above copyright
 19  
  *     notice, this list of conditions and the following disclaimer in the
 20  
  *     documentation and/or other materials provided with the distribution.
 21  
  * 
 22  
  *   * Neither the name of the Jaxen Project nor the names of its
 23  
  *     contributors may be used to endorse or promote products derived 
 24  
  *     from this software without specific prior written permission.
 25  
  * 
 26  
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 27  
  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 28  
  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 29  
  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
 30  
  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 31  
  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 32  
  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 33  
  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 34  
  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 35  
  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 36  
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 37  
  *
 38  
  * ====================================================================
 39  
  * This software consists of voluntary contributions made by many 
 40  
  * individuals on behalf of the Jaxen Project and was originally 
 41  
  * created by bob mcwhirter <bob@werken.com> and 
 42  
  * James Strachan <jstrachan@apache.org>.  For more information on the 
 43  
  * Jaxen Project, please see <http://www.jaxen.org/>.
 44  
  * 
 45  
  * $Id: PatternParser.java,v 1.18 2006/02/05 21:47:42 elharo Exp $
 46  
  */
 47  
 
 48  
 
 49  
 package org.jaxen.pattern;
 50  
 
 51  
 import java.util.Iterator;
 52  
 import java.util.List;
 53  
 import java.util.ListIterator;
 54  
 
 55  
 import org.jaxen.JaxenException;
 56  
 import org.jaxen.JaxenHandler;
 57  
 import org.jaxen.expr.DefaultAllNodeStep;
 58  
 import org.jaxen.expr.DefaultCommentNodeStep;
 59  
 import org.jaxen.expr.DefaultFilterExpr;
 60  
 import org.jaxen.expr.DefaultNameStep;
 61  
 import org.jaxen.expr.DefaultProcessingInstructionNodeStep;
 62  
 import org.jaxen.expr.DefaultStep;
 63  
 import org.jaxen.expr.DefaultTextNodeStep;
 64  
 import org.jaxen.expr.DefaultXPathFactory;
 65  
 import org.jaxen.expr.Expr;
 66  
 import org.jaxen.expr.FilterExpr;
 67  
 import org.jaxen.expr.LocationPath;
 68  
 import org.jaxen.expr.Predicate;
 69  
 import org.jaxen.expr.PredicateSet;
 70  
 import org.jaxen.expr.Step;
 71  
 import org.jaxen.expr.UnionExpr;
 72  
 import org.jaxen.saxpath.Axis;
 73  
 import org.jaxen.saxpath.XPathReader;
 74  
 import org.jaxen.saxpath.helpers.XPathReaderFactory;
 75  
 
 76  
 
 77  
 /** <code>PatternParser</code> is a helper class for parsing
 78  
   * XSLT patterns
 79  
   *
 80  
   * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
 81  
   */
 82  0
 public class PatternParser 
 83  
 {
 84  
     private static final boolean TRACE = false;
 85  
     private static final boolean USE_HANDLER = false;
 86  
     public static Pattern parse(String text) throws JaxenException, org.jaxen.saxpath.SAXPathException
 87  
     {
 88  
         if ( USE_HANDLER )
 89  
         {
 90  
             XPathReader reader = XPathReaderFactory.createReader();
 91  
             PatternHandler handler = new PatternHandler();       
 92  
             
 93  
             handler.setXPathFactory( new DefaultXPathFactory() );            
 94  
             reader.setXPathHandler( handler );
 95  
             reader.parse( text );
 96  
             
 97  
             return handler.getPattern();
 98  
         }
 99  
         else
 100  
         {
 101  46
             XPathReader reader = XPathReaderFactory.createReader();
 102  46
             JaxenHandler handler = new JaxenHandler();
 103  
             
 104  46
             handler.setXPathFactory( new DefaultXPathFactory() );            
 105  46
             reader.setXPathHandler( handler );
 106  46
             reader.parse( text );
 107  
 
 108  46
             Pattern pattern = convertExpr( handler.getXPathExpr().getRootExpr() );
 109  46
             return pattern.simplify();
 110  
         }
 111  
     }
 112  
     
 113  
     protected static Pattern convertExpr(Expr expr) throws JaxenException 
 114  
     {
 115  
         if ( TRACE )
 116  
         {
 117  
             System.out.println( "Converting: " + expr + " into a pattern." );
 118  
         }
 119  
         
 120  58
         if ( expr instanceof LocationPath )
 121  
         {
 122  52
             return convertExpr( (LocationPath) expr );
 123  
         }
 124  6
         else if ( expr instanceof FilterExpr )
 125  
         {
 126  0
             LocationPathPattern answer = new LocationPathPattern();
 127  0
             answer.addFilter( (FilterExpr) expr );
 128  0
             return answer;
 129  
         }
 130  6
         else if ( expr instanceof UnionExpr )
 131  
         {
 132  6
             UnionExpr unionExpr = (UnionExpr) expr;
 133  6
             Pattern lhs = convertExpr( unionExpr.getLHS() );
 134  6
             Pattern rhs = convertExpr( unionExpr.getRHS() );
 135  6
             return new UnionPattern( lhs, rhs );
 136  
         }
 137  
         else 
 138  
         {
 139  0
             LocationPathPattern answer = new LocationPathPattern();
 140  0
             answer.addFilter( new DefaultFilterExpr( expr,
 141  
                                 new PredicateSet()) );
 142  0
             return answer;
 143  
         }
 144  
     }
 145  
     
 146  
     protected static LocationPathPattern convertExpr(LocationPath locationPath) throws JaxenException
 147  
     {
 148  52
         LocationPathPattern answer = new LocationPathPattern();        
 149  
         //answer.setAbsolute( locationPath.isAbsolute() );
 150  52
         List steps = locationPath.getSteps();
 151  
         
 152  
         // go through steps backwards
 153  52
         LocationPathPattern path = answer;
 154  52
         boolean first = true;
 155  52
         for ( ListIterator iter = steps.listIterator( steps.size() ); iter.hasPrevious(); ) 
 156  
         {
 157  72
             Step step = (Step) iter.previous();
 158  72
             if ( first )
 159  
             {
 160  48
                 first = false;
 161  48
                 path = convertStep( path, step );
 162  48
             }
 163  
             else
 164  
             {
 165  24
                 if ( navigationStep( step ) ) 
 166  
                 {
 167  24
                     LocationPathPattern parent = new LocationPathPattern();
 168  24
                     int axis = step.getAxis();
 169  24
                     if ( axis == Axis.DESCENDANT || axis == Axis.DESCENDANT_OR_SELF )
 170  
                     {
 171  4
                         path.setAncestorPattern( parent );
 172  4
                     }
 173  
                     else
 174  
                     {
 175  20
                         path.setParentPattern( parent );
 176  
                     }
 177  24
                     path = parent;
 178  
                 }
 179  24
                 path = convertStep( path, step );
 180  
             }
 181  72
         }
 182  52
         if ( locationPath.isAbsolute() )
 183  
         {
 184  8
             LocationPathPattern parent = new LocationPathPattern( NodeTypeTest.DOCUMENT_TEST );
 185  8
             path.setParentPattern( parent );
 186  
         }
 187  52
         return answer;
 188  
     }   
 189  
     
 190  
     protected static LocationPathPattern convertStep(LocationPathPattern path, Step step) throws JaxenException
 191  
     {
 192  72
         if ( step instanceof DefaultAllNodeStep )
 193  
         {
 194  4
             int axis = step.getAxis();
 195  4
             if ( axis == Axis.ATTRIBUTE )
 196  
             {
 197  0
                 path.setNodeTest( NodeTypeTest.ATTRIBUTE_TEST );
 198  0
             }
 199  
             else 
 200  
             {
 201  4
                 path.setNodeTest( NodeTypeTest.ELEMENT_TEST );
 202  
             }
 203  4
         }
 204  68
         else if ( step instanceof DefaultCommentNodeStep )
 205  
         {
 206  0
             path.setNodeTest( NodeTypeTest.COMMENT_TEST );
 207  0
         }
 208  68
         else if ( step instanceof DefaultProcessingInstructionNodeStep )
 209  
         {
 210  0
             path.setNodeTest( NodeTypeTest.PROCESSING_INSTRUCTION_TEST );
 211  0
         }
 212  68
         else if ( step instanceof DefaultTextNodeStep )
 213  
         {
 214  4
             path.setNodeTest( TextNodeTest.SINGLETON );
 215  4
         }
 216  64
         else if ( step instanceof DefaultCommentNodeStep )
 217  
         {
 218  0
             path.setNodeTest( NodeTypeTest.COMMENT_TEST );
 219  0
         }
 220  64
         else if ( step instanceof DefaultNameStep )
 221  
         {
 222  64
             DefaultNameStep nameStep = (DefaultNameStep) step;
 223  64
             String localName = nameStep.getLocalName();
 224  64
             String prefix = nameStep.getPrefix();
 225  64
             int axis = nameStep.getAxis();
 226  64
             short nodeType = Pattern.ELEMENT_NODE;
 227  64
             if ( axis == Axis.ATTRIBUTE )
 228  
             {
 229  4
                 nodeType = Pattern.ATTRIBUTE_NODE;
 230  
             }
 231  64
             if ( nameStep.isMatchesAnyName() )
 232  
             {
 233  16
                 if ( prefix.length() == 0 || prefix.equals( "*" ) ) 
 234  
                 {
 235  14
                     if ( axis == Axis.ATTRIBUTE )
 236  
                     {
 237  4
                         path.setNodeTest( NodeTypeTest.ATTRIBUTE_TEST );
 238  4
                     }
 239  
                     else 
 240  
                     {
 241  10
                         path.setNodeTest( NodeTypeTest.ELEMENT_TEST );
 242  
                     }
 243  10
                 }
 244  
                 else 
 245  
                 {
 246  2
                     path.setNodeTest( new NamespaceTest( prefix, nodeType ) );
 247  
                 }
 248  2
             }
 249  
             else 
 250  
             {
 251  48
                 path.setNodeTest( new NameTest( localName, nodeType ) );
 252  
                 // XXXX: should support namespace in the test too
 253  
             }
 254  64
             return convertDefaultStep(path, nameStep);
 255  
         }
 256  0
         else if ( step instanceof DefaultStep )
 257  
         {
 258  0
             return convertDefaultStep(path, (DefaultStep) step);
 259  
         }
 260  
         else 
 261  
         {
 262  0
             throw new JaxenException( "Cannot convert: " + step + " to a Pattern" );            
 263  
         }
 264  8
         return path;
 265  
     }
 266  
     
 267  
     protected static LocationPathPattern convertDefaultStep(LocationPathPattern path, DefaultStep step) throws JaxenException
 268  
     {
 269  64
         List predicates = step.getPredicates();
 270  64
         if ( ! predicates.isEmpty() ) 
 271  
         {
 272  10
             FilterExpr filter = new DefaultFilterExpr(new PredicateSet());
 273  10
             for ( Iterator iter = predicates.iterator(); iter.hasNext(); )
 274  
             {
 275  10
                 filter.addPredicate( (Predicate) iter.next() );
 276  10
             }
 277  10
             path.addFilter( filter );
 278  
         }         
 279  64
         return path;
 280  
     }
 281  
     
 282  
     protected static boolean navigationStep( Step step )
 283  
     {
 284  24
         if ( step instanceof DefaultNameStep )
 285  
         {
 286  20
             return true;
 287  
         }
 288  
         else
 289  6
         if ( step.getClass().equals( DefaultStep.class ) )
 290  
         {
 291  0
             return ! step.getPredicates().isEmpty();
 292  
         }
 293  
         else 
 294  
         {
 295  4
             return true;
 296  
         }
 297  
     }
 298  
 
 299  
 }
 300