Coverage Report - org.apache.torque.engine.database.model.Table
 
Classes in this File Line Coverage Branch Coverage Complexity
Table
0%
0/284
0%
0/126
1.918
 
 1  
 package org.apache.torque.engine.database.model;
 2  
 
 3  
 /*
 4  
  * Licensed to the Apache Software Foundation (ASF) under one
 5  
  * or more contributor license agreements.  See the NOTICE file
 6  
  * distributed with this work for additional information
 7  
  * regarding copyright ownership.  The ASF licenses this file
 8  
  * to you under the Apache License, Version 2.0 (the
 9  
  * "License"); you may not use this file except in compliance
 10  
  * with the License.  You may obtain a copy of the License at
 11  
  *
 12  
  *   http://www.apache.org/licenses/LICENSE-2.0
 13  
  *
 14  
  * Unless required by applicable law or agreed to in writing,
 15  
  * software distributed under the License is distributed on an
 16  
  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 17  
  * KIND, either express or implied.  See the License for the
 18  
  * specific language governing permissions and limitations
 19  
  * under the License.
 20  
  */
 21  
 
 22  
 import java.util.ArrayList;
 23  
 import java.util.Collections;
 24  
 import java.util.Hashtable;
 25  
 import java.util.Iterator;
 26  
 import java.util.List;
 27  
 import java.util.Map;
 28  
 import org.apache.commons.collections.map.ListOrderedMap;
 29  
 import org.apache.commons.lang.StringUtils;
 30  
 
 31  
 import org.apache.commons.logging.Log;
 32  
 import org.apache.commons.logging.LogFactory;
 33  
 
 34  
 import org.apache.torque.engine.EngineException;
 35  
 
 36  
 import org.xml.sax.Attributes;
 37  
 
 38  
 /**
 39  
  * Data about a table used in an application.
 40  
  * 
 41  
  * @author <a href="mailto:leon@opticode.co.za">Leon Messerschmidt</a>
 42  
  * @author <a href="mailto:jvanzyl@apache.org">Jason van Zyl</a>
 43  
  * @author <a href="mailto:mpoeschl@marmot.at>Martin Poeschl</a>
 44  
  * @author <a href="mailto:jmcnally@collab.net>John McNally</a>
 45  
  * @author <a href="mailto:dlr@collab.net>Daniel Rall</a>
 46  
  * @author <a href="mailto:byron_foster@byron_foster@yahoo.com>Byron Foster</a>
 47  
  * @author <a href="mailto:monroe@dukece.com>Greg Monroe</a>
 48  
  * @version $Id: Table.java,v 1.1 2007-10-21 07:57:27 abyrne Exp $
 49  
  */
 50  
 public class Table implements IDMethod {
 51  
         /** Logging class from commons.logging */
 52  0
         private static Log log = LogFactory.getLog(Table.class);
 53  
 
 54  
         // private AttributeListImpl attributes;
 55  
         private List columnList;
 56  
         private List foreignKeys;
 57  
         private List indices;
 58  
         private List unices;
 59  
         private List idMethodParameters;
 60  
         private String name;
 61  
         private String description;
 62  
         private String javaName;
 63  
         private String idMethod;
 64  
         private String javaNamingMethod;
 65  
         private Database tableParent;
 66  
         private List referrers;
 67  
         private List foreignTableNames;
 68  
         private boolean containsForeignPK;
 69  
         private Column inheritanceColumn;
 70  
         private boolean skipSql;
 71  
         private boolean abstractValue;
 72  
         private String alias;
 73  
         private String enterface;
 74  
         private String pkg;
 75  
         private String baseClass;
 76  
         private String basePeer;
 77  
         private Hashtable columnsByName;
 78  
         private Hashtable columnsByJavaName;
 79  
         private boolean needsTransactionInPostgres;
 80  
         private boolean heavyIndexing;
 81  
         private boolean forReferenceOnly;
 82  
         private Map options;
 83  
 
 84  
         /**
 85  
          * Default Constructor
 86  
          */
 87  
         public Table() {
 88  0
                 this(null);
 89  0
         }
 90  
 
 91  
         /**
 92  
          * Constructs a table object with a name
 93  
          * 
 94  
          * @param name
 95  
          *            table name
 96  
          */
 97  0
         public Table(String name) {
 98  0
                 this.name = name;
 99  0
                 columnList = new ArrayList();
 100  0
                 foreignKeys = new ArrayList(5);
 101  0
                 indices = new ArrayList(5);
 102  0
                 unices = new ArrayList(5);
 103  0
                 columnsByName = new Hashtable();
 104  0
                 columnsByJavaName = new Hashtable();
 105  0
                 options = Collections.synchronizedMap(new ListOrderedMap());
 106  0
         }
 107  
 
 108  
         /**
 109  
          * Load the table object from an xml tag.
 110  
          * 
 111  
          * @param attrib
 112  
          *            xml attributes
 113  
          * @param defaultIdMethod
 114  
          *            defined at db level
 115  
          */
 116  
         public void loadFromXML(Attributes attrib, String defaultIdMethod) {
 117  0
                 name = attrib.getValue("name");
 118  0
                 javaName = attrib.getValue("javaName");
 119  0
                 idMethod = attrib.getValue("idMethod");
 120  
 
 121  
                 // retrieves the method for converting from specified name to
 122  
                 // a java name.
 123  0
                 javaNamingMethod = attrib.getValue("javaNamingMethod");
 124  0
                 if (javaNamingMethod == null) {
 125  0
                         javaNamingMethod = getDatabase().getDefaultJavaNamingMethod();
 126  
                 }
 127  
 
 128  0
                 if ("null".equals(idMethod)) {
 129  0
                         idMethod = defaultIdMethod;
 130  
                 }
 131  0
                 skipSql = "true".equals(attrib.getValue("skipSql"));
 132  
                 // pkg = attrib.getValue("package");
 133  0
                 abstractValue = "true".equals(attrib.getValue("abstract"));
 134  0
                 baseClass = attrib.getValue("baseClass");
 135  0
                 basePeer = attrib.getValue("basePeer");
 136  0
                 alias = attrib.getValue("alias");
 137  0
                 heavyIndexing = "true".equals(attrib.getValue("heavyIndexing")) || (!"false".equals(attrib.getValue("heavyIndexing")) && getDatabase().isHeavyIndexing());
 138  0
                 description = attrib.getValue("description");
 139  0
                 enterface = attrib.getValue("interface");
 140  0
         }
 141  
 
 142  
         /**
 143  
          * <p>
 144  
          * A hook for the SAX XML parser to call when this table has been fully loaded from the XML, and all nested elements
 145  
          * have been processed.
 146  
          * </p>
 147  
          * 
 148  
          * <p>
 149  
          * Performs heavy indexing and naming of elements which weren't provided with a name.
 150  
          * </p>
 151  
          */
 152  
         public void doFinalInitialization() {
 153  
                 // Heavy indexing must wait until after all columns composing
 154  
                 // a table's primary key have been parsed.
 155  0
                 if (heavyIndexing) {
 156  0
                         doHeavyIndexing();
 157  
                 }
 158  
 
 159  
                 // Name any indices which are missing a name using the
 160  
                 // appropriate algorithm.
 161  0
                 doNaming();
 162  0
         }
 163  
 
 164  
         /**
 165  
          * <p>
 166  
          * Adds extra indices for multi-part primary key columns.
 167  
          * </p>
 168  
          * 
 169  
          * <p>
 170  
          * For databases like MySQL, values in a where clause must match key part order from the left to right. So, in the
 171  
          * key definition <code>PRIMARY KEY (FOO_ID, BAR_ID)</code>, <code>FOO_ID</code> <i>must</i> be the first element
 172  
          * used in the <code>where</code> clause of the SQL query used against this table for the primary key index to be
 173  
          * used. This feature could cause problems under MySQL with heavily indexed tables, as MySQL currently only supports
 174  
          * 16 indices per table (i.e. it might cause too many indices to be created).
 175  
          * </p>
 176  
          * 
 177  
          * <p>
 178  
          * See <a href="http://www.mysql.com/doc/E/X/EXPLAIN.html">the manual</a> for a better description of why heavy
 179  
          * indexing is useful for quickly searchable database tables.
 180  
          * </p>
 181  
          */
 182  
         private void doHeavyIndexing() {
 183  0
                 if (log.isDebugEnabled()) {
 184  0
                         log.debug("doHeavyIndex() called on table " + name);
 185  
                 }
 186  
 
 187  0
                 List pk = getPrimaryKey();
 188  0
                 int size = pk.size();
 189  
 
 190  
                 try {
 191  
                         // We start at an offset of 1 because the entire column
 192  
                         // list is generally implicitly indexed by the fact that
 193  
                         // it's a primary key.
 194  0
                         for (int i = 1; i < size; i++) {
 195  0
                                 addIndex(new Index(this, pk.subList(i, size)));
 196  
                         }
 197  0
                 } catch (EngineException e) {
 198  0
                         log.error(e, e);
 199  0
                 }
 200  0
         }
 201  
 
 202  
         /**
 203  
          * Names composing objects which haven't yet been named. This currently consists of foreign-key and index entities.
 204  
          */
 205  
         private void doNaming() {
 206  
                 int i;
 207  
                 int size;
 208  
                 String name;
 209  
 
 210  
                 // Assure names are unique across all databases.
 211  
                 try {
 212  0
                         for (i = 0, size = foreignKeys.size(); i < size; i++) {
 213  0
                                 ForeignKey fk = (ForeignKey) foreignKeys.get(i);
 214  0
                                 name = fk.getName();
 215  0
                                 if (StringUtils.isEmpty(name)) {
 216  0
                                         name = acquireConstraintName("FK", i + 1);
 217  0
                                         fk.setName(name);
 218  
                                 }
 219  
                         }
 220  
 
 221  0
                         for (i = 0, size = indices.size(); i < size; i++) {
 222  0
                                 Index index = (Index) indices.get(i);
 223  0
                                 name = index.getName();
 224  0
                                 if (StringUtils.isEmpty(name)) {
 225  0
                                         name = acquireConstraintName("I", i + 1);
 226  0
                                         index.setName(name);
 227  
                                 }
 228  
                         }
 229  
 
 230  0
                         for (i = 0, size = unices.size(); i < size; i++) {
 231  0
                                 Unique unique = (Unique) unices.get(i);
 232  0
                                 name = unique.getName();
 233  0
                                 if (StringUtils.isEmpty(name)) {
 234  0
                                         name = acquireConstraintName("U", i + 1);
 235  0
                                         unique.setName(name);
 236  
                                 }
 237  
                         }
 238  0
                 } catch (EngineException nameAlreadyInUse) {
 239  0
                         log.error(nameAlreadyInUse, nameAlreadyInUse);
 240  0
                 }
 241  0
         }
 242  
 
 243  
         /**
 244  
          * Macro to a constraint name.
 245  
          * 
 246  
          * @param nameType
 247  
          *            constraint type
 248  
          * @param nbr
 249  
          *            unique number for this constraint type
 250  
          * @return unique name for constraint
 251  
          * @throws EngineException
 252  
          */
 253  
         private final String acquireConstraintName(String nameType, int nbr) throws EngineException {
 254  0
                 List inputs = new ArrayList(4);
 255  0
                 inputs.add(getDatabase());
 256  0
                 inputs.add(getName());
 257  0
                 inputs.add(nameType);
 258  0
                 inputs.add(new Integer(nbr));
 259  0
                 return NameFactory.generateName(NameFactory.CONSTRAINT_GENERATOR, inputs);
 260  
         }
 261  
 
 262  
         /**
 263  
          * Gets the value of base class for classes produced from this table.
 264  
          * 
 265  
          * @return The base class for classes produced from this table.
 266  
          */
 267  
         public String getBaseClass() {
 268  0
                 if (isAlias() && baseClass == null) {
 269  0
                         return alias;
 270  0
                 } else if (baseClass == null) {
 271  0
                         return getDatabase().getBaseClass();
 272  
                 } else {
 273  0
                         return baseClass;
 274  
                 }
 275  
         }
 276  
 
 277  
         /**
 278  
          * Set the value of baseClass.
 279  
          * 
 280  
          * @param v
 281  
          *            Value to assign to baseClass.
 282  
          */
 283  
         public void setBaseClass(String v) {
 284  0
                 this.baseClass = v;
 285  0
         }
 286  
 
 287  
         /**
 288  
          * Get the value of basePeer.
 289  
          * 
 290  
          * @return value of basePeer.
 291  
          */
 292  
         public String getBasePeer() {
 293  0
                 if (isAlias() && basePeer == null) {
 294  0
                         return alias + "Peer";
 295  0
                 } else if (basePeer == null) {
 296  0
                         return getDatabase().getBasePeer();
 297  
                 } else {
 298  0
                         return basePeer;
 299  
                 }
 300  
         }
 301  
 
 302  
         /**
 303  
          * Set the value of basePeer.
 304  
          * 
 305  
          * @param v
 306  
          *            Value to assign to basePeer.
 307  
          */
 308  
         public void setBasePeer(String v) {
 309  0
                 this.basePeer = v;
 310  0
         }
 311  
 
 312  
         /**
 313  
          * A utility function to create a new column from attrib and add it to this table.
 314  
          * 
 315  
          * @param attrib
 316  
          *            xml attributes for the column to add
 317  
          * @return the added column
 318  
          */
 319  
         public Column addColumn(Attributes attrib) {
 320  0
                 Column col = new Column();
 321  0
                 col.setTable(this);
 322  0
                 col.setCorrectGetters(false);
 323  0
                 col.loadFromXML(attrib);
 324  0
                 addColumn(col);
 325  0
                 return col;
 326  
         }
 327  
 
 328  
         /**
 329  
          * Adds a new column to the column list and set the parent table of the column to the current table
 330  
          * 
 331  
          * @param col
 332  
          *            the column to add
 333  
          */
 334  
         public void addColumn(Column col) {
 335  0
                 col.setTable(this);
 336  0
                 if (col.isInheritance()) {
 337  0
                         inheritanceColumn = col;
 338  
                 }
 339  0
                 columnList.add(col);
 340  0
                 columnsByName.put(col.getName(), col);
 341  0
                 columnsByJavaName.put(col.getJavaName(), col);
 342  0
                 col.setPosition(columnList.size());
 343  0
                 needsTransactionInPostgres |= col.requiresTransactionInPostgres();
 344  0
         }
 345  
 
 346  
         /**
 347  
          * A utility function to create a new foreign key from attrib and add it to this table.
 348  
          * 
 349  
          * @param attrib
 350  
          *            the xml attributes
 351  
          * @return the created ForeignKey
 352  
          */
 353  
         public ForeignKey addForeignKey(Attributes attrib) {
 354  0
                 ForeignKey fk = new ForeignKey();
 355  0
                 fk.loadFromXML(attrib);
 356  0
                 addForeignKey(fk);
 357  0
                 return fk;
 358  
         }
 359  
 
 360  
         /**
 361  
          * Gets the column that subclasses of the class representing this table can be produced from.
 362  
          */
 363  
         public Column getChildrenColumn() {
 364  0
                 return inheritanceColumn;
 365  
         }
 366  
 
 367  
         /**
 368  
          * Get the objects that can be created from this table.
 369  
          */
 370  
         public List getChildrenNames() {
 371  0
                 if (inheritanceColumn == null || !inheritanceColumn.isEnumeratedClasses()) {
 372  0
                         return null;
 373  
                 }
 374  0
                 List children = inheritanceColumn.getChildren();
 375  0
                 List names = new ArrayList(children.size());
 376  0
                 for (int i = 0; i < children.size(); i++) {
 377  0
                         names.add(((Inheritance) children.get(i)).getClassName());
 378  
                 }
 379  0
                 return names;
 380  
         }
 381  
 
 382  
         /**
 383  
          * Adds the foreign key from another table that refers to this table.
 384  
          * 
 385  
          * @param fk
 386  
          *            A foreign key refering to this table
 387  
          */
 388  
         public void addReferrer(ForeignKey fk) {
 389  0
                 if (referrers == null) {
 390  0
                         referrers = new ArrayList(5);
 391  
                 }
 392  0
                 referrers.add(fk);
 393  0
         }
 394  
 
 395  
         /**
 396  
          * Get list of references to this table.
 397  
          * 
 398  
          * @return A list of references to this table
 399  
          */
 400  
         public List getReferrers() {
 401  0
                 return referrers;
 402  
         }
 403  
 
 404  
         /**
 405  
          * Set whether this table contains a foreign PK
 406  
          * 
 407  
          * @param b
 408  
          */
 409  
         public void setContainsForeignPK(boolean b) {
 410  0
                 containsForeignPK = b;
 411  0
         }
 412  
 
 413  
         /**
 414  
          * Determine if this table contains a foreign PK
 415  
          */
 416  
         public boolean getContainsForeignPK() {
 417  0
                 return containsForeignPK;
 418  
         }
 419  
 
 420  
         /**
 421  
          * A list of tables referenced by foreign keys in this table
 422  
          * 
 423  
          * @return A list of tables
 424  
          */
 425  
         public List getForeignTableNames() {
 426  0
                 if (foreignTableNames == null) {
 427  0
                         foreignTableNames = new ArrayList(1);
 428  
                 }
 429  0
                 return foreignTableNames;
 430  
         }
 431  
 
 432  
         /**
 433  
          * Adds a new FK to the FK list and set the parent table of the column to the current table
 434  
          * 
 435  
          * @param fk
 436  
          *            A foreign key
 437  
          */
 438  
         public void addForeignKey(ForeignKey fk) {
 439  0
                 fk.setTable(this);
 440  0
                 foreignKeys.add(fk);
 441  
 
 442  0
                 if (foreignTableNames == null) {
 443  0
                         foreignTableNames = new ArrayList(5);
 444  
                 }
 445  0
                 if (!foreignTableNames.contains(fk.getForeignTableName())) {
 446  0
                         foreignTableNames.add(fk.getForeignTableName());
 447  
                 }
 448  0
         }
 449  
 
 450  
         /**
 451  
          * Return true if the column requires a transaction in Postgres
 452  
          */
 453  
         public boolean requiresTransactionInPostgres() {
 454  0
                 return needsTransactionInPostgres;
 455  
         }
 456  
 
 457  
         /**
 458  
          * A utility function to create a new id method parameter from attrib and add it to this table.
 459  
          */
 460  
         public IdMethodParameter addIdMethodParameter(Attributes attrib) {
 461  0
                 IdMethodParameter imp = new IdMethodParameter();
 462  0
                 imp.loadFromXML(attrib);
 463  0
                 addIdMethodParameter(imp);
 464  0
                 return imp;
 465  
         }
 466  
 
 467  
         /**
 468  
          * Adds a new ID method parameter to the list and sets the parent table of the column associated with the supplied
 469  
          * parameter to this table.
 470  
          * 
 471  
          * @param imp
 472  
          *            The column to add as an ID method parameter.
 473  
          */
 474  
         public void addIdMethodParameter(IdMethodParameter imp) {
 475  0
                 imp.setTable(this);
 476  0
                 if (idMethodParameters == null) {
 477  0
                         idMethodParameters = new ArrayList(2);
 478  
                 }
 479  0
                 idMethodParameters.add(imp);
 480  0
         }
 481  
 
 482  
         /**
 483  
          * Adds a new index to the index list and set the parent table of the column to the current table
 484  
          */
 485  
         public void addIndex(Index index) {
 486  0
                 index.setTable(this);
 487  0
                 indices.add(index);
 488  0
         }
 489  
 
 490  
         /**
 491  
          * A utility function to create a new index from attrib and add it to this table.
 492  
          */
 493  
         public Index addIndex(Attributes attrib) {
 494  0
                 Index index = new Index();
 495  0
                 index.loadFromXML(attrib);
 496  0
                 addIndex(index);
 497  0
                 return index;
 498  
         }
 499  
 
 500  
         /**
 501  
          * Adds a new Unique to the Unique list and set the parent table of the column to the current table
 502  
          */
 503  
         public void addUnique(Unique unique) {
 504  0
                 unique.setTable(this);
 505  0
                 unices.add(unique);
 506  0
         }
 507  
 
 508  
         /**
 509  
          * A utility function to create a new Unique from attrib and add it to this table.
 510  
          * 
 511  
          * @param attrib
 512  
          *            the xml attributes
 513  
          */
 514  
         public Unique addUnique(Attributes attrib) {
 515  0
                 Unique unique = new Unique();
 516  0
                 unique.loadFromXML(attrib);
 517  0
                 addUnique(unique);
 518  0
                 return unique;
 519  
         }
 520  
 
 521  
         /**
 522  
          * Get the name of the Table
 523  
          */
 524  
         public String getName() {
 525  0
                 return name;
 526  
         }
 527  
 
 528  
         /**
 529  
          * Set the name of the Table
 530  
          */
 531  
         public void setName(String newName) {
 532  0
                 name = newName;
 533  0
         }
 534  
 
 535  
         /**
 536  
          * Get the description for the Table
 537  
          */
 538  
         public String getDescription() {
 539  0
                 return description;
 540  
         }
 541  
 
 542  
         /**
 543  
          * Set the description for the Table
 544  
          * 
 545  
          * @param newDescription
 546  
          *            description for the Table
 547  
          */
 548  
         public void setDescription(String newDescription) {
 549  0
                 description = newDescription;
 550  0
         }
 551  
 
 552  
         /**
 553  
          * Get name to use in Java sources
 554  
          */
 555  
         public String getJavaName() {
 556  0
                 if (javaName == null) {
 557  0
                         List inputs = new ArrayList(2);
 558  0
                         inputs.add(name);
 559  0
                         inputs.add(javaNamingMethod);
 560  
                         try {
 561  0
                                 javaName = NameFactory.generateName(NameFactory.JAVA_GENERATOR, inputs);
 562  0
                         } catch (EngineException e) {
 563  0
                                 log.error(e, e);
 564  0
                         }
 565  
                 }
 566  0
                 return javaName;
 567  
         }
 568  
 
 569  
         /**
 570  
          * Set name to use in Java sources
 571  
          */
 572  
         public void setJavaName(String javaName) {
 573  0
                 this.javaName = javaName;
 574  0
         }
 575  
 
 576  
         /**
 577  
          * Get the method for generating pk's
 578  
          */
 579  
         public String getIdMethod() {
 580  0
                 if (idMethod == null) {
 581  0
                         return IDMethod.NO_ID_METHOD;
 582  
                 } else {
 583  0
                         return idMethod;
 584  
                 }
 585  
         }
 586  
 
 587  
         /**
 588  
          * Set the method for generating pk's
 589  
          */
 590  
         public void setIdMethod(String idMethod) {
 591  0
                 this.idMethod = idMethod;
 592  0
         }
 593  
 
 594  
         /**
 595  
          * Skip generating sql for this table (in the event it should not be created from scratch).
 596  
          * 
 597  
          * @return value of skipSql.
 598  
          */
 599  
         public boolean isSkipSql() {
 600  0
                 return (skipSql || isAlias() || isForReferenceOnly());
 601  
         }
 602  
 
 603  
         /**
 604  
          * Set whether this table should have its creation sql generated.
 605  
          * 
 606  
          * @param v
 607  
          *            Value to assign to skipSql.
 608  
          */
 609  
         public void setSkipSql(boolean v) {
 610  0
                 this.skipSql = v;
 611  0
         }
 612  
 
 613  
         /**
 614  
          * JavaName of om object this entry references.
 615  
          * 
 616  
          * @return value of external.
 617  
          */
 618  
         public String getAlias() {
 619  0
                 return alias;
 620  
         }
 621  
 
 622  
         /**
 623  
          * Is this table specified in the schema or is there just a foreign key reference to it.
 624  
          * 
 625  
          * @return value of external.
 626  
          */
 627  
         public boolean isAlias() {
 628  0
                 return (alias != null);
 629  
         }
 630  
 
 631  
         /**
 632  
          * Set whether this table specified in the schema or is there just a foreign key reference to it.
 633  
          * 
 634  
          * @param v
 635  
          *            Value to assign to alias.
 636  
          */
 637  
         public void setAlias(String v) {
 638  0
                 this.alias = v;
 639  0
         }
 640  
 
 641  
         /**
 642  
          * Interface which objects for this table will implement
 643  
          * 
 644  
          * @return value of interface.
 645  
          */
 646  
         public String getInterface() {
 647  0
                 return enterface;
 648  
         }
 649  
 
 650  
         /**
 651  
          * Interface which objects for this table will implement
 652  
          * 
 653  
          * @param v
 654  
          *            Value to assign to interface.
 655  
          */
 656  
         public void setInterface(String v) {
 657  0
                 this.enterface = v;
 658  0
         }
 659  
 
 660  
         /**
 661  
          * When a table is abstract, it marks the business object class that is generated as being abstract. If you have a
 662  
          * table called "FOO", then the Foo BO will be <code>public abstract class Foo</code> This helps support class
 663  
          * hierarchies
 664  
          * 
 665  
          * @return value of abstractValue.
 666  
          */
 667  
         public boolean isAbstract() {
 668  0
                 return abstractValue;
 669  
         }
 670  
 
 671  
         /**
 672  
          * When a table is abstract, it marks the business object class that is generated as being abstract. If you have a
 673  
          * table called "FOO", then the Foo BO will be <code>public abstract class Foo</code> This helps support class
 674  
          * hierarchies
 675  
          * 
 676  
          * @param v
 677  
          *            Value to assign to abstractValue.
 678  
          */
 679  
         public void setAbstract(boolean v) {
 680  0
                 this.abstractValue = v;
 681  0
         }
 682  
 
 683  
         /**
 684  
          * Get the value of package.
 685  
          * 
 686  
          * @return value of package.
 687  
          */
 688  
         public String getPackage() {
 689  0
                 if (pkg != null) {
 690  0
                         return pkg;
 691  
                 } else {
 692  0
                         return this.getDatabase().getPackage();
 693  
                 }
 694  
         }
 695  
 
 696  
         /**
 697  
          * Set the value of package.
 698  
          * 
 699  
          * @param v
 700  
          *            Value to assign to package.
 701  
          */
 702  
         public void setPackage(String v) {
 703  0
                 this.pkg = v;
 704  0
         }
 705  
 
 706  
         /**
 707  
          * Returns a List containing all the columns in the table
 708  
          * 
 709  
          * @return a List containing all the columns
 710  
          */
 711  
         public List getColumns() {
 712  0
                 return columnList;
 713  
         }
 714  
 
 715  
         /**
 716  
          * Utility method to get the number of columns in this table
 717  
          */
 718  
         public int getNumColumns() {
 719  0
                 return columnList.size();
 720  
         }
 721  
 
 722  
         /**
 723  
          * Returns a List containing all the FKs in the table
 724  
          * 
 725  
          * @return a List containing all the FKs
 726  
          */
 727  
         public List getForeignKeys() {
 728  0
                 return foreignKeys;
 729  
         }
 730  
 
 731  
         /**
 732  
          * Returns a Collection of parameters relevant for the chosen id generation method.
 733  
          */
 734  
         public List getIdMethodParameters() {
 735  0
                 return idMethodParameters;
 736  
         }
 737  
 
 738  
         /**
 739  
          * A name to use for creating a sequence if one is not specified.
 740  
          * 
 741  
          * @return name of the sequence
 742  
          */
 743  
         public String getSequenceName() {
 744  0
                 String result = null;
 745  0
                 if (getIdMethod().equals(NATIVE)) {
 746  0
                         List idMethodParams = getIdMethodParameters();
 747  0
                         if (idMethodParams == null) {
 748  0
                                 result = getName() + "_SEQ";
 749  
                         } else {
 750  0
                                 result = ((IdMethodParameter) idMethodParams.get(0)).getValue();
 751  
                         }
 752  
                 }
 753  0
                 return result;
 754  
         }
 755  
 
 756  
         /**
 757  
          * Returns a List containing all the indices in the table
 758  
          * 
 759  
          * @return A List containing all the indices
 760  
          */
 761  
         public List getIndices() {
 762  0
                 return indices;
 763  
         }
 764  
 
 765  
         /**
 766  
          * Returns a List containing all the UKs in the table
 767  
          * 
 768  
          * @return A List containing all the UKs
 769  
          */
 770  
         public List getUnices() {
 771  0
                 return unices;
 772  
         }
 773  
 
 774  
         /**
 775  
          * Returns a specified column.
 776  
          * 
 777  
          * @param name
 778  
          *            name of the column
 779  
          * @return Return a Column object or null if it does not exist.
 780  
          */
 781  
         public Column getColumn(String name) {
 782  0
                 return (Column) columnsByName.get(name);
 783  
         }
 784  
 
 785  
         /**
 786  
          * Returns a specified column.
 787  
          * 
 788  
          * @param javaName
 789  
          *            java name of the column
 790  
          * @return Return a Column object or null if it does not exist.
 791  
          */
 792  
         public Column getColumnByJavaName(String javaName) {
 793  0
                 return (Column) columnsByJavaName.get(javaName);
 794  
         }
 795  
 
 796  
         /**
 797  
          * Return the first foreign key that includes col in it's list of local columns. Eg. Foreign key (a,b,c) refrences
 798  
          * tbl(x,y,z) will be returned of col is either a,b or c.
 799  
          * 
 800  
          * @param col
 801  
          *            column name included in the key
 802  
          * @return Return a Column object or null if it does not exist.
 803  
          */
 804  
         public ForeignKey getForeignKey(String col) {
 805  0
                 ForeignKey firstFK = null;
 806  0
                 for (Iterator iter = foreignKeys.iterator(); iter.hasNext();) {
 807  0
                         ForeignKey key = (ForeignKey) iter.next();
 808  0
                         if (key.getLocalColumns().contains(col)) {
 809  0
                                 if (firstFK == null) {
 810  0
                                         firstFK = key;
 811  
                                 } else {
 812  
                                         // System.out.println(col+" is in multiple FKs.  This is not"
 813  
                                         // + " being handled properly.");
 814  
                                         // throw new IllegalStateException("Cannot call method if " +
 815  
                                         // "column is referenced multiple times");
 816  
                                 }
 817  
                         }
 818  0
                 }
 819  0
                 return firstFK;
 820  
         }
 821  
 
 822  
         /**
 823  
          * Returns true if the table contains a specified column
 824  
          * 
 825  
          * @param col
 826  
          *            the column
 827  
          * @return true if the table contains the column
 828  
          */
 829  
         public boolean containsColumn(Column col) {
 830  0
                 return columnList.contains(col);
 831  
         }
 832  
 
 833  
         /**
 834  
          * Returns true if the table contains a specified column
 835  
          * 
 836  
          * @param name
 837  
          *            name of the column
 838  
          * @return true if the table contains the column
 839  
          */
 840  
         public boolean containsColumn(String name) {
 841  0
                 return (getColumn(name) != null);
 842  
         }
 843  
 
 844  
         /**
 845  
          * Set the parent of the table
 846  
          * 
 847  
          * @param parent
 848  
          *            the parant database
 849  
          */
 850  
         public void setDatabase(Database parent) {
 851  0
                 tableParent = parent;
 852  0
         }
 853  
 
 854  
         /**
 855  
          * Get the parent of the table
 856  
          * 
 857  
          * @return the parant database
 858  
          */
 859  
         public Database getDatabase() {
 860  0
                 return tableParent;
 861  
         }
 862  
 
 863  
         /**
 864  
          * Flag to determine if code/sql gets created for this table. Table will be skipped, if return true.
 865  
          * 
 866  
          * @return value of forReferenceOnly.
 867  
          */
 868  
         public boolean isForReferenceOnly() {
 869  0
                 return forReferenceOnly;
 870  
         }
 871  
 
 872  
         /**
 873  
          * Flag to determine if code/sql gets created for this table. Table will be skipped, if set to true.
 874  
          * 
 875  
          * @param v
 876  
          *            Value to assign to forReferenceOnly.
 877  
          */
 878  
         public void setForReferenceOnly(boolean v) {
 879  0
                 this.forReferenceOnly = v;
 880  0
         }
 881  
 
 882  
         /**
 883  
          * Returns a XML representation of this table.
 884  
          * 
 885  
          * @return XML representation of this table
 886  
          */
 887  
         public String toString() {
 888  0
                 StringBuffer result = new StringBuffer();
 889  
 
 890  0
                 result.append("<table name=\"").append(name).append('\"');
 891  
 
 892  0
                 if (javaName != null) {
 893  0
                         result.append(" javaName=\"").append(javaName).append('\"');
 894  
                 }
 895  
 
 896  0
                 if (idMethod != null) {
 897  0
                         result.append(" idMethod=\"").append(idMethod).append('\"');
 898  
                 }
 899  
 
 900  0
                 if (skipSql) {
 901  0
                         result.append(" skipSql=\"").append(new Boolean(skipSql)).append('\"');
 902  
                 }
 903  
 
 904  0
                 if (abstractValue) {
 905  0
                         result.append(" abstract=\"").append(new Boolean(abstractValue)).append('\"');
 906  
                 }
 907  
 
 908  0
                 if (baseClass != null) {
 909  0
                         result.append(" baseClass=\"").append(baseClass).append('\"');
 910  
                 }
 911  
 
 912  0
                 if (basePeer != null) {
 913  0
                         result.append(" basePeer=\"").append(basePeer).append('\"');
 914  
                 }
 915  
 
 916  0
                 result.append(">\n");
 917  
 
 918  0
                 if (columnList != null) {
 919  0
                         for (Iterator iter = columnList.iterator(); iter.hasNext();) {
 920  0
                                 result.append(iter.next());
 921  
                         }
 922  
                 }
 923  
 
 924  0
                 if (foreignKeys != null) {
 925  0
                         for (Iterator iter = foreignKeys.iterator(); iter.hasNext();) {
 926  0
                                 result.append(iter.next());
 927  
                         }
 928  
                 }
 929  
 
 930  0
                 if (idMethodParameters != null) {
 931  0
                         Iterator iter = idMethodParameters.iterator();
 932  0
                         while (iter.hasNext()) {
 933  0
                                 result.append(iter.next());
 934  
                         }
 935  
                 }
 936  
 
 937  0
                 result.append("</table>\n");
 938  
 
 939  0
                 return result.toString();
 940  
         }
 941  
 
 942  
         /**
 943  
          * Returns the collection of Columns which make up the single primary key for this table.
 944  
          * 
 945  
          * @return A list of the primary key parts.
 946  
          */
 947  
         public List getPrimaryKey() {
 948  0
                 List pk = new ArrayList(columnList.size());
 949  
 
 950  0
                 Iterator iter = columnList.iterator();
 951  0
                 while (iter.hasNext()) {
 952  0
                         Column col = (Column) iter.next();
 953  0
                         if (col.isPrimaryKey()) {
 954  0
                                 pk.add(col);
 955  
                         }
 956  0
                 }
 957  0
                 return pk;
 958  
         }
 959  
 
 960  
         /**
 961  
          * Determine whether this table has a primary key.
 962  
          * 
 963  
          * @return Whether this table has any primary key parts.
 964  
          */
 965  
         public boolean hasPrimaryKey() {
 966  0
                 return (getPrimaryKey().size() > 0);
 967  
         }
 968  
 
 969  
         /**
 970  
          * Returns all parts of the primary key, separated by commas.
 971  
          * 
 972  
          * @return A CSV list of primary key parts.
 973  
          */
 974  
         public String printPrimaryKey() {
 975  0
                 return printList(columnList);
 976  
         }
 977  
 
 978  
         /**
 979  
          * Returns the elements of the list, separated by commas.
 980  
          * 
 981  
          * @param list
 982  
          *            a list of Columns
 983  
          * @return A CSV list.
 984  
          */
 985  
         private String printList(List list) {
 986  0
                 StringBuffer result = new StringBuffer();
 987  0
                 boolean comma = false;
 988  0
                 for (Iterator iter = list.iterator(); iter.hasNext();) {
 989  0
                         Column col = (Column) iter.next();
 990  0
                         if (col.isPrimaryKey()) {
 991  0
                                 if (comma) {
 992  0
                                         result.append(',');
 993  
                                 } else {
 994  0
                                         comma = true;
 995  
                                 }
 996  0
                                 result.append(col.getName());
 997  
                         }
 998  0
                 }
 999  0
                 return result.toString();
 1000  
         }
 1001  
 
 1002  
         /**
 1003  
          * Force all columns to set the correctGetters property.
 1004  
          * 
 1005  
          * @param value
 1006  
          *            The new value of the correctGetters property.
 1007  
          * @since 3.2
 1008  
          */
 1009  
         public void setCorrectGetters(Boolean value) {
 1010  0
                 boolean correctGetters = value != null && value.booleanValue();
 1011  0
                 for (Iterator it = columnList.iterator(); it.hasNext();) {
 1012  0
                         Column col = (Column) it.next();
 1013  0
                         col.setCorrectGetters(correctGetters);
 1014  0
                 }
 1015  0
         }
 1016  
 
 1017  
         /**
 1018  
          * Add an XML Specified option key/value pair to this element's option set.
 1019  
          * 
 1020  
          * @param key
 1021  
          *            the key of the option.
 1022  
          * @param value
 1023  
          *            the value of the option.
 1024  
          */
 1025  
         public void addOption(String key, String value) {
 1026  0
                 options.put(key, value);
 1027  0
         }
 1028  
 
 1029  
         /**
 1030  
          * Get the value that was associated with this key in an XML option element.
 1031  
          * 
 1032  
          * @param key
 1033  
          *            the key of the option.
 1034  
          * @return The value for the key or a null.
 1035  
          */
 1036  
         public String getOption(String key) {
 1037  0
                 return (String) options.get(key);
 1038  
         }
 1039  
 
 1040  
         /**
 1041  
          * Gets the full ordered hashtable array of items specified by XML option statements under this element.
 1042  
          * <p>
 1043  
          * 
 1044  
          * Note, this is not thread save but since it's only used for generation which is single threaded, there should be
 1045  
          * minimum danger using this in Velocity.
 1046  
          * 
 1047  
          * @return An Map of all options. Will not be null but may be empty.
 1048  
          */
 1049  
         public Map getOptions() {
 1050  0
                 return options;
 1051  
         }
 1052  
 }