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.Hashtable;
0025: import java.util.Iterator;
0026: import java.util.List;
0027: import java.util.Map;
0028: import org.apache.commons.collections.map.ListOrderedMap;
0029: import org.apache.commons.lang.StringUtils;
0030:
0031: import org.apache.commons.logging.Log;
0032: import org.apache.commons.logging.LogFactory;
0033:
0034: import org.apache.torque.engine.EngineException;
0035:
0036: import org.xml.sax.Attributes;
0037:
0038: /**
0039: * Data about a table used in an application.
0040: *
0041: * @author <a href="mailto:leon@opticode.co.za">Leon Messerschmidt</a>
0042: * @author <a href="mailto:jvanzyl@apache.org">Jason van Zyl</a>
0043: * @author <a href="mailto:mpoeschl@marmot.at>Martin Poeschl</a>
0044: * @author <a href="mailto:jmcnally@collab.net>John McNally</a>
0045: * @author <a href="mailto:dlr@collab.net>Daniel Rall</a>
0046: * @author <a href="mailto:byron_foster@byron_foster@yahoo.com>Byron Foster</a>
0047: * @author <a href="mailto:monroe@dukece.com>Greg Monroe</a>
0048: * @version $Id: Table.java 473814 2006-11-11 22:30:30Z tv $
0049: */
0050: public class Table implements IDMethod {
0051: /** Logging class from commons.logging */
0052: private static Log log = LogFactory.getLog(Table.class);
0053:
0054: //private AttributeListImpl attributes;
0055: private List columnList;
0056: private List foreignKeys;
0057: private List indices;
0058: private List unices;
0059: private List idMethodParameters;
0060: private String name;
0061: private String description;
0062: private String javaName;
0063: private String idMethod;
0064: private String javaNamingMethod;
0065: private Database tableParent;
0066: private List referrers;
0067: private List foreignTableNames;
0068: private boolean containsForeignPK;
0069: private Column inheritanceColumn;
0070: private boolean skipSql;
0071: private boolean abstractValue;
0072: private String alias;
0073: private String enterface;
0074: private String pkg;
0075: private String baseClass;
0076: private String basePeer;
0077: private Hashtable columnsByName;
0078: private Hashtable columnsByJavaName;
0079: private boolean needsTransactionInPostgres;
0080: private boolean heavyIndexing;
0081: private boolean forReferenceOnly;
0082: private Map options;
0083:
0084: /**
0085: * Default Constructor
0086: */
0087: public Table() {
0088: this (null);
0089: }
0090:
0091: /**
0092: * Constructs a table object with a name
0093: *
0094: * @param name table name
0095: */
0096: public Table(String name) {
0097: this .name = name;
0098: columnList = new ArrayList();
0099: foreignKeys = new ArrayList(5);
0100: indices = new ArrayList(5);
0101: unices = new ArrayList(5);
0102: columnsByName = new Hashtable();
0103: columnsByJavaName = new Hashtable();
0104: options = Collections.synchronizedMap(new ListOrderedMap());
0105: }
0106:
0107: /**
0108: * Load the table object from an xml tag.
0109: *
0110: * @param attrib xml attributes
0111: * @param defaultIdMethod defined at db level
0112: */
0113: public void loadFromXML(Attributes attrib, String defaultIdMethod) {
0114: name = attrib.getValue("name");
0115: javaName = attrib.getValue("javaName");
0116: idMethod = attrib.getValue("idMethod");
0117:
0118: // retrieves the method for converting from specified name to
0119: // a java name.
0120: javaNamingMethod = attrib.getValue("javaNamingMethod");
0121: if (javaNamingMethod == null) {
0122: javaNamingMethod = getDatabase()
0123: .getDefaultJavaNamingMethod();
0124: }
0125:
0126: if ("null".equals(idMethod)) {
0127: idMethod = defaultIdMethod;
0128: }
0129: skipSql = "true".equals(attrib.getValue("skipSql"));
0130: // pkg = attrib.getValue("package");
0131: abstractValue = "true".equals(attrib.getValue("abstract"));
0132: baseClass = attrib.getValue("baseClass");
0133: basePeer = attrib.getValue("basePeer");
0134: alias = attrib.getValue("alias");
0135: heavyIndexing = "true".equals(attrib.getValue("heavyIndexing"))
0136: || (!"false".equals(attrib.getValue("heavyIndexing")) && getDatabase()
0137: .isHeavyIndexing());
0138: description = attrib.getValue("description");
0139: enterface = attrib.getValue("interface");
0140: }
0141:
0142: /**
0143: * <p>A hook for the SAX XML parser to call when this table has
0144: * been fully loaded from the XML, and all nested elements have
0145: * been processed.</p>
0146: *
0147: * <p>Performs heavy indexing and naming of elements which weren't
0148: * provided with a name.</p>
0149: */
0150: public void doFinalInitialization() {
0151: // Heavy indexing must wait until after all columns composing
0152: // a table's primary key have been parsed.
0153: if (heavyIndexing) {
0154: doHeavyIndexing();
0155: }
0156:
0157: // Name any indices which are missing a name using the
0158: // appropriate algorithm.
0159: doNaming();
0160: }
0161:
0162: /**
0163: * <p>Adds extra indices for multi-part primary key columns.</p>
0164: *
0165: * <p>For databases like MySQL, values in a where clause must
0166: * match key part order from the left to right. So, in the key
0167: * definition <code>PRIMARY KEY (FOO_ID, BAR_ID)</code>,
0168: * <code>FOO_ID</code> <i>must</i> be the first element used in
0169: * the <code>where</code> clause of the SQL query used against
0170: * this table for the primary key index to be used. This feature
0171: * could cause problems under MySQL with heavily indexed tables,
0172: * as MySQL currently only supports 16 indices per table (i.e. it
0173: * might cause too many indices to be created).</p>
0174: *
0175: * <p>See <a href="http://www.mysql.com/doc/E/X/EXPLAIN.html">the
0176: * manual</a> for a better description of why heavy indexing is
0177: * useful for quickly searchable database tables.</p>
0178: */
0179: private void doHeavyIndexing() {
0180: if (log.isDebugEnabled()) {
0181: log.debug("doHeavyIndex() called on table " + name);
0182: }
0183:
0184: List pk = getPrimaryKey();
0185: int size = pk.size();
0186:
0187: try {
0188: // We start at an offset of 1 because the entire column
0189: // list is generally implicitly indexed by the fact that
0190: // it's a primary key.
0191: for (int i = 1; i < size; i++) {
0192: addIndex(new Index(this , pk.subList(i, size)));
0193: }
0194: } catch (EngineException e) {
0195: log.error(e, e);
0196: }
0197: }
0198:
0199: /**
0200: * Names composing objects which haven't yet been named. This
0201: * currently consists of foreign-key and index entities.
0202: */
0203: private void doNaming() {
0204: int i;
0205: int size;
0206: String name;
0207:
0208: // Assure names are unique across all databases.
0209: try {
0210: for (i = 0, size = foreignKeys.size(); i < size; i++) {
0211: ForeignKey fk = (ForeignKey) foreignKeys.get(i);
0212: name = fk.getName();
0213: if (StringUtils.isEmpty(name)) {
0214: name = acquireConstraintName("FK", i + 1);
0215: fk.setName(name);
0216: }
0217: }
0218:
0219: for (i = 0, size = indices.size(); i < size; i++) {
0220: Index index = (Index) indices.get(i);
0221: name = index.getName();
0222: if (StringUtils.isEmpty(name)) {
0223: name = acquireConstraintName("I", i + 1);
0224: index.setName(name);
0225: }
0226: }
0227:
0228: for (i = 0, size = unices.size(); i < size; i++) {
0229: Unique unique = (Unique) unices.get(i);
0230: name = unique.getName();
0231: if (StringUtils.isEmpty(name)) {
0232: name = acquireConstraintName("U", i + 1);
0233: unique.setName(name);
0234: }
0235: }
0236: } catch (EngineException nameAlreadyInUse) {
0237: log.error(nameAlreadyInUse, nameAlreadyInUse);
0238: }
0239: }
0240:
0241: /**
0242: * Macro to a constraint name.
0243: *
0244: * @param nameType constraint type
0245: * @param nbr unique number for this constraint type
0246: * @return unique name for constraint
0247: * @throws EngineException
0248: */
0249: private final String acquireConstraintName(String nameType, int nbr)
0250: throws EngineException {
0251: List inputs = new ArrayList(4);
0252: inputs.add(getDatabase());
0253: inputs.add(getName());
0254: inputs.add(nameType);
0255: inputs.add(new Integer(nbr));
0256: return NameFactory.generateName(
0257: NameFactory.CONSTRAINT_GENERATOR, inputs);
0258: }
0259:
0260: /**
0261: * Gets the value of base class for classes produced from this table.
0262: *
0263: * @return The base class for classes produced from this table.
0264: */
0265: public String getBaseClass() {
0266: if (isAlias() && baseClass == null) {
0267: return alias;
0268: } else if (baseClass == null) {
0269: return getDatabase().getBaseClass();
0270: } else {
0271: return baseClass;
0272: }
0273: }
0274:
0275: /**
0276: * Set the value of baseClass.
0277: * @param v Value to assign to baseClass.
0278: */
0279: public void setBaseClass(String v) {
0280: this .baseClass = v;
0281: }
0282:
0283: /**
0284: * Get the value of basePeer.
0285: * @return value of basePeer.
0286: */
0287: public String getBasePeer() {
0288: if (isAlias() && basePeer == null) {
0289: return alias + "Peer";
0290: } else if (basePeer == null) {
0291: return getDatabase().getBasePeer();
0292: } else {
0293: return basePeer;
0294: }
0295: }
0296:
0297: /**
0298: * Set the value of basePeer.
0299: * @param v Value to assign to basePeer.
0300: */
0301: public void setBasePeer(String v) {
0302: this .basePeer = v;
0303: }
0304:
0305: /**
0306: * A utility function to create a new column from attrib and add it to this
0307: * table.
0308: *
0309: * @param attrib xml attributes for the column to add
0310: * @return the added column
0311: */
0312: public Column addColumn(Attributes attrib) {
0313: Column col = new Column();
0314: col.setTable(this );
0315: col.setCorrectGetters(false);
0316: col.loadFromXML(attrib);
0317: addColumn(col);
0318: return col;
0319: }
0320:
0321: /**
0322: * Adds a new column to the column list and set the
0323: * parent table of the column to the current table
0324: *
0325: * @param col the column to add
0326: */
0327: public void addColumn(Column col) {
0328: col.setTable(this );
0329: if (col.isInheritance()) {
0330: inheritanceColumn = col;
0331: }
0332: columnList.add(col);
0333: columnsByName.put(col.getName(), col);
0334: columnsByJavaName.put(col.getJavaName(), col);
0335: col.setPosition(columnList.size());
0336: needsTransactionInPostgres |= col
0337: .requiresTransactionInPostgres();
0338: }
0339:
0340: /**
0341: * A utility function to create a new foreign key
0342: * from attrib and add it to this table.
0343: *
0344: * @param attrib the xml attributes
0345: * @return the created ForeignKey
0346: */
0347: public ForeignKey addForeignKey(Attributes attrib) {
0348: ForeignKey fk = new ForeignKey();
0349: fk.loadFromXML(attrib);
0350: addForeignKey(fk);
0351: return fk;
0352: }
0353:
0354: /**
0355: * Gets the column that subclasses of the class representing this
0356: * table can be produced from.
0357: */
0358: public Column getChildrenColumn() {
0359: return inheritanceColumn;
0360: }
0361:
0362: /**
0363: * Get the objects that can be created from this table.
0364: */
0365: public List getChildrenNames() {
0366: if (inheritanceColumn == null
0367: || !inheritanceColumn.isEnumeratedClasses()) {
0368: return null;
0369: }
0370: List children = inheritanceColumn.getChildren();
0371: List names = new ArrayList(children.size());
0372: for (int i = 0; i < children.size(); i++) {
0373: names.add(((Inheritance) children.get(i)).getClassName());
0374: }
0375: return names;
0376: }
0377:
0378: /**
0379: * Adds the foreign key from another table that refers to this table.
0380: *
0381: * @param fk A foreign key refering to this table
0382: */
0383: public void addReferrer(ForeignKey fk) {
0384: if (referrers == null) {
0385: referrers = new ArrayList(5);
0386: }
0387: referrers.add(fk);
0388: }
0389:
0390: /**
0391: * Get list of references to this table.
0392: *
0393: * @return A list of references to this table
0394: */
0395: public List getReferrers() {
0396: return referrers;
0397: }
0398:
0399: /**
0400: * Set whether this table contains a foreign PK
0401: *
0402: * @param b
0403: */
0404: public void setContainsForeignPK(boolean b) {
0405: containsForeignPK = b;
0406: }
0407:
0408: /**
0409: * Determine if this table contains a foreign PK
0410: */
0411: public boolean getContainsForeignPK() {
0412: return containsForeignPK;
0413: }
0414:
0415: /**
0416: * A list of tables referenced by foreign keys in this table
0417: *
0418: * @return A list of tables
0419: */
0420: public List getForeignTableNames() {
0421: if (foreignTableNames == null) {
0422: foreignTableNames = new ArrayList(1);
0423: }
0424: return foreignTableNames;
0425: }
0426:
0427: /**
0428: * Adds a new FK to the FK list and set the
0429: * parent table of the column to the current table
0430: *
0431: * @param fk A foreign key
0432: */
0433: public void addForeignKey(ForeignKey fk) {
0434: fk.setTable(this );
0435: foreignKeys.add(fk);
0436:
0437: if (foreignTableNames == null) {
0438: foreignTableNames = new ArrayList(5);
0439: }
0440: if (!foreignTableNames.contains(fk.getForeignTableName())) {
0441: foreignTableNames.add(fk.getForeignTableName());
0442: }
0443: }
0444:
0445: /**
0446: * Return true if the column requires a transaction in Postgres
0447: */
0448: public boolean requiresTransactionInPostgres() {
0449: return needsTransactionInPostgres;
0450: }
0451:
0452: /**
0453: * A utility function to create a new id method parameter
0454: * from attrib and add it to this table.
0455: */
0456: public IdMethodParameter addIdMethodParameter(Attributes attrib) {
0457: IdMethodParameter imp = new IdMethodParameter();
0458: imp.loadFromXML(attrib);
0459: addIdMethodParameter(imp);
0460: return imp;
0461: }
0462:
0463: /**
0464: * Adds a new ID method parameter to the list and sets the parent
0465: * table of the column associated with the supplied parameter to this table.
0466: *
0467: * @param imp The column to add as an ID method parameter.
0468: */
0469: public void addIdMethodParameter(IdMethodParameter imp) {
0470: imp.setTable(this );
0471: if (idMethodParameters == null) {
0472: idMethodParameters = new ArrayList(2);
0473: }
0474: idMethodParameters.add(imp);
0475: }
0476:
0477: /**
0478: * Adds a new index to the index list and set the
0479: * parent table of the column to the current table
0480: */
0481: public void addIndex(Index index) {
0482: index.setTable(this );
0483: indices.add(index);
0484: }
0485:
0486: /**
0487: * A utility function to create a new index
0488: * from attrib and add it to this table.
0489: */
0490: public Index addIndex(Attributes attrib) {
0491: Index index = new Index();
0492: index.loadFromXML(attrib);
0493: addIndex(index);
0494: return index;
0495: }
0496:
0497: /**
0498: * Adds a new Unique to the Unique list and set the
0499: * parent table of the column to the current table
0500: */
0501: public void addUnique(Unique unique) {
0502: unique.setTable(this );
0503: unices.add(unique);
0504: }
0505:
0506: /**
0507: * A utility function to create a new Unique
0508: * from attrib and add it to this table.
0509: *
0510: * @param attrib the xml attributes
0511: */
0512: public Unique addUnique(Attributes attrib) {
0513: Unique unique = new Unique();
0514: unique.loadFromXML(attrib);
0515: addUnique(unique);
0516: return unique;
0517: }
0518:
0519: /**
0520: * Get the name of the Table
0521: */
0522: public String getName() {
0523: return name;
0524: }
0525:
0526: /**
0527: * Set the name of the Table
0528: */
0529: public void setName(String newName) {
0530: name = newName;
0531: }
0532:
0533: /**
0534: * Get the description for the Table
0535: */
0536: public String getDescription() {
0537: return description;
0538: }
0539:
0540: /**
0541: * Set the description for the Table
0542: *
0543: * @param newDescription description for the Table
0544: */
0545: public void setDescription(String newDescription) {
0546: description = newDescription;
0547: }
0548:
0549: /**
0550: * Get name to use in Java sources
0551: */
0552: public String getJavaName() {
0553: if (javaName == null) {
0554: List inputs = new ArrayList(2);
0555: inputs.add(name);
0556: inputs.add(javaNamingMethod);
0557: try {
0558: javaName = NameFactory.generateName(
0559: NameFactory.JAVA_GENERATOR, inputs);
0560: } catch (EngineException e) {
0561: log.error(e, e);
0562: }
0563: }
0564: return javaName;
0565: }
0566:
0567: /**
0568: * Set name to use in Java sources
0569: */
0570: public void setJavaName(String javaName) {
0571: this .javaName = javaName;
0572: }
0573:
0574: /**
0575: * Get the method for generating pk's
0576: */
0577: public String getIdMethod() {
0578: if (idMethod == null) {
0579: return IDMethod.NO_ID_METHOD;
0580: } else {
0581: return idMethod;
0582: }
0583: }
0584:
0585: /**
0586: * Set the method for generating pk's
0587: */
0588: public void setIdMethod(String idMethod) {
0589: this .idMethod = idMethod;
0590: }
0591:
0592: /**
0593: * Skip generating sql for this table (in the event it should
0594: * not be created from scratch).
0595: * @return value of skipSql.
0596: */
0597: public boolean isSkipSql() {
0598: return (skipSql || isAlias() || isForReferenceOnly());
0599: }
0600:
0601: /**
0602: * Set whether this table should have its creation sql generated.
0603: * @param v Value to assign to skipSql.
0604: */
0605: public void setSkipSql(boolean v) {
0606: this .skipSql = v;
0607: }
0608:
0609: /**
0610: * JavaName of om object this entry references.
0611: * @return value of external.
0612: */
0613: public String getAlias() {
0614: return alias;
0615: }
0616:
0617: /**
0618: * Is this table specified in the schema or is there just
0619: * a foreign key reference to it.
0620: * @return value of external.
0621: */
0622: public boolean isAlias() {
0623: return (alias != null);
0624: }
0625:
0626: /**
0627: * Set whether this table specified in the schema or is there just
0628: * a foreign key reference to it.
0629: * @param v Value to assign to alias.
0630: */
0631: public void setAlias(String v) {
0632: this .alias = v;
0633: }
0634:
0635: /**
0636: * Interface which objects for this table will implement
0637: * @return value of interface.
0638: */
0639: public String getInterface() {
0640: return enterface;
0641: }
0642:
0643: /**
0644: * Interface which objects for this table will implement
0645: * @param v Value to assign to interface.
0646: */
0647: public void setInterface(String v) {
0648: this .enterface = v;
0649: }
0650:
0651: /**
0652: * When a table is abstract, it marks the business object class that is
0653: * generated as being abstract. If you have a table called "FOO", then the
0654: * Foo BO will be <code>public abstract class Foo</code>
0655: * This helps support class hierarchies
0656: *
0657: * @return value of abstractValue.
0658: */
0659: public boolean isAbstract() {
0660: return abstractValue;
0661: }
0662:
0663: /**
0664: * When a table is abstract, it marks the business object
0665: * class that is generated as being abstract. If you have a
0666: * table called "FOO", then the Foo BO will be
0667: * <code>public abstract class Foo</code>
0668: * This helps support class hierarchies
0669: *
0670: * @param v Value to assign to abstractValue.
0671: */
0672: public void setAbstract(boolean v) {
0673: this .abstractValue = v;
0674: }
0675:
0676: /**
0677: * Get the value of package.
0678: *
0679: * @return value of package.
0680: */
0681: public String getPackage() {
0682: if (pkg != null) {
0683: return pkg;
0684: } else {
0685: return this .getDatabase().getPackage();
0686: }
0687: }
0688:
0689: /**
0690: * Set the value of package.
0691: *
0692: * @param v Value to assign to package.
0693: */
0694: public void setPackage(String v) {
0695: this .pkg = v;
0696: }
0697:
0698: /**
0699: * Returns a List containing all the columns in the table
0700: *
0701: * @return a List containing all the columns
0702: */
0703: public List getColumns() {
0704: return columnList;
0705: }
0706:
0707: /**
0708: * Utility method to get the number of columns in this table
0709: */
0710: public int getNumColumns() {
0711: return columnList.size();
0712: }
0713:
0714: /**
0715: * Returns a List containing all the FKs in the table
0716: *
0717: * @return a List containing all the FKs
0718: */
0719: public List getForeignKeys() {
0720: return foreignKeys;
0721: }
0722:
0723: /**
0724: * Returns a Collection of parameters relevant for the chosen
0725: * id generation method.
0726: */
0727: public List getIdMethodParameters() {
0728: return idMethodParameters;
0729: }
0730:
0731: /**
0732: * A name to use for creating a sequence if one is not specified.
0733: *
0734: * @return name of the sequence
0735: */
0736: public String getSequenceName() {
0737: String result = null;
0738: if (getIdMethod().equals(NATIVE)) {
0739: List idMethodParams = getIdMethodParameters();
0740: if (idMethodParams == null) {
0741: result = getName() + "_SEQ";
0742: } else {
0743: result = ((IdMethodParameter) idMethodParams.get(0))
0744: .getValue();
0745: }
0746: }
0747: return result;
0748: }
0749:
0750: /**
0751: * Returns a List containing all the indices in the table
0752: *
0753: * @return A List containing all the indices
0754: */
0755: public List getIndices() {
0756: return indices;
0757: }
0758:
0759: /**
0760: * Returns a List containing all the UKs in the table
0761: *
0762: * @return A List containing all the UKs
0763: */
0764: public List getUnices() {
0765: return unices;
0766: }
0767:
0768: /**
0769: * Returns a specified column.
0770: *
0771: * @param name name of the column
0772: * @return Return a Column object or null if it does not exist.
0773: */
0774: public Column getColumn(String name) {
0775: return (Column) columnsByName.get(name);
0776: }
0777:
0778: /**
0779: * Returns a specified column.
0780: *
0781: * @param javaName java name of the column
0782: * @return Return a Column object or null if it does not exist.
0783: */
0784: public Column getColumnByJavaName(String javaName) {
0785: return (Column) columnsByJavaName.get(javaName);
0786: }
0787:
0788: /**
0789: * Return the first foreign key that includes col in it's list
0790: * of local columns. Eg. Foreign key (a,b,c) refrences tbl(x,y,z)
0791: * will be returned of col is either a,b or c.
0792: *
0793: * @param col column name included in the key
0794: * @return Return a Column object or null if it does not exist.
0795: */
0796: public ForeignKey getForeignKey(String col) {
0797: ForeignKey firstFK = null;
0798: for (Iterator iter = foreignKeys.iterator(); iter.hasNext();) {
0799: ForeignKey key = (ForeignKey) iter.next();
0800: if (key.getLocalColumns().contains(col)) {
0801: if (firstFK == null) {
0802: firstFK = key;
0803: } else {
0804: //System.out.println(col+" is in multiple FKs. This is not"
0805: // + " being handled properly.");
0806: //throw new IllegalStateException("Cannot call method if " +
0807: // "column is referenced multiple times");
0808: }
0809: }
0810: }
0811: return firstFK;
0812: }
0813:
0814: /**
0815: * Returns true if the table contains a specified column
0816: *
0817: * @param col the column
0818: * @return true if the table contains the column
0819: */
0820: public boolean containsColumn(Column col) {
0821: return columnList.contains(col);
0822: }
0823:
0824: /**
0825: * Returns true if the table contains a specified column
0826: *
0827: * @param name name of the column
0828: * @return true if the table contains the column
0829: */
0830: public boolean containsColumn(String name) {
0831: return (getColumn(name) != null);
0832: }
0833:
0834: /**
0835: * Set the parent of the table
0836: *
0837: * @param parent the parant database
0838: */
0839: public void setDatabase(Database parent) {
0840: tableParent = parent;
0841: }
0842:
0843: /**
0844: * Get the parent of the table
0845: *
0846: * @return the parant database
0847: */
0848: public Database getDatabase() {
0849: return tableParent;
0850: }
0851:
0852: /**
0853: * Flag to determine if code/sql gets created for this table.
0854: * Table will be skipped, if return true.
0855: * @return value of forReferenceOnly.
0856: */
0857: public boolean isForReferenceOnly() {
0858: return forReferenceOnly;
0859: }
0860:
0861: /**
0862: * Flag to determine if code/sql gets created for this table.
0863: * Table will be skipped, if set to true.
0864: * @param v Value to assign to forReferenceOnly.
0865: */
0866: public void setForReferenceOnly(boolean v) {
0867: this .forReferenceOnly = v;
0868: }
0869:
0870: /**
0871: * Returns a XML representation of this table.
0872: *
0873: * @return XML representation of this table
0874: */
0875: public String toString() {
0876: StringBuffer result = new StringBuffer();
0877:
0878: result.append("<table name=\"").append(name).append('\"');
0879:
0880: if (javaName != null) {
0881: result.append(" javaName=\"").append(javaName).append('\"');
0882: }
0883:
0884: if (idMethod != null) {
0885: result.append(" idMethod=\"").append(idMethod).append('\"');
0886: }
0887:
0888: if (skipSql) {
0889: result.append(" skipSql=\"").append(new Boolean(skipSql))
0890: .append('\"');
0891: }
0892:
0893: if (abstractValue) {
0894: result.append(" abstract=\"").append(
0895: new Boolean(abstractValue)).append('\"');
0896: }
0897:
0898: if (baseClass != null) {
0899: result.append(" baseClass=\"").append(baseClass).append(
0900: '\"');
0901: }
0902:
0903: if (basePeer != null) {
0904: result.append(" basePeer=\"").append(basePeer).append('\"');
0905: }
0906:
0907: result.append(">\n");
0908:
0909: if (columnList != null) {
0910: for (Iterator iter = columnList.iterator(); iter.hasNext();) {
0911: result.append(iter.next());
0912: }
0913: }
0914:
0915: if (foreignKeys != null) {
0916: for (Iterator iter = foreignKeys.iterator(); iter.hasNext();) {
0917: result.append(iter.next());
0918: }
0919: }
0920:
0921: if (idMethodParameters != null) {
0922: Iterator iter = idMethodParameters.iterator();
0923: while (iter.hasNext()) {
0924: result.append(iter.next());
0925: }
0926: }
0927:
0928: result.append("</table>\n");
0929:
0930: return result.toString();
0931: }
0932:
0933: /**
0934: * Returns the collection of Columns which make up the single primary
0935: * key for this table.
0936: *
0937: * @return A list of the primary key parts.
0938: */
0939: public List getPrimaryKey() {
0940: List pk = new ArrayList(columnList.size());
0941:
0942: Iterator iter = columnList.iterator();
0943: while (iter.hasNext()) {
0944: Column col = (Column) iter.next();
0945: if (col.isPrimaryKey()) {
0946: pk.add(col);
0947: }
0948: }
0949: return pk;
0950: }
0951:
0952: /**
0953: * Determine whether this table has a primary key.
0954: *
0955: * @return Whether this table has any primary key parts.
0956: */
0957: public boolean hasPrimaryKey() {
0958: return (getPrimaryKey().size() > 0);
0959: }
0960:
0961: /**
0962: * Returns all parts of the primary key, separated by commas.
0963: *
0964: * @return A CSV list of primary key parts.
0965: */
0966: public String printPrimaryKey() {
0967: return printList(columnList);
0968: }
0969:
0970: /**
0971: * Returns the elements of the list, separated by commas.
0972: *
0973: * @param list a list of Columns
0974: * @return A CSV list.
0975: */
0976: private String printList(List list) {
0977: StringBuffer result = new StringBuffer();
0978: boolean comma = false;
0979: for (Iterator iter = list.iterator(); iter.hasNext();) {
0980: Column col = (Column) iter.next();
0981: if (col.isPrimaryKey()) {
0982: if (comma) {
0983: result.append(',');
0984: } else {
0985: comma = true;
0986: }
0987: result.append(col.getName());
0988: }
0989: }
0990: return result.toString();
0991: }
0992:
0993: /**
0994: * Force all columns to set the correctGetters property.
0995: *
0996: * @param value The new value of the correctGetters property.
0997: * @since 3.2
0998: */
0999: public void setCorrectGetters(Boolean value) {
1000: boolean correctGetters = value != null && value.booleanValue();
1001: for (Iterator it = columnList.iterator(); it.hasNext();) {
1002: Column col = (Column) it.next();
1003: col.setCorrectGetters(correctGetters);
1004: }
1005: }
1006:
1007: /**
1008: * Add an XML Specified option key/value pair to this element's option set.
1009: *
1010: * @param key the key of the option.
1011: * @param value the value of the option.
1012: */
1013: public void addOption(String key, String value) {
1014: options.put(key, value);
1015: }
1016:
1017: /**
1018: * Get the value that was associated with this key in an XML option
1019: * element.
1020: *
1021: * @param key the key of the option.
1022: * @return The value for the key or a null.
1023: */
1024: public String getOption(String key) {
1025: return (String) options.get(key);
1026: }
1027:
1028: /**
1029: * Gets the full ordered hashtable array of items specified by XML option
1030: * statements under this element.<p>
1031: *
1032: * Note, this is not thread save but since it's only used for
1033: * generation which is single threaded, there should be minimum
1034: * 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: return options;
1040: }
1041: }
|