View Javadoc
1 package org.apache.torque.engine.database.model; 2 3 /* ==================================================================== 4 * The Apache Software License, Version 1.1 5 * 6 * Copyright (c) 2001-2003 The Apache Software Foundation. All rights 7 * reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in 18 * the documentation and/or other materials provided with the 19 * distribution. 20 * 21 * 3. The end-user documentation included with the redistribution, 22 * if any, must include the following acknowledgment: 23 * "This product includes software developed by the 24 * Apache Software Foundation (http://www.apache.org/)." 25 * Alternately, this acknowledgment may appear in the software itself, 26 * if and wherever such third-party acknowledgments normally appear. 27 * 28 * 4. The names "Apache" and "Apache Software Foundation" and 29 * "Apache Turbine" must not be used to endorse or promote products 30 * derived from this software without prior written permission. For 31 * written permission, please contact apache@apache.org. 32 * 33 * 5. Products derived from this software may not be called "Apache", 34 * "Apache Turbine", nor may "Apache" appear in their name, without 35 * prior written permission of the Apache Software Foundation. 36 * 37 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED 38 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 39 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 40 * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR 41 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 42 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 43 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 44 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 45 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 46 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 47 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 48 * SUCH DAMAGE. 49 * ==================================================================== 50 * 51 * This software consists of voluntary contributions made by many 52 * individuals on behalf of the Apache Software Foundation. For more 53 * information on the Apache Software Foundation, please see 54 * <http://www.apache.org/>. 55 */ 56 57 import java.util.ArrayList; 58 import java.util.Date; 59 import java.util.Hashtable; 60 import java.util.List; 61 62 import org.apache.commons.lang.StringUtils; 63 64 import org.apache.commons.logging.Log; 65 import org.apache.commons.logging.LogFactory; 66 67 import org.apache.torque.engine.EngineException; 68 69 import org.xml.sax.Attributes; 70 71 /*** 72 * A Class for holding data about a column used in an Application. 73 * 74 * @author <a href="mailto:leon@opticode.co.za">Leon Messerschmidt</a> 75 * @author <a href="mailto:jvanzyl@apache.org">Jason van Zyl</a> 76 * @author <a href="mailto:jon@latchkey.com">Jon S. Stevens</a> 77 * @author <a href="mailto:dlr@finemaltcoding.com">Daniel Rall</a> 78 * @author <a href="mailto:byron_foster@byron_foster@yahoo.com>Byron Foster</a> 79 * @version $Id: Column.java,v 1.5 2003/08/08 09:15:12 mpoeschl Exp $ 80 */ 81 public class Column 82 { 83 /*** Logging class from commons.logging */ 84 private static Log log = LogFactory.getLog(Column.class); 85 private String name; 86 private String description; 87 private String javaName = null; 88 private String javaNamingMethod; 89 private boolean isNotNull = false; 90 private String size; 91 /*** type as defined in schema.xml */ 92 private String torqueType; 93 private String javaType; 94 private Object columnType; 95 private Table parentTable; 96 private int position; 97 private boolean isPrimaryKey = false; 98 private boolean isUnique = false; 99 private boolean isAutoIncrement = false; 100 private String defaultValue; 101 private List referrers; 102 // only one type is supported currently, which assumes the 103 // column either contains the classnames or a key to 104 // classnames specified in the schema. Others may be 105 // supported later. 106 private String inheritanceType; 107 private boolean isInheritance; 108 private boolean isEnumeratedClasses; 109 private List inheritanceList; 110 private boolean needsTransactionInPostgres; 111 112 /*** class name to do input validation on this column */ 113 private String inputValidator = null; 114 115 /*** 116 * Creates a new instance with a <code>null</code> name. 117 */ 118 public Column() 119 { 120 this(null); 121 } 122 123 /*** 124 * Creates a new column and set the name 125 * 126 * @param name column name 127 */ 128 public Column(String name) 129 { 130 this.name = name; 131 } 132 133 /*** 134 * Return a comma delimited string listing the specified columns. 135 * 136 * @param columns Either a list of <code>Column</code> objects, or 137 * a list of <code>String</code> objects with column names. 138 */ 139 public static String makeList(List columns) 140 { 141 Object obj = columns.get(0); 142 boolean isColumnList = (obj instanceof Column); 143 if (isColumnList) 144 { 145 obj = ((Column) obj).getName(); 146 } 147 StringBuffer buf = new StringBuffer((String) obj); 148 for (int i = 1; i < columns.size(); i++) 149 { 150 obj = columns.get(i); 151 if (isColumnList) 152 { 153 obj = ((Column) obj).getName(); 154 } 155 buf.append(", ").append(obj); 156 } 157 return buf.toString(); 158 } 159 160 /*** 161 * Imports a column from an XML specification 162 */ 163 public void loadFromXML(Attributes attrib) 164 { 165 //Name 166 name = attrib.getValue("name"); 167 168 javaName = attrib.getValue("javaName"); 169 javaType = attrib.getValue("javaType"); 170 if (javaType != null && javaType.length() == 0) 171 { 172 javaType = null; 173 } 174 175 // retrieves the method for converting from specified name to 176 // a java name. 177 javaNamingMethod = attrib.getValue("javaNamingMethod"); 178 if (javaNamingMethod == null) 179 { 180 javaNamingMethod 181 = parentTable.getDatabase().getDefaultJavaNamingMethod(); 182 } 183 184 //Primary Key 185 String primaryKey = attrib.getValue("primaryKey"); 186 //Avoid NullPointerExceptions on string comparisons. 187 isPrimaryKey = ("true".equals (primaryKey)); 188 189 // If this column is a primary key then it can't be null. 190 if ("true".equals (primaryKey)) 191 { 192 isNotNull = true; 193 } 194 195 // HELP: Should primary key, index, and/or idMethod="native" 196 // affect isNotNull? If not, please document why here. 197 String notNull = attrib.getValue("required"); 198 isNotNull = (notNull != null && "true".equals(notNull)); 199 200 //AutoIncrement/Sequences 201 String autoIncrement = attrib.getValue("autoIncrement"); 202 isAutoIncrement = ("true".equals(autoIncrement)); 203 204 //Default column value. 205 defaultValue = attrib.getValue("default"); 206 207 size = attrib.getValue("size"); 208 209 setType(attrib.getValue("type")); 210 211 inheritanceType = attrib.getValue("inheritance"); 212 isInheritance = (inheritanceType != null 213 && !inheritanceType.equals("false")); 214 215 this.inputValidator = attrib.getValue("inputValidator"); 216 description = attrib.getValue("description"); 217 } 218 219 /*** 220 * Returns table.column 221 */ 222 public String getFullyQualifiedName() 223 { 224 return (parentTable.getName() + '.' + name); 225 } 226 227 /*** 228 * Get the name of the column 229 */ 230 public String getName() 231 { 232 return name; 233 } 234 235 /*** 236 * Set the name of the column 237 */ 238 public void setName(String newName) 239 { 240 name = newName; 241 } 242 243 /*** 244 * Get the description for the Table 245 */ 246 public String getDescription() 247 { 248 return description; 249 } 250 251 /*** 252 * Set the description for the Table 253 * 254 * @param newDescription description for the Table 255 */ 256 public void setDescription(String newDescription) 257 { 258 description = newDescription; 259 } 260 261 /*** 262 * Get name to use in Java sources to build method names. 263 * 264 * @return the capitalised javaName 265 */ 266 public String getJavaName() 267 { 268 if (javaName == null) 269 { 270 List inputs = new ArrayList(2); 271 inputs.add(name); 272 inputs.add(javaNamingMethod); 273 try 274 { 275 javaName = NameFactory.generateName(NameFactory.JAVA_GENERATOR, 276 inputs); 277 } 278 catch (EngineException e) 279 { 280 log.error(e, e); 281 } 282 } 283 return StringUtils.capitalise(javaName); 284 } 285 286 /*** 287 * Get variable name to use in Java sources (= uncapitalised java name) 288 */ 289 public String getUncapitalisedJavaName() 290 { 291 return StringUtils.uncapitalise(getJavaName()); 292 } 293 294 /*** 295 * Set name to use in Java sources 296 */ 297 public void setJavaName(String javaName) 298 { 299 this.javaName = javaName; 300 } 301 302 /*** 303 * Get type to use in Java sources 304 */ 305 public String getJavaType() 306 { 307 return javaType; 308 } 309 310 /*** 311 * Get the location of this column within the table (one-based). 312 * @return value of position. 313 */ 314 public int getPosition() 315 { 316 return position; 317 } 318 319 /*** 320 * Get the location of this column within the table (one-based). 321 * @param v Value to assign to position. 322 */ 323 public void setPosition(int v) 324 { 325 this.position = v; 326 } 327 328 /*** 329 * Set the parent Table of the column 330 */ 331 public void setTable(Table parent) 332 { 333 parentTable = parent; 334 } 335 336 /*** 337 * Get the parent Table of the column 338 */ 339 public Table getTable() 340 { 341 return parentTable; 342 } 343 344 /*** 345 * Returns the Name of the table the column is in 346 */ 347 public String getTableName() 348 { 349 return parentTable.getName(); 350 } 351 352 /*** 353 * A utility function to create a new column 354 * from attrib and add it to this table. 355 */ 356 public Inheritance addInheritance(Attributes attrib) 357 { 358 Inheritance inh = new Inheritance(); 359 inh.loadFromXML (attrib); 360 addInheritance(inh); 361 362 return inh; 363 } 364 365 /*** 366 * Adds a new inheritance definition to the inheritance list and set the 367 * parent column of the inheritance to the current column 368 */ 369 public void addInheritance(Inheritance inh) 370 { 371 inh.setColumn(this); 372 if (inheritanceList == null) 373 { 374 inheritanceList = new ArrayList(); 375 isEnumeratedClasses = true; 376 } 377 inheritanceList.add(inh); 378 } 379 380 /*** 381 * Get the inheritance definitions. 382 */ 383 public List getChildren() 384 { 385 return inheritanceList; 386 } 387 388 /*** 389 * Determine if this column is a normal property or specifies a 390 * the classes that are represented in the table containing this column. 391 */ 392 public boolean isInheritance() 393 { 394 return isInheritance; 395 } 396 397 /*** 398 * Determine if possible classes have been enumerated in the xml file. 399 */ 400 public boolean isEnumeratedClasses() 401 { 402 return isEnumeratedClasses; 403 } 404 405 /*** 406 * Return the isNotNull property of the column 407 */ 408 public boolean isNotNull() 409 { 410 return isNotNull; 411 } 412 413 /*** 414 * Set the isNotNull property of the column 415 */ 416 public void setNotNull(boolean status) 417 { 418 isNotNull = status; 419 } 420 421 /*** 422 * Set if the column is a primary key or not 423 */ 424 public void setPrimaryKey(boolean pk) 425 { 426 isPrimaryKey = pk; 427 } 428 429 /*** 430 * Return true if the column is a primary key 431 */ 432 public boolean isPrimaryKey() 433 { 434 return isPrimaryKey; 435 } 436 437 /*** 438 * Set true if the column is UNIQUE 439 */ 440 public void setUnique (boolean u) 441 { 442 isUnique = u; 443 } 444 445 /*** 446 * Get the UNIQUE property 447 */ 448 public boolean isUnique() 449 { 450 return isUnique; 451 } 452 453 /*** 454 * Return true if the column requires a transaction in Postgres 455 */ 456 public boolean requiresTransactionInPostgres() 457 { 458 return needsTransactionInPostgres; 459 } 460 461 /*** 462 * Utility method to determine if this column is a foreign key. 463 */ 464 public boolean isForeignKey() 465 { 466 return (getForeignKey() != null); 467 } 468 469 /*** 470 * Determine if this column is a foreign key that refers to the 471 * same table as another foreign key column in this table. 472 */ 473 public boolean isMultipleFK() 474 { 475 ForeignKey fk = getForeignKey(); 476 if (fk != null) 477 { 478 ForeignKey[] fks = parentTable.getForeignKeys(); 479 for (int i = 0; i < fks.length; i++) 480 { 481 if (fks[i].getForeignTableName() 482 .equals(fk.getForeignTableName()) 483 && !fks[i].getLocalColumns().contains(this.name)) 484 { 485 return true; 486 } 487 } 488 } 489 490 // No multiple foreign keys. 491 return false; 492 } 493 494 /*** 495 * get the foreign key object for this column 496 * if it is a foreign key or part of a foreign key 497 */ 498 public ForeignKey getForeignKey() 499 { 500 return parentTable.getForeignKey (this.name); 501 } 502 503 /*** 504 * Utility method to get the related table of this column if it is a foreign 505 * key or part of a foreign key 506 */ 507 public String getRelatedTableName() 508 { 509 ForeignKey fk = getForeignKey(); 510 return (fk == null ? null : fk.getForeignTableName()); 511 } 512 513 514 /*** 515 * Utility method to get the related column of this local column if this 516 * column is a foreign key or part of a foreign key. 517 */ 518 public String getRelatedColumnName() 519 { 520 ForeignKey fk = getForeignKey(); 521 if (fk == null) 522 { 523 return null; 524 } 525 else 526 { 527 return fk.getLocalForeignMapping().get(this.name).toString(); 528 } 529 } 530 531 /*** 532 * Adds the foreign key from another table that refers to this column. 533 */ 534 public void addReferrer(ForeignKey fk) 535 { 536 if (referrers == null) 537 { 538 referrers = new ArrayList(5); 539 } 540 referrers.add(fk); 541 } 542 543 /*** 544 * Get list of references to this column. 545 */ 546 public List getReferrers() 547 { 548 if (referrers == null) 549 { 550 referrers = new ArrayList(5); 551 } 552 return referrers; 553 } 554 555 /*** 556 * Returns the colunm type 557 */ 558 public void setType(String torqueType) 559 { 560 this.torqueType = torqueType; 561 if (torqueType.equals("VARBINARY") || torqueType.equals("BLOB")) 562 { 563 needsTransactionInPostgres = true; 564 } 565 } 566 567 /*** 568 * Returns the column jdbc type as an object 569 */ 570 public Object getType() 571 { 572 return TypeMap.getJdbcType(torqueType); 573 } 574 575 /*** 576 * Returns the column type as given in the schema as an object 577 */ 578 public Object getTorqueType() 579 { 580 return torqueType; 581 } 582 583 /*** 584 * Utility method to see if the column is a string 585 */ 586 public boolean isString() 587 { 588 return (columnType instanceof String); 589 } 590 591 /*** 592 * Utility method to return the value as an element to be usable 593 * in an SQL insert statement. This is used from the SQL loader task 594 */ 595 public boolean needEscapedValue() 596 { 597 return (torqueType != null) && 598 ( torqueType.equals("VARCHAR") 599 || torqueType.equals("LONGVARCHAR") 600 || torqueType.equals("DATE") 601 || torqueType.equals("DATETIME") 602 || torqueType.equals("TIMESTAMP") 603 || torqueType.equals("CHAR")); 604 } 605 606 /*** 607 * String representation of the column. This is an xml representation. 608 * 609 * @return string representation in xml 610 */ 611 public String toString() 612 { 613 StringBuffer result = new StringBuffer(); 614 result.append(" <column name=\"").append(name).append('"'); 615 616 if (javaName != null) 617 { 618 result.append(" javaName=\"").append(javaName).append('"'); 619 } 620 621 if (isPrimaryKey) 622 { 623 result.append(" primaryKey=\"").append(isPrimaryKey).append('"'); 624 } 625 626 if (isNotNull) 627 { 628 result.append(" required=\"true\""); 629 } 630 else 631 { 632 result.append(" required=\"false\""); 633 } 634 635 result.append(" type=\"").append (torqueType).append('"'); 636 637 if (size != null) 638 { 639 result.append(" size=\"").append(size).append('"'); 640 } 641 642 if (defaultValue != null) 643 { 644 result.append(" default=\"").append(defaultValue).append('"'); 645 } 646 647 if (isInheritance()) 648 { 649 result.append(" inheritance=\"").append(inheritanceType) 650 .append('"'); 651 } 652 653 // Close the column. 654 result.append(" />\n"); 655 656 return result.toString(); 657 } 658 659 /*** 660 * Returns the size of the column 661 */ 662 public String getSize() 663 { 664 return size; 665 } 666 667 /*** 668 * Set the size of the column 669 */ 670 public void setSize(String newSize) 671 { 672 size = newSize; 673 } 674 675 /*** 676 * Return the size in brackets for use in an sql 677 * schema if the type is String. Otherwise return an empty string 678 */ 679 public String printSize() 680 { 681 return (size == null ? "" : '(' + size + ')'); 682 } 683 684 /*** 685 * Return a string that will give this column a default value. 686 * <p> 687 * TODO: Properly SQL-escape text values. 688 */ 689 public String getDefaultSetting() 690 { 691 StringBuffer dflt = new StringBuffer(0); 692 if (defaultValue != null) 693 { 694 dflt.append("default "); 695 if (TypeMap.isTextType(torqueType)) 696 { 697 // TODO: Properly SQL-escape the text. 698 dflt.append('\'').append(defaultValue).append('\''); 699 } 700 else 701 { 702 dflt.append(defaultValue); 703 } 704 } 705 return dflt.toString(); 706 } 707 708 /*** 709 * Set a string that will give this column a default value. 710 */ 711 public void setDefaultValue(String def) 712 { 713 defaultValue = def; 714 } 715 716 /*** 717 * Get a string that will give this column a default value. 718 */ 719 public String getDefaultValue() 720 { 721 return defaultValue; 722 } 723 724 /*** 725 * Returns the class name to do input validation 726 */ 727 public String getInputValidator() 728 { 729 return this.inputValidator; 730 } 731 732 /*** 733 * Return auto increment/sequence string for the target database. We need to 734 * pass in the props for the target database! 735 */ 736 public boolean isAutoIncrement() 737 { 738 return isAutoIncrement; 739 } 740 741 /*** 742 * Set the auto increment value. 743 * Use isAutoIncrement() to find out if it is set or not. 744 */ 745 public void setAutoIncrement(boolean value) 746 { 747 isAutoIncrement = value; 748 } 749 750 /*** 751 * Set the column type from a string property 752 * (normally a string from an sql input file) 753 */ 754 public void setTypeFromString (String typeName, String size) 755 { 756 String tn = typeName.toUpperCase(); 757 setType(tn); 758 759 if (size != null) 760 { 761 this.size = size; 762 } 763 764 if (tn.indexOf ("CHAR") != -1) 765 { 766 torqueType = "VARCHAR"; 767 columnType = ""; 768 } 769 else if (tn.indexOf ("INT") != -1) 770 { 771 torqueType = "INTEGER"; 772 columnType = new Integer (0); 773 } 774 else if (tn.indexOf ("FLOAT") != -1) 775 { 776 torqueType = "FLOAT"; 777 columnType = new Float (0); 778 } 779 else if (tn.indexOf ("DATE") != -1) 780 { 781 torqueType = "DATE"; 782 columnType = new Date(); 783 } 784 else if (tn.indexOf ("TIME") != -1) 785 { 786 torqueType = "TIMESTAMP"; 787 columnType = new Date(); 788 } 789 else if (tn.indexOf ("BINARY") != -1) 790 { 791 torqueType = "LONGVARBINARY"; 792 columnType = new Hashtable(); 793 } 794 else 795 { 796 torqueType = "VARCHAR"; 797 columnType = ""; 798 } 799 } 800 801 /*** 802 * Return a string representation of the 803 * Java object which corresponds to the JDBC 804 * type of this column. Use in the generation 805 * of MapBuilders. 806 */ 807 public String getJavaObject() 808 { 809 return TypeMap.getJavaObject(torqueType); 810 } 811 812 /*** 813 * Return a string representation of the primitive java type which 814 * corresponds to the JDBC type of this column. 815 * 816 * @return string representation of the primitive java type 817 */ 818 public String getJavaPrimitive() 819 { 820 return TypeMap.getJavaNative(torqueType); 821 } 822 823 /*** 824 * Return a string representation of the native java type which corresponds 825 * to the JDBC type of this column. Use in the generation of Base objects. 826 * This method is used by torque, so it returns Key types for primaryKey and 827 * foreignKey columns 828 * 829 * @return java datatype used by torque 830 */ 831 public String getJavaNative() 832 { 833 String jtype = TypeMap.getJavaNativeObject(torqueType); 834 if (isUsePrimitive()) 835 { 836 jtype = TypeMap.getJavaNative(torqueType); 837 } 838 839 return jtype; 840 } 841 842 /*** 843 * Return Village asX() method which corresponds to the JDBC type 844 * which represents this column. 845 */ 846 public String getVillageMethod() 847 { 848 String vmethod = TypeMap.getVillageObjectMethod(torqueType); 849 if (isUsePrimitive()) 850 { 851 vmethod = TypeMap.getVillageMethod(torqueType); 852 } 853 854 return vmethod; 855 } 856 857 /*** 858 * Return ParameterParser getX() method which 859 * corresponds to the JDBC type which represents this column. 860 */ 861 public String getParameterParserMethod() 862 { 863 return TypeMap.getPPMethod(torqueType); 864 } 865 866 /*** 867 * Returns true if the column type is boolean in the 868 * java object and a numeric (1 or 0) in the db. 869 */ 870 public boolean isBooleanInt() 871 { 872 return TypeMap.isBooleanInt(torqueType); 873 } 874 875 /*** 876 * Returns true if the column type is boolean in the 877 * java object and a String ("Y" or "N") in the db. 878 */ 879 public boolean isBooleanChar() 880 { 881 return TypeMap.isBooleanChar(torqueType); 882 } 883 884 /*** 885 * returns true, if the columns java native type is an 886 * boolean, byte, short, int, long, float, double, char 887 */ 888 public boolean isPrimitive() 889 { 890 String t = getJavaNative(); 891 return "boolean".equals(t) 892 || "byte".equals(t) 893 || "short".equals(t) 894 || "int".equals(t) 895 || "long".equals(t) 896 || "float".equals(t) 897 || "double".equals(t) 898 || "char".equals(t); 899 } 900 901 public boolean isUsePrimitive() 902 { 903 String s = getJavaType(); 904 return (s != null && s.equals("primitive")) 905 || (s == null && !"object".equals( 906 getTable().getDatabase().getDefaultJavaType())); 907 } 908 }

This page was automatically generated by Maven