Coverage Report - org.apache.torque.engine.database.model.Column
 
Classes in this File Line Coverage Branch Coverage Complexity
Column
0%
0/298
0%
0/178
2.081
 
 1  
 package org.apache.torque.engine.database.model;
 2  
 
 3  
 /*
 4  
  * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE
 5  
  * file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file
 6  
  * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
 7  
  * License. You may obtain a copy of the License at
 8  
  * 
 9  
  * http://www.apache.org/licenses/LICENSE-2.0
 10  
  * 
 11  
  * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
 12  
  * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
 13  
  * specific language governing permissions and limitations under the License.
 14  
  */
 15  
 
 16  
 import java.util.ArrayList;
 17  
 import java.util.Collections;
 18  
 import java.util.Iterator;
 19  
 import java.util.List;
 20  
 import java.util.Map;
 21  
 
 22  
 import org.apache.commons.collections.map.ListOrderedMap;
 23  
 import org.apache.commons.lang.StringUtils;
 24  
 import org.apache.commons.logging.Log;
 25  
 import org.apache.commons.logging.LogFactory;
 26  
 import org.apache.torque.engine.EngineException;
 27  
 import org.apache.torque.engine.platform.Platform;
 28  
 import org.apache.torque.engine.platform.PlatformDefaultImpl;
 29  
 import org.xml.sax.Attributes;
 30  
 
 31  
 /**
 32  
  * A Class for holding data about a column used in an Application.
 33  
  * 
 34  
  * @author <a href="mailto:leon@opticode.co.za">Leon Messerschmidt</a>
 35  
  * @author <a href="mailto:jvanzyl@apache.org">Jason van Zyl</a>
 36  
  * @author <a href="mailto:jon@latchkey.com">Jon S. Stevens</a>
 37  
  * @author <a href="mailto:dlr@finemaltcoding.com">Daniel Rall</a>
 38  
  * @author <a href="mailto:byron_foster@byron_foster@yahoo.com>Byron Foster</a>
 39  
  * @author <a href="mailto:mpoeschl@marmot.at>Martin Poeschl</a>
 40  
  * @author <a href="mailto:monroe@dukece.com>Greg Monroe</a>
 41  
  * @version $Id: Column.java,v 1.1 2007-10-21 07:57:27 abyrne Exp $
 42  
  */
 43  
 public class Column {
 44  0
     private static final SchemaType DEFAULT_TYPE = SchemaType.VARCHAR;
 45  
     /** Logging class from commons.logging */
 46  0
     private static Log log = LogFactory.getLog(Column.class);
 47  
     private String name;
 48  
     private String description;
 49  0
     private Domain domain = new Domain();
 50  0
     private String javaName = null;
 51  
     private String javaNamingMethod;
 52  0
     private boolean isNotNull = false;
 53  0
     private boolean isProtected = false;
 54  
     private String javaType;
 55  
     private Table parentTable;
 56  
     private int position;
 57  0
     private boolean isPrimaryKey = false;
 58  0
     private boolean isUnique = false;
 59  0
     private boolean isAutoIncrement = false;
 60  
     private List referrers;
 61  
     // only one type is supported currently, which assumes the
 62  
     // column either contains the classnames or a key to
 63  
     // classnames specified in the schema. Others may be
 64  
     // supported later.
 65  
     private String inheritanceType;
 66  
     private boolean isInheritance;
 67  
     private boolean isEnumeratedClasses;
 68  
     private List inheritanceList;
 69  
     private boolean needsTransactionInPostgres;
 70  
     /**
 71  
      * The type from java.sql.Types
 72  
      */
 73  
     private int jdbcType;
 74  
 
 75  
     /** generate is... setters for boolean columns if true */
 76  0
     private boolean correctGetters = false;
 77  
 
 78  
     /** class name to do input validation on this column */
 79  0
     private String inputValidator = null;
 80  
     private Map options;
 81  
 
 82  
     /**
 83  
      * Creates a new instance with a <code>null</code> name.
 84  
      */
 85  
     public Column() {
 86  0
         this(null);
 87  0
     }
 88  
 
 89  
     /**
 90  
      * Creates a new column and set the name
 91  
      * 
 92  
      * @param name
 93  
      *            column name
 94  
      */
 95  0
     public Column(String name) {
 96  0
         this.name = name;
 97  0
         options = Collections.synchronizedMap(new ListOrderedMap());
 98  0
     }
 99  
 
 100  
     /**
 101  
      * Return a comma delimited string listing the specified columns.
 102  
      * 
 103  
      * @param columns
 104  
      *            Either a list of <code>Column</code> objects, or a list of <code>String</code> objects with column
 105  
      *            names.
 106  
      */
 107  
     public static String makeList(List columns) {
 108  0
         Object obj = columns.get(0);
 109  0
         boolean isColumnList = (obj instanceof Column);
 110  0
         if (isColumnList) {
 111  0
             obj = ((Column) obj).getName();
 112  
         }
 113  0
         StringBuffer buf = new StringBuffer((String) obj);
 114  0
         for (int i = 1; i < columns.size(); i++) {
 115  0
             obj = columns.get(i);
 116  0
             if (isColumnList) {
 117  0
                 obj = ((Column) obj).getName();
 118  
             }
 119  0
             buf.append(", ").append(obj);
 120  
         }
 121  0
         return buf.toString();
 122  
     }
 123  
 
 124  
     /**
 125  
      * Imports a column from an XML specification
 126  
      */
 127  
     public void loadFromXML(Attributes attrib) {
 128  0
         String dom = attrib.getValue("domain");
 129  0
         if (StringUtils.isNotEmpty(dom)) {
 130  0
             domain = new Domain(getTable().getDatabase().getDomain(dom));
 131  
         } else {
 132  0
             domain = new Domain(getPlatform().getDomainForSchemaType(DEFAULT_TYPE));
 133  0
             setType(attrib.getValue("type"));
 134  
         }
 135  
         // Name
 136  0
         name = attrib.getValue("name");
 137  
 
 138  0
         javaName = attrib.getValue("javaName");
 139  0
         javaType = attrib.getValue("javaType");
 140  0
         if (javaType != null && javaType.length() == 0) {
 141  0
             javaType = null;
 142  
         }
 143  
 
 144  
         // retrieves the method for converting from specified name to
 145  
         // a java name.
 146  0
         javaNamingMethod = attrib.getValue("javaNamingMethod");
 147  0
         if (javaNamingMethod == null) {
 148  0
             javaNamingMethod = parentTable.getDatabase().getDefaultJavaNamingMethod();
 149  
         }
 150  
 
 151  
         // Primary Key
 152  0
         String primaryKey = attrib.getValue("primaryKey");
 153  
         // Avoid NullPointerExceptions on string comparisons.
 154  0
         isPrimaryKey = ("true".equals(primaryKey));
 155  
 
 156  
         // If this column is a primary key then it can't be null.
 157  0
         if ("true".equals(primaryKey)) {
 158  0
             isNotNull = true;
 159  
         }
 160  
 
 161  
         // HELP: Should primary key, index, and/or idMethod="native"
 162  
         // affect isNotNull? If not, please document why here.
 163  0
         String notNull = attrib.getValue("required");
 164  0
         isNotNull = (notNull != null && "true".equals(notNull));
 165  
 
 166  
         // AutoIncrement/Sequences
 167  0
         String autoIncrement = attrib.getValue("autoIncrement");
 168  
         // autoincrement is false per default,
 169  
         // except if the column is a primary key
 170  
         // and the idMethod is native
 171  
         // and the platform's default id Method is identity
 172  
         // and autoIncrement is not excplicitly set to false
 173  0
         isAutoIncrement = ("true".equals(autoIncrement) || (isPrimaryKey()
 174  
                 && IDMethod.NATIVE.equals(getTable().getIdMethod())
 175  
                 && Platform.IDENTITY.equals(getPlatform().getNativeIdMethod()) && (!"false".equals(autoIncrement))));
 176  
         // Default column value.
 177  0
         domain.replaceDefaultValue(attrib.getValue("default"));
 178  
 
 179  0
         domain.replaceSize(attrib.getValue("size"));
 180  0
         domain.replaceScale(attrib.getValue("scale"));
 181  
 
 182  0
         inheritanceType = attrib.getValue("inheritance");
 183  0
         isInheritance = (inheritanceType != null && !inheritanceType.equals("false"));
 184  
 
 185  0
         this.inputValidator = attrib.getValue("inputValidator");
 186  0
         description = attrib.getValue("description");
 187  
 
 188  0
         isProtected = ("true".equals(attrib.getValue("protected")));
 189  0
     }
 190  
 
 191  
     /**
 192  
      * Returns table.column
 193  
      */
 194  
     public String getFullyQualifiedName() {
 195  0
         return (parentTable.getName() + '.' + name);
 196  
     }
 197  
 
 198  
     /**
 199  
      * Get the name of the column
 200  
      */
 201  
     public String getName() {
 202  0
         return name;
 203  
     }
 204  
 
 205  
     /**
 206  
      * Set the name of the column
 207  
      */
 208  
     public void setName(String newName) {
 209  0
         name = newName;
 210  0
     }
 211  
 
 212  
     /**
 213  
      * Get the description for the Table
 214  
      */
 215  
     public String getDescription() {
 216  0
         return description;
 217  
     }
 218  
 
 219  
     /**
 220  
      * Set the description for the Table
 221  
      * 
 222  
      * @param newDescription
 223  
      *            description for the Table
 224  
      */
 225  
     public void setDescription(String newDescription) {
 226  0
         description = newDescription;
 227  0
     }
 228  
 
 229  
     /**
 230  
      * Get name to use in Java sources to build method names.
 231  
      * 
 232  
      * @return the capitalised javaName
 233  
      */
 234  
     public String getJavaName() {
 235  0
         if (javaName == null) {
 236  0
             List inputs = new ArrayList(2);
 237  0
             inputs.add(name);
 238  0
             inputs.add(javaNamingMethod);
 239  
             try {
 240  0
                 javaName = NameFactory.generateName(NameFactory.JAVA_GENERATOR, inputs);
 241  0
             } catch (EngineException e) {
 242  0
                 log.error(e, e);
 243  0
             }
 244  
         }
 245  0
         return StringUtils.capitalize(javaName);
 246  
     }
 247  
 
 248  
     /**
 249  
      * Returns the name for the getter method to retrieve the value of this column
 250  
      * 
 251  
      * @return A getter method name for this column.
 252  
      * @since 3.2
 253  
      */
 254  
     public String getGetterName() {
 255  0
         if (("boolean".equalsIgnoreCase(getJavaNative()) && isCorrectGetters())) {
 256  0
             return "is" + StringUtils.capitalize(getJavaName());
 257  
         } else {
 258  0
             return "get" + StringUtils.capitalize(getJavaName());
 259  
         }
 260  
     }
 261  
 
 262  
     /**
 263  
      * Returns the name for the setter method to set the value of this column
 264  
      * 
 265  
      * @return A setter method name for this column.
 266  
      * @since 3.2
 267  
      */
 268  
     public String getSetterName() {
 269  0
         return "set" + StringUtils.capitalize(getJavaName());
 270  
     }
 271  
 
 272  
     /**
 273  
      * Get variable name to use in Java sources (= uncapitalised java name)
 274  
      */
 275  
     public String getUncapitalisedJavaName() {
 276  0
         return StringUtils.uncapitalize(getJavaName());
 277  
     }
 278  
 
 279  
     /**
 280  
      * Returns the name of the constant that is used for the column in the Peer class, e.g., RecordPeer.COLVARNAME.
 281  
      * Generally this will be a straight conversion to upper case. But if the column name is equals to TABLE_NAME or
 282  
      * DATABASE_NAME (Torque predefined vars), the column name will have an _ prefixed, e.g. _TABLE_NAME.
 283  
      * <p>
 284  
      * TODO: Handle delimited column names that have non-Java identifier characters in them.
 285  
      * 
 286  
      * @return The name to use in defining the Peer class column variable.
 287  
      */
 288  
     public String getPeerJavaName() {
 289  0
         String peerName = name.toUpperCase();
 290  0
         if (peerName.equals("TABLE_NAME") || peerName.equals("DATABASE_NAME")) {
 291  0
             peerName = "_" + peerName;
 292  
         }
 293  0
         return peerName;
 294  
     }
 295  
 
 296  
     /**
 297  
      * Set the name to use in Java sources.
 298  
      */
 299  
     public void setJavaName(String javaName) {
 300  0
         this.javaName = javaName;
 301  0
     }
 302  
 
 303  
     /**
 304  
      * Returns whether the type in the java object should be an object or primitive.
 305  
      */
 306  
     public String getJavaType() {
 307  0
         return javaType;
 308  
     }
 309  
 
 310  
     /**
 311  
      * Get the location of this column within the table (one-based).
 312  
      * 
 313  
      * @return value of position.
 314  
      */
 315  
     public int getPosition() {
 316  0
         return position;
 317  
     }
 318  
 
 319  
     /**
 320  
      * Get the location of this column within the table (one-based).
 321  
      * 
 322  
      * @param v
 323  
      *            Value to assign to position.
 324  
      */
 325  
     public void setPosition(int v) {
 326  0
         this.position = v;
 327  0
     }
 328  
 
 329  
     /**
 330  
      * Set the parent Table of the column
 331  
      */
 332  
     public void setTable(Table parent) {
 333  0
         parentTable = parent;
 334  0
     }
 335  
 
 336  
     /**
 337  
      * Get the parent Table of the column
 338  
      */
 339  
     public Table getTable() {
 340  0
         return parentTable;
 341  
     }
 342  
 
 343  
     /**
 344  
      * Returns the Name of the table the column is in
 345  
      */
 346  
     public String getTableName() {
 347  0
         return parentTable.getName();
 348  
     }
 349  
 
 350  
     /**
 351  
      * A utility function to create a new column from attrib and add it to this table.
 352  
      */
 353  
     public Inheritance addInheritance(Attributes attrib) {
 354  0
         Inheritance inh = new Inheritance();
 355  0
         inh.loadFromXML(attrib);
 356  0
         addInheritance(inh);
 357  
 
 358  0
         return inh;
 359  
     }
 360  
 
 361  
     /**
 362  
      * Adds a new inheritance definition to the inheritance list and set the parent column of the inheritance to the
 363  
      * current column
 364  
      */
 365  
     public void addInheritance(Inheritance inh) {
 366  0
         inh.setColumn(this);
 367  0
         if (inheritanceList == null) {
 368  0
             inheritanceList = new ArrayList();
 369  0
             isEnumeratedClasses = true;
 370  
         }
 371  0
         inheritanceList.add(inh);
 372  0
     }
 373  
 
 374  
     /**
 375  
      * Get the inheritance definitions.
 376  
      */
 377  
     public List getChildren() {
 378  0
         return inheritanceList;
 379  
     }
 380  
 
 381  
     /**
 382  
      * Determine if this column is a normal property or specifies a the classes that are represented in the table
 383  
      * containing this column.
 384  
      */
 385  
     public boolean isInheritance() {
 386  0
         return isInheritance;
 387  
     }
 388  
 
 389  
     /**
 390  
      * Determine if possible classes have been enumerated in the xml file.
 391  
      */
 392  
     public boolean isEnumeratedClasses() {
 393  0
         return isEnumeratedClasses;
 394  
     }
 395  
 
 396  
     /**
 397  
      * Return the isNotNull property of the column
 398  
      */
 399  
     public boolean isNotNull() {
 400  0
         return isNotNull;
 401  
     }
 402  
 
 403  
     /**
 404  
      * Set the isNotNull property of the column
 405  
      */
 406  
     public void setNotNull(boolean status) {
 407  0
         isNotNull = status;
 408  0
     }
 409  
 
 410  
     /**
 411  
      * Return NOT NULL String for this column
 412  
      * 
 413  
      * @return "NOT NULL" if null values are not allowed or an empty String.
 414  
      */
 415  
     public String getNotNullString() {
 416  0
         return getTable().getDatabase().getPlatform().getNullString(this.isNotNull());
 417  
     }
 418  
 
 419  
     /**
 420  
      * Return the isProtected property of the column
 421  
      */
 422  
     public boolean isProtected() {
 423  0
         return isProtected;
 424  
     }
 425  
 
 426  
     /**
 427  
      * Set the isProtected property of the Column
 428  
      */
 429  
     public void setProtected(boolean prot) {
 430  0
         isProtected = prot;
 431  0
     }
 432  
 
 433  
     /**
 434  
      * Set if the column is a primary key or not
 435  
      */
 436  
     public void setPrimaryKey(boolean pk) {
 437  0
         isPrimaryKey = pk;
 438  0
     }
 439  
 
 440  
     /**
 441  
      * Return true if the column is a primary key
 442  
      */
 443  
     public boolean isPrimaryKey() {
 444  0
         return isPrimaryKey;
 445  
     }
 446  
 
 447  
     /**
 448  
      * Set true if the column is UNIQUE
 449  
      */
 450  
     public void setUnique(boolean u) {
 451  0
         isUnique = u;
 452  0
     }
 453  
 
 454  
     /**
 455  
      * Get the UNIQUE property
 456  
      */
 457  
     public boolean isUnique() {
 458  0
         return isUnique;
 459  
     }
 460  
 
 461  
     /**
 462  
      * Return true if the column requires a transaction in Postgres
 463  
      */
 464  
     public boolean requiresTransactionInPostgres() {
 465  0
         return needsTransactionInPostgres;
 466  
     }
 467  
 
 468  
     /**
 469  
      * Utility method to determine if this column is a foreign key.
 470  
      */
 471  
     public boolean isForeignKey() {
 472  0
         return (getForeignKey() != null);
 473  
     }
 474  
 
 475  
     /**
 476  
      * Determine if this column is a foreign key that refers to the same table as another foreign key column in this
 477  
      * table.
 478  
      */
 479  
     public boolean isMultipleFK() {
 480  0
         ForeignKey fk = getForeignKey();
 481  0
         if (fk != null) {
 482  0
             Iterator fks = parentTable.getForeignKeys().iterator();
 483  0
             while (fks.hasNext()) {
 484  0
                 ForeignKey key = (ForeignKey) fks.next();
 485  0
                 if (key.getForeignTableName().equals(fk.getForeignTableName())
 486  
                         && !key.getLocalColumns().contains(this.name)) {
 487  0
                     return true;
 488  
                 }
 489  0
             }
 490  
         }
 491  
 
 492  
         // No multiple foreign keys.
 493  0
         return false;
 494  
     }
 495  
 
 496  
     /**
 497  
      * get the foreign key object for this column if it is a foreign key or part of a foreign key
 498  
      */
 499  
     public ForeignKey getForeignKey() {
 500  0
         return parentTable.getForeignKey(this.name);
 501  
     }
 502  
 
 503  
     /**
 504  
      * Utility method to get the related table of this column if it is a foreign key or part of a foreign key
 505  
      */
 506  
     public String getRelatedTableName() {
 507  0
         ForeignKey fk = getForeignKey();
 508  0
         return (fk == null ? null : fk.getForeignTableName());
 509  
     }
 510  
 
 511  
     /**
 512  
      * Utility method to get the related column of this local column if this column is a foreign key or part of a
 513  
      * foreign key.
 514  
      */
 515  
     public String getRelatedColumnName() {
 516  0
         ForeignKey fk = getForeignKey();
 517  0
         if (fk == null) {
 518  0
             return null;
 519  
         } else {
 520  0
             return fk.getLocalForeignMapping().get(this.name).toString();
 521  
         }
 522  
     }
 523  
 
 524  
     /**
 525  
      * Adds the foreign key from another table that refers to this column.
 526  
      */
 527  
     public void addReferrer(ForeignKey fk) {
 528  0
         if (referrers == null) {
 529  0
             referrers = new ArrayList(5);
 530  
         }
 531  0
         referrers.add(fk);
 532  0
     }
 533  
 
 534  
     /**
 535  
      * Get list of references to this column.
 536  
      */
 537  
     public List getReferrers() {
 538  0
         if (referrers == null) {
 539  0
             referrers = new ArrayList(5);
 540  
         }
 541  0
         return referrers;
 542  
     }
 543  
 
 544  
     /**
 545  
      * Sets the colunm type
 546  
      */
 547  
     public void setType(String torqueType) {
 548  0
         SchemaType type = SchemaType.getEnum(torqueType);
 549  0
         if (type == null) {
 550  0
             log.warn("SchemaType " + torqueType + " does not exist");
 551  0
             type = Column.DEFAULT_TYPE;
 552  
         }
 553  0
         setType(type);
 554  0
     }
 555  
 
 556  
     /**
 557  
      * Sets the colunm type
 558  
      */
 559  
     public void setType(SchemaType torqueType) {
 560  0
         domain = new Domain(getPlatform().getDomainForSchemaType(torqueType));
 561  0
         if (torqueType.equals(SchemaType.VARBINARY) || torqueType.equals(SchemaType.BLOB)) {
 562  0
             needsTransactionInPostgres = true;
 563  
         }
 564  0
     }
 565  
 
 566  
     /**
 567  
      * Returns the column jdbc type as an object
 568  
      * 
 569  
      * @deprecated the type conversion is handled by the platform package (since torque 3.2)
 570  
      */
 571  
     public Object getType() {
 572  0
         return TypeMap.getJdbcType(domain.getType()).getName();
 573  
     }
 574  
 
 575  
     /**
 576  
      * Returns the column type as given in the schema as an object
 577  
      */
 578  
     public Object getTorqueType() {
 579  0
         return domain.getType().getName();
 580  
     }
 581  
 
 582  
     /**
 583  
      * Utility method to see if the column is a string
 584  
      * 
 585  
      * @deprecated will be removed after the 3.3 release
 586  
      */
 587  
     public boolean isString() {
 588  0
         return (domain.getType().getName().indexOf("CHAR") != -1);
 589  
     }
 590  
 
 591  
     /**
 592  
      * Utility method to return the value as an element to be usable in an SQL insert statement. This is used from the
 593  
      * SQL loader task
 594  
      */
 595  
     public boolean needEscapedValue() {
 596  0
         String torqueType = domain.getType().getName();
 597  0
         return (torqueType != null)
 598  
                 && (torqueType.equals("VARCHAR") || torqueType.equals("LONGVARCHAR") || torqueType.equals("DATE")
 599  
                         || torqueType.equals("DATETIME") || torqueType.equals("TIMESTAMP") || torqueType.equals("TIME")
 600  
                         || torqueType.equals("CHAR") || torqueType.equals("CLOB"));
 601  
     }
 602  
 
 603  
     /**
 604  
      * String representation of the column. This is an xml representation.
 605  
      * 
 606  
      * @return string representation in xml
 607  
      */
 608  
     public String toString() {
 609  0
         StringBuffer result = new StringBuffer();
 610  0
         result.append("    <column name=\"").append(name).append('"');
 611  
 
 612  0
         if (javaName != null) {
 613  0
             result.append(" javaName=\"").append(javaName).append('"');
 614  
         }
 615  
 
 616  0
         if (isPrimaryKey) {
 617  0
             result.append(" primaryKey=\"").append(isPrimaryKey).append('"');
 618  
         }
 619  
 
 620  0
         if (isNotNull) {
 621  0
             result.append(" required=\"true\"");
 622  
         } else {
 623  0
             result.append(" required=\"false\"");
 624  
         }
 625  
 
 626  0
         result.append(" type=\"").append(domain.getType().getName()).append('"');
 627  
 
 628  0
         if (domain.getSize() != null) {
 629  0
             result.append(" size=\"").append(domain.getSize()).append('"');
 630  
         }
 631  
 
 632  0
         if (domain.getScale() != null) {
 633  0
             result.append(" scale=\"").append(domain.getScale()).append('"');
 634  
         }
 635  
 
 636  0
         if (domain.getDefaultValue() != null) {
 637  0
             result.append(" default=\"").append(domain.getDefaultValue()).append('"');
 638  
         }
 639  
 
 640  0
         if (isInheritance()) {
 641  0
             result.append(" inheritance=\"").append(inheritanceType).append('"');
 642  
         }
 643  
 
 644  
         // Close the column.
 645  0
         result.append(" />\n");
 646  
 
 647  0
         return result.toString();
 648  
     }
 649  
 
 650  
     /**
 651  
      * Returns the size of the column
 652  
      */
 653  
     public String getSize() {
 654  0
         return domain.getSize();
 655  
     }
 656  
 
 657  
     /**
 658  
      * Set the size of the column
 659  
      */
 660  
     public void setSize(String newSize) {
 661  0
         domain.setSize(newSize);
 662  0
     }
 663  
 
 664  
     /**
 665  
      * Try to determine the precision of the field from the size attribute. If size attribute is an integer number, it
 666  
      * will be returned. If size attribute is of the format "Precision,Scale", then Precision will be returned. If size
 667  
      * is null or the size value is not an valid integer, null is returned.
 668  
      * <p>
 669  
      * Note: Unparseable values will be logged as a warning.
 670  
      * 
 671  
      * @return The precision portion of the size attribute.
 672  
      */
 673  
     public String getPrecision() {
 674  0
         String size = getSize();
 675  0
         if (size == null) {
 676  0
             return size;
 677  
         }
 678  0
         int cLoc = size.indexOf(',');
 679  0
         if (cLoc > 0) {
 680  0
             size = size.substring(0, cLoc);
 681  
         }
 682  
         try {
 683  0
             Integer.parseInt(size);
 684  0
         } catch (NumberFormatException e) {
 685  0
             log.warn("getPrecision(): Size attribute found (" + getSize()
 686  
                     + ") was not an integer number, using default of null!");
 687  0
             size = null;
 688  0
         }
 689  0
         return size;
 690  
     }
 691  
 
 692  
     /**
 693  
      * Try to determine the scale of the field from the scale and size attribute. If scale attribute is an integer
 694  
      * number, it will be returned. If size attribute is of the format "Precision,Scale", then Scale will be returned.
 695  
      * If scale and size attributes are null or the scale value found is not an valid integer, a null value is returned.
 696  
      * <p>
 697  
      * Note: Unparseable values will be logged as a warning.
 698  
      * 
 699  
      * @return The precision portion of the size attribute.
 700  
      */
 701  
     public String getScale() {
 702  0
         String scale = domain.getScale();
 703  
         // Check for scale on size attribute if no scale attribute
 704  0
         if (scale == null) {
 705  0
             scale = getSize();
 706  0
             if (scale == null) { // No scale or size attribute set.
 707  0
                 return scale;
 708  
             }
 709  0
             int cLoc = scale.indexOf(',');
 710  0
             if (cLoc < 0) { // Size did not have "P,S" format
 711  0
                 return null;
 712  
             }
 713  0
             scale = scale.substring(cLoc + 1);
 714  
         }
 715  
 
 716  
         // Validate that scale string found is integer.
 717  
         try {
 718  0
             Integer.parseInt(scale);
 719  0
         } catch (NumberFormatException e) {
 720  0
             log.warn("getScale(): Scale (or size=\"p,s\") attribute found (" + scale
 721  
                     + ") was not an integer number, using default of null.");
 722  0
             scale = null;
 723  0
         }
 724  0
         return scale;
 725  
     }
 726  
 
 727  
     /**
 728  
      * Set the scale of the column
 729  
      */
 730  
     public void setScale(String newScale) {
 731  0
         domain.setScale(newScale);
 732  0
     }
 733  
 
 734  
     /**
 735  
      * Return the size and scale in brackets for use in an sql schema.
 736  
      * 
 737  
      * @return size and scale or an empty String if there are no values available.
 738  
      */
 739  
     public String printSize() {
 740  0
         return domain.printSize();
 741  
     }
 742  
 
 743  
     /**
 744  
      * Return a string that will give this column a default value.
 745  
      * 
 746  
      * @deprecated
 747  
      */
 748  
     public String getDefaultSetting() {
 749  0
         return domain.getDefaultSetting();
 750  
     }
 751  
 
 752  
     /**
 753  
      * Set a string that will give this column a default value.
 754  
      */
 755  
     public void setDefaultValue(String def) {
 756  0
         domain.setDefaultValue(def);
 757  0
     }
 758  
 
 759  
     /**
 760  
      * Get a string that will give this column a default value.
 761  
      */
 762  
     public String getDefaultValue() {
 763  0
         return domain.getDefaultValue();
 764  
     }
 765  
 
 766  
     /**
 767  
      * Returns the class name to do input validation
 768  
      */
 769  
     public String getInputValidator() {
 770  0
         return this.inputValidator;
 771  
     }
 772  
 
 773  
     /**
 774  
      * Return auto increment/sequence string for the target database. We need to pass in the props for the target
 775  
      * database!
 776  
      */
 777  
     public boolean isAutoIncrement() {
 778  0
         return isAutoIncrement;
 779  
     }
 780  
 
 781  
     /**
 782  
      * Set the auto increment value. Use isAutoIncrement() to find out if it is set or not.
 783  
      */
 784  
     public void setAutoIncrement(boolean value) {
 785  0
         isAutoIncrement = value;
 786  0
     }
 787  
 
 788  
     public String getAutoIncrementString() {
 789  0
         if (isAutoIncrement() && IDMethod.NATIVE.equals(getTable().getIdMethod())) {
 790  0
             return getPlatform().getAutoIncrement();
 791  
         }
 792  0
         return "";
 793  
     }
 794  
 
 795  
     /**
 796  
      * Set the column type from a string property (normally a string from an sql input file)
 797  
      */
 798  
     public void setTypeFromString(String typeName, String size) {
 799  0
         String tn = typeName.toUpperCase();
 800  0
         setType(tn);
 801  
 
 802  0
         if (size != null) {
 803  0
             domain.setSize(size);
 804  
         }
 805  
 
 806  0
         if (tn.indexOf("CHAR") != -1) {
 807  0
             domain.setType(SchemaType.VARCHAR);
 808  0
         } else if (tn.indexOf("INT") != -1) {
 809  0
             domain.setType(SchemaType.INTEGER);
 810  0
         } else if (tn.indexOf("FLOAT") != -1) {
 811  0
             domain.setType(SchemaType.FLOAT);
 812  0
         } else if (tn.indexOf("DATE") != -1) {
 813  0
             domain.setType(SchemaType.DATE);
 814  0
         } else if (tn.indexOf("TIME") != -1) {
 815  0
             domain.setType(SchemaType.TIMESTAMP);
 816  0
         } else if (tn.indexOf("BINARY") != -1) {
 817  0
             domain.setType(SchemaType.LONGVARBINARY);
 818  
         } else {
 819  0
             domain.setType(SchemaType.VARCHAR);
 820  
         }
 821  0
     }
 822  
 
 823  
     /**
 824  
      * Return a string representation of the Java object which corresponds to the JDBC type of this column. Use in the
 825  
      * generation of MapBuilders.
 826  
      */
 827  
     public String getJavaObject() {
 828  0
         return TypeMap.getJavaObject(domain.getType());
 829  
     }
 830  
 
 831  
     /**
 832  
      * Return a string representation of the primitive java type which corresponds to the JDBC type of this column.
 833  
      * 
 834  
      * @return string representation of the primitive java type
 835  
      */
 836  
     public String getJavaPrimitive() {
 837  0
         return TypeMap.getJavaNative(domain.getType());
 838  
     }
 839  
 
 840  
     /**
 841  
      * Return a string representation of the native java type which corresponds to the JDBC type of this column. Use in
 842  
      * the generation of Base objects. This method is used by torque, so it returns Key types for primaryKey and
 843  
      * foreignKey columns
 844  
      * 
 845  
      * @return java datatype used by torque
 846  
      */
 847  
     public String getJavaNative() {
 848  0
         String jtype = TypeMap.getJavaNativeObject(domain.getType());
 849  0
         if (isUsePrimitive()) {
 850  0
             jtype = TypeMap.getJavaNative(domain.getType());
 851  
         }
 852  
 
 853  0
         return jtype;
 854  
     }
 855  
 
 856  
     /**
 857  
      * Return Village asX() method which corresponds to the JDBC type which represents this column.
 858  
      */
 859  
     public String getVillageMethod() {
 860  0
         String vmethod = TypeMap.getVillageObjectMethod(domain.getType());
 861  0
         if (isUsePrimitive()) {
 862  0
             vmethod = TypeMap.getVillageMethod(domain.getType());
 863  
         }
 864  
 
 865  0
         return vmethod;
 866  
     }
 867  
 
 868  
     /**
 869  
      * Return ParameterParser getX() method which corresponds to the JDBC type which represents this column.
 870  
      */
 871  
     public String getParameterParserMethod() {
 872  0
         return TypeMap.getPPMethod(domain.getType());
 873  
     }
 874  
 
 875  
     /**
 876  
      * Returns true if the column type is boolean in the java object and a numeric (1 or 0) in the db.
 877  
      */
 878  
     public boolean isBooleanInt() {
 879  0
         return TypeMap.isBooleanInt(domain.getType());
 880  
     }
 881  
 
 882  
     /**
 883  
      * Returns true if the column type is boolean in the java object and a String ("Y" or "N") in the db.
 884  
      */
 885  
     public boolean isBooleanChar() {
 886  0
         return TypeMap.isBooleanChar(domain.getType());
 887  
     }
 888  
 
 889  
     /**
 890  
      * Returns true if the column type is boolean in the java object and a Bit ("1" or "0") in the db.
 891  
      */
 892  
     public boolean isBit() {
 893  0
         return TypeMap.isBit(domain.getType());
 894  
     }
 895  
 
 896  
     /**
 897  
      * returns true, if the columns java native type is an boolean, byte, short, int, long, float, double, char
 898  
      */
 899  
     public boolean isPrimitive() {
 900  0
         String t = getJavaNative();
 901  0
         return "boolean".equals(t) || "byte".equals(t) || "short".equals(t) || "int".equals(t) || "long".equals(t)
 902  
                 || "float".equals(t) || "double".equals(t) || "char".equals(t);
 903  
     }
 904  
 
 905  
     public boolean isUsePrimitive() {
 906  0
         String s = getJavaType();
 907  0
         return (s != null && s.equals("primitive"))
 908  
                 || (s == null && !"object".equals(getTable().getDatabase().getDefaultJavaType()));
 909  
     }
 910  
 
 911  
     /**
 912  
      * @return Returns the domain.
 913  
      */
 914  
     public Domain getDomain() {
 915  0
         return domain;
 916  
     }
 917  
 
 918  
     /**
 919  
      * @param domain
 920  
      *            The domain to set.
 921  
      */
 922  
     public void setDomain(Domain domain) {
 923  0
         this.domain = domain;
 924  0
     }
 925  
 
 926  
     private Platform getPlatform() {
 927  
         try {
 928  0
             return getTable().getDatabase().getPlatform();
 929  0
         } catch (Exception ex) {
 930  0
             log.warn("could not load platform implementation");
 931  
         }
 932  0
         return new PlatformDefaultImpl();
 933  
     }
 934  
 
 935  
     public String getSqlString() {
 936  0
         List resultList = new ArrayList();
 937  0
         resultList.add(getName());
 938  
 
 939  0
         String type = getDomain().getSqlType();
 940  
 
 941  0
         if (getPlatform().hasSize(getDomain().getSqlType())) {
 942  0
             type += getDomain().printSize();
 943  
         }
 944  
 
 945  0
         resultList.add(type);
 946  
 
 947  0
         String defaultStr = getPlatform().filterInvalidDefaultValues(getDomain().getDefaultValue());
 948  0
         if (StringUtils.isNotEmpty(defaultStr)) {
 949  
 
 950  0
             resultList.add("default");
 951  
 
 952  0
             if (TypeMap.isTextType(getDomain().getType()) && !getPlatform().isSpecialDefault(defaultStr)) {
 953  
                 // TODO: Properly SQL-escape the text.
 954  0
                 resultList.add(new StringBuffer().append('\'').append(getDefaultValue()).append('\''));
 955  
             } else {
 956  0
                 resultList.add(getDefaultValue());
 957  
             }
 958  
         }
 959  0
         if (getPlatform().createNotNullBeforeAutoincrement()) {
 960  0
             if (StringUtils.isNotEmpty(getNotNullString())) {
 961  0
                 resultList.add(getNotNullString());
 962  
             }
 963  
         }
 964  0
         if (StringUtils.isNotEmpty(getAutoIncrementString())) {
 965  0
             resultList.add(getAutoIncrementString());
 966  
         }
 967  0
         if (!getPlatform().createNotNullBeforeAutoincrement()) {
 968  0
             if (StringUtils.isNotEmpty(getNotNullString())) {
 969  0
                 resultList.add(getNotNullString());
 970  
             }
 971  
         }
 972  0
         return StringUtils.join(resultList.iterator(), ' ');
 973  
     }
 974  
 
 975  
     /**
 976  
      * Return the correctGetters property of the column
 977  
      * 
 978  
      * @return The currentValue of the correctGetters property.
 979  
      * @since 3.2
 980  
      */
 981  
     public boolean isCorrectGetters() {
 982  0
         return correctGetters;
 983  
     }
 984  
 
 985  
     /**
 986  
      * Set the correctGetters property of the column. If set to true, the column returns is&lt;xxx&gt; as the getter
 987  
      * name which is correct for the Bean Specs but incompatible to pre-3.2 releases.
 988  
      * 
 989  
      * @param correctGetters
 990  
      *            The new value of the correctGetters property.
 991  
      * @since 3.2
 992  
      */
 993  
     public void setCorrectGetters(boolean correctGetters) {
 994  0
         this.correctGetters = correctGetters;
 995  0
     }
 996  
 
 997  
     /**
 998  
      * Get the value of the inheritance attribute defined in the schema XML.
 999  
      * 
 1000  
      * @return Returns the inheritanceType.
 1001  
      */
 1002  
     public String getInheritanceType() {
 1003  0
         return inheritanceType;
 1004  
     }
 1005  
 
 1006  
     /**
 1007  
      * Add an XML Specified option key/value pair to this element's option set.
 1008  
      * 
 1009  
      * @param key
 1010  
      *            the key of the option.
 1011  
      * @param value
 1012  
      *            the value of the option.
 1013  
      */
 1014  
     public void addOption(String key, String value) {
 1015  0
         options.put(key, value);
 1016  0
     }
 1017  
 
 1018  
     /**
 1019  
      * Get the value that was associated with this key in an XML option element.
 1020  
      * 
 1021  
      * @param key
 1022  
      *            the key of the option.
 1023  
      * @return The value for the key or a null.
 1024  
      */
 1025  
     public String getOption(String key) {
 1026  0
         return (String) options.get(key);
 1027  
     }
 1028  
 
 1029  
     /**
 1030  
      * Gets the full ordered hashtable array of items specified by XML option statements under this element.
 1031  
      * <p>
 1032  
      * 
 1033  
      * Note, this is not thread save but since it's only used for generation which is single threaded, there should be
 1034  
      * minimum danger using this in Velocity.
 1035  
      * 
 1036  
      * @return An Map of all options. Will not be null but may be empty.
 1037  
      */
 1038  
     public Map getOptions() {
 1039  0
         return options;
 1040  
     }
 1041  
 
 1042  
     public int getJdbcType() {
 1043  0
         return jdbcType;
 1044  
     }
 1045  
 
 1046  
     public void setJdbcType(int jdbcType) {
 1047  0
         this.jdbcType = jdbcType;
 1048  0
     }
 1049  
 }