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 }