/*
 * Copyright (c) 1998, 2019 Oracle and/or its affiliates. All rights reserved.
 * Copyright (c) 1998, 2015 Sei Syvalta. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0,
 * or the Eclipse Distribution License v. 1.0 which is available at
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
 */

// 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.Iterator;
import java.util.LinkedHashMap;
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.logging.AbstractSessionLog;
import org.eclipse.persistence.logging.SessionLog;
import org.eclipse.persistence.mappings.AggregateCollectionMapping;
import org.eclipse.persistence.mappings.DatabaseMapping;
import org.eclipse.persistence.mappings.DirectCollectionMapping;
import org.eclipse.persistence.mappings.DirectMapMapping;
import org.eclipse.persistence.mappings.DirectToFieldMapping;
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.converters.Converter;
import org.eclipse.persistence.mappings.converters.SerializedObjectConverter;
import org.eclipse.persistence.mappings.converters.TypeConversionConverter;
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;

/**
 * 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", 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 = 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(((SerializedObjectConverter)converter).getSerializer().getType());
                    }
                }
            } 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(mapping.getReferenceDescriptor().getDefaultTable());
                    addFieldsForMappedKeyMapContainerPolicy(mapping.getContainerPolicy(), targTblDef);
                }
            } else if (mapping.isTransformationMapping()) {
                resetTransformedFieldType((TransformationMapping) mapping);
            } else if (mapping.isAggregateObjectMapping()){
                postInitTableSchema(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) {
            FieldDefinition fieldDef = getFieldDefFromDBField(listOrderField);
            if (!table.getFields().contains(fieldDef)) {
                table.addField(fieldDef);
            }
        }
    }

    /**
     * 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()) {
            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);
            FieldDefinition fieldDef = getFieldDefFromDBField(fkField);
            // Avoid adding fields twice for table per class.
            if (!table.getFields().contains(fieldDef)) {
                table.addField(fieldDef);
            }
        }

        // 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.
        FieldDefinition fieldDef = getFieldDefFromDBField(mapping.getDirectField());
        if (!table.getFields().contains(fieldDef)) {
            table.addField(fieldDef);
        }

        //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();
            fieldDef = getFieldDefFromDBField(dbField);
            if (!table.getFields().contains(fieldDef)) {
                table.addField(fieldDef);
            }
        } else {
            addFieldsForMappedKeyMapContainerPolicy(mapping.getContainerPolicy(), table);

            if (mapping.getListOrderField() != null) {
                fieldDef = getFieldDefFromDBField(mapping.getListOrderField());
                if (!table.getFields().contains(fieldDef)) {
                    table.addField(fieldDef);
                }
            }
        }
        if (mapping.getDescriptor().hasTablePerClassPolicy()) {
            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
            FieldDefinition fieldDef = getFieldDefFromDBField(dbField);
            if (!targetTable.getFields().contains(fieldDef)) {
                targetTable.addField(fieldDef);
            }
        }

        //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);
            FieldDefinition fieldDef = getFieldDefFromDBField(fkField);
            if (!targetTable.getFields().contains(fieldDef)) {
                targetTable.addField(fieldDef);
            }
        }

        // add a foreign key constraint from fk field to target field
        DatabaseTable sourceDatabaseTable = targetField.getTable();
        TableDefinition sourceTable = getTableDefFromDBTable(sourceDatabaseTable);

        if (mapping.getListOrderField() != null) {
            FieldDefinition fieldDef = getFieldDefFromDBField(mapping.getListOrderField());
            TableDefinition table = getTableDefFromDBTable(mapping.getListOrderField().getTable());
            if (!table.getFields().contains(fieldDef)) {
                table.addField(fieldDef);
            }
        }
        if (mapping.getDescriptor().hasTablePerClassPolicy()) {
            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()) {
            return;
        }
        addForeignMappingFkConstraint(mapping.getTargetForeignKeysToSourceKeys(), mapping.isCascadeOnDeleteSetOnDatabase());
        if (mapping.getListOrderField() != null) {
            FieldDefinition fieldDef = getFieldDefFromDBField(mapping.getListOrderField());
            TableDefinition table = getTableDefFromDBTable(mapping.getListOrderField().getTable());
            if (!table.getFields().contains(fieldDef)) {
                table.addField(fieldDef);
            }
        }
    }

    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<>();
        List<DatabaseField> targetFields = new ArrayList<>();

        for (Map.Entry<DatabaseField, DatabaseField> field : srcFields.entrySet()) {
            fkFields.add(field.getKey());
            targetFields.add(field.getValue());
        }
        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<>();
                List<DatabaseField> pkFields = new ArrayList<>();

                for (Map.Entry<DatabaseField, DatabaseField> field : srcFields.entrySet()) {
                    pkFields.add(field.getKey());
                    fkFields.add(field.getValue());
                }
                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<>();
            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<>(fkFields.size());
            List<String> orderedTargetFields = new ArrayList<>(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));
                }
            }
        }
    }
}
