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