0001: package org.apache.torque.engine.database.model;
0002:
0003: /*
0004: * Licensed to the Apache Software Foundation (ASF) under one
0005: * or more contributor license agreements. See the NOTICE file
0006: * distributed with this work for additional information
0007: * regarding copyright ownership. The ASF licenses this file
0008: * to you under the Apache License, Version 2.0 (the
0009: * "License"); you may not use this file except in compliance
0010: * with the License. You may obtain a copy of the License at
0011: *
0012: * http://www.apache.org/licenses/LICENSE-2.0
0013: *
0014: * Unless required by applicable law or agreed to in writing,
0015: * software distributed under the License is distributed on an
0016: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
0017: * KIND, either express or implied. See the License for the
0018: * specific language governing permissions and limitations
0019: * under the License.
0020: */
0021:
0022: import java.util.ArrayList;
0023: import java.util.Collections;
0024: import java.util.Iterator;
0025: import java.util.List;
0026: import java.util.Map;
0027:
0028: import org.apache.commons.collections.map.ListOrderedMap;
0029: import org.apache.commons.lang.StringUtils;
0030: import org.apache.commons.logging.Log;
0031: import org.apache.commons.logging.LogFactory;
0032: import org.apache.torque.engine.EngineException;
0033: import org.apache.torque.engine.platform.Platform;
0034: import org.apache.torque.engine.platform.PlatformDefaultImpl;
0035: import org.xml.sax.Attributes;
0036:
0037: /**
0038: * A Class for holding data about a column used in an Application.
0039: *
0040: * @author <a href="mailto:leon@opticode.co.za">Leon Messerschmidt</a>
0041: * @author <a href="mailto:jvanzyl@apache.org">Jason van Zyl</a>
0042: * @author <a href="mailto:jon@latchkey.com">Jon S. Stevens</a>
0043: * @author <a href="mailto:dlr@finemaltcoding.com">Daniel Rall</a>
0044: * @author <a href="mailto:byron_foster@byron_foster@yahoo.com>Byron Foster</a>
0045: * @author <a href="mailto:mpoeschl@marmot.at>Martin Poeschl</a>
0046: * @author <a href="mailto:monroe@dukece.com>Greg Monroe</a>
0047: * @version $Id: Column.java 476581 2006-11-18 18:14:14Z tv $
0048: */
0049: public class Column {
0050: private static final SchemaType DEFAULT_TYPE = SchemaType.VARCHAR;
0051: /** Logging class from commons.logging */
0052: private static Log log = LogFactory.getLog(Column.class);
0053: private String name;
0054: private String description;
0055: private Domain domain = new Domain();
0056: private String javaName = null;
0057: private String javaNamingMethod;
0058: private boolean isNotNull = false;
0059: private boolean isProtected = false;
0060: private String javaType;
0061: private Table parentTable;
0062: private int position;
0063: private boolean isPrimaryKey = false;
0064: private boolean isUnique = false;
0065: private boolean isAutoIncrement = false;
0066: private List referrers;
0067: // only one type is supported currently, which assumes the
0068: // column either contains the classnames or a key to
0069: // classnames specified in the schema. Others may be
0070: // supported later.
0071: private String inheritanceType;
0072: private boolean isInheritance;
0073: private boolean isEnumeratedClasses;
0074: private List inheritanceList;
0075: private boolean needsTransactionInPostgres;
0076:
0077: /** generate is... setters for boolean columns if true */
0078: private boolean correctGetters = false;
0079:
0080: /** class name to do input validation on this column */
0081: private String inputValidator = null;
0082: private Map options;
0083:
0084: /**
0085: * Creates a new instance with a <code>null</code> name.
0086: */
0087: public Column() {
0088: this (null);
0089: }
0090:
0091: /**
0092: * Creates a new column and set the name
0093: *
0094: * @param name column name
0095: */
0096: public Column(String name) {
0097: this .name = name;
0098: options = Collections.synchronizedMap(new ListOrderedMap());
0099: }
0100:
0101: /**
0102: * Return a comma delimited string listing the specified columns.
0103: *
0104: * @param columns Either a list of <code>Column</code> objects, or
0105: * a list of <code>String</code> objects with column names.
0106: */
0107: public static String makeList(List columns) {
0108: Object obj = columns.get(0);
0109: boolean isColumnList = (obj instanceof Column);
0110: if (isColumnList) {
0111: obj = ((Column) obj).getName();
0112: }
0113: StringBuffer buf = new StringBuffer((String) obj);
0114: for (int i = 1; i < columns.size(); i++) {
0115: obj = columns.get(i);
0116: if (isColumnList) {
0117: obj = ((Column) obj).getName();
0118: }
0119: buf.append(", ").append(obj);
0120: }
0121: return buf.toString();
0122: }
0123:
0124: /**
0125: * Imports a column from an XML specification
0126: */
0127: public void loadFromXML(Attributes attrib) {
0128: String dom = attrib.getValue("domain");
0129: if (StringUtils.isNotEmpty(dom)) {
0130: domain = new Domain(getTable().getDatabase().getDomain(dom));
0131: } else {
0132: domain = new Domain(getPlatform().getDomainForSchemaType(
0133: DEFAULT_TYPE));
0134: setType(attrib.getValue("type"));
0135: }
0136: //Name
0137: name = attrib.getValue("name");
0138:
0139: javaName = attrib.getValue("javaName");
0140: javaType = attrib.getValue("javaType");
0141: if (javaType != null && javaType.length() == 0) {
0142: javaType = null;
0143: }
0144:
0145: // retrieves the method for converting from specified name to
0146: // a java name.
0147: javaNamingMethod = attrib.getValue("javaNamingMethod");
0148: if (javaNamingMethod == null) {
0149: javaNamingMethod = parentTable.getDatabase()
0150: .getDefaultJavaNamingMethod();
0151: }
0152:
0153: //Primary Key
0154: String primaryKey = attrib.getValue("primaryKey");
0155: //Avoid NullPointerExceptions on string comparisons.
0156: isPrimaryKey = ("true".equals(primaryKey));
0157:
0158: // If this column is a primary key then it can't be null.
0159: if ("true".equals(primaryKey)) {
0160: isNotNull = true;
0161: }
0162:
0163: // HELP: Should primary key, index, and/or idMethod="native"
0164: // affect isNotNull? If not, please document why here.
0165: String notNull = attrib.getValue("required");
0166: isNotNull = (notNull != null && "true".equals(notNull));
0167:
0168: //AutoIncrement/Sequences
0169: String autoIncrement = attrib.getValue("autoIncrement");
0170: // autoincrement is false per default,
0171: // except if the column is a primary key
0172: // and the idMethod is native
0173: // and the platform's default id Method is identity
0174: // and autoIncrement is not excplicitly set to false
0175: isAutoIncrement = ("true".equals(autoIncrement) || (isPrimaryKey()
0176: && IDMethod.NATIVE.equals(getTable().getIdMethod())
0177: && Platform.IDENTITY.equals(getPlatform()
0178: .getNativeIdMethod()) && (!"false"
0179: .equals(autoIncrement))));
0180: //Default column value.
0181: domain.replaceDefaultValue(attrib.getValue("default"));
0182:
0183: domain.replaceSize(attrib.getValue("size"));
0184: domain.replaceScale(attrib.getValue("scale"));
0185:
0186: inheritanceType = attrib.getValue("inheritance");
0187: isInheritance = (inheritanceType != null && !inheritanceType
0188: .equals("false"));
0189:
0190: this .inputValidator = attrib.getValue("inputValidator");
0191: description = attrib.getValue("description");
0192:
0193: isProtected = ("true".equals(attrib.getValue("protected")));
0194: }
0195:
0196: /**
0197: * Returns table.column
0198: */
0199: public String getFullyQualifiedName() {
0200: return (parentTable.getName() + '.' + name);
0201: }
0202:
0203: /**
0204: * Get the name of the column
0205: */
0206: public String getName() {
0207: return name;
0208: }
0209:
0210: /**
0211: * Set the name of the column
0212: */
0213: public void setName(String newName) {
0214: name = newName;
0215: }
0216:
0217: /**
0218: * Get the description for the Table
0219: */
0220: public String getDescription() {
0221: return description;
0222: }
0223:
0224: /**
0225: * Set the description for the Table
0226: *
0227: * @param newDescription description for the Table
0228: */
0229: public void setDescription(String newDescription) {
0230: description = newDescription;
0231: }
0232:
0233: /**
0234: * Get name to use in Java sources to build method names.
0235: *
0236: * @return the capitalised javaName
0237: */
0238: public String getJavaName() {
0239: if (javaName == null) {
0240: List inputs = new ArrayList(2);
0241: inputs.add(name);
0242: inputs.add(javaNamingMethod);
0243: try {
0244: javaName = NameFactory.generateName(
0245: NameFactory.JAVA_GENERATOR, inputs);
0246: } catch (EngineException e) {
0247: log.error(e, e);
0248: }
0249: }
0250: return StringUtils.capitalize(javaName);
0251: }
0252:
0253: /**
0254: * Returns the name for the getter method to retrieve the value of this
0255: * column
0256: *
0257: * @return A getter method name for this column.
0258: * @since 3.2
0259: */
0260: public String getGetterName() {
0261: if (("boolean".equalsIgnoreCase(getJavaNative()) && isCorrectGetters())) {
0262: return "is" + StringUtils.capitalize(getJavaName());
0263: } else {
0264: return "get" + StringUtils.capitalize(getJavaName());
0265: }
0266: }
0267:
0268: /**
0269: * Returns the name for the setter method to set the value of this
0270: * column
0271: *
0272: * @return A setter method name for this column.
0273: * @since 3.2
0274: */
0275: public String getSetterName() {
0276: return "set" + StringUtils.capitalize(getJavaName());
0277: }
0278:
0279: /**
0280: * Get variable name to use in Java sources (= uncapitalised java name)
0281: */
0282: public String getUncapitalisedJavaName() {
0283: return StringUtils.uncapitalize(getJavaName());
0284: }
0285:
0286: /**
0287: * Returns the name of the constant that is used for the column in the Peer
0288: * class, e.g., RecordPeer.COLVARNAME.
0289: * Generally this will be a straight conversion to upper case.
0290: * But if the column name is equals to TABLE_NAME or
0291: * DATABASE_NAME (Torque predefined vars), the column name will have an _
0292: * prefixed, e.g. _TABLE_NAME.
0293: * <p>
0294: * TODO: Handle delimited column names that have non-Java identifier
0295: * characters in them.
0296: *
0297: * @return The name to use in defining the Peer class column variable.
0298: */
0299: public String getPeerJavaName() {
0300: String peerName = name.toUpperCase();
0301: if (peerName.equals("TABLE_NAME")
0302: || peerName.equals("DATABASE_NAME")) {
0303: peerName = "_" + peerName;
0304: }
0305: return peerName;
0306: }
0307:
0308: /**
0309: * Set the name to use in Java sources.
0310: */
0311: public void setJavaName(String javaName) {
0312: this .javaName = javaName;
0313: }
0314:
0315: /**
0316: * Returns whether the type in the java object should be an object
0317: * or primitive.
0318: */
0319: public String getJavaType() {
0320: return javaType;
0321: }
0322:
0323: /**
0324: * Get the location of this column within the table (one-based).
0325: * @return value of position.
0326: */
0327: public int getPosition() {
0328: return position;
0329: }
0330:
0331: /**
0332: * Get the location of this column within the table (one-based).
0333: * @param v Value to assign to position.
0334: */
0335: public void setPosition(int v) {
0336: this .position = v;
0337: }
0338:
0339: /**
0340: * Set the parent Table of the column
0341: */
0342: public void setTable(Table parent) {
0343: parentTable = parent;
0344: }
0345:
0346: /**
0347: * Get the parent Table of the column
0348: */
0349: public Table getTable() {
0350: return parentTable;
0351: }
0352:
0353: /**
0354: * Returns the Name of the table the column is in
0355: */
0356: public String getTableName() {
0357: return parentTable.getName();
0358: }
0359:
0360: /**
0361: * A utility function to create a new column
0362: * from attrib and add it to this table.
0363: */
0364: public Inheritance addInheritance(Attributes attrib) {
0365: Inheritance inh = new Inheritance();
0366: inh.loadFromXML(attrib);
0367: addInheritance(inh);
0368:
0369: return inh;
0370: }
0371:
0372: /**
0373: * Adds a new inheritance definition to the inheritance list and set the
0374: * parent column of the inheritance to the current column
0375: */
0376: public void addInheritance(Inheritance inh) {
0377: inh.setColumn(this );
0378: if (inheritanceList == null) {
0379: inheritanceList = new ArrayList();
0380: isEnumeratedClasses = true;
0381: }
0382: inheritanceList.add(inh);
0383: }
0384:
0385: /**
0386: * Get the inheritance definitions.
0387: */
0388: public List getChildren() {
0389: return inheritanceList;
0390: }
0391:
0392: /**
0393: * Determine if this column is a normal property or specifies a
0394: * the classes that are represented in the table containing this column.
0395: */
0396: public boolean isInheritance() {
0397: return isInheritance;
0398: }
0399:
0400: /**
0401: * Determine if possible classes have been enumerated in the xml file.
0402: */
0403: public boolean isEnumeratedClasses() {
0404: return isEnumeratedClasses;
0405: }
0406:
0407: /**
0408: * Return the isNotNull property of the column
0409: */
0410: public boolean isNotNull() {
0411: return isNotNull;
0412: }
0413:
0414: /**
0415: * Set the isNotNull property of the column
0416: */
0417: public void setNotNull(boolean status) {
0418: isNotNull = status;
0419: }
0420:
0421: /**
0422: * Return NOT NULL String for this column
0423: *
0424: * @return "NOT NULL" if null values are not allowed or an empty String.
0425: */
0426: public String getNotNullString() {
0427: return getTable().getDatabase().getPlatform().getNullString(
0428: this .isNotNull());
0429: }
0430:
0431: /**
0432: * Return the isProtected property of the column
0433: */
0434: public boolean isProtected() {
0435: return isProtected;
0436: }
0437:
0438: /**
0439: * Set the isProtected property of the Column
0440: */
0441: public void setProtected(boolean prot) {
0442: isProtected = prot;
0443: }
0444:
0445: /**
0446: * Set if the column is a primary key or not
0447: */
0448: public void setPrimaryKey(boolean pk) {
0449: isPrimaryKey = pk;
0450: }
0451:
0452: /**
0453: * Return true if the column is a primary key
0454: */
0455: public boolean isPrimaryKey() {
0456: return isPrimaryKey;
0457: }
0458:
0459: /**
0460: * Set true if the column is UNIQUE
0461: */
0462: public void setUnique(boolean u) {
0463: isUnique = u;
0464: }
0465:
0466: /**
0467: * Get the UNIQUE property
0468: */
0469: public boolean isUnique() {
0470: return isUnique;
0471: }
0472:
0473: /**
0474: * Return true if the column requires a transaction in Postgres
0475: */
0476: public boolean requiresTransactionInPostgres() {
0477: return needsTransactionInPostgres;
0478: }
0479:
0480: /**
0481: * Utility method to determine if this column is a foreign key.
0482: */
0483: public boolean isForeignKey() {
0484: return (getForeignKey() != null);
0485: }
0486:
0487: /**
0488: * Determine if this column is a foreign key that refers to the
0489: * same table as another foreign key column in this table.
0490: */
0491: public boolean isMultipleFK() {
0492: ForeignKey fk = getForeignKey();
0493: if (fk != null) {
0494: Iterator fks = parentTable.getForeignKeys().iterator();
0495: while (fks.hasNext()) {
0496: ForeignKey key = (ForeignKey) fks.next();
0497: if (key.getForeignTableName().equals(
0498: fk.getForeignTableName())
0499: && !key.getLocalColumns().contains(this .name)) {
0500: return true;
0501: }
0502: }
0503: }
0504:
0505: // No multiple foreign keys.
0506: return false;
0507: }
0508:
0509: /**
0510: * get the foreign key object for this column
0511: * if it is a foreign key or part of a foreign key
0512: */
0513: public ForeignKey getForeignKey() {
0514: return parentTable.getForeignKey(this .name);
0515: }
0516:
0517: /**
0518: * Utility method to get the related table of this column if it is a foreign
0519: * key or part of a foreign key
0520: */
0521: public String getRelatedTableName() {
0522: ForeignKey fk = getForeignKey();
0523: return (fk == null ? null : fk.getForeignTableName());
0524: }
0525:
0526: /**
0527: * Utility method to get the related column of this local column if this
0528: * column is a foreign key or part of a foreign key.
0529: */
0530: public String getRelatedColumnName() {
0531: ForeignKey fk = getForeignKey();
0532: if (fk == null) {
0533: return null;
0534: } else {
0535: return fk.getLocalForeignMapping().get(this .name)
0536: .toString();
0537: }
0538: }
0539:
0540: /**
0541: * Adds the foreign key from another table that refers to this column.
0542: */
0543: public void addReferrer(ForeignKey fk) {
0544: if (referrers == null) {
0545: referrers = new ArrayList(5);
0546: }
0547: referrers.add(fk);
0548: }
0549:
0550: /**
0551: * Get list of references to this column.
0552: */
0553: public List getReferrers() {
0554: if (referrers == null) {
0555: referrers = new ArrayList(5);
0556: }
0557: return referrers;
0558: }
0559:
0560: /**
0561: * Sets the colunm type
0562: */
0563: public void setType(String torqueType) {
0564: SchemaType type = SchemaType.getEnum(torqueType);
0565: if (type == null) {
0566: log.warn("SchemaType " + torqueType + " does not exist");
0567: type = Column.DEFAULT_TYPE;
0568: }
0569: setType(type);
0570: }
0571:
0572: /**
0573: * Sets the colunm type
0574: */
0575: public void setType(SchemaType torqueType) {
0576: domain = new Domain(getPlatform().getDomainForSchemaType(
0577: torqueType));
0578: if (torqueType.equals(SchemaType.VARBINARY)
0579: || torqueType.equals(SchemaType.BLOB)) {
0580: needsTransactionInPostgres = true;
0581: }
0582: }
0583:
0584: /**
0585: * Returns the column jdbc type as an object
0586: *
0587: * @deprecated the type conversion is handled by the platform package
0588: * (since torque 3.2)
0589: */
0590: public Object getType() {
0591: return TypeMap.getJdbcType(domain.getType()).getName();
0592: }
0593:
0594: /**
0595: * Returns the column type as given in the schema as an object
0596: */
0597: public Object getTorqueType() {
0598: return domain.getType().getName();
0599: }
0600:
0601: /**
0602: * Utility method to see if the column is a string
0603: *
0604: * @deprecated will be removed after the 3.3 release
0605: */
0606: public boolean isString() {
0607: return (domain.getType().getName().indexOf("CHAR") != -1);
0608: }
0609:
0610: /**
0611: * Utility method to return the value as an element to be usable
0612: * in an SQL insert statement. This is used from the SQL loader task
0613: */
0614: public boolean needEscapedValue() {
0615: String torqueType = domain.getType().getName();
0616: return (torqueType != null)
0617: && (torqueType.equals("VARCHAR")
0618: || torqueType.equals("LONGVARCHAR")
0619: || torqueType.equals("DATE")
0620: || torqueType.equals("DATETIME")
0621: || torqueType.equals("TIMESTAMP")
0622: || torqueType.equals("TIME")
0623: || torqueType.equals("CHAR") || torqueType
0624: .equals("CLOB"));
0625: }
0626:
0627: /**
0628: * String representation of the column. This is an xml representation.
0629: *
0630: * @return string representation in xml
0631: */
0632: public String toString() {
0633: StringBuffer result = new StringBuffer();
0634: result.append(" <column name=\"").append(name).append('"');
0635:
0636: if (javaName != null) {
0637: result.append(" javaName=\"").append(javaName).append('"');
0638: }
0639:
0640: if (isPrimaryKey) {
0641: result.append(" primaryKey=\"").append(isPrimaryKey)
0642: .append('"');
0643: }
0644:
0645: if (isNotNull) {
0646: result.append(" required=\"true\"");
0647: } else {
0648: result.append(" required=\"false\"");
0649: }
0650:
0651: result.append(" type=\"").append(domain.getType().getName())
0652: .append('"');
0653:
0654: if (domain.getSize() != null) {
0655: result.append(" size=\"").append(domain.getSize()).append(
0656: '"');
0657: }
0658:
0659: if (domain.getScale() != null) {
0660: result.append(" scale=\"").append(domain.getScale())
0661: .append('"');
0662: }
0663:
0664: if (domain.getDefaultValue() != null) {
0665: result.append(" default=\"").append(
0666: domain.getDefaultValue()).append('"');
0667: }
0668:
0669: if (isInheritance()) {
0670: result.append(" inheritance=\"").append(inheritanceType)
0671: .append('"');
0672: }
0673:
0674: // Close the column.
0675: result.append(" />\n");
0676:
0677: return result.toString();
0678: }
0679:
0680: /**
0681: * Returns the size of the column
0682: */
0683: public String getSize() {
0684: return domain.getSize();
0685: }
0686:
0687: /**
0688: * Set the size of the column
0689: */
0690: public void setSize(String newSize) {
0691: domain.setSize(newSize);
0692: }
0693:
0694: /**
0695: * Try to determine the precision of the field from the size attribute.
0696: * If size attribute is an integer number, it will be returned.
0697: * If size attribute is of the format "Precision,Scale", then Precision
0698: * will be returned.
0699: * If size is null or the size value is not an valid integer,
0700: * null is returned.
0701: * <p>
0702: * Note: Unparseable values will be logged as a warning.
0703: *
0704: * @return The precision portion of the size attribute.
0705: */
0706: public String getPrecision() {
0707: String size = getSize();
0708: if (size == null) {
0709: return size;
0710: }
0711: int cLoc = size.indexOf(',');
0712: if (cLoc > 0) {
0713: size = size.substring(0, cLoc);
0714: }
0715: try {
0716: Integer.parseInt(size);
0717: } catch (NumberFormatException e) {
0718: log
0719: .warn("getPrecision(): Size attribute found ("
0720: + getSize()
0721: + ") was not an integer number, using default of null!");
0722: size = null;
0723: }
0724: return size;
0725: }
0726:
0727: /**
0728: * Try to determine the scale of the field from the scale and size
0729: * attribute.
0730: * If scale attribute is an integer number, it will be returned.
0731: * If size attribute is of the format "Precision,Scale", then Scale
0732: * will be returned.
0733: * If scale and size attributes are null or the scale value found
0734: * is not an valid integer, a null value is returned.
0735: * <p>
0736: * Note: Unparseable values will be logged as a warning.
0737: *
0738: * @return The precision portion of the size attribute.
0739: */
0740: public String getScale() {
0741: String scale = domain.getScale();
0742: // Check for scale on size attribute if no scale attribute
0743: if (scale == null) {
0744: scale = getSize();
0745: if (scale == null) // No scale or size attribute set.
0746: {
0747: return scale;
0748: }
0749: int cLoc = scale.indexOf(',');
0750: if (cLoc < 0) // Size did not have "P,S" format
0751: {
0752: return null;
0753: }
0754: scale = scale.substring(cLoc + 1);
0755: }
0756:
0757: // Validate that scale string found is integer.
0758: try {
0759: Integer.parseInt(scale);
0760: } catch (NumberFormatException e) {
0761: log
0762: .warn("getScale(): Scale (or size=\"p,s\") attribute found ("
0763: + scale
0764: + ") was not an integer number, using default of null.");
0765: scale = null;
0766: }
0767: return scale;
0768: }
0769:
0770: /**
0771: * Set the scale of the column
0772: */
0773: public void setScale(String newScale) {
0774: domain.setScale(newScale);
0775: }
0776:
0777: /**
0778: * Return the size and scale in brackets for use in an sql schema.
0779: *
0780: * @return size and scale or an empty String if there are no values
0781: * available.
0782: */
0783: public String printSize() {
0784: return domain.printSize();
0785: }
0786:
0787: /**
0788: * Return a string that will give this column a default value.
0789: * @deprecated
0790: */
0791: public String getDefaultSetting() {
0792: return domain.getDefaultSetting();
0793: }
0794:
0795: /**
0796: * Set a string that will give this column a default value.
0797: */
0798: public void setDefaultValue(String def) {
0799: domain.setDefaultValue(def);
0800: }
0801:
0802: /**
0803: * Get a string that will give this column a default value.
0804: */
0805: public String getDefaultValue() {
0806: return domain.getDefaultValue();
0807: }
0808:
0809: /**
0810: * Returns the class name to do input validation
0811: */
0812: public String getInputValidator() {
0813: return this .inputValidator;
0814: }
0815:
0816: /**
0817: * Return auto increment/sequence string for the target database. We need to
0818: * pass in the props for the target database!
0819: */
0820: public boolean isAutoIncrement() {
0821: return isAutoIncrement;
0822: }
0823:
0824: /**
0825: * Set the auto increment value.
0826: * Use isAutoIncrement() to find out if it is set or not.
0827: */
0828: public void setAutoIncrement(boolean value) {
0829: isAutoIncrement = value;
0830: }
0831:
0832: public String getAutoIncrementString() {
0833: if (isAutoIncrement()
0834: && IDMethod.NATIVE.equals(getTable().getIdMethod())) {
0835: return getPlatform().getAutoIncrement();
0836: }
0837: return "";
0838: }
0839:
0840: /**
0841: * Set the column type from a string property
0842: * (normally a string from an sql input file)
0843: */
0844: public void setTypeFromString(String typeName, String size) {
0845: String tn = typeName.toUpperCase();
0846: setType(tn);
0847:
0848: if (size != null) {
0849: domain.setSize(size);
0850: }
0851:
0852: if (tn.indexOf("CHAR") != -1) {
0853: domain.setType(SchemaType.VARCHAR);
0854: } else if (tn.indexOf("INT") != -1) {
0855: domain.setType(SchemaType.INTEGER);
0856: } else if (tn.indexOf("FLOAT") != -1) {
0857: domain.setType(SchemaType.FLOAT);
0858: } else if (tn.indexOf("DATE") != -1) {
0859: domain.setType(SchemaType.DATE);
0860: } else if (tn.indexOf("TIME") != -1) {
0861: domain.setType(SchemaType.TIMESTAMP);
0862: } else if (tn.indexOf("BINARY") != -1) {
0863: domain.setType(SchemaType.LONGVARBINARY);
0864: } else {
0865: domain.setType(SchemaType.VARCHAR);
0866: }
0867: }
0868:
0869: /**
0870: * Return a string representation of the
0871: * Java object which corresponds to the JDBC
0872: * type of this column. Use in the generation
0873: * of MapBuilders.
0874: */
0875: public String getJavaObject() {
0876: return TypeMap.getJavaObject(domain.getType());
0877: }
0878:
0879: /**
0880: * Return a string representation of the primitive java type which
0881: * corresponds to the JDBC type of this column.
0882: *
0883: * @return string representation of the primitive java type
0884: */
0885: public String getJavaPrimitive() {
0886: return TypeMap.getJavaNative(domain.getType());
0887: }
0888:
0889: /**
0890: * Return a string representation of the native java type which corresponds
0891: * to the JDBC type of this column. Use in the generation of Base objects.
0892: * This method is used by torque, so it returns Key types for primaryKey and
0893: * foreignKey columns
0894: *
0895: * @return java datatype used by torque
0896: */
0897: public String getJavaNative() {
0898: String jtype = TypeMap.getJavaNativeObject(domain.getType());
0899: if (isUsePrimitive()) {
0900: jtype = TypeMap.getJavaNative(domain.getType());
0901: }
0902:
0903: return jtype;
0904: }
0905:
0906: /**
0907: * Return Village asX() method which corresponds to the JDBC type
0908: * which represents this column.
0909: */
0910: public String getVillageMethod() {
0911: String vmethod = TypeMap.getVillageObjectMethod(domain
0912: .getType());
0913: if (isUsePrimitive()) {
0914: vmethod = TypeMap.getVillageMethod(domain.getType());
0915: }
0916:
0917: return vmethod;
0918: }
0919:
0920: /**
0921: * Return ParameterParser getX() method which
0922: * corresponds to the JDBC type which represents this column.
0923: */
0924: public String getParameterParserMethod() {
0925: return TypeMap.getPPMethod(domain.getType());
0926: }
0927:
0928: /**
0929: * Returns true if the column type is boolean in the
0930: * java object and a numeric (1 or 0) in the db.
0931: */
0932: public boolean isBooleanInt() {
0933: return TypeMap.isBooleanInt(domain.getType());
0934: }
0935:
0936: /**
0937: * Returns true if the column type is boolean in the
0938: * java object and a String ("Y" or "N") in the db.
0939: */
0940: public boolean isBooleanChar() {
0941: return TypeMap.isBooleanChar(domain.getType());
0942: }
0943:
0944: /**
0945: * Returns true if the column type is boolean in the
0946: * java object and a Bit ("1" or "0") in the db.
0947: */
0948: public boolean isBit() {
0949: return TypeMap.isBit(domain.getType());
0950: }
0951:
0952: /**
0953: * returns true, if the columns java native type is an
0954: * boolean, byte, short, int, long, float, double, char
0955: */
0956: public boolean isPrimitive() {
0957: String t = getJavaNative();
0958: return "boolean".equals(t) || "byte".equals(t)
0959: || "short".equals(t) || "int".equals(t)
0960: || "long".equals(t) || "float".equals(t)
0961: || "double".equals(t) || "char".equals(t);
0962: }
0963:
0964: public boolean isUsePrimitive() {
0965: String s = getJavaType();
0966: return (s != null && s.equals("primitive"))
0967: || (s == null && !"object".equals(getTable()
0968: .getDatabase().getDefaultJavaType()));
0969: }
0970:
0971: /**
0972: * @return Returns the domain.
0973: */
0974: public Domain getDomain() {
0975: return domain;
0976: }
0977:
0978: /**
0979: * @param domain The domain to set.
0980: */
0981: public void setDomain(Domain domain) {
0982: this .domain = domain;
0983: }
0984:
0985: private Platform getPlatform() {
0986: try {
0987: return getTable().getDatabase().getPlatform();
0988: } catch (Exception ex) {
0989: log.warn("could not load platform implementation");
0990: }
0991: return new PlatformDefaultImpl();
0992: }
0993:
0994: public String getSqlString() {
0995: List resultList = new ArrayList();
0996: resultList.add(getName());
0997:
0998: String type = getDomain().getSqlType();
0999:
1000: if (getPlatform().hasSize(getDomain().getSqlType())) {
1001: type += getDomain().printSize();
1002: }
1003:
1004: resultList.add(type);
1005:
1006: if (StringUtils.isNotEmpty(getDomain().getDefaultValue())) {
1007: resultList.add("default");
1008:
1009: if (TypeMap.isTextType(getDomain().getType())) {
1010: // TODO: Properly SQL-escape the text.
1011: resultList.add(new StringBuffer().append('\'').append(
1012: getDefaultValue()).append('\''));
1013: } else {
1014: resultList.add(getDefaultValue());
1015: }
1016: }
1017: if (getPlatform().createNotNullBeforeAutoincrement()) {
1018: if (StringUtils.isNotEmpty(getNotNullString())) {
1019: resultList.add(getNotNullString());
1020: }
1021: }
1022: if (StringUtils.isNotEmpty(getAutoIncrementString())) {
1023: resultList.add(getAutoIncrementString());
1024: }
1025: if (!getPlatform().createNotNullBeforeAutoincrement()) {
1026: if (StringUtils.isNotEmpty(getNotNullString())) {
1027: resultList.add(getNotNullString());
1028: }
1029: }
1030: return StringUtils.join(resultList.iterator(), ' ');
1031: }
1032:
1033: /**
1034: * Return the correctGetters property of the column
1035: *
1036: * @return The currentValue of the correctGetters property.
1037: * @since 3.2
1038: */
1039: public boolean isCorrectGetters() {
1040: return correctGetters;
1041: }
1042:
1043: /**
1044: * Set the correctGetters property of the column. If set to true, the
1045: * column returns is<xxx> as the getter name which is correct for the
1046: * Bean Specs but incompatible to pre-3.2 releases.
1047: *
1048: * @param correctGetters The new value of the correctGetters property.
1049: * @since 3.2
1050: */
1051: public void setCorrectGetters(boolean correctGetters) {
1052: this .correctGetters = correctGetters;
1053: }
1054:
1055: /**
1056: * Get the value of the inheritance attribute defined in the schema XML.
1057: *
1058: * @return Returns the inheritanceType.
1059: */
1060: public String getInheritanceType() {
1061: return inheritanceType;
1062: }
1063:
1064: /**
1065: * Add an XML Specified option key/value pair to this element's option set.
1066: *
1067: * @param key the key of the option.
1068: * @param value the value of the option.
1069: */
1070: public void addOption(String key, String value) {
1071: options.put(key, value);
1072: }
1073:
1074: /**
1075: * Get the value that was associated with this key in an XML option
1076: * element.
1077: *
1078: * @param key the key of the option.
1079: * @return The value for the key or a null.
1080: */
1081: public String getOption(String key) {
1082: return (String) options.get(key);
1083: }
1084:
1085: /**
1086: * Gets the full ordered hashtable array of items specified by XML option
1087: * statements under this element.<p>
1088: *
1089: * Note, this is not thread save but since it's only used for
1090: * generation which is single threaded, there should be minimum
1091: * danger using this in Velocity.
1092: *
1093: * @return An Map of all options. Will not be null but may be empty.
1094: */
1095: public Map getOptions() {
1096: return options;
1097: }
1098: }
|