001: package org.apache.ojb.tools.mapping.reversedb;
002:
003: /* Copyright 2002-2005 The Apache Software Foundation
004: *
005: * Licensed under the Apache License, Version 2.0 (the "License");
006: * you may not use this file except in compliance with the License.
007: * You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: import javax.swing.tree.TreeNode;
019: import java.sql.SQLException;
020: import java.io.File;
021:
022: /**
023: *
024: * @author <a href="mailto:bfl@florianbruckner.com">Florian Bruckner</a>
025: * @version $Id: DBTable.java,v 1.1.2.1 2005/12/21 22:32:04 tomdz Exp $
026: */
027: public class DBTable implements MetadataNodeInterface, TreeNode,
028: org.apache.ojb.tools.mapping.reversedb.gui.PropertySheetModel {
029: private java.sql.DatabaseMetaData dbMeta;
030: private DBSchema aSchema;
031: private java.util.HashMap hmReferences = new java.util.HashMap(0);
032: private java.util.HashMap hmCollections = new java.util.HashMap(0);
033: private java.util.TreeMap tmColumns = new java.util.TreeMap();
034: private java.util.Vector vSubTreeNodes = new java.util.Vector();
035: private String strTableName;
036: private String strClassName;
037: private String strPackageName = ""; // In default package by default ;-)
038: private String strConversionStrategyClass = "";
039:
040: private boolean dynamicProxy = false;
041:
042: private boolean enabled = true;
043:
044: /** Creates a new instance of DBTable */
045: public DBTable(java.sql.DatabaseMetaData pdbMeta,
046: DBSchema paSchema, String pstrTableName) {
047: strTableName = pstrTableName;
048: // this.strClassName = Character.toUpperCase (strTableName.charAt(0)) + strTableName.substring(1).toLowerCase();
049: this .strClassName = Namer.nameClass(this .strTableName);
050: aSchema = paSchema;
051: dbMeta = pdbMeta;
052: }
053:
054: public boolean hasDynamicProxy() {
055: return dynamicProxy;
056: }
057:
058: public void setDynamicProxy(boolean b) {
059: dynamicProxy = b;
060: }
061:
062: public String getConversionStrategyClass() {
063: return this .strConversionStrategyClass;
064: }
065:
066: public void setConversionStrategyClass(String s) {
067: this .strConversionStrategyClass = s;
068: }
069:
070: public boolean isEnabled() {
071: return this .enabled;
072: }
073:
074: public void setEnabled(boolean b) {
075: this .enabled = b;
076: }
077:
078: public boolean isTreeEnabled() {
079: return this .aSchema.isTreeEnabled() && this .isEnabled();
080: }
081:
082: public DBColumn getColumn(String colName) {
083: return (DBColumn) tmColumns.get(colName);
084: }
085:
086: public String getTableName() {
087: return strTableName;
088: }
089:
090: public String getFQTableName() {
091: String strReturn = null;
092: // Are table names supported in table definitions?
093: if (aSchema.getDBCatalog().getDBMeta()
094: .getSupportsCatalogsInTableDefinitions()) {
095: // Yes, include catalog name in fq table name
096: // Now check, where we have to specify the catalog
097: if (aSchema.getDBCatalog().getDBMeta()
098: .getIsCatalogAtStart()) {
099: // At the beginning
100: strReturn = aSchema.getDBCatalog().getCatalogName()
101: + aSchema.getDBCatalog().getDBMeta()
102: .getCatalogSeparator()
103: + aSchema.getSchemaName() + "."
104: + this .getTableName();
105: } else {
106: // At the end
107: strReturn = aSchema.getSchemaName()
108: + "."
109: + this .getTableName()
110: + aSchema.getDBCatalog().getDBMeta()
111: .getCatalogSeparator()
112: + aSchema.getDBCatalog().getCatalogName();
113: }
114: } else {
115: strReturn = aSchema.getSchemaName() + "."
116: + this .getTableName();
117: }
118: return strReturn;
119: }
120:
121: public String getClassName() {
122: return strClassName;
123: }
124:
125: public void setClassName(String s) {
126: this .strClassName = s;
127: }
128:
129: public String getPackageName() {
130: return strPackageName;
131: }
132:
133: public void setPackageName(String s) {
134: this .strPackageName = s;
135: }
136:
137: public String getFQClassName() {
138: if (this .getPackageName() != null
139: && this .getPackageName().trim().length() > 0)
140: return this .getPackageName() + "." + this .getClassName();
141: else
142: return this .getClassName();
143: }
144:
145: public DBSchema getDBSchema() {
146: return this .aSchema;
147: }
148:
149: public void read() throws SQLException {
150:
151: }
152:
153: public void addColumn(String strColumnName, int iDataType,
154: String strTypeName, int iColumnSize, int iNullable) {
155: DBColumn aDBColumn = new DBColumn(this .dbMeta, this ,
156: strColumnName, iDataType, strTypeName);
157: this .tmColumns.put(strColumnName, aDBColumn);
158: }
159:
160: public void addPrimaryKeyColumn(String strColumnName) {
161: DBColumn aDBColumn = this .getColumn(strColumnName);
162: if (aDBColumn != null) {
163: aDBColumn.setPrimaryKeyPart(true);
164: }
165: }
166:
167: public void generateReferences() throws SQLException {
168: // Check if primary keys for this table have already been set. If not, do it now...
169: // This is necessary because Oracle doesn't return the Primary Keys for all tables
170: // and for Informix it speeds up things significantly if we do it onve for all tables.
171: java.util.Iterator it = this .tmColumns.values().iterator();
172: boolean hasNoPrimaryKey = true;
173: while (hasNoPrimaryKey && it.hasNext())
174: if (((DBColumn) it.next()).isPrimaryKeyPart())
175: hasNoPrimaryKey = false;
176: if (hasNoPrimaryKey)
177: readPrimaryKeys();
178:
179: // Now generate References and Collections
180: generateFKReferences();
181: generateFKCollections();
182: vSubTreeNodes.addAll(this .tmColumns.values());
183: vSubTreeNodes.addAll(this .hmCollections.values());
184: vSubTreeNodes.addAll(this .hmReferences.values());
185: }
186:
187: public java.util.Enumeration children() {
188: return vSubTreeNodes.elements();
189: }
190:
191: public boolean getAllowsChildren() {
192: return true;
193: }
194:
195: public TreeNode getChildAt(int param) {
196: TreeNode tn = (TreeNode) vSubTreeNodes.elementAt(param);
197: return tn;
198: }
199:
200: public int getChildCount() {
201: return this .vSubTreeNodes.size();
202: }
203:
204: public int getIndex(TreeNode treeNode) {
205: return this .vSubTreeNodes.indexOf(treeNode);
206: }
207:
208: public TreeNode getParent() {
209: return this .aSchema;
210: }
211:
212: public boolean isLeaf() {
213: if (this .vSubTreeNodes.size() == 0)
214: return true;
215: else
216: return false;
217: }
218:
219: public String toString() {
220: return this .strTableName;
221: }
222:
223: private void readPrimaryKeys() throws SQLException {
224: // Now get the primary keys for this table. Ignore any exceptions thrown here as
225: // primary keys are not absolutely necessary for reverse engineering
226: java.sql.ResultSet rs = null;
227: try {
228: rs = dbMeta.getPrimaryKeys(null, this .getDBSchema()
229: .getSchemaName(), this .strTableName);
230: while (rs.next()) {
231: String strCatalogName = rs.getString("TABLE_CAT");
232: String strSchemaName = rs.getString("TABLE_SCHEM");
233: if ((strSchemaName == null
234: && this .aSchema.getSchemaName() == null || strSchemaName
235: .equals(this .aSchema.getSchemaName()))
236: && (strCatalogName == null
237: && this .aSchema.getDBCatalog()
238: .getCatalogName() == null || strCatalogName
239: .equals(this .aSchema.getDBCatalog()
240: .getCatalogName()))) {
241: String strColumnName = rs.getString("COLUMN_NAME");
242: String pkName = rs.getString("PK_NAME");
243: DBColumn dbcol = (DBColumn) tmColumns
244: .get(strColumnName);
245: if (dbcol != null)
246: dbcol.setPrimaryKeyPart(true);
247: }
248: }
249: } catch (SQLException sqlEx) {
250: // Ignore excpetions here.
251: } finally {
252: try {
253: rs.close();
254: } catch (Throwable t) {
255: } // Ignore this exception
256: }
257: }
258:
259: private void generateFKReferences() throws SQLException {
260: // References, points from this class to another class using attributes
261: // of this class
262: // Ignore any exceptions thrown here.
263: java.sql.ResultSet rs = null;
264: try {
265: rs = dbMeta.getImportedKeys(this .getDBSchema()
266: .getDBCatalog().getCatalogName(), this
267: .getDBSchema().getSchemaName(), strTableName);
268: while (rs.next()) {
269: String strFKSchemaName = rs.getString("FKTABLE_SCHEM");
270: String strFKCatalogName = rs.getString("FKTABLE_CAT");
271:
272: if ((strFKCatalogName == null
273: && this .aSchema.getDBCatalog().getCatalogName() == null || strFKCatalogName
274: .equals(this .aSchema.getDBCatalog()
275: .getCatalogName()))
276: && (strFKSchemaName == null
277: && this .aSchema.getSchemaName() == null || strFKSchemaName
278: .equals(this .aSchema.getSchemaName()))) {
279: String strPKCatalogName = rs
280: .getString("PKTABLE_CAT");
281: String strPKSchemaName = rs
282: .getString("PKTABLE_SCHEM");
283: String strPKTableName = rs
284: .getString("PKTABLE_NAME");
285: String strPKColumnName = rs
286: .getString("PKCOLUMN_NAME");
287: String strFKTableName = rs
288: .getString("FKTABLE_NAME");
289: String strFKColumnName = rs
290: .getString("FKCOLUMN_NAME");
291:
292: // Resolove the primaryKey column
293: DBCatalog dbPKCatalog = this .aSchema.getDBCatalog()
294: .getDBMeta().getCatalog(strPKCatalogName);
295: if (dbPKCatalog != null) {
296: DBSchema dbPKSchem = dbPKCatalog
297: .getSchema(strPKSchemaName);
298: if (dbPKSchem != null) {
299: DBTable dbPKTable = dbPKSchem
300: .getTable(strPKTableName);
301: if (dbPKTable != null) {
302: DBColumn dbPKColumn = dbPKTable
303: .getColumn(strPKColumnName);
304: // The FK column is always from this table.
305: DBColumn dbFKColumn = getColumn(strFKColumnName);
306:
307: // Now retrieve the FKReference to this table from the collection
308: DBFKRelation aFKRef = (DBFKRelation) this .hmReferences
309: .get(dbPKSchem.getSchemaName()
310: + "."
311: + dbPKTable
312: .getTableName());
313: if (aFKRef == null) {
314: aFKRef = new DBFKRelation(
315: dbPKTable, this , false);
316: this .hmReferences.put(dbPKSchem
317: .getSchemaName()
318: + "."
319: + dbPKTable.getTableName(),
320: aFKRef);
321: }
322: aFKRef.addColumnPair(dbPKColumn,
323: dbFKColumn);
324: }
325: }
326: }
327: }
328: }
329: } catch (SQLException sqlEx) {
330: // sqlEx.printStackTrace();
331: }
332: try {
333: rs.close();
334: } catch (Throwable t) {
335: }
336: }
337:
338: private void generateFKCollections() throws SQLException {
339: // Collections, points from this class to a collection of objects using
340: // attributes from the referenced class
341: // Ignore any exceptions thrown here
342: java.sql.ResultSet rs = null;
343: try {
344: rs = dbMeta.getExportedKeys(this .getDBSchema()
345: .getDBCatalog().getCatalogName(), this
346: .getDBSchema().getSchemaName(), strTableName);
347: while (rs.next()) {
348: String strPKSchemaName = rs.getString("PKTABLE_SCHEM");
349: String strPKCatalogName = rs.getString("PKTABLE_CAT");
350:
351: if ((strPKSchemaName == null
352: && this .aSchema.getSchemaName() == null || strPKSchemaName
353: .equals(this .aSchema.getSchemaName()))
354: && (strPKCatalogName == null
355: && this .aSchema.getDBCatalog()
356: .getCatalogName() == null || strPKCatalogName
357: .equals(this .aSchema.getDBCatalog()
358: .getCatalogName()))) {
359: String strPKTableName = rs
360: .getString("PKTABLE_NAME");
361: String strPKColumnName = rs
362: .getString("PKCOLUMN_NAME");
363: String strFKCatalogName = rs
364: .getString("FKTABLE_CAT");
365: String strFKTableName = rs
366: .getString("FKTABLE_NAME");
367: String strFKColumnName = rs
368: .getString("FKCOLUMN_NAME");
369: String strFKSchemaName = rs
370: .getString("FKTABLE_SCHEM");
371:
372: // Resolve the FK column. If catalog is supported in the index
373: // definition, resolve the catalog of the FK column, otherwise
374: // assume the current catalog (Note: This is needed for Informix,
375: // because the driver reports null for the catalog in this case.
376: DBCatalog dbFKCatalog = null;
377: if (this .aSchema.getDBCatalog().getDBMeta()
378: .getSupportsCatalogsInIndexDefinitions()) {
379: dbFKCatalog = this .aSchema.getDBCatalog()
380: .getDBMeta().getCatalog(
381: strFKCatalogName);
382: } else {
383: dbFKCatalog = this .aSchema.getDBCatalog();
384: }
385: if (dbFKCatalog != null) {
386: DBSchema dbFKSchema = dbFKCatalog
387: .getSchema(strFKSchemaName);
388: if (dbFKSchema != null) {
389: DBTable dbFKTable = dbFKSchema
390: .getTable(strFKTableName);
391: if (dbFKTable != null) {
392: DBColumn dbFKColumn = dbFKTable
393: .getColumn(strFKColumnName);
394: // The PK column is always from this table
395: DBColumn dbPKColumn = getColumn(strPKColumnName);
396: //Retrieve the FK Reference for the FK Table
397: DBFKRelation aFKRef = (DBFKRelation) this .hmCollections
398: .get(dbFKSchema.getSchemaName()
399: + "."
400: + dbFKTable
401: .getTableName());
402: if (aFKRef == null) {
403: aFKRef = new DBFKRelation(this ,
404: dbFKTable, true);
405: this .hmCollections.put(dbFKSchema
406: .getSchemaName()
407: + "."
408: + dbFKTable.getTableName(),
409: aFKRef);
410: }
411: aFKRef.addColumnPair(dbPKColumn,
412: dbFKColumn);
413: }
414: }
415: }
416: }
417: }
418: } catch (SQLException sqlEx) {
419: // sqlEx.printStackTrace();
420: }
421: try {
422: rs.close();
423: } catch (Throwable t) {
424: }
425: }
426:
427: public Class getPropertySheetClass() {
428: return org.apache.ojb.tools.mapping.reversedb.gui.DBTablePropertySheet.class;
429: }
430:
431: public String getXML() {
432: java.io.StringWriter sw = new java.io.StringWriter();
433: writeXML(new java.io.PrintWriter(sw));
434: return sw.getBuffer().toString();
435: }
436:
437: public void writeXML(java.io.PrintWriter pw) {
438: // Only generate a Classdescriptor if this table is enabled
439: if (this .isTreeEnabled()) {
440: java.util.Iterator it = tmColumns.values().iterator();
441: if (it.hasNext()) {
442: // Generate the class descriptor
443: pw.println("<class-descriptor ");
444: pw.println(" class=\"" + this .getFQClassName() + "\"");
445: pw
446: .println(" table=\"" + this .getFQTableName()
447: + "\">");
448: if (this .hasDynamicProxy())
449: pw.println(" <class.proxy>dynamic</class.proxy>");
450: if (this .getConversionStrategyClass() != null
451: && this .getConversionStrategyClass().trim()
452: .length() > 0)
453: pw.println(" <conversionStrategy>"
454: + this .getConversionStrategyClass()
455: + "</conversionStrategy>");
456:
457: it = this .tmColumns.values().iterator();
458:
459: while (it.hasNext()) {
460: ((DBColumn) it.next()).writeXML(pw);
461: }
462:
463: // Generate references
464: it = this .hmReferences.values().iterator();
465: while (it.hasNext()) {
466: ((DBFKRelation) it.next()).writeXML(pw);
467: }
468: // Generate collections
469: it = this .hmCollections.values().iterator();
470: while (it.hasNext()) {
471: ((DBFKRelation) it.next()).writeXML(pw);
472: }
473: pw.println("</class-descriptor>");
474: }
475: }
476: }
477:
478: public void generateJava(File aFile, String strHeader,
479: String strFooter) throws java.io.IOException,
480: java.io.FileNotFoundException {
481: if (this .isTreeEnabled()) {
482: // 1. Generate the package directories
483: String dirName = this .getPackageName().replace('.',
484: File.separatorChar);
485: File packageDir;
486: if (this .getPackageName() != null
487: && this .getPackageName().trim().length() > 0) {
488: packageDir = new File(aFile, dirName);
489: } else {
490: packageDir = aFile;
491: }
492:
493: if (!packageDir.exists())
494: packageDir.mkdirs();
495: File javaFile = new File(packageDir, this .getClassName()
496: + ".java");
497: if (!javaFile.exists())
498: javaFile.createNewFile();
499: java.io.PrintWriter pw = new java.io.PrintWriter(
500: new java.io.FileOutputStream(javaFile));
501: pw.println(strHeader);
502: pw.println("// Generated by OJB SchemeGenerator");
503: pw.println();
504: if (this .getPackageName().trim().length() > 0) {
505: pw.println("package " + this .getPackageName() + ";");
506: pw.println();
507: }
508: pw.println("public class " + this .getClassName());
509: pw.println("{");
510:
511: // Generate Fields
512: java.util.Iterator it = this .tmColumns.values().iterator();
513: while (it.hasNext()) {
514: pw.println(((DBColumn) it.next())
515: .getJavaFieldDefinition());
516: pw.println();
517: }
518:
519: it = this .hmReferences.values().iterator();
520: while (it.hasNext()) {
521: pw.println(((DBFKRelation) it.next())
522: .getJavaFieldDefinition());
523: pw.println();
524: }
525:
526: it = this .hmCollections.values().iterator();
527: while (it.hasNext()) {
528: pw.println(((DBFKRelation) it.next())
529: .getJavaFieldDefinition());
530: pw.println();
531: }
532:
533: // Generate Getter/Setter
534: it = this .tmColumns.values().iterator();
535: while (it.hasNext()) {
536: pw.println(((DBColumn) it.next())
537: .getJavaGetterSetterDefinition());
538: pw.println();
539: }
540:
541: it = this .hmReferences.values().iterator();
542: while (it.hasNext()) {
543: pw.println(((DBFKRelation) it.next())
544: .getJavaGetterSetterDefinition());
545: pw.println();
546: }
547:
548: it = this .hmCollections.values().iterator();
549: while (it.hasNext()) {
550: pw.println(((DBFKRelation) it.next())
551: .getJavaGetterSetterDefinition());
552: pw.println();
553: }
554:
555: pw.println("}");
556: pw.println(strFooter);
557: pw.close();
558: }
559: }
560:
561: public void setPackage(String packageName) {
562: this .setPackageName(packageName);
563: }
564:
565: public void disableClassesWithRegex(org.apache.regexp.RE aRegexp) {
566: if (aRegexp.match(this .getClassName()))
567: this .setEnabled(false);
568: }
569:
570: }
571:
572: /***************************** Changelog *****************************
573: // $Log: DBTable.java,v $
574: // Revision 1.1.2.1 2005/12/21 22:32:04 tomdz
575: // Updated license
576: //
577: // Revision 1.1 2004/05/05 16:39:05 arminw
578: // fix fault
579: // wrong package structure used:
580: // org.apache.ojb.tools.reversdb
581: // org.apache.ojb.tools.reversdb2
582: //
583: // instead of
584: // org.apache.ojb.tools.mapping.reversdb
585: // org.apache.ojb.tools.mapping.reversdb2
586: //
587: // Revision 1.1 2004/05/04 13:45:01 arminw
588: // move reverseDB stuff
589: //
590: // Revision 1.9 2004/04/04 23:53:42 brianm
591: // Fixed initial copyright dates to match cvs repository
592: //
593: // Revision 1.8 2004/03/11 18:16:22 brianm
594: // ASL 2.0
595: //
596: // Revision 1.7 2003/12/12 16:37:16 brj
597: // removed unnecessary casts, semicolons etc.
598: //
599: // Revision 1.6 2003/07/22 11:05:13 florianbruckner
600: // add a name beautifier (courtesy G.Wayne Kidd)
601: //
602: // Revision 1.5 2003/06/21 10:35:03 florianbruckner
603: // implement XML generation with PrintWriter; getXML() still works and uses writeXML(java.io.PrintWriter)
604: // does not generate an Id anymore.
605: //
606: // Revision 1.4 2003/01/28 21:42:53 florianbruckner
607: // update XML generation
608: //
609: // Revision 1.3 2003/01/28 19:59:14 florianbruckner
610: // some updates to schema reading to make it a bit more compatible
611: //
612: // Revision 1.2 2002/06/17 19:34:33 jvanzyl
613: // Correcting all the package references.
614: // PR:
615: // Obtained from:
616: // Submitted by:
617: // Reviewed by:
618: //
619: // Revision 1.1.1.1 2002/06/17 18:16:52 jvanzyl
620: // Initial OJB import
621: //
622: // Revision 1.3 2002/05/16 11:47:09 florianbruckner
623: // fix CR/LF issue, change license to ASL
624: //
625: // Revision 1.2 2002/05/16 10:43:59 florianbruckner
626: // use jakarta-regexp instead of gnu-regexp due to the move to jakarta.
627: //
628: // Revision 1.1 2002/04/18 11:44:16 mpoeschl
629: //
630: // move files to new location
631: //
632: // Revision 1.3 2002/04/07 09:05:16 thma
633: // *** empty log message ***
634: //
635: // Revision 1.2 2002/03/11 17:36:05 florianbruckner
636: // fix line break issue for these files that were previously checked in with -kb
637: //
638: // Revision 1.1 2002/03/04 17:19:32 thma
639: // initial checking for Florians Reverse engineering tool
640: //
641: // Revision 1.2 2002/02/20 13:55:11 Administrator
642: // add semicolon after package name
643: //
644: // Revision 1.1.1.1 2002/02/20 13:35:25 Administrator
645: // initial import
646: //
647: /***************************** Changelog *****************************/
|