001: package org.gomba;
002:
003: import java.util.ArrayList;
004: import java.util.Enumeration;
005: import java.util.List;
006: import java.util.Vector;
007:
008: /**
009: * Defines a JDBC query. The definition contains a SQL query with question
010: * marks, the parameter definitions corresponding to the question marks, and
011: * skip max expression. This class is used together with <code>Query</code>.
012: *
013: * @author Flavio Tordini
014: * @version $Id: QueryDefinition.java,v 1.2 2004/09/16 09:23:16 flaviotordini Exp $
015: */
016: class QueryDefinition {
017:
018: /**
019: * SQL query possibly containing question marks for a JDBC PreparedStatement
020: */
021: private final String SQLQuery;
022:
023: /**
024: * Parameters in the same order as they appear in the query. List of
025: * <code>ParameterDefinition</code>.
026: */
027: private List parameters;
028:
029: /**
030: * The parsed skip expression, if any,
031: */
032: private Expression skipExpression;
033:
034: /**
035: * The parsed max expression, if any,
036: */
037: private Expression maxExpression;
038:
039: /**
040: * Constructor.
041: */
042: public QueryDefinition(String queryDefinition, String skip,
043: String max) throws Exception {
044:
045: this .SQLQuery = parseQueryDefinition(queryDefinition);
046:
047: if (skip != null) {
048: this .skipExpression = new Expression(skip);
049: }
050:
051: if (max != null) {
052: this .maxExpression = new Expression(max);
053: }
054:
055: }
056:
057: /**
058: * Constructor.
059: */
060: public QueryDefinition(String queryDefinition, Expression skip,
061: Expression max) throws Exception {
062: this .SQLQuery = parseQueryDefinition(queryDefinition);
063:
064: if (skip != null) {
065: this .skipExpression = skip;
066: }
067:
068: if (max != null) {
069: this .maxExpression = max;
070: }
071:
072: }
073:
074: /**
075: * Constructor.
076: */
077: public QueryDefinition(String queryDefinition) throws Exception {
078: this .SQLQuery = parseQueryDefinition(queryDefinition);
079: }
080:
081: /**
082: * Replaces <code>${domain.paramName:JavaType}</code> expressions in the
083: * given query definition with the question marks and populates the
084: * <code>parameters</code> list.
085: *
086: * @param queryDefinition
087: * The string to be scanned for parameter references.
088: *
089: * @exception Exception
090: * if the string contains an opening <code>${</code>
091: * without a closing <code>}</code>
092: * @return the original string with the properties replaced by question
093: * marks
094: */
095: private String parseQueryDefinition(String queryDefinition)
096: throws Exception {
097: if (queryDefinition == null) {
098: throw new IllegalArgumentException(
099: "Query definition cannot be null.");
100: }
101:
102: Vector fragments = new Vector();
103: Vector parameterRefs = new Vector();
104: Expression.parseParameters(queryDefinition, fragments,
105: parameterRefs);
106:
107: StringBuffer sb = new StringBuffer();
108: Enumeration i = fragments.elements();
109: Enumeration j = parameterRefs.elements();
110:
111: this .parameters = new ArrayList(parameterRefs.size());
112:
113: while (i.hasMoreElements()) {
114: String fragment = (String) i.nextElement();
115: if (fragment == null) {
116:
117: ParameterDefinition parameterDefinition = (ParameterDefinition) j
118: .nextElement();
119: if (parameterDefinition == null) {
120: throw new Exception(
121: "Can't happen! parameter definition is null.");
122: }
123: this .parameters.add(parameterDefinition);
124:
125: // PreparedStatement parameter
126: sb.append('?');
127: } else {
128: sb.append(fragment);
129: }
130:
131: }
132:
133: // paranoia: make parameters immutable
134: // parameters = Collections.unmodifiableList(parameters);
135:
136: return sb.toString();
137: }
138:
139: /**
140: * @return Returns the SQL query containing question marks for the
141: * PreparedStatement parameters.
142: */
143: public String getSQLQuery() {
144: return this .SQLQuery;
145: }
146:
147: /**
148: * @return Returns the parameters.
149: */
150: public List getParameters() {
151: return this .parameters;
152: }
153:
154: /**
155: * @return Returns the maxExpression, if any.
156: */
157: public Expression getMaxExpression() {
158: return this .maxExpression;
159: }
160:
161: /**
162: * @return Returns the skipExpression, if any.
163: */
164: public Expression getSkipExpression() {
165: return this.skipExpression;
166: }
167: }
|