1 package pl.aislib.tools.mapping.generators;
2
3 import java.io.File;
4 import java.io.FileWriter;
5 import java.io.IOException;
6 import java.io.InputStream;
7 import java.io.Writer;
8 import java.util.Iterator;
9 import java.util.List;
10
11 import org.apache.commons.io.IOUtils;
12
13 import pl.aislib.tools.mapping.Generator;
14 import pl.aislib.tools.mapping.structure.Aggregate;
15 import pl.aislib.tools.mapping.structure.Call;
16 import pl.aislib.tools.mapping.structure.CallParam;
17 import pl.aislib.tools.mapping.structure.CallParams;
18 import pl.aislib.tools.mapping.structure.Count;
19 import pl.aislib.tools.mapping.structure.Delete;
20 import pl.aislib.tools.mapping.structure.Field;
21 import pl.aislib.tools.mapping.structure.Fields;
22 import pl.aislib.tools.mapping.structure.JavaClass;
23 import pl.aislib.tools.mapping.structure.JavaField;
24 import pl.aislib.tools.mapping.structure.JavaMethod;
25 import pl.aislib.tools.mapping.structure.Operation;
26 import pl.aislib.tools.mapping.structure.Operations;
27 import pl.aislib.tools.mapping.structure.Select;
28 import pl.aislib.tools.mapping.structure.SqlField;
29 import pl.aislib.tools.mapping.structure.SqlQuery;
30 import pl.aislib.tools.mapping.structure.SqlTable;
31 import pl.aislib.tools.mapping.structure.Structure;
32 import pl.aislib.tools.mapping.structure.Update;
33
34 /***
35 * <code>dbhandlers</code> generator.
36 *
37 * @author <a href="mailto:milosz@ais.pl">Milosz Tylenda</a>, AIS.PL
38 * $Revision: 1.39 $
39 */
40 public class BeanHelperGenerator extends Generator {
41
42 private File baseDir;
43 private Writer writer;
44
45 private File initDirectory(File destinationDir) {
46 File dir = new File(destinationDir.getPath() + File.separator + dbHandlersSubdir);
47 if (!dir.exists()) {
48 dir.mkdirs();
49 }
50 return dir;
51 }
52
53 private void initWriter(String fileName) throws IOException {
54 writer = new FileWriter(baseDir.getPath() + File.separator + fileName);
55 }
56
57 private void closeWriter() throws IOException {
58 writer.close();
59 }
60
61 public void generate() throws IOException {
62 baseDir = initDirectory(destinationDir);
63 MiscPutter miscPutter = new MiscPutter();
64 DisuPutter disuPutter = new DisuPutter();
65 AggregatePutter aggregatePutter = new AggregatePutter();
66 CallPutter callPutter = new CallPutter();
67 CountPutter countPutter = new CountPutter();
68 DeletePutter deletePutter = new DeletePutter();
69 SelectPutter selectPutter = new SelectPutter();
70 UpdatePutter updatePutter = new UpdatePutter();
71 ReadPutter readPutter = new ReadPutter();
72 List structureList = database.getStructureList();
73 for (int i = 0, size = structureList.size() ; i < size ; i++) {
74 Structure structure = (Structure) structureList.get(i);
75 SqlTable sqlTable = structure.getSqlTable();
76 JavaClass javaClass = structure.getJavaClass();
77 Fields fields = structure.getFields();
78
79 initWriter(javaClass.getName() + "Handler.java");
80 miscPutter.setWriter(writer);
81 miscPutter.setProperties(packageName, javaClass);
82 miscPutter.putHeader();
83 disuPutter.setWriter(writer);
84 disuPutter.setProperties(sqlTable, javaClass, fields);
85 disuPutter.put();
86
87 aggregatePutter.setWriter(writer);
88 callPutter.setWriter(writer);
89 countPutter.setWriter(writer);
90 deletePutter.setWriter(writer);
91 selectPutter.setWriter(writer);
92 updatePutter.setWriter(writer);
93 Operations operations = structure.getOperations();
94 if (operations != null) {
95 List aggregateList = operations.getAggregateList();
96 for (Iterator aggregateIter = aggregateList.listIterator() ; aggregateIter.hasNext() ; ) {
97 Aggregate aggregate = (Aggregate) aggregateIter.next();
98 aggregatePutter.setProperties(aggregate, sqlTable);
99 aggregatePutter.put();
100 }
101 List callList = operations.getCallList();
102 for (Iterator callIter = callList.listIterator() ; callIter.hasNext() ; ) {
103 Call call = (Call) callIter.next();
104 callPutter.setProperties(call, javaClass, fields);
105 callPutter.put();
106 }
107 List countList = operations.getCountList();
108 for (Iterator countIter = countList.listIterator() ; countIter.hasNext() ; ) {
109 Count count = (Count) countIter.next();
110 countPutter.setProperties(count, sqlTable);
111 countPutter.put();
112 }
113 List deleteList = operations.getDeleteList();
114 for (Iterator deleteIter = deleteList.listIterator() ; deleteIter.hasNext() ; ) {
115 Delete deletee = (Delete) deleteIter.next();
116 deletePutter.setProperties(deletee, sqlTable);
117 deletePutter.put();
118 }
119 List selectList = operations.getSelectList();
120 for (Iterator selectIter = selectList.listIterator() ; selectIter.hasNext() ; ) {
121 Select select = (Select) selectIter.next();
122 selectPutter.setProperties(select, fields, sqlTable, javaClass);
123 selectPutter.put();
124 }
125 List updateList = operations.getUpdateList();
126 for (Iterator updateIter = updateList.listIterator() ; updateIter.hasNext() ; ) {
127 Update update = (Update) updateIter.next();
128 updatePutter.setProperties(update, sqlTable);
129 updatePutter.put();
130 }
131 }
132 readPutter.setWriter(writer);
133 readPutter.setProperties(javaClass, fields);
134 readPutter.put();
135 miscPutter.putClassEndBrace();
136 closeWriter();
137 }
138 putEnhancedStatement(structureList);
139 log(structureList.size() + " " + dbHandlersSubpackage + ".XHandler classes generated");
140 }
141
142
143 /***
144 * Puts a special implementation of PreparedStatement if a raw parameter found
145 * in operations.
146 */
147 private void putEnhancedStatement(List structureList) throws IOException {
148 boolean classFileNeeded = false;
149
150 for (int i = 0, size = structureList.size() ; i < size ; i++) {
151 Structure structure = (Structure) structureList.get(i);
152 Operations operations = structure.getOperations();
153 if (operations == null) {
154 continue;
155 }
156
157 List operationList = operations.getAllOperations();
158 for (int j = 0, sizej = operationList.size(); j < sizej; j++) {
159 Operation operation = (Operation) operationList.get(j);
160 if (operation.getSqlQuery().containsRawParam()) {
161 classFileNeeded = true;
162 break;
163 }
164 }
165 }
166
167 if (!classFileNeeded) {
168 return;
169 }
170
171 initWriter("EnhancedStatement.java");
172 InputStream classSourceStream =
173 getClass().getClassLoader().getResourceAsStream("pl/aislib/tools/mapping/generators/EnhancedStatement.java");
174 String classSourceContent = IOUtils.toString(classSourceStream, "ISO-8859-2");
175 String classSourceContentWithoutPackage = classSourceContent.substring(classSourceContent.indexOf(';') + 2);
176 writer.write("package " + packageName + "." + dbHandlersSubpackage + ";\n");
177 writer.write(classSourceContentWithoutPackage);
178 closeWriter();
179 log("EnhancedStatement class generated.");
180 }
181
182
183
184 /***
185 * Puts <code>delete/insert/select/update</code> methods.
186 * @author Milosz Tylenda, AIS.PL
187 */
188 class DisuPutter {
189
190 private Writer writer;
191 private SqlTable sqlTable;
192 private JavaClass javaClass;
193 private Fields fields;
194
195 public void setWriter(Writer awriter) {
196 writer = awriter;
197 }
198
199 public void put() throws IOException {
200 String className = javaClass.getName();
201 String tableName = sqlTable.getName();
202 List fieldList = fields.getFieldList();
203 List fieldListNotOmitted = fields.getFieldListNotOmitted();
204 List primaryKeyList = fields.getPrimaryKeyList();
205 List nonPrimaryKeyList = fields.getNonPrimaryKeyList();
206 boolean pkDefined = fields.hasPrimaryKey();
207
208
209 if (sqlTable.isDelete() && pkDefined) {
210 writer.write(" public static void delete(" + className);
211 writer.write(" object, Connection con) throws SQLException {\n");
212 writer.write(" SQLException sqlEx = null;\n");
213 writer.write(" try {\n");
214 writer.write(" PreparedStatement pstmt = con.prepareStatement(\"delete from ");
215 writer.write(tableName + " where \" +\n");
216 writer.write(" \"" + Utils.formatSqlListForWhere(primaryKeyList) + "\");\n");
217 writer.write(" int counter = 1;\n");
218 writer.write(" try {\n");
219 generateObjectIfs(primaryKeyList);
220 writer.write(" pstmt.executeUpdate();\n");
221 writer.write(createEndOfMethod2(false));
222 }
223
224
225 if (sqlTable.isInsert()) {
226 writer.write(" public static void insert(" + className + " object, Connection con) throws SQLException {\n");
227 writer.write(" SQLException sqlEx = null;\n");
228 writer.write(" try {\n");
229 writer.write(" int counter = 1;\n");
230 writer.write(" PreparedStatement pstmt = con.prepareStatement(\"insert into ");
231 writer.write(tableName + " (\" +\n");
232 writer.write(" " + Utils.formatSqlList(fieldListNotOmitted) + " +\n");
233 writer.write(" \") values (");
234 for (int i = 0, size = fieldListNotOmitted.size() ; i < size ; i++) {
235 if (i > 0) {
236 writer.write(", ");
237 }
238 if ((i % 10) == 0) {
239 writer.write("\" +\n");
240 writer.write(" \"");
241 }
242 writer.write ("?");
243 }
244 writer.write(")\");\n");
245 writer.write(" try {\n");
246 generateObjectIfs(fieldListNotOmitted);
247 writer.write(" pstmt.executeUpdate();\n");
248 writer.write(createEndOfMethod2(false));
249 }
250
251
252 if (sqlTable.isSelect() && pkDefined) {
253 writer.write(" public static " + className + " select(");
254 writer.write(Utils.formatArgList(primaryKeyList) + ",\n");
255 writer.write(" Connection con) throws SQLException {\n");
256 writer.write(" SQLException sqlEx = null;\n");
257 writer.write(" " + className + " result = null;\n");
258 writer.write(" try {\n");
259 writer.write(" PreparedStatement pstmt = con.prepareStatement(\"select \" +\n");
260 writer.write(" " + Utils.formatSqlList(fieldList) + " + \" \" +\n");
261 writer.write(" \"from " + tableName + " where \" +\n");
262 writer.write(" \"" + Utils.formatSqlListForWhere(primaryKeyList) + "\");\n");
263 writer.write(" int counter = 1;\n");
264 writer.write(" try {\n");
265 for (int i = 0, size = primaryKeyList.size() ; i < size ; i++) {
266 Field field = (Field) primaryKeyList.get(i);
267 JavaField javaField = field.getJavaField();
268 String fieldName = javaField.getName();
269 String fieldType = javaField.getType();
270 writer.write(" pstmt.set" + Utils.mapTypeToMethod(fieldType));
271 writer.write("(counter++, " + fieldName);
272 writer.write(Utils.castMethod(fieldType));
273 writer.write(");\n");
274 }
275 writer.write(" ResultSet rs = pstmt.executeQuery();\n");
276 writer.write(" try {\n");
277 writer.write(" if (rs.next()) {\n");
278 writer.write(" return read(rs);\n");
279 writer.write(" }\n");
280 writer.write(createEndOfMethod());
281 }
282
283
284 if (sqlTable.isUpdate() && pkDefined) {
285 writer.write(" public static void update(" + className);
286 writer.write(" object, Connection con) throws SQLException {\n");
287 writer.write(" SQLException sqlEx = null;\n");
288 writer.write(" try {\n");
289 writer.write(" PreparedStatement pstmt = con.prepareStatement(\"update ");
290 writer.write(tableName + " set \" +\n");
291 writer.write(" " + Utils.formatSqlListForUpdate(nonPrimaryKeyList) + " +\n");
292 writer.write(" \"where \" +\n");
293 writer.write(" \"" + Utils.formatSqlListForWhere(primaryKeyList) + "\");\n");
294 writer.write(" int counter = 1;\n");
295 writer.write(" try {\n");
296 generateObjectIfs(nonPrimaryKeyList);
297 generateObjectIfs(primaryKeyList);
298 writer.write(" pstmt.executeUpdate();\n");
299 writer.write(createEndOfMethod2(false));
300 }
301 }
302
303 private void generateObjectIfs(List fieldList) throws IOException {
304 for (int i = 0, size = fieldList.size() ; i < size ; i++) {
305 Field field = (Field) fieldList.get(i);
306 JavaField javaField = field.getJavaField();
307 String fieldName = javaField.getName();
308 String fieldType = javaField.getType();
309 writer.write(" if (object." + Utils.getter(fieldName) + " != null) {\n");
310 writer.write(" pstmt.set" + Utils.mapTypeToMethod(fieldType));
311 writer.write("(counter++, object." + Utils.getter(fieldName));
312 writer.write(Utils.castMethod(fieldType));
313 writer.write(");\n");
314 writer.write(" } else {\n");
315 writer.write(" pstmt.setNull(counter++, ");
316 writer.write(Utils.getSQLType(fieldType));
317 writer.write(");\n");
318 writer.write(" }\n");
319 }
320 }
321
322 public void setProperties(SqlTable sqlTable, JavaClass javaClass, Fields fields) {
323 this.sqlTable = sqlTable;
324 this.javaClass = javaClass;
325 this.fields = fields;
326 }
327 }
328
329
330
331 /***
332 * Puts <code>read</code> method.
333 * @author Milosz Tylenda, AIS.PL
334 */
335 class ReadPutter {
336
337 private Writer writer;
338 private Fields fields;
339 private String className;
340
341 public void setWriter(Writer awriter) {
342 writer = awriter;
343 }
344
345 public void put() throws IOException {
346 List fieldList = fields.getFieldList();
347 writer.write(" public static " + className + " read(ResultSet rs) throws SQLException {\n");
348 writer.write(" " + className + " result = new " + className + "();\n");
349 writer.write(" int counter = 1;\n");
350
351 for (int i = 0, size = fieldList.size() ; i < size ; i++) {
352 Field field = (Field) fieldList.get(i);
353 JavaField javaField = field.getJavaField();
354 SqlField sqlField = field.getSqlField();
355 if (sqlField.isClobType()) {
356 putClobFieldGetting(javaField);
357 continue;
358 }
359 String cappedFieldName = Utils.capitalize(javaField.getName());
360 String fieldType = javaField.getType();
361 writer.write(" result.set" + cappedFieldName + "(");
362 if (Utils.isBaseType(fieldType)) {
363 writer.write("new " + fieldType + "(rs.get" + Utils.mapTypeToMethod(fieldType) + "(counter++)));\n");
364 writer.write(" if (rs.wasNull()) {\n");
365 writer.write(" result.set" + cappedFieldName + "(null);\n");
366 writer.write(" }\n");
367 } else {
368 writer.write("rs.get" + Utils.mapTypeToMethod(fieldType) + "(counter++));\n");
369 }
370 }
371 writer.write(" return result;\n");
372 writer.write(" }\n\n");
373 }
374
375 public void setProperties(JavaClass javaClass, Fields fields) {
376 this.fields = fields;
377 this.className = javaClass.getName();
378 }
379
380 /***
381 * Puts Clob getting code. It is assumed than javaField is of String type.
382 * That is, the application sees field mapped to CLOB as String.
383 */
384 private void putClobFieldGetting(JavaField javaField) throws IOException {
385 String cappedFieldName = Utils.capitalize(javaField.getName());
386 writer.write(" java.sql.Clob clob" + cappedFieldName + " = rs.getClob(counter++);\n");
387 writer.write(" if (clob" + cappedFieldName + " != null) {\n");
388 writer.write(" result.set" + cappedFieldName +
389 "(clob" + cappedFieldName + ".getSubString(1L, (int) clob" + cappedFieldName + ".length()));\n");
390 writer.write(" } else {\n");
391 writer.write(" result.set" + cappedFieldName + "(null);\n");
392 writer.write(" }\n");
393 }
394
395 }
396
397
398 /***
399 * Puts <code><operations></code> aggregate-methods.
400 * @author Milosz Tylenda, AIS.PL
401 */
402 class AggregatePutter {
403
404 private Writer writer;
405 private Aggregate aggregate;
406 private SqlTable sqlTable;
407
408 public void setWriter(Writer awriter) {
409 writer = awriter;
410 }
411
412 public void put() throws IOException {
413 JavaMethod javaMethod = aggregate.getJavaMethod();
414 SqlQuery sqlQuery = aggregate.getSqlQuery();
415 List javaParamList = javaMethod.getJavaParamList();
416
417 String query = "SELECT " + sqlQuery.createDistinctClause() + sqlQuery.getColumns() +
418 sqlQuery.createFromClause(sqlTable.getName()) + sqlQuery.createWhereClause() +
419 sqlQuery.createGroupByAndHavingClause() + sqlQuery.createOrderByClause() +
420 sqlQuery.createOtherClause();
421
422 writer.write(createJavaDoc(query, javaParamList, aggregate.createReturnForJavadoc()));
423 if (aggregate.isMultipleRows()) {
424 putMultipleRows(query);
425 } else {
426 putOneRow(query);
427 }
428 }
429
430 public void setProperties(Aggregate aggregate, SqlTable sqlTable) {
431 this.aggregate = aggregate;
432 this.sqlTable = sqlTable;
433 }
434
435 private void putOneRow(String query) throws IOException {
436 JavaMethod javaMethod = aggregate.getJavaMethod();
437 String methodName = javaMethod.getName();
438 List javaParamList = javaMethod.getJavaParamList();
439 String returnType = javaMethod.getReturnType();
440
441 writer.write(" public static " + returnType + " aggregate" + Utils.capitalize(methodName) + "(");
442 writer.write(Utils.formatMethodArgs(javaParamList));
443 writer.write("Connection con) throws SQLException {\n");
444 writer.write(" SQLException sqlEx = null;\n");
445 writer.write(" " + returnType + " result = null;\n");
446 writer.write(" try {\n");
447 writer.write(Utils.createPreparedStatement(query));
448 writer.write(" try {\n");
449 writer.write(Utils.generatePstmtSets(javaParamList));
450 writer.write(" ResultSet rs = pstmt.executeQuery();\n");
451 writer.write(" try {\n");
452 writer.write(" if (rs.next()) {\n");
453 if (Utils.isBaseType(returnType)) {
454 writer.write(" result = new " + returnType + "(rs.get" + Utils.mapTypeToMethod(returnType)+ "(1));\n");
455 writer.write(" if (rs.wasNull()) {\n");
456 writer.write(" result = null;\n");
457 writer.write(" }\n");
458 } else {
459 writer.write(" result = rs.get" + Utils.mapTypeToMethod(returnType)+ "(1);\n");
460 }
461 writer.write(" }\n");
462 writer.write(" return result;\n");
463 writer.write(createEndOfMethod());
464 }
465
466 private void putMultipleRows(String query) throws IOException {
467 JavaMethod javaMethod = aggregate.getJavaMethod();
468 String methodName = javaMethod.getName();
469 List javaParamList = javaMethod.getJavaParamList();
470 String returnType = javaMethod.getReturnType();
471
472 writer.write(" public static List aggregate" + Utils.capitalize(methodName) + "(");
473 writer.write(Utils.formatMethodArgs(javaParamList));
474 writer.write("Connection con) throws SQLException {\n");
475 writer.write(" SQLException sqlEx = null;\n");
476 writer.write(" List result = new ArrayList();\n");
477 writer.write(" try {\n");
478 writer.write(Utils.createPreparedStatement(query));
479 writer.write(" try {\n");
480 writer.write(Utils.generatePstmtSets(javaParamList));
481 writer.write(" ResultSet rs = pstmt.executeQuery();\n");
482 writer.write(" try {\n");
483 writer.write(" while (rs.next()) {\n");
484 if (Utils.isBaseType(returnType)) {
485 writer.write(" " + returnType + " element = new " + returnType + "(rs.get" + Utils.mapTypeToMethod(returnType)+ "(1));\n");
486 } else {
487 writer.write(" " + returnType + " element = rs.get" + Utils.mapTypeToMethod(returnType)+ "(1);\n");
488 }
489 writer.write(" if (!rs.wasNull()) {\n");
490 writer.write(" result.add(element);\n");
491 writer.write(" }\n");
492 writer.write(" }\n");
493 writer.write(" return result;\n");
494 writer.write(createEndOfMethod());
495 }
496
497 }
498
499
500 /***
501 * Puts <code><operations></code> call-methods.
502 * @author Milosz Tylenda, AIS.PL
503 */
504 class CallPutter {
505
506 private Writer writer;
507 private Call call;
508 private JavaClass javaClass;
509 private Fields fields;
510
511 public void setWriter(Writer awriter) {
512 writer = awriter;
513 }
514
515 public void put() throws IOException {
516 CallParams callParams = call.getCallParams();
517 JavaMethod javaMethod = call.getJavaMethod();
518 String methodName = javaMethod.getName();
519 List extendedJavaParamList = javaMethod.createExtendedJavaParamList(javaClass);
520 SqlQuery sqlQuery = call.getSqlQuery();
521
522 boolean hasOutOrInoutParam = false;
523 String returnType = "void";
524 String returnString = null;
525
526 String query = sqlQuery.getBody();
527 CallParam outParam = callParams.findOutOrInoutParam();
528 if (outParam != null) {
529 hasOutOrInoutParam = true;
530 returnType = outParam.determineType(fields, javaMethod);
531 returnString = Call.JAVADOC_RETURN_STRING;
532 }
533 writer.write(createJavaDoc(query, extendedJavaParamList, returnString));
534 writer.write(" public static " + returnType + " call" + Utils.capitalize(methodName) + "(");
535 writer.write(Utils.formatMethodArgs(extendedJavaParamList));
536 writer.write("Connection con) throws SQLException {\n");
537 writer.write(" SQLException sqlEx = null;\n");
538 if (hasOutOrInoutParam) {
539 writer.write(" " + returnType + " result = null;\n");
540 }
541 writer.write(" try {\n");
542 writer.write(" CallableStatement pstmt = con.prepareCall(" + Utils.equalLengthSplit(query) + ");\n");
543 writer.write(" try {\n");
544 writer.write(generatePstmtSets(callParams, fields, javaMethod));
545 writer.write(" pstmt.executeUpdate();\n");
546 if (hasOutOrInoutParam) {
547 int outIndex = callParams.getIndexOfOutOrInoutParam() + 1;
548 String method = Utils.mapTypeToMethod(returnType) + "(" + outIndex + ")";
549 if (Utils.isBaseType(returnType)) {
550 writer.write(" result = new " + returnType + "(pstmt.get" + method + ");\n");
551 writer.write(" if (pstmt.wasNull()) {\n");
552 writer.write(" result = null;\n");
553 writer.write(" }\n");
554 } else {
555 writer.write(" result = pstmt.get" + method + ";\n");
556 }
557 }
558 writer.write(createEndOfMethod2(hasOutOrInoutParam));
559 }
560
561 public void setProperties(Call call, JavaClass javaClass, Fields fields) {
562 this.call = call;
563 this.javaClass = javaClass;
564 this.fields = fields;
565 }
566
567 /***
568 * Generates PreparedStatement.setX() code.
569 */
570 private String generatePstmtSets(CallParams callParams, Fields fields, JavaMethod javaMethod) {
571 List callParamList = callParams.getCallParamList();
572 StringBuffer result = new StringBuffer(512);
573 for (int i = 0, size = callParamList.size() ; i < size ; i++) {
574 CallParam callParam = (CallParam) callParamList.get(i);
575
576 if (callParam.isInOrInoutParam()) {
577 Utils.generatePstmtSet(result, callParam.createJavaParam(fields, javaMethod), i + 1);
578 }
579
580 if (callParam.isOutOrInoutParam()) {
581 String sqlType = Utils.getSQLType(callParam.determineType(fields, javaMethod));
582 result.append(" pstmt.registerOutParameter(" + (i + 1) + ", " + sqlType + ");\n");
583 }
584
585 }
586 return result.toString();
587 }
588
589 }
590
591
592 /***
593 * Puts <code><operations></code> count-methods.
594 * @author Milosz Tylenda, AIS.PL
595 */
596 class CountPutter {
597
598 private Writer writer;
599 private Count count;
600 private SqlTable sqlTable;
601
602 public void setWriter(Writer awriter) {
603 writer = awriter;
604 }
605
606 public void put() throws IOException {
607 JavaMethod javaMethod = count.getJavaMethod();
608 String methodName = javaMethod.getName();
609 List javaParamList = javaMethod.getJavaParamList();
610 SqlQuery sqlQuery = count.getSqlQuery();
611
612 String query = "SELECT COUNT(*) " + sqlQuery.createFromClause(sqlTable.getName()) +
613 sqlQuery.createWhereClause() + sqlQuery.createOtherClause();
614 writer.write(createJavaDoc(query, javaParamList, "number of counted rows"));
615 writer.write(" public static int count" + Utils.capitalize(methodName) + "(");
616 writer.write(Utils.formatMethodArgs(javaParamList));
617 writer.write("Connection con) throws SQLException {\n");
618 writer.write(" SQLException sqlEx = null;\n");
619 writer.write(" int result = 0;\n");
620 writer.write(" try {\n");
621 writer.write(Utils.createPreparedStatement(query));
622 writer.write(" try {\n");
623 writer.write(Utils.generatePstmtSets(javaParamList));
624 writer.write(" ResultSet rs = pstmt.executeQuery();\n");
625 writer.write(" try {\n");
626 writer.write(" if (rs.next()) {\n");
627 writer.write(" result = rs.getInt(1);\n");
628 writer.write(" }\n");
629 writer.write(" return result;\n");
630 writer.write(createEndOfMethod());
631 }
632
633 public void setProperties(Count count, SqlTable sqlTable) {
634 this.count = count;
635 this.sqlTable = sqlTable;
636 }
637 }
638
639
640 /***
641 * Puts <code><operations></code> select-methods.
642 * @author Milosz Tylenda, AIS.PL
643 */
644 class SelectPutter {
645
646 private Writer writer;
647 private Select select;
648 private Fields fields;
649 private SqlTable sqlTable;
650 private JavaClass javaClass;
651
652 public void setWriter(Writer awriter) {
653 writer = awriter;
654 }
655
656 public void put() throws IOException {
657 List fieldList = fields.getFieldList();
658 SqlQuery sqlQuery = select.getSqlQuery();
659 JavaMethod javaMethod = select.getJavaMethod();
660 List javaParamList = javaMethod.getJavaParamList();
661
662 String query = "SELECT " + sqlQuery.createDistinctClause() +
663 sqlQuery.createColumnsClause(fieldList, sqlTable.getName()) +
664 sqlQuery.createFromClause(sqlTable.getName()) + sqlQuery.createWhereClause() +
665 sqlQuery.createGroupByAndHavingClause() + sqlQuery.createOrderByClause() +
666 sqlQuery.createOtherClause();
667
668 writer.write(createJavaDoc(query, javaParamList, select.createReturnForJavadoc(javaClass)));
669 if (select.isMultipleRows()) {
670 putMultipleRows(query);
671 } else {
672 putOneRow(query);
673 }
674 }
675
676 public void setProperties(Select select, Fields fields, SqlTable sqlTable, JavaClass javaClass) {
677 this.select = select;
678 this.fields = fields;
679 this.sqlTable = sqlTable;
680 this.javaClass = javaClass;
681 }
682
683 private void putOneRow(String query) throws IOException {
684 JavaMethod javaMethod = select.getJavaMethod();
685 String methodName = javaMethod.getName();
686 List javaParamList = javaMethod.getJavaParamList();
687 String className = javaClass.getName();
688
689 writer.write(" public static " + className + " select" + Utils.capitalize(methodName) + "(");
690 writer.write(Utils.formatMethodArgs(javaParamList));
691 writer.write("Connection con) throws SQLException {\n");
692 writer.write(" SQLException sqlEx = null;\n");
693 writer.write(" " + className + " result = null;\n");
694 writer.write(" try {\n");
695 writer.write(Utils.createPreparedStatement(query));
696 writer.write(" try {\n");
697 writer.write(Utils.generatePstmtSets(javaParamList));
698 writer.write(" ResultSet rs = pstmt.executeQuery();\n");
699 writer.write(" try {\n");
700 writer.write(" if (rs.next()) {\n");
701 writer.write(" result = read(rs);\n");
702 writer.write(" }\n");
703 writer.write(" return result;\n");
704 writer.write(createEndOfMethod());
705 }
706
707 private void putMultipleRows(String query) throws IOException {
708 JavaMethod javaMethod = select.getJavaMethod();
709 String methodName = javaMethod.getName();
710 List javaParamList = javaMethod.getJavaParamList();
711
712 writer.write(" public static List select" + Utils.capitalize(methodName) + "(");
713 writer.write(Utils.formatMethodArgs(javaParamList));
714 writer.write("Connection con) throws SQLException {\n");
715 writer.write(" SQLException sqlEx = null;\n");
716 writer.write(" List result = new ArrayList();\n");
717 writer.write(" try {\n");
718 writer.write(Utils.createPreparedStatement(query));
719 writer.write(" try {\n");
720 writer.write(Utils.generatePstmtSets(javaParamList));
721 writer.write(" ResultSet rs = pstmt.executeQuery();\n");
722 writer.write(" try {\n");
723 writer.write(" while (rs.next()) {\n");
724 writer.write(" result.add(read(rs));\n");
725 writer.write(" }\n");
726 writer.write(" return result;\n");
727 writer.write(createEndOfMethod());
728 }
729
730 }
731
732
733 /***
734 * Puts <code><operations></code> delete-methods.
735 * @author Milosz Tylenda, AIS.PL
736 */
737 class DeletePutter {
738
739 private Writer writer;
740 private Delete deletee;
741 private SqlTable sqlTable;
742
743 public void setWriter(Writer awriter) {
744 writer = awriter;
745 }
746
747 public void put() throws IOException {
748 JavaMethod javaMethod = deletee.getJavaMethod();
749 String methodName = javaMethod.getName();
750 List javaParamList = javaMethod.getJavaParamList();
751 SqlQuery sqlQuery = deletee.getSqlQuery();
752
753
754 String query = "DELETE FROM " + sqlTable.getName() + sqlQuery.createWhereClause() +
755 sqlQuery.createOtherClause();
756 writer.write(createJavaDoc(query, javaParamList, "number of deleted rows"));
757 writer.write(" public static int delete" + Utils.capitalize(methodName) + "(");
758 writer.write(Utils.formatMethodArgs(javaParamList));
759 writer.write("Connection con) throws SQLException {\n");
760 writer.write(" SQLException sqlEx = null;\n");
761 writer.write(" int result = 0;\n");
762 writer.write(" try {\n");
763 writer.write(Utils.createPreparedStatement(query));
764 writer.write(" try {\n");
765 writer.write(Utils.generatePstmtSets(javaParamList));
766 writer.write(" result = pstmt.executeUpdate();\n");
767 writer.write(createEndOfMethod2(true));
768 }
769
770 public void setProperties(Delete deletee, SqlTable sqlTable) {
771 this.deletee = deletee;
772 this.sqlTable = sqlTable;
773 }
774 }
775
776
777 /***
778 * Puts <code><operations></code> update-methods.
779 * @author Milosz Tylenda, AIS.PL
780 */
781 class UpdatePutter {
782
783 private Writer writer;
784 private Update update;
785 private SqlTable sqlTable;
786
787 public void setWriter(Writer awriter) {
788 writer = awriter;
789 }
790
791 public void put() throws IOException {
792 JavaMethod javaMethod = update.getJavaMethod();
793 String methodName = javaMethod.getName();
794 List javaParamList = javaMethod.getJavaParamList();
795 SqlQuery sqlQuery = update.getSqlQuery();
796
797 String query = "UPDATE " + sqlTable.getName() + " SET " + sqlQuery.getSet() + sqlQuery.createWhereClause() +
798 sqlQuery.createOtherClause();
799 writer.write(createJavaDoc(query, javaParamList, "number of updated rows"));
800 writer.write(" public static int update" + Utils.capitalize(methodName) + "(");
801 writer.write(Utils.formatMethodArgs(javaParamList));
802 writer.write("Connection con) throws SQLException {\n");
803 writer.write(" SQLException sqlEx = null;\n");
804 writer.write(" int result = 0;\n");
805 writer.write(" try {\n");
806 writer.write(Utils.createPreparedStatement(query));
807 writer.write(" try {\n");
808 writer.write(Utils.generatePstmtSets(javaParamList));
809 writer.write(" result = pstmt.executeUpdate();\n");
810 writer.write(createEndOfMethod2(true));
811 }
812
813 public void setProperties(Update update, SqlTable sqlTable) {
814 this.update = update;
815 this.sqlTable = sqlTable;
816 }
817 }
818
819
820
821 /***
822 * Puts some little things like <CODE>package</CODE> string and class end brace.
823 * @author Milosz Tylenda, AIS.PL
824 */
825 class MiscPutter {
826
827 private Writer writer;
828 private String packagePrefix/package-summary.html">ong> String packagePrefix;
829 private String className;
830
831 public void setWriter(Writer awriter) {
832 writer = awriter;
833 }
834
835 public void setProperties(String aPackagePrefix, JavaClass javaClass) {
836 packagePrefix = aPackagePrefix;
837 className = javaClass.getName();
838 }
839
840 public void putHeader() throws IOException {
841 writer.write("package " + packagePrefix + "." + dbHandlersSubpackage + ";\n\n");
842 writer.write("// THIS FILE HAS BEEN GENERATED AUTOMAGICALLY. DO NOT EDIT!\n\n");
843 writer.write("import java.math.BigDecimal;\n\n");
844 writer.write("import java.sql.Connection;\n");
845 writer.write("import java.sql.CallableStatement;\n");
846 writer.write("import java.sql.PreparedStatement;\n");
847 writer.write("import java.sql.ResultSet;\n");
848 writer.write("import java.sql.SQLException;\n");
849 writer.write("import java.sql.Timestamp;\n\n");
850 writer.write("import java.util.ArrayList;\n");
851 writer.write("import java.util.List;\n\n");
852 writer.write("import " + packagePrefix + "." + objectsSubpackage + "." + className + ";\n\n");
853 writer.write("/**\n");
854 writer.write(" * <code>" + className + "</code> database handler.\n");
855 writer.write(" * @author BeanHelperGenerator\n");
856 writer.write(" */\n");
857 writer.write("public class " + className + "Handler {\n\n");
858 }
859
860 public void putClassEndBrace() throws IOException {
861 writer.write("}\n");
862 }
863
864 }
865
866 /***
867 * Common code used in SELECT queries.
868 */
869 String createEndOfMethod() {
870 return
871 " } catch (SQLException sqle1) {\n" +
872 " sqlEx = sqle1;\n" +
873 " } finally {\n" +
874 " rs.close();\n" +
875 " }\n" +
876 " } catch (SQLException sqle2) {\n" +
877 " if (sqlEx == null) {\n" +
878 " sqlEx = sqle2;\n" +
879 " }\n" +
880 " } finally {\n" +
881 " pstmt.close();\n" +
882 " }\n" +
883 " } catch (SQLException sqle3) {\n" +
884 " if (sqlEx == null) {\n" +
885 " sqlEx = sqle3;\n" +
886 " }\n" +
887 " } finally {\n" +
888 " if (sqlEx != null) {\n" +
889 " throw sqlEx;\n" +
890 " }\n" +
891 " }\n" +
892 " return result;\n" +
893 " }\n\n";
894 }
895
896 /***
897 * Common code used in DELETE/INSERT/UPDATE/SP queries.
898 */
899 String createEndOfMethod2(boolean createReturn) {
900 StringBuffer result = new StringBuffer(512);
901 result.append(
902 " } catch (SQLException sqle1) {\n" +
903 " sqlEx = sqle1;\n" +
904 " } finally {\n" +
905 " pstmt.close();\n" +
906 " }\n" +
907 " } catch (SQLException sqle2) {\n" +
908 " if (sqlEx == null) {\n" +
909 " sqlEx = sqle2;\n" +
910 " }\n" +
911 " } finally {\n" +
912 " if (sqlEx != null) {\n" +
913 " throw sqlEx;\n" +
914 " }\n" +
915 " }\n"
916 );
917 if (createReturn) {
918 result.append(" return result;\n");
919 }
920 result.append(" }\n\n");
921 return result.toString();
922 }
923
924 /***
925 * JavaDoc before method.
926 */
927 String createJavaDoc(String query, List javaParamList, String returnString) {
928 StringBuffer result = new StringBuffer(512);
929 result.append(" /**\n");
930 result.append(" * <code>" + Utils.protectHTML(query) + "</code>.\n");
931 result.append(Utils.formatMethodArgsForJavaDoc(javaParamList));
932 result.append(" * @param con the <code>Connection</code> to database\n");
933 if (returnString != null) {
934 result.append(" * @return " + returnString + "\n");
935 }
936 result.append(" * @throws SQLException when operation failed\n");
937 result.append(" */\n");
938 return result.toString();
939 }
940
941 }
942
943 /***
944 * $Log: BeanHelperGenerator.java,v $
945 * Revision 1.39 2004/09/27 10:34:54 milosz
946 * SelectPutter: call to static method from Utils replaced with SqlQuery.createColumnsClause adding support of columns attribute to select element.
947 *
948 * Revision 1.38 2004/09/13 13:32:34 milosz
949 * putEnhancedStatement: logging added.
950 *
951 * Revision 1.37 2004/09/10 16:15:12 milosz
952 * Support for raw params added: putEnhancedStatement method added; uses method from Utils to generate suitable code for PreparedStatement creation.
953 *
954 * Revision 1.36 2004/09/08 11:37:11 milosz
955 * Removed empty constructors, changed scopes of some methods to default to decrease the number of compiler warnings.
956 *
957 * Revision 1.35 2004/08/11 12:41:01 wswiatek
958 * Database and map handlers location are now parametrizable.
959 * Maven plugin version changed to 1.0.1
960 *
961 * Revision 1.34 2004/07/02 07:39:52 milosz
962 * Support for 'group-by', 'having' and 'other' attributes added to 'sql-query.' Removed unnecessary line from generated code in aggregate method.
963 *
964 * Revision 1.33 2004/06/17 07:33:00 milosz
965 * Generated read method now public and always generated.
966 *
967 * Revision 1.32 2003/10/29 11:47:02 pikus
968 * use ant logger where possible
969 *
970 * Revision 1.31 2003/10/29 10:32:06 milosz
971 * Support for CLOB <-> String mapping added.
972 *
973 * Revision 1.30 2003/09/12 13:22:19 milosz
974 * Refactoring: syntax checking moved from generators to DatabaseChecker and other classes in structure package.
975 *
976 * Revision 1.29 2003/09/10 07:35:19 milosz
977 * CallPutter.generatePstmtSets method simplified.
978 *
979 * Revision 1.28 2003/09/09 13:25:39 milosz
980 * Support for operations/call element added.
981 *
982 * Revision 1.27 2003/09/02 13:33:07 milosz
983 * java.sql.Statement import was unnecessary.
984 *
985 * Revision 1.26 2003/09/02 11:06:29 milosz
986 * Generic UPDATE generator changed to complain when a table has all columns marked as primary keys and update method wanted.
987 *
988 * Revision 1.25 2003/09/02 10:40:56 milosz
989 * Generic UPDATE generator corrected to generate compilable code (although not SQL parseable) when a table has all columns marked as primary keys.
990 *
991 * Revision 1.24 2003/09/02 10:15:00 milosz
992 * Some of generated String constants are splitted, so Jalopy can break more lines.
993 *
994 * Revision 1.23 2003/07/11 13:08:14 milosz
995 * objectsSubpackage property added.
996 *
997 * Revision 1.22 2003/06/04 07:58:10 milosz
998 * 'multipleRows' attribute added to operations/select element.
999 *
1000 * Revision 1.21 2003/05/28 13:10:09 milosz
1001 * Support for 'from' attribute added in 'sql-query' element.
1002 *
1003 * Revision 1.20 2003/05/28 08:27:57 milosz
1004 * Generated read method optimized - ResulSet.wasNull() checks are necessary for objects.
1005 *
1006 * Revision 1.19 2003/05/26 08:36:03 pikus
1007 * cleanup imports
1008 *
1009 * Revision 1.18 2003/05/20 08:12:12 milosz
1010 * Support for 'multipleRows' attribute in 'aggregate' element added.
1011 *
1012 * Revision 1.17 2003/05/20 07:25:44 milosz
1013 * Refactoring: createJavaDoc method extracted.
1014 *
1015 * Revision 1.16 2003/05/19 11:49:20 milosz
1016 * Refactoring: createEndOfMethodX methods extracted.
1017 *
1018 * Revision 1.15 2003/05/19 08:57:54 milosz
1019 * Added createXClause methods to SqlQuery.
1020 *
1021 * Revision 1.14 2003/05/16 13:04:00 milosz
1022 * Forgotten order-by support added to operations/aggregate.
1023 *
1024 * Revision 1.13 2003/05/14 13:55:45 milosz
1025 * Dead code removed (was introduced by Array support).
1026 *
1027 * Revision 1.12 2003/05/14 13:39:03 milosz
1028 * operations/aggregate element added.
1029 *
1030 * Revision 1.11 2003/04/08 09:54:24 milosz
1031 * Removed unnecessary <code> tag from @throws tag in JavaDoc.
1032 *
1033 * Revision 1.10 2002/12/05 09:37:54 milosz
1034 * DML strings displayed correctly in JavaDocs.
1035 *
1036 * Revision 1.9 2002/12/05 09:24:29 milosz
1037 * count element code was not correct.
1038 *
1039 * Revision 1.8 2002/12/03 11:53:12 milosz
1040 * Added JavaDoc generation to operations/select.
1041 *
1042 * Revision 1.7 2002/12/03 11:09:20 milosz
1043 * operations/count element added.
1044 *
1045 * Revision 1.6 2002/12/03 09:10:50 milosz
1046 * operations/update element added.
1047 *
1048 * Revision 1.5 2002/12/02 14:28:13 milosz
1049 * operations/delete element added.
1050 *
1051 * Revision 1.4 2002/11/04 07:31:32 wswiatek
1052 * Added oracle.sql.ARRAY type
1053 *
1054 * Revision 1.3 2002/10/09 10:03:31 milosz
1055 * Better messages and behaviour for structure without primary keys.
1056 *
1057 * Revision 1.2 2002/10/08 08:27:10 milosz
1058 * Generators became AntTasks(?). Ufff...
1059 *
1060 * Revision 1.1 2002/10/04 13:07:22 milosz
1061 * Reaching old mapping's functionality.
1062 *
1063 */
1064