1 package org.apache.torque.engine.database.model;
2
3 /* ====================================================================
4 * The Apache Software License, Version 1.1
5 *
6 * Copyright (c) 2001-2003 The Apache Software Foundation. All rights
7 * reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 *
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 *
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in
18 * the documentation and/or other materials provided with the
19 * distribution.
20 *
21 * 3. The end-user documentation included with the redistribution,
22 * if any, must include the following acknowledgment:
23 * "This product includes software developed by the
24 * Apache Software Foundation (http://www.apache.org/)."
25 * Alternately, this acknowledgment may appear in the software itself,
26 * if and wherever such third-party acknowledgments normally appear.
27 *
28 * 4. The names "Apache" and "Apache Software Foundation" and
29 * "Apache Turbine" must not be used to endorse or promote products
30 * derived from this software without prior written permission. For
31 * written permission, please contact apache@apache.org.
32 *
33 * 5. Products derived from this software may not be called "Apache",
34 * "Apache Turbine", nor may "Apache" appear in their name, without
35 * prior written permission of the Apache Software Foundation.
36 *
37 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
38 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
39 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
40 * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
41 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
42 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
43 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
44 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
45 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
46 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
47 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
48 * SUCH DAMAGE.
49 * ====================================================================
50 *
51 * This software consists of voluntary contributions made by many
52 * individuals on behalf of the Apache Software Foundation. For more
53 * information on the Apache Software Foundation, please see
54 * <http://www.apache.org/>.
55 */
56
57 import java.util.ArrayList;
58 import java.util.Hashtable;
59 import java.util.Iterator;
60 import java.util.List;
61 import java.util.Properties;
62
63 import org.apache.torque.engine.EngineException;
64
65 import org.xml.sax.Attributes;
66
67
68 /***
69 * A class for holding application data structures.
70 *
71 * @author <a href="mailto:leon@opticode.co.za>Leon Messerschmidt</a>
72 * @author <a href="mailto:jmcnally@collab.net>John McNally</a>
73 * @author <a href="mailto:mpoeschl@marmot.at>Martin Poeschl</a>
74 * @author <a href="mailto:dlr@collab.net>Daniel Rall</a>
75 * @author <a href="mailto:byron_foster@byron_foster@yahoo.com>Byron Foster</a>
76 * @version $Id: Database.java,v 1.6 2003/08/04 05:30:29 mpoeschl Exp $
77 */
78 public class Database
79 {
80 private String databaseType = null;
81 private List tableList = new ArrayList(100);
82 private String name;
83 private String pkg;
84 private String baseClass;
85 private String basePeer;
86 private String defaultIdMethod;
87 private String defaultJavaType;
88 private String defaultJavaNamingMethod;
89 private AppData dbParent;
90 private Hashtable tablesByName = new Hashtable();
91 private Hashtable tablesByJavaName = new Hashtable();
92 private boolean heavyIndexing;
93
94 /***
95 * Load the database object from an xml tag.
96 *
97 * @param attrib the xml attributes
98 */
99 public void loadFromXML(Attributes attrib)
100 {
101 setName(attrib.getValue("name"));
102 pkg = attrib.getValue("package");
103 baseClass = attrib.getValue("baseClass");
104 basePeer = attrib.getValue("basePeer");
105 defaultJavaType = attrib.getValue("defaultJavaType");
106 defaultIdMethod = attrib.getValue("defaultIdMethod");
107 defaultJavaNamingMethod = attrib.getValue("defaultJavaNamingMethod");
108 if (defaultJavaNamingMethod == null)
109 {
110 defaultJavaNamingMethod = NameGenerator.CONV_METHOD_UNDERSCORE;
111 }
112 heavyIndexing = "true".equals(attrib.getValue("heavyIndexing"));
113 }
114
115 /***
116 * Get the name of the Database
117 *
118 * @return name of the Database
119 */
120 public String getName()
121 {
122 return name;
123 }
124
125 /***
126 * Set the name of the Database
127 *
128 * @param name name of the Database
129 */
130 public void setName(String name)
131 {
132 /*** @task check this */
133 // this.name = (name == null ? Torque.getDefaultDB() : name);
134 this.name = (name == null ? "default" : name);
135 }
136
137 /***
138 * Get the value of package.
139 * @return value of package.
140 */
141 public String getPackage()
142 {
143 return pkg;
144 }
145
146 /***
147 * Set the value of package.
148 * @param v Value to assign to package.
149 */
150 public void setPackage(String v)
151 {
152 this.pkg = v;
153 }
154
155 /***
156 * Get the value of baseClass.
157 * @return value of baseClass.
158 */
159 public String getBaseClass()
160 {
161 if (baseClass == null)
162 {
163 return "BaseObject";
164 }
165 return baseClass;
166 }
167
168 /***
169 * Set the value of baseClass.
170 * @param v Value to assign to baseClass.
171 */
172 public void setBaseClass(String v)
173 {
174 this.baseClass = v;
175 }
176
177 /***
178 * Get the value of basePeer.
179 * @return value of basePeer.
180 */
181 public String getBasePeer()
182 {
183 if (basePeer == null)
184 {
185 return "BasePeer";
186 }
187 return basePeer;
188 }
189
190 /***
191 * Set the value of basePeer.
192 * @param v Value to assign to basePeer.
193 */
194 public void setBasePeer(String v)
195 {
196 this.basePeer = v;
197 }
198
199 /***
200 * Get the value of defaultIdMethod.
201 * @return value of defaultIdMethod.
202 */
203 public String getDefaultIdMethod()
204 {
205 return defaultIdMethod;
206 }
207
208 /***
209 * Set the value of defaultIdMethod.
210 * @param v Value to assign to defaultIdMethod.
211 */
212 public void setDefaultIdMethod(String v)
213 {
214 this.defaultIdMethod = v;
215 }
216
217 /***
218 * Get type to use in Java sources (primitive || object)
219 *
220 * @return the type to use
221 */
222 public String getDefaultJavaType()
223 {
224 return defaultJavaType;
225 }
226
227 /***
228 * Get the value of defaultJavaNamingMethod which specifies the
229 * method for converting schema names for table and column to Java names.
230 *
231 * @return The default naming conversion used by this database.
232 */
233 public String getDefaultJavaNamingMethod()
234 {
235 return defaultJavaNamingMethod;
236 }
237
238 /***
239 * Set the value of defaultJavaNamingMethod.
240 * @param v The default naming conversion for this database to use.
241 */
242 public void setDefaultJavaNamingMethod(String v)
243 {
244 this.defaultJavaNamingMethod = v;
245 }
246
247 /***
248 * Get the value of heavyIndexing.
249 * @return value of heavyIndexing.
250 */
251 public boolean isHeavyIndexing()
252 {
253 return heavyIndexing;
254 }
255
256 /***
257 * Set the value of heavyIndexing.
258 * @param v Value to assign to heavyIndexing.
259 */
260 public void setHeavyIndexing(boolean v)
261 {
262 this.heavyIndexing = v;
263 }
264
265 /***
266 * Return an array of all tables
267 *
268 * @return array of all tables
269 */
270 public Table[] getTables()
271 {
272 int size = tableList.size();
273 Table[] tbls = new Table[size];
274 for (int i = 0; i < size; i++)
275 {
276 tbls[i] = (Table) tableList.get(i);
277 }
278 return tbls;
279 }
280
281 /***
282 * Return the table with the specified name.
283 *
284 * @param name table name
285 * @return A Table object. If it does not exist it returns null
286 */
287 public Table getTable(String name)
288 {
289 return (Table) tablesByName.get(name);
290 }
291
292 /***
293 * Return the table with the specified javaName.
294 *
295 * @param javaName name of the java object representing the table
296 * @return A Table object. If it does not exist it returns null
297 */
298 public Table getTableByJavaName(String javaName)
299 {
300 return (Table) tablesByJavaName.get(javaName);
301 }
302
303 /***
304 * An utility method to add a new table from an xml attribute.
305 *
306 * @param attrib the xml attributes
307 * @return the created Table
308 */
309 public Table addTable(Attributes attrib)
310 {
311 Table tbl = new Table();
312 tbl.setDatabase(this);
313 tbl.loadFromXML(attrib, this.getDefaultIdMethod());
314 addTable(tbl);
315 return tbl;
316 }
317
318 /***
319 * Add a table to the list and sets the Database property to this Database
320 *
321 * @param tbl the table to add
322 */
323 public void addTable(Table tbl)
324 {
325 tbl.setDatabase(this);
326 tableList.add(tbl);
327 tablesByName.put(tbl.getName(), tbl);
328 tablesByJavaName.put(tbl.getJavaName(), tbl);
329 tbl.setPackage(getPackage());
330 }
331
332 /***
333 * Set the parent of the database
334 *
335 * @param parent the parent
336 */
337 public void setAppData(AppData parent)
338 {
339 dbParent = parent;
340 }
341
342 /***
343 * Get the parent of the table
344 *
345 * @return the parent
346 */
347 public AppData getAppData()
348 {
349 return dbParent;
350 }
351
352 protected String getDatabaseType()
353 {
354 return databaseType;
355 }
356
357 public void setDatabaseType(String databaseType)
358 {
359 this.databaseType = databaseType;
360 }
361
362 /***
363 * Returns the value of the named property from this database's
364 * <code>db.props</code> file.
365 *
366 * @param name The name of the property to retrieve the value of.
367 * @return The value of the specified property.
368 * @exception EngineException Couldn't access properties.
369 */
370 protected String getProperty(String name)
371 throws EngineException
372 {
373 Properties p = getAppData().getIdiosyncrasies(databaseType);
374 return (p == null ? null : p.getProperty(name));
375 }
376
377 /***
378 * Determines if this database will be using the
379 * <code>IDMethod.ID_BROKER</code> to create ids for torque OM
380 * objects.
381 * @return true if there is at least one table in this database that
382 * uses the <code>IDMethod.ID_BROKER</code> method of generating
383 * ids. returns false otherwise.
384 */
385 public boolean requiresIdTable()
386 {
387 Table table[] = getTables();
388 for (int i = 0; i < table.length; i++)
389 {
390 if (table[i].getIdMethod().equals(IDMethod.ID_BROKER))
391 {
392 return true;
393 }
394 }
395 return false;
396 }
397
398 public void doFinalInitialization()
399 throws EngineException
400 {
401 Table[] tables = getTables();
402 for (int i = 0; i < tables.length; i++)
403 {
404 Table currTable = tables[i];
405
406 // check schema integrity
407 // if idMethod="autoincrement", make sure a column is
408 // specified as autoIncrement="true"
409 // FIXME: Handle idMethod="native" via DB adapter.
410 if (currTable.getIdMethod().equals("autoincrement"))
411 {
412 Column[] columns = currTable.getColumns();
413 boolean foundOne = false;
414 for (int j = 0; j < columns.length && !foundOne; j++)
415 {
416 foundOne = columns[j].isAutoIncrement();
417 }
418
419 if (!foundOne)
420 {
421 String errorMessage = "Table '" + currTable.getName()
422 + "' is marked as autoincrement, but it does not "
423 + "have a column which declared as the one to "
424 + "auto increment (i.e. autoIncrement=\"true\")\n";
425 throw new EngineException("Error in XML schema: " + errorMessage);
426 }
427 }
428
429 currTable.doFinalInitialization();
430
431 // setup reverse fk relations
432 ForeignKey[] fks = currTable.getForeignKeys();
433 for (int j = 0; j < fks.length; j++)
434 {
435 ForeignKey currFK = fks[j];
436 Table foreignTable = getTable(currFK.getForeignTableName());
437 if (foreignTable == null)
438 {
439 throw new EngineException("Attempt to set foreign"
440 + " key to nonexistent table, "
441 + currFK.getForeignTableName());
442 }
443 else
444 {
445 List referrers = foreignTable.getReferrers();
446 if ((referrers == null || !referrers.contains(currFK)))
447 {
448 foreignTable.addReferrer(currFK);
449 }
450
451 // local column references
452 Iterator localColumnNames = currFK.getLocalColumns().iterator();
453 while (localColumnNames.hasNext())
454 {
455 Column local = currTable
456 .getColumn((String) localColumnNames.next());
457 // give notice of a schema inconsistency.
458 // note we do not prevent the npe as there is nothing
459 // that we can do, if it is to occur.
460 if (local == null)
461 {
462 throw new EngineException("Attempt to define foreign"
463 + " key with nonexistent column in table, "
464 + currTable.getName());
465 }
466 else
467 {
468 //check for foreign pk's
469 if (local.isPrimaryKey())
470 {
471 currTable.setContainsForeignPK(true);
472 }
473 }
474 }
475
476 // foreign column references
477 Iterator foreignColumnNames
478 = currFK.getForeignColumns().iterator();
479 while (foreignColumnNames.hasNext())
480 {
481 String foreignColumnName = (String) foreignColumnNames.next();
482 Column foreign = foreignTable.getColumn(foreignColumnName);
483 // if the foreign column does not exist, we may have an
484 // external reference or a misspelling
485 if (foreign == null)
486 {
487 throw new EngineException("Attempt to set foreign"
488 + " key to nonexistent column: table="
489 + currTable.getName() + ", foreign column="
490 + foreignColumnName);
491 }
492 else
493 {
494 foreign.addReferrer(currFK);
495 }
496 }
497 }
498 }
499 }
500 }
501
502 /***
503 * Creats a string representation of this Database.
504 * The representation is given in xml format.
505 *
506 * @return string representation in xml
507 */
508 public String toString()
509 {
510 StringBuffer result = new StringBuffer();
511
512 result.append("<database name=\"").append(getName()).append('"')
513 .append(" package=\"").append(getPackage()).append('"')
514 .append(" defaultIdMethod=\"").append(getDefaultIdMethod())
515 .append('"')
516 .append(" baseClass=\"").append(getBaseClass()).append('"')
517 .append(" basePeer=\"").append(getBasePeer()).append('"')
518 .append(">\n");
519
520 for (Iterator i = tableList.iterator(); i.hasNext();)
521 {
522 result.append(i.next());
523 }
524
525 result.append("</database>");
526 return result.toString();
527 }
528 }
This page was automatically generated by Maven