001package gu.sql2java.generator; 002 003import java.sql.DatabaseMetaData; 004import java.sql.Types; 005import java.text.SimpleDateFormat; 006import java.util.Calendar; 007import java.util.Date; 008import java.util.List; 009import java.util.Random; 010import java.util.Vector; 011import java.util.regex.Matcher; 012import java.util.regex.Pattern; 013 014import org.apache.commons.lang.builder.EqualsBuilder; 015import org.apache.commons.lang.builder.ToStringBuilder; 016 017import com.google.common.base.Function; 018import com.google.common.base.Strings; 019import com.google.common.collect.ImmutableMap; 020import com.google.common.collect.Maps; 021import com.google.common.primitives.Primitives; 022 023import gu.sql2java.generator.CodeWriter; 024import gu.sql2java.generator.Database; 025import gu.sql2java.generator.StringUtilities; 026import gu.sql2java.generator.Table; 027 028public class Column implements Cloneable, Comparable<Column>,MappedType { 029 private String catalog; 030 private String schema; 031 private String tableName; 032 private String name; 033 private String remarks; 034 private String defaultValue; 035 private int size; 036 private int decDigits; 037 private int radix; 038 private int nullable; 039 private int ordinal; 040 private short type; 041 private boolean isPrimaryKey; 042 private String strCheckingType = ""; 043 private String autoincrement; 044 private Database db; 045 private List<Column> foreignKeys = new Vector<Column>(); 046 private List<Column> importedKeys = new Vector<Column>(); 047 private String typeName = ""; 048 private static Random rand = new Random(); 049 050 @Override 051 public String toString() { 052 return new ToStringBuilder(this) 053 .append("catalog",catalog) 054 .append("schema",schema) 055 .append("tableName",tableName) 056 .append("name",name) 057 .append("remarks",remarks) 058 .append("defaultValue",defaultValue) 059 .append("size",size) 060 .append("decDigits",decDigits) 061 .append("radix",radix) 062 .append("nullable",nullable) 063 .append("ordinal",ordinal) 064 .append("type",type) 065 .append("isPrimaryKey",isPrimaryKey) 066 .append("autoincrement",autoincrement) 067 .append("typeName",typeName) 068 .toString(); 069 } 070 071 @Override 072 public boolean equals(Object obj) { 073 if(super.equals(obj))return true; 074 if(!(obj instanceof Column))return false; 075 Column other = (Column)obj; 076 return new EqualsBuilder() 077 .append(catalog,other.catalog) 078 .append(schema,other.schema) 079 .append(tableName,other.tableName) 080 .append(name,other.name) 081 .append(remarks,other.remarks) 082 .append(defaultValue,other.defaultValue) 083 .append(size,other.size) 084 .append(decDigits,other.decDigits) 085 .append(radix,other.radix) 086 .append(nullable,other.nullable) 087 .append(ordinal,other.ordinal) 088 .append(type,other.type) 089 .append(isPrimaryKey,other.isPrimaryKey) 090 .append(autoincrement,other.autoincrement) 091 .append(typeName,other.typeName) 092 .isEquals(); 093 } 094 095 public void setCheckingType(String strValue) { 096 this.strCheckingType = strValue; 097 } 098 099 public String getCheckingType() { 100 return this.strCheckingType; 101 } 102 103 public void setDatabase(Database db) { 104 this.db = db; 105 } 106 107 public void setCatalog(String catalog) { 108 this.catalog = catalog; 109 } 110 111 public void setSchema(String schema) { 112 this.schema = schema; 113 } 114 115 public void setTableName(String tableName) { 116 this.tableName = tableName; 117 } 118 119 public void setName(String name) { 120 this.name = null == name ? "" : name.replaceAll("\\W", ""); 121 } 122 123 public void setType(short type) { 124 this.type = type; 125 } 126 127 public void setSize(int size) { 128 this.size = size; 129 } 130 131 public void setDecimalDigits(int decDigits) { 132 this.decDigits = decDigits; 133 } 134 135 public void setRadix(int radix) { 136 this.radix = radix; 137 } 138 139 public void setNullable(int nullable) { 140 this.nullable = nullable; 141 } 142 143 public void setRemarks(String remarks) { 144 if (remarks != null) { 145 this.remarks = remarks.replaceAll("/\\*", "SLASH*").replaceAll("\\*/", "*SLASH"); 146 } 147 } 148 149 public void setDefaultValue(String defaultValue) { 150 this.defaultValue = defaultValue; 151 } 152 153 public void setOrdinalPosition(int ordinal) { 154 this.ordinal = ordinal; 155 } 156 157 public void isPrimaryKey(boolean isKey) { 158 this.isPrimaryKey = isKey; 159 } 160 161 public String getCatalog() { 162 return this.catalog; 163 } 164 165 public String getSchema() { 166 return this.schema; 167 } 168 169 public String getTableName() { 170 return this.tableName; 171 } 172 173 public String getName() { 174 return this.name; 175 } 176 177 public short getType() { 178 return this.type; 179 } 180 181 public int getSize() { 182 return this.size; 183 } 184 185 public int getDecimalDigits() { 186 return this.decDigits; 187 } 188 189 public int getRadix() { 190 return this.radix; 191 } 192 193 public int getNullable() { 194 return this.nullable; 195 } 196 197 public String getNullableAsString() { 198 return this.getNullable() != 0 ? "nullable" : "null not allowed"; 199 } 200 201 public int getOrdinalPosition() { 202 return this.ordinal; 203 } 204 205 public boolean isPrimaryKey() { 206 return this.isPrimaryKey; 207 } 208 209 public String getFullName() { 210 return this.tableName + "." + this.getName(); 211 } 212 213 public String getConstName() { 214 return this.getName().toUpperCase(); 215 } 216 217 public String getIDConstName() { 218 return (this.tableName + "_ID_" + this.getName()).toUpperCase(); 219 } 220 public String getIDMaskConstName() { 221 return (this.tableName + "_ID_" + this.getName()).toUpperCase() + "_MASK"; 222 } 223 public Object clone() throws CloneNotSupportedException { 224 return super.clone(); 225 } 226 227 private void tuoe() { 228 throw new UnsupportedOperationException("Not supported yet: " + this.getTableName() + "." + this.getName() + " " 229 + this.getJavaTypeAsTypeName()); 230 } 231 232 private void tiae() { 233 throw new IllegalArgumentException("No primary type associated: " + this.getTableName() + "." + this.getName()); 234 } 235 236 public int getMappedType() { 237 switch (this.getType()) { 238 case Types.ARRAY : { 239 return M_ARRAY; 240 } 241 case Types.BIGINT : { 242 return M_LONG; 243 } 244 case Types.BINARY : { 245 return M_BYTES; 246 } 247 case Types.BIT : { 248 return M_BOOLEAN; 249 } 250 case Types.BLOB : { 251 return M_BLOB; 252 } 253 case Types.BOOLEAN : { 254 return M_BOOLEAN; 255 } 256 case Types.CHAR : { 257 return M_STRING; 258 } 259 case Types.CLOB : { 260 return M_CLOB; 261 } 262 case Types.DATALINK : { 263 return M_URL; 264 } 265 case Types.DATE : { 266 if ("java.util.Date".equals(CodeWriter.dateClassName)) { 267 return M_UTILDATE; 268 } 269 if ("java.sql.Date".equals(CodeWriter.dateClassName)) { 270 return M_SQLDATE; 271 } 272 if ("java.util.Calendar".equals(CodeWriter.dateClassName)) { 273 return M_CALENDAR; 274 } 275 this.tuoe(); 276 } 277 case Types.DECIMAL : { 278 return this.getDecimalDigits() > 0 ? M_BIGDECIMAL : M_LONG; 279 } 280 case Types.DISTINCT : { 281 return M_OBJECT; 282 } 283 case Types.DOUBLE : { 284 return M_DOUBLE; 285 } 286 case Types.FLOAT : { 287 return M_DOUBLE; 288 } 289 case Types.INTEGER : { 290 return this.getTypeName().equalsIgnoreCase("INT UNSIGNED") ? M_LONG : M_INTEGER; 291 } 292 case Types.JAVA_OBJECT : { 293 return M_OBJECT; 294 } 295 case Types.LONGVARBINARY : { 296 return M_BYTES; 297 } 298 case Types.LONGVARCHAR : { 299 return M_STRING; 300 } 301 case Types.NUMERIC : { 302 return this.getDecimalDigits() > 0 ? M_BIGDECIMAL : M_LONG; 303 } 304 case Types.OTHER : { 305 return M_OBJECT; 306 } 307 case Types.REAL : { 308 return M_FLOAT; 309 } 310 case Types.REF : { 311 return M_REF; 312 } 313 case Types.SMALLINT : { 314 return M_INTEGER; 315 } 316 case Types.STRUCT : { 317 return M_OBJECT; 318 } 319 case Types.TIME : { 320 if ("java.util.Date".equals(CodeWriter.timeClassName)) { 321 return M_UTILDATE; 322 } 323 if ("java.sql.Time".equals(CodeWriter.timeClassName)) { 324 return M_TIME; 325 } 326 if ("java.util.Calendar".equals(CodeWriter.timeClassName)) { 327 return M_CALENDAR; 328 } 329 this.tuoe(); 330 } 331 case Types.TIMESTAMP : { 332 if ("java.util.Date".equals(CodeWriter.timestampClassName)) { 333 return M_UTILDATE; 334 } 335 if ("java.sql.Timestamp".equals(CodeWriter.timestampClassName)) { 336 return M_TIMESTAMP; 337 } 338 if ("java.util.Calendar".equals(CodeWriter.timestampClassName)) { 339 return M_CALENDAR; 340 } 341 this.tuoe(); 342 } 343 case Types.TINYINT : { 344 return M_INTEGER; 345 } 346 case Types.VARBINARY : { 347 return M_BYTES; 348 } 349 case Types.VARCHAR : { 350 return M_STRING; 351 } 352 } 353 this.tuoe(); 354 return -1; 355 } 356 357 public String getQuerySetMethod() { 358 switch (this.getType()) { 359 case Types.ARRAY : { 360 return "setArray"; 361 } 362 case Types.BIGINT : { 363 return "setBigDecimal"; 364 } 365 case Types.BINARY : { 366 return "setBytes"; 367 } 368 case Types.BIT : { 369 return "setBoolean"; 370 } 371 case Types.BLOB : { 372 return "setBlob"; 373 } 374 case Types.BOOLEAN : { 375 return "setBoolean"; 376 } 377 case Types.CHAR : { 378 return "setString"; 379 } 380 case Types.CLOB : { 381 return "setClob"; 382 } 383 case Types.DATALINK : { 384 return "setURL"; 385 } 386 case Types.DATE : { 387 return "setDate"; 388 } 389 case Types.DECIMAL : { 390 return this.getDecimalDigits() > 0 ? "setBigDecimal" : "setLong"; 391 } 392 case Types.DISTINCT : { 393 return "setObject"; 394 } 395 case Types.DOUBLE : { 396 return "setDouble"; 397 } 398 case Types.FLOAT : { 399 return "setDouble"; 400 } 401 case Types.INTEGER : { 402 return this.getTypeName().equalsIgnoreCase("INT UNSIGNED") ? "setLong" : "setInt"; 403 } 404 case Types.JAVA_OBJECT : { 405 return "setObject"; 406 } 407 case Types.LONGVARBINARY : { 408 return "setBytes"; 409 } 410 case Types.LONGVARCHAR : { 411 return "setString"; 412 } 413 case Types.NUMERIC : { 414 return this.getDecimalDigits() > 0 ? "setBigDecimal" : "setLong"; 415 } 416 case Types.OTHER : { 417 return "setObject"; 418 } 419 case Types.REAL : { 420 return "setFloat"; 421 } 422 case Types.REF : { 423 return "setRef"; 424 } 425 case Types.SMALLINT : { 426 return "setInt"; 427 } 428 case Types.STRUCT : { 429 return "setObject"; 430 } 431 case Types.TIME : { 432 if ("java.util.Date".equals(CodeWriter.timeClassName)) { 433 return "setDate"; 434 } 435 if ("java.sql.Time".equals(CodeWriter.timeClassName)) { 436 return "setTime"; 437 } 438 this.tuoe(); 439 } 440 case Types.TIMESTAMP : { 441 if ("java.util.Date".equals(CodeWriter.timestampClassName)) { 442 return "setDate"; 443 } 444 if ("java.sql.Timestamp".equals(CodeWriter.timestampClassName)) { 445 return "setTimestamp"; 446 } 447 this.tuoe(); 448 } 449 case Types.TINYINT : { 450 return "setInt"; 451 } 452 case Types.VARBINARY : { 453 return "setBytes"; 454 } 455 case Types.VARCHAR : { 456 return "setString"; 457 } 458 } 459 this.tuoe(); 460 return "setObject"; 461 } 462 463 /** 464 * 返回对应的Java类型,除java语言内置类型(java.lang)外,其他类型返回全名 465 * @return 466 */ 467 public String getJavaType() { 468 switch (this.getMappedType()) { 469 case M_ARRAY : { 470 return "java.sql.Array"; 471 } 472 case M_BIGDECIMAL : { 473 return "java.math.BigDecimal"; 474 } 475 case M_BOOLEAN : { 476 return "Boolean"; 477 } 478 case M_BYTES : { 479 return CodeWriter.binaryClassName; 480 } 481 case M_CLOB : { 482 // map Clob to java.lang.String 483 return "String"; 484 } 485 case M_SQLDATE : { 486 return "java.sql.Date"; 487 } 488 case M_UTILDATE : { 489 return "java.util.Date"; 490 } 491 case M_DOUBLE : { 492 return "Double"; 493 } 494 case M_FLOAT : { 495 return "Float"; 496 } 497 case M_BLOB : { 498 return CodeWriter.binaryClassName; 499 } 500 case M_INTEGER : { 501 return "Integer"; 502 } 503 case M_LONG : { 504 return "Long"; 505 } 506 case M_REF : { 507 return "java.sql.Ref"; 508 } 509 case M_STRING : { 510 return "String"; 511 } 512 case M_TIME : { 513 return "java.sql.Time"; 514 } 515 case M_TIMESTAMP : { 516 return "java.sql.Timestamp"; 517 } 518 case M_URL : { 519 return "java.net.URL"; 520 } 521 case M_OBJECT : { 522 return "Object"; 523 } 524 case M_CALENDAR : { 525 return "java.util.Calendar"; 526 } 527 } 528 this.tiae(); 529 return null; 530 } 531 532 public boolean hasPrimaryType() { 533 return this.getJavaPrimaryType() != null; 534 } 535 536 public String getJavaPrimaryType() throws IllegalArgumentException { 537 int decimalDigits = this.getDecimalDigits(); 538 if ((this.type == Types.DECIMAL || this.type == Types.NUMERIC) && decimalDigits == 0) { 539 if (this.size == 1) { 540 return "boolean"; 541 } 542 if (this.size < 3) { 543 return "byte"; 544 } 545 if (this.size < 5) { 546 return "short"; 547 } 548 if (this.size < 10) { 549 return "int"; 550 } 551 if (this.size < 19) { 552 return "long"; 553 } 554 } 555 switch (this.getMappedType()) { 556 case M_BOOLEAN : { 557 return "boolean"; 558 } 559 case M_SQLDATE : { 560 return "long"; 561 } 562 case M_UTILDATE : { 563 return "long"; 564 } 565 case M_DOUBLE : { 566 return "double"; 567 } 568 case M_FLOAT : { 569 return "float"; 570 } 571 case M_INTEGER : { 572 return "int"; 573 } 574 case M_LONG : { 575 return "long"; 576 } 577 case M_TIME : { 578 return "long"; 579 } 580 case M_TIMESTAMP : { 581 return "long"; 582 } 583 } 584 return null; 585 } 586 587 public String getNullInstead(){ 588 if(isDate()){ 589 return "new "+getJavaType() + "(0L)"; 590 }else if(isString()){ 591 return "\"\""; 592 }else{ 593 String primitiveName = getJavaPrimaryType(); 594 if(null != primitiveName){ 595 ImmutableMap<String, Class<?>> primtypes = Maps.uniqueIndex(Primitives.allWrapperTypes(),new Function<Class<?>,String>(){ 596 @Override 597 public String apply(Class<?> input) { 598 return Primitives.unwrap(input).getSimpleName(); 599 }}); 600 Class<?> wrapType = primtypes.get(primitiveName); 601 if(Number.class.isAssignableFrom(wrapType) || Character.class==wrapType){ 602 return wrapType.getSimpleName()+".MIN_VALUE"; 603 }else if(Boolean.class == wrapType) 604 return wrapType.getSimpleName()+".FALSE"; 605 tuoe(); 606 } 607 } 608 return "null"; 609 } 610 public String getJavaTypeAsTypeName() { 611 switch (this.getType()) { 612 case Types.ARRAY : { 613 return "Types.ARRAY"; 614 } 615 case Types.BIGINT : { 616 return "Types.BIGINT"; 617 } 618 case Types.BINARY : { 619 return "Types.BINARY"; 620 } 621 case Types.BIT : { 622 return "Types.BIT"; 623 } 624 case Types.BLOB : { 625 return "Types.BLOB"; 626 } 627 case Types.BOOLEAN : { 628 return "Types.BOOLEAN"; 629 } 630 case Types.CHAR : { 631 return "Types.CHAR"; 632 } 633 case Types.CLOB : { 634 return "Types.CLOB"; 635 } 636 case Types.DATALINK : { 637 return "Types.DATALINK"; 638 } 639 case Types.DATE : { 640 return "Types.DATE"; 641 } 642 case Types.DECIMAL : { 643 return "Types.DECIMAL"; 644 } 645 case Types.DISTINCT : { 646 return "Types.DISTINCT"; 647 } 648 case Types.DOUBLE : { 649 return "Types.DOUBLE"; 650 } 651 case Types.FLOAT : { 652 return "Types.FLOAT"; 653 } 654 case Types.INTEGER : { 655 return "Types.INTEGER"; 656 } 657 case Types.JAVA_OBJECT : { 658 return "Types.JAVA_OBJECT"; 659 } 660 case Types.LONGVARBINARY : { 661 return "Types.LONGVARBINARY"; 662 } 663 case Types.LONGVARCHAR : { 664 return "Types.LONGVARCHAR"; 665 } 666 case Types.NULL : { 667 return "Types.NULL"; 668 } 669 case Types.NUMERIC : { 670 return "Types.NUMERIC"; 671 } 672 case Types.OTHER : { 673 return "Types.OTHER"; 674 } 675 case Types.REAL : { 676 return "Types.REAL"; 677 } 678 case Types.REF : { 679 return "Types.REF"; 680 } 681 case Types.SMALLINT : { 682 return "Types.SMALLINT"; 683 } 684 case Types.STRUCT : { 685 return "Types.STRUCT"; 686 } 687 case Types.TIME : { 688 return "Types.TIME"; 689 } 690 case Types.TIMESTAMP : { 691 return "Types.TIMESTAMP"; 692 } 693 case Types.TINYINT : { 694 return "Types.TINYINT"; 695 } 696 case Types.VARBINARY : { 697 return "Types.VARBINARY"; 698 } 699 case Types.VARCHAR : { 700 return "Types.VARCHAR"; 701 } 702 } 703 return "unkown SQL type " + this.getType(); 704 } 705 706 public boolean isColumnNumeric() { 707 switch (this.getMappedType()) { 708 case M_BIGDECIMAL : 709 case M_DOUBLE : 710 case M_FLOAT : 711 case M_INTEGER : 712 case M_LONG : { 713 return true; 714 } 715 } 716 return false; 717 } 718 719 public boolean isString() { 720 return M_STRING == this.getMappedType(); 721 } 722 public boolean isFloat() { 723 return M_FLOAT == this.getMappedType(); 724 } 725 public boolean isDate() { 726 switch (this.getMappedType()) { 727 case M_SQLDATE: 728 case M_UTILDATE : 729 case M_TIME : 730 case M_TIMESTAMP : 731 return true; 732 } 733 return false; 734 } 735 public boolean isBinary() { 736 switch (this.getMappedType()) { 737 case M_BYTES: 738 case M_BLOB: 739 return true; 740 } 741 return false; 742 } 743 public boolean isCalendar() { 744 return this.getMappedType() == M_CALENDAR; 745 } 746 747 public boolean hasCompareTo() throws Exception { 748 switch (this.getMappedType()) { 749 case M_ARRAY : { 750 return false; 751 } 752 case M_BIGDECIMAL : { 753 return true; 754 } 755 case M_BOOLEAN : { 756 return true; 757 } 758 case M_BYTES : { 759 return CodeWriter.binaryIsByteBuffer(); 760 } 761 case M_CLOB : { 762 // Clob map to java.lang.String that has compareTo 763 return true; 764 } 765 case M_SQLDATE : { 766 return true; 767 } 768 case M_UTILDATE : { 769 return true; 770 } 771 case M_DOUBLE : { 772 return true; 773 } 774 case M_FLOAT : { 775 return true; 776 } 777 case M_BLOB : { 778 return CodeWriter.binaryIsByteBuffer(); 779 } 780 case M_INTEGER : { 781 return true; 782 } 783 case M_LONG : { 784 return true; 785 } 786 case M_REF : { 787 return false; 788 } 789 case M_STRING : { 790 return true; 791 } 792 case M_TIME : { 793 return true; 794 } 795 case M_TIMESTAMP : { 796 return true; 797 } 798 case M_URL : { 799 return false; 800 } 801 case M_OBJECT : { 802 return false; 803 } 804 case M_CALENDAR : { 805 return true; 806 } 807 } 808 return false; 809 } 810 811 public boolean useEqualsInSetter() throws Exception { 812 // 优先使用equals方法 813 if(hasCompareTo())return true; 814 switch (this.getMappedType()) { 815 case M_BOOLEAN : { 816 return true; 817 } 818 case M_URL : { 819 return true; 820 } 821 } 822 return false; 823 } 824 825 public String getResultSetMethodObject(String pos) { 826 return this.getResultSetMethodObject("rs", pos); 827 } 828 829 public String getResultSetMethodObject(String resultSet, String pos) { 830 switch (this.getMappedType()) { 831 case M_ARRAY : { 832 return resultSet + ".getArray(" + pos + ")"; 833 } 834 case M_LONG : { 835 return CodeWriter.MGR_CLASS + ".getLong(" + resultSet + ", " + pos + ")"; 836 } 837 case M_BYTES : { 838 return CodeWriter.MGR_CLASS + ".getBytes(" + resultSet + ", " + pos + ")"; 839 } 840 case M_BLOB : { 841 return CodeWriter.MGR_CLASS + ".getBlob(" + resultSet + ", " + pos + ")"; 842 } 843 case M_BOOLEAN : { 844 return CodeWriter.MGR_CLASS + ".getBoolean(" + resultSet + ", " + pos + ")"; 845 } 846 case M_STRING : { 847 return resultSet + ".getString(" + pos + ")"; 848 } 849 case M_CLOB : { 850 return CodeWriter.MGR_CLASS + ".getClob(" + resultSet + ", " + pos + ")"; 851 } 852 case M_URL : { 853 return resultSet + ".getURL(" + pos + ")"; 854 } 855 case M_BIGDECIMAL : { 856 return resultSet + ".getBigDecimal(" + pos + ")"; 857 } 858 case M_DOUBLE : { 859 return CodeWriter.MGR_CLASS + ".getDouble(" + resultSet + ", " + pos + ")"; 860 } 861 case M_FLOAT : { 862 return CodeWriter.MGR_CLASS + ".getFloat(" + resultSet + ", " + pos + ")"; 863 } 864 case M_INTEGER : { 865 return CodeWriter.MGR_CLASS + ".getInteger(" + resultSet + ", " + pos + ")"; 866 } 867 case M_OBJECT : { 868 return resultSet + ".getObject(" + pos + ")"; 869 } 870 case M_REF : { 871 return resultSet + ".getRef(" + pos + ")"; 872 } 873 case M_SQLDATE : { 874 return resultSet + ".getDate(" + pos + ")"; 875 } 876 case M_TIME : { 877 return resultSet + ".getTime(" + pos + ")"; 878 } 879 case M_TIMESTAMP : { 880 return resultSet + ".getTimestamp(" + pos + ")"; 881 } 882 case M_UTILDATE : { 883 switch (this.getType()) { 884 case Types.TIME : { 885 return resultSet + ".getTime(" + pos + ")"; 886 } 887 case Types.TIMESTAMP : { 888 return resultSet + ".getTimestamp(" + pos + ")"; 889 } 890 case Types.DATE : { 891 return resultSet + ".getDate(" + pos + ")"; 892 } 893 } 894 this.tuoe(); 895 } 896 case M_CALENDAR : { 897 return CodeWriter.MGR_CLASS + ".getCalendar(" + resultSet + ", " + pos + ")"; 898 } 899 } 900 this.tuoe(); 901 return null; 902 } 903 904 public String getPreparedStatementMethod(String var, int pos) { 905 return this.getPreparedStatementMethod(var, String.valueOf(pos)); 906 } 907 908 public String getPreparedStatementMethod(String var, String pos) { 909 StringBuffer sb = new StringBuffer(); 910 StringBuffer end = new StringBuffer(); 911 end.append(pos).append(", ").append(var).append(");"); 912 String fillNullStart = Boolean.TRUE == CodeWriter.getFillNull() ? "" : "if(fillNull){"; 913 String fillNullEnd = Boolean.TRUE == CodeWriter.getFillNull() ? "" : "}"; 914 Pattern p = Pattern.compile("^((?:SQL_LIKE_WILDCARD\\s*\\+)*)([\\w\\. \\(\\)-]*)((?:\\+\\s*SQL_LIKE_WILDCARD)*)$"); 915 916 Matcher m = p.matcher(var); 917 if(!m.matches()){ 918 throw new IllegalArgumentException(String.format("Not match found %s", var)); 919 } 920 String v = m.group(2); 921 sb.append("if (").append(v).append(" == null) {"+fillNullStart+" ps.setNull(").append(pos).append(", ") 922 .append(this.getJavaTypeAsTypeName()).append(");").append(fillNullEnd).append(" } else { "); 923 end.append(" }"); 924 switch (this.getMappedType()) { 925 case M_ARRAY : { 926 return sb.append("ps.setArray(").append(end).toString(); 927 } 928 case M_LONG : { 929 return sb.append(CodeWriter.MGR_CLASS).append(".setLong(ps, ").append(end).toString(); 930 } 931 case M_BYTES : { 932 return sb.append(CodeWriter.MGR_CLASS).append(".setBytes("+this.getJavaTypeAsTypeName()+",ps, ").append(end).toString(); 933 } 934 case M_BLOB : { 935 return sb.append(CodeWriter.MGR_CLASS).append(".setBlob(ps, ").append(end).toString(); 936 } 937 case M_BOOLEAN : { 938 return sb.append(CodeWriter.MGR_CLASS).append(".setBoolean(ps, ").append(end).toString(); 939 } 940 case M_STRING : { 941 return sb.append("ps.setString(").append(end).toString(); 942 } 943 case M_CLOB : { 944 return sb.append(CodeWriter.MGR_CLASS).append(".setClob(ps, ").append(end).toString(); 945 } 946 case M_URL : { 947 return sb.append("ps.setURL(").append(end).toString(); 948 } 949 case M_BIGDECIMAL : { 950 return sb.append("ps.setBigDecimal(").append(end).toString(); 951 } 952 case M_DOUBLE : { 953 return sb.append(CodeWriter.MGR_CLASS).append(".setDouble(ps, ").append(end).toString(); 954 } 955 case M_INTEGER : { 956 return sb.append(CodeWriter.MGR_CLASS).append(".setInteger(ps, ").append(end).toString(); 957 } 958 case M_OBJECT : { 959 return sb.append("ps.setObject(").append(end).toString(); 960 } 961 case M_FLOAT : { 962 return sb.append(CodeWriter.MGR_CLASS).append(".setFloat(ps, ").append(end).toString(); 963 } 964 case M_SQLDATE : { 965 return sb.append("ps.setDate(").append(end).toString(); 966 } 967 case M_TIME : { 968 return sb.append("ps.setTime(").append(end).toString(); 969 } 970 case M_TIMESTAMP : { 971 return sb.append("ps.setTimestamp(").append(end).toString(); 972 } 973 case M_UTILDATE : { 974 switch (this.getType()) { 975 case Types.TIMESTAMP : { 976 return sb.append("ps.setTimestamp(").append(pos).append(", new java.sql.Timestamp(").append(var) 977 .append(".getTime())); }").toString(); 978 } 979 case Types.DATE : { 980 return sb.append("ps.setDate(").append(pos).append(", new java.sql.Date(").append(var) 981 .append(".getTime())); }").toString(); 982 } 983 case Types.TIME : { 984 return sb.append("ps.setTime(").append(pos).append(", new java.sql.Time(").append(var) 985 .append(".getTime())); }").toString(); 986 } 987 } 988 return null; 989 } 990 case M_CALENDAR : { 991 return sb.append(CodeWriter.MGR_CLASS).append(".setCalendar(ps, ").append(end).toString(); 992 } 993 case M_REF : { 994 sb.setLength(0); 995 sb.append("ps.setRef(").append(end); 996 sb.setLength(sb.length() - 2); 997 return sb.toString(); 998 } 999 } 1000 sb.setLength(0); 1001 sb.append("ps.setObject(").append(end); 1002 sb.setLength(sb.length() - 2); 1003 return sb.toString(); 1004 } 1005 1006 public String getStringConvertionMethod() { 1007 switch (this.getMappedType()) { 1008 case M_BIGDECIMAL : { 1009 return "new java.math.BigDecimal"; 1010 } 1011 case M_BOOLEAN : { 1012 return "new Boolean"; 1013 } 1014 case M_SQLDATE : { 1015 return "new java.sql.Date"; 1016 } 1017 case M_DOUBLE : { 1018 return "new Double"; 1019 } 1020 case M_FLOAT : { 1021 return "new Float"; 1022 } 1023 case M_INTEGER : { 1024 return "new Integer"; 1025 } 1026 case M_LONG : { 1027 return "new Long"; 1028 } 1029 case M_STRING : { 1030 return ""; 1031 } 1032 case M_UTILDATE : 1033 case M_TIME : 1034 case M_TIMESTAMP : { 1035 if ("java.util.GregorianCalendar".equals(CodeWriter.dateClassName)) { 1036 return "GregorianDate"; 1037 } 1038 return CodeWriter.MGR_CLASS + ".getDateFromString"; 1039 } 1040 } 1041 System.err.println( 1042 " unknown mapped type " + this.getMappedType() + " (" + this.getType() + ") for " + this.getFullName()); 1043 return ""; 1044 } 1045 1046 public String getDefaultWidget() { 1047 if (this.isForeignKey()) { 1048 return "SelectWidget"; 1049 } 1050 if (this.isString() && (this.getSize() > 200 || this.getSize() == -1)) { 1051 return "TextAreaWidget"; 1052 } 1053 switch (this.getMappedType()) { 1054 case M_BOOLEAN : { 1055 return "BooleanWidget"; 1056 } 1057 case M_SQLDATE : 1058 case M_UTILDATE : 1059 case M_TIME : 1060 case M_TIMESTAMP : { 1061 return "DateWidget"; 1062 } 1063 case M_BIGDECIMAL : 1064 case M_DOUBLE : 1065 case M_FLOAT : 1066 case M_INTEGER : 1067 case M_LONG : { 1068 return "NumericWidget"; 1069 } 1070 case M_ARRAY : 1071 case M_BYTES : 1072 case M_CLOB : 1073 case M_REF : 1074 case M_STRING : 1075 case M_URL : 1076 case M_OBJECT : { 1077 return "InputWidget"; 1078 } 1079 } 1080 System.err.println("type unknown for " + this.getFullName()); 1081 return ""; 1082 } 1083 1084 public boolean isVersion() { 1085 if (!CodeWriter.optimisticLockType.equalsIgnoreCase("timestamp")) { 1086 return false; 1087 } 1088 if (!this.getName().equalsIgnoreCase(CodeWriter.optimisticLockColumn)) { 1089 return false; 1090 } 1091 if (this.getMappedType() == M_LONG || this.getMappedType() == M_STRING) { 1092 return true; 1093 } 1094 return false; 1095 } 1096 1097 public Table getTable() { 1098 return this.db.getTable(this.getTableName()); 1099 } 1100 1101 public void addForeignKey(Column col, 1102 String fkName, 1103 short keySeq, 1104 Table.ForeignKeyRule updateRule, 1105 Table.ForeignKeyRule deleteRule) { 1106 this.foreignKeys.add(col); 1107 this.getTable().addForeignKey(this, fkName,keySeq, updateRule, deleteRule); 1108 } 1109 1110 public List<Column> getForeignKeys() { 1111 return this.foreignKeys; 1112 } 1113 1114 public void addImportedKey(Column col) { 1115 this.importedKeys.add(col); 1116 this.getTable().addImportedKey(col); 1117 } 1118 1119 public List<Column> getImportedKeys() { 1120 return this.importedKeys; 1121 } 1122 1123 public int countImportedKeys() { 1124 return this.importedKeys.size(); 1125 } 1126 1127 public boolean isImportedKey() { 1128 if (this.countImportedKeys() > 0) { 1129 return true; 1130 } 1131 return false; 1132 } 1133 1134 public Column getForeignColumn() { 1135 return (Column) this.foreignKeys.get(0); 1136 } 1137 1138 public int countForeignKeys() { 1139 return this.foreignKeys.size(); 1140 } 1141 1142 public boolean isForeignKey() { 1143 if (this.countForeignKeys() > 0) { 1144 return true; 1145 } 1146 return false; 1147 } 1148 1149 public String getPropertyTag() { 1150 return (this.getTableName() + "." + this.getName()).toLowerCase(); 1151 } 1152 1153 public String getDefaultRules() { 1154 String rule = ""; 1155 rule = this.getNullable() == 0 && !this.isPrimaryKey() ? rule + " nullnotallowed" : rule + " nullallowed"; 1156 if (this.getType() == 91 || this.getType() == 93) { 1157 rule = rule + " dateformat"; 1158 } 1159 return rule; 1160 } 1161 1162 public boolean getDefaultIncludeFor(String webElement) { 1163 return true; 1164 } 1165 1166 private static final String EMPTY_STRING = ""; 1167 /** 1168 * 生成缺省值字符串 1169 * @param nullInstead 指示{@link #defaultValue}为 {@code null}时是否用字符串'null'代替 1170 * @return 1171 */ 1172 public String getDefaultValue(boolean nullInstead) { 1173 String empty = nullInstead?"null":EMPTY_STRING; 1174 if(!CodeWriter.getPropertyBoolean("codewriter.generate.defaultvalue")){ 1175 return empty; 1176 } 1177 if (null != this.defaultValue) { 1178 if (this.isColumnNumeric()) { 1179 try { 1180 double value = Double.parseDouble(this.defaultValue); 1181 switch (this.getMappedType()) { 1182 case M_BIGDECIMAL : 1183 case M_INTEGER : 1184 case M_LONG : { 1185 return this.generateNewNumeric(this.getJavaType(), this.defaultValue); 1186 } 1187 case M_DOUBLE : 1188 case M_FLOAT : { 1189 return this.generateNewNumeric(this.getJavaType(), String.valueOf(value)); 1190 } 1191 } 1192 return empty; 1193 } catch (NumberFormatException nfe) { 1194 return empty; 1195 } 1196 } 1197 if (this.isDate()) { 1198 try { 1199 return generateDateDefaultValue(this.getJavaType(),this.defaultValue); 1200 } catch (IllegalArgumentException pe) { 1201 return empty; 1202 } 1203 } 1204 if (this.isString()) { 1205 return "\"" + this.defaultValue + '\"'; 1206 } 1207 if (M_BOOLEAN == this.getMappedType()) { 1208 return "Boolean.valueOf(\"" + ("1".equals(this.defaultValue) ? "true" : "false") 1209 + "\").booleanValue()"; 1210 } 1211 } 1212 return this.defaultValue == null ? empty : this.defaultValue; 1213 } 1214 /** 兼容之前版本 */ 1215 public String getDefaultValue() { 1216 return getDefaultValue(false); 1217 } 1218 /** 返回{@link #defaultValue}原始值 */ 1219 public String getOriginalDefaultValue(){ 1220 return this.defaultValue; 1221 } 1222 /** SQL 类型日期字符串转为java 日期对象 */ 1223 private static Date parseSqlDate(String source){ 1224 if(null == source) 1225 throw new IllegalArgumentException(); 1226 try{ 1227 return java.sql.Date.valueOf(source); 1228 }catch(IllegalArgumentException e){ 1229 try{ 1230 return java.sql.Time.valueOf(source); 1231 }catch(IllegalArgumentException e2){ 1232 return java.sql.Timestamp.valueOf(source); 1233 } 1234 } 1235 } 1236 /** 生成日期类型缺省值语句 */ 1237 private String generateDateDefaultValue(String type, String parameter) { 1238 StringBuffer sb = new StringBuffer(100); 1239 Date parsedDate = parseSqlDate(parameter); 1240 String dateStr; 1241 switch(this.getMappedType()){ 1242 case M_UTILDATE:{ 1243 String instanceName=""; 1244 if(parsedDate instanceof java.sql.Date){ 1245 instanceName = "new java.text.SimpleDateFormat(\"yyyy-MM-dd\")"; 1246 }else if(parsedDate instanceof java.sql.Time){ 1247 instanceName = "new java.text.SimpleDateFormat(\"HH:mm:ss\")"; 1248 }else if(parsedDate instanceof java.sql.Timestamp){ 1249 instanceName = "new java.text.SimpleDateFormat(\"yyyy-MM-dd HH:mm:ss\")"; 1250 }else{ 1251 throw new IllegalStateException("invalid type"); 1252 } 1253 sb.append(instanceName).append(".parse(\"").append(parsedDate.toString()).append("\",new java.text.ParsePosition(0))"); 1254 break; 1255 } 1256 case M_SQLDATE:{ 1257 dateStr = new java.sql.Date(parsedDate.getTime()).toString(); 1258 sb.append(type).append(".valueOf(\"").append(dateStr).append("\")"); 1259 break; 1260 } 1261 case M_TIME:{ 1262 dateStr = new java.sql.Time(parsedDate.getTime()).toString(); 1263 sb.append(type).append(".valueOf(\"").append(dateStr).append("\")"); 1264 break; 1265 } 1266 case M_TIMESTAMP:{ 1267 dateStr = new java.sql.Timestamp(parsedDate.getTime()).toString(); 1268 sb.append(type).append(".valueOf(\"").append(dateStr).append("\")"); 1269 break; 1270 } 1271 default: 1272 return EMPTY_STRING; 1273 } 1274 return sb.toString(); 1275 } 1276 1277 private String generateNewNumeric(String type, String parameter) { 1278 StringBuffer sb = new StringBuffer(70); 1279 sb.append("new ").append(type); 1280 sb.append('(').append(parameter).append(')'); 1281 return sb.toString(); 1282 } 1283 1284 /** 生成缺省值({@link #defaultValue})的注释信息 */ 1285 public String commentOfDefaultValue(){ 1286 return Strings.isNullOrEmpty(defaultValue)?EMPTY_STRING: "/* DEFAULT:'"+defaultValue+"'*/"; 1287 } 1288 /** 生成缺省值赋值语句 */ 1289 public String getDefaultValueAssignment(boolean nullInstead){ 1290 StringBuffer buffer = new StringBuffer(); 1291 String value = getDefaultValue(nullInstead); 1292 if(!value.isEmpty()) 1293 buffer.append(" = ").append(value); 1294 return buffer.toString(); 1295 } 1296 public String getRemarks() { 1297 return this.remarks == null ? "" : this.remarks; 1298 } 1299 1300 public String getJavaName() { 1301 return this.convertName(this.getName()); 1302 } 1303 1304 public String getSampleData() { 1305 if (this.getNullable() > 1 && rand.nextInt(20) == 10) { 1306 return ""; 1307 } 1308 if (this.isColumnNumeric()) { 1309 return "" + rand.nextInt(100); 1310 } 1311 if (this.isDate()) { 1312 Calendar rightNow = Calendar.getInstance(); 1313 rightNow.set(2000 + rand.nextInt(20), 1 + rand.nextInt(12), 1 + rand.nextInt(28), rand.nextInt(23), 1314 rand.nextInt(60), rand.nextInt(60)); 1315 SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss"); 1316 return dateFormat.format(rightNow.getTime()); 1317 } 1318 return StringUtilities.getSampleString((int) this.getSize()); 1319 } 1320 1321 private String escape(String s) { 1322 return StringUtilities.escape((String) s); 1323 } 1324 1325 private String escape() { 1326 return this.escape(this.getName()); 1327 } 1328 1329 public String convertName(String columnName) { 1330 return StringUtilities.convertName((String) columnName, true); 1331 } 1332 1333 public String convertName(Column col) { 1334 return this.convertName(col.getName()); 1335 } 1336 1337 public String convertName() { 1338 return this.convertName(this.name); 1339 } 1340 1341 public String getImportedKeyVarName() { 1342 return this.convertName(this.escape() + "_collection"); 1343 } 1344 1345 public String getGetMethod() { 1346 return this.convertName("get_" + this.escape()); 1347 } 1348 1349 public String getSetMethod() { 1350 return this.convertName("set_" + this.escape()); 1351 } 1352 public String getReadMethod() { 1353 return this.convertName("read_" + this.escape()); 1354 } 1355 public String getWriteMethod() { 1356 return this.convertName("write_" + this.escape()); 1357 } 1358 public String getModifiedMethod() { 1359 return this.convertName("check_" + this.escape() + "_modified"); 1360 } 1361 1362 public String getInitializedMethod() { 1363 return this.convertName("check_" + this.escape() + "_initialized"); 1364 } 1365 public String getGetCacheMethod() { 1366 return this.convertName("get_bean_by_" + this.escape()); 1367 } 1368 public String getPutCacheMethod() { 1369 return this.convertName("put_by_" + this.escape()); 1370 } 1371 public String getPutIfAbsentCacheMethod() { 1372 return this.convertName("put_If_absent_by_" + this.escape()); 1373 } 1374 public String getReplaceCacheMethod() { 1375 return this.convertName("replace_by_" + this.escape()); 1376 } 1377 1378 public String bitAndExpression(String varName){ 1379 if(this.getTable().countColumns()>32){ 1380 int pos = getOrdinalPosition()-1; 1381 return String.format("(%s[%d] & (1 << %d))",varName,pos>>6,pos & 0x3f); 1382 }else{ 1383 return String.format("(%s & %s)", varName,getIDMaskConstName()); 1384 } 1385 } 1386 1387 public String bitORAssignExpression(String varName){ 1388 if(this.getTable().countColumns()>32){ 1389 int pos = getOrdinalPosition()-1; 1390 return String.format("%s[%d] |= (1 << %d)",varName,pos>>6,pos & 0x3f); 1391 }else{ 1392 return String.format("%s |= %s", varName,getIDMaskConstName()); 1393 } 1394 } 1395 public String bitResetAssignExpression(String varName){ 1396 if(this.getTable().countColumns()>32){ 1397 int pos = getOrdinalPosition()-1; 1398 return String.format("%s[%d] &= (~(1 << %d))",varName,pos>>6,pos & 0x3f); 1399 }else{ 1400 return String.format("%s &= (~%s)", varName,getIDMaskConstName()); 1401 } 1402 } 1403 public String getWidgetMethod() { 1404 return this.convertName("get_" + this.escape() + "_widget"); 1405 } 1406 1407 public String getVarName() { 1408 return this.convertName(this.escape()); 1409 } 1410 public String getCacheVarName() { 1411 return this.convertName(this.escape() + "_cacher"); 1412 } 1413 public String getFullVarName() { 1414 return this.convertName(this.name +"_of_" + this.getTable().getBasename(true)); 1415 } 1416 public String getModifiedVarName() { 1417 return this.convertName(this.escape() + "_is_modified"); 1418 } 1419 1420 public String getInitializedVarName() { 1421 return this.convertName(this.escape() + "_is_initialized"); 1422 } 1423 1424 public String getImportedKeyModifiedVarName() { 1425 return this.convertName(this.escape() + "_collection_is_modified"); 1426 } 1427 1428 public String getImportedKeyInitializedVarName() { 1429 return this.convertName(this.escape() + "_collection_is_initialized"); 1430 } 1431 1432 public String getImportedKeyInitializedMethod() { 1433 return this.convertName("is_" + this.escape() + "_collection_initialized"); 1434 } 1435 1436 public String getImportedKeyGetMethod() { 1437 return this.convertName("get_" + this.escape() + "_collection"); 1438 } 1439 1440 public String getImportedKeyAddMethod() { 1441 return this.convertName("add_" + this.escape() + ""); 1442 } 1443 1444 public String getImportedKeySetMethod() { 1445 return this.convertName("set_" + this.escape() + "_collection"); 1446 } 1447 1448 public String getImportedKeyModifiedMethod() { 1449 return this.convertName("is_" + this.escape() + "_collection_modified"); 1450 } 1451 1452 public String getForeignKeyVarName() { 1453 return this.convertName(this.escape() + "_object"); 1454 } 1455 1456 public String getForeignKeyModifiedVarName() { 1457 return this.convertName(this.escape() + "_object_is_modified"); 1458 } 1459 1460 public String getForeignKeyInitializedVarName() { 1461 return this.convertName(this.escape() + "_object_is_initialized"); 1462 } 1463 1464 public String getForeignKeyInitializedMethod() { 1465 return this.convertName("is_" + this.escape() + "_object_initialized"); 1466 } 1467 1468 public String getForeignKeyGetMethod(String col) { 1469 return this.convertName("get_" + this.escape() + "_object"); 1470 } 1471 1472 public String getForeignKeySetMethod(String col) { 1473 return this.convertName("set_" + this.escape() + "_object"); 1474 } 1475 1476 public String getForeignKeyModifiedMethod(String col) { 1477 return this.convertName("is_" + this.escape() + "_object_modified"); 1478 } 1479 1480 public String getTypeName() { 1481 return this.typeName; 1482 } 1483 1484 public void setTypeName(String typeName) { 1485 this.typeName = typeName; 1486 } 1487 1488 public int compareTo(Column obj) { 1489 return this.ordinal - obj.ordinal; 1490 } 1491 1492 public String getAutoincrement() { 1493 return autoincrement; 1494 } 1495 1496 public void setAutoincrement(String autoincrement) { 1497 this.autoincrement = autoincrement; 1498 } 1499 public boolean isAutoincrement(){ 1500 return "YES".equals(this.autoincrement); 1501 } 1502 public boolean isNotNull(){ 1503 return DatabaseMetaData.columnNoNulls == this.nullable ; 1504 } 1505}