001: /**
002: * JOnAS: Java(TM) Open Application Server
003: * Copyright (C) 2004 Bull S.A.
004: * Contact: jonas-team@objectweb.org
005: *
006: * This library is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU Lesser General Public
008: * License as published by the Free Software Foundation; either
009: * version 2.1 of the License, or any later version.
010: *
011: * This library is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * Lesser General Public License for more details.
015: *
016: * You should have received a copy of the GNU Lesser General Public
017: * License along with this library; if not, write to the Free Software
018: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
019: * USA
020: *
021: * --------------------------------------------------------------------------
022: * $Id: EjbqlLimitVisitor.java 5843 2004-12-03 07:48:57Z joaninh $
023: * --------------------------------------------------------------------------
024: */package org.objectweb.jonas_ejb.lib;
025:
026: import java.util.Stack;
027:
028: import org.objectweb.jonas_ejb.deployment.ejbql.ASTEJBQL;
029: import org.objectweb.jonas_ejb.deployment.ejbql.ASTInputParameter;
030: import org.objectweb.jonas_ejb.deployment.ejbql.ASTIntegerLiteral;
031: import org.objectweb.jonas_ejb.deployment.ejbql.ASTLimitClause;
032: import org.objectweb.jonas_ejb.deployment.ejbql.ASTLimitExpression;
033: import org.objectweb.jonas_ejb.deployment.ejbql.ParseException;
034: import org.objectweb.jonas_ejb.deployment.ejbql.SimpleNode;
035:
036: /**
037: * Implementation of a visitor that creates the limiter ranges corresponding to
038: * the LIMIT clause
039: * @author Cyrille Blot : Initial developer
040: * @author Helene Joanin
041: */
042: public class EjbqlLimitVisitor extends EjbqlAbstractVisitor {
043:
044: /**
045: * Types of the parameters list of the finder/select method
046: */
047: private Class[] paramTypes;
048:
049: /**
050: * Limiter ranges
051: */
052: private EjbqlLimiterRange[] ranges = new EjbqlLimiterRange[0];
053:
054: /**
055: * Constructor
056: * @param ejbql root of the lexical tree of the query
057: * @param paramTypes Types of the parameters list of the finder/select
058: * method
059: * @throws Exception in error case
060: */
061: public EjbqlLimitVisitor(ASTEJBQL ejbql, Class[] paramTypes)
062: throws Exception {
063: this .paramTypes = paramTypes;
064: visit(ejbql);
065: }
066:
067: /**
068: * @return returns the limiter ranges of the LIMIT clause.
069: * May be 0 element if no LIMIT clause, 1 or 2 elements otherwise.
070: */
071: public EjbqlLimiterRange[] getLimiterRanges() {
072: return ranges;
073: }
074:
075: /**
076: * Visit child node. LIMIT LimitExpression() ( , LimitExpression())?
077: * @param node sub-root of the lexical tree
078: * @param data stack
079: * @return returns null
080: */
081: public Object visit(ASTLimitClause node, Object data) {
082: visit((SimpleNode) node, data);
083: Stack s = (Stack) data;
084: ranges = new EjbqlLimiterRange[s.size()];
085: if (s.size() > 1) {
086: // s = [row, nbr]
087: ranges[1] = (EjbqlLimiterRange) s.pop();
088: }
089: // s = [row]
090: ranges[0] = (EjbqlLimiterRange) s.pop();
091: return null;
092: }
093:
094: /**
095: * Visit child node LimitExpression().
096: * @param node sub-root of the lexical tree
097: * @param data stack
098: * @return returns null
099: */
100: public Object visit(ASTLimitExpression node, Object data) {
101: visit((SimpleNode) node, data);
102: return null;
103: }
104:
105: /**
106: * Visit child nodes literal ::= integer_literal Push the corresponding
107: * EjbqlLimiterRange to the stack
108: * @param node sub-root of the lexical tree
109: * @param data stack
110: * @return returns null
111: */
112: public Object visit(ASTIntegerLiteral node, Object data) {
113: ((Stack) data).push(new EjbqlLimiterRange(
114: EjbqlLimiterRange.KIND_LITERAL, ((Long) node.value)
115: .intValue()));
116: return null;
117: }
118:
119: /**
120: * Node with value set to parameter index (1..n) string. Push the
121: * corresponding EjbqlLimiterRange to the stack
122: * @param node sub-root of the lexical tree
123: * @param data stack
124: * @return returns null
125: */
126: public Object visit(ASTInputParameter node, Object data) {
127: try {
128: int pIndex = ((Integer) node.value).intValue() - 1;
129: if (pIndex >= paramTypes.length) {
130: throw new ParseException("Parameter ?" + (pIndex + 1)
131: + " is out of range (max=" + paramTypes.length
132: + ")");
133: }
134: // TODO : check if the associated parameter type is compatible to
135: // integer
136: ((Stack) data).push(new EjbqlLimiterRange(
137: EjbqlLimiterRange.KIND_PARAMETER, pIndex));
138: return null;
139: } catch (ParseException e) {
140: throw new VisitorException(e);
141: }
142: }
143:
144: }
|