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

COVERAGE SUMMARY FOR SOURCE FILE [ParameterMappingGenerator.java]

nameclass, %method, %block, %line, %
ParameterMappingGenerator.java100% (1/1)100% (21/21)98%  (1439/1475)99%  (325/329)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class ParameterMappingGenerator100% (1/1)100% (21/21)98%  (1439/1475)99%  (325/329)
findIndex (int): int 100% (1/1)77%  (17/22)75%  (3/4)
visit (Mapper, AdapterMapping): void 100% (1/1)91%  (301/332)95%  (62/65)
ParameterMappingGenerator (CodeEmitter, Local, Local [], MethodParameterInfo ... 100% (1/1)100% (38/38)100% (10/10)
generateParameterMapping (AbstractDateTimeMapping, Type, Signature, int): void 100% (1/1)100% (259/259)100% (58/58)
generateParameterMapping (ParameterMapping, Type, Type, Signature, Signature,... 100% (1/1)100% (265/265)100% (61/61)
loadValue (int, Method, boolean): void 100% (1/1)100% (27/27)100% (6/6)
visit (Mapper, AbstractCharacterMapping$CharacterMapping): void 100% (1/1)100% (278/278)100% (63/63)
visit (Mapper, AbstractCharacterMapping$StringMapping): void 100% (1/1)100% (155/155)100% (36/36)
visit (Mapper, AbstractCharacterMapping): void 100% (1/1)100% (5/5)100% (2/2)
visit (Mapper, AbstractDateTimeMapping$DateMapping): void 100% (1/1)100% (7/7)100% (2/2)
visit (Mapper, AbstractDateTimeMapping$TimeMapping): void 100% (1/1)100% (7/7)100% (2/2)
visit (Mapper, AbstractDateTimeMapping$TimestampMapping): void 100% (1/1)100% (7/7)100% (2/2)
visit (Mapper, AbstractDateTimeMapping): void 100% (1/1)100% (5/5)100% (2/2)
visit (Mapper, AbstractNumberMapping$BooleanMapping): void 100% (1/1)100% (9/9)100% (2/2)
visit (Mapper, AbstractNumberMapping$ByteMapping): void 100% (1/1)100% (9/9)100% (2/2)
visit (Mapper, AbstractNumberMapping$DoubleMapping): void 100% (1/1)100% (9/9)100% (2/2)
visit (Mapper, AbstractNumberMapping$FloatMapping): void 100% (1/1)100% (9/9)100% (2/2)
visit (Mapper, AbstractNumberMapping$IntegerMapping): void 100% (1/1)100% (9/9)100% (2/2)
visit (Mapper, AbstractNumberMapping$LongMapping): void 100% (1/1)100% (9/9)100% (2/2)
visit (Mapper, AbstractNumberMapping$ShortMapping): void 100% (1/1)100% (9/9)100% (2/2)
visit (Mapper, AbstractNumberMapping): void 100% (1/1)100% (5/5)100% (2/2)

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.SIG_booleanValue;
22import static sf.qof.codegen.Constants.SIG_byteValue;
23import static sf.qof.codegen.Constants.SIG_doubleValue;
24import static sf.qof.codegen.Constants.SIG_floatValue;
25import static sf.qof.codegen.Constants.SIG_getTimeLong;
26import static sf.qof.codegen.Constants.SIG_intValue;
27import static sf.qof.codegen.Constants.SIG_longValue;
28import static sf.qof.codegen.Constants.SIG_setBoolean;
29import static sf.qof.codegen.Constants.SIG_setByte;
30import static sf.qof.codegen.Constants.SIG_setDate;
31import static sf.qof.codegen.Constants.SIG_setDouble;
32import static sf.qof.codegen.Constants.SIG_setFloat;
33import static sf.qof.codegen.Constants.SIG_setInt;
34import static sf.qof.codegen.Constants.SIG_setLong;
35import static sf.qof.codegen.Constants.SIG_setNull;
36import static sf.qof.codegen.Constants.SIG_setShort;
37import static sf.qof.codegen.Constants.SIG_setString;
38import static sf.qof.codegen.Constants.SIG_setTime;
39import static sf.qof.codegen.Constants.SIG_setTimestamp;
40import static sf.qof.codegen.Constants.SIG_shortValue;
41import static sf.qof.codegen.Constants.TYPE_Boolean;
42import static sf.qof.codegen.Constants.TYPE_Byte;
43import static sf.qof.codegen.Constants.TYPE_Character;
44import static sf.qof.codegen.Constants.TYPE_Date;
45import static sf.qof.codegen.Constants.TYPE_Double;
46import static sf.qof.codegen.Constants.TYPE_Float;
47import static sf.qof.codegen.Constants.TYPE_Integer;
48import static sf.qof.codegen.Constants.TYPE_Long;
49import static sf.qof.codegen.Constants.TYPE_Short;
50import static sf.qof.codegen.Constants.TYPE_String;
51import static sf.qof.codegen.Constants.TYPE_boolean;
52import static sf.qof.codegen.Constants.TYPE_byte;
53import static sf.qof.codegen.Constants.TYPE_char;
54import static sf.qof.codegen.Constants.TYPE_double;
55import static sf.qof.codegen.Constants.TYPE_float;
56import static sf.qof.codegen.Constants.TYPE_int;
57import static sf.qof.codegen.Constants.TYPE_long;
58import static sf.qof.codegen.Constants.TYPE_short;
59import static sf.qof.codegen.Constants.TYPE_sqlDate;
60import static sf.qof.codegen.Constants.TYPE_sqlTime;
61import static sf.qof.codegen.Constants.TYPE_sqlTimestamp;
62 
63import java.lang.reflect.Method;
64 
65import net.sf.cglib.core.CodeEmitter;
66import net.sf.cglib.core.Local;
67import net.sf.cglib.core.Signature;
68 
69import org.objectweb.asm.Label;
70import org.objectweb.asm.Type;
71 
72import sf.qof.adapter.DynamicMappingAdapter;
73import sf.qof.adapter.GeneratorMappingAdapter;
74import sf.qof.mapping.AbstractCharacterMapping;
75import sf.qof.mapping.AbstractDateTimeMapping;
76import sf.qof.mapping.AbstractNumberMapping;
77import sf.qof.mapping.AdapterMapping;
78import sf.qof.mapping.CharacterMappingVisitor;
79import sf.qof.mapping.DateTimeMappingVisitor;
80import sf.qof.mapping.Mapper;
81import sf.qof.mapping.MappingVisitor;
82import sf.qof.mapping.MethodParameterInfo;
83import sf.qof.mapping.NumberMappingVisitor;
84import sf.qof.mapping.ParameterMapping;
85import sf.qof.mapping.AbstractCharacterMapping.CharacterMapping;
86import sf.qof.mapping.AbstractCharacterMapping.StringMapping;
87import sf.qof.mapping.AbstractDateTimeMapping.DateMapping;
88import sf.qof.mapping.AbstractDateTimeMapping.TimeMapping;
89import sf.qof.mapping.AbstractDateTimeMapping.TimestampMapping;
90import sf.qof.mapping.AbstractNumberMapping.BooleanMapping;
91import sf.qof.mapping.AbstractNumberMapping.ByteMapping;
92import sf.qof.mapping.AbstractNumberMapping.DoubleMapping;
93import sf.qof.mapping.AbstractNumberMapping.FloatMapping;
94import sf.qof.mapping.AbstractNumberMapping.IntegerMapping;
95import sf.qof.mapping.AbstractNumberMapping.LongMapping;
96import sf.qof.mapping.AbstractNumberMapping.ShortMapping;
97import sf.qof.util.ReflectionUtils;
98 
99/**
100 * Internal - ParameterMappingGenerator is the generator class for parameter mappings. 
101 */
102public class ParameterMappingGenerator implements MappingVisitor, NumberMappingVisitor, CharacterMappingVisitor,
103    DateTimeMappingVisitor {
104 
105  private CodeEmitter co;
106  private Local preparedStatement;
107  private Local[] currentCollectionObj;
108  private int[] collectionIndexes;
109  private Local parameterIndexOffset;
110 
111  public ParameterMappingGenerator(CodeEmitter co, Local statement, Local[] currentCollectionObjs,
112      MethodParameterInfo[] parameterInfos, Local parameterIndexOffset) {
113    this.co = co;
114    this.preparedStatement = statement;
115    this.currentCollectionObj = currentCollectionObjs;
116    this.parameterIndexOffset = parameterIndexOffset;
117    if (parameterInfos != null) {
118      collectionIndexes = new int[parameterInfos.length];
119      for (int i = 0; i < parameterInfos.length; i++) {
120        collectionIndexes[i] = parameterInfos[i].getIndex();
121      }
122    }
123  }
124 
125  private void loadValue(int argIndex, Method getter, boolean usesCollection) {
126    // if (currentCollectionObj == null) {
127    if (!usesCollection) {
128      // load value from a method parameter
129      co.load_arg(argIndex);
130    } else {
131      // load value from the current object of the iterator
132      co.load_local(currentCollectionObj[findIndex(argIndex)]);
133      // co.checkcast(Type.getType(getter.getDeclaringClass()));
134    }
135    // invoke the getter
136    if (getter != null) {
137      co.invoke_virtual(Type.getType(getter.getDeclaringClass()), ReflectionUtils.getMethodSignature(getter));
138    }
139  }
140 
141  private int findIndex(int argIndex) {
142    for (int i = 0; i < collectionIndexes.length; i++) {
143      if (collectionIndexes[i] == argIndex) {
144        return i;
145      }
146    }
147    throw new RuntimeException("Inconsistent state");
148  }
149 
150  // implementation of MappingVisitor
151 
152  public final void visit(Mapper mapper, AbstractNumberMapping mapping) {
153    mapping.accept(mapper, (NumberMappingVisitor) this);
154  }
155 
156  public final void visit(Mapper mapper, AbstractCharacterMapping mapping) {
157    mapping.accept(mapper, (CharacterMappingVisitor) this);
158  }
159 
160  public final void visit(Mapper mapper, AbstractDateTimeMapping mapping) {
161    mapping.accept(mapper, (DateTimeMappingVisitor) this);
162  }
163 
164  // implementation of NumberMappingVisitor
165 
166  public void visit(Mapper mapper, ByteMapping mapping) {
167    generateParameterMapping(mapping, TYPE_Byte, TYPE_byte, SIG_byteValue, SIG_setByte, java.sql.Types.TINYINT);
168  }
169 
170  public void visit(Mapper mapper, ShortMapping mapping) {
171    generateParameterMapping(mapping, TYPE_Short, TYPE_short, SIG_shortValue, SIG_setShort, java.sql.Types.SMALLINT);
172  }
173 
174  public void visit(Mapper mapper, IntegerMapping mapping) {
175    generateParameterMapping(mapping, TYPE_Integer, TYPE_int, SIG_intValue, SIG_setInt, java.sql.Types.INTEGER);
176  }
177 
178  public void visit(Mapper mapper, LongMapping mapping) {
179    generateParameterMapping(mapping, TYPE_Long, TYPE_long, SIG_longValue, SIG_setLong, java.sql.Types.BIGINT);
180  }
181 
182  public void visit(Mapper mapper, FloatMapping mapping) {
183    generateParameterMapping(mapping, TYPE_Float, TYPE_float, SIG_floatValue, SIG_setFloat, java.sql.Types.REAL);
184  }
185 
186  public void visit(Mapper mapper, DoubleMapping mapping) {
187    generateParameterMapping(mapping, TYPE_Double, TYPE_double, SIG_doubleValue, SIG_setDouble, java.sql.Types.DOUBLE);
188  }
189 
190  public void visit(Mapper mapper, BooleanMapping mapping) {
191    generateParameterMapping(mapping, TYPE_Boolean, TYPE_boolean, SIG_booleanValue, SIG_setBoolean, java.sql.Types.BOOLEAN);
192  }
193 
194  private void generateParameterMapping(ParameterMapping mapping, Type boxedType, Type unboxedType, 
195      Signature signatureUnbox, Signature signatureSet, int sqlType) {
196    int argIndex = mapping.getIndex();
197    int sqlIndex = mapping.getSqlIndexes()[0];
198    Method getter = mapping.getGetter();
199    Class<?> objectType = mapping.getType();
200 
201    if (mapping.usesArray()) {
202      Local localIndex = co.make_local(TYPE_int);
203      co.push(0);
204      co.store_local(localIndex);
205      Label labelLoopTest = co.make_label();
206      co.goTo(labelLoopTest);
207      Label labelLoopStart = co.make_label();
208      co.mark(labelLoopStart);
209      
210      co.load_local(preparedStatement);
211      co.push(sqlIndex);
212      co.load_local(parameterIndexOffset);
213      co.math(CodeEmitter.ADD, TYPE_int);
214      co.load_arg(argIndex);
215      co.load_local(localIndex);
216      if (objectType.isPrimitive()) {
217        co.array_load(unboxedType);
218      } else {
219        // should we check null values?
220        co.array_load(boxedType);
221        co.invoke_virtual(boxedType, signatureUnbox);
222      }
223      
224      co.invoke_interface(preparedStatement.getType(), signatureSet);
225      
226      co.iinc(parameterIndexOffset, 1);
227      
228      co.iinc(localIndex, 1);
229      co.mark(labelLoopTest);
230      co.load_local(localIndex);
231      co.load_arg(argIndex);
232      co.arraylength();
233      co.if_icmp(CodeEmitter.LT, labelLoopStart);
234      
235      co.iinc(parameterIndexOffset, -1);
236      
237    } else {
238 
239      if (!objectType.isPrimitive()) {
240        // it's an Integer
241        Label lIsNull = co.make_label();
242        Label lEnd = co.make_label();
243        // if (value != null) ps.setInt(index, value.intValue);
244        loadValue(argIndex, getter, mapping.usesCollection());
245        co.ifnull(lIsNull);
246        co.load_local(preparedStatement);
247        co.push(sqlIndex);
248        if (parameterIndexOffset != null) {
249                co.load_local(parameterIndexOffset);
250                co.math(CodeEmitter.ADD, TYPE_int);
251        }
252        loadValue(argIndex, getter, mapping.usesCollection());
253        co.invoke_virtual(boxedType, signatureUnbox);
254        co.invoke_interface(preparedStatement.getType(), signatureSet);
255        co.goTo(lEnd);
256        // else ps.setNull(index, java.sql.Type.NUMERIC);
257        co.mark(lIsNull);
258        co.load_local(preparedStatement);
259        co.push(sqlIndex);
260        // co.push(java.sql.Types.NUMERIC);
261        co.push(sqlType);
262        co.invoke_interface(preparedStatement.getType(), SIG_setNull);
263  
264        co.mark(lEnd);
265  
266      } else {
267        // it's an int
268        // setInt(index, value);
269        co.load_local(preparedStatement);
270        co.push(sqlIndex);
271        if (parameterIndexOffset != null) {
272                co.load_local(parameterIndexOffset);
273                co.math(CodeEmitter.ADD, TYPE_int);
274        }
275        loadValue(argIndex, getter, mapping.usesCollection());
276        co.invoke_interface(preparedStatement.getType(), signatureSet);
277      }
278    }
279  }
280 
281  // implementation of CharacterMappingVisitor
282 
283  public final void visit(Mapper mapper, StringMapping mapping) {
284    int argIndex = mapping.getIndex();
285    int sqlIndex = mapping.getSqlIndexes()[0];
286    Method getter = mapping.getGetter();
287 
288    if (mapping.usesArray()) {
289      Local localIndex = co.make_local(TYPE_int);
290      co.push(0);
291      co.store_local(localIndex);
292      Label labelLoopTest = co.make_label();
293      co.goTo(labelLoopTest);
294      Label labelLoopStart = co.make_label();
295      co.mark(labelLoopStart);
296      
297      co.load_local(preparedStatement);
298      co.push(sqlIndex);
299      co.load_local(parameterIndexOffset);
300      co.math(CodeEmitter.ADD, TYPE_int);
301      co.load_arg(argIndex);
302      co.load_local(localIndex);
303      co.array_load(TYPE_String);
304      
305      co.invoke_interface(preparedStatement.getType(), SIG_setString);
306      
307      co.iinc(parameterIndexOffset, 1);
308      
309      co.iinc(localIndex, 1);
310      co.mark(labelLoopTest);
311      co.load_local(localIndex);
312      co.load_arg(argIndex);
313      co.arraylength();
314      co.if_icmp(CodeEmitter.LT, labelLoopStart);
315      
316      co.iinc(parameterIndexOffset, -1);
317      
318    } else {
319      // setString(index, value);
320      co.load_local(preparedStatement);
321      co.push(sqlIndex);
322      if (parameterIndexOffset != null) {
323        co.load_local(parameterIndexOffset);
324                    co.math(CodeEmitter.ADD, TYPE_int);
325      }
326      loadValue(argIndex, getter, mapping.usesCollection());
327      co.invoke_interface(preparedStatement.getType(), SIG_setString);
328    }
329  }
330 
331  public final void visit(Mapper mapper, CharacterMapping mapping) {
332    int argIndex = mapping.getIndex();
333    int sqlIndex = mapping.getSqlIndexes()[0];
334    Method getter = mapping.getGetter();
335    Class<?> objectType = mapping.getType();
336 
337    if (mapping.usesArray()) {
338      Local localIndex = co.make_local(TYPE_int);
339      co.push(0);
340      co.store_local(localIndex);
341      Label labelLoopTest = co.make_label();
342      co.goTo(labelLoopTest);
343      Label labelLoopStart = co.make_label();
344      co.mark(labelLoopStart);
345      
346      co.load_local(preparedStatement);
347      co.push(sqlIndex);
348      co.load_local(parameterIndexOffset);
349      co.math(CodeEmitter.ADD, TYPE_int);
350      co.load_arg(argIndex);
351      co.load_local(localIndex);
352      
353      if (objectType.isPrimitive()) {
354        // it's a char
355        // Character.toString(char)
356        co.array_load(TYPE_char);
357        co.invoke_static(TYPE_Character, new Signature("toString", "(C)Ljava/lang/String;"));
358      } else {
359        // it's a Character
360        co.array_load(TYPE_Character);
361        co.dup();
362        Label labelEnd = co.make_label();
363        Label labelNull = co.make_label();
364        co.ifnull(labelNull);
365        co.invoke_virtual(TYPE_Character, new Signature("toString", "()Ljava/lang/String;"));
366        co.goTo(labelEnd);
367        co.mark(labelNull);
368        co.pop();
369        co.aconst_null();
370        co.mark(labelEnd);
371      }
372      co.invoke_interface(preparedStatement.getType(), SIG_setString);
373      
374      co.iinc(parameterIndexOffset, 1);
375      
376      co.iinc(localIndex, 1);
377      co.mark(labelLoopTest);
378      co.load_local(localIndex);
379      co.load_arg(argIndex);
380      co.arraylength();
381      co.if_icmp(CodeEmitter.LT, labelLoopStart);
382      
383      co.iinc(parameterIndexOffset, -1);
384      
385    } else {
386      // setString(index, value);
387      co.load_local(preparedStatement);
388      co.push(sqlIndex);
389      if (parameterIndexOffset != null) {
390        co.load_local(parameterIndexOffset);
391              co.math(CodeEmitter.ADD, TYPE_int);
392      }
393      if (objectType.isPrimitive()) {
394        // it's a char
395        // Character.toString(char)
396        loadValue(argIndex, getter, mapping.usesCollection());
397        co.invoke_static(TYPE_Character, new Signature("toString", "(C)Ljava/lang/String;"));
398      } else {
399        // it's a Character
400        loadValue(argIndex, getter, mapping.usesCollection());
401        co.dup();
402        Label labelEnd = co.make_label();
403        Label labelNull = co.make_label();
404        co.ifnull(labelNull);
405        co.invoke_virtual(TYPE_Character, new Signature("toString", "()Ljava/lang/String;"));
406        co.goTo(labelEnd);
407        co.mark(labelNull);
408        co.pop();
409        co.aconst_null();
410        co.mark(labelEnd);
411      }
412      co.invoke_interface(preparedStatement.getType(), SIG_setString);
413    }
414  }
415 
416  // implementation of DateTimeVisitor
417 
418  public void visit(Mapper mapper, DateMapping mapping) {
419    generateParameterMapping(mapping, TYPE_sqlDate, SIG_setDate, java.sql.Types.DATE);
420  }
421 
422  public void visit(Mapper mapper, TimeMapping mapping) {
423    generateParameterMapping(mapping, TYPE_sqlTime, SIG_setTime, java.sql.Types.TIME);
424  }
425 
426  public void visit(Mapper mapper, TimestampMapping mapping) {
427    generateParameterMapping(mapping, TYPE_sqlTimestamp, SIG_setTimestamp, java.sql.Types.TIMESTAMP);
428  }
429 
430  public final void generateParameterMapping(AbstractDateTimeMapping mapping, Type sqlType, Signature sqlTypeSet,
431      int sqlTypeCode) {
432    int argIndex = mapping.getIndex();
433    int sqlIndex = mapping.getSqlIndexes()[0];
434    Method getter = mapping.getGetter();
435 
436    if (mapping.usesArray()) {
437      Local localIndex = co.make_local(TYPE_int);
438      co.push(0);
439      co.store_local(localIndex);
440      Label labelLoopTest = co.make_label();
441      co.goTo(labelLoopTest);
442      Label labelLoopStart = co.make_label();
443      co.mark(labelLoopStart);
444      
445      co.load_local(preparedStatement);
446      co.push(sqlIndex);
447      co.load_local(parameterIndexOffset);
448      co.math(CodeEmitter.ADD, TYPE_int);
449      
450      co.new_instance(sqlType);
451      co.dup();
452 
453      co.load_arg(argIndex);
454      co.load_local(localIndex);
455      co.aaload();
456      
457      co.invoke_virtual(TYPE_Date, SIG_getTimeLong);
458      co.invoke_constructor(sqlType, new Signature("<init>", "(J)V"));
459      co.invoke_interface(preparedStatement.getType(), sqlTypeSet);
460      
461      co.iinc(parameterIndexOffset, 1);
462      
463      co.iinc(localIndex, 1);
464      co.mark(labelLoopTest);
465      co.load_local(localIndex);
466      co.load_arg(argIndex);
467      co.arraylength();
468      co.if_icmp(CodeEmitter.LT, labelLoopStart);
469      
470      co.iinc(parameterIndexOffset, -1);
471      
472    } else {
473 
474      Label lIsNull = co.make_label();
475      Label lEnd = co.make_label();
476      // if (value != null) setDate(index, new java.sql.Date(value.getTime()));
477      loadValue(argIndex, getter, mapping.usesCollection());
478      co.ifnull(lIsNull);
479      co.load_local(preparedStatement);
480      co.push(sqlIndex);
481      if (parameterIndexOffset != null) {
482        co.load_local(parameterIndexOffset);
483              co.math(CodeEmitter.ADD, TYPE_int);
484      }
485      co.new_instance(sqlType);
486      co.dup();
487      loadValue(argIndex, getter, mapping.usesCollection());
488      co.invoke_virtual(TYPE_Date, SIG_getTimeLong);
489      co.invoke_constructor(sqlType, new Signature("<init>", "(J)V"));
490      co.invoke_interface(preparedStatement.getType(), sqlTypeSet);
491      co.goTo(lEnd);
492      // else ps.setNull(index, java.sql.Type.DATE);
493      co.mark(lIsNull);
494      co.load_local(preparedStatement);
495      co.push(sqlIndex);
496      if (parameterIndexOffset != null) {
497        co.load_local(parameterIndexOffset);
498              co.math(CodeEmitter.ADD, TYPE_int);
499      }
500      co.push(sqlTypeCode);
501      co.invoke_interface(preparedStatement.getType(), SIG_setNull);
502  
503      co.mark(lEnd);
504    }
505  }
506 
507  public final void visit(Mapper mapper, AdapterMapping mapping) {
508    int argIndex = mapping.getIndex();
509    int[] sqlIndexes = mapping.getSqlIndexes();
510    Method getter = mapping.getGetter();
511 
512    if (mapping.usesArray()) {
513      if (mapping.getAdapter().getNumberOfColumns() != 1) {
514        throw new RuntimeException("Only adapters for one column can be used for in-clauses");
515      }
516      
517      Local localIndex = co.make_local(TYPE_int);
518      co.push(0);
519      co.store_local(localIndex);
520      Label labelLoopTest = co.make_label();
521      co.goTo(labelLoopTest);
522      Label labelLoopStart = co.make_label();
523      co.mark(labelLoopStart);
524      
525      if (mapping.getAdapter() instanceof GeneratorMappingAdapter) {
526        // load the argument on top of the stack
527        co.load_arg(argIndex);
528        co.load_local(localIndex);
529        co.aaload();
530        ((GeneratorMappingAdapter) mapping.getAdapter()).generateToPreparedStatement(
531            mapping, co, preparedStatement, sqlIndexes, parameterIndexOffset);
532      } else if (mapping.getAdapter() instanceof DynamicMappingAdapter) {
533        co.getfield(QueryObjectGenerator.getAdapterFieldName(mapping.getAdapter().getClass()));
534        // set(PreparedStatement ps, Object value, int[] indexes)
535        co.load_local(preparedStatement);
536        co.load_arg(argIndex);
537        co.load_local(localIndex);
538        co.aaload();
539        // new int[] {...}
540        co.push(sqlIndexes.length);
541        co.newarray(TYPE_int);
542        for (int i = 0; i < sqlIndexes.length; i++) {
543          co.dup();
544          co.push(i);
545          co.push(sqlIndexes[i]);
546          if (parameterIndexOffset != null) {
547            co.load_local(parameterIndexOffset);
548            co.math(CodeEmitter.ADD, TYPE_int);
549          }
550          co.array_store(TYPE_int);
551        }
552        co.invoke_interface(Type.getType(DynamicMappingAdapter.class), 
553            new Signature("set", "(Ljava/sql/PreparedStatement;Ljava/lang/Object;[I)V"));
554      } else {
555        throw new RuntimeException("Unsupported adapter type " + mapping.getAdapter());
556      }
557 
558      co.iinc(parameterIndexOffset, 1);
559      
560      co.iinc(localIndex, 1);
561      co.mark(labelLoopTest);
562      co.load_local(localIndex);
563      co.load_arg(argIndex);
564      co.arraylength();
565      co.if_icmp(CodeEmitter.LT, labelLoopStart);
566      
567      co.iinc(parameterIndexOffset, -1);
568      
569    } else {
570      if (mapping.getAdapter() instanceof GeneratorMappingAdapter) {
571        loadValue(argIndex, getter, mapping.usesCollection());
572        ((GeneratorMappingAdapter) mapping.getAdapter()).generateToPreparedStatement(
573            mapping, co, preparedStatement, sqlIndexes, parameterIndexOffset);
574  
575      } else if (mapping.getAdapter() instanceof DynamicMappingAdapter) {
576        co.getfield(QueryObjectGenerator.getAdapterFieldName(mapping.getAdapter().getClass()));
577        // set(PreparedStatement ps, Object value, int[] indexes)
578        co.load_local(preparedStatement);
579        loadValue(argIndex, getter, mapping.usesCollection());
580        // new int[] {...}
581        co.push(sqlIndexes.length);
582        co.newarray(TYPE_int);
583        for (int i = 0; i < sqlIndexes.length; i++) {
584          co.dup();
585          co.push(i);
586          co.push(sqlIndexes[i]);
587          if (parameterIndexOffset != null) {
588            co.load_local(parameterIndexOffset);
589                  co.math(CodeEmitter.ADD, TYPE_int);
590          }
591          co.array_store(TYPE_int);
592        }
593        co.invoke_interface(Type.getType(DynamicMappingAdapter.class), 
594            new Signature("set", "(Ljava/sql/PreparedStatement;Ljava/lang/Object;[I)V"));
595      } else {
596        throw new RuntimeException("Unsupported adapter type " + mapping.getAdapter());
597      }
598    }
599  }
600 
601}

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