View Javadoc

1   /*
2    * $Header$
3    * $Revision: 1128 $
4    * $Date: 2006-02-05 13:49:04 -0800 (Sun, 05 Feb 2006) $
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: PatternHandler.java 1128 2006-02-05 21:49:04Z elharo $
46   */
47  
48  
49  package org.jaxen.pattern;
50  
51  import java.util.LinkedList;
52  
53  import org.jaxen.JaxenException;
54  import org.jaxen.JaxenHandler;
55  import org.jaxen.expr.Expr;
56  import org.jaxen.expr.FilterExpr;
57  import org.jaxen.saxpath.Axis;
58  
59  /** SAXPath <code>XPathHandler</code> implementation capable
60   *  of building Jaxen expression trees which can walk various
61   *  different object models.
62   *
63   *  @author bob mcwhirter (bob@werken.com)
64   */
65  public class PatternHandler extends JaxenHandler
66  {
67      private Pattern pattern;
68      
69      public PatternHandler()
70      {
71      }
72      
73      /** Retrieve the simplified Jaxen Pattern expression tree.
74       *
75       *  <p>
76       *  This method is only valid once <code>XPathReader.parse(...)</code>
77       *  successfully returned.
78       *  </p>
79       *
80       *  @return The Pattern expression tree.
81       */
82      public Pattern getPattern()
83      {
84          return getPattern( true );
85      }
86  
87      /** Retrieve the Jaxen Pattern expression tree, optionally
88       *  simplified.
89       *
90       *  <p>
91       *  This method is only valid once <code>XPathReader.parse(...)</code>
92       *  successfully returned.
93       *  </p>
94       *  
95       *  @param shouldSimplify ????
96       *
97       *  @return The Pattern expression tree.
98       */
99      public Pattern getPattern(boolean shouldSimplify)
100     {
101         if ( shouldSimplify && ! this.simplified )
102         {
103             //System.err.println("simplifying....");
104             this.pattern.simplify();
105             this.simplified = true;
106         }
107 
108         return this.pattern;
109     }
110 
111     
112     
113     
114     public void endXPath()
115     {
116         this.pattern = (Pattern) pop();
117 
118         System.out.println( "stack is: " + stack );
119         
120         popFrame();
121     }
122 
123     public void endPathExpr()
124     {
125         //System.err.println("endPathExpr()");
126 
127         // PathExpr ::=   LocationPath
128         //              | FilterExpr
129         //              | FilterExpr / RelativeLocationPath
130         //              | FilterExpr // RelativeLocationPath
131         //
132         // If the current stack-frame has two items, it's a
133         // FilterExpr and a LocationPath (of some flavor).
134         //
135         // If the current stack-frame has one item, it's simply
136         // a FilterExpr, and more than like boils down to a
137         // primary expr of some flavor.  But that's for another
138         // method...
139 
140         LinkedList frame = popFrame();
141         
142         System.out.println( "endPathExpr(): " + frame );
143             
144         push( frame.removeFirst() );
145 /*        
146         LocationPathPattern locationPath = new LocationPathPattern();
147         push( locationPath );
148         while (! frame.isEmpty() )
149         {
150             Object filter = frame.removeLast();
151             if ( filter instanceof NodeTest ) 
152             {
153                 locationPath.setNodeTest( (NodeTest) filter );
154             }
155             else if ( filter instanceof FilterExpr )
156             {
157                 locationPath.addFilter( (FilterExpr) filter );
158             }
159             else if ( filter instanceof LocationPathPattern ) 
160             {
161                 LocationPathPattern parent = (LocationPathPattern) filter;
162                 locationPath.setParentPattern( parent );
163                 locationPath = parent;
164             }
165             else if ( filter != null ) 
166             {
167                 throw new JaxenException( "Unknown filter: " + filter );
168             }
169         }
170 */
171     }
172 
173     public void startAbsoluteLocationPath()
174     {
175         //System.err.println("startAbsoluteLocationPath()");
176         pushFrame();
177 
178         push( createAbsoluteLocationPath() );
179     }
180     
181     public void endAbsoluteLocationPath() throws JaxenException
182     {
183         //System.err.println("endAbsoluteLocationPath()");
184         endLocationPath();
185     }
186 
187     public void startRelativeLocationPath()
188     {
189         //System.err.println("startRelativeLocationPath()");
190         pushFrame();
191 
192         push( createRelativeLocationPath() );
193     }
194 
195     public void endRelativeLocationPath() throws JaxenException
196     {
197         //System.err.println("endRelativeLocationPath()");
198         endLocationPath();
199     }
200 
201     protected void endLocationPath() throws JaxenException
202     {
203         // start at the back, its the main pattern then add everything else as 
204         LinkedList list = popFrame();
205         
206         System.out.println( "endLocationPath: " + list );
207 
208         LocationPathPattern locationPath = (LocationPathPattern) list.removeFirst();
209         push( locationPath );
210         boolean doneNodeTest = false;
211         while ( ! list.isEmpty() )
212         {
213             Object filter = list.removeFirst();
214             if ( filter instanceof NodeTest ) 
215             {
216                 if ( doneNodeTest ) 
217                 {
218                     LocationPathPattern parent = new LocationPathPattern( (NodeTest) filter );
219                     locationPath.setParentPattern( parent );
220                     locationPath = parent;
221                     doneNodeTest = false;
222                 }   
223                 else
224                 {
225                     locationPath.setNodeTest( (NodeTest) filter );
226                 }
227             }
228             else if ( filter instanceof FilterExpr )
229             {
230                 locationPath.addFilter( (FilterExpr) filter );
231             }
232             else if ( filter instanceof LocationPathPattern ) 
233             {
234                 LocationPathPattern parent = (LocationPathPattern) filter;
235                 locationPath.setParentPattern( parent );
236                 locationPath = parent;
237                 doneNodeTest = false;
238             }
239         }
240     }
241 
242     
243     public void startNameStep(int axis,
244                               String prefix,
245                               String localName)
246     {
247         //System.err.println("startNameStep(" + axis + ", " + prefix + ", " + localName + ")");
248         pushFrame();
249 
250         short nodeType = Pattern.ELEMENT_NODE;            
251         switch ( axis ) 
252         {
253             case Axis.ATTRIBUTE:
254                 nodeType = Pattern.ATTRIBUTE_NODE;
255                 break;
256             case Axis.NAMESPACE:
257                 nodeType = Pattern.NAMESPACE_NODE;
258                 break;
259         }
260         
261         if ( prefix != null && prefix.length() > 0 && ! prefix.equals( "*" ) ) 
262         {                    
263             push( new NamespaceTest( prefix, nodeType ) );
264         }
265         if ( localName != null && localName.length() > 0 && ! localName.equals( "*" ) ) 
266         {
267             push( new NameTest( localName, nodeType ) );
268         }
269     }
270 
271     public void startTextNodeStep(int axis)
272     {
273         //System.err.println("startTextNodeStep()");
274         pushFrame();
275         
276         push( new NodeTypeTest( Pattern.TEXT_NODE ) );
277     }
278     
279     public void startCommentNodeStep(int axis)
280     {
281         //System.err.println("startCommentNodeStep()");
282         pushFrame();
283 
284         push( new NodeTypeTest( Pattern.COMMENT_NODE ) );
285     }
286 
287     public void startAllNodeStep(int axis)
288     {
289         //System.err.println("startAllNodeStep()");
290         pushFrame();
291 
292         push( AnyNodeTest.getInstance() );
293     }
294 
295     public void startProcessingInstructionNodeStep(int axis,
296                                                    String name)
297     {
298         //System.err.println("startProcessingInstructionStep()");
299         pushFrame();
300 
301         // XXXX: should we throw an exception if name is present?            
302         push( new NodeTypeTest( Pattern.PROCESSING_INSTRUCTION_NODE ) );
303     }
304     
305     protected void endStep()
306     {
307         LinkedList list = popFrame();
308         if ( ! list.isEmpty() ) 
309         {
310             push( list.removeFirst() );
311             
312             if ( ! list.isEmpty() )
313             {
314                 System.out.println( "List should now be empty!" + list );
315             }
316         }
317     }
318     
319 
320     public void startUnionExpr()
321     {
322         //System.err.println("startUnionExpr()");
323     }
324 
325     public void endUnionExpr(boolean create) throws JaxenException
326     {
327         //System.err.println("endUnionExpr()");
328 
329         if ( create )
330         {
331             //System.err.println("makeUnionExpr");
332 
333             Expr rhs = (Expr) pop();
334             Expr lhs = (Expr) pop();
335 
336             push( getXPathFactory().createUnionExpr( lhs,
337                                                     rhs ) );
338         }
339     }
340 
341     protected Pattern createAbsoluteLocationPath() 
342     {
343         return new LocationPathPattern( NodeTypeTest.DOCUMENT_TEST );
344     }
345 
346     protected Pattern createRelativeLocationPath() 
347     {
348         return new LocationPathPattern();
349     }
350 
351 }