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