1 package org.apache.torque.engine.database.model;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 import java.util.ArrayList;
20 import java.util.Hashtable;
21 import java.util.Iterator;
22 import java.util.List;
23 import java.util.Properties;
24
25 import org.apache.torque.engine.EngineException;
26
27 import org.xml.sax.Attributes;
28
29
30 /***
31 * A class for holding application data structures.
32 *
33 * @author <a href="mailto:leon@opticode.co.za>Leon Messerschmidt</a>
34 * @author <a href="mailto:jmcnally@collab.net>John McNally</a>
35 * @author <a href="mailto:mpoeschl@marmot.at>Martin Poeschl</a>
36 * @author <a href="mailto:dlr@collab.net>Daniel Rall</a>
37 * @author <a href="mailto:byron_foster@byron_foster@yahoo.com>Byron Foster</a>
38 * @version $Id: Database.java,v 1.6.2.2 2004/05/20 04:34:15 seade Exp $
39 */
40 public class Database
41 {
42 private String databaseType = null;
43 private List tableList = new ArrayList(100);
44 private String name;
45 private String pkg;
46 private String baseClass;
47 private String basePeer;
48 private String defaultIdMethod;
49 private String defaultJavaType;
50 private String defaultJavaNamingMethod;
51 private AppData dbParent;
52 private Hashtable tablesByName = new Hashtable();
53 private Hashtable tablesByJavaName = new Hashtable();
54 private boolean heavyIndexing;
55
56 /***
57 * Load the database object from an xml tag.
58 *
59 * @param attrib the xml attributes
60 */
61 public void loadFromXML(Attributes attrib)
62 {
63 setName(attrib.getValue("name"));
64 pkg = attrib.getValue("package");
65 baseClass = attrib.getValue("baseClass");
66 basePeer = attrib.getValue("basePeer");
67 defaultJavaType = attrib.getValue("defaultJavaType");
68 defaultIdMethod = attrib.getValue("defaultIdMethod");
69 defaultJavaNamingMethod = attrib.getValue("defaultJavaNamingMethod");
70 if (defaultJavaNamingMethod == null)
71 {
72 defaultJavaNamingMethod = NameGenerator.CONV_METHOD_UNDERSCORE;
73 }
74 heavyIndexing = "true".equals(attrib.getValue("heavyIndexing"));
75 }
76
77 /***
78 * Get the name of the Database
79 *
80 * @return name of the Database
81 */
82 public String getName()
83 {
84 return name;
85 }
86
87 /***
88 * Set the name of the Database
89 *
90 * @param name name of the Database
91 */
92 public void setName(String name)
93 {
94 /*** @task check this */
95
96 this.name = (name == null ? "default" : name);
97 }
98
99 /***
100 * Get the value of package.
101 * @return value of package.
102 */
103 public String getPackage()
104 {
105 return pkg;
106 }
107
108 /***
109 * Set the value of package.
110 * @param v Value to assign to package.
111 */
112 public void setPackage(String v)
113 {
114 this.pkg = v;
115 }
116
117 /***
118 * Get the value of baseClass.
119 * @return value of baseClass.
120 */
121 public String getBaseClass()
122 {
123 if (baseClass == null)
124 {
125 return "BaseObject";
126 }
127 return baseClass;
128 }
129
130 /***
131 * Set the value of baseClass.
132 * @param v Value to assign to baseClass.
133 */
134 public void setBaseClass(String v)
135 {
136 this.baseClass = v;
137 }
138
139 /***
140 * Get the value of basePeer.
141 * @return value of basePeer.
142 */
143 public String getBasePeer()
144 {
145 if (basePeer == null)
146 {
147 return "BasePeer";
148 }
149 return basePeer;
150 }
151
152 /***
153 * Set the value of basePeer.
154 * @param v Value to assign to basePeer.
155 */
156 public void setBasePeer(String v)
157 {
158 this.basePeer = v;
159 }
160
161 /***
162 * Get the value of defaultIdMethod.
163 * @return value of defaultIdMethod.
164 */
165 public String getDefaultIdMethod()
166 {
167 return defaultIdMethod;
168 }
169
170 /***
171 * Set the value of defaultIdMethod.
172 * @param v Value to assign to defaultIdMethod.
173 */
174 public void setDefaultIdMethod(String v)
175 {
176 this.defaultIdMethod = v;
177 }
178
179 /***
180 * Get type to use in Java sources (primitive || object)
181 *
182 * @return the type to use
183 */
184 public String getDefaultJavaType()
185 {
186 return defaultJavaType;
187 }
188
189 /***
190 * Get the value of defaultJavaNamingMethod which specifies the
191 * method for converting schema names for table and column to Java names.
192 *
193 * @return The default naming conversion used by this database.
194 */
195 public String getDefaultJavaNamingMethod()
196 {
197 return defaultJavaNamingMethod;
198 }
199
200 /***
201 * Set the value of defaultJavaNamingMethod.
202 * @param v The default naming conversion for this database to use.
203 */
204 public void setDefaultJavaNamingMethod(String v)
205 {
206 this.defaultJavaNamingMethod = v;
207 }
208
209 /***
210 * Get the value of heavyIndexing.
211 * @return value of heavyIndexing.
212 */
213 public boolean isHeavyIndexing()
214 {
215 return heavyIndexing;
216 }
217
218 /***
219 * Set the value of heavyIndexing.
220 * @param v Value to assign to heavyIndexing.
221 */
222 public void setHeavyIndexing(boolean v)
223 {
224 this.heavyIndexing = v;
225 }
226
227 /***
228 * Return an array of all tables
229 *
230 * @return array of all tables
231 */
232 public Table[] getTables()
233 {
234 int size = tableList.size();
235 Table[] tbls = new Table[size];
236 for (int i = 0; i < size; i++)
237 {
238 tbls[i] = (Table) tableList.get(i);
239 }
240 return tbls;
241 }
242
243 /***
244 * Return the table with the specified name.
245 *
246 * @param name table name
247 * @return A Table object. If it does not exist it returns null
248 */
249 public Table getTable(String name)
250 {
251 return (Table) tablesByName.get(name);
252 }
253
254 /***
255 * Return the table with the specified javaName.
256 *
257 * @param javaName name of the java object representing the table
258 * @return A Table object. If it does not exist it returns null
259 */
260 public Table getTableByJavaName(String javaName)
261 {
262 return (Table) tablesByJavaName.get(javaName);
263 }
264
265 /***
266 * An utility method to add a new table from an xml attribute.
267 *
268 * @param attrib the xml attributes
269 * @return the created Table
270 */
271 public Table addTable(Attributes attrib)
272 {
273 Table tbl = new Table();
274 tbl.setDatabase(this);
275 tbl.loadFromXML(attrib, this.getDefaultIdMethod());
276 addTable(tbl);
277 return tbl;
278 }
279
280 /***
281 * Add a table to the list and sets the Database property to this Database
282 *
283 * @param tbl the table to add
284 */
285 public void addTable(Table tbl)
286 {
287 tbl.setDatabase(this);
288 tableList.add(tbl);
289 tablesByName.put(tbl.getName(), tbl);
290 tablesByJavaName.put(tbl.getJavaName(), tbl);
291 tbl.setPackage(getPackage());
292 }
293
294 /***
295 * Set the parent of the database
296 *
297 * @param parent the parent
298 */
299 public void setAppData(AppData parent)
300 {
301 dbParent = parent;
302 }
303
304 /***
305 * Get the parent of the table
306 *
307 * @return the parent
308 */
309 public AppData getAppData()
310 {
311 return dbParent;
312 }
313
314 protected String getDatabaseType()
315 {
316 return databaseType;
317 }
318
319 public void setDatabaseType(String databaseType)
320 {
321 this.databaseType = databaseType;
322 }
323
324 /***
325 * Returns the value of the named property from this database's
326 * <code>db.props</code> file.
327 *
328 * @param name The name of the property to retrieve the value of.
329 * @return The value of the specified property.
330 * @exception EngineException Couldn't access properties.
331 */
332 protected String getProperty(String name)
333 throws EngineException
334 {
335 Properties p = getAppData().getIdiosyncrasies(databaseType);
336 return (p == null ? null : p.getProperty(name));
337 }
338
339 /***
340 * Determines if this database will be using the
341 * <code>IDMethod.ID_BROKER</code> to create ids for torque OM
342 * objects.
343 * @return true if there is at least one table in this database that
344 * uses the <code>IDMethod.ID_BROKER</code> method of generating
345 * ids. returns false otherwise.
346 */
347 public boolean requiresIdTable()
348 {
349 Table table[] = getTables();
350 for (int i = 0; i < table.length; i++)
351 {
352 if (table[i].getIdMethod().equals(IDMethod.ID_BROKER))
353 {
354 return true;
355 }
356 }
357 return false;
358 }
359
360 public void doFinalInitialization()
361 throws EngineException
362 {
363 Table[] tables = getTables();
364 for (int i = 0; i < tables.length; i++)
365 {
366 Table currTable = tables[i];
367
368
369
370
371
372 if (currTable.getIdMethod().equals("autoincrement"))
373 {
374 Column[] columns = currTable.getColumns();
375 boolean foundOne = false;
376 for (int j = 0; j < columns.length && !foundOne; j++)
377 {
378 foundOne = columns[j].isAutoIncrement();
379 }
380
381 if (!foundOne)
382 {
383 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 throw new EngineException("Error in XML schema: " + errorMessage);
388 }
389 }
390
391 currTable.doFinalInitialization();
392
393
394 ForeignKey[] fks = currTable.getForeignKeys();
395 for (int j = 0; j < fks.length; j++)
396 {
397 ForeignKey currFK = fks[j];
398 Table foreignTable = getTable(currFK.getForeignTableName());
399 if (foreignTable == null)
400 {
401 throw new EngineException("Attempt to set foreign"
402 + " key to nonexistent table, "
403 + currFK.getForeignTableName());
404 }
405 else
406 {
407 List referrers = foreignTable.getReferrers();
408 if ((referrers == null || !referrers.contains(currFK)))
409 {
410 foreignTable.addReferrer(currFK);
411 }
412
413
414 Iterator localColumnNames = currFK.getLocalColumns().iterator();
415 while (localColumnNames.hasNext())
416 {
417 Column local = currTable
418 .getColumn((String) localColumnNames.next());
419
420
421
422 if (local == null)
423 {
424 throw new EngineException("Attempt to define foreign"
425 + " key with nonexistent column in table, "
426 + currTable.getName());
427 }
428 else
429 {
430
431 if (local.isPrimaryKey())
432 {
433 currTable.setContainsForeignPK(true);
434 }
435 }
436 }
437
438
439 Iterator foreignColumnNames
440 = currFK.getForeignColumns().iterator();
441 while (foreignColumnNames.hasNext())
442 {
443 String foreignColumnName = (String) foreignColumnNames.next();
444 Column foreign = foreignTable.getColumn(foreignColumnName);
445
446
447 if (foreign == null)
448 {
449 throw new EngineException("Attempt to set foreign"
450 + " key to nonexistent column: table="
451 + currTable.getName() + ", foreign column="
452 + foreignColumnName);
453 }
454 else
455 {
456 foreign.addReferrer(currFK);
457 }
458 }
459 }
460 }
461 }
462 }
463
464 /***
465 * Creats a string representation of this Database.
466 * The representation is given in xml format.
467 *
468 * @return string representation in xml
469 */
470 public String toString()
471 {
472 StringBuffer result = new StringBuffer();
473
474 result.append("<database name=\"").append(getName()).append('"')
475 .append(" package=\"").append(getPackage()).append('"')
476 .append(" defaultIdMethod=\"").append(getDefaultIdMethod())
477 .append('"')
478 .append(" baseClass=\"").append(getBaseClass()).append('"')
479 .append(" basePeer=\"").append(getBasePeer()).append('"')
480 .append(">\n");
481
482 for (Iterator i = tableList.iterator(); i.hasNext();)
483 {
484 result.append(i.next());
485 }
486
487 result.append("</database>");
488 return result.toString();
489 }
490 }