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 | */ |
19 | package sf.qof.codegen; |
20 | |
21 | import static sf.qof.codegen.Constants.SIG_registerOutParameter; |
22 | import static sf.qof.codegen.Constants.TYPE_CallableStatement; |
23 | import static sf.qof.codegen.Constants.TYPE_int; |
24 | import net.sf.cglib.core.CodeEmitter; |
25 | import net.sf.cglib.core.Local; |
26 | import net.sf.cglib.core.Signature; |
27 | |
28 | import org.objectweb.asm.Type; |
29 | |
30 | import sf.qof.adapter.DynamicMappingAdapter; |
31 | import sf.qof.adapter.GeneratorMappingAdapter; |
32 | import sf.qof.mapping.AbstractCharacterMapping; |
33 | import sf.qof.mapping.AbstractDateTimeMapping; |
34 | import sf.qof.mapping.AbstractNumberMapping; |
35 | import sf.qof.mapping.AdapterMapping; |
36 | import sf.qof.mapping.CharacterMappingVisitor; |
37 | import sf.qof.mapping.DateTimeMappingVisitor; |
38 | import sf.qof.mapping.Mapper; |
39 | import sf.qof.mapping.MappingVisitor; |
40 | import sf.qof.mapping.NumberMappingVisitor; |
41 | import sf.qof.mapping.ResultMapping; |
42 | import sf.qof.mapping.AbstractCharacterMapping.CharacterMapping; |
43 | import sf.qof.mapping.AbstractCharacterMapping.StringMapping; |
44 | import sf.qof.mapping.AbstractDateTimeMapping.DateMapping; |
45 | import sf.qof.mapping.AbstractDateTimeMapping.TimeMapping; |
46 | import sf.qof.mapping.AbstractDateTimeMapping.TimestampMapping; |
47 | import sf.qof.mapping.AbstractNumberMapping.BooleanMapping; |
48 | import sf.qof.mapping.AbstractNumberMapping.ByteMapping; |
49 | import sf.qof.mapping.AbstractNumberMapping.DoubleMapping; |
50 | import sf.qof.mapping.AbstractNumberMapping.FloatMapping; |
51 | import sf.qof.mapping.AbstractNumberMapping.IntegerMapping; |
52 | import sf.qof.mapping.AbstractNumberMapping.LongMapping; |
53 | import sf.qof.mapping.AbstractNumberMapping.ShortMapping; |
54 | |
55 | /** |
56 | * Internal - OutputParameterRegistrationMappingGenerator is the generator class for output parameter registration. |
57 | */ |
58 | public class OutputParameterRegistrationMappingGenerator implements MappingVisitor, NumberMappingVisitor, |
59 | CharacterMappingVisitor, DateTimeMappingVisitor { |
60 | |
61 | private CodeEmitter co; |
62 | private Local callableStatement; |
63 | |
64 | public OutputParameterRegistrationMappingGenerator(CodeEmitter co, Local callableStatement) { |
65 | this.co = co; |
66 | this.callableStatement = callableStatement; |
67 | } |
68 | |
69 | public void visit(Mapper mapper, AbstractCharacterMapping mapping) { |
70 | mapping.accept(mapper, (CharacterMappingVisitor) this); |
71 | } |
72 | |
73 | public void visit(Mapper mapper, AbstractNumberMapping mapping) { |
74 | mapping.accept(mapper, (NumberMappingVisitor) this); |
75 | } |
76 | |
77 | public void visit(Mapper mapper, AbstractDateTimeMapping mapping) { |
78 | mapping.accept(mapper, (DateTimeMappingVisitor) this); |
79 | } |
80 | |
81 | public void visit(Mapper mapper, AdapterMapping mapping) { |
82 | int[] sqlIndexes = mapping.getSqlIndexes(); |
83 | |
84 | if (mapping.getAdapter() instanceof GeneratorMappingAdapter) { |
85 | ((GeneratorMappingAdapter) mapping.getAdapter()).generateRegisterOutputParameters(mapping, co, callableStatement, sqlIndexes); |
86 | } else if (mapping.getAdapter() instanceof DynamicMappingAdapter) { |
87 | co.getfield(QueryObjectGenerator.getAdapterFieldName(mapping.getAdapter().getClass())); |
88 | co.load_local(callableStatement); |
89 | // push indexes |
90 | co.push(sqlIndexes.length); |
91 | co.newarray(TYPE_int); |
92 | for (int i = 0; i < sqlIndexes.length; i++) { |
93 | co.dup(); |
94 | co.push(i); |
95 | co.push(sqlIndexes[i]); |
96 | co.array_store(TYPE_int); |
97 | } |
98 | co.invoke_interface(Type.getType(DynamicMappingAdapter.class), new Signature("registerOutputParameter", |
99 | "(Ljava/sql/CallableStatement;[I)V")); |
100 | } else { |
101 | throw new RuntimeException("Unsupported adapter type " + mapping.getAdapter()); |
102 | } |
103 | } |
104 | |
105 | // NumberMappingVisitor |
106 | |
107 | public void visit(Mapper mapper, ByteMapping mapping) { |
108 | emitRegisterOutputParameter(mapping, java.sql.Types.TINYINT); |
109 | } |
110 | |
111 | public void visit(Mapper mapper, ShortMapping mapping) { |
112 | emitRegisterOutputParameter(mapping, java.sql.Types.SMALLINT); |
113 | } |
114 | |
115 | public void visit(Mapper mapper, IntegerMapping mapping) { |
116 | emitRegisterOutputParameter(mapping, java.sql.Types.INTEGER); |
117 | } |
118 | |
119 | public void visit(Mapper mapper, LongMapping mapping) { |
120 | emitRegisterOutputParameter(mapping, java.sql.Types.BIGINT); |
121 | } |
122 | |
123 | public void visit(Mapper mapper, FloatMapping mapping) { |
124 | emitRegisterOutputParameter(mapping, java.sql.Types.REAL); |
125 | } |
126 | |
127 | public void visit(Mapper mapper, DoubleMapping mapping) { |
128 | emitRegisterOutputParameter(mapping, java.sql.Types.DOUBLE); |
129 | } |
130 | |
131 | public void visit(Mapper mapper, BooleanMapping mapping) { |
132 | emitRegisterOutputParameter(mapping, java.sql.Types.BOOLEAN); |
133 | } |
134 | |
135 | // CharacterMappingVisitor |
136 | |
137 | public void visit(Mapper mapper, StringMapping mapping) { |
138 | emitRegisterOutputParameter(mapping, java.sql.Types.VARCHAR); |
139 | } |
140 | |
141 | public void visit(Mapper mapper, CharacterMapping mapping) { |
142 | emitRegisterOutputParameter(mapping, java.sql.Types.VARCHAR); |
143 | } |
144 | |
145 | // DateTimeMappingVisitor |
146 | |
147 | public void visit(Mapper mapper, DateMapping mapping) { |
148 | emitRegisterOutputParameter(mapping, java.sql.Types.DATE); |
149 | } |
150 | |
151 | public void visit(Mapper mapper, TimeMapping mapping) { |
152 | emitRegisterOutputParameter(mapping, java.sql.Types.TIME); |
153 | } |
154 | |
155 | public void visit(Mapper mapper, TimestampMapping mapping) { |
156 | emitRegisterOutputParameter(mapping, java.sql.Types.TIMESTAMP); |
157 | } |
158 | |
159 | private void emitRegisterOutputParameter(ResultMapping resultMapping, int sqlType) { |
160 | co.load_local(callableStatement); |
161 | co.push(resultMapping.getSqlIndexes()[0]); |
162 | co.push(sqlType); |
163 | co.invoke_interface(TYPE_CallableStatement, SIG_registerOutParameter); |
164 | } |
165 | } |