EMMA Coverage Report (generated Sat Nov 03 21:53:04 GMT 2007)
[all classes][sf.qof.codegen]

COVERAGE SUMMARY FOR SOURCE FILE [CallQueryMethodGenerator.java]

nameclass, %method, %block, %line, %
CallQueryMethodGenerator.java100% (1/1)75%  (3/4)98%  (530/543)98%  (138/141)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class CallQueryMethodGenerator100% (1/1)75%  (3/4)98%  (530/543)98%  (138/141)
CallQueryMethodGenerator (): void 0%   (0/1)0%   (0/3)0%   (0/1)
addCallQueryBodyWithCollection (CodeEmitter, QueryObjectGenerator, Mapper): void 100% (1/1)97%  (380/390)98%  (100/102)
addCallQueryBody (CodeEmitter, QueryObjectGenerator, Mapper): void 100% (1/1)100% (15/15)100% (4/4)
addCallQueryBodyNoCollection (CodeEmitter, QueryObjectGenerator, Mapper): void 100% (1/1)100% (135/135)100% (34/34)

1/*
2 * Copyright 2007 brunella ltd
3 *
4 * Licensed under the LGPL Version 3 (the "License");
5 * you may not use this file except in compliance with the License.
6 *
7 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
8 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
9 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
10 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
11 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
12 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
13 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
14 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
15 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
16 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
17 * THE POSSIBILITY OF SUCH DAMAGE.
18 */
19package sf.qof.codegen;
20 
21import static sf.qof.codegen.Constants.EXCEPTION_COLLECTIONS_DIFFERENT_SIZE;
22import static sf.qof.codegen.Constants.FIELD_NAME_BATCH_SIZE;
23import static sf.qof.codegen.Constants.SIG_addBatch;
24import static sf.qof.codegen.Constants.SIG_execute;
25import static sf.qof.codegen.Constants.SIG_executeBatch;
26import static sf.qof.codegen.Constants.SIG_executeUpdate;
27import static sf.qof.codegen.Constants.SIG_getConnection;
28import static sf.qof.codegen.Constants.SIG_hasNext;
29import static sf.qof.codegen.Constants.SIG_iterator;
30import static sf.qof.codegen.Constants.SIG_iterator_next;
31import static sf.qof.codegen.Constants.SIG_prepareCall;
32import static sf.qof.codegen.Constants.SIG_size;
33import static sf.qof.codegen.Constants.TYPE_CallableStatement;
34import static sf.qof.codegen.Constants.TYPE_Collection;
35import static sf.qof.codegen.Constants.TYPE_Connection;
36import static sf.qof.codegen.Constants.TYPE_Iterator;
37import static sf.qof.codegen.Constants.TYPE_SQLException;
38import static sf.qof.codegen.Constants.TYPE_Throwable;
39import static sf.qof.codegen.Constants.TYPE_int;
40import net.sf.cglib.core.Block;
41import net.sf.cglib.core.CodeEmitter;
42import net.sf.cglib.core.Local;
43 
44import org.objectweb.asm.Label;
45import org.objectweb.asm.Type;
46 
47import sf.qof.exception.ValidationException;
48import sf.qof.mapping.Mapper;
49import sf.qof.mapping.MethodParameterInfo;
50 
51/**
52 * Internal - CallQueryMethodGenerator is the main generator class for call query methods.
53 */
54public class CallQueryMethodGenerator {
55 
56  public static void addCallQueryBody(CodeEmitter co, QueryObjectGenerator generator, Mapper mapper) {
57    if (mapper.getMethod().getCollectionParameterInfos().length > 0) {
58      addCallQueryBodyWithCollection(co, generator, mapper);
59    } else {
60      addCallQueryBodyNoCollection(co, generator, mapper);
61    }
62  }
63 
64  private static void addCallQueryBodyNoCollection(CodeEmitter co, QueryObjectGenerator generator, Mapper mapper) {
65    Local localCallableStatement = co.make_local(TYPE_CallableStatement);
66    Local localException = co.make_local(TYPE_Throwable);
67  
68    // ps = connection.prepareCall("{ ? = call xyz (?,?) }");
69    co.load_this();
70    co.invoke_virtual(Type.getType(generator.getClassNameType()), SIG_getConnection);
71    co.push(mapper.getSql());
72    co.invoke_interface(TYPE_Connection, SIG_prepareCall);
73    co.store_local(localCallableStatement);
74  
75    // try{
76    Block blockTry = co.begin_block();
77  
78    // set the parameters
79    ParameterMappingGenerator pmg = new ParameterMappingGenerator(co, localCallableStatement, null, null, null);
80    mapper.acceptParameterMappers(pmg);
81  
82    // register output parameters
83    OutputParameterRegistrationMappingGenerator omg = new OutputParameterRegistrationMappingGenerator(co, localCallableStatement);
84    mapper.acceptResultMappers(omg);
85  
86    // ps.execute();
87    co.load_local(localCallableStatement);
88    co.invoke_interface(TYPE_CallableStatement, SIG_execute);
89    co.pop(); // not interested in result
90  
91    Class<?> returnType = mapper.getMethod().getReturnInfo().getType();
92  
93    Local localResult = null;
94  
95    if (returnType != void.class) {
96      localResult = co.make_local(Type.getType(returnType));
97      if (!(mapper.getResults().size() == 1 && mapper.getResults().get(0).usesAtomic())) {
98        EmitUtils.createAndStoreNewResultObject(co, mapper, localCallableStatement, localResult);
99      }
100  
101      // --- get results
102      ResultMappingGenerator rmp = new ResultMappingGenerator(co, localCallableStatement, localResult, null, false, null);
103      mapper.acceptResultMappers(rmp);
104    }
105  
106    // finally block
107    EmitUtils.emitClose(co, localCallableStatement, false);
108  
109    // return result
110    if (localResult != null) {
111      co.load_local(localResult);
112    }
113    co.return_value();
114    // }
115  
116    // exception handler + finally
117    blockTry.end();
118    co.catch_exception(blockTry, TYPE_Throwable);
119    // store thrown exception
120    co.store_local(localException);
121    // finally block
122    EmitUtils.emitClose(co, localCallableStatement, false);
123    // throw stored exception
124    co.load_local(localException);
125    co.athrow();
126  }
127 
128  private static void addCallQueryBodyWithCollection(CodeEmitter co, QueryObjectGenerator generator, Mapper mapper) {
129    if (mapper.getResults() != null && mapper.getResults().size() > 0) {
130      throw new ValidationException("No results allowed for call with collection");
131    }
132  
133    // check for valid return type
134    Class<?> returnType = mapper.getMethod().getReturnInfo().getType();
135    if (returnType != Void.TYPE) {
136                    throw new ValidationException("Only void is allowed as return type");
137            }
138    MethodParameterInfo[] collectionParameterInfos = mapper.getMethod().getCollectionParameterInfos();
139    int numParameterCollections = collectionParameterInfos.length;
140  
141    // check for different sizes
142    if (numParameterCollections > 1) {
143      Label labelException = co.make_label();
144      Label labelNoException = co.make_label();
145  
146      for (int i = 0; i < numParameterCollections - 1; i++) {
147        co.load_arg(collectionParameterInfos[i].getIndex());
148        co.invoke_interface(TYPE_Collection, SIG_size);
149        co.load_arg(collectionParameterInfos[i + 1].getIndex());
150        co.invoke_interface(TYPE_Collection, SIG_size);
151        co.if_icmp(CodeEmitter.NE, labelException);
152      }
153      co.goTo(labelNoException);
154  
155      co.mark(labelException);
156      co.throw_exception(TYPE_SQLException, EXCEPTION_COLLECTIONS_DIFFERENT_SIZE);
157  
158      co.mark(labelNoException);
159    }
160  
161    // if (parameter.size() == 0) return;
162    co.load_arg(collectionParameterInfos[0].getIndex());
163    co.invoke_interface(TYPE_Collection, SIG_size);
164    Label labelNotZero = co.make_label();
165    co.if_jump(CodeEmitter.NE, labelNotZero);
166    co.return_value();
167    co.mark(labelNotZero);
168  
169    Local localCallableStatement = co.make_local(TYPE_CallableStatement);
170    Local localException = co.make_local(TYPE_Throwable);
171  
172    // ps = connection.prepareStatement("select count(*) from person");
173    co.load_this();
174    co.invoke_virtual(Type.getType(generator.getClassNameType()), SIG_getConnection);
175    co.push(mapper.getSql());
176    co.invoke_interface(TYPE_Connection, SIG_prepareCall);
177    co.store_local(localCallableStatement);
178  
179    // try{
180    Block blockTry = co.begin_block();
181  
182    // start the loop
183    // Iterator<Person> iter = list.iterator();
184    // int i = 0;
185    // while (iter.hasNext()) {
186    // Person person = iter.next();
187    // i++;
188    Local localCounter = co.make_local(TYPE_int);
189    co.push(0);
190    co.store_local(localCounter);
191    Local[] localIterators = new Local[numParameterCollections];
192    Local[] localObjects = new Local[numParameterCollections];
193    for (int i = 0; i < numParameterCollections; i++) {
194      localIterators[i] = co.make_local(TYPE_Iterator);
195      co.load_arg(collectionParameterInfos[i].getIndex());
196      co.invoke_interface(TYPE_Collection, SIG_iterator);
197      co.store_local(localIterators[i]);
198  
199      localObjects[i] = co.make_local(Type.getType(collectionParameterInfos[i].getCollectionElementType()));
200    }
201  
202    // while
203    Label labelBeginWhile = co.make_label();
204    Label labelEndWhile = co.make_label();
205    co.mark(labelBeginWhile);
206    co.load_local(localIterators[0]);
207    co.invoke_interface(TYPE_Iterator, SIG_hasNext);
208    co.if_jump(CodeEmitter.EQ, labelEndWhile);
209  
210    for (int i = 0; i < numParameterCollections; i++) {
211      co.load_local(localIterators[i]);
212      co.invoke_interface(TYPE_Iterator, SIG_iterator_next);
213      co.checkcast(Type.getType(collectionParameterInfos[i].getCollectionElementType()));
214      co.store_local(localObjects[i]);
215    }
216    co.iinc(localCounter, 1);
217  
218    ParameterMappingGenerator pmg = new ParameterMappingGenerator(co, localCallableStatement, localObjects,
219        collectionParameterInfos, null);
220    mapper.acceptParameterMappers(pmg);
221  
222    // if (batchSize > 0) {
223    // ps.addBatch();
224    // if (i >= batchSize) {
225    // ps.executeBatch();
226    // i = 0;
227    // }
228    // } else {
229    // ps.execute();
230    // }
231    co.load_this();
232    co.getfield(FIELD_NAME_BATCH_SIZE);
233    Label labelNoBatching = co.make_label();
234    co.if_jump(CodeEmitter.LE, labelNoBatching);
235  
236    co.load_local(localCallableStatement);
237    co.invoke_interface(TYPE_CallableStatement, SIG_addBatch);
238  
239    // if (i >= batchSize) {
240    // ps.executeBatch();
241    // i = 0;
242    // }
243    co.load_local(localCounter);
244    co.load_this();
245    co.getfield(FIELD_NAME_BATCH_SIZE);
246    Label labelAfter = co.make_label();
247    co.if_icmp(CodeEmitter.LT, labelAfter);
248  
249    co.load_local(localCallableStatement);
250    co.invoke_interface(TYPE_CallableStatement, SIG_executeBatch);
251    co.pop();
252    co.push(0);
253    co.store_local(localCounter);
254  
255    co.mark(labelAfter);
256  
257    co.goTo(labelBeginWhile);
258  
259    co.mark(labelNoBatching);
260  
261    co.load_local(localCallableStatement);
262    co.invoke_interface(TYPE_CallableStatement, SIG_executeUpdate);
263    co.pop();
264  
265    co.goTo(labelBeginWhile);
266  
267    co.mark(labelEndWhile);
268  
269    // if (batchSize > 0 && i > 0) {
270    // ps.executeBatch();
271    // }
272    Label labelAfter2 = co.make_label();
273    co.load_local(localCounter);
274    co.if_jump(CodeEmitter.LE, labelAfter2);
275    co.load_this();
276    co.getfield(FIELD_NAME_BATCH_SIZE);
277    co.if_jump(CodeEmitter.LE, labelAfter2);
278  
279    co.load_local(localCallableStatement);
280    co.invoke_interface(TYPE_CallableStatement, SIG_executeBatch);
281    co.pop();
282  
283    co.mark(labelAfter2);
284  
285    // finally block
286    EmitUtils.emitClose(co, localCallableStatement, false);
287  
288    // return result
289    co.return_value();
290    // }
291  
292    // exception handler + finally
293    blockTry.end();
294    co.catch_exception(blockTry, TYPE_Throwable);
295    // store thrown exception
296    co.store_local(localException);
297    // finally block
298    EmitUtils.emitClose(co, localCallableStatement, false);
299    // throw stored exception
300    co.load_local(localException);
301    co.athrow();
302  }
303 
304}

[all classes][sf.qof.codegen]
EMMA 2.0.5312 (C) Vladimir Roubtsov