/* * $Id: IDOTableCreator.java,v 1.62 2008/11/05 16:39:41 laddi Exp $ * * Copyright (C) 2001-2006 Idega Software hf. All Rights Reserved. * * This software is the proprietary information of Idega hf. Use is subject to * license terms. */ package com.idega.data; import java.io.BufferedInputStream; import java.io.BufferedWriter; import java.io.File; import java.io.FileWriter; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.Collection; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import java.util.Stack; import java.util.Vector; import java.util.logging.Level; import java.util.logging.Logger; import javax.transaction.TransactionManager; import com.idega.idegaweb.IWMainApplication; import com.idega.io.MemoryFileBuffer; import com.idega.io.MemoryInputStream; import com.idega.io.MemoryOutputStream; import com.idega.transaction.IdegaTransactionManager; import com.idega.user.data.GroupBMPBean; import com.idega.util.FileUtil; import com.idega.util.ThreadContext; import com.idega.util.Timer; import com.idega.util.database.ConnectionBroker; import com.idega.util.database.PoolManager; import com.idega.util.logging.LoggingHelper; /** * <p> * Class that handles the creation and generation of the (DDL) commands for creating and * updating database tables for IDO Entity beans. * </p> * Last modified: $Date: 2008/11/05 16:39:41 $ by $Author: laddi $ * * @author <a href="mailto:tryggvil@idega.com">Tryggvi Larusson</a> * @version $Revision: 1.62 $ */ public class IDOTableCreator { private static String recordCreationKey="datastoreinterface_entity_record_creation"; private DatastoreInterface _dsi; private List _entityWithStartData = new Stack(); private boolean useCopyLog = false; private static String sourceDatasource = "sourceDB"; protected IDOTableCreator(DatastoreInterface dsi){ this._dsi=dsi; } protected void executeQuery(GenericEntity entity,String SQLCode)throws Exception{ this._dsi.executeQuery(entity,SQLCode); } protected int executeUpdate(GenericEntity entity,String SQLCode)throws Exception{ return this._dsi.executeUpdate(entity,SQLCode); } /** * Returns a List whichs elements are the Classes that the EntityAutoCreator is still creating */ protected List getCreationList(){ List alreadyInCreation=(List)ThreadContext.getInstance().getAttribute(recordCreationKey); if(alreadyInCreation==null){ alreadyInCreation=new Vector(); ThreadContext.getInstance().setAttribute(recordCreationKey,alreadyInCreation); } return alreadyInCreation; } protected void registerEndOfCreatingEntity(GenericEntity entity){ List alreadyInCreation=(List)ThreadContext.getInstance().getAttribute(recordCreationKey); if(alreadyInCreation!=null){ alreadyInCreation.remove(entity.getClass()); if(alreadyInCreation.isEmpty()){ ThreadContext.getInstance().removeAttribute(recordCreationKey); } } } protected void registerStartOfCreatingEntity(GenericEntity entity){ //Code block to prevent circular recursiveness //i.e. that it infinately recurses through the same entity when it is circularly referenced List alreadyInCreation=this.getCreationList(); if(!hasAlreadyStartedCreatingEntity(entity)){ alreadyInCreation.add(entity.getClass()); // try { // createRefrencedTables(entity); // } catch (Exception e) { // // TODO Auto-generated catch block // e.printStackTrace(); // } } } protected boolean hasAlreadyStartedCreatingEntity(GenericEntity entity){ List alreadyInCreation=this.getCreationList(); return alreadyInCreation.contains(entity.getClass()); } protected boolean startEntityCreationTransaction(GenericEntity entity,boolean isPermittedToCommit){ TransactionManager trans=null; boolean canCommit=isPermittedToCommit; try{ if(this._dsi.useTransactionsInEntityCreation){ trans = com.idega.transaction.IdegaTransactionManager.getInstance(entity.getClass()); if(!((IdegaTransactionManager)trans).hasCurrentThreadBoundTransaction()){ this._dsi.executeBeforeCreateEntityRecord(entity); ((IdegaTransactionManager)trans).setEntity(entity); trans.begin(); canCommit=true; } else{ canCommit=false; } } registerStartOfCreatingEntity(entity); } catch(Exception e){ e.printStackTrace(); } return canCommit; } protected void endEntityCreationTransaction(GenericEntity entity,boolean isPermittedToCommit,boolean transactionSuccessful){ boolean canCommit = isPermittedToCommit; try{ TransactionManager trans = com.idega.transaction.IdegaTransactionManager.getInstance(); if(this._dsi.useTransactionsInEntityCreation){ if(canCommit){ if(transactionSuccessful){ //System.out.println("\t\t\tCommitting!!!!"); trans.commit(); registerEndOfCreatingEntity(entity); } else{ //System.out.println("\t\t\tRollbacking!!!!"); trans.rollback(); registerEndOfCreatingEntity(entity); } ThreadContext.getInstance().removeAttribute(recordCreationKey); this._dsi.executeAfterCreateEntityRecord(entity); //ThreadContext.getInstance().releaseThread(Thread.currentThread()); } else{ if(transactionSuccessful){ //System.out.println("\t\t\tNot permitted to commit!!"); } else{ trans.setRollbackOnly(); //System.out.println("\t\t\tNot permitted to Rollback!!"); } } } } catch(Exception e){ e.printStackTrace(); } } protected boolean doesViewExist(GenericView entityView){ boolean returner =true; String viewName =entityView.getViewName(); Timer timer = new Timer(); timer.start(); try { if(!this._dsi.doesViewExist(entityView.getDatasource(),viewName)) { throw new Exception("View "+viewName+"does not exists"); } } catch (Exception e) { returner =false; } timer.stop(); debug("doesViewExist() check took "+(timer.getTime())+" milliseconds"+" ("+viewName+")"); return returner; } protected boolean doesTableExist(GenericEntity entity,String tableName){ boolean theReturner=true; try{ long start = System.currentTimeMillis(); /** * @todo: Change to doTableCheckDatabaseMetadata() **/ //doTableCheckSelectStar(entity,tableName); doTableCheckDatastoreInterface(entity,tableName); //doTableCheckDatabaseMetadata(entity,tableName); long end = System.currentTimeMillis(); debug("doesTableExist() check took "+((end-start))+" milliseconds"+" ("+tableName+")"); } catch(Exception se){ //String message = se.getMessage(); //if(message.toLowerCase().indexOf("table")!=-1){ theReturner=false; //System.out.println("Table: "+tableName+" does not exist, exception:"+se.getClass().getName()); //} //else{ //se.printStackTrace(); //} } return theReturner; } private void doTableCheckDatastoreInterface(GenericEntity entity,String tableName)throws Exception{ if(!this._dsi.doesTableExist(entity.getDatasource(),tableName)) { throw new Exception("Table "+tableName+"does not exists"); } } /** * Creates an entity record (view) that represents the view entity in the datastore */ public void createEntityView(GenericView entityView){ if(!doesViewExist(entityView)){ boolean canCommit=false; debug("Creating "+entityView.getClass().getName()+" - view: "+entityView.getTableName()); try { canCommit = this.startEntityCreationTransaction(entityView,canCommit); //Create the records of all referenced entities (which this entity has dependent relationships on) if(!this.hasAlreadyStartedCreatingEntity(entityView)){ createRefrencedTables(entityView); } createView(entityView); //commit this.endEntityCreationTransaction(entityView,canCommit,true); } catch (Exception e) { log(e); // rollback this.endEntityCreationTransaction(entityView,canCommit,false); e.printStackTrace(); } } else{ debug("Synchronizing "+entityView.getClass().getName()+" - viewname: "+entityView.getViewName()); } } /** * Creates an entity record (table) that represents the entity in the datastore */ public void createEntityRecord(GenericEntity entity)throws Exception{ // entity = (GenericEntity) com.idega.data.GenericEntity.getStaticInstanceIDO(ICFile.class); if(!doesTableExist(entity,entity.getTableName())){ //if(this.isDebugActive()) debug("Creating "+entity.getClass().getName()+" - tablename: "+entity.getTableName()); boolean canCommit=false; canCommit = this.startEntityCreationTransaction(entity,canCommit); try{ //Create the records of all referenced entities (which this entity has dependent relationships on) if(!this.hasAlreadyStartedCreatingEntity(entity)){ createRefrencedTables(entity); } //Check again if table exists because it could be created through createRefrencedTables(entity) if(!this.doesTableExist(entity,entity.getTableName())){ createTable(entity); createTrigger(entity); try{ createForeignKeys(entity); } catch(Exception e){ e.printStackTrace(); //System.err.println("Exception in creating Foreign Keys for: "+entity.getClass().getName()); //System.err.println(" Error was: "+e.getMessage()); } // CHECKING IF COPYING if (PoolManager.getInstance().hasDatasource(sourceDatasource)) { useCopyLog = true; IDOHome sourceHome = IDOLookup.getHome(entity.getInterfaceClass(), sourceDatasource); // IDOHome localHome = IDOLookup.getHome(entity.getInterfaceClass()); GenericEntity ent = (GenericEntity) com.idega.data.GenericEntity.getStaticInstanceIDO(entity.getInterfaceClass(),sourceDatasource); ent.setDatasource(sourceDatasource, false); System.out.println("Getting data from "+ent.getEntityName()); Class pkClass = ent.getPrimaryKeyClass(); Collection results = null; Collection ids = null; if (IDOPrimaryKey.class.isAssignableFrom(pkClass)) { //for combined primary keys we must fetch one by one, and the order shouldn't matter since no generators exist for them ids = ent.idoFindPKsBySQL("select * from "+ent.getEntityName()); results = sourceHome.getEntityCollectionForPrimaryKeys(ids); } else { //for single primary keys we can fetch in batches! ids = ent.idoFindPKsBySQL("select * from "+ent.getEntityName()+" order by "+ent.getIDColumnName()); Collection pkList = ent.idoFindByPrimaryKeyCollection(ids,_dsi.getOptimalEJBLoadFetchSize()); results = sourceHome.getEntityCollectionForPrimaryKeys(pkList); } // Collection results = sourceHome.getEntityCollectionForPrimaryKeys(ids); // String[] cols = entity.getColumnNames(); // Iterator i = ids.iterator(); Iterator i = results.iterator(); int counter = 0; System.out.print("Starting copy ("+ids.size()+")..."); while (i.hasNext()) { MemoryFileBuffer buffer = null; BufferedInputStream bis = null; MemoryOutputStream bos = null; MemoryInputStream mis = null; try { // Object pk = (Object) i.next(); // GenericEntity sourceEnt = (GenericEntity) sourceHome.findByPrimaryKeyIDO(pk); GenericEntity sourceEnt = (GenericEntity) i.next(); if (sourceEnt.hasLobColumn()) { bis = new BufferedInputStream(sourceEnt.getInputStreamColumnValue(sourceEnt.getLobColumnName())); buffer = new MemoryFileBuffer(); bos = new MemoryOutputStream(buffer); byte[] buff = new byte[10240]; int bytesRead; // Simple read/write loop. while (-1 != (bytesRead = bis.read(buff, 0, buff.length))) { bos.write(buff, 0, bytesRead); } } sourceEnt.setEntityState(IDOLegacyEntity.STATE_NEW_AND_NOT_IN_SYNCH_WITH_DATASTORE); sourceEnt.setDatasource(ConnectionBroker.DEFAULT_POOL, false); if (buffer != null) { mis = new MemoryInputStream(buffer); sourceEnt.setColumn(sourceEnt.getLobColumnName(), mis); } (sourceEnt).store(); } catch (Exception e) { logCopyError(entity, e, "data copying"); // e.printStackTrace(); } finally { if (mis != null) { mis.close(); } if (bos != null) { bos.close(); } if (bis != null) { bis.close(); } } if (counter % 10000 == 0) { if (counter != 0) { System.out.println(":"); System.out.print(counter+" "); } else { System.out.println(); System.out.print(" "); } } else if (counter % 1000 == 0) { System.out.print(":"); } else if (counter % 100 == 0) { System.out.print("."); } ++counter; // GenericEntity targetEnt = (GenericEntity) localHome.createIDO(); // System.out.print("cp : "); // for (int j = 0; j < cols.length; j++) { // targetEnt.setColumn(cols[j], sourceEnt.getColumnValue(cols[j])); // System.out.print(cols[j]+" = "+sourceEnt.getColumnValue(cols[j])+", "); // } // System.out.println(); // targetEnt.store(); } // updateNumberGeneratorValue(entity, (counter+1)); System.out.println(" done : "+counter); } else if(entity.getIfInsertStartData()){ // ELSE NORMAL this._entityWithStartData.add(entity); } try{ createIndexes(entity); } catch(Exception e){ e.printStackTrace(); //this can fail but don't kill the transaction then! } createMiddleTables(entity); } this.endEntityCreationTransaction(entity,canCommit,true); try { //boolean notUseTransactions = !_dsi.useTransactionsInEntityCreation; boolean entitiesInList = !this._entityWithStartData.isEmpty(); if (entitiesInList) { //if (canCommit || notUseTransactions && entitiesInList) { Iterator iter = this._entityWithStartData.iterator(); while (iter.hasNext()) { GenericEntity tmpEnt = (GenericEntity) iter.next(); try{ debug("[IDOTableCreator] : Inserting start data for entity : "+tmpEnt.getEntityName()); tmpEnt.insertStartData(); } catch(Exception e){ e.printStackTrace(); } } this._entityWithStartData = new Stack(); } } catch (Exception e) { System.out.println("==========================================="); System.out.println("============"+e.getMessage()+"============="); if (e.getMessage() == null) { e.printStackTrace(); } System.out.println("==========================================="); } } catch(Exception ex){ //if(this.isDebugActive()){ System.err.println("==="); System.err.println("Exception and rollback for: "+entity.getClass().getName()); System.err.println("\tMessage: "+ex.getMessage()); ex.printStackTrace(); System.err.println("==="); //} //ex.printStackTrace(); /**@todo fix this Tryggvi so that we can use it!**/ this.endEntityCreationTransaction(entity,canCommit,false); //tmp fix //this.endEntityCreationTransaction(entity,canCommit,true); } } else{ debug("Synchronizing "+entity.getClass().getName()+" - tablename: "+entity.getTableName()); boolean canCommit = false; canCommit = this.startEntityCreationTransaction(entity,canCommit); updateColumns(entity); updateIndexes(entity); updateTriggers(entity); createMiddleTables(entity); this.endEntityCreationTransaction(entity,canCommit,true); }//End if(!doesTableExist()) } // private void updateNumberGeneratorValue(GenericEntity entity, int highestValue) { // Connection conn = null; // Statement stmt = null; // ResultSet rs = null; // int valueToSet = highestValue; // try { // conn = entity.getConnection(); // stmt = conn.createStatement(); // rs = stmt.executeQuery("select max(" + entity.getIDColumnName() + ") from " + entity.getTableName()); // rs.next(); // int i = rs.getInt(1); // if (i > valueToSet) { // valueToSet = i; // } // rs.close(); // stmt.close(); // } // catch (SQLException e) { // logCopyError(entity, e, "updating generator"); //// e.printStackTrace(); // } // finally { // if (conn != null) { // entity.freeConnection(conn); // } // } // DatastoreInterface.getInstance(entity).setNumberGeneratorValue(entity, valueToSet); // } protected String getCreationStatement(GenericEntity entity){ if (entity instanceof GroupBMPBean) { System.out.println("GROUP"); } IDOEntityField[] pkFields = entity.getEntityDefinition().getPrimaryKeyDefinition().getFields(); //StringBuffer returnString = new StringBuffer("CREATE TABLE ").append(entity.getTableName()).append("("); String tableName = entity.getEntityDefinition().getSQLTableName(); StringBuffer returnString = new StringBuffer(this._dsi.getCreateTableCommand(tableName)).append("("); String[] names = entity.getColumnNames(); for (int i = 0; i < names.length; i++){ String columnName = names[i]; returnString.append(getColumnSQLDefinition(columnName,entity)); if (i!=names.length-1){ returnString.append(","); } else if (pkFields != null && pkFields.length > 0) { returnString.append(", PRIMARY KEY ("); for (int j = 0; j < pkFields.length; j++) { if (j != 0) { returnString.append(","); } returnString.append(pkFields[j].getSQLFieldName()); } returnString.append(")"); } } returnString.append(")"); //System.out.println(returnString); return returnString.toString(); } public void deleteEntityRecord(GenericEntity entity)throws Exception{ deleteTable(entity); } protected void deleteTable(GenericEntity entity)throws Exception{ Connection conn= null; Statement Stmt= null; try{ conn = entity.getConnection(); Stmt = conn.createStatement(); Stmt.executeUpdate("drop table "+entity.getTableName()); } finally{ if(Stmt != null){ Stmt.close(); } if (conn != null){ entity.freeConnection(conn); } } } protected void createRefrencedTables(GenericEntity entity)throws Exception{ /*String[] names = entity.getColumnNames(); for (int i = 0; i < names.length; i++) { String relationShipClass = entity.getRelationShipClassName(names[i]); if (!relationShipClass.equals("")) { try{ GenericEntity relationShipEntity = (GenericEntity)Class.forName(relationShipClass).newInstance(); createEntityRecord(relationShipEntity); } catch(Exception ex){ ex.printStackTrace(); } } }*/ List list = getRelatedEntityClasses(entity); Iterator iter = list.iterator(); while (iter.hasNext()) { //String className = (String)iter.next(); Class myClass = (Class)iter.next(); //try{ //GenericEntity relationShipEntity = (GenericEntity)Class.forName(className).newInstance(); myClass = IDOLookup.getBeanClassFor(myClass); GenericEntity relationShipEntity = (GenericEntity)myClass.newInstance(); createEntityRecord(relationShipEntity); //} //catch(Exception ex){ // ex.printStackTrace(); //} } } protected void createReferencedViews(GenericView entityView)throws Exception{ java.util.Collection list = entityView.getDependantViewClasses(); Iterator iter = list.iterator(); while (iter.hasNext()) { Class myClass = (Class)iter.next(); GenericView relationShipView = (GenericView)myClass.newInstance(); createEntityView(relationShipView); } } /** * Gets the entities that are related by one-to many and many-to-many relationships * Returns a List of Class Objects */ private List getRelatedEntityClasses(GenericEntity entity){ List returnNames = new Vector(); String[] names = entity.getColumnNames(); for (int i = 0; i < names.length; i++) { Class relationShipClass = entity.getRelationShipClass(names[i]); if ( relationShipClass!=null ) { try{ returnNames.add(relationShipClass); } catch(Exception ex){ ex.printStackTrace(); } } } returnNames.addAll(getManyToManyRelatedEntityClasses(entity)); return returnNames; } /** * Gets the entities that are related by many-to-many relationships * Returns a List of Class Objects */ private List getManyToManyRelatedEntityClasses(GenericEntity entity){ List list = new Vector(); List classList = EntityControl.getManyToManyRelationShipClasses(entity); if(classList!=null){ Iterator iter = classList.iterator(); while (iter.hasNext()) { Class item = (Class)iter.next(); //String className = item.getName(); //list.add(className); list.add(item); } } return list; } protected void createMiddleTables(GenericEntity entity)throws Exception{ //List classList = EntityControl.getManyToManyRelationShipClasses(entity); List relationshipList = EntityControl.getManyToManyRelationShips(entity); /* if(classList==null){ System.out.println("classList==null for "+entity.getClass().getName()); } if(tableList==null){ System.out.println("tableList==null for "+entity.getClass().getName()); }*/ if(relationshipList!=null){ //System.out.println("inside 1 for "+entity.getClass().getName()); //Iterator iter = classList.iterator(); Iterator relIter = relationshipList.iterator(); while (relIter.hasNext()) { //System.out.println("inside 2 for "+entity.getClass().getName()); //Class item = (Class)iter.next(); EntityRelationship relation = (EntityRelationship)relIter.next(); Map relMap = relation.getColumnsAndReferencingClasses(); String tableName = relation.getTableName(); boolean doCreateMiddleTable = !doesTableExist(entity,tableName); if(doCreateMiddleTable){ Set tempSet = relMap.keySet(); Iterator tempIter = tempSet.iterator(); while (tempIter.hasNext() && doCreateMiddleTable) { String column = (String)tempIter.next(); Class relClass = (Class)relMap.get(column); //GenericEntity entity1 = (GenericEntity)relClass.newInstance(); GenericEntity entity1 = (GenericEntity)IDOContainer.getInstance().instanciateBean(relClass); String referencingTableName = entity1.getTableName(); doCreateMiddleTable = doesTableExist(entity,referencingTableName); } } //try{ if(doCreateMiddleTable){ //String creationStatement = "CREATE TABLE "; //creationStatement += tableName; String creationStatement = this._dsi.getCreateTableCommand(tableName); creationStatement += "("; String primaryKeyStatement = this._dsi.getCreatePrimaryKeyStatementBeginning(tableName); Set set; Iterator iter; set = relMap.keySet(); iter = set.iterator(); boolean mayAddComma = false; while (iter.hasNext()) { if(mayAddComma){ creationStatement += ","; primaryKeyStatement += ","; } String column = (String)iter.next(); Class relClass = (Class)relMap.get(column); //GenericEntity entity1 = (GenericEntity)relClass.newInstance(); GenericEntity entity1 = (GenericEntity)IDOContainer.getInstance().instanciateBean(relClass); //creationStatement += column + " INTEGER NOT NULL"; creationStatement += column+this.getPrimaryKeyReferenceForManyToManyRelationship(entity1,column,entity1.getIDColumnName()); primaryKeyStatement +=column; mayAddComma = true; } creationStatement += ")"; primaryKeyStatement +=")"; executeUpdate(entity,creationStatement); executeUpdate(entity,primaryKeyStatement); set = relMap.keySet(); iter = set.iterator(); while (iter.hasNext()) { String column = (String)iter.next(); Class relClass = (Class)relMap.get(column); //try{ GenericEntity entity1 = (GenericEntity)IDOLookup.getBeanClassFor(relClass).newInstance(); //createEntityRecord(entity1); createForeignKey(entity,tableName,column,entity1.getTableName(),entity1.getIDColumnName()); //} //catch(Exception e){ // e.printStackTrace(); //} } if (PoolManager.getInstance().hasDatasource(sourceDatasource)) { // IDOHome sourceHome = IDOLookup.getHome(entity.getInterfaceClass(), sourceDatasource); String[] columnNames = _dsi.getColumnNames(tableName, null); // System.out.println(columnNames); Statement stmtSource = null; ResultSet rsSource = null; Statement stmtNew = null; Connection connSource = null; Connection connNew = null; try { StringBuffer colNameStr = new StringBuffer(); for (int i = 0; i< columnNames.length; i++) { if (i !=0) { colNameStr.append(","); } colNameStr.append(columnNames[i]); } connSource = ConnectionBroker.getConnection(sourceDatasource); connNew = ConnectionBroker.getConnection(); // prepare query String query = "select "+colNameStr.toString()+" from "+tableName; // create a statement stmtSource = connSource.createStatement(); // execute query and return result as a ResultSet rsSource = stmtSource.executeQuery(query); // get the column names from the ResultSet int counter = 0; System.out.println("Starting copy "); while (rsSource.next()) { stmtNew = connNew.createStatement(); StringBuffer b = new StringBuffer(); for (int i = 0; i < columnNames.length; i++) { if (i != 0) { b.append(", "); } Object val = rsSource.getObject(columnNames[i]); b.append(val.toString()); } String sql = "insert into "+tableName+" ("+colNameStr.toString()+") values ("+b.toString()+")"; stmtNew.executeUpdate(sql); stmtNew.close(); if (counter % 10000 == 0) { if (counter != 0) { System.out.println(":"); System.out.print(counter+" "); } else { System.out.println(); System.out.print(" "); } } else if (counter % 1000 == 0) { System.out.print(":"); } else if (counter % 100 == 0) { System.out.print("."); } ++counter; } } catch (Exception e) { e.printStackTrace(); // System.exit(1); } finally { // release database resources try { rsSource.close(); stmtSource.close(); ConnectionBroker.freeConnection(connNew); ConnectionBroker.freeConnection(sourceDatasource, connSource); } catch (SQLException e) { e.printStackTrace(); } } // _dsi.getColumnStringForSelectList(entity, columnName) // IDOHome localHome = IDOLookup.getHome(entity.getInterfaceClass()); // GenericEntity ent = (GenericEntity) com.idega.data.GenericEntity.getStaticInstanceIDO(entity.getInterfaceClass(),sourceDatasource); // ent.setDatasource(sourceDatasource, false); } } /* relatingEntity = (GenericEntity)item.newInstance(); if(!this.doesTableExist(entity,tableName)){ String creationStatement = "CREATE TABLE "+tableName+" ( "+entity.getIDColumnName() + " INTEGER NOT NULL,"+relatingEntity.getIDColumnName() + " INTEGER NOT NULL , PRIMARY KEY("+entity.getIDColumnName() + "," + relatingEntity.getIDColumnName() +") )"; executeUpdate(entity,creationStatement); createForeignKey(entity,tableName,entity.getIDColumnName(),entity.getTableName()); createForeignKey(entity,tableName,relatingEntity.getIDColumnName(),relatingEntity.getTableName()); }*/ //} //catch(Exception ex){ //System.err.println("Failed creating middle-table: "+tableName); //ex.printStackTrace(); //} //} //catch(Exception ex){ // System.err.println("Failed creating middle-table: "+tableName); // ex.printStackTrace(); //} } } } protected void createIndexes(GenericEntity entity) throws Exception { try { HashMap map = entity.getEntityDefinition().getIndexes(); Set keys = map.keySet(); if (keys != null) { Iterator iter = keys.iterator(); String key = null; String[] values = null; while (iter.hasNext()) { try { key = (String) iter.next(); values = (String[]) map.get(key); // createIndex(entity, key, values); _dsi.createIndex(entity, key, values); } catch (Exception e) { logCopyError(entity, e, "index creation"); // e.printStackTrace(); } } } } catch (NoIndexException ignore) {} } protected void createForeignKeys(IDOEntity entity) throws Exception { /*Connection conn = null; Statement Stmt = null; try { conn = entity.getConnection(); conn.commit(); String[] names = entity.getColumnNames(); for (int i = 0; i < names.length; i++) { if (!entity.getRelationShipClassName(names[i]).equals("")) { Stmt = conn.createStatement(); int n = Stmt.executeUpdate("ALTER TABLE " + entity.getTableName() + " ADD FOREIGN KEY (" + names[i] + ") REFERENCES " + ((GenericEntity)Class.forName(entity.getRelationShipClassName(names[i])).newInstance()).getTableName() + " "); if (Stmt != null) { Stmt.close(); } } } } finally { if (Stmt != null) { Stmt.close(); } if (conn != null) { entity.freeConnection(conn); } }*/ //String[] names = entity.getColumnNames(); IDOEntityField[] fields = entity.getEntityDefinition().getFields(); //for (int i = 0; i < names.length; i++) { for (int i = 0; i < fields.length; i++) { //try{ //Class relationShipClass = entity.getRelationShipClass(names[i]); //if (relationShipClass!=null) { if(fields[i].isPartOfManyToOneRelationship()){ //String table1=entity.getTableName(); //Class intefaceClass = IDOLookup.getInterfaceClassFor(relationShipClass); Class intefaceClass = fields[i].getManyToOneRelated().getInterfaceClass(); GenericEntity entityToReference = (GenericEntity)IDOLookup.instanciateEntity(intefaceClass); //GenericEntity entityToReference = (GenericEntity)relationShipClass.newInstance(); //String tableToReference=entityToReference.getTableName(); //if(!doesTableExist(entity,tableToReference)){ // createEntityRecord(entityToReference); //} //String columnInTableToReference=entityToReference.getIDColumnName(); //String columnName = names[i]; String columnName = fields[i].getSQLFieldName(); try{ createForeignKey((GenericEntity)entity,entityToReference,columnName); } catch(Exception e){ logError("Error Creating foreign key for entity "+entity.getEntityDefinition().getSQLTableName()+" and field "+columnName+". Error message was : "+e.getMessage()); } //createForeignKey(entity,table1,columnName,tableToReference,columnInTableToReference); } //} //catch(Exception ex){ // ex.printStackTrace(); //} } } protected void createView(GenericView viewEntity)throws Exception{ executeUpdate(viewEntity,viewEntity.getCreationSQL()); } protected void createTable(GenericEntity entity)throws Exception{ //if(!doesTableExist(entity,entity.getTableName())){ executeUpdate(entity,getCreationStatement(entity)); //} } protected void createTrigger(GenericEntity entity)throws Exception{ this._dsi.createTrigger(entity); } protected void createForeignKey(GenericEntity entity,String columnName)throws Exception{ Class referencingClass = entity.getRelationShipClass(columnName); GenericEntity referencingEntity = (GenericEntity)referencingClass.newInstance(); createForeignKey(entity,referencingEntity,columnName); } protected void createForeignKey(GenericEntity entity,GenericEntity entityToReference,String columnName)throws Exception{ createForeignKey(entity,entity.getEntityDefinition().getSQLTableName(),columnName,entityToReference.getEntityDefinition().getSQLTableName(),entityToReference.getIDColumnName()); } protected void createForeignKey(GenericEntity entity,String baseTableName,String columnName, String refrencingTableName)throws Exception{ createForeignKey(entity,baseTableName,columnName,refrencingTableName,columnName); } /*protected void createForeignKey(GenericEntity entity,String baseTableName,String columnName, String refrencingTableName,String referencingColumnName)throws Exception{ String SQLCommand = "ALTER TABLE " + baseTableName + " ADD CONSTRAINT FOREIGN KEY (" + columnName + ") REFERENCES " + refrencingTableName + "(" + referencingColumnName + ")"; executeUpdate(entity,SQLCommand); }*/ protected void createForeignKey(GenericEntity entity,String baseTableName,String columnName, String refrencingTableName,String referencingColumnName)throws Exception{ //String SQLCommand = "ALTER TABLE " + baseTableName + " ADD CONSTRAINT FOREIGN KEY (" + columnName + ") REFERENCES " + refrencingTableName + "(" + referencingColumnName + ")"; //executeUpdate(entity,SQLCommand); this._dsi.createForeignKey(entity,baseTableName,columnName,refrencingTableName,referencingColumnName); } protected void createPrimaryKey(GenericEntity entity,String baseTableName,String columnName, String refrencingTableName,String referencingColumnName)throws Exception{ //String SQLCommand = "ALTER TABLE " + baseTableName + " ADD CONSTRAINT FOREIGN KEY (" + columnName + ") REFERENCES " + refrencingTableName + "(" + referencingColumnName + ")"; //executeUpdate(entity,SQLCommand); this._dsi.createForeignKey(entity,baseTableName,columnName,refrencingTableName,referencingColumnName); } protected void updateColumns(GenericEntity entity)throws Exception{ String[] columnArrayFromDB = getColumnArrayFromDataBase(entity); String[] columnArrayFromEntity = entity.getColumnNames(); for (int i = 0; i < columnArrayFromEntity.length; i++) { String column = columnArrayFromEntity[i]; if(!hasEntityColumn(column,columnArrayFromDB)){ try{ addColumn(column,entity); if(doesColumnHaveRelationship(column,entity)){ this.createForeignKey(entity,column); } } catch(Exception e){ //e.printStackTrace(); } } else { // Checking size !!! // EntityAttribute att = entity.getAttribute(column); // int size = att.getMaxLength(); // int oldSize = getColumnSize(column, columnArrayFromDB); // if (!att.isUpdated()) { // // TODO add support to more dataTypes // if (size != oldSize && size > 0 && att.getStorageClass() == String.class && oldSize < 4000 && size < 4000) { // att.setUpdated(true); // this._dsi.executeUpdate(entity, "alter table "+entity.getTableName()+" add "+column+"_t varchar("+size+")"); // this._dsi.executeUpdate(entity, "update "+entity.getTableName()+" set "+column+"_t = "+column); // this._dsi.executeUpdate(entity, "alter table "+entity.getTableName()+" drop "+column); // // this._dsi.executeUpdate(entity, "alter table "+entity.getTableName()+" add "+column+" varchar("+size+")"); // this._dsi.executeUpdate(entity, "update "+entity.getTableName()+" set "+column+" = "+column+"_t"); // this._dsi.executeUpdate(entity, "alter table "+entity.getTableName()+" drop "+column+"_t"); // } // } else { // System.out.println("Column is updated = "+column); // } } } } // private int getColumnSize(String colName, ColumnInfo[] columnsToSearch) { // for (int i = 0; i < columnsToSearch.length; i++) { // if (columnsToSearch[i].getColumnName().equalsIgnoreCase(colName)) { // return columnsToSearch[i].getColumnSize(); // } // } // return -1; // } private boolean compareIndexColumns(String[] arr1, String[] arr2) { if (arr1 != null && arr2 != null && arr1.length == arr2.length) { boolean returner = true; for (int i = 0; i < arr1.length && returner; i++) { returner = false; for (int j = 0; j < arr2.length && !returner; j++) { if (arr1[i].equals(arr2[j])) { returner = true; } } if (!returner) { return returner; } } return true; } return false; } private void updateTriggers(GenericEntity entity) { try { this._dsi.updateTriggers(entity, true); } catch (Exception e) { e.printStackTrace(); } } private void updateIndexes(GenericEntity entity) { if (this._dsi.useIndexes()) { HashMap indexesFromDB = this._dsi.getTableIndexes(entity.getDatasource(), entity.getTableName()); try { HashMap map = entity.getEntityDefinition().getIndexes(); Set indexesFromEntity = map.keySet(); Set setFromDB = indexesFromDB.keySet(); // Removing keys from map that exist in DB Iterator dbKeyIter = setFromDB.iterator(); String dbKey; while (dbKeyIter.hasNext()) { dbKey = (String) dbKeyIter.next(); if (map.containsKey(dbKey)) { map.remove(dbKey); } } // Removing columns from map that are already indexed if (indexesFromDB != null && !indexesFromDB.isEmpty()) { try { HashMap tempMap = new HashMap(map); Iterator dbValues = indexesFromDB.values().iterator(); Iterator entityKeys;// = tempMap.keySet().iterator(); String[] columns = null; while (dbValues.hasNext()) { columns = (String[]) dbValues.next(); entityKeys = tempMap.keySet().iterator(); while (entityKeys.hasNext()) { String key = (String) entityKeys.next(); if (compareIndexColumns(columns, (String[]) map.get( key ))) { map.remove(key); } } } } catch (Exception e) { e.printStackTrace(); } } // CREATING Iterator iter = indexesFromEntity.iterator(); String indexName; while (iter.hasNext()) { indexName = (String) iter.next(); try { _dsi.createIndex(entity, indexName, (String[]) map.get(indexName)); // this.createIndex(entity, indexName, (String[]) map.get(indexName)); } catch (Exception e1) { logError("[IDOTableCreator] : failed to create index : "+indexName+" ("+e1.getMessage()+")"); } } // REMOVING - Not active since it tries to removed the PRIMARY_KEY index.... /*iter = indexesFromDB.iterator(); while (iter.hasNext()) { indexName = (String) iter.next(); try { dropIndex(entity, indexName); } catch (Exception e1) { System.out.println("IDOTableCreator : failed to drop index : "+indexName); } }*/ } catch (NoIndexException e) { // REMOVING ALL INDEXES - Not active since it tries to removed the PRIMARY_KEY index.... /* if (indexesFromDB != null) { Iterator iter = indexesFromDB.iterator(); String indexName; while (iter.hasNext()) { indexName = (String) iter.next(); try { dropIndex(entity, indexName); } catch (Exception e1) { System.out.println("IDOTableCreator : failed to drop index : "+indexName); } } }*/ } } } private String[] getColumnArrayFromDataBase(GenericEntity entity){ return this._dsi.getTableColumnNames(entity.getDatasource(),entity.getTableName()); } private boolean hasEntityColumn(String columnName,String[] columnsFromDB){ String currentColumn = null; if(columnsFromDB!=null){ for (int i = 0; i < columnsFromDB.length; i++) { currentColumn = columnsFromDB[i]; if(currentColumn.equalsIgnoreCase(columnName)){ return true; } } } return false; } private void addColumn(String columnName,GenericEntity entity)throws Exception{ //String SQLString = "alter table "+entity.getTableName()+" add "+getColumnSQLDefinition(columnName,entity); String SQLString = this._dsi.getAddColumnCommand(columnName,entity); executeUpdate(entity,SQLString); } protected String getColumnSQLDefinition(String columnName,GenericEntity entity){ return this._dsi.getColumnSQLDefinition(columnName,entity); } private boolean doesColumnHaveRelationship(String columnName,GenericEntity entity){ return (entity.getRelationShipClass(columnName)!=null); } protected String getPrimaryKeyReferenceForManyToManyRelationship(GenericEntity entity,String column,String referencingColumn){ try{ EntityAttribute attr = entity.getAttribute(referencingColumn); Class storageClass = attr.getStorageClass(); int maxLength = attr.getMaxLength(); String sqlType = this._dsi.getSQLType(storageClass,maxLength); return " "+sqlType + " NOT NULL"; } catch(NullPointerException ne){ ne.printStackTrace(); System.err.println("---"); System.err.println("Nullpointer where entity="+entity.getClass().getName()+" and column="+column); System.err.println("---"); return " INTEGER NOT NULL"; } } //STANDARD LOGGING METHODS: /** * Logs out to the default log level (which is by default INFO) * @param msg The message to log out */ protected void log(String msg) { //System.out.println(string); getLogger().log(getDefaultLogLevel(),msg); } /** * Logs out to the error log level (which is by default WARNING) to the default Logger * @param e The Exception to log out */ protected void log(Exception e) { LoggingHelper.logException(e,this,getLogger(),getErrorLogLevel()); } /** * Logs out to the specified log level to the default Logger * @param level The log level * @param msg The message to log out */ protected void log(Level level,String msg) { //System.out.println(msg); getLogger().log(level,msg); } /** * Logs out to the error log level (which is by default WARNING) to the default Logger * @param msg The message to log out */ protected void logError(String msg) { //System.err.println(msg); getLogger().log(getErrorLogLevel(),msg); } /** * Logs out to the debug log level (which is by default FINER) to the default Logger * @param msg The message to log out */ protected void logDebug(String msg) { //System.err.println(msg); getLogger().log(getDebugLogLevel(),msg); } /** * Logs out to the SEVERE log level to the default Logger * @param msg The message to log out */ protected void logSevere(String msg) { //System.err.println(msg); getLogger().log(Level.SEVERE,msg); } /** * Logs out to the WARNING log level to the default Logger * @param msg The message to log out */ protected void logWarning(String msg) { //System.err.println(msg); getLogger().log(Level.WARNING,msg); } /** * Logs out to the CONFIG log level to the default Logger * @param msg The message to log out */ protected void logConfig(String msg) { //System.err.println(msg); getLogger().log(Level.CONFIG,msg); } /** * Logs out to the debug log level to the default Logger * @param msg The message to log out */ protected void debug(String msg) { String logMsg = "[idoTableCreator] : "+msg; logDebug(logMsg); } /** * Gets the default Logger. By default it uses the package and the class name to get the logger.<br> * This behaviour can be overridden in subclasses. * @return the default Logger */ protected Logger getLogger(){ return Logger.getLogger(this.getClass().getName()); } /** * Gets the log level which messages are sent to when no log level is given. * @return the Level */ protected Level getDefaultLogLevel(){ return Level.INFO; } /** * Gets the log level which debug messages are sent to. * @return the Level */ protected Level getDebugLogLevel(){ return Level.FINER; } /** * Gets the log level which error messages are sent to. * @return the Level */ protected Level getErrorLogLevel(){ return Level.WARNING; } //ENTITY SPECIFIC LOG MEHTODS: ///** // * This method outputs the outputString to System.out if the Application property // * "debug" is set to "TRUE" // */ //public void debug(String outputString) { // if (isDebugActive()) { // //System.out.println("[DEBUG] \"" + outputString + "\" : " + this.getEntityName()); // } //} /** * This method logs the sqlCommand if the Log Level is low enough */ public void logSQL(String sqlCommand) { log(Level.FINEST,sqlCommand); //if (isDebugActive()) { //System.out.println("[DEBUG] \"" + outputString + "\" : " + this.getEntityName()); //} } protected boolean isDebugActive() { return getIWMainApplication().getSettings().isDebugActive(); } public IWMainApplication getIWMainApplication(){ return IWMainApplication.getDefaultIWMainApplication(); } //END STANDARD LOGGING METHODS protected void logCopyError(GenericEntity entity, Exception exception, String extraInfo) { try{ if (useCopyLog) { File file = new File(getIWMainApplication().getApplicationRealPath()+"/copyErrorLog.txt"); FileUtil.createFileIfNotExistent(file); FileWriter fstream = new FileWriter(file, true); BufferedWriter out = new BufferedWriter(fstream); StackTraceElement[] elems = exception.getStackTrace(); out.write("=====================================================================================================\n"); out.write(entity.getEntityName() +" ("+entity.getPrimaryKey()+") : "+extraInfo+"\n"); out.write(exception.getMessage() +"\n"); for (int i = 0; i < elems.length && i < 15; i++) { out.write(" "+elems[i] +"\n"); } out.write("=====================================================================================================\n"); out.close(); System.out.println(">>>> COPY ERROR, logged to "+file.getAbsolutePath()); } else { getLogger().log(getErrorLogLevel(), "Error", exception); } }catch (Exception e){//Catch exception if any System.err.println("Error: " + e.getMessage()); } } }