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