/*******************************************************************************
 * Copyright (c) 1998, 2013 Oracle, Sei Syvalta. All rights reserved.
 * This program and the accompanying materials are made available under the 
 * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0 
 * which accompanies this distribution. 
 * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
 * and the Eclipse Distribution License is available at 
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * Contributors:
 *     Oracle - initial API and implementation from Oracle TopLink
 *     Sei Syvalta  - Bug 330237 - Tables are created in unspecified order (DDL creation)
 *     01/06/2011-2.3 Guy Pelletier
 *       - 312244: can't map optional one-to-one relationship using @PrimaryKeyJoinColumn
 *     04/05/2011-2.3 Guy Pelletier 
 *       - 337323: Multi-tenant with shared schema support (part 3)
 *     09/09/2011-2.3.1 Guy Pelletier 
 *       - 356197: Add new VPD type to MultitenantType
 *     11/10/2011-2.4 Guy Pelletier 
 *       - 357474: Address primaryKey option from tenant discriminator column
 *     14/05/2012-2.4 Guy Pelletier   
 *       - 376603: Provide for table per tenant support for multitenant applications
 *     31/05/2012-2.4 Guy Pelletier  
 *       - 381196: Multitenant persistence units with a dedicated emf should allow for DDL generation.
 *     12/07/2012-2.5 Guy Pelletier 
 *       - 389090: JPA 2.1 DDL Generation Support (foreign key metadata support)
 *     04/04/2013-2.4.3 Guy Pelletier 
 *       - 388564: Generated DDL does not match annotation
 ******************************************************************************/  
package org.eclipse.persistence.tools.schemaframework;

import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.eis.EISDescriptor;
import org.eclipse.persistence.exceptions.DatabaseException;
import org.eclipse.persistence.exceptions.ValidationException;
import org.eclipse.persistence.internal.databaseaccess.DatabasePlatform;
import org.eclipse.persistence.internal.databaseaccess.FieldTypeDefinition;
import org.eclipse.persistence.internal.descriptors.FieldTransformation;
import org.eclipse.persistence.internal.descriptors.MethodBasedFieldTransformation;
import org.eclipse.persistence.internal.descriptors.TransformerBasedFieldTransformation;
import org.eclipse.persistence.internal.helper.ClassConstants;
import org.eclipse.persistence.internal.helper.ConversionManager;
import org.eclipse.persistence.internal.helper.DatabaseField;
import org.eclipse.persistence.internal.helper.DatabaseTable;
import org.eclipse.persistence.internal.helper.Helper;
import org.eclipse.persistence.internal.queries.ContainerPolicy;
import org.eclipse.persistence.internal.queries.MappedKeyMapContainerPolicy;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.internal.sessions.DatabaseSessionImpl;
import org.eclipse.persistence.logging.AbstractSessionLog;
import org.eclipse.persistence.logging.SessionLog;
import org.eclipse.persistence.mappings.AggregateCollectionMapping;
import org.eclipse.persistence.mappings.AggregateObjectMapping;
import org.eclipse.persistence.mappings.DatabaseMapping;
import org.eclipse.persistence.mappings.DirectCollectionMapping;
import org.eclipse.persistence.mappings.DirectMapMapping;
import org.eclipse.persistence.mappings.ForeignReferenceMapping;
import org.eclipse.persistence.mappings.ManyToManyMapping;
import org.eclipse.persistence.mappings.OneToManyMapping;
import org.eclipse.persistence.mappings.OneToOneMapping;
import org.eclipse.persistence.mappings.RelationTableMechanism;
import org.eclipse.persistence.mappings.TransformationMapping;
import org.eclipse.persistence.mappings.structures.ObjectRelationalDataTypeDescriptor;
import org.eclipse.persistence.oxm.XMLDescriptor;
import org.eclipse.persistence.sequencing.DefaultSequence;
import org.eclipse.persistence.sequencing.NativeSequence;
import org.eclipse.persistence.sequencing.Sequence;
import org.eclipse.persistence.sessions.DatabaseLogin;
import org.eclipse.persistence.sessions.Project;
import org.eclipse.persistence.sessions.Session;
import org.eclipse.persistence.sessions.server.ServerSession;
import org.eclipse.persistence.mappings.DirectToFieldMapping;
import org.eclipse.persistence.mappings.converters.Converter;
import org.eclipse.persistence.mappings.converters.SerializedObjectConverter;
import org.eclipse.persistence.mappings.converters.TypeConversionConverter;

/**
 * DefaultTableGenerator is a utility class used to generate a default table schema for a EclipseLink project object.
 *
 * The utility can be used in EclipseLink CMP for OC4J to perform the table auto creation process, which can be triggered
 * at deployment time when EclipseLink project descriptor is absent (default mapping) or present.
 *
 * The utility can also be used to any EclipseLink application to perform the table drop/creation at runtime.
 *
 * The utility handles all direct/relational mappings, inheritance, multiple tables, interface with/without tables,
 * optimistic version/timestamp lockings, nested relationships, BLOB/CLOB generation.
 *
 * The utility is platform-agnostic.
 *
 * Usage:
 * - CMP
 *  1. set "autocreate-tables=true|false, autodelete-tables=true|false" in oc4j application deployment
 *     descriptor files (config/system-application.xml, config/application.xml, or orion-application.xml in an .ear)
 *
 *  2. Default Mapping: the same as CMP, plus system properties setting -Declipselink.defaultmapping.autocreate-tables='true|false'
 *     and  -Declipselink.defaultmapping.autodelete-tables='true|false'
 *
 * - Non-CMP:
 *  1.  Configuration: through sessions.xml
 *  2.  Directly runtime call through schema framework:
 *      SchemaManager mgr = new SchemaManager(session);
 *      mgr.replaceDefaultTables(); //drop and create
 *		mgr.createDefaultTables(); //create only
 *
 * The utility currently only supports relational project.
 *
 * @author King Wang
 * @since Oracle TopLink 10.1.3
 */
public class DefaultTableGenerator {
    /** The project object used to generate the default data schema. */
    Project project = null;

    /** the target database platform. */
    protected DatabasePlatform databasePlatform;
    
    /**
     * Used to track the table definition: keyed by the table name, and valued 
     * by the table definition object.
     */
    protected Map<String, TableDefinition> tableMap = null;

    /** 
     * Used to track the field definition: keyed by the database field object, and 
     * valued by the field definition.
     */
    protected Map<DatabaseField, FieldDefinition> fieldMap = null;

    /** DatabaseField pool (synchronized with above 'fieldMap') */
    protected Map<DatabaseField, DatabaseField> databaseFields;

    /** When this flag is 'false' EclipseLink will not attempt to create fk constraints. */
    protected boolean generateFKConstraints;

    /**
     * Default constructor
     */
    public DefaultTableGenerator(Project project) {
        this.project = project;
        if (project.getDatasourceLogin().getDatasourcePlatform() instanceof DatabasePlatform){
            this.databasePlatform = (DatabasePlatform)project.getDatasourceLogin().getDatasourcePlatform();
            this.generateFKConstraints = this.databasePlatform.supportsForeignKeyConstraints();
        }
        this.tableMap = new LinkedHashMap();
        this.fieldMap = new LinkedHashMap();
        this.databaseFields = new LinkedHashMap();
    }
    
    /**
     * This constructor will create a DefaultTableGenerator that can be set to create fk
     * constraints
     */
    public DefaultTableGenerator(Project project, boolean generateFKConstraints){
    	this(project);
    	this.generateFKConstraints = generateFKConstraints;
    }

    /**
     * Generate a default TableCreator object from the EclipseLink project object.
     */
    public TableCreator generateDefaultTableCreator() {
        TableCreator tblCreator = new TableCreator();

        //go through each descriptor and build the table/field definitions out of mappings
        for (ClassDescriptor descriptor : this.project.getOrderedDescriptors()) {

            if ((descriptor instanceof XMLDescriptor) || (descriptor instanceof EISDescriptor) || (descriptor instanceof ObjectRelationalDataTypeDescriptor)) {
                //default table generator does not support ox, eis and object-relational descriptor
                AbstractSessionLog.getLog().log(SessionLog.WARNING, SessionLog.DDL, "relational_descriptor_support_only", (Object[])null, true);

                return tblCreator;
            }

            // Aggregate descriptors do not contain table/field data and are 
            // processed through their owning entities. Aggregate descriptors
            // can not exist on their own.
            // Table per tenant descriptors will not be initialized.
            if (!descriptor.isDescriptorTypeAggregate() && ! (descriptor.hasTablePerMultitenantPolicy() && ! project.allowTablePerMultitenantDDLGeneration())) {
                initTableSchema(descriptor);
            }
        }

        //Post init the schema for relation table and direct collection/map tables, and several special mapping handlings.
        for (ClassDescriptor descriptor : this.project.getOrderedDescriptors()) {
            // Aggregate descriptors do not contain table/field data and are 
            // processed through their owning entities. Aggregate descriptors
            // can not exist on their own.
            // Table per tenant descriptors will not be initialized.
            if (!descriptor.isAggregateDescriptor() && !descriptor.isAggregateCollectionDescriptor() && ! (descriptor.hasTablePerMultitenantPolicy() && ! project.allowTablePerMultitenantDDLGeneration())) {
                postInitTableSchema(descriptor);
                
                // If VPD descriptor we need to generate some DDL for its default table.
                if (descriptor.hasMultitenantPolicy()) {
                    descriptor.getMultitenantPolicy().addToTableDefinition(getTableDefFromDBTable(descriptor.getDefaultTable()));
                }
            }
        }

        tblCreator.addTableDefinitions(tableMap.values());

        return tblCreator;
    }

    /**
     * Generate a default TableCreator object from the EclipseLink project object,
     * and perform the table existence check through jdbc table metadata, and filter out
     * tables which are already in the database.
     */
    public TableCreator generateFilteredDefaultTableCreator(AbstractSession session) throws DatabaseException {
        TableCreator tblCreator = generateDefaultTableCreator();

        try {
            //table exisitence check.
            java.sql.Connection conn = null;
            if (session.isServerSession()) {
                //acquire a connection from the pool
                conn = ((ServerSession)session).getDefaultConnectionPool().acquireConnection().getConnection();
            } else if (session.isDatabaseSession()) {
                conn = ((DatabaseSessionImpl)session).getAccessor().getConnection();
            } 
            if (conn == null) {
                //TODO: this is not pretty, connection is not obtained for some reason. 
                return tblCreator;
            }
            DatabaseMetaData dbMetaData = conn.getMetaData();
            ResultSet resultSet = dbMetaData.getTables(null, dbMetaData.getUserName(), null, new String[] { "TABLE" });
            List tablesInDatabase = new ArrayList();

            while (resultSet.next()) {
                //save all tables from the database
                tablesInDatabase.add(resultSet.getString("TABLE_NAME"));
            }

            resultSet.close();

            List existedTables = new ArrayList();
            List existedTableNames = new ArrayList();
            Iterator tblDefIter = tblCreator.getTableDefinitions().iterator();

            while (tblDefIter.hasNext()) {
                TableDefinition tblDef = (TableDefinition) tblDefIter.next();

                //check if the to-be-created table is already in the database
                if (tablesInDatabase.contains(tblDef.getFullName())) {
                    existedTables.add(tblDef);
                    existedTableNames.add(tblDef.getFullName());
                }
            }

            if (!existedTableNames.isEmpty()) {
                session.getSessionLog().log(SessionLog.FINEST, SessionLog.DDL, "skip_create_existing_tables", existedTableNames);

                //remove the existed tables, won't create them.
                tblCreator.getTableDefinitions().removeAll(existedTables);
            }
        } catch (SQLException sqlEx) {
            throw DatabaseException.errorRetrieveDbMetadataThroughJDBCConnection();
        }

        return tblCreator;
    } 

    /**
     * Build tables/fields information into the table creator object from a EclipseLink descriptor.
     * This should handle most of the direct/relational mappings except many-to-many and direct
     * collection/map mappings, which must be down in postInit method.
     */
    protected void initTableSchema(ClassDescriptor descriptor) {
        TableDefinition tableDefintion = null;
        if (descriptor.hasTablePerClassPolicy() && descriptor.isAbstract()) {
            return;
        }

        //create a table definition for each mapped database table
        for (DatabaseTable table : descriptor.getTables()) {
            tableDefintion = getTableDefFromDBTable(table);
        }

        //build each field definition and figure out which table it goes
        for (DatabaseField dbField : descriptor.getFields()) {
            if (dbField.isCreatable()) {
                boolean isPKField = false;
    
                //first check if the field is a pk field in the default table.
                isPKField = descriptor.getPrimaryKeyFields().contains(dbField);
    
                //then check if the field is a pk field in the secondary table(s), this is only applied to the multiple tables case.
                Map secondaryKeyMap = descriptor.getAdditionalTablePrimaryKeyFields().get(dbField.getTable());
    
                if (secondaryKeyMap != null) {
                    isPKField = isPKField || secondaryKeyMap.containsValue(dbField);
                }
                
                // Now check if it is a tenant discriminat column primary key field.
                isPKField = isPKField || dbField.isPrimaryKey();
    
                //build or retrieve the field definition.
                FieldDefinition fieldDef = getFieldDefFromDBField(dbField);            
                if (isPKField) {
                    fieldDef.setIsPrimaryKey(true);
                    // Check if the generation strategy is IDENTITY
                    String sequenceName = descriptor.getSequenceNumberName();
                    DatabaseLogin login = this.project.getLogin();
                    Sequence seq = login.getSequence(sequenceName);
                    if(seq instanceof DefaultSequence) {
                        seq = login.getDefaultSequence();
                    }
                    //The native sequence whose value should be acquired after insert is identity sequence
                    boolean isIdentity = seq instanceof NativeSequence && seq.shouldAcquireValueAfterInsert();
                    fieldDef.setIsIdentity(isIdentity);
                }
    
                //find the table the field belongs to, and add it to the table, only if not already added.
                tableDefintion = this.tableMap.get(dbField.getTableName());
    
                if ((tableDefintion != null) && !tableDefintion.getFields().contains(fieldDef)) {
                    tableDefintion.addField(fieldDef);
                }
            }
        }
    }
    
    /**
     * Build additional table/field definitions for the descriptor, like relation table
     * and direct-collection, direct-map table, as well as reset LOB type for serialized
     * object mapping and type conversion mapping for LOB usage
     */
    protected void postInitTableSchema(ClassDescriptor descriptor) {
        for (DatabaseMapping mapping : descriptor.getMappings()) {
            if (descriptor.isChildDescriptor() && descriptor.getInheritancePolicy().getParentDescriptor().getMappingForAttributeName(mapping.getAttributeName()) != null) {
                // If we are an inheritance subclass, do nothing. That is, don't 
                // generate mappings that will be generated by our parent,
                // otherwise the fields for that mapping will be generated n 
                // times for the same table.
                continue;
            } else if (mapping.isManyToManyMapping()) {
                buildRelationTableDefinition((ManyToManyMapping)mapping, ((ManyToManyMapping)mapping).getRelationTableMechanism(), ((ManyToManyMapping)mapping).getListOrderField(), mapping.getContainerPolicy());
            } else if (mapping.isDirectCollectionMapping()) {
                buildDirectCollectionTableDefinition((DirectCollectionMapping) mapping, descriptor);
            } else if (mapping.isDirectToFieldMapping()) {
                Converter converter = ((DirectToFieldMapping)mapping).getConverter();
                if (converter != null) {
                    if (converter instanceof TypeConversionConverter) {
                        resetFieldTypeForLOB((DirectToFieldMapping)mapping);
                    }
                    
                    if (converter instanceof SerializedObjectConverter) {
                        //serialized object mapping field should be BLOB/IMAGE
                        getFieldDefFromDBField(mapping.getField()).setType(Byte[].class);
                    }
                }
            } else if (mapping.isAggregateCollectionMapping()) {
                //need to figure out the target foreign key field and add it into the aggregate target table
                createAggregateTargetTable((AggregateCollectionMapping) mapping);
            } else if (mapping.isForeignReferenceMapping()) {
                if (mapping.isOneToOneMapping()) {
                    RelationTableMechanism relationTableMechanism = ((OneToOneMapping)mapping).getRelationTableMechanism(); 
                    if(relationTableMechanism == null) {
                        addForeignKeyFieldToSourceTargetTable((OneToOneMapping) mapping);
                    } else {
                        buildRelationTableDefinition((OneToOneMapping)mapping, relationTableMechanism, null, null);
                    }
                } else if (mapping.isOneToManyMapping()) {
                    addForeignKeyFieldToSourceTargetTable((OneToManyMapping) mapping);
                    TableDefinition targTblDef = getTableDefFromDBTable(((OneToManyMapping)mapping).getReferenceDescriptor().getDefaultTable());
                    addFieldsForMappedKeyMapContainerPolicy(mapping.getContainerPolicy(), targTblDef);
                }
            } else if (mapping.isTransformationMapping()) {
                resetTransformedFieldType((TransformationMapping) mapping);
            } else if (mapping.isAggregateObjectMapping()){
                postInitTableSchema(((AggregateObjectMapping)mapping).getReferenceDescriptor());
            }
        }
        
        processAdditionalTablePkFields(descriptor);
    }

    
    /**
     * The ContainerPolicy may contain some additional fields that should be added to the table
     * 
     * @see MappedKeyMapContainerPolicy
     */
    protected void addFieldsForMappedKeyMapContainerPolicy(ContainerPolicy cp, TableDefinition table){
        if (cp.isMappedKeyMapPolicy()){
            List<DatabaseField> keyFields = cp.getIdentityFieldsForMapKey();
            Iterator<DatabaseField> i = keyFields.iterator();
            while (i.hasNext()){
                DatabaseField foreignKey = i.next();
                FieldDefinition fieldDef = getFieldDefFromDBField(foreignKey);
                if (!table.getFields().contains(fieldDef)) {
                    table.addField(fieldDef);
                }
            }
            Map<DatabaseField, DatabaseField> foreignKeys = ((MappedKeyMapContainerPolicy)cp).getForeignKeyFieldsForMapKey();
            if (foreignKeys != null){
                addForeignMappingFkConstraint(foreignKeys, false);
            }
        }
    }
    
    /**
     * Build relation table definitions for all many-to-many relationships in a EclipseLink descriptor.
     */
    protected void buildRelationTableDefinition(ForeignReferenceMapping mapping, RelationTableMechanism relationTableMechanism, DatabaseField listOrderField, ContainerPolicy cp) {
        //first create relation table
        TableDefinition table = getTableDefFromDBTable(relationTableMechanism.getRelationTable());

        //add source foreign key fields into the relation table
        List<DatabaseField> srcFkFields = relationTableMechanism.getSourceRelationKeyFields();
        List<DatabaseField> srcKeyFields = relationTableMechanism.getSourceKeyFields();

        buildRelationTableFields(mapping, table, srcFkFields, srcKeyFields);

        //add target foreign key fields into the relation table
        List<DatabaseField> targFkFields = relationTableMechanism.getTargetRelationKeyFields();
        List<DatabaseField> targKeyFields = relationTableMechanism.getTargetKeyFields();
        
        buildRelationTableFields(mapping, table, targFkFields, targKeyFields);
        
        if (cp != null){
            addFieldsForMappedKeyMapContainerPolicy(cp, table);
        }
        
        if (listOrderField != null) {
            table.addField(getFieldDefFromDBField(listOrderField));
        }
    }

    /**
     * Build field definitions and foreign key constraints for all many-to-many relation table.
     */
    protected void buildRelationTableFields(ForeignReferenceMapping mapping, TableDefinition table, List<DatabaseField> fkFields, List<DatabaseField> targetFields) {
        assert fkFields.size() > 0 && fkFields.size() == targetFields.size();
        
        DatabaseField fkField = null;
        DatabaseField targetField = null;
        List<String> fkFieldNames = new ArrayList();
        List<String> targetFieldNames = new ArrayList();

        for (int index = 0; index < fkFields.size(); index++) {
            fkField = fkFields.get(index);
            targetField = targetFields.get(index);
            fkFieldNames.add(fkField.getNameDelimited(databasePlatform));
            targetFieldNames.add(targetField.getNameDelimited(databasePlatform));
            
            fkField = resolveDatabaseField(fkField, targetField);
            setFieldToRelationTable(fkField, table);
        }
        
        // add a foreign key constraint from fk field to target field
        DatabaseTable targetTable = targetField.getTable();
        TableDefinition targetTblDef = getTableDefFromDBTable(targetTable);

        if (mapping.getDescriptor().hasTablePerClassPolicy()
                && mapping.getDescriptor().getTablePerClassPolicy().hasChild()) {
            return;
        }
        if (mapping.getReferenceDescriptor().hasTablePerClassPolicy()
                && mapping.getReferenceDescriptor().getTablePerClassPolicy().hasChild()) {
            return;
        }
        addForeignKeyConstraint(table, targetTblDef, fkFieldNames, targetFieldNames, mapping.isCascadeOnDeleteSetOnDatabase());
    }

    /**
     * Build direct collection table definitions in a EclipseLink descriptor
     */
    protected void buildDirectCollectionTableDefinition(DirectCollectionMapping mapping, ClassDescriptor descriptor) {
        //first create direct collection table
        TableDefinition table = getTableDefFromDBTable(mapping.getReferenceTable());

        DatabaseField dbField = null;
        DatabaseField targetField = null;
        List<String> fkFieldNames = new ArrayList();
        List<String> targetFieldNames = new ArrayList();
        List<DatabaseField> fkFields = mapping.getReferenceKeyFields();
        List<DatabaseField> targetFields = mapping.getSourceKeyFields();
        for (int index = 0; index < fkFields.size(); index++) {
            DatabaseField fkField = fkFields.get(index);
            targetField = targetFields.get(index);
            fkFieldNames.add(fkField.getNameDelimited(databasePlatform));
            targetFieldNames.add(targetField.getNameDelimited(databasePlatform));
            
            fkField = resolveDatabaseField(fkField, targetField);
            table.addField(getFieldDefFromDBField(fkField));
        }
        
        // add a foreign key constraint from fk field to target field
        DatabaseTable targetTable = targetField.getTable();
        TableDefinition targetTblDef = getTableDefFromDBTable(targetTable);

        //add the direct collection field to the table.
        table.addField(getFieldDefFromDBField(mapping.getDirectField()));

        //if the mapping is direct-map field, add the direct key field to the table as well.
        // TODO: avoid generating DDL for map key mappings for the time being.
        // Bug: 270814
        if (mapping.isDirectMapMapping() && ! mapping.getContainerPolicy().isMappedKeyMapPolicy() ) {
            dbField = ((DirectMapMapping) mapping).getDirectKeyField();
            table.addField(getFieldDefFromDBField(dbField));
        } else {
            addFieldsForMappedKeyMapContainerPolicy(mapping.getContainerPolicy(), table);
            
            if (mapping.getListOrderField() != null) {
                table.addField(getFieldDefFromDBField(mapping.getListOrderField()));
            }
        }
        if (mapping.getDescriptor().hasTablePerClassPolicy()
                && mapping.getDescriptor().getTablePerClassPolicy().hasChild()) {
            return;
        }
        addForeignKeyConstraint(table, targetTblDef, fkFieldNames, targetFieldNames, mapping.isCascadeOnDeleteSetOnDatabase());
    }

    /**
     * Reset field type to use BLOB/CLOB with type conversion mapping fix for 4k oracle thin driver bug.
     */
    protected void resetFieldTypeForLOB(DirectToFieldMapping mapping) {
        if (mapping.getFieldClassification().getName().equals("java.sql.Blob")) {
            //allow the platform to figure out what database field type gonna be used. 
            //For example, Oracle9 will generate BLOB type, SQL Server generats IMAGE.
            getFieldDefFromDBField(mapping.getField()).setType(Byte[].class);
        } else if (mapping.getFieldClassification().getName().equals("java.sql.Clob")) {
            //allow the platform to figure out what database field type gonna be used. 
            //For example, Oracle9 will generate CLOB type. SQL Server generats TEXT.
            getFieldDefFromDBField(mapping.getField()).setType(Character[].class);
        }
    }

    /**
     * Reset the transformation mapping field types
     */
    protected void resetTransformedFieldType(TransformationMapping mapping) {
        Iterator transIter = mapping.getFieldTransformations().iterator();
        while (transIter.hasNext()) {
            FieldTransformation transformation = (FieldTransformation) transIter.next();
            
            if (transformation instanceof MethodBasedFieldTransformation) {
                MethodBasedFieldTransformation methodTransformation = (MethodBasedFieldTransformation) transformation; 
                try {
                    Class returnType = Helper.getDeclaredMethod(mapping.getDescriptor().getJavaClass(), methodTransformation.getMethodName(), null).getReturnType();
                    getFieldDefFromDBField(methodTransformation.getField()).setType(returnType);
                } catch (NoSuchMethodException ex) {
                    // For some reason, the method type could not be retrieved, 
                    // use the default java.lang.String type
                }
            } else {
                // Must be a TransformerBasedFieldTransformation
                TransformerBasedFieldTransformation classTransformation = (TransformerBasedFieldTransformation) transformation;
                String methodName = "buildFieldValue";
                Class[] params = new Class[] {Object.class, String.class, Session.class};
                
                try {
                    Class returnType = Helper.getDeclaredMethod(classTransformation.getTransformerClass(), methodName, params).getReturnType();
                    
                    if (returnType.equals(Object.class)) {
                        // User needs to be more specific with their class
                        // transformer return type if they are using DDL. Throw
                        // an exception.
                        throw ValidationException.missingFieldTypeForDDLGenerationOfClassTransformation(mapping.getDescriptor(), mapping.getAttributeName(), methodName);
                    }
                    
                    getFieldDefFromDBField(classTransformation.getField()).setType(returnType);
                } catch (NoSuchMethodException ex) {
                    // For some reason, the method type could not be retrieved.
                    // Did the interface method change? Throw an exception. 
                    throw ValidationException.missingTransformerMethodForDDLGenerationOfClassTransformation(mapping.getDescriptor(), mapping.getAttributeName(), methodName);
                }
            }
        }
    }

    /**
     * Add the foreign key to the aggregate collection mapping target table.
     * Also add listOrderField if specified.
     */
    protected void createAggregateTargetTable(AggregateCollectionMapping mapping) {
        TableDefinition targetTable = getTableDefFromDBTable(mapping.getReferenceDescriptor().getDefaultTable());
        addFieldsForMappedKeyMapContainerPolicy(mapping.getContainerPolicy(), targetTable);

        Iterator aggregateFieldIterator = mapping.getReferenceDescriptor().getFields().iterator();
        while (aggregateFieldIterator.hasNext()) {
            DatabaseField dbField = (DatabaseField) aggregateFieldIterator.next();
            //add the target definition to the table definition
            targetTable.addField(getFieldDefFromDBField(dbField));
        }
        
        //unlike normal one-to-many mapping, aggregate collection mapping does not have 1:1 back reference
        //mapping, so the target foreign key fields are not stored in the target descriptor.
        List<String> fkFieldNames = new ArrayList();
        List<String> targetFieldNames = new ArrayList();
        List<DatabaseField> fkFields = mapping.getTargetForeignKeyFields();
        List<DatabaseField> targetFields = mapping.getSourceKeyFields();
        DatabaseField targetField = null;
        for (int index = 0; index < fkFields.size(); index++) {
            DatabaseField fkField = fkFields.get(index);
            targetField = targetFields.get(index);
            fkFieldNames.add(fkField.getNameDelimited(databasePlatform));
            targetFieldNames.add(targetField.getNameDelimited(databasePlatform));
            
            fkField = resolveDatabaseField(fkField, targetField);
            targetTable.addField(getFieldDefFromDBField(fkField));
        }
        
        // add a foreign key constraint from fk field to target field
        DatabaseTable sourceDatabaseTable = targetField.getTable();
        TableDefinition sourceTable = getTableDefFromDBTable(sourceDatabaseTable);
        
        if (mapping.getListOrderField() != null) {
            getTableDefFromDBTable(mapping.getListOrderField().getTable()).addField(getFieldDefFromDBField(mapping.getListOrderField()));
        }
        if (mapping.getDescriptor().hasTablePerClassPolicy()
                && mapping.getDescriptor().getTablePerClassPolicy().hasChild()) {
            return;
        }
        addForeignKeyConstraint(targetTable, sourceTable, fkFieldNames, targetFieldNames, mapping.isCascadeOnDeleteSetOnDatabase());
    }

    protected void addForeignKeyFieldToSourceTargetTable(OneToOneMapping mapping) {        
        if (!mapping.isForeignKeyRelationship()
                || (mapping.getReferenceDescriptor().hasTablePerClassPolicy()
                        && mapping.getReferenceDescriptor().getTablePerClassPolicy().hasChild())) {
            return;
        }
        boolean cascadeDelete = false;
        // Find mappedBy target mapping to check constraint cascade.
        for (DatabaseField foreignKey : mapping.getSourceToTargetKeyFields().values()) {
            DatabaseMapping mappedBy = mapping.getReferenceDescriptor().getObjectBuilder().getMappingForField(foreignKey);
            if (mappedBy != null && mappedBy.isOneToOneMapping()) {
                cascadeDelete = ((OneToOneMapping)mappedBy).isCascadeOnDeleteSetOnDatabase();
            } else {
                List<DatabaseMapping> readOnlyMappings = mapping.getReferenceDescriptor().getObjectBuilder().getReadOnlyMappingsForField(foreignKey);
                if (readOnlyMappings != null) {
                    for (DatabaseMapping mappedByPK : readOnlyMappings) {
                        if (mappedByPK.isOneToOneMapping()) {
                            cascadeDelete = ((OneToOneMapping)mappedByPK).isCascadeOnDeleteSetOnDatabase();
                            if (cascadeDelete) {
                                break;
                            }
                        }
                    }
                }
            }
            if (cascadeDelete) {
                break;
            }
        }

        // If the mapping is optional and uses primary key join columns, don't 
        // generate foreign key constraints which would require the target to 
        // always be set.
        if (! mapping.isOptional() || ! mapping.isOneToOnePrimaryKeyRelationship()) {
            addForeignMappingFkConstraint(mapping.getSourceToTargetKeyFields(), cascadeDelete);
        }
    }
    
    protected void addForeignKeyFieldToSourceTargetTable(OneToManyMapping mapping) {
        if (mapping.getDescriptor().hasTablePerClassPolicy()
                && mapping.getDescriptor().getTablePerClassPolicy().hasChild()) {
            return;
        }
        addForeignMappingFkConstraint(mapping.getTargetForeignKeysToSourceKeys(), mapping.isCascadeOnDeleteSetOnDatabase());
        if(mapping.getListOrderField() != null) {
            getTableDefFromDBTable(mapping.getListOrderField().getTable()).addField(getFieldDefFromDBField(mapping.getListOrderField()));
        }
    }    

    protected void addForeignMappingFkConstraint(final Map<DatabaseField, DatabaseField> srcFields, boolean cascadeOnDelete) {
        // srcFields map from the foreign key field to the target key field

        if(srcFields.size() == 0) {
            return;
        }

        List<DatabaseField> fkFields = new ArrayList<DatabaseField>();
        List<DatabaseField> targetFields = new ArrayList<DatabaseField>();
        
        for (DatabaseField fkField : srcFields.keySet()) {
            fkFields.add(fkField);
            targetFields.add(srcFields.get(fkField));
        }
        addJoinColumnsFkConstraint(fkFields, targetFields, cascadeOnDelete);
    }

    /**
     * Build a table definition object from a database table object
     */
    protected TableDefinition getTableDefFromDBTable(DatabaseTable databaseTable) {
        TableDefinition tableDefinition = this.tableMap.get(databaseTable.getName());

        if (tableDefinition == null) {
            //table not built yet, simply built it
            tableDefinition = new TableDefinition();
            tableDefinition.setTable(databaseTable);
            tableDefinition.setName(databaseTable.getNameDelimited(databasePlatform));
            tableDefinition.setQualifier(databaseTable.getTableQualifier());
            if (databaseTable.hasUniqueConstraints()) {
                addUniqueKeyConstraints(tableDefinition, databaseTable.getUniqueConstraints());
            }
            if (databaseTable.hasIndexes()) {
                tableDefinition.getIndexes().addAll(databaseTable.getIndexes());
            }
            if (databaseTable.getCreationSuffix() !=null){
                tableDefinition.setCreationSuffix(databaseTable.getCreationSuffix());
            }
            
            // Add the foreign key constraints that were set on the table.
            if (databaseTable.hasForeignKeyConstraints()) {
                tableDefinition.setUserDefinedForeignKeyConstraints(databaseTable.getForeignKeyConstraints());
            }
            
            tableMap.put(databaseTable.getName(), tableDefinition);
        }

        return tableDefinition;
    }

    /**
     * Resolve the foreign key database field metadata in relation table or direct collection/map table.
     * Those metadata includes type, and maybe dbtype/size/subsize if DatabaseField carries those info.
     */
    protected DatabaseField resolveDatabaseField(DatabaseField childField, DatabaseField parentField) {
        //set through the type from the source table key field to the relation or direct collection table key field.        
        DatabaseField resolvedDatabaseField = new DatabaseField();
        // find original field in the parent table, which contains actual type definitions
        // if 'resolvedParentField' is null, there is no corresponding field definition (typo?)
        DatabaseField resolvedParentField = databaseFields.get(parentField);
        
        resolvedDatabaseField.setName(childField.getName());
        //Table should be set, otherwise other same name field will be used wrongly because equals() is true.
        //Fix for GF#1392 the same name column for the entity and many-to-many table cause wrong pk constraint.
        resolvedDatabaseField.setTable(childField.getTable());
        
        // type definitions from parent field definition
        if(resolvedParentField != null) {
            resolvedDatabaseField.setType(resolvedParentField.getType());
            resolvedDatabaseField.setScale(resolvedParentField.getScale());
            resolvedDatabaseField.setLength(resolvedParentField.getLength());
            resolvedDatabaseField.setPrecision(resolvedParentField.getPrecision());
        }

        // these are defined in childField definition(see @JoinColumn)
        resolvedDatabaseField.setUnique(childField.isUnique());
        resolvedDatabaseField.setNullable(childField.isNullable());
        resolvedDatabaseField.setUpdatable(childField.isUpdatable());
        resolvedDatabaseField.setInsertable(childField.isInsertable());
        resolvedDatabaseField.setUseDelimiters(childField.shouldUseDelimiters());
        resolvedDatabaseField.useUpperCaseForComparisons(childField.getUseUpperCaseForComparisons());
        resolvedDatabaseField.setNameForComparisons(childField.getNameForComparisons());
        
        String columnDef = childField.getColumnDefinition();
        if(columnDef == null || columnDef.trim().equals("")) {
            // if childField has no column definition, follow the definition of the parent field
            if(resolvedParentField != null) {
                resolvedDatabaseField.setColumnDefinition(resolvedParentField.getColumnDefinition());
            }
        } else {
            resolvedDatabaseField.setColumnDefinition(columnDef);
        }
        
        return resolvedDatabaseField;
    }

    /**
     * Build a field definition object from a database field.
     */
    protected FieldDefinition getFieldDefFromDBField(DatabaseField dbField) {
        FieldDefinition fieldDef = this.fieldMap.get(dbField);

        if (fieldDef == null) {
            //not built yet, build one
            fieldDef = new FieldDefinition();
            fieldDef.setName(dbField.getNameDelimited(databasePlatform));
            //added for extending tables where the field needs to be looked up
            fieldDef.setDatabaseField(dbField);

            if (dbField.getColumnDefinition() != null && dbField.getColumnDefinition().length() > 0) {
                // This column definition would include the complete definition of the  
                // column like type, size,  "NULL/NOT NULL" clause, unique key clause 
                fieldDef.setTypeDefinition(dbField.getColumnDefinition());
            } else {
                Class fieldType = dbField.getType();
                FieldTypeDefinition fieldTypeDef = (fieldType == null) ? null : databasePlatform.getFieldTypeDefinition(fieldType);
                
                // Check if the user field is a String and only then allow the length specified
                // in the @Column annotation to be set on the field.
                if (fieldType != null) {
                    // If a length has been specified, set it, otherwise let the
                    // field def from individual platforms handle it.
                    if (dbField.getLength() > 0) {
                        fieldDef.setSize(dbField.getLength());
                    } else if (dbField.getPrecision() > 0) {
                        fieldDef.setSize(dbField.getPrecision()); 
                        fieldDef.setSubSize(dbField.getScale());
                    }
                }

                if ((fieldType == null) || (!fieldType.isPrimitive() && (fieldTypeDef  == null))) {
                    //TODO: log a warning for inaccessible type or not convertable type.
                    AbstractSessionLog.getLog().log(SessionLog.CONFIG, SessionLog.METADATA, "field_type_set_to_java_lang_string", dbField.getQualifiedName(), fieldType);

                    //set the default type (lang.String) to all un-resolved java type, like null, Number, util.Date, NChar/NType, Calendar
                    //sql.Blob/Clob, Object, or unknown type). Please refer to bug 4352820.
                    fieldDef.setType(ClassConstants.STRING);
                } else {
                    //need to convert the primitive type if applied.
                    fieldDef.setType(ConversionManager.getObjectClass(fieldType));
                }

                fieldDef.setShouldAllowNull(dbField.isNullable());             
                fieldDef.setUnique(dbField.isUnique());     
            }
            this.fieldMap.put(dbField, fieldDef);
            this.databaseFields.put(dbField, dbField);
        }

        return fieldDef;
    }

    /**
     * Build and add a field definition object to relation table
     */
    protected void setFieldToRelationTable(DatabaseField dbField, TableDefinition table) {
        FieldDefinition fieldDef = getFieldDefFromDBField(dbField);

        if (!table.getFields().contains(fieldDef)) {
            //only add the field once, to avoid add twice if m:m is bi-directional.
            table.addField(getFieldDefFromDBField(dbField));
            fieldDef.setIsPrimaryKey(true); // make this a PK as we will be creating constrains later
        }
    }

    protected void processAdditionalTablePkFields(ClassDescriptor descriptor) {
        // only if there are additional tables
        if (!descriptor.hasMultipleTables()) {
            return;
        }
        
        DatabaseTable databaseTable = null;
        Iterator dbTblIter = descriptor.getTables().iterator();
        while (dbTblIter.hasNext()) {
            databaseTable = (DatabaseTable) dbTblIter.next();
            Map<DatabaseField, DatabaseField> srcFields = descriptor.getAdditionalTablePrimaryKeyFields().get(databaseTable);
            if ((null != srcFields) && srcFields.size() > 0) {
                // srcFields is from the secondary field to the primary key field
                // Let's make fk constraint from the secondary field to the primary key field
                List<DatabaseField> fkFields = new ArrayList<DatabaseField>();
                List<DatabaseField> pkFields = new ArrayList<DatabaseField>();
        
                for (DatabaseField pkField : srcFields.keySet()) {
                    pkFields.add(pkField);
                    fkFields.add(srcFields.get(pkField));
                }
                addJoinColumnsFkConstraint(fkFields, pkFields, descriptor.isCascadeOnDeleteSetOnDatabaseOnSecondaryTables());
            }
        }              
    }    
   
    protected void addJoinColumnsFkConstraint(List<DatabaseField> fkFields, List<DatabaseField> targetFields, boolean cascadeOnDelete) {
        assert fkFields.size() == targetFields.size();
        
        if (fkFields.size() == 0) {
            return;
        }
        
        DatabaseField fkField = null;
        DatabaseField targetField = null;
        List<String> fkFieldNames = new ArrayList();
        List<String> targetFieldNames = new ArrayList();
        
        DatabaseTable sourceTable = fkFields.get(0).getTable();
        TableDefinition sourceTableDef = getTableDefFromDBTable(sourceTable);
        
        for (int i=0; i < fkFields.size(); i++) {            
            fkField = fkFields.get(i);
            targetField = targetFields.get(i);
            fkFieldNames.add(fkField.getNameDelimited(this.databasePlatform));
            targetFieldNames.add(targetField.getNameDelimited(this.databasePlatform));

            FieldDefinition fkFieldDef = fieldMap.get(fkField);
            FieldDefinition targetFieldDef = fieldMap.get(targetField);
            
            if (targetFieldDef != null) {
                // UnidirectionalOneToOneMapping case
                if (fkFieldDef == null) {
                    fkFieldDef = getFieldDefFromDBField(fkField);
                    if (!sourceTableDef.getFields().contains(fkFieldDef)) {
                        sourceTableDef.addField(fkFieldDef);
                    }
                }
                
                // Set the fkFieldDef type definition to the that of the target if one is not set.
                if (fkFieldDef.getTypeDefinition() == null || fkFieldDef.getTypeDefinition().trim().equals("")) {
                    fkFieldDef.setTypeDefinition(targetFieldDef.getTypeDefinition());
                }
                
                // Also ensure that the type, size and subsize of the foreign key field is 
                // same as that of the original field.
                fkFieldDef.setType(targetFieldDef.getType());
                fkFieldDef.setSize(targetFieldDef.getSize()); 
                fkFieldDef.setSubSize(targetFieldDef.getSubSize());
            }
        }

        // add a foreign key constraint
        DatabaseTable targetTable = targetField.getTable();
        TableDefinition targetTableDef = getTableDefFromDBTable(targetTable);
        
        addForeignKeyConstraint(sourceTableDef, targetTableDef, fkFieldNames, targetFieldNames, cascadeOnDelete);
    }

    /**
     * Add a foreign key constraint to the source table.
     */
    protected void addForeignKeyConstraint(TableDefinition sourceTableDef, TableDefinition targetTableDef, 
        List<String> fkFields, List<String> targetFields, boolean cascadeOnDelete) {

        // Only generate FK constraints if instructed to
        if (! this.generateFKConstraints){
            return;
        }
        assert fkFields.size() > 0 && fkFields.size() == targetFields.size();
        
        // target keys could be primary keys or candidate(unique) keys of the target table

        List<String> fkFieldNames = fkFields;
        List<String> targetFieldNames = targetFields;
        
        if (fkFields.size() > 1) {
            // if composite key, we should consider the order of keys.
            // Foreign Key constraint should follow the primary/unique key order of the target table.
            // e.g. if the primary key constraint of the target table is (p2, p1),
            // foreign key constraint should be "(f2, f1) REFERENCES TARGET (p2, p1)".

            // we try to reorder keys using primary keys or unique keys order of the target table,
            // but if we might not resolve it due to incorrect field name, then let it as it is.
            // This will trigger underlying database exception so users can recognize errors.
            
            boolean resolved = false;
            boolean error = false;
            
            Map<String, String> targetToFkField = new LinkedHashMap<String, String>();
            for (int index = 0; index < fkFields.size(); index++) {
                String targetField = targetFields.get(index);
                if (targetToFkField.containsKey(targetField)) {
                    //target key column appears more than once
                    error = true;
                    break;
                }
                targetToFkField.put(targetField, fkFields.get(index));
            }

            List<String> orderedFkFields = new ArrayList<String>(fkFields.size());
            List<String> orderedTargetFields = new ArrayList<String>(targetFields.size());

            if (!error) {
                // if target fields are primary keys
                resolved = true;
                for (String pkField : targetTableDef.getPrimaryKeyFieldNames()) {
                    String fkField = targetToFkField.get(pkField);
                    if (fkField == null) {
                        //primary key column not found
                        resolved = false;
                        break;
                    }
                    orderedFkFields.add(fkField);
                    orderedTargetFields.add(pkField);
                }
            }
            
            if (!error && !resolved) {
                // if target fields are unique keys
                for (UniqueKeyConstraint uniqueConstraint : targetTableDef.getUniqueKeys()) {
                    orderedFkFields.clear();
                    orderedTargetFields.clear();

                    resolved = true;
                    for (String ukField : uniqueConstraint.getSourceFields()) {
                        String fkField = targetToFkField.get(ukField);
                        if (fkField == null) {
                            //unique key column not found
                            resolved = false;
                            break;
                        }
                        orderedFkFields.add(fkField);
                        orderedTargetFields.add(ukField);
                    }
                    if (resolved) {
                        break;
                    }
                }
            }

            if (resolved) {
                fkFieldNames = orderedFkFields;
                targetFieldNames = orderedTargetFields;
            }
        }

        // For bidirectional relationships both side of mapping will make the same FK constraint twice.
        // TableDefinition.addForeignKeyConstraint() will ignore the same FK constraint.

        ForeignKeyConstraint constraint = sourceTableDef.buildForeignKeyConstraint(fkFieldNames, targetFieldNames,
            targetTableDef, this.databasePlatform);
        constraint.setShouldCascadeOnDelete(cascadeOnDelete);
        sourceTableDef.addForeignKeyConstraint(constraint);
    }
    
    protected void addUniqueKeyConstraints(TableDefinition sourceTableDef, Map<String, List<List<String>>> uniqueConstraintsMap) {
        int serialNumber = -1;
        
        for (String name : uniqueConstraintsMap.keySet()) {
            List<List<String>> uniqueConstraints = uniqueConstraintsMap.get(name);
           
            for (List<String> uniqueConstraint : uniqueConstraints) {
                if (uniqueConstraint != null) {
                    // To keep the serialNumber consecutive, increment it only
                    // if the name is not specified.
                    if (name == null || name.equals("")) {
                        serialNumber++;
                    }
                    
                    sourceTableDef.addUniqueKeyConstraint(sourceTableDef.buildUniqueKeyConstraint(name, uniqueConstraint, serialNumber, databasePlatform));
                }
            }
        }
    }
}
