Coverage Report - org.apache.torque.engine.database.model.Database
 
Classes in this File Line Coverage Branch Coverage Complexity
Database
0%
0/151
0%
0/46
1.865
 
 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.HashMap;
 25  
 import java.util.Hashtable;
 26  
 import java.util.Iterator;
 27  
 import java.util.List;
 28  
 import java.util.Map;
 29  
 
 30  
 import org.apache.commons.collections.map.ListOrderedMap;
 31  
 import org.apache.commons.logging.Log;
 32  
 import org.apache.commons.logging.LogFactory;
 33  
 import org.apache.torque.engine.EngineException;
 34  
 import org.apache.torque.engine.database.transform.DTDResolver;
 35  
 import org.apache.torque.engine.platform.Platform;
 36  
 import org.apache.torque.engine.platform.PlatformFactory;
 37  
 import org.xml.sax.Attributes;
 38  
 
 39  
 /**
 40  
  * A class for holding application data structures.
 41  
  * 
 42  
  * @author <a href="mailto:leon@opticode.co.za>Leon Messerschmidt</a>
 43  
  * @author <a href="mailto:jmcnally@collab.net>John McNally</a>
 44  
  * @author <a href="mailto:mpoeschl@marmot.at>Martin Poeschl</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: Database.java,v 1.1.6.1 2008-04-01 04:07:48 jkeller Exp $
 49  
  */
 50  
 public class Database {
 51  
         /** Logging class from commons.logging */
 52  0
         private static Log log = LogFactory.getLog(Database.class);
 53  
 
 54  0
         private String databaseType = null;
 55  0
         private List tableList = new ArrayList(100);
 56  0
         private Map domainMap = new HashMap();
 57  
         private String name;
 58  
         private String javaName;
 59  
         private String pkg;
 60  
         private String baseClass;
 61  
         private String basePeer;
 62  
         private String defaultIdMethod;
 63  
         private String defaultJavaType;
 64  
         private String defaultJavaNamingMethod;
 65  0
         private Hashtable tablesByName = new Hashtable();
 66  0
         private Hashtable tablesByJavaName = new Hashtable();
 67  
         private boolean heavyIndexing;
 68  
         /** the name of the definition file */
 69  
         private String fileName;
 70  0
         private Map options = Collections.synchronizedMap(new ListOrderedMap());
 71  
 
 72  
         /**
 73  
          * Creates a new instance for the specified database type.
 74  
          * 
 75  
          * @param databaseType
 76  
          *            The default type for this database.
 77  
          */
 78  0
         public Database(String databaseType) {
 79  0
                 this.databaseType = databaseType;
 80  0
         }
 81  
 
 82  
         /**
 83  
          * Load the database object from an xml tag.
 84  
          * 
 85  
          * @param attrib
 86  
          *            the xml attributes
 87  
          */
 88  
         public void loadFromXML(Attributes attrib) {
 89  0
                 setName(attrib.getValue("name"));
 90  0
                 pkg = attrib.getValue("package");
 91  0
                 baseClass = attrib.getValue("baseClass");
 92  0
                 basePeer = attrib.getValue("basePeer");
 93  0
                 defaultJavaType = attrib.getValue("defaultJavaType");
 94  0
                 defaultIdMethod = attrib.getValue("defaultIdMethod");
 95  0
                 defaultJavaNamingMethod = attrib.getValue("defaultJavaNamingMethod");
 96  0
                 if (defaultJavaNamingMethod == null) {
 97  0
                         defaultJavaNamingMethod = NameGenerator.CONV_METHOD_UNDERSCORE;
 98  
                 }
 99  0
                 heavyIndexing = "true".equals(attrib.getValue("heavyIndexing"));
 100  0
         }
 101  
 
 102  
         /**
 103  
          * Get the name of the Database
 104  
          * 
 105  
          * @return name of the Database
 106  
          */
 107  
         public String getName() {
 108  0
                 return name;
 109  
         }
 110  
 
 111  
         /**
 112  
          * Set the name of the Database
 113  
          * 
 114  
          * @param name
 115  
          *            name of the Database
 116  
          */
 117  
         public void setName(String name) {
 118  
                 /** @task check this */
 119  
                 // this.name = (name == null ? Torque.getDefaultDB() : name);
 120  0
                 this.name = (name == null ? "default" : name);
 121  0
         }
 122  
 
 123  
         public String getFileName() {
 124  0
                 return fileName;
 125  
         }
 126  
 
 127  
         public void setFileName(String name) {
 128  0
                 this.fileName = name;
 129  0
         }
 130  
 
 131  
         /**
 132  
          * Get the value of package.
 133  
          * 
 134  
          * @return value of package.
 135  
          */
 136  
         public String getPackage() {
 137  0
                 return pkg;
 138  
         }
 139  
 
 140  
         /**
 141  
          * Set the value of package.
 142  
          * 
 143  
          * @param v
 144  
          *            Value to assign to package.
 145  
          */
 146  
         public void setPackage(String v) {
 147  0
                 this.pkg = v;
 148  0
         }
 149  
 
 150  
         /**
 151  
          * Get the value of baseClass.
 152  
          * 
 153  
          * @return value of baseClass.
 154  
          */
 155  
         public String getBaseClass() {
 156  0
                 if (baseClass == null) {
 157  0
                         return "BaseObject";
 158  
                 }
 159  0
                 return baseClass;
 160  
         }
 161  
 
 162  
         /**
 163  
          * Set the value of baseClass.
 164  
          * 
 165  
          * @param v
 166  
          *            Value to assign to baseClass.
 167  
          */
 168  
         public void setBaseClass(String v) {
 169  0
                 this.baseClass = v;
 170  0
         }
 171  
 
 172  
         /**
 173  
          * Get the value of basePeer.
 174  
          * 
 175  
          * @return value of basePeer.
 176  
          */
 177  
         public String getBasePeer() {
 178  0
                 if (basePeer == null) {
 179  0
                         return "BasePeer";
 180  
                 }
 181  0
                 return basePeer;
 182  
         }
 183  
 
 184  
         /**
 185  
          * Set the value of basePeer.
 186  
          * 
 187  
          * @param v
 188  
          *            Value to assign to basePeer.
 189  
          */
 190  
         public void setBasePeer(String v) {
 191  0
                 this.basePeer = v;
 192  0
         }
 193  
 
 194  
         /**
 195  
          * Get the value of defaultIdMethod.
 196  
          * 
 197  
          * @return value of defaultIdMethod.
 198  
          */
 199  
         public String getDefaultIdMethod() {
 200  0
                 return defaultIdMethod;
 201  
         }
 202  
 
 203  
         /**
 204  
          * Set the value of defaultIdMethod.
 205  
          * 
 206  
          * @param v
 207  
          *            Value to assign to defaultIdMethod.
 208  
          */
 209  
         public void setDefaultIdMethod(String v) {
 210  0
                 this.defaultIdMethod = v;
 211  0
         }
 212  
 
 213  
         /**
 214  
          * Get type to use in Java sources (primitive || object)
 215  
          * 
 216  
          * @return the type to use
 217  
          */
 218  
         public String getDefaultJavaType() {
 219  0
                 return defaultJavaType;
 220  
         }
 221  
 
 222  
         /**
 223  
          * Get the value of defaultJavaNamingMethod which specifies the method for converting schema names for table and
 224  
          * column to Java names.
 225  
          * 
 226  
          * @return The default naming conversion used by this database.
 227  
          */
 228  
         public String getDefaultJavaNamingMethod() {
 229  0
                 return defaultJavaNamingMethod;
 230  
         }
 231  
 
 232  
         /**
 233  
          * Set the value of defaultJavaNamingMethod.
 234  
          * 
 235  
          * @param v
 236  
          *            The default naming conversion for this database to use.
 237  
          */
 238  
         public void setDefaultJavaNamingMethod(String v) {
 239  0
                 this.defaultJavaNamingMethod = v;
 240  0
         }
 241  
 
 242  
         /**
 243  
          * Get the value of heavyIndexing.
 244  
          * 
 245  
          * @return value of heavyIndexing.
 246  
          */
 247  
         public boolean isHeavyIndexing() {
 248  0
                 return heavyIndexing;
 249  
         }
 250  
 
 251  
         /**
 252  
          * Set the value of heavyIndexing.
 253  
          * 
 254  
          * @param v
 255  
          *            Value to assign to heavyIndexing.
 256  
          */
 257  
         public void setHeavyIndexing(boolean v) {
 258  0
                 this.heavyIndexing = v;
 259  0
         }
 260  
 
 261  
         /**
 262  
          * Return an List of all tables
 263  
          * 
 264  
          * @return List of all tables
 265  
          */
 266  
         public List getTables() {
 267  0
                 return tableList;
 268  
         }
 269  
 
 270  
         /**
 271  
          * Return the table with the specified name.
 272  
          * 
 273  
          * @param name
 274  
          *            table name
 275  
          * @return A Table object. If it does not exist it returns null
 276  
          */
 277  
         public Table getTable(String name) {
 278  0
                 return (Table) tablesByName.get(name);
 279  
         }
 280  
 
 281  
         /**
 282  
          * Return the table with the specified javaName.
 283  
          * 
 284  
          * @param javaName
 285  
          *            name of the java object representing the table
 286  
          * @return A Table object. If it does not exist it returns null
 287  
          */
 288  
         public Table getTableByJavaName(String javaName) {
 289  0
                 return (Table) tablesByJavaName.get(javaName);
 290  
         }
 291  
 
 292  
         /**
 293  
          * An utility method to add a new table from an xml attribute.
 294  
          * 
 295  
          * @param attrib
 296  
          *            the xml attributes
 297  
          * @return the created Table
 298  
          */
 299  
         public Table addTable(Attributes attrib) {
 300  0
                 Table tbl = new Table();
 301  0
                 tbl.setDatabase(this);
 302  0
                 tbl.loadFromXML(attrib, this.getDefaultIdMethod());
 303  0
                 addTable(tbl);
 304  0
                 return tbl;
 305  
         }
 306  
 
 307  
         /**
 308  
          * Add a table to the list and sets the Database property to this Database
 309  
          * 
 310  
          * @param tbl
 311  
          *            the table to add
 312  
          */
 313  
         public void addTable(Table tbl) {
 314  0
                 tbl.setDatabase(this);
 315  0
                 tableList.add(tbl);
 316  0
                 tablesByName.put(tbl.getName(), tbl);
 317  0
                 tablesByName.put(tbl.getName().toLowerCase(), tbl);
 318  0
                 tablesByName.put(tbl.getName().toUpperCase(), tbl);
 319  0
                 tablesByJavaName.put(tbl.getJavaName(), tbl);
 320  0
                 tbl.setPackage(getPackage());
 321  0
         }
 322  
 
 323  
         public void addDomain(Domain domain) {
 324  0
                 domainMap.put(domain.getName(), domain);
 325  0
         }
 326  
 
 327  
         public Domain getDomain(String domainName) {
 328  0
                 return (Domain) domainMap.get(domainName);
 329  
         }
 330  
 
 331  
         protected String getDatabaseType() {
 332  0
                 return databaseType;
 333  
         }
 334  
 
 335  
         public void setDatabaseType(String databaseType) {
 336  0
                 this.databaseType = databaseType;
 337  0
         }
 338  
 
 339  
         /**
 340  
          * Returns the Platform implementation for this database.
 341  
          * 
 342  
          * @return a Platform implementation
 343  
          */
 344  
         public Platform getPlatform() {
 345  0
                 return PlatformFactory.getPlatformFor(databaseType);
 346  
         }
 347  
 
 348  
         /**
 349  
          * Determines if this database will be using the <code>IDMethod.ID_BROKER</code> to create ids for torque OM
 350  
          * objects.
 351  
          * 
 352  
          * @return true if there is at least one table in this database that uses the <code>IDMethod.ID_BROKER</code> method
 353  
          *         of generating ids. returns false otherwise.
 354  
          */
 355  
         public boolean requiresIdTable() {
 356  0
                 Iterator iter = getTables().iterator();
 357  0
                 while (iter.hasNext()) {
 358  0
                         Table table = (Table) iter.next();
 359  0
                         if (table.getIdMethod().equals(IDMethod.ID_BROKER)) {
 360  0
                                 return true;
 361  
                         }
 362  0
                 }
 363  0
                 return false;
 364  
         }
 365  
 
 366  
         /**
 367  
          * Initializes the model.
 368  
          * 
 369  
          * @throws EngineException
 370  
          */
 371  
         public void doFinalInitialization() throws EngineException {
 372  0
                 Iterator iter = getTables().iterator();
 373  0
                 while (iter.hasNext()) {
 374  0
                         Table currTable = (Table) iter.next();
 375  
 
 376  
                         // check schema integrity
 377  
                         // if idMethod="autoincrement", make sure a column is
 378  
                         // specified as autoIncrement="true"
 379  
                         // FIXME: Handle idMethod="native" via DB adapter.
 380  
                         // TODO autoincrement is no longer supported!!!
 381  0
                         if (currTable.getIdMethod().equals("autoincrement")) {
 382  0
                                 boolean foundOne = false;
 383  0
                                 Iterator colIter = currTable.getColumns().iterator();
 384  0
                                 while (colIter.hasNext() && !foundOne) {
 385  0
                                         foundOne = ((Column) colIter.next()).isAutoIncrement();
 386  
                                 }
 387  
 
 388  0
                                 if (!foundOne) {
 389  0
                                         String errorMessage = "Table '" + currTable.getName() + "' is marked as autoincrement, but it does not " + "have a column which declared as the one to " + "auto increment (i.e. autoIncrement=\"true\")\n";
 390  0
                                         throw new EngineException("Error in XML schema: " + errorMessage);
 391  
                                 }
 392  
                         }
 393  
 
 394  0
                         currTable.doFinalInitialization();
 395  
 
 396  
                         // setup reverse fk relations
 397  0
                         Iterator fks = currTable.getForeignKeys().iterator();
 398  0
                         while (fks.hasNext()) {
 399  0
                                 ForeignKey currFK = (ForeignKey) fks.next();
 400  0
                                 Table foreignTable = getTable(currFK.getForeignTableName());
 401  0
                                 if (foreignTable == null) {
 402  0
                                         throw new EngineException("Attempt to set foreign" + " key to nonexistent table, " + currFK.getForeignTableName());
 403  
                                 } else {
 404  
                                         // TODO check type and size
 405  0
                                         List referrers = foreignTable.getReferrers();
 406  0
                                         if ((referrers == null || !referrers.contains(currFK))) {
 407  0
                                                 foreignTable.addReferrer(currFK);
 408  
                                         }
 409  
 
 410  
                                         // local column references
 411  0
                                         Iterator localColumnNames = currFK.getLocalColumns().iterator();
 412  0
                                         while (localColumnNames.hasNext()) {
 413  0
                                                 Column local = currTable.getColumn((String) localColumnNames.next());
 414  
                                                 // give notice of a schema inconsistency.
 415  
                                                 // note we do not prevent the npe as there is nothing
 416  
                                                 // that we can do, if it is to occur.
 417  0
                                                 if (local == null) {
 418  0
                                                         throw new EngineException("Attempt to define foreign" + " key with nonexistent column in table, " + currTable.getName());
 419  
                                                 } else {
 420  
                                                         // check for foreign pk's
 421  0
                                                         if (local.isPrimaryKey()) {
 422  0
                                                                 currTable.setContainsForeignPK(true);
 423  
                                                         }
 424  
                                                 }
 425  0
                                         }
 426  
 
 427  
                                         // foreign column references
 428  0
                                         Iterator foreignColumnNames = currFK.getForeignColumns().iterator();
 429  0
                                         while (foreignColumnNames.hasNext()) {
 430  0
                                                 String foreignColumnName = (String) foreignColumnNames.next();
 431  0
                                                 Column foreign = foreignTable.getColumn(foreignColumnName);
 432  
                                                 // if the foreign column does not exist, we may have an
 433  
                                                 // external reference or a misspelling
 434  0
                                                 if (foreign == null) {
 435  0
                                                         throw new EngineException("Attempt to set foreign" + " key to nonexistent column: table=" + currTable.getName() + ", foreign column=" + foreignColumnName);
 436  
                                                 } else {
 437  0
                                                         foreign.addReferrer(currFK);
 438  
                                                 }
 439  0
                                         }
 440  
                                 }
 441  0
                         }
 442  0
                 }
 443  0
         }
 444  
 
 445  
         /**
 446  
          * Get the base name to use when creating related Java Classes.
 447  
          * 
 448  
          * @return A Java syntax capatible version of the dbName using the method defined by the defaultJavaNamingMethod XML
 449  
          *         value.
 450  
          */
 451  
         public String getJavaName() {
 452  0
                 if (javaName == null) {
 453  0
                         List inputs = new ArrayList(2);
 454  0
                         inputs.add(name);
 455  0
                         inputs.add(defaultJavaNamingMethod);
 456  
                         try {
 457  0
                                 javaName = NameFactory.generateName(NameFactory.JAVA_GENERATOR, inputs);
 458  0
                         } catch (EngineException e) {
 459  0
                                 log.error(e, e);
 460  0
                         }
 461  
                 }
 462  0
                 return javaName;
 463  
         }
 464  
 
 465  
         /**
 466  
          * Convert dbName to a Java compatible name by the JavaName method only (ignores the defaultJavaNamingMethod).
 467  
          * 
 468  
          * @return The current dbName converted to a standard format that can be used as part of a Java Object name.
 469  
          */
 470  
         public String getStandardJavaName() {
 471  0
                 if (javaName == null) {
 472  0
                         List inputs = new ArrayList(2);
 473  0
                         inputs.add(name);
 474  0
                         inputs.add(NameGenerator.CONV_METHOD_JAVANAME);
 475  
                         try {
 476  0
                                 javaName = NameFactory.generateName(NameFactory.JAVA_GENERATOR, inputs);
 477  0
                         } catch (EngineException e) {
 478  0
                                 log.error(e, e);
 479  0
                         }
 480  
                 }
 481  0
                 return javaName;
 482  
         }
 483  
 
 484  
         /**
 485  
          * Creats a string representation of this Database. The representation is given in xml format.
 486  
          * 
 487  
          * @return string representation in xml
 488  
          */
 489  
         public String toString() {
 490  0
                 StringBuffer result = new StringBuffer();
 491  
 
 492  0
                 result.append("<?xml version=\"1.0\"?>\n");
 493  0
                 result.append("<!DOCTYPE database SYSTEM \"" + DTDResolver.WEB_SITE_DTD + "\">\n");
 494  0
                 result.append("<!-- Autogenerated by SQLToXMLSchema! -->\n");
 495  0
                 result.append("<database name=\"").append(getName()).append('"').append(" package=\"").append(getPackage()).append('"').append(" defaultIdMethod=\"").append(getDefaultIdMethod()).append('"').append(" baseClass=\"").append(getBaseClass()).append('"').append(" basePeer=\"").append(getBasePeer()).append('"').append(">\n");
 496  
 
 497  0
                 for (Iterator i = tableList.iterator(); i.hasNext();) {
 498  0
                         result.append(i.next());
 499  
                 }
 500  
 
 501  0
                 result.append("</database>");
 502  0
                 return result.toString();
 503  
         }
 504  
 
 505  
         /**
 506  
          * Add an XML Specified option key/value pair to this element's option set.
 507  
          * 
 508  
          * @param key
 509  
          *            the key of the option.
 510  
          * @param value
 511  
          *            the value of the option.
 512  
          */
 513  
         public void addOption(String key, String value) {
 514  0
                 options.put(key, value);
 515  0
         }
 516  
 
 517  
         /**
 518  
          * Get the value that was associated with this key in an XML option element.
 519  
          * 
 520  
          * @param key
 521  
          *            the key of the option.
 522  
          * @return The value for the key or a null.
 523  
          */
 524  
         public String getOption(String key) {
 525  0
                 return (String) options.get(key);
 526  
         }
 527  
 
 528  
         /**
 529  
          * Gets the full ordered hashtable array of items specified by XML option statements under this element.
 530  
          * <p>
 531  
          * 
 532  
          * Note, this is not thread save but since it's only used for generation which is single threaded, there should be
 533  
          * minimum danger using this in Velocity.
 534  
          * 
 535  
          * @return An Map of all options. Will not be null but may be empty.
 536  
          */
 537  
         public Map getOptions() {
 538  0
                 return options;
 539  
         }
 540  
 }