package com.idega.data;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
//import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;
import java.util.ArrayList;
/**
* Title: A class to copy the IDO data objects persisted in one datasource to another.
* Description:
* Copyright: Copyright (c) 2001-2002 idega software
* Company: idega software
*@author <a href="mailto:tryggvi@idega.is">Tryggvi Larusson</a>
*@version 1.0
*/
public class IDOCopier {
private GenericEntity fromEntity;
private String toDataSourceName;
private GenericEntity toEntity;
private List entityToCopyList;
private List entityRelationshipInfos = new ArrayList();
//private List copiedEntityClasses=new Vector();
private List copiedEntites = new ArrayList();
private boolean copySameTableOnlyOnce = false;
protected IDOCopier() {
}
private IDOCopier(GenericEntity entity) {
this.fromEntity = entity;
addEntityToCopy(entity);
}
public static IDOCopier getCopierInstance() {
return new IDOCopier();
}
public static IDOCopier getCopierInstance(GenericEntity entity) {
return new IDOCopier(entity);
}
public void setToDatasource(String dataSourceName) {
this.toDataSourceName = dataSourceName;
}
public void addEntityToCopy(GenericEntity entity) {
if (this.fromEntity == null) {
this.fromEntity = entity;
}
getEntityCopyList().add(entity);
}
private List getEntityCopyList() {
if (this.entityToCopyList == null) {
this.entityToCopyList = new Vector();
}
return this.entityToCopyList;
}
public String getToDatasource() {
return this.toDataSourceName;
}
public void copyAllData() {
try {
//toEntity = (GenericEntity)fromEntity.getClass().newInstance();
this.toEntity = this.createEntityInstance(this.fromEntity);
this.toEntity.setDatasource(getToDatasource());
this.toEntity.setToInsertStartData(false);
IDODependencyList dep = IDODependencyList.createDependencyList();
dep.addAllEntityClasses(this.getEntityCopyList());
dep.compile();
List depList = dep.getDependencyListAsClasses();
//List depList = compileDependencyList(com.idega.core.data.ICFile.class);
//List depList = compileDependencyList(com.idega.core.user.data.User.class);
Iterator iter = com.idega.util.ListUtil.reverseList(depList).iterator();
while (iter.hasNext()) {
Class item = (Class) iter.next();
//out.println(item.getName()+"\n<br>");
try {
GenericEntity toInstance = this.createEntityInstance(item);
//GenericEntity toInstance = (GenericEntity)item.newInstance();
toInstance.setDatasource(this.getToDatasource());
toInstance.setToInsertStartData(false);
//GenericEntity fromInstance = (GenericEntity)item.newInstance();
GenericEntity fromInstance = this.createEntityInstance(item);
fromInstance.setDatasource(this.fromEntity.getDatasource());
DatastoreInterface.getInstance(toInstance).createEntityRecord(toInstance);
copyAllData(fromInstance, toInstance, true);
copyManyToManyData(fromInstance, toInstance);
}
catch (java.lang.IllegalAccessException illae) {
//illae.printStackTrace();
}
}
}
catch (Exception e) {
e.printStackTrace();
}
}
private void copyAllData(GenericEntity fromInstance, GenericEntity toInstance, boolean maintainIDs) {
try {
IDOEntityCopyInfo info = getIDOEntityCopyInfo(fromInstance.getClass(), fromInstance.getTableName());
if (!isTableAlreadyCopied(info)) {
System.out.println("[idoCopier] Copying data for " + fromInstance.getClass().getName());
List l = null;
if (fromInstance instanceof com.idega.core.builder.data.ICPage) {
/**
* @todo change - Shitty mix change this as soon as possible!!!
*
*/
List l1 = EntityFinder.findAll((IDOLegacyEntity)fromInstance, "select * from ib_page where template_id is null");
l = new Vector();
l.addAll(l1);
List l2 =
EntityFinder.findAll((IDOLegacyEntity)
fromInstance,
"select * from ib_page where template_id is not null order by template_id asc,ib_page_id asc");
l.addAll(l2);
}
else {
l = EntityFinder.findAll((IDOLegacyEntity)fromInstance);
}
if (l != null) {
int highestID = 1;
Iterator iter = l.iterator();
while (iter.hasNext()) {
GenericEntity tempEntity = (GenericEntity) iter.next();
String originalDatasource = tempEntity.getDatasource();
tempEntity.setDatasource(this.getToDatasource());
if (!maintainIDs) {
/**
* @todo: Implement
*/
}
try {
tempEntity.insert();
}
catch (SQLException e) {
System.err.println(
"Error in inserting "
+ tempEntity.getClass().getName()
+ " for id="
+ tempEntity.getID()
+ " Message: "
+ e.getMessage());
}
try {
if (tempEntity.getID() > highestID) {
highestID = tempEntity.getID();
// DatastoreInterface.getInstance(tempEntity).setSequenceValue(tempEntity,highestID);
}
}
catch (ClassCastException e) {
//e.printStackTrace();
System.err.println("ClassCastException: " + e.getMessage());
}
tempEntity.setDatasource(originalDatasource);
}
updateNumberGeneratorValue(toInstance, highestID);
}
this.addToCopiedEntityList(fromInstance);
}
else {
System.out.println(
"[idoCopier] Skipping copying data for " + fromInstance.getClass().getName() + " as table has already been copied");
}
}
catch (Exception e) {
e.printStackTrace();
}
}
private void copyManyToManyData(GenericEntity fromInstance, GenericEntity toInstance) {
//addToCopiedEntityList(fromInstance);
List infoList = getManyToManyRelatedAndCopied(fromInstance);
Iterator iter = infoList.iterator();
while (iter.hasNext()) {
IDOEntityRelationshipCopyInfo info = (IDOEntityRelationshipCopyInfo) iter.next();
if (!info.copied) {
Connection toConn = null;
Connection fromConn = null;
try {
toConn = this.toEntity.getConnection();
fromConn = this.fromEntity.getConnection();
String fromTableName = getCrossTableName(info.relation,fromConn);
String toTableName = getCrossTableName(info.relation,toConn);
this.copyManyToManyData(fromTableName,toTableName, fromConn, toConn);
info.copied = true;
}
catch (SQLException e) {
e.printStackTrace();
}
finally {
if (toConn != null) {
this.toEntity.freeConnection(toConn);
}
if (fromConn != null) {
this.fromEntity.freeConnection(fromConn);
}
}
}
}
}
/**
* Method getCrosTableName.
* @param entityRelationship
* @param fromConn
* @return String
*/
private String getCrossTableName(EntityRelationship entityRelationship, Connection fromConn) {
/**
* Workaround implementation
* @todo Implement this in a more elegant way
*/
if(IDOCopier.isDatasourceOracle(fromConn)){
/**
* Returns the possibly truncated name of the table
*/
return EntityControl.getCheckedRelatedTableName(entityRelationship.getTableName());
}
else{
/**
* Returns the originally set "longer" set name of the table
*/
return entityRelationship.getSetTableName();
}
}
private IDOEntityCopyInfo addToCopiedEntityList(GenericEntity entity) {
IDOEntityCopyInfo cInfo = getIDOEntityCopyInfo(entity.getClass(), entity.getTableName());
this.copiedEntites.add(cInfo);
//copiedEntityClasses.add(entity.getClass());
List relations = EntityControl.getManyToManyRelationShips(entity);
if (relations != null) {
Iterator iter = relations.iterator();
while (iter.hasNext()) {
boolean areAllReferencedEntitiesCopied = true;
EntityRelationship item = (EntityRelationship) iter.next();
Collection referencedClasses = item.getColumnsAndReferencingClasses().values();
Iterator classIter = referencedClasses.iterator();
while (classIter.hasNext()) {
Class classToCheck = (Class) classIter.next();
IDOEntityCopyInfo cInfoToCheck = getIDOEntityCopyInfo(classToCheck);
if (this.copiedEntites.contains(cInfoToCheck) && areAllReferencedEntitiesCopied) {
//if(copiedEntityClasses.contains(classToCheck)&&areAllReferencedEntitiesCopied){
//areAllReferencedEntitiesCopied still kept true
areAllReferencedEntitiesCopied = true;
}
else {
areAllReferencedEntitiesCopied = false;
}
}
if (areAllReferencedEntitiesCopied) {
IDOEntityRelationshipCopyInfo info = new IDOEntityRelationshipCopyInfo();
info.relation = item;
if (!this.entityRelationshipInfos.contains(info)) {
this.entityRelationshipInfos.add(info);
}
}
}
}
return cInfo;
}
/**
* Returns a List of IDOEntityRelationshipCopyInfo Objects
*/
private List getManyToManyRelatedAndCopied(GenericEntity entity) {
return this.entityRelationshipInfos;
}
private void copyManyToManyData(String fromTableName,String toTableName, Connection fromConnection, Connection toConnection) throws SQLException{
System.out.println("[idoCopier] Copying data from cross-table: " + fromTableName+" to cross-table: " + toTableName);
Statement stmt = null;
PreparedStatement ps = null;
ResultSet RS = null;
try {
stmt = fromConnection.createStatement();
ps = toConnection.prepareStatement("insert into " + toTableName + " values(?,?)");
RS = stmt.executeQuery("select * from " + fromTableName);
//ResultSetMetaData rsm = RS.getMetaData();
//int columnCount = rsm.getColumnCount();
while (RS.next()) {
//try {
int i1 = RS.getInt(1);
int i2 = RS.getInt(2);
ps.setInt(1, i1);
ps.setInt(2, i2);
ps.executeUpdate();
//}
//catch (SQLException e) {
// //e.printStackTrace();
// System.err.println(e.getMessage());
// throw new SQLException();
//}
}
}
//catch (SQLException e) {
// e.printStackTrace();
//}
finally {
if (RS != null) {
try {
RS.close();
}
catch (SQLException e) {
e.printStackTrace();
}
}
if (stmt != null) {
try {
stmt.close();
}
catch (SQLException e) {
e.printStackTrace();
}
}
if (ps != null) {
try {
ps.close();
}
catch (SQLException e) {
e.printStackTrace();
}
}
}
}
protected IDOEntityRelationshipCopyInfo getIDOEntityRelationshipCopyInfoInstance(){
return new IDOEntityRelationshipCopyInfo();
}
protected IDOEntityCopyInfo getIDOEntityCopyInfo(Class entityClass){
GenericEntity entity = this.createEntityInstance(entityClass);
String tableName = entity.getTableName();
return getIDOEntityCopyInfo(entityClass,tableName);
}
protected IDOEntityCopyInfo getIDOEntityCopyInfo(Class entityClass, String tableName){
return new IDOEntityCopyInfo(entityClass,tableName);
}
protected class IDOEntityRelationshipCopyInfo {
EntityRelationship relation;
boolean copied = false;
/*String fromTableName;
String toTableName;
IDOEntityRelationshipCopyInfo(EntityRelationship aRelation,String fromTableName,String toTableName){
relation=aRelation;
this.fromTableName=fromTableName;
this.toTableName=toTableName;
}*/
public boolean equals(Object o) {
if (o != null) {
if (o instanceof IDOEntityRelationshipCopyInfo) {
return ((IDOEntityRelationshipCopyInfo) o).relation.equals(this.relation);
}
}
return false;
}
}
protected class IDOEntityCopyInfo {
protected IDOEntityCopyInfo(Class entityClass, String tableName) {
this.entityClass = entityClass;
this.tableName = tableName;
}
public Class entityClass;
public String tableName;
public boolean equals(Object o) {
if (o != null) {
if (o instanceof IDOEntityCopyInfo) {
return ((IDOEntityCopyInfo) o).tableName.equals(this.tableName);
}
else if (o instanceof Class) {
return ((Class) o).equals(this.entityClass);
}
else if (o instanceof String) {
return ((String) o).equals(this.tableName);
}
}
return false;
}
}
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) {
e.printStackTrace();
}
finally {
if (conn != null) {
entity.freeConnection(conn);
}
}
DatastoreInterface.getInstance(entity).setNumberGeneratorValue(entity, valueToSet);
}
protected GenericEntity createEntityInstance(GenericEntity entity) {
return createEntityInstance(entity.getClass());
}
protected GenericEntity createEntityInstance(Class entityInterfaceOrBeanClass) {
try {
Class interfaceClass = IDOLookup.getInterfaceClassFor(entityInterfaceOrBeanClass);
return (GenericEntity) IDOLookup.getHome(interfaceClass).createIDO();
}
catch (Exception e) {
throw new RuntimeException(
"[idoCopier] : Error creating entity " + entityInterfaceOrBeanClass.getName() + " Message: " + e.getMessage());
}
}
/**
* Gets the name of the table checked with constraints such as maximum length of name.
**/
protected static String getNameOfTableChecked(Connection connForDatasource, EntityRelationship relation) {
String origTableName = relation.getTableName();
if (doesDatasourceLimitTableNamesToThirtyCharacters(connForDatasource)) {
return EntityControl.getTableNameShortenedToThirtyCharacters(origTableName);
}
else {
return origTableName;
}
}
/**
* Checks if the datasource with the given connection connForDatasource is connected to a database that limits character length to 30.
**/
protected static boolean doesDatasourceLimitTableNamesToThirtyCharacters(Connection connForDatasource) {
return isDatasourceOracle(connForDatasource);
}
/**
* Checks if the datasource with the given connection connForDatasource is connected to an Oracle database
**/
protected static boolean isDatasourceOracle(Connection connForDatasource) {
DatastoreInterface di = DatastoreInterface.getInstance(connForDatasource);
if (di instanceof OracleDatastoreInterface) {
return true;
}
return false;
}
protected boolean isTableAlreadyCopied(GenericEntity entity) {
IDOEntityCopyInfo info = getIDOEntityCopyInfo(entity.getClass(), entity.getTableName());
return isTableAlreadyCopied(info);
}
protected boolean isTableAlreadyCopied(IDOEntityCopyInfo cInfo) {
if(this.copySameTableOnlyOnce){
for (Iterator iterator = this.copiedEntites.iterator(); iterator.hasNext();) {
IDOEntityCopyInfo element = (IDOEntityCopyInfo) iterator.next();
if(element.equals(cInfo)){
return true;
}
}
}
return false;
}
public void setToTryCopyingSameTableOnlyOnce(boolean setValue){
this.copySameTableOnlyOnce=setValue;
}
}