View Javadoc
1 /* 2 * PROJECT : DAR Runtime and Tools 3 * COPYRIGHT : Copyright (C) 1999-2004 tim.stephenson@enableit.org 4 * LICENSE : GNU LESSER GENERAL PUBLIC LICENSE 5 * Version 2.1, February 1999 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation; either version 2 of the License, or 10 * (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 */ 21 22 package org.enableit.db.darrt.ext; 23 24 import java.io.InputStreamReader; 25 import java.util.ArrayList; 26 import java.util.Iterator; 27 import java.util.List; 28 29 import org.apache.log4j.Logger; 30 import org.enableit.db.beans.Column; 31 import org.enableit.db.beans.DarrtDbms; 32 import org.enableit.db.beans.Function; 33 import org.enableit.db.beans.Index; 34 import org.enableit.db.beans.Table; 35 import org.enableit.db.beans.View; 36 import org.enableit.db.darrt.AbstractDDLGenerator; 37 import org.enableit.db.darrt.ConfigurationException; 38 import org.enableit.db.darrt.DDLGenerator; 39 import org.enableit.db.darrt.beans.DiffData; 40 import org.exolab.castor.xml.Unmarshaller; 41 42 /*** 43 * RDBMS-specific extensions backed by XML files. 44 */ 45 public class DeclarativeDDLGenerator 46 extends AbstractDDLGenerator implements DDLGenerator { 47 /*** 48 * The Log4J <code>Logger</code> doing the logging. 49 */ 50 private static Logger logger 51 = Logger.getLogger(DeclarativeDDLGenerator.class); 52 53 /*** 54 * CVS info about this class and its current version 55 */ 56 public static final String ABOUT 57 = "$Revision: 1.7 $"; 58 59 /*** 60 * The config for this instance. 61 */ 62 private DarrtDbms dbms; 63 64 /*** 65 * Name of this generator. 66 */ 67 private String name; 68 69 /*** 70 * Default constructor. 71 */ 72 public DeclarativeDDLGenerator() { 73 super(); 74 } 75 76 /*** 77 * Constructor that also sets the resource to configure with. 78 * 79 * @param resourceName The resource name to read. 80 * @throws ConfigurationException If no meta-data definition available 81 * for the specified resourceName. 82 */ 83 public DeclarativeDDLGenerator(String resourceName) 84 throws ConfigurationException { 85 this(); 86 setResourceName(resourceName); 87 } 88 89 /*** 90 * Sets the resource name to read to instantiate from. 91 * 92 * @param resourceName The resource name to read config'n from. 93 * @throws ConfigurationException If no meta-data definition available 94 * for the specified resourceName. 95 */ 96 public void setResourceName(String resourceName) 97 throws ConfigurationException { 98 logger.fatal("METHOD_ENTRY: setResourceName: " + resourceName); 99 100 this.name = resourceName; 101 102 try { 103 InputStreamReader isr = new InputStreamReader( 104 this.getClass().getResourceAsStream(resourceName + ".xml")); 105 106 dbms = (DarrtDbms) Unmarshaller.unmarshal(DarrtDbms.class, isr); 107 logger.debug("DBMS alter table parentheses setting: " 108 + dbms.hasParenthesesWrappedDdlColumns()); 109 } catch (NullPointerException e) { 110 logger.error(e.getClass().getName() + ":" + e.getMessage(), e); 111 throw new ConfigurationException(e.getMessage(), e); 112 } catch (org.exolab.castor.xml.CastorException e) { 113 logger.error(e.getClass().getName() + ":" + e.getMessage()); 114 throw new ConfigurationException(e.getMessage(), e); 115 } 116 117 logger.info("METHOD_EXIT: setResourceName"); 118 } 119 120 /*** 121 * @return the name of this DDLGenerator. 122 */ 123 public String getName() { 124 return name; 125 } 126 127 /*** 128 * Create a database object that does not currently exist. 129 * 130 * @param dataObject Java representation of the data object to create. 131 * @return <code>List</code> of DDL statements (<code>String</code> type). 132 */ 133 public List getCreate(Object dataObject) { 134 logger.info("METHOD_ENTRY: getCreate"); 135 136 List ddlList = new ArrayList(); 137 StringBuffer ddl = new StringBuffer(); 138 139 if (dataObject instanceof Table) { 140 Table table = (Table) dataObject; 141 List pkCols = new ArrayList() ; 142 List fkCols = new ArrayList() ; 143 144 ddl.append("CREATE TABLE " + table.getName() + "(" + EOL); 145 146 for (int i = 0; i < table.getColumnCount(); i++) { 147 Column col = (Column) table.getColumn(i); 148 149 ddl.append(col.getColName() + " "); 150 ddl.append(getDataType(col.getColType()) + " "); 151 ddl.append(col.getNull().equalsIgnoreCase("false") ? "NOT NULL" 152 : "NULL"); 153 if (col.getDefault() != null) { 154 ddl.append(getDefault(col.getDefault())) ; 155 } 156 157 if ("TRUE".equalsIgnoreCase(col.getPrimaryKey())) { 158 pkCols.add(col) ; 159 } 160 if (col.getForeignKey() != null) { 161 fkCols.add(col) ; 162 } 163 164 if ((i + 1) < table.getColumnCount()) { 165 ddl.append("," + EOL); 166 } else { 167 ddl.append(")" + EOL); 168 } 169 } 170 171 ddlList.add(ddl.toString()); 172 173 // Add alter table for PK constraint 174 if (pkCols.size() > 0) { 175 ddlList.add(getPKConstraint(table.getName(), pkCols)) ; 176 } 177 178 // Add alter table for FK constraints 179 if (fkCols.size() > 0) { 180 for (Iterator it = fkCols.iterator() ; it.hasNext() ;) { 181 ddlList.add(getFKConstraint(table.getName(), (Column) it.next())) ; 182 } 183 } 184 185 // Now get DDL for any indexes 186 for (int i = 0; i < table.getIndexCount(); i++) { 187 ddlList.addAll(getCreate(table.getIndex(i))); 188 } 189 } else if (dataObject instanceof Column) { 190 Column col = (Column) dataObject; 191 String table = col.getTableName(); 192 193 ddl.append("ALTER TABLE " + table + EOL); 194 ddl.append("ADD "); 195 ddl.append(col.getColName() + " "); 196 ddl.append(getDataType(col.getColType()) + " "); 197 ddl.append(col.getNull().equalsIgnoreCase("false") ? "NOT NULL" 198 : "NULL"); 199 ddl.append(EOL); 200 ddlList.add(ddl.toString()); 201 } else if (dataObject instanceof Index) { 202 ddlList.add(getCreateIndex((Index) dataObject)); 203 } else if (dataObject instanceof View) { 204 View view = (View) dataObject; 205 206 if ((view.getDefinition() == null) 207 || (view.getDefinition().trim().length() < 1)) { 208 ddl.append("/* No definition available */"); 209 } else if (!view.getDefinition().toUpperCase().startsWith("CREATE VIEW")) { 210 // Oracle 211 ddl.append("CREATE VIEW " + view.getName() + EOL); 212 ddl.append(" AS "); 213 ddl.append(view.getDefinition()); 214 } else { 215 // Sybase 216 ddl.append(view.getDefinition()); 217 } 218 219 ddlList.add(ddl.toString()); 220 } else { 221 ddl.append("Unsupported database object " 222 + dataObject.getClass().getName()); 223 } 224 225 logger.info("METHOD_EXIT: getCreate, ddl=" + ddlList); 226 227 return ddlList; 228 } 229 230 /*** 231 * @param def The RDBMS-independent default. 232 * @return The RDBMS-specific default. 233 */ 234 private String getDefault(String def) { 235 logger.info("METHOD_ENTRY getDefault, def") ; 236 System.out.println("METHOD_ENTRY getDefault, def") ; 237 StringBuffer sb = new StringBuffer() ; 238 sb.append(" ") ; 239 if ("autoincrement".equals(def)) { 240 sb.append(dbms.getAutoincrement()) ; 241 } else if ("CURRENT TIMESTAMP".equals(def)) { 242 sb.append(dbms.getDefault() + " ") ; 243 sb.append(getCurrentTimestamp()) ; 244 } else { 245 sb.append(dbms.getDefault() + " " + def) ; 246 } 247 System.out.println("METHOD_EXIT getDefault, returning: " + sb) ; 248 logger.info("METHOD_EXIT getDefault, returning: " + sb) ; 249 return sb.toString(); 250 } 251 252 /*** 253 * @param fkCols List of foreign key <code>Columns</code>. 254 * @return Data definition language String. 255 */ 256 private String getFKConstraint(String tableName, Column col) { 257 StringBuffer ddl = new StringBuffer(); 258 ddl.append("ALTER TABLE ") ; 259 ddl.append(tableName) ; 260 ddl.append(" ADD FOREIGN KEY (") ; 261 ddl.append(col.getColName()) ; 262 ddl.append(")") ; 263 ddl.append(" REFERENCES ") ; 264 ddl.append(col.getForeignKey().getFkTableName()) ; 265 ddl.append(" (") ; 266 ddl.append(col.getForeignKey().getDataColumn().getColName()) ; 267 ddl.append(")") ; 268 return ddl.toString(); 269 } 270 271 /*** 272 * @param pkCols List of primary key <code>Columns</code>. 273 * @return Data definition language String. 274 */ 275 private String getPKConstraint(String tableName, List pkCols) { 276 StringBuffer ddl = new StringBuffer(); 277 ddl.append("ALTER TABLE ") ; 278 ddl.append(tableName) ; 279 ddl.append(" ADD ") ; 280 ddl.append(dbms.getPrimaryKey()) ; 281 ddl.append(" (") ; 282 for (Iterator it = pkCols.iterator() ; it.hasNext() ;) { 283 ddl.append(((Column) it.next()).getColName()) ; 284 if (it.hasNext()) { 285 ddl.append(",") ; 286 } 287 } 288 ddl.append(")") ; 289 return ddl.toString(); 290 } 291 292 /*** 293 * @param diff 294 * @return <code>List</code> of DDL statements (<code>String</code> type). 295 */ 296 public List getModify(DiffData diff) { 297 logger.info("METHOD_ENTRY: getModify"); 298 299 List ddlList = new ArrayList(); 300 StringBuffer ddl = new StringBuffer(); 301 Object refObject = diff.getRefObj(); 302 303 if (refObject instanceof Column) { 304 Column rColumn = (Column) refObject; 305 Column tColumn = (Column) diff.getTargetObj(); 306 String table = diff.getName().substring(0, 307 diff.getName().indexOf(".")); 308 309 // Handle column def'n change in one go (supported by most modern dbms) 310 ddl.append("ALTER TABLE " + table + EOL); 311 ddl.append(getModifyColumn(rColumn)); 312 313 ddl.append(EOL); 314 ddlList.add(ddl.toString()); 315 } else if (refObject instanceof Index) { 316 Index index = (Index) refObject; 317 318 ddl.append("DROP INDEX "); 319 ddl.append(index.getTableName()); 320 ddl.append("."); 321 ddl.append(index.getName()); 322 ddlList.add(ddl.toString()); 323 ddlList.add(getCreateIndex(index)); 324 } else { 325 ddl.append("Unsupported database object " 326 + refObject.getClass().getName()); 327 } 328 329 logger.info("METHOD_EXIT: getModify, ddl=" + ddlList); 330 331 return ddlList; 332 } 333 334 private String getModifyColumn(Column rColumn) { 335 StringBuffer ddl = new StringBuffer(dbms.getModifyColumn()) ; 336 ddl.append(" ") ; 337 if (dbms.getParenthesesWrappedDdlColumns()) { 338 ddl.append("("); 339 } 340 341 ddl.append(rColumn.getColName() + " "); 342 ddl.append(getDataType(rColumn.getColType()) + " "); 343 ddl.append(rColumn.getNull().equalsIgnoreCase("false") ? "NOT NULL" 344 : "NULL"); 345 346 if (dbms.getParenthesesWrappedDdlColumns()) { 347 ddl.append(")"); 348 } 349 return ddl.toString(); 350 } 351 352 /*** 353 * Returns this RDBMS' implementation for the JDBC type. 354 */ 355 public String getDataType(String schemaDataType) { 356 logger.info("METHOD_ENTRY: getDataType, schemaDataType=" 357 + schemaDataType); 358 359 String baseType = schemaDataType; 360 if (schemaDataType.indexOf("(") > 0) { 361 baseType = schemaDataType.substring(0, schemaDataType.indexOf("(")) ; 362 logger.debug("BaseType: " + baseType) ; 363 } 364 String returnType = baseType ; 365 for (int i = 0; i < dbms.getJdbcMappingCount(); i++) { 366 if (dbms.getJdbcMapping(i).getJdbc().equals(baseType)) { 367 logger.debug("found rdbms specific type: " + dbms.getJdbcMapping(i).getName()) ; 368 returnType = dbms.getJdbcMapping(i).getName(); 369 370 break; 371 } 372 } 373 if (schemaDataType.indexOf("(") > 0) { 374 returnType += schemaDataType.substring(schemaDataType.indexOf("(")) ; 375 } 376 377 logger.info("METHOD_EXIT: getDataType, returnType=" + returnType); 378 return returnType; 379 } 380 /*** 381 * @see org.enableit.db.darrt.DDLGenerator#getSubstring(java.lang.String, int, int) 382 */ 383 public String getSubstring(String colName, int from, int to) { 384 StringBuffer retVal = new StringBuffer("SUBSTR("); 385 386 retVal.append(colName); 387 retVal.append(","); 388 retVal.append(from); 389 390 if (to > 0) { 391 retVal.append(","); 392 retVal.append(to); 393 } 394 395 retVal.append(")"); 396 397 return retVal.toString(); 398 } 399 400 /*** 401 * @see org.enableit.db.darrt.DDLGenerator#getFormattedDate(java.lang.String, java.lang.String) 402 */ 403 public String getFormattedDate(String colName, String format) { 404 StringBuffer formattedCol = new StringBuffer("DATEFORMAT("); 405 406 formattedCol.append(colName); 407 formattedCol.append(", '"); 408 formattedCol.append(format); 409 formattedCol.append("')"); 410 411 return formattedCol.toString(); 412 } 413 414 private String getCurrentTimestamp() { 415 StringBuffer sFunc = new StringBuffer() ; 416 417 for (int i = 0 ; i < dbms.getFunctionCount() ; i++) { 418 Function func = dbms.getFunction(i) ; 419 if (func.getName().equals("CURRENT TIMESTAMP")) { 420 sFunc.append(func.getPattern()) ; 421 break ; 422 } 423 } 424 return sFunc.toString() ; 425 } 426 427 /*** 428 * @see org.enableit.db.darrt.DDLGenerator#getGenericDefault(java.lang.String) 429 */ 430 public String getGenericDefault(String dbmsDefault) { 431 logger.info("METHOD_ENTRY getGenericDefault") ; 432 StringBuffer sFunc = new StringBuffer() ; 433 boolean found = false ; 434 435 if ("autoincrement".equals(dbmsDefault)) { 436 sFunc.append("autoincrement") ; 437 found = true ; 438 } else { 439 for (int i = 0 ; i < dbms.getFunctionCount() ; i++) { 440 Function func = dbms.getFunction(i) ; 441 logger.fatal("Comparing " + func.getPattern() 442 + " to " + dbmsDefault) ; 443 if (func.getPattern().equals(dbmsDefault)) { 444 logger.fatal("... matched") ; 445 sFunc.append(func.getName()) ; 446 found = true; 447 break ; 448 } 449 } 450 } 451 452 if (!found) { 453 logger.warn("No generic default found for: " + dbmsDefault) ; 454 sFunc.append(dbmsDefault) ; 455 } 456 logger.fatal("METHOD_EXIT getGenericDefault, returning:" + sFunc) ; 457 return sFunc.toString() ; 458 } 459 }

This page was automatically generated by Maven