OSDN Git Service

"https://svn.sourceforge.jp/svnroot/ea2ddl" にプロジェクト "ea2ddl-dao" を共用
[ea2ddl/ea2ddl.git] / ea2ddl-dao / src / main / java / jp / sourceforge / ea2ddl / dao / allcommon / s2dao / internal / sqlhandler / InternalProcedureHandler.java
1 package jp.sourceforge.ea2ddl.dao.allcommon.s2dao.internal.sqlhandler;\r
2 \r
3 import java.util.ArrayList;\r
4 import java.util.List;\r
5 import java.util.Map;\r
6 import java.sql.CallableStatement;\r
7 import java.sql.Connection;\r
8 import java.sql.ResultSet;\r
9 import java.sql.ResultSetMetaData;\r
10 import java.sql.Statement;\r
11 import java.sql.SQLException;\r
12 import javax.sql.DataSource;\r
13 \r
14 import org.seasar.framework.util.CaseInsensitiveMap;\r
15 import org.seasar.extension.jdbc.PropertyType;\r
16 import org.seasar.extension.jdbc.ResultSetHandler;\r
17 import org.seasar.extension.jdbc.StatementFactory;\r
18 import org.seasar.extension.jdbc.ValueType;\r
19 import org.seasar.extension.jdbc.impl.PropertyTypeImpl;\r
20 import org.seasar.extension.jdbc.types.ValueTypes;\r
21 \r
22 import jp.sourceforge.ea2ddl.dao.allcommon.s2dao.internal.various.InternalProcedureMetaData;\r
23 import jp.sourceforge.ea2ddl.dao.allcommon.s2dao.internal.various.InternalProcedureParameterType;\r
24 \r
25 /**\r
26  * @author DBFlute(AutoGenerator)\r
27  */\r
28 public class InternalProcedureHandler extends InternalBasicSelectHandler {\r
29 \r
30     // ===================================================================================\r
31     //                                                                           Attribute\r
32     //                                                                           =========\r
33     private InternalProcedureMetaData procedureMetaData;\r
34                 \r
35     // ===================================================================================\r
36     //                                                                         Constructor\r
37     //                                                                         ===========\r
38     public InternalProcedureHandler(final DataSource dataSource, final String sql,\r
39             final ResultSetHandler resultSetHandler, final StatementFactory statementFactory,\r
40             final InternalProcedureMetaData procedureMetaData) {\r
41         super(dataSource, sql, resultSetHandler, statementFactory);\r
42         this.procedureMetaData = procedureMetaData;\r
43     }\r
44         \r
45     // ===================================================================================\r
46     //                                                                             Execute\r
47     //                                                                             =======\r
48     @SuppressWarnings("unchecked")\r
49     public Object execute(final Connection connection, final Object[] args, final Class[] argTypes) {\r
50         final Object dto = getArgumentDto(args);\r
51         logSql(args, argTypes);\r
52         CallableStatement cs = null;\r
53         try {\r
54             cs = prepareCallableStatement(connection);\r
55             bindArgs(cs, dto);\r
56             Object returnValue = null; \r
57             if (cs.execute()) {\r
58                 final ResultSet resultSet = cs.getResultSet();\r
59                 if (resultSet != null) {\r
60                     final ResultSetHandler handler = createReturnResultSetHandler(resultSet);\r
61                     try {\r
62                         returnValue = handler.handle(resultSet);\r
63                     } finally {\r
64                         if (resultSet != null) {\r
65                             resultSet.close();\r
66                         }\r
67                     }\r
68                 }\r
69             }\r
70             return handleOutParameters(cs, dto, returnValue);\r
71         } catch (SQLException e) {\r
72             handleSQLException(e, cs);\r
73             return null;// Unreachable!\r
74         } finally {\r
75             close(cs);\r
76         }\r
77     }\r
78 \r
79     protected ResultSetHandler createReturnResultSetHandler(ResultSet resultSet) {\r
80         return new InternalMapListResultSetHandler();\r
81     }\r
82 \r
83     @Override\r
84     protected String getCompleteSql(final Object[] args) {// for Procedure Call\r
85         String sql = getSql();\r
86         Object dto = getArgumentDto(args);\r
87         if (args == null || dto == null) {\r
88             return sql;\r
89         }\r
90         StringBuilder sb = new StringBuilder(100);\r
91         int pos = 0;\r
92         int pos2 = 0;\r
93         for (InternalProcedureParameterType ppt : procedureMetaData.parameterTypes()) {\r
94             if ((pos2 = sql.indexOf('?', pos)) < 0) {\r
95                 break;\r
96             }\r
97             sb.append(sql.substring(pos, pos2));\r
98             pos = pos2 + 1;\r
99             if (ppt.isInType()) {\r
100                 sb.append(getBindVariableText(ppt.getValue(dto)));\r
101             } else {\r
102                 sb.append(sql.substring(pos2, pos));\r
103             }\r
104         }\r
105         sb.append(sql.substring(pos));\r
106         return sb.toString();\r
107     }\r
108 \r
109     protected CallableStatement prepareCallableStatement(final Connection connection) {\r
110         if (getSql() == null) { throw new IllegalStateException("The SQL should not be null!"); }\r
111         return getStatementFactory().createCallableStatement(connection, getSql());\r
112     }\r
113 \r
114     protected void bindArgs(final CallableStatement cs, final Object dto) throws SQLException {\r
115         if (dto == null) { return; }\r
116         int i = 0;\r
117         for (InternalProcedureParameterType ppt : procedureMetaData.parameterTypes()) {\r
118             final ValueType valueType = ppt.getValueType();\r
119             if (ppt.isOutType()) {\r
120                 valueType.registerOutParameter(cs, i + 1);\r
121             }\r
122             if (ppt.isInType()) {\r
123                 final Object value = ppt.getValue(dto);\r
124                 valueType.bindValue(cs, i + 1, value);\r
125             }\r
126             ++i;\r
127         }\r
128     }\r
129 \r
130     protected Object handleResultSet(final CallableStatement cs) throws SQLException {\r
131         ResultSet rs = null;\r
132         try {\r
133             rs = getResultSet(cs);\r
134             return getResultSetHandler().handle(rs);\r
135         } finally {\r
136             close(rs);\r
137         }\r
138     }\r
139 \r
140     protected ResultSet getResultSet(Statement statement)  {\r
141         try {\r
142             return statement.getResultSet();\r
143         } catch (SQLException e) {\r
144             handleSQLException(e, statement);\r
145             return null;// Unreachable!\r
146         }\r
147     }\r
148 \r
149     protected Object handleOutParameters(final CallableStatement cs, final Object dto, Object returnValue) throws SQLException {\r
150         if (dto == null) {\r
151             return null;\r
152         }\r
153         int i = 0;\r
154         for (InternalProcedureParameterType ppt : procedureMetaData.parameterTypes()) {\r
155             final ValueType valueType = ppt.getValueType();\r
156             if (ppt.isOutType()) {\r
157                 Object value = valueType.getValue(cs, i + 1);\r
158                 if (value instanceof ResultSet) {\r
159                     final ResultSet resultSet = (ResultSet) value;\r
160                     final ResultSetHandler handler = createOutParameterResultSetHandler(ppt, resultSet);\r
161                     try {\r
162                         value = handler.handle(resultSet);\r
163                     } finally {\r
164                         if (resultSet != null) {\r
165                             resultSet.close();\r
166                         }\r
167                     }\r
168                 }\r
169                 ppt.setValue(dto, value);\r
170             } else if (ppt.isReturnType()) {\r
171                 ppt.setValue(dto, returnValue);\r
172             }\r
173             ++i;\r
174         }\r
175         return dto;\r
176     }\r
177 \r
178     protected Object getArgumentDto(Object[] args) {\r
179         if (args.length == 0) {\r
180             return null;\r
181         }\r
182         if (args.length == 1) {\r
183             if (args[0] == null) {\r
184                 throw new IllegalArgumentException("args[0] should not be null!");\r
185             }\r
186             return args[0];\r
187         }\r
188         throw new IllegalArgumentException("args");\r
189     }\r
190 \r
191     protected ResultSetHandler createOutParameterResultSetHandler(InternalProcedureParameterType ppt, ResultSet resultSet) {\r
192         return new InternalMapListResultSetHandler();\r
193     }\r
194 \r
195         // ===================================================================================\r
196     //                                                              Map Result Set Handler\r
197     //                                                              ======================\r
198     protected static abstract class InternalAbstractMapResultSetHandler implements ResultSetHandler {\r
199 \r
200         @SuppressWarnings("unchecked")\r
201         protected Map<String, Object> createRow(ResultSet rs, PropertyType[] propertyTypes) throws SQLException {\r
202             Map<String, Object> row = new CaseInsensitiveMap();\r
203             for (int i = 0; i < propertyTypes.length; ++i) {\r
204                 Object value = propertyTypes[i].getValueType().getValue(rs, i + 1);\r
205                 row.put(propertyTypes[i].getPropertyName(), value);\r
206             }\r
207             return row;\r
208         }\r
209 \r
210         protected PropertyType[] createPropertyTypes(ResultSetMetaData rsmd) throws SQLException {\r
211             int count = rsmd.getColumnCount();\r
212             PropertyType[] propertyTypes = new PropertyType[count];\r
213             for (int i = 0; i < count; ++i) {\r
214                 String propertyName = rsmd.getColumnLabel(i + 1);\r
215                 ValueType valueType = ValueTypes.getValueType(rsmd.getColumnType(i + 1));\r
216                 propertyTypes[i] = new PropertyTypeImpl(propertyName, valueType);\r
217             }\r
218             return propertyTypes;\r
219         }\r
220     }\r
221 \r
222     protected static class InternalMapListResultSetHandler extends InternalAbstractMapResultSetHandler {\r
223 \r
224         public Object handle(ResultSet resultSet) throws SQLException {\r
225             PropertyType[] propertyTypes = createPropertyTypes(resultSet.getMetaData());\r
226             List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();\r
227             while (resultSet.next()) {\r
228                 list.add(createRow(resultSet, propertyTypes));\r
229             }\r
230             return list;\r
231         }\r
232     }\r
233 }\r