KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectweb > jonas_ejb > lib > EjbqlQueryFilterVisitor


1 /**
2  * JOnAS: Java(TM) Open Application Server
3  * Copyright (C) 1999-2004 Bull S.A.
4  * Contact: jonas-team@objectweb.org
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19  * USA
20  *
21  * --------------------------------------------------------------------------
22  * $Id: EjbqlQueryFilterVisitor.java,v 1.30 2005/01/22 01:42:53 rhs Exp $
23  * --------------------------------------------------------------------------
24  */

25 package org.objectweb.jonas_ejb.lib;
26
27 import java.util.ArrayList JavaDoc;
28 import java.util.Map JavaDoc;
29 import java.util.Stack JavaDoc;
30
31 import javax.ejb.EJBObject JavaDoc;
32
33 import org.objectweb.jonas_ejb.deployment.ejbql.ASTArithmeticExpression;
34 import org.objectweb.jonas_ejb.deployment.ejbql.ASTArithmeticFactor;
35 import org.objectweb.jonas_ejb.deployment.ejbql.ASTArithmeticLiteral;
36 import org.objectweb.jonas_ejb.deployment.ejbql.ASTArithmeticTerm;
37 import org.objectweb.jonas_ejb.deployment.ejbql.ASTBetweenExpression;
38 import org.objectweb.jonas_ejb.deployment.ejbql.ASTBooleanExpression;
39 import org.objectweb.jonas_ejb.deployment.ejbql.ASTBooleanLiteral;
40 import org.objectweb.jonas_ejb.deployment.ejbql.ASTCmpPathExpression;
41 import org.objectweb.jonas_ejb.deployment.ejbql.ASTCollectionMemberExpression;
42 import org.objectweb.jonas_ejb.deployment.ejbql.ASTCollectionValuedPathExpression;
43 import org.objectweb.jonas_ejb.deployment.ejbql.ASTComparisonExpression;
44 import org.objectweb.jonas_ejb.deployment.ejbql.ASTConditionalExpression;
45 import org.objectweb.jonas_ejb.deployment.ejbql.ASTConditionalFactor;
46 import org.objectweb.jonas_ejb.deployment.ejbql.ASTConditionalTerm;
47 import org.objectweb.jonas_ejb.deployment.ejbql.ASTDatetimeExpression;
48 import org.objectweb.jonas_ejb.deployment.ejbql.ASTEJBQL;
49 import org.objectweb.jonas_ejb.deployment.ejbql.ASTEmptyCollectionComparisonExpression;
50 import org.objectweb.jonas_ejb.deployment.ejbql.ASTEntityBeanExpression;
51 import org.objectweb.jonas_ejb.deployment.ejbql.ASTFloatingPointLiteral;
52 import org.objectweb.jonas_ejb.deployment.ejbql.ASTFunctionsReturningNumerics;
53 import org.objectweb.jonas_ejb.deployment.ejbql.ASTFunctionsReturningStrings;
54 import org.objectweb.jonas_ejb.deployment.ejbql.ASTIdentificationVariable;
55 import org.objectweb.jonas_ejb.deployment.ejbql.ASTInExpression;
56 import org.objectweb.jonas_ejb.deployment.ejbql.ASTInputParameter;
57 import org.objectweb.jonas_ejb.deployment.ejbql.ASTIntegerLiteral;
58 import org.objectweb.jonas_ejb.deployment.ejbql.ASTLikeExpression;
59 import org.objectweb.jonas_ejb.deployment.ejbql.ASTLiteral;
60 import org.objectweb.jonas_ejb.deployment.ejbql.ASTNullComparisonExpression;
61 import org.objectweb.jonas_ejb.deployment.ejbql.ASTPath;
62 import org.objectweb.jonas_ejb.deployment.ejbql.ASTSingleValuedCmrPathExpression;
63 import org.objectweb.jonas_ejb.deployment.ejbql.ASTSingleValuedPathExpression;
64 import org.objectweb.jonas_ejb.deployment.ejbql.ASTStringExpression;
65 import org.objectweb.jonas_ejb.deployment.ejbql.ASTStringLiteral;
66 import org.objectweb.jonas_ejb.deployment.ejbql.ASTWhereClause;
67 import org.objectweb.jonas_ejb.deployment.ejbql.EJBQLConstants;
68 import org.objectweb.jonas_ejb.deployment.ejbql.ParseException;
69 import org.objectweb.jonas_ejb.deployment.ejbql.SimpleNode;
70 import org.objectweb.jorm.api.PMapper;
71 import org.objectweb.jorm.lib.JormPathHelper;
72 import org.objectweb.jorm.naming.api.PName;
73 import org.objectweb.jorm.type.api.PType;
74 import org.objectweb.medor.api.Field;
75 import org.objectweb.medor.expression.api.MalformedExpressionException;
76 import org.objectweb.medor.expression.api.Expression;
77 import org.objectweb.medor.filter.api.FieldOperand;
78 import org.objectweb.medor.expression.api.Operand;
79 import org.objectweb.medor.filter.jorm.lib.IsNullPName;
80 import org.objectweb.medor.expression.lib.Abs;
81 import org.objectweb.medor.expression.lib.And;
82 import org.objectweb.medor.filter.lib.BasicFieldOperand;
83 import org.objectweb.medor.expression.lib.BasicOperand;
84 import org.objectweb.medor.expression.lib.BasicParameterOperand;
85 import org.objectweb.medor.filter.lib.CollectionOperand;
86 import org.objectweb.medor.expression.lib.Concat;
87 import org.objectweb.medor.expression.lib.DivideBy;
88 import org.objectweb.medor.expression.lib.Equal;
89 import org.objectweb.medor.expression.lib.FirstLocate;
90 import org.objectweb.medor.expression.lib.Greater;
91 import org.objectweb.medor.expression.lib.GreaterEqual;
92 import org.objectweb.medor.filter.lib.InCollection;
93 import org.objectweb.medor.expression.lib.IndexedLocate;
94 import org.objectweb.medor.filter.lib.IsEmpty;
95 import org.objectweb.medor.filter.lib.IsNull;
96 import org.objectweb.medor.expression.lib.Length;
97 import org.objectweb.medor.expression.lib.Like;
98 import org.objectweb.medor.expression.lib.Lower;
99 import org.objectweb.medor.expression.lib.LowerEqual;
100 import org.objectweb.medor.filter.lib.MemberOf;
101 import org.objectweb.medor.expression.lib.Minus;
102 import org.objectweb.medor.expression.lib.Mod;
103 import org.objectweb.medor.expression.lib.Mult;
104 import org.objectweb.medor.expression.lib.Not;
105 import org.objectweb.medor.expression.lib.NotEqual;
106 import org.objectweb.medor.expression.lib.Or;
107 import org.objectweb.medor.expression.lib.Plus;
108 import org.objectweb.medor.expression.lib.Sqrt;
109 import org.objectweb.medor.expression.lib.Substring;
110 import org.objectweb.medor.expression.lib.UMinus;
111 import org.objectweb.medor.query.api.PropagatedField;
112 import org.objectweb.medor.query.jorm.lib.PNameField;
113 import org.objectweb.medor.query.jorm.lib.QueryBuilder;
114 import org.objectweb.medor.type.lib.PTypeSpaceMedor;
115 import org.objectweb.medor.type.lib.QType;
116
117 /**
118  * Implementation of a visitor that creates the filter corresponding
119  * to the WHERE clause.
120  * Created on Sep 6, 2002
121  * @author Christophe Ney [cney@batisseurs.com] : Intial developer
122  * @author Helene Joanin: Take into account the following operators
123  * abs(x), sqrt(x),
124  * length(str), substring(s, start, length),
125  * locate(str1, str2), locate(str1, str2, start).
126  * @author Helene Joanin: EJBLocalObject as parameter of a EJB-QL query.
127  * @author Helene Joanin: Take into account the InExpression (IN operator).
128  * @author Helene Joanin: Take into account the IS NULL operator.
129  * @author Helene Joanin: Fix a bug in the visitor for ASTIdentificationVariable:
130  * push a BasicFieldOperand(field) instead of the field itself.
131  * @author Helene Joanin: add '.element' to the path for CollectionValuedPathExpression.
132  * @author Helene Joanin: Convert IsNull(cmr-field) to Equal(cmr-field, PNameNull).
133  * @author Helene Joanin: Take into account the operators: IS EMPTY / IS NOT EMPTY
134  * @author Helene Joanin: Take into account the CONCAT operator
135  * @author Helene Joanin: Take into account the EJBQL version 2.1 syntax.
136  * @author Helene Joanin: Take into account the operator MOD.
137  * @author Helene Joanin: Take into account the operator ISNULL with a parameter.
138  */

139 public class EjbqlQueryFilterVisitor extends EjbqlAbstractVisitor {
140
141     Expression qf = null;
142     PMapper mapper = null;
143     Map JavaDoc fields = null;
144     Class JavaDoc[] parameterTypes;
145     QueryBuilder qb;
146
147     static final String JavaDoc OP_IGNORE = "ignore";
148
149     /**
150      * Constructor
151      * @param _mapper the mapper of each fields.
152      * Needed to build the expression for the IsNull with a reference as an operand.
153      * This parameter may be null in case of the GenIC phase
154      * @param _fields QueryTreeFields for all defined identifiers and all path expression of the query
155      * @param parameterTypes Type of paramaters of the finder/select method
156      * @param ejbql root of the lexical tree of the query
157      */

158     public EjbqlQueryFilterVisitor(PMapper _mapper,
159                                    Map JavaDoc _fields,
160                                    Class JavaDoc[] parameterTypes,
161                                    ASTEJBQL ejbql,
162                                    QueryBuilder qb) throws Exception JavaDoc {
163         mapper = _mapper;
164         fields = _fields;
165         this.parameterTypes = parameterTypes;
166         this.qb = qb;
167         visit(ejbql);
168     }
169
170     /**
171      * get the query filter that was built from visiting the syntaxic tree
172      */

173     public Expression getQueryFilter() {
174         return qf;
175     }
176
177     /**
178      * If query contains WHERE clause, visit child nodes<br>
179      * where_clause ::= WHERE conditional_expression
180      */

181     public Object JavaDoc visit(ASTWhereClause node, Object JavaDoc data) {
182         visit((SimpleNode) node, data);
183         if (OP_IGNORE.equals(((Stack JavaDoc) data).peek())) {
184             qf = null;
185         } else {
186             qf = (Expression) ((Stack JavaDoc) data).pop();
187         }
188         return null;
189     }
190
191     /**
192      * Push corresponding MedorField to the stack.<br>
193      * single_valued_path_expression ::= path
194      * was in initial BNF
195      * single_valued_path_expression ::= cmp_path_expression | single_valued_cmr_path_expression
196      */

197     public Object JavaDoc visit(ASTSingleValuedPathExpression node, Object JavaDoc data) {
198         visit((SimpleNode) node, data);
199         try {
200             String JavaDoc path = (String JavaDoc) ((ASTPath) ((Stack JavaDoc) data).pop()).value;
201             Field f = (Field) fields.get(path);
202             // FIXME check type for single valued
203
// test GenClassRef or ClassRef
204
((Stack JavaDoc) data).push(new BasicFieldOperand(f));
205         } catch (Exception JavaDoc e) {
206             throw new VisitorException(e);
207         }
208         return null;
209     }
210
211     /**
212      * Push corresponding MedorField to the stack.<br>
213      * cmp_path_expression ::= path
214      * was in initial BNF
215      * cmp_path_expression ::= identification_variable. [ single_valued_cmr_field. ] * cmp_field
216      */

217     public Object JavaDoc visit(ASTCmpPathExpression node, Object JavaDoc data) {
218         visit((SimpleNode) node, data);
219         try {
220             String JavaDoc path = (String JavaDoc) ((ASTPath) ((Stack JavaDoc) data).pop()).value;
221             Field f = (Field) fields.get(path);
222             // FIXME check type for cmp field
223
((Stack JavaDoc) data).push(new BasicFieldOperand(f));
224         } catch (Exception JavaDoc e) {
225             throw new VisitorException(e);
226         }
227         return null;
228     }
229
230     /**
231      * Push corresponding MedorField to the stack.<br>
232      * single_valued_cmr_path_expression ::= path
233      * was in initial BNF
234      * single_valued_cmr_path_expression ::= identification_variable. [ single_valued_cmr_field. ] * single_valued_cmr_field
235      */

236     public Object JavaDoc visit(ASTSingleValuedCmrPathExpression node, Object JavaDoc data) {
237         visit((SimpleNode) node, data);
238         try {
239             String JavaDoc path = (String JavaDoc) ((ASTPath) ((Stack JavaDoc) data).pop()).value;
240             Field f = (Field) fields.get(path);
241             // FIXME check type for single valued cmr
242
((Stack JavaDoc) data).push(new BasicFieldOperand(f));
243         } catch (Exception JavaDoc e) {
244             throw new VisitorException(e);
245         }
246         return null;
247     }
248
249     /**
250      * Push corresponding MedorField to the stack.<br>
251      * collection_valued_path_expression ::= path
252      * was in initial BNF
253      * collection_valued_path_expression ::= identification_variable. [ single_valued_cmr_field. ] *collection_valued_cmr_field
254      */

255     public Object JavaDoc visit(ASTCollectionValuedPathExpression node, Object JavaDoc data) {
256         visit((SimpleNode) node, data);
257         try {
258             // FIXME check type for collection valued cmr
259
String JavaDoc path = (String JavaDoc) ((ASTPath) ((Stack JavaDoc) data).pop()).value;
260             String JavaDoc[] parts = splitPath(path);
261             String JavaDoc first = parts[0];
262             String JavaDoc rest = mergePath(parts, 1, parts.length - 1);
263             QueryBuilder subquery = new QueryBuilder(qb);
264             subquery.define("", qb.navigate(first));
265             Field f = subquery.project(subquery.navigate(rest));
266             ((Stack JavaDoc) data).push(new BasicFieldOperand(f));
267         } catch (Exception JavaDoc e) {
268             throw new VisitorException(e);
269         }
270         return null;
271     }
272
273     /**
274      * Push corresponding Expression to the stack.<br>
275      * conditional_expression ::= conditional_term [ OR conditional_term ]*
276      */

277     public Object JavaDoc visit(ASTConditionalExpression node, Object JavaDoc data) {
278         visit((SimpleNode) node, data);
279         Object JavaDoc ret = ((Stack JavaDoc) data).pop();
280         for (int i = 1; i < node.jjtGetNumChildren(); i++) {
281             if (OP_IGNORE.equals(ret)) {
282                 ret = ((Stack JavaDoc) data).pop();
283             } else if (OP_IGNORE.equals(((Stack JavaDoc) data).peek())) {
284                 ((Stack JavaDoc) data).pop();
285             } else {
286                 ret = new Or((Expression) ((Stack JavaDoc) data).pop(), (Expression) ret);
287             }
288         }
289         // push result on Stack
290
((Stack JavaDoc) data).push(ret);
291         return null;
292     }
293
294     /**
295      * Push corresponding Expression to the stack.<br>
296      * conditional_term ::= conditional_factor [ AND conditional_factor ]*
297      */

298     public Object JavaDoc visit(ASTConditionalTerm node, Object JavaDoc data) {
299         visit((SimpleNode) node, data);
300         Object JavaDoc ret = ((Stack JavaDoc) data).pop();
301         for (int i = 1; i < node.jjtGetNumChildren(); i++) {
302             if (OP_IGNORE.equals(ret)) {
303                 ret = ((Stack JavaDoc) data).pop();
304             } else if (OP_IGNORE.equals(((Stack JavaDoc) data).peek())) {
305                 ((Stack JavaDoc) data).pop();
306             } else {
307                 ret = new And((Expression) ((Stack JavaDoc) data).pop(), (Expression) ret);
308             }
309         }
310         // push result on Stack
311
((Stack JavaDoc) data).push(ret);
312         return null;
313     }
314
315     /**
316      * Push corresponding Expression to the stack.<br>
317      * conditional_factor ::= [ NOT ] conditional_test
318      */

319     public Object JavaDoc visit(ASTConditionalFactor node, Object JavaDoc data) {
320         visit((SimpleNode) node, data);
321         if (node.not) {
322             if (!OP_IGNORE.equals(((Stack JavaDoc) data).peek())) {
323                 Expression ret = (Expression) ((Stack JavaDoc) data).pop();
324                 // push result on Stack
325
((Stack JavaDoc) data).push(new Not(ret));
326             }
327         }
328         return null;
329     }
330
331     /**
332      * Push corresponding Expression to the stack.<br>
333      * between_expression ::= arithmetic_expression [ NOT ] BETWEEN arithmetic_expression AND arithmetic_expression
334      */

335     public Object JavaDoc visit(ASTBetweenExpression node, Object JavaDoc data) {
336         visit((SimpleNode) node, data);
337         Expression[] terms = new Expression[3];
338         terms[2] = (Expression) ((Stack JavaDoc) data).pop();
339         terms[1] = (Expression) ((Stack JavaDoc) data).pop();
340         terms[0] = (Expression) ((Stack JavaDoc) data).pop();
341         if (node.not) {
342             ((Stack JavaDoc) data).push(new Or(new Lower(terms[0], terms[1]), new Greater(terms[0], terms[2])));
343         } else {
344             ((Stack JavaDoc) data).push(new And(new GreaterEqual(terms[0], terms[1]), new LowerEqual(terms[0], terms[2])));
345         }
346         return null;
347     }
348
349     /**
350      * Push corresponding Expression to the stack.<br>
351      * in_expression ::= cmp_path_expression [ NOT ] IN
352      * {literal|input_parameter} [ , {literal|input_parameter} ] * )
353      */

354     public Object JavaDoc visit(ASTInExpression node, Object JavaDoc data) {
355         visit((SimpleNode) node, data);
356         Stack JavaDoc s = (Stack JavaDoc) data;
357         ArrayList JavaDoc c = new ArrayList JavaDoc();
358         for (int i = 1; i <= node.eltnum; i++) {
359             c.add(s.pop());
360         }
361         CollectionOperand co = new CollectionOperand(c);
362         FieldOperand f = (FieldOperand) s.pop();
363         if (node.not) {
364             s.push(new Not(new InCollection(f, co, f.getField().getType())));
365         } else {
366             s.push(new InCollection(f, co, f.getField().getType()));
367         }
368         return null;
369     }
370
371     /**
372      * Push corresponding Expression to the stack.<br>
373      * like_expression ::= cmp_path_expression [ NOT ] LIKE pattern_value
374      * [ ESCAPE escape_character ]
375      */

376     public Object JavaDoc visit(ASTLikeExpression node, Object JavaDoc data) {
377         visit((SimpleNode) node, data);
378         Stack JavaDoc s = (Stack JavaDoc) data;
379         Expression e1 = (Expression) s.pop();
380         Expression e2 = (Expression) s.pop();
381         Expression e3 = null;
382         if (node.third) {
383             //The like operator contains a ESCAPE section.
384
e3 = (Expression) s.pop();
385         }
386         if (e3 == null) {
387             s.push(new Like(e2, e1, node.not));
388         } else {
389             s.push(new Like(e3, e2, e1, node.not));
390         }
391         return null;
392     }
393
394     /**
395      * Push corresponding Expression to the stack.<br>
396      * null_comparison_expression ::= {single_valued_path_expression|input_parameter} IS [ NOT ] NULL
397      */

398     public Object JavaDoc visit(ASTNullComparisonExpression node, Object JavaDoc data) {
399         visit((SimpleNode) node, data);
400         Stack JavaDoc s = (Stack JavaDoc) data;
401         Expression e1 = (Expression) s.pop();
402         if ((e1 instanceof BasicParameterOperand)
403             && (e1.getType().getTypeCode() == QType.TYPECODE_PNAME)) {
404             // The operand is a bean parameter: use IsNullPName
405
if (node.not) {
406                 s.push(new Not(new IsNullPName(((BasicParameterOperand)e1).getName())));
407             } else {
408                 s.push(new IsNullPName(((BasicParameterOperand)e1).getName()));
409             }
410         } else if (e1.getType().getTypeCode() == PType.TYPECODE_REFERENCE) {
411             // The operand is a cmr field: use the Equal operator with PNameNull as second operand
412
// Warning: The PNameNull value may not be build because the mapper may be null
413
// in case of this expression building is done in the GenIC phase
414
Field f = ((FieldOperand) e1).getField();
415             PNameField pnf = null;
416             if (f instanceof PNameField) {
417                 pnf = (PNameField) f;
418             } else if (f instanceof PropagatedField) {
419                 pnf = (PNameField)((PropagatedField) f).getOriginFields()[0];
420             } else {
421                 // error: unmanaged case
422
throw new Error JavaDoc("Operand of IS NULL not valid !?");
423             }
424             Operand op2;
425             if (mapper == null) {
426                 // dummy operand2 to be able to build a query even in the GenIC phase
427
op2 = new BasicOperand("pnamenull");
428             } else {
429                 // real operand2 PNameNull
430
PName pnamenull = JormPathHelper.getPNameCoder(pnf.getPNamingContextParameter(),
431                                                                mapper).getNull();
432                 op2 = new BasicOperand(pnamenull, PTypeSpaceMedor.PNAME);
433             }
434             if (node.not) {
435                 s.push(new Not(new Equal(e1, op2)));
436             } else {
437                 s.push(new Equal(e1, op2));
438             }
439         } else {
440             // The operand is a cmp field, or a ...: use the IsNull operator
441
if (node.not) {
442                 s.push(new Not(new IsNull(e1)));
443             } else {
444                 s.push(new IsNull(e1));
445             }
446         }
447         return null;
448         
449     }
450
451     /**
452      * Nothing to do:
453      * Already taken into account in EjbqlVariableVisitor at the variables parsing,
454      * so, just push the OP_IGNORE in the stack
455      * empty_collection_comparison_expression ::= collection_valued_path_expression IS [ NOT ] EMPTY
456      */

457     public Object JavaDoc visit(ASTEmptyCollectionComparisonExpression node, Object JavaDoc data) {
458         visit((SimpleNode) node, data);
459         Stack JavaDoc s = (Stack JavaDoc) data;
460         Expression e = (Expression) s.pop();
461         Expression res = new IsEmpty(e);
462         if (node.not) {
463             res = new Not(res);
464         }
465         s.push(res);
466         return null;
467     }
468
469     /**
470      * Push corresponding Expression to the stack.<br>
471      * collection_member_expression ::= {single_valued_cmr_path_expression | identification_variable | input_parameter}
472      * [ NOT ] MEMBER [ OF ] collection_valued_path_expression
473      */

474     public Object JavaDoc visit(ASTCollectionMemberExpression node, Object JavaDoc data) {
475         visit((SimpleNode) node, data);
476         Stack JavaDoc s = (Stack JavaDoc) data;
477         Expression e2 = (Expression) s.pop();
478         Expression e1 = (Expression) s.pop();
479         ArrayList JavaDoc le2 = new ArrayList JavaDoc(); le2.add(e2);
480         ArrayList JavaDoc le1 = new ArrayList JavaDoc(); le1.add(e1);
481         Expression res = null;
482         try {
483             res = new MemberOf(le1, le2);
484         } catch (MalformedExpressionException e) {
485             throw new Error JavaDoc("Operand expression of MEMBER OF malformed: "
486                             + e + e.getNestedException());
487         }
488         if (node.not) {
489             s.push(new Not(res));
490         } else {
491             s.push(res);
492         }
493         return null;
494     }
495
496
497     /**
498      * Push corresponding Expression to the stack.<br>
499      * comparison_expression ::= string_value { = | > | >= | < | <= | <> } string_expression
500      * | boolean_value { = | <>} boolean_expression
501      * | datetime_value { = | > | >= | < | <= | <> } datetime_expression
502      * | entity_bean_value { = | <> } entity_bean_expression
503      * | arithmetic_value { = | > | >= | < | <= | <> } single_value_designator
504      */

505     public Object JavaDoc visit(ASTComparisonExpression node, Object JavaDoc data) {
506         visit((SimpleNode) node, data);
507         Expression[] terms = new Expression[2];
508         terms[1] = (Expression) ((Stack JavaDoc) data).pop();
509         terms[0] = (Expression) ((Stack JavaDoc) data).pop();
510         int op = ((Integer JavaDoc) node.ops.get(0)).intValue();
511         switch (op) {
512         case EJBQLConstants.EQ:
513             ((Stack JavaDoc) data).push(new Equal(terms[0], terms[1]));
514             break;
515         case EJBQLConstants.NE:
516             ((Stack JavaDoc) data).push(new NotEqual(terms[0], terms[1]));
517             break;
518         case EJBQLConstants.GT:
519             ((Stack JavaDoc) data).push(new Greater(terms[0], terms[1]));
520             break;
521         case EJBQLConstants.GE:
522             ((Stack JavaDoc) data).push(new GreaterEqual(terms[0], terms[1]));
523             break;
524         case EJBQLConstants.LT:
525             ((Stack JavaDoc) data).push(new Lower(terms[0], terms[1]));
526             break;
527         case EJBQLConstants.LE:
528             ((Stack JavaDoc) data).push(new LowerEqual(terms[0], terms[1]));
529             break;
530         }
531         return null;
532     }
533
534     /**
535      * Push corresponding Expression to the stack.<br>
536      * arithmetic_expression ::= arithmetic_term [ { + | - } arithmetic_term ] *
537      */

538     public Object JavaDoc visit(ASTArithmeticExpression node, Object JavaDoc data) {
539         visit((SimpleNode) node, data);
540         Expression ret = (Expression) ((Stack JavaDoc) data).pop();
541         for (int i = 0; i < node.jjtGetNumChildren() - 1; i++) {
542             switch (((Integer JavaDoc) node.ops.get(node.jjtGetNumChildren() - 2 - i)).intValue()) {
543             case EJBQLConstants.PLUS:
544                 ret = new Plus((Expression) ((Stack JavaDoc) data).pop(), ret);
545                 break;
546             case EJBQLConstants.MINUS:
547                 ret = new Minus((Expression) ((Stack JavaDoc) data).pop(), ret);
548                 break;
549             }
550         }
551         // push result to the Stack
552
((Stack JavaDoc) data).push(ret);
553         return null;
554     }
555
556     /**
557      * Push corresponding Expression to the stack.<br>
558      * arithmetic_term ::= arithmetic_factor [ { * | / } arithmetic_factor ]*
559      */

560     public Object JavaDoc visit(ASTArithmeticTerm node, Object JavaDoc data) {
561         visit((SimpleNode) node, data);
562         Expression ret = (Expression) ((Stack JavaDoc) data).pop();
563         for (int i = 0; i < node.jjtGetNumChildren() - 1; i++) {
564             switch (((Integer JavaDoc) node.ops.get(node.jjtGetNumChildren() - 2 - i)).intValue()) {
565             case EJBQLConstants.MULT:
566                 ret = new Mult((Expression) ((Stack JavaDoc) data).pop(), ret);
567                 break;
568             case EJBQLConstants.DIV:
569                 ret = new DivideBy((Expression) ((Stack JavaDoc) data).pop(), ret);
570                 break;
571             }
572         }
573         // push result to the Stack
574
((Stack JavaDoc) data).push(ret);
575         return null;
576     }
577
578     /**
579      * Push corresponding Expression to the stack.<br>
580      * arithmetic_factor ::= [ + |- ] arithmetic_primary
581      */

582     public Object JavaDoc visit(ASTArithmeticFactor node, Object JavaDoc data) {
583         visit((SimpleNode) node, data);
584         Expression ret = (Expression) ((Stack JavaDoc) data).pop();
585         if (node.ops.size() > 0) {
586             if (((Integer JavaDoc) node.ops.get(0)).intValue() == EJBQLConstants.MINUS) {
587                 ret = new UMinus((Expression) ret);
588             }
589         }
590         // push result on Stack
591
((Stack JavaDoc) data).push(ret);
592         return null;
593     }
594
595
596     /**
597      * Visit child nodes
598      * string_expression ::= string_primary | input_parameter
599      */

600     public Object JavaDoc visit(ASTStringExpression node, Object JavaDoc data) {
601         visit((SimpleNode) node, data);
602         // FIXME check or convert type?
603
return null;
604     }
605
606     /**
607      * Visit child nodes
608      * datetime_expression ::= datetime_value | input_parameter
609      */

610     public Object JavaDoc visit(ASTDatetimeExpression node, Object JavaDoc data) {
611         visit((SimpleNode) node, data);
612         // FIXME check or convert type?
613
return null;
614     }
615
616     /**
617      * Visit child nodes
618      * boolean_expression ::= cmp_path_expression | boolean_literal | input_parameter
619      */

620     public Object JavaDoc visit(ASTBooleanExpression node, Object JavaDoc data) {
621         visit((SimpleNode) node, data);
622         // FIXME check or convert type?
623
return null;
624     }
625
626     /**
627      * Visit child nodes
628      * entity_bean_expression ::= entity_bean_value | input_parameter
629      */

630     public Object JavaDoc visit(ASTEntityBeanExpression node, Object JavaDoc data) {
631         visit((SimpleNode) node, data);
632         // FIXME check or convert type?
633
return null;
634     }
635
636     /**
637      * visit child nodes
638      * Push corresponding Expression to the stack.<br>
639      * functions_returning_strings ::= CONCAT (string_expression, string_expression)
640      * | SUBSTRING (string_expression,arithmetic_expression,arithmetic_expression)
641      */

642     public Object JavaDoc visit(ASTFunctionsReturningStrings node, Object JavaDoc data) {
643         visit((SimpleNode) node, data);
644         Stack JavaDoc s = (Stack JavaDoc) data;
645         int op = ((Integer JavaDoc) node.ops.get(0)).intValue();
646         Expression ret = null;
647         Expression e1, e2;
648         switch (op) {
649         case EJBQLConstants.CONCAT:
650             // e1, e2 are in reverse order in the stack
651
e2 = (Expression) s.pop();
652             e1 = (Expression) s.pop();
653             ret = new Concat(e1, e2);
654             break;
655         case EJBQLConstants.SUBSTRING:
656             // e1, e2, e3 are in reverse order in the stack
657
Expression e3 = (Expression) s.pop();
658             e2 = (Expression) s.pop();
659             e1 = (Expression) s.pop();
660             ret = new Substring(e1, e2, e3);
661             break;
662         }
663         // push result to the Stack
664
s.push(ret);
665         return null;
666     }
667
668
669     /**
670      * visit child nodes
671      * Push corresponding Expression to the stack.<br>
672      * functions_returning_numerics ::= LENGTH (string_expression)
673      * | LOCATE (string_expression, string_expression
674      * [ , arithmetic_expression ] )
675      * | ABS (arithmetic_expression)
676      * | SQRT (arithmetic_expression)
677      * | MOD (arithmetic_expression , arithmetic_expression)
678      */

679     public Object JavaDoc visit(ASTFunctionsReturningNumerics node, Object JavaDoc data) {
680         visit((SimpleNode) node, data);
681         Stack JavaDoc s = (Stack JavaDoc) data;
682         int op = ((Integer JavaDoc) node.ops.get(0)).intValue();
683         Expression e1, e2;
684         Expression ret = null;
685         switch (op) {
686         case EJBQLConstants.LENGTH:
687             e1 = (Expression) s.pop();
688             ret = new Length(e1);
689             break;
690         case EJBQLConstants.LOCATE:
691             // Operands are in the reverse order in the stack
692
Expression e3 = null;
693             if (node.third) {
694                 // The locate operator contains a third operand.
695
e3 = (Expression) s.pop();
696             }
697             e2 = (Expression) s.pop();
698             e1 = (Expression) s.pop();
699             // Warning on the args order for IndexedLocate and FirstLocate.
700
if (node.third) {
701                 ret = new IndexedLocate(e2, e1, e3);
702             } else {
703                 ret = new FirstLocate(e1, e2);
704             }
705             break;
706         case EJBQLConstants.ABS:
707             e1 = (Expression) s.pop();
708             ret = new Abs(e1);
709             break;
710         case EJBQLConstants.SQRT:
711             e1 = (Expression) s.pop();
712             ret = new Sqrt(e1);
713             break;
714         case EJBQLConstants.MOD:
715             e2 = (Expression) s.pop();
716             e1 = (Expression) s.pop();
717             ret = new Mod(e1, e2);
718             break;
719         }
720         // push result to the Stack
721
s.push(ret);
722         return null;
723     }
724
725     /**
726      * Node with value set to identification variable string.
727      * Push the Node to the stack
728      */

729     public Object JavaDoc visit(ASTIdentificationVariable node, Object JavaDoc data) {
730         String JavaDoc fieldname = (String JavaDoc) node.value + "." + Field.PNAMENAME;
731         Field f = (Field) fields.get(fieldname);
732         ((Stack JavaDoc) data).push(new BasicFieldOperand(f));
733         return null;
734     }
735
736     /**
737      * Visit child nodes
738      * literal ::= string_literal | arithmetic_literal | boolean_literal
739      */

740     public Object JavaDoc visit(ASTLiteral node, Object JavaDoc data) {
741         visit((SimpleNode) node, data);
742         return null;
743     }
744
745     /**
746      * Node with value set to litteral string.
747      * Push the corresponding Operand to the stack
748      */

749     public Object JavaDoc visit(ASTStringLiteral node, Object JavaDoc data) {
750         ((Stack JavaDoc) data).push(new BasicOperand((String JavaDoc) node.value));
751         return null;
752     }
753
754     /**
755      * Visit child nodes
756      * arithmetic_literal ::= integer_literal | floatingpoint_literal
757      */

758     public Object JavaDoc visit(ASTArithmeticLiteral node, Object JavaDoc data) {
759         visit((SimpleNode) node, data);
760         return null;
761     }
762
763     /**
764      * Node with value set to integer litteral arithmetic.
765      * Push the corresponding Operand to the stack
766      */

767     public Object JavaDoc visit(ASTIntegerLiteral node, Object JavaDoc data) {
768         ((Stack JavaDoc) data).push(new BasicOperand(((Long JavaDoc) node.value).longValue()));
769         return null;
770     }
771
772     /**
773      * Node with value set to integer litteral arithmetic.
774      * Push the corresponding Operand to the stack
775      */

776     public Object JavaDoc visit(ASTFloatingPointLiteral node, Object JavaDoc data) {
777         ((Stack JavaDoc) data).push(new BasicOperand(((Double JavaDoc) node.value).doubleValue()));
778         return null;
779     }
780
781     /**
782      * Node with value set to litteral boolean.
783      * Push the corresponding Operand to the stack
784      */

785     public Object JavaDoc visit(ASTBooleanLiteral node, Object JavaDoc data) {
786         ((Stack JavaDoc) data).push(new BasicOperand(((Boolean JavaDoc) node.value).booleanValue()));
787         return null;
788     }
789
790     /**
791      * Node with value set to parameter index (1..n) string.
792      * Push the corresponding Operand to the stack
793      */

794     public Object JavaDoc visit(ASTInputParameter node, Object JavaDoc data) {
795         try {
796             int pIndex = ((Integer JavaDoc) node.value).intValue() - 1;
797             if (pIndex >= parameterTypes.length) {
798                 throw new ParseException("Parameter ?" + (pIndex + 1)
799                                          + " is out of range (max = "
800                                          + parameterTypes.length + ")");
801             }
802             if (EJBObject JavaDoc.class.isAssignableFrom(parameterTypes[pIndex])) {
803                 // TODO: Take into account EJBObject as parameter
804
// (Only EJBLocalObject are already taken into account)
805
throw new Error JavaDoc("EJBObject params not implemented");
806             }
807             Operand op = new BasicParameterOperand(JormType.getPType(parameterTypes[pIndex], false),
808                                                    "?" + node.value);
809             ((Stack JavaDoc) data).push(op);
810             return null;
811         } catch (ParseException e) {
812             throw new VisitorException(e);
813         }
814     }
815
816     /**
817      * Push the Node to the stack
818      */

819     public Object JavaDoc visit(ASTPath node, Object JavaDoc data) {
820         ((Stack JavaDoc) data).push(node);
821         return null;
822     }
823 }
824
Popular Tags