1 17 package org.apache.ws.jaxme.js.pattern; 18 19 import java.sql.Connection ; 20 import java.sql.Date ; 21 import java.sql.PreparedStatement ; 22 import java.sql.ResultSet ; 23 import java.sql.SQLException ; 24 import java.sql.Time ; 25 import java.sql.Timestamp ; 26 import java.sql.Types ; 27 import java.util.ArrayList ; 28 import java.util.HashMap ; 29 import java.util.HashSet ; 30 import java.util.Iterator ; 31 import java.util.List ; 32 import java.util.Map ; 33 import java.util.Set ; 34 35 import org.apache.ws.jaxme.js.DirectAccessible; 36 import org.apache.ws.jaxme.js.JavaComment; 37 import org.apache.ws.jaxme.js.JavaConstructor; 38 import org.apache.ws.jaxme.js.JavaField; 39 import org.apache.ws.jaxme.js.JavaInnerClass; 40 import org.apache.ws.jaxme.js.JavaMethod; 41 import org.apache.ws.jaxme.js.JavaQName; 42 import org.apache.ws.jaxme.js.JavaQNameImpl; 43 import org.apache.ws.jaxme.js.JavaSource; 44 import org.apache.ws.jaxme.js.LocalJavaField; 45 import org.apache.ws.jaxme.logging.Logger; 46 import org.apache.ws.jaxme.logging.LoggerAccess; 47 import org.apache.ws.jaxme.sqls.Column; 48 import org.apache.ws.jaxme.sqls.ColumnSet; 49 import org.apache.ws.jaxme.sqls.ForeignKey; 50 import org.apache.ws.jaxme.sqls.InsertStatement; 51 import org.apache.ws.jaxme.sqls.SelectStatement; 52 import org.apache.ws.jaxme.sqls.Table; 53 54 55 71 public class VersionGenerator { 72 80 public interface ColumnUpdater { 81 95 public void update(JavaMethod pMethod, TableInfo pTableInfo, 96 DirectAccessible pConnection, 97 DirectAccessible pMap, 98 DirectAccessible pRow); 99 } 100 101 104 public static class TableInfo { 105 private final Table table; 106 private final String propertyName; 107 private boolean isReferenced; 108 private boolean hasPrimaryKey; 109 private final List columnUpdaters = new ArrayList (); 110 TableInfo(Table pTable, String pPropertyName) { 111 table = pTable; 112 propertyName = pPropertyName; 113 } 114 public Table getTable() { return table; } 115 public String getPropertyName() { return propertyName; } 116 public void add(ColumnUpdater pColumnUpdater) { 117 columnUpdaters.add(pColumnUpdater); 118 } 119 public Iterator getColumnUpdaters() { return columnUpdaters.iterator(); } 120 121 public void setReferenced(boolean pReferenced) { 122 isReferenced = true; 123 } 124 public boolean isReferenced() { 125 return isReferenced; 126 } 127 public boolean hasPrimaryKey() { 128 return hasPrimaryKey; 129 } 130 public void setPrimaryKey(boolean pPrimaryKey) { 131 hasPrimaryKey = pPrimaryKey; 132 } 133 } 134 135 138 private class ForeignKeyUpdater implements ColumnUpdater { 139 private final ForeignKey foreignKey; 140 private final TableInfo referencedTable; 141 142 private ForeignKeyUpdater(ForeignKey pForeignKey, TableInfo pReferencedTable) { 143 foreignKey = pForeignKey; 144 referencedTable = pReferencedTable; 145 } 146 147 public void update(JavaMethod pMethod, TableInfo pTableInfo, 148 DirectAccessible pConnection, 149 DirectAccessible pMap, DirectAccessible pRow) { 150 Table table = foreignKey.getTable(); 151 List params = new ArrayList (); 152 for (Iterator iter = foreignKey.getColumns(); iter.hasNext(); ) { 153 Column primaryKeyColumn = (Column) iter.next(); 154 int index = -1; 155 int i = 0; 156 for (Iterator iter2 = table.getColumns(); iter2.hasNext(); ++i) { 157 Column tableColumn = (Column) iter2.next(); 158 if (tableColumn.equals(primaryKeyColumn)) { 159 index = i; 160 break; 161 } 162 } 163 if (index == -1) { 164 throw new IllegalStateException ("Key column " + primaryKeyColumn.getQName() + " not found."); 165 } 166 if (params.size() > 0) { 167 params.add(" || "); 168 } 169 params.add(new Object []{pRow, "[" + index + "] != null"}); 170 } 171 172 pMethod.addIf(params); 173 LocalJavaField referencedKey = getCacheDataClassInstance(pMethod, 174 referencedTable, 175 foreignKey, pRow); 176 LocalJavaField mappedKey = pMethod.newJavaField(referencedKey.getType()); 177 mappedKey.addLine("(", referencedKey.getType(), ") ", pMap, ".get(", 178 referencedKey, ")"); 179 pMethod.addIf(mappedKey, " == null"); 180 pMethod.addThrowNew(IllegalStateException .class, 181 JavaSource.getQuoted("Unknown reference: "), " + ", 182 referencedKey); 183 pMethod.addEndIf(); 184 int valNum = 0; 185 for (Iterator iter = referencedTable.getTable().getPrimaryKey().getColumns(); iter.hasNext(); ) { 186 Column referencedKeyColumn = (Column) iter.next(); 187 Column localColumn = null; 188 for (Iterator iter2 = foreignKey.getColumnLinks(); iter2.hasNext(); ) { 189 ForeignKey.ColumnLink link = (ForeignKey.ColumnLink) iter2.next(); 190 if (link.getReferencedColumn().equals(referencedKeyColumn)) { 191 localColumn = link.getLocalColumn(); 192 break; 193 } 194 } 195 if (localColumn == null) { 196 throw new IllegalStateException ("Unable to find the column referencing " + referencedKeyColumn.getQName()); 197 } 198 199 int colNum = -1, i = 0; 200 for (Iterator iter2 = pTableInfo.getTable().getColumns(); iter2.hasNext(); ) { 201 Column col = (Column) iter2.next(); 202 if (col.equals(localColumn)) { 203 colNum = i; 204 break; 205 } 206 ++i; 207 } 208 if (colNum == -1) { 209 throw new IllegalStateException ("Unable to find the column " + localColumn.getQName() + " in table " + pTableInfo.getTable().getQName()); 210 } 211 pMethod.addLine(pRow, "[" + colNum + "] = ", mappedKey, ".getValues()[" + valNum++ + "];"); 212 } 213 214 pMethod.addEndIf(); 215 } 216 } 217 218 private List tablesByOrder = new ArrayList (); 219 private Map tablesByName = new HashMap (); 220 private Set propertyNames = new HashSet (); 221 private boolean generatingLogging; 222 223 private boolean isReferencing(Table pReferencingTable, Table pReferencedTable) { 224 for (Iterator iter = pReferencingTable.getForeignKeys(); iter.hasNext(); ) { 225 ForeignKey foreignKey = (ForeignKey) iter.next(); 226 if (foreignKey.getReferencedTable().equals(pReferencedTable)) { 227 return true; 228 } 229 } 230 return false; 231 } 232 233 244 public boolean isGeneratingLogging() { 245 return generatingLogging; 246 } 247 248 259 public void setGeneratingLogging(boolean pGeneratingLogging) { 260 generatingLogging = pGeneratingLogging; 261 } 262 263 267 protected void initLogging(JavaSource pSource) { 268 if (isGeneratingLogging()) { 269 JavaField jf = pSource.newJavaField("logger", Logger.class, JavaSource.PRIVATE); 270 jf.setFinal(true); 271 jf.setStatic(true); 272 jf.addLine(LoggerAccess.class, ".getLogger(", pSource.getQName(), ".class)"); 273 } 274 } 275 276 284 protected void logEntering(JavaMethod pMethod, Object pValues) { 285 if (isGeneratingLogging()) { 286 LocalJavaField mName = pMethod.newJavaField(String .class, "mName"); 287 mName.addLine(JavaSource.getQuoted(pMethod.getLoggingSignature())); 288 mName.setFinal(true); 289 if (pValues == null) { 290 pMethod.addLine("logger.entering(", mName, ");"); 291 } else { 292 pMethod.addLine("logger.entering(", mName, ", ", pValues, ");"); 293 } 294 } 295 } 296 297 307 protected void logFinestEntering(JavaMethod pMethod, Object pValues) { 308 if (isGeneratingLogging()) { 309 LocalJavaField mName = pMethod.newJavaField(String .class, "mName"); 310 mName.addLine(JavaSource.getQuoted(pMethod.getLoggingSignature())); 311 mName.setFinal(true); 312 logFinest(pMethod, JavaSource.getQuoted("->"), pValues); 313 } 314 } 315 316 324 protected void logExiting(JavaMethod pMethod, Object pValues) { 325 if (isGeneratingLogging()) { 326 if (pValues == null) { 327 pMethod.addLine("logger.exiting(mName);"); 328 } else { 329 pMethod.addLine("logger.exiting(mName, ", pValues, ");"); 330 } 331 } 332 } 333 334 344 protected void logFinestExiting(JavaMethod pMethod, Object pValues) { 345 logFinest(pMethod, JavaSource.getQuoted("->"), pValues); 346 } 347 348 356 protected void logFinest(JavaMethod pMethod, Object pMsg, Object pValues) { 357 if (isGeneratingLogging()) { 358 if (pValues == null) { 359 pMethod.addLine("logger.finest(mName, ", pMsg, ");"); 360 } else { 361 pMethod.addLine("logger.finest(mName, ", pMsg, ", ", pValues, ");"); 362 } 363 } 364 } 365 366 374 public void addTable(Table pTable, ColumnUpdater pUpdater) { 375 String name = pTable.getQName(); 376 if (tablesByName.containsKey(pTable)) { 377 throw new IllegalStateException ("A table " + name + " has already been added."); 378 } 379 if (isReferencing(pTable, pTable)) { 380 throw new IllegalStateException ("The table " + name + " is containing self references."); 381 } 382 for (Iterator iter = tablesByOrder.iterator(); iter.hasNext(); ) { 383 TableInfo tableInfo = (TableInfo) iter.next(); 384 if (isReferencing(tableInfo.getTable(), pTable)) { 385 throw new IllegalStateException ("The table " + tableInfo.getTable().getQName() + 386 " contains a forward reference to the table " + name + "."); 387 } 388 } 389 390 String s = pTable.getName().getName(); 391 String t = s; 392 int num = 0; 393 for (;;) { 394 t = Character.toUpperCase(t.charAt(0)) + t.substring(1); 395 if (!propertyNames.contains(t)) { 396 break; 397 } 398 t = s + num++; 399 } 400 propertyNames.add(t); 401 402 TableInfo tableInfo = new TableInfo(pTable, t); 403 tableInfo.setPrimaryKey(pTable.getPrimaryKey() != null); 404 if (pUpdater != null) { 405 tableInfo.add(pUpdater); 406 } 407 408 for (Iterator iter = pTable.getForeignKeys(); iter.hasNext(); ) { 409 ForeignKey foreignKey = (ForeignKey) iter.next(); 410 Table referencedTable = foreignKey.getReferencedTable(); 411 for (Iterator iter2 = tablesByOrder.iterator(); iter2.hasNext(); ) { 412 TableInfo referencedTableInfo = (TableInfo) iter2.next(); 413 if (referencedTableInfo.getTable().equals(referencedTable)) { 414 ColumnUpdater columnUpdater = new ForeignKeyUpdater(foreignKey, referencedTableInfo); 415 tableInfo.add(columnUpdater); 416 if (!referencedTableInfo.hasPrimaryKey()) { 417 throw new IllegalStateException ("The table " + pTable.getQName() + 418 " is referencing table " + referencedTable.getQName() + 419 ", which doesn't have a primary key."); 420 } 421 referencedTableInfo.setReferenced(true); 422 } 423 } 424 } 425 426 tablesByName.put(name, tableInfo); 427 tablesByOrder.add(tableInfo); 428 } 429 430 432 protected JavaQName getCacheDataClassName(JavaQName pQName) { 433 return JavaQNameImpl.getInnerInstance(pQName, "CacheData"); 434 } 435 436 438 protected JavaInnerClass getCacheDataClass(JavaSource pSource) { 439 JavaInnerClass jic = pSource.newJavaInnerClass("CacheData", JavaSource.PRIVATE); 440 441 JavaField name = jic.newJavaField("name", String .class, JavaSource.PRIVATE); 442 name.setFinal(true); 443 JavaField values = jic.newJavaField("values", Object [].class, JavaSource.PRIVATE); 444 values.setFinal(true); 445 446 JavaConstructor jcon = jic.newJavaConstructor(JavaSource.PRIVATE); 447 DirectAccessible pName = jcon.addParam(String .class, "pName"); 448 DirectAccessible pValues = jcon.addParam(Object [].class, "pValues"); 449 jcon.addLine(name, " = ", pName, ";"); 450 jcon.addLine(values, " = ", pValues, ";"); 451 452 JavaMethod getNameMethod = jic.newJavaMethod("getName", String .class, JavaSource.PUBLIC); 453 getNameMethod.addLine("return ", name, ";"); 454 455 JavaMethod getValuesMethod = jic.newJavaMethod("getValues", Object [].class, JavaSource.PUBLIC); 456 getValuesMethod.addLine("return ", values, ";"); 457 458 { 459 JavaMethod jm = jic.newJavaMethod("toString", String .class, JavaSource.PUBLIC); 460 LocalJavaField sb = jm.newJavaField(StringBuffer .class, "sb"); 461 sb.addLine("new ", StringBuffer .class, "(", name, ")"); 462 DirectAccessible loopVar = jm.addForArray(values); 463 jm.addLine(sb, ".append(", JavaSource.getQuoted(", "), ").append(", 464 values, "[", loopVar, "]);"); 465 jm.addEndFor(); 466 jm.addLine("return ", sb, ".toString();"); 467 468 } 469 470 { 471 JavaMethod jm = jic.newJavaMethod("hashCode", int.class, JavaSource.PUBLIC); 472 LocalJavaField hashCodeResult = jm.newJavaField(int.class, "result"); 473 hashCodeResult.addLine(name, ".hashCode() + ", values, ".length;"); 474 DirectAccessible loopVar = jm.addForArray(values); 475 LocalJavaField o = jm.newJavaField(Object .class, "o"); 476 o.addLine(values, "[", loopVar, "]"); 477 jm.addIf(o, " != null"); 478 jm.addLine(hashCodeResult, " += ", o, ".hashCode();"); 479 jm.addEndIf(); 480 jm.addEndFor(); 481 jm.addLine("return ", hashCodeResult, ";"); 482 } 483 484 { 485 JavaMethod jm = jic.newJavaMethod("equals", boolean.class, JavaSource.PUBLIC); 486 DirectAccessible o = jm.addParam(Object .class, "o"); 487 jm.addIf(o, " == null || !(", o, " instanceof ", jic.getQName(), ")"); 488 jm.addLine("return false;"); 489 jm.addEndIf(); 490 LocalJavaField other = jm.newJavaField(jic.getQName(), "other"); 491 other.addLine("(", jic.getQName(), ") ", o); 492 jm.addIf("!", name, ".equals(", other, ".name) || ", values, ".length != ", 493 other, ".values.length"); 494 jm.addLine("return false;"); 495 jm.addEndIf(); 496 DirectAccessible loopVar = jm.addForArray(values); 497 LocalJavaField v = jm.newJavaField(Object .class, "v"); 498 v.addLine(values, "[", loopVar, "]"); 499 jm.addIf(v, " == null"); 500 jm.addIf(other, ".values[", loopVar, "] != null"); 501 jm.addLine("return false;"); 502 jm.addEndIf(); 503 jm.addElse(); 504 jm.addIf("!", v, ".equals(", other, ".values[", loopVar, "])"); 505 jm.addLine("return false;"); 506 jm.addEndIf(); 507 jm.addEndIf(); 508 jm.addEndFor(); 509 jm.addLine("return true;"); 510 } 511 512 return jic; 513 } 514 515 517 protected void setResultSetValue(JavaMethod pMethod, Column pColumn, 518 DirectAccessible pResultSet, 519 int pColumnNum, Object pTarget) { 520 Integer p = new Integer (pColumnNum+1); 521 522 Column.Type type = pColumn.getType(); 523 if (Column.Type.BIGINT.equals(type)) { 524 LocalJavaField l = pMethod.newJavaField(long.class); 525 l.addLine(pResultSet, ".getLong(", p, ");"); 526 pMethod.addIf("!", pResultSet, ".wasNull()"); 527 pMethod.addLine(pTarget, "[", Integer.toString(pColumnNum), "] = new ", 528 Long .class, "(", l, ");"); 529 pMethod.addEndIf(); 530 } else if (pColumn.isBinaryColumn()) { 531 pMethod.addLine(pTarget, "[", Integer.toString(pColumnNum), "] = ", 532 pResultSet, ".getBytes(", p, ");"); 533 } else if (Column.Type.BIT.equals(type)) { 534 LocalJavaField b = pMethod.newJavaField(boolean.class); 535 b.addLine(pResultSet, ".getBoolean(", p, ");"); 536 pMethod.addIf("!", pResultSet, ".wasNull()"); 537 pMethod.addLine(pTarget, "[", Integer.toString(pColumnNum), "] = ", b, 538 " ? ", Boolean .class, ".TRUE : ", Boolean .class, ".FALSE;"); 539 pMethod.addEndIf(); 540 } else if (pColumn.isStringColumn()) { 541 pMethod.addLine(pTarget, "[", Integer.toString(pColumnNum), "] = ", 542 pResultSet, ".getString(", p, ");"); 543 } else if (Column.Type.DATE.equals(type)) { 544 pMethod.addLine(pTarget, "[", Integer.toString(pColumnNum), "] = ", 545 pResultSet, ".getDate(", p, ");"); 546 } else if (Column.Type.DOUBLE.equals(type)) { 547 LocalJavaField d = pMethod.newJavaField(double.class); 548 d.addLine(pResultSet, ".getDouble(", p, ");"); 549 pMethod.addIf("!", pResultSet, ".wasNull()"); 550 pMethod.addLine(pTarget, "[", Integer.toString(pColumnNum), "] = new ", 551 Double .class, "(", d, ");"); 552 pMethod.addEndIf(); 553 } else if (Column.Type.FLOAT.equals(type)) { 554 LocalJavaField f = pMethod.newJavaField(float.class); 555 f.addLine(pResultSet, ".getFloat(", p, ");"); 556 pMethod.addIf("!", pResultSet, ".wasNull()"); 557 pMethod.addLine(pTarget, "[", Integer.toString(pColumnNum), "] = new ", 558 Float .class, "(", f, ");"); 559 pMethod.addEndIf(); 560 } else if (Column.Type.INTEGER.equals(type)) { 561 LocalJavaField i = pMethod.newJavaField(int.class); 562 i.addLine(pResultSet, ".getInt(", p, ");"); 563 pMethod.addIf("!", pResultSet, ".wasNull()"); 564 pMethod.addLine(pTarget, "[", Integer.toString(pColumnNum), "] = new ", 565 Integer .class, "(", i, ");"); 566 pMethod.addEndIf(); 567 } else if (Column.Type.SMALLINT.equals(type)) { 568 LocalJavaField s = pMethod.newJavaField(short.class); 569 s.addLine(pResultSet, ".getShort(", p, ");"); 570 pMethod.addIf("!", pResultSet, ".wasNull()"); 571 pMethod.addLine(pTarget, "[", Integer.toString(pColumnNum), "] = new ", 572 Short .class, "(", s, ");"); 573 pMethod.addEndIf(); 574 } else if (Column.Type.TIME.equals(type)) { 575 pMethod.addLine(pTarget, "[", Integer.toString(pColumnNum), "] = ", 576 pResultSet, ".getTime(", p, ");"); 577 } else if (Column.Type.TIMESTAMP.equals(type)) { 578 pMethod.addLine(pTarget, "[", Integer.toString(pColumnNum), "] = ", 579 pResultSet, ".getTimestamp(", p, ");"); 580 } else if (Column.Type.TINYINT.equals(type)) { 581 LocalJavaField b = pMethod.newJavaField(short.class); 582 b.addLine(pResultSet, ".getByte(", p, ");"); 583 pMethod.addIf("!", pResultSet, ".wasNull()"); 584 pMethod.addLine(pTarget, "[", Integer.toString(pColumnNum), "] = new ", 585 Byte .class, "(", b, ");"); 586 pMethod.addEndIf(); 587 } else { 588 throw new IllegalStateException ("Unknown column type: " + type); 589 } 590 } 591 592 594 protected void setPreparedStatementValue(JavaMethod pMethod, Column pColumn, 595 Object pStmt, Object pParamNum, 596 Object pValue) { 597 if (!(pValue instanceof DirectAccessible)) { 598 LocalJavaField v = pMethod.newJavaField(Object .class); 599 v.addLine(pValue); 600 pValue = v; 601 } 602 603 Column.Type type = pColumn.getType(); 604 pMethod.addIf(pValue, " == null"); 605 pMethod.addLine(pStmt, ".setNull(", pParamNum, ", ", Types .class, ".", 606 type, ");"); 607 pMethod.addElse(); 608 if (Column.Type.BIGINT.equals(type)) { 609 pMethod.addLine(pStmt, ".setLong(", pParamNum, ", ((", Long .class, 610 ") ", pValue, ").longValue());"); 611 } else if (pColumn.isBinaryColumn()) { 612 pMethod.addLine(pStmt, ".setBytes(", pParamNum, ", (", byte[].class, 613 ") ", pValue, ");"); 614 } else if (Column.Type.BIT.equals(type)) { 615 pMethod.addLine(pStmt, ".setBoolean(", pParamNum, ", ((", Boolean .class, 616 ") ", pValue, ").booleanValue());"); 617 } else if (pColumn.isStringColumn()) { 618 pMethod.addLine(pStmt, ".setString(", pParamNum, ", (", String .class, 619 ") ", pValue, ");"); 620 } else if (Column.Type.DATE.equals(type)) { 621 pMethod.addLine(pStmt, ".setDate(", pParamNum, ", (", Date .class, 622 ") ", pValue, ");"); 623 } else if (Column.Type.DOUBLE.equals(type)) { 624 pMethod.addLine(pStmt, ".setDouble(", pParamNum, ", ((", Double .class, 625 ") ", pValue, ").doubleValue());"); 626 } else if (Column.Type.FLOAT.equals(type)) { 627 pMethod.addLine(pStmt, ".setFloat(", pParamNum, ", ((", Float .class, 628 ") ", pValue, ").floatValue());"); 629 } else if (Column.Type.INTEGER.equals(type)) { 630 pMethod.addLine(pStmt, ".setInt(", pParamNum, ", ((", Integer .class, 631 ") ", pValue, ").intValue());"); 632 } else if (Column.Type.SMALLINT.equals(type)) { 633 pMethod.addLine(pStmt, ".setShort(", pParamNum, ", ((", Short .class, 634 ") ", pValue, ").shortValue());"); 635 } else if (Column.Type.TIME.equals(type)) { 636 pMethod.addLine(pStmt, ".setTime(", pParamNum, ", (", Time .class, 637 ") ", pValue, ");"); 638 } else if (Column.Type.TIMESTAMP.equals(type)) { 639 pMethod.addLine(pStmt, ".setTimestamp(", pParamNum, ", (", Timestamp .class, 640 ") ", pValue, ");"); 641 } else if (Column.Type.TINYINT.equals(type)) { 642 pMethod.addLine(pStmt, ".setByte(", pParamNum, ", ((", Byte .class, ") ", 643 pValue, ").byteValue());"); 644 } else { 645 throw new IllegalStateException ("Unknown column type: " + type); 646 } 647 648 pMethod.addEndIf(); 649 } 650 651 653 protected void getSelectRowsCode(JavaMethod pMethod, 654 TableInfo pTableInfo, 655 ColumnSet pColumnSet, 656 DirectAccessible pConn, 657 DirectAccessible pMap, 658 DirectAccessible pValues, 659 boolean pReturnValue) { 660 Table table = pTableInfo.getTable(); 661 SelectStatement statement = table.getSelectStatement(); 662 statement.getWhere().addColumnSetQuery(pColumnSet, statement.getTableReference()); 663 String s = table.getSchema().getSQLFactory().newSQLGenerator().getQuery(statement); 664 Object query = JavaSource.getQuoted(s); 665 if (isGeneratingLogging()) { 666 LocalJavaField q = pMethod.newJavaField(String .class); 667 q.addLine(query); 668 query = q; 669 logFinest(pMethod, query, pValues); 670 } 671 672 LocalJavaField stmt = pMethod.newJavaField(PreparedStatement .class); 673 stmt.addLine(pConn, ".prepareStatement(", JavaSource.getQuoted(s), ");"); 674 LocalJavaField isStmtClosed = pMethod.newJavaField(boolean.class); 675 isStmtClosed.addLine("false"); 676 pMethod.addTry(); 677 678 int paramNum = 0; 679 for (Iterator iter = pColumnSet.getColumns(); iter.hasNext(); ) { 680 Object v = new Object []{pValues, "[", Integer.toString(paramNum), "]"}; 681 Column column = (Column) iter.next(); 682 setPreparedStatementValue(pMethod, column, stmt, Integer.toString(++paramNum), v); 683 } 684 LocalJavaField rs = pMethod.newJavaField(ResultSet .class, "rs"); 685 rs.addLine(stmt, ".executeQuery()"); 686 LocalJavaField isRsClosed = pMethod.newJavaField(boolean.class); 687 isRsClosed.addLine("false"); 688 LocalJavaField result; 689 if (pReturnValue) { 690 result = pMethod.newJavaField(Object [].class, "result"); 691 result.addLine("null"); 692 } else { 693 result = null; 694 } 695 pMethod.addTry(); 696 697 pMethod.addWhile(rs, ".next()"); 698 if (result != null) { 699 pMethod.addIf(result, " != null"); 700 pMethod.addThrowNew(IllegalStateException .class, 701 JavaSource.getQuoted("Expected a single row only.")); 702 pMethod.addEndIf(); 703 } 704 705 int resultColumnSize = 0; 706 for (Iterator iter = table.getColumns(); iter.hasNext(); iter.next()) { 707 ++resultColumnSize; 708 } 709 LocalJavaField row = pMethod.newJavaField(Object [].class, "row"); 710 row.addLine("new ", Object .class, "[" + resultColumnSize + "];"); 711 712 int resultColumnNum = 0; 713 for (Iterator iter = table.getColumns(); iter.hasNext(); ) { 714 Column column = (Column) iter.next(); 715 setResultSetValue(pMethod, column, rs, resultColumnNum++, row); 716 } 717 718 pMethod.addLine(((result == null) ? "" : "result = "), 719 getInsertRowMethodName(pTableInfo), "(", pConn, ", ", pMap, ", ", 720 row, ");"); 721 722 pMethod.addEndWhile(); 723 pMethod.addLine(isRsClosed, " = true;"); 724 pMethod.addLine(rs, ".close();"); 725 726 pMethod.addFinally(); 727 pMethod.addIf("!", isRsClosed); 728 pMethod.addTry(); 729 pMethod.addLine(rs, ".close();"); 730 pMethod.addCatch(Throwable .class, "pIgnore"); 731 pMethod.addEndTry(); 732 pMethod.addEndIf(); 733 pMethod.addEndTry(); 734 735 pMethod.addLine(isStmtClosed, " = true;"); 736 pMethod.addLine(stmt, ".close();"); 737 if (result != null) { 738 logExiting(pMethod, result); 739 pMethod.addLine("return ", result, ";"); 740 } else { 741 logFinestExiting(pMethod, null); 742 } 743 744 pMethod.addFinally(); 745 pMethod.addIf("!", isStmtClosed); 746 pMethod.addTry(); 747 pMethod.addLine(stmt, ".close();"); 748 pMethod.addCatch(Throwable .class, "pIgnore"); 749 pMethod.addEndTry(); 750 pMethod.addEndIf(); 751 pMethod.addEndTry(); 752 753 } 754 755 758 protected String getInsertRowMethodName(TableInfo pTableInfo) { 759 return "clone" + pTableInfo.getPropertyName() + "Row"; 760 } 761 762 765 protected LocalJavaField getCacheDataClassInstance(JavaMethod pMethod, 766 TableInfo pTableInfo, 767 ColumnSet pColumnSet, 768 DirectAccessible pValues) { 769 Table table = pColumnSet.getTable(); 770 List params = new ArrayList (); 771 for (Iterator iter = pColumnSet.getColumns(); iter.hasNext(); ) { 772 Column primaryKeyColumn = (Column) iter.next(); 773 int index = -1; 774 int i = 0; 775 for (Iterator iter2 = table.getColumns(); iter2.hasNext(); ++i) { 776 Column tableColumn = (Column) iter2.next(); 777 if (tableColumn.equals(primaryKeyColumn)) { 778 index = i; 779 break; 780 } 781 } 782 if (index == -1) { 783 throw new IllegalStateException ("Key column " + primaryKeyColumn.getQName() + " not found."); 784 } 785 if (params.size() > 0) { 786 params.add(", "); 787 } 788 params.add(new Object []{pValues, "[" + index + "]"}); 789 } 790 791 JavaQName cacheDataClass = getCacheDataClassName(pMethod.getJavaSource().getQName()); 792 LocalJavaField jf = pMethod.newJavaField(cacheDataClass); 793 jf.addLine("new ", cacheDataClass, "(", 794 JavaSource.getQuoted(pTableInfo.getPropertyName()), 795 ", new ", Object [].class, "{", params, "})"); 796 return jf; 797 } 798 799 802 protected void getApplyCacheData(JavaMethod pMethod, 803 TableInfo pTableInfo, 804 ColumnSet pColumnSet, 805 DirectAccessible pRow, 806 DirectAccessible pData) { 807 Table table = pTableInfo.getTable(); 808 for (Iterator iter = pColumnSet.getColumns(); iter.hasNext(); ) { 809 Column primaryKeyColumn = (Column) iter.next(); 810 int index = -1; 811 int i = 0; 812 for (Iterator iter2 = table.getColumns(); iter2.hasNext(); ++i) { 813 Column tableColumn = (Column) iter2.next(); 814 if (tableColumn.equals(primaryKeyColumn)) { 815 index = i; 816 break; 817 } 818 } 819 if (index == -1) { 820 throw new IllegalStateException ("Key column " + primaryKeyColumn.getQName() + " not found."); 821 } 822 pMethod.addLine(pRow, "[" + index + "] = ", pData, "[" + (i+1) + "];"); 823 } 824 } 825 826 828 protected JavaMethod getInsertRowMethod(JavaSource pSource, TableInfo pTableInfo) { 829 Table table = pTableInfo.getTable(); 830 JavaMethod jm = pSource.newJavaMethod(getInsertRowMethodName(pTableInfo), 831 Object [].class, JavaSource.PRIVATE); 832 jm.addThrows(SQLException .class); 833 DirectAccessible connection = jm.addParam(Connection .class, "pConn"); 834 DirectAccessible map = jm.addParam(Map .class, "pMap"); 835 DirectAccessible values = jm.addParam(Object [].class, "pValue"); 836 837 logFinestEntering(jm, values); 838 839 LocalJavaField baseKey = null; 840 if (table.getPrimaryKey() != null) { 841 baseKey = getCacheDataClassInstance(jm, pTableInfo, 842 table.getPrimaryKey(), values); 843 jm.addIf(map, ".containsKey(", baseKey, ")"); 844 logFinestExiting(jm, JavaSource.getQuoted("null (Already cloned)")); 845 jm.addLine("return null;"); 846 jm.addEndIf(); 847 } 848 849 for (Iterator iter = pTableInfo.getColumnUpdaters(); iter.hasNext(); ) { 850 ((ColumnUpdater) iter.next()).update(jm, pTableInfo, connection, map, values); 851 } 852 853 jm.addLine(jm.getName(), "(", connection, ", ", values, ");"); 854 855 if (baseKey != null) { 856 LocalJavaField clonedKey = getCacheDataClassInstance(jm, pTableInfo, 857 table.getPrimaryKey(), 858 values); 859 jm.addLine(map, ".put(", baseKey, ", ", clonedKey, ");"); 860 } 861 862 863 LocalJavaField referencedValues = null; 865 for (Iterator referencingIter = tablesByOrder.iterator(); referencingIter.hasNext(); ) { 866 TableInfo prevTableInfo = (TableInfo) referencingIter.next(); 867 Table prevTable = prevTableInfo.getTable(); 868 for (Iterator fkIter = prevTable.getForeignKeys(); fkIter.hasNext(); ) { 869 ForeignKey fk = (ForeignKey) fkIter.next(); 870 if (fk.getReferencedTable().equals(table)) { 871 if (referencedValues == null) { 872 referencedValues = jm.newJavaField(Object [].class); 873 referencedValues.addLine(baseKey, ".getValues()"); 874 } 875 getSelectRowsCode(jm, prevTableInfo, fk, connection, map, referencedValues, false); 876 } 877 } 878 } 879 880 logFinestExiting(jm, values); 881 jm.addLine("return ", values, ";"); 882 883 return jm; 884 } 885 886 888 protected JavaMethod getInnerInsertRowMethod(JavaSource pSource, TableInfo pTableInfo) { 889 Table table = pTableInfo.getTable(); 890 JavaMethod jm = pSource.newJavaMethod(getInsertRowMethodName(pTableInfo), 891 JavaQNameImpl.VOID, JavaSource.PRIVATE); 892 jm.addThrows(SQLException .class); 893 DirectAccessible connection = jm.addParam(Connection .class, "pConn"); 894 DirectAccessible values = jm.addParam(Object [].class, "pValue"); 895 896 logFinestEntering(jm, null); 897 898 InsertStatement insertStatement = table.getInsertStatement(); 899 String s = table.getSchema().getSQLFactory().newSQLGenerator().getQuery(insertStatement); 900 Object query = JavaSource.getQuoted(s); 901 if (isGeneratingLogging()) { 902 LocalJavaField q = jm.newJavaField(String .class); 903 q.addLine(query); 904 query = q; 905 logFinest(jm, query, values); 906 } 907 LocalJavaField stmt = jm.newJavaField(PreparedStatement .class, "stmt"); 908 stmt.setFinal(true); 909 stmt.addLine(connection, ".prepareStatement(", query, ");"); 910 LocalJavaField isStmtClosed = jm.newJavaField(boolean.class, "isStmtClosed"); 911 isStmtClosed.addLine("false"); 912 jm.addTry(); 913 914 int paramNum = 0; 915 for (Iterator iter = table.getColumns(); iter.hasNext(); ) { 916 Column column = (Column) iter.next(); 917 Object v = new Object []{ values, "[", Integer.toString(paramNum), "]" }; 918 setPreparedStatementValue(jm, column, stmt, Integer.toString(++paramNum), v); 919 } 920 921 jm.addLine(stmt, ".executeUpdate();"); 922 jm.addLine(isStmtClosed, " = true;"); 923 jm.addLine(stmt, ".close();"); 924 925 jm.addFinally(); 926 jm.addIf("!", isStmtClosed); 927 jm.addTry(); 928 jm.addLine(stmt, ".close();"); 929 jm.addCatch(Throwable .class, "ignore"); 930 jm.addEndTry(); 931 jm.addEndIf(); 932 jm.addEndTry(); 933 934 logFinestExiting(jm, null); 935 return jm; 936 } 937 938 939 941 protected JavaMethod getPublicCloneMethod(JavaSource pSource) { 942 TableInfo headTable; 943 { 944 Iterator iter = tablesByOrder.iterator(); 945 if (!iter.hasNext()) { 946 throw new IllegalStateException ("No tables have been added."); 947 } 948 headTable = (TableInfo) iter.next(); 949 } 950 951 JavaQName resultType = JavaQNameImpl.getInstance(Object [].class); 952 JavaMethod jm = pSource.newJavaMethod("clone", resultType, JavaSource.PUBLIC); 953 jm.addThrows(SQLException .class); 954 JavaComment jc = jm.newComment(); 955 jc.addLine("<p>This method takes as input the key values of a row in the table " + 956 headTable.getTable().getQName() + "."); 957 jc.addLine("The key values are given by the array <code>pRow</code>:"); 958 jc.addLine("<ul>"); 959 int i = 0; 960 for (Iterator iter = headTable.getTable().getPrimaryKey().getColumns(); 961 iter.hasNext(); i++) { 962 Column col = (Column) iter.next(); 963 jc.addLine(" <li><code>pRow[" + i+ "] = " + col.getQName() + "</code></li>"); 964 } 965 jc.addLine("</ul>"); 966 jc.addLine("The method updates the rows version number and creates a new row"); 967 jc.addLine("with the updated values.</p>"); 968 { 969 Iterator iter = tablesByOrder.iterator(); 970 iter.next(); 971 if (iter.hasNext()) { 972 jc.addLine("<p>Once the new row is created, the method searches for entries"); 973 jc.addLine("referencing the old row in the following tables:"); 974 jc.addLine("<table>"); 975 do { 976 TableInfo subTable = (TableInfo) iter.next(); 977 jc.addLine(" <tr><td>" + subTable.getTable().getQName() + "</td></tr>"); 978 } while (iter.hasNext()); 979 jc.addLine("All the referencing entries are cloned as well, with updated"); 980 jc.addLine("references."); 981 } 982 } 983 984 DirectAccessible conn = jm.addParam(Connection .class, "pConn"); 985 DirectAccessible row = jm.addParam(resultType, "pRow"); 986 987 logEntering(jm, new Object []{"new ", Object [].class, "{", conn, ", ", row, "}"}); 988 989 LocalJavaField map = jm.newJavaField(Map .class, "clonedObjects"); 990 map.addLine("new ", HashMap .class, "()"); 991 992 getSelectRowsCode(jm, headTable, headTable.getTable().getPrimaryKey(), 993 conn, map, row, true); 994 return jm; 995 } 996 997 999 public JavaMethod getCloneMethod(JavaSource pSource) { 1000 initLogging(pSource); 1001 1002 for (Iterator iter = tablesByOrder.iterator(); iter.hasNext(); ) { 1003 TableInfo tableInfo = (TableInfo) iter.next(); 1004 1005 getInsertRowMethod(pSource, tableInfo); 1006 getInnerInsertRowMethod(pSource, tableInfo); 1007 } 1008 getCacheDataClass(pSource); 1009 getPublicCloneMethod(pSource); 1010 1011 return null; 1012 } 1013} 1014 | Popular Tags |