KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectstyle > cayenne > access > trans > ProcedureTranslator


1 /* ====================================================================
2  *
3  * The ObjectStyle Group Software License, version 1.1
4  * ObjectStyle Group - http://objectstyle.org/
5  *
6  * Copyright (c) 2002-2005, Andrei (Andrus) Adamchik and individual authors
7  * of the software. All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  *
13  * 1. Redistributions of source code must retain the above copyright
14  * notice, this list of conditions and the following disclaimer.
15  *
16  * 2. Redistributions in binary form must reproduce the above copyright
17  * notice, this list of conditions and the following disclaimer in
18  * the documentation and/or other materials provided with the
19  * distribution.
20  *
21  * 3. The end-user documentation included with the redistribution, if any,
22  * must include the following acknowlegement:
23  * "This product includes software developed by independent contributors
24  * and hosted on ObjectStyle Group web site (http://objectstyle.org/)."
25  * Alternately, this acknowlegement may appear in the software itself,
26  * if and wherever such third-party acknowlegements normally appear.
27  *
28  * 4. The names "ObjectStyle Group" and "Cayenne" must not be used to endorse
29  * or promote products derived from this software without prior written
30  * permission. For written permission, email
31  * "andrus at objectstyle dot org".
32  *
33  * 5. Products derived from this software may not be called "ObjectStyle"
34  * or "Cayenne", nor may "ObjectStyle" or "Cayenne" appear in their
35  * names without prior written permission.
36  *
37  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
38  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
39  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
40  * DISCLAIMED. IN NO EVENT SHALL THE OBJECTSTYLE GROUP OR
41  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
42  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
43  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
44  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
45  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
46  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
47  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
48  * SUCH DAMAGE.
49  * ====================================================================
50  *
51  * This software consists of voluntary contributions made by many
52  * individuals and hosted on ObjectStyle Group web site. For more
53  * information on the ObjectStyle Group, please see
54  * <http://objectstyle.org/>.
55  */

56 package org.objectstyle.cayenne.access.trans;
57
58 import java.sql.CallableStatement JavaDoc;
59 import java.sql.PreparedStatement JavaDoc;
60 import java.util.ArrayList JavaDoc;
61 import java.util.Iterator JavaDoc;
62 import java.util.List JavaDoc;
63 import java.util.Map JavaDoc;
64
65 import org.apache.log4j.Level;
66 import org.objectstyle.cayenne.access.QueryLogger;
67 import org.objectstyle.cayenne.access.QueryTranslator;
68 import org.objectstyle.cayenne.map.Procedure;
69 import org.objectstyle.cayenne.map.ProcedureParameter;
70 import org.objectstyle.cayenne.query.ProcedureQuery;
71
72 /**
73  * Stored procedure query translator.
74  *
75  * @author Andrei Adamchik
76  */

77 public class ProcedureTranslator extends QueryTranslator {
78
79     /**
80      * Helper class to make OUT and VOID parameters logger-friendly.
81      */

82     static class NotInParam {
83
84         protected String JavaDoc type;
85
86         public NotInParam(String JavaDoc type) {
87             this.type = type;
88         }
89
90         public String JavaDoc toString() {
91             return type;
92         }
93     }
94
95     private static NotInParam OUT_PARAM = new NotInParam("[OUT]");
96
97     protected List JavaDoc callParams;
98     protected List JavaDoc values;
99
100     /**
101      * Creates an SQL String for the stored procedure call.
102      */

103     protected String JavaDoc createSqlString() {
104         Procedure procedure = getProcedure();
105
106         StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
107
108         int totalParams = callParams.size();
109
110         // check if procedure returns values
111
if (procedure.isReturningValue()) {
112             totalParams--;
113             buf.append("{? = call ");
114         }
115         else {
116             buf.append("{call ");
117         }
118
119         buf.append(procedure.getFullyQualifiedName());
120
121         if (totalParams > 0) {
122             // unroll the loop
123
buf.append("(?");
124
125             for (int i = 1; i < totalParams; i++) {
126                 buf.append(", ?");
127             }
128
129             buf.append(")");
130         }
131
132         buf.append("}");
133         return buf.toString();
134     }
135
136     public PreparedStatement JavaDoc createStatement(Level logLevel) throws Exception JavaDoc {
137         long t1 = System.currentTimeMillis();
138
139         this.callParams = getProcedure().getCallParameters();
140         this.values = new ArrayList JavaDoc(callParams.size());
141
142         initValues();
143         String JavaDoc sqlStr = createSqlString();
144
145         if (QueryLogger.isLoggable(logLevel)) {
146             // need to convert OUT/VOID parameters to loggable strings
147
long time = System.currentTimeMillis() - t1;
148
149             List JavaDoc loggableParameters = new ArrayList JavaDoc(values.size());
150             Iterator JavaDoc it = values.iterator();
151             while (it.hasNext()) {
152                 Object JavaDoc val = it.next();
153                 if (val instanceof NotInParam) {
154                     val = val.toString();
155                 }
156                 loggableParameters.add(val);
157             }
158
159             QueryLogger.logQuery(logLevel, sqlStr, loggableParameters, time);
160         }
161         CallableStatement JavaDoc stmt = connection.prepareCall(sqlStr);
162         initStatement(stmt);
163         return stmt;
164     }
165
166     public Procedure getProcedure() {
167         return getEntityResolver().lookupProcedure(query);
168     }
169
170     public ProcedureQuery getProcedureQuery() {
171         return (ProcedureQuery) query;
172     }
173
174     /**
175      * Returns a result descriptor for the stored procedure OUT parameters.
176      *
177      * @deprecated Since 1.2 is unused. Instead OUTParametersReader is created inside a
178      * SQLAction.
179      */

180     public org.objectstyle.cayenne.access.util.ResultDescriptor getProcedureResultDescriptor() {
181         return org.objectstyle.cayenne.access.util.ResultDescriptor.createDescriptor(
182                 getProcedure(),
183                 getAdapter().getExtendedTypes());
184     }
185
186     /**
187      * Set IN and OUT parameters.
188      */

189     protected void initStatement(CallableStatement JavaDoc stmt) throws Exception JavaDoc {
190         if (values != null && values.size() > 0) {
191             List JavaDoc params = getProcedure().getCallParameters();
192
193             int len = values.size();
194             for (int i = 0; i < len; i++) {
195                 ProcedureParameter param = (ProcedureParameter) params.get(i);
196
197                 // !Stored procedure parameter can be both in and out
198
// at the same time
199
if (param.isOutParam()) {
200                     setOutParam(stmt, param, i + 1);
201                 }
202
203                 if (param.isInParameter()) {
204                     setInParam(stmt, param, values.get(i), i + 1);
205                 }
206             }
207         }
208     }
209
210     protected void initValues() {
211         Map JavaDoc queryValues = getProcedureQuery().getParameters();
212
213         // match values with parameters in the correct order.
214
// make an assumption that a missing value is NULL
215
// Any reason why this is bad?
216

217         Iterator JavaDoc it = callParams.iterator();
218         while (it.hasNext()) {
219             ProcedureParameter param = (ProcedureParameter) it.next();
220
221             if (param.getDirection() == ProcedureParameter.OUT_PARAMETER) {
222                 values.add(OUT_PARAM);
223             }
224             else {
225                 values.add(queryValues.get(param.getName()));
226             }
227         }
228     }
229
230     /**
231      * Sets a single IN parameter of the CallableStatement.
232      */

233     protected void setInParam(
234             CallableStatement JavaDoc stmt,
235             ProcedureParameter param,
236             Object JavaDoc val,
237             int pos) throws Exception JavaDoc {
238
239         int type = param.getType();
240         adapter.bindParameter(stmt, val, pos, type, param.getPrecision());
241     }
242
243     /**
244      * Sets a single OUT parameter of the CallableStatement.
245      */

246     protected void setOutParam(CallableStatement JavaDoc stmt, ProcedureParameter param, int pos)
247             throws Exception JavaDoc {
248
249         int precision = param.getPrecision();
250         if (precision >= 0) {
251             stmt.registerOutParameter(pos, param.getType(), precision);
252         }
253         else {
254             stmt.registerOutParameter(pos, param.getType());
255         }
256     }
257 }
Popular Tags