/*
 * Copyright (c) 1998, 2021 Oracle and/or its affiliates. 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
//     Dies Koper - avoid generating constraints on platforms that do not support constraint generation
//     Dies Koper - add support for creating indices on tables
//     09/09/2011-2.3.1 Guy Pelletier
//       - 356197: Add new VPD type to MultitenantType
//     09/14/2011-2.3.1 Guy Pelletier
//       - 357533: Allow DDL queries to execute even when Multitenant entities are part of the PU
//     12/07/2012-2.5 Guy Pelletier
//       - 389090: JPA 2.1 DDL Generation Support (foreign key metadata support)
//     02/04/2013-2.5 Guy Pelletier
//       - 389090: JPA 2.1 DDL Generation Support
package org.eclipse.persistence.tools.schemaframework;

import java.io.IOException;
import java.io.StringWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Vector;

import org.eclipse.persistence.exceptions.DatabaseException;
import org.eclipse.persistence.exceptions.EclipseLinkException;
import org.eclipse.persistence.exceptions.ValidationException;
import org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor;
import org.eclipse.persistence.internal.databaseaccess.DatabasePlatform;
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.sessions.AbstractSession;
import org.eclipse.persistence.queries.SQLCall;

/**
 * <p>
 * <b>Purpose</b>: Allow a generic way of creating tables on the different platforms.
 * </p>
 */
public class TableDefinition extends DatabaseObjectDefinition {
    protected List<FieldDefinition> fields; //FieldDefinitions
    protected Map<String, ForeignKeyConstraint> foreignKeyMap; //key is the name of ForeignKeyConstraint
    protected List<UniqueKeyConstraint> uniqueKeys;
    protected List<IndexDefinition> indexes;
    protected String creationPrefix;
    protected String creationSuffix;
    private boolean createSQLFiles;
    private boolean createVPDCalls;
    private String tenantFieldName;
    //holds onto the name and delimiting info.
    protected DatabaseTable table;
    protected boolean hasUserDefinedForeignKeyConstraints;

    public TableDefinition() {
        createVPDCalls = false;
        hasUserDefinedForeignKeyConstraints = false;
        this.fields = new ArrayList<>();
        this.indexes = new ArrayList<>();
        this.foreignKeyMap = new HashMap<>();
        this.uniqueKeys = new ArrayList<>();
        this.creationPrefix = "CREATE TABLE ";
        this.creationSuffix = "";
    }

    /**
     * PUBLIC:
     * Add the field to the table, default sizes are used.
     * @param type is the Java class type corresponding to the database type.
     */
    public void addField(String fieldName, Class type) {
        this.addField(new FieldDefinition(fieldName, type));
    }

    /**
     * PUBLIC:
     * Add the field to the table.
     * @param type is the Java class type corresponding to the database type.
     */
    public void addField(String fieldName, Class type, int fieldSize) {
        this.addField(new FieldDefinition(fieldName, type, fieldSize));
    }

    /**
     * PUBLIC:
     * Add the field to the table.
     * @param type is the Java class type corresponding to the database type.
     */
    public void addField(String fieldName, Class type, int fieldSize, int fieldSubSize) {
        this.addField(new FieldDefinition(fieldName, type, fieldSize, fieldSubSize));
    }

    /**
     * PUBLIC:
     * Add the field to the type to a nested type.
     * @param typeName is the name of the nested type.
     */
    public void addField(String fieldName, String typeName) {
        addField(new FieldDefinition(fieldName, typeName));
    }

    /**
     * PUBLIC:
     * Add the field to the table.
     */
    public void addField(FieldDefinition field) {
        getFields().add(field);
    }

    /**
     * INTERNAL:
     * Execute the SQL alter table to add the field to the table.
     */
    public void addFieldOnDatabase(final AbstractSession session, FieldDefinition field){
        session.priviledgedExecuteNonSelectingCall(
                new SQLCall( buildAddFieldWriter(session, field, new StringWriter()).toString() ) );
    }

    /**
     * INTERNAL:
     * Return the alter table statement to add a field to the table.
     */
    public Writer buildAddFieldWriter(AbstractSession session, FieldDefinition field, Writer writer) throws ValidationException {
        try {
            writer.write("ALTER TABLE " + getFullName() + " ");
            session.getPlatform().writeAddColumnClause(writer, session, this, field);
            writer.write(" ");
        } catch (IOException ioException) {
            throw ValidationException.fileError(ioException);
        }
        return writer;
    }

    /**
     * PUBLIC:
     * Add a foreign key constraint to the table.
     * If there is a same name foreign key constraint already, nothing will happen.
     */
    public void addForeignKeyConstraint(String name, String sourceField, String targetField, String targetTable) {
        ForeignKeyConstraint foreignKey = new ForeignKeyConstraint(name, sourceField, targetField, targetTable);
        addForeignKeyConstraint(foreignKey);
    }

    /**
     * PUBLIC:
     * Add a unique key constraint to the table.
     */
    public void addUniqueKeyConstraint(String name, String sourceField) {
        UniqueKeyConstraint uniqueKey = new UniqueKeyConstraint(name, sourceField);
        addUniqueKeyConstraint(uniqueKey);
    }

    /**
     * PUBLIC:
     * Add a unique key constraint to the table.
     */
    public void addUniqueKeyConstraint(String name, String[] sourceFields) {
        UniqueKeyConstraint uniqueKey = new UniqueKeyConstraint(name, sourceFields);
        addUniqueKeyConstraint(uniqueKey);
    }

    /**
     * PUBLIC:
     * Add a foreign key constraint to the table.
     * If there is a same name foreign key constraint already, nothing will happen.
     */
    public void addForeignKeyConstraint(ForeignKeyConstraint foreignKey) {
        if (! hasUserDefinedForeignKeyConstraints) {
            if (!foreignKeyMap.containsKey(foreignKey.getName())) {
                foreignKeyMap.put(foreignKey.getName(), foreignKey);
            }
        }
    }

    /**
     * PUBLIC:
     * Add a unique key constraint to the table.
     */
    public void addUniqueKeyConstraint(UniqueKeyConstraint uniqueKey) {
        getUniqueKeys().add(uniqueKey);
    }

    /**
     * PUBLIC:
     * Add an index to the table.
     */
    public void addIndex(IndexDefinition index) {
        getIndexes().add(index);
    }

    /**
     * PUBLIC:
     * Add the field to the table, default sizes are used.
     * Identity fields are used on Sybase for native sequencing,
     * The field must be of number type and cannot have a subsize.
     * @param type is the Java class type corresponding to the database type.
     */
    public void addIdentityField(String fieldName, Class type) {
        FieldDefinition fieldDef = new FieldDefinition(fieldName, type);
        fieldDef.setIsIdentity(true);
        fieldDef.setIsPrimaryKey(true);
        addField(fieldDef);
    }

    /**
     * PUBLIC:
     * Add the field to the table, default sizes are used.
     * Identity fields are used on Sybase for native sequencing,
     * The field must be of number type and cannot have a subsize.
     * @param type is the Java class type corresponding to the database type.
     */
    public void addIdentityField(String fieldName, Class type, int fieldSize) {
        FieldDefinition fieldDef = new FieldDefinition(fieldName, type, fieldSize);
        fieldDef.setIsIdentity(true);
        fieldDef.setIsPrimaryKey(true);
        addField(fieldDef);
    }

    /**
     * PUBLIC:
     * Add the field to the table, default sizes are used.
     * This field is set as part of the primary key.
     * @param type is the Java class type corresponding to the database type.
     */
    public void addPrimaryKeyField(String fieldName, Class type) {
        FieldDefinition fieldDef = new FieldDefinition(fieldName, type);
        fieldDef.setIsPrimaryKey(true);
        addField(fieldDef);
    }

    /**
     * PUBLIC:
     * Add the field to the table, default sizes are used.
     * This field is set as part of the primary key.
     * @param type is the Java class type corresponding to the database type.
     */
    public void addPrimaryKeyField(String fieldName, Class type, int fieldSize) {
        FieldDefinition fieldDef = new FieldDefinition(fieldName, type, fieldSize);
        fieldDef.setIsPrimaryKey(true);
        addField(fieldDef);
    }

    /**
     * INTERNAL:
     * Return the alter table statement to add the constraints.
     * This is done separately from the create because of dependencies.
     */
    public Writer buildConstraintCreationWriter(AbstractSession session, ForeignKeyConstraint foreignKey, Writer writer) throws ValidationException {
        try {
            writer.write("ALTER TABLE " + getFullName());
            writer.write(" ADD CONSTRAINT ");
            if (!session.getPlatform().shouldPrintConstraintNameAfter()) {
                writer.write(foreignKey.getName() + " ");
            }
            foreignKey.appendDBString(writer, session);
            if (session.getPlatform().shouldPrintConstraintNameAfter()) {
                writer.write(" CONSTRAINT " + foreignKey.getName());
            }
        } catch (IOException ioException) {
            throw ValidationException.fileError(ioException);
        }

        return writer;
    }

    /**
     * INTERNAL:
     * Return the alter table statement to drop the constraints.
     * This is done separately to allow constraints to be dropped before the tables.
     */
    public Writer buildConstraintDeletionWriter(AbstractSession session, ForeignKeyConstraint foreignKey, Writer writer) throws ValidationException {
        try {
            writer.write("ALTER TABLE " + getFullName());
            writer.write(session.getPlatform().getConstraintDeletionString() + foreignKey.getName());
        } catch (IOException ioException) {
            throw ValidationException.fileError(ioException);
        }
        return writer;
    }

    /**
     * INTERNAL:
     * Return the alter table statement to add the constraints.
     * This is done separately from the create because of dependencies.
     */
    public Writer buildUniqueConstraintCreationWriter(AbstractSession session, UniqueKeyConstraint uniqueKey, Writer writer) throws ValidationException {
        try {
            writer.write("ALTER TABLE " + getFullName());
            writer.write(" ADD CONSTRAINT ");
            if (!session.getPlatform().shouldPrintConstraintNameAfter()) {
                writer.write(uniqueKey.getName() + " ");
            }
            uniqueKey.appendDBString(writer, session);
            if (session.getPlatform().shouldPrintConstraintNameAfter()) {
                writer.write(" CONSTRAINT " + uniqueKey.getName());
            }
        } catch (IOException ioException) {
            throw ValidationException.fileError(ioException);
        }
        return writer;
    }

    /**
     * INTERNAL:
     * Return the alter table statement to drop the constraints.
     * This is done separately to allow constraints to be dropped before the tables.
     */
    public Writer buildUniqueConstraintDeletionWriter(AbstractSession session, UniqueKeyConstraint uniqueKey, Writer writer) throws ValidationException {
        try {
            writer.write("ALTER TABLE " + getFullName());
            writer.write(session.getPlatform().getUniqueConstraintDeletionString() + uniqueKey.getName());
        } catch (IOException ioException) {
            throw ValidationException.fileError(ioException);
        }
        return writer;
    }

    /**
     * INTERNAL:
     * Return the index creation statement.
     */
    public IndexDefinition buildIndex(AbstractSession session, String key, List<String> columnNames, boolean isUniqueSetOnField) {
        String indexName = buildIndexName(getName(), key, session.getPlatform().getIndexNamePrefix(isUniqueSetOnField), session.getPlatform().getMaxIndexNameSize(), session.getPlatform());
        IndexDefinition index = new IndexDefinition();
        index.setName(indexName);
        index.setTargetTable(getFullName());
        index.getFields().addAll(columnNames);
        return index;
    }

    /**
     * INTERNAL:
     * Return the index drop statement.
     */
    public Writer buildIndexDeletionWriter(AbstractSession session, String key, Writer writer, boolean isUniqueSetOnField) {
            String indexName = buildIndexName(getName(), key, session.getPlatform().getIndexNamePrefix(isUniqueSetOnField),
                    session.getPlatform().getMaxIndexNameSize(), session.getPlatform());
        IndexDefinition index = new IndexDefinition();
        index.setName(indexName);
        index.setTargetTable(getFullName());
        index.buildDeletionWriter(session, writer);
        return writer;
    }


    /**
     * INTERNAL:
     * Return the beginning of the sql create statement - the part before the name.
     * Unless temp table is created should be "CREATE TABLE "
     */
    public String getCreationPrefix() {
        return creationPrefix;
    }

    /**
     * INTERNAL:
     * Set the beginning of the sql create statement - the part before the name.
     * Use to create temp. table.
     */
    public void setCreationPrefix(String  creationPrefix) {
        this.creationPrefix = creationPrefix;
    }

    /**
     * INTERNAL:
     * Return the end of the sql create statement - the part after the field list.
     * Unless temp table is created should be empty.
     */
    public String getCreationSuffix() {
        return creationSuffix;
    }

    /**
     * PUBLIC:
     * Return the schema associated with this table.
     */
    @Override
    public String getDatabaseSchema() {
        return getTable().getTableQualifier();
    }

    /**
     * INTERNAL:
     * Set the end of the sql create statement - the part after the field list.
     */
    public void setCreationSuffix(String  creationSuffix) {
        this.creationSuffix = creationSuffix;
    }

    /**
     * INTERNAL:
     * Return the create table statement.
     */
    @Override
    public Writer buildCreationWriter(AbstractSession session, Writer writer) throws ValidationException {
        try {
            writer.write(getCreationPrefix() + getFullName() + " (");
            for (Iterator<FieldDefinition> itetrator = getFields().iterator(); itetrator.hasNext();) {
                FieldDefinition field = itetrator.next();
                field.appendDBString(writer, session, this);
                if (itetrator.hasNext()) {
                    writer.write(", ");
                }
            }
            List<String> keyFields = getPrimaryKeyFieldNames();
            if ((!keyFields.isEmpty()) && session.getPlatform().supportsPrimaryKeyConstraint()) {
                writer.write(", ");
                if (session.getPlatform().requiresNamedPrimaryKeyConstraints()) {
                    writer.write("CONSTRAINT " + getFullName() + "_PK ");
                }
                writer.write("PRIMARY KEY (");
                for (Iterator<String> iterator = keyFields.iterator(); iterator.hasNext();) {
                    writer.write(iterator.next());
                    if (iterator.hasNext()) {
                        writer.write(", ");
                    }
                }
                writer.write(")");
            }
            if (session.getPlatform().requiresUniqueConstraintCreationOnTableCreate()) {
                for (UniqueKeyConstraint constraint : getUniqueKeys()) {
                    writer.write(", ");
                    constraint.appendDBString(writer, session);
                }
            }
            writer.write(")");
            //let the platform write out the CreationSuffix and the platform's default tableCreationSuffix
            session.getPlatform().writeTableCreationSuffix(writer, getCreationSuffix());
        } catch (IOException ioException) {
            throw ValidationException.fileError(ioException);
        }
        return writer;
    }

    /**
     * INTERNAL:
     * Return the drop table statement.
     */
    @Override
    public Writer buildDeletionWriter(AbstractSession session, Writer writer) throws ValidationException {
        try {
            writer.write("DROP TABLE " + getFullName() + session.getPlatform().getDropCascadeString());
        } catch (IOException ioException) {
            throw ValidationException.fileError(ioException);
        }
        return writer;
    }

    /**
     * INTERNAL:
     */
    @Override
    public Writer buildVPDCreationPolicyWriter(AbstractSession session, Writer writer) {
        try {
            writer.write(session.getPlatform().getVPDCreationPolicyString(getName(), session));
            return writer;
        } catch (IOException ioException) {
            throw ValidationException.fileError(ioException);
        }
    }

    /**
     * INTERNAL:
     */
    @Override
    public Writer buildVPDCreationFunctionWriter(AbstractSession session, Writer writer) {
        try {
            writer.write(session.getPlatform().getVPDCreationFunctionString(getName(), tenantFieldName));
        } catch (IOException ioException) {
            throw ValidationException.fileError(ioException);
        }

        return writer;
    }

    /**
     * INTERNAL:
     * Build the create schema DDL.
     */
    protected Writer buildDatabaseSchemaCreationWriter(AbstractSession session, Writer writer, Set<String> createdDatabaseSchemas) {
        try {
            writer.write(session.getPlatform().getCreateDatabaseSchemaString(getDatabaseSchema()));
        } catch (IOException ioException) {
            throw ValidationException.fileError(ioException);
        }

        // Tag that we created a schema (to avoid creating it again)
        createdDatabaseSchemas.add(getDatabaseSchema());
        return writer;
    }

    /**
     * INTERNAL:
     * Build the drop schema DDL.
     */
    protected Writer buildDatabaseSchemaDeletionWriter(AbstractSession session, Writer writer) {
        try {
            writer.write(session.getPlatform().getDropDatabaseSchemaString(getDatabaseSchema()));
        } catch (IOException ioException) {
            throw ValidationException.fileError(ioException);
        }

        return writer;
    }

    /**
     * INTERNAL:
     */
    @Override
    public Writer buildVPDDeletionWriter(AbstractSession session, Writer writer) {
        try {
            writer.write(session.getPlatform().getVPDDeletionString(getName(), session));
        } catch (IOException ioException) {
            throw ValidationException.fileError(ioException);
        }

        return writer;
    }

    /**
     * INTERNAL:
     * Build the foreign key constraints.
     */
    protected void buildFieldTypes(AbstractSession session) {
        // The ForeignKeyConstraint object is the newer way of doing things.
        // We support FieldDefinition.getForeignKeyFieldName() due to backwards compatibility
        // by converting it. To allow mixing both ways, we just add converted one to foreignKeys list.
        for (FieldDefinition field : getFields()) {
            if (field.getForeignKeyFieldName() != null) {
                addForeignKeyConstraint(buildForeignKeyConstraint(field, session.getPlatform()));
            }
        }
    }

    /**
     * Build a foreign key constraint using FieldDefinition.getForeignKeyFieldName().
     */
    protected ForeignKeyConstraint buildForeignKeyConstraint(FieldDefinition field, DatabasePlatform platform) {
        List<String> sourceFields = new Vector<>();
        List<String> targetFields = new Vector<>();
        ForeignKeyConstraint fkConstraint = new ForeignKeyConstraint();
        DatabaseField tempTargetField = new DatabaseField(field.getForeignKeyFieldName());
        DatabaseField tempSourceField = new DatabaseField(field.getName());

        sourceFields.add(tempSourceField.getName());
        targetFields.add(tempTargetField.getName());

        fkConstraint.setSourceFields(sourceFields);
        fkConstraint.setTargetFields(targetFields);
        fkConstraint.setTargetTable(tempTargetField.getTable().getQualifiedNameDelimited(platform));
        String tempName = buildForeignKeyConstraintName(this.getName(), tempSourceField.getName(), platform.getMaxForeignKeyNameSize(), platform);

        fkConstraint.setName(tempName);
        return fkConstraint;
    }

    /**
     * Build a foreign key constraint.
     */
    protected ForeignKeyConstraint buildForeignKeyConstraint(List<String> fkFieldNames, List<String> pkFieldNames, TableDefinition targetTable, DatabasePlatform platform) {
        assert fkFieldNames.size() > 0 && fkFieldNames.size() == pkFieldNames.size();

        ForeignKeyConstraint fkConstraint = new ForeignKeyConstraint();
        for(int i=0; i<fkFieldNames.size(); i++) {
            fkConstraint.getSourceFields().add(fkFieldNames.get(i));
            fkConstraint.getTargetFields().add(pkFieldNames.get(i));
        }

        fkConstraint.setTargetTable(targetTable.getFullName());
        String fkFieldName = fkFieldNames.get(0);
        String name = buildForeignKeyConstraintName(this.getName(), fkFieldName, platform.getMaxForeignKeyNameSize(), platform);

        fkConstraint.setName(name);
        return fkConstraint;
    }

    /**
     * Return foreign key constraint name built from the table and field name with the specified maximum length. To
     * make the name short enough we
     * 1. Drop the "FK_" prefix.
     * 2. Drop the underscore characters if any.
     * 3. Drop the vowels from the table and field name.
     * 4. Truncate the table name to zero length if necessary.
     */
    protected String buildForeignKeyConstraintName(String tableName, String fieldName, int maximumNameLength, DatabasePlatform platform) {
        String startDelimiter = "";
        String endDelimiter = "";
        boolean useDelimiters = !platform.getStartDelimiter().equals("") && (tableName.startsWith(platform.getStartDelimiter()) || fieldName.startsWith(platform.getStartDelimiter()));
        // we will only delimit our generated constraints if either of the names that composes them is already delimited
        if (useDelimiters){
            startDelimiter = platform.getStartDelimiter();
            endDelimiter = platform.getEndDelimiter();
        }
        String adjustedTableName = tableName;
        if(adjustedTableName.indexOf(' ') != -1 || adjustedTableName.indexOf('\"') != -1 || adjustedTableName.indexOf('`') != -1) {
            //if table name has spaces and/or is quoted, remove this from the constraint name.
            StringBuilder buff = new StringBuilder();
            for(int i = 0; i < tableName.length(); i++) {
                char c = tableName.charAt(i);
                if(c != ' ' && c != '\"' && c != '`') {
                    buff.append(c);
                }
            }
            adjustedTableName = buff.toString();
        }
        StringBuilder buff = new StringBuilder();
        for(int i = 0; i < fieldName.length(); i++) {
            char c = fieldName.charAt(i);
            if(c != ' ' && c != '\"' && c != '`') {
                buff.append(c);
            }
        }
        String adjustedFieldName = buff.toString();
        String foreignKeyName = startDelimiter + "FK_" + adjustedTableName + "_" + adjustedFieldName + endDelimiter;
        if (foreignKeyName.length() > maximumNameLength) {
            // First Remove the "FK_" prefix.
            foreignKeyName = startDelimiter + adjustedTableName + "_" + adjustedFieldName + endDelimiter;
            if (foreignKeyName.length() > maximumNameLength) {
                // Still too long: remove the underscore characters
                foreignKeyName = startDelimiter + Helper.removeAllButAlphaNumericToFit(adjustedTableName + adjustedFieldName, maximumNameLength) + endDelimiter;
                if (foreignKeyName.length() > maximumNameLength) {
                    // Still too long: remove vowels from the table name and field name.
                    String onlyAlphaNumericTableName = Helper.removeAllButAlphaNumericToFit(adjustedTableName, 0);
                    String onlyAlphaNumericFieldName = Helper.removeAllButAlphaNumericToFit(adjustedFieldName, 0);
                    foreignKeyName = startDelimiter + Helper.shortenStringsByRemovingVowelsToFit(onlyAlphaNumericTableName, onlyAlphaNumericFieldName, maximumNameLength) + endDelimiter;
                    if (foreignKeyName.length() > maximumNameLength) {
                        // Still too long: remove vowels from the table name and field name and truncate the table name.
                        String shortenedFieldName = Helper.removeVowels(onlyAlphaNumericFieldName);
                        String shortenedTableName = Helper.removeVowels(onlyAlphaNumericTableName);
                        int delimiterLength = startDelimiter.length() + endDelimiter.length();
                        if (shortenedFieldName.length() + delimiterLength >= maximumNameLength) {
                            foreignKeyName = startDelimiter + Helper.truncate(shortenedFieldName, maximumNameLength - delimiterLength) + endDelimiter;
                        } else {
                            foreignKeyName = startDelimiter + Helper.truncate(shortenedTableName, maximumNameLength - shortenedFieldName.length() - delimiterLength) + shortenedFieldName + endDelimiter;
                        }
                    }
                }
            }
        }
        return foreignKeyName;
    }

    protected UniqueKeyConstraint buildUniqueKeyConstraint(String name, List<String> fieldNames, int serialNumber, DatabasePlatform platform) {
        assert fieldNames.size() > 0;

        UniqueKeyConstraint unqConstraint = new UniqueKeyConstraint();

        for (String fieldName : fieldNames) {
            unqConstraint.addSourceField(fieldName);
        }

        // If the name was not provided, default one, otherwise use the name provided.
        if (name == null || name.equals("")) {
            unqConstraint.setName(buildUniqueKeyConstraintName(getName(), serialNumber, platform.getMaxUniqueKeyNameSize()));
        } else {
            // Hack if off if it exceeds the max size.
            if (name.length() > platform.getMaxUniqueKeyNameSize()) {
                unqConstraint.setName(name.substring(0, platform.getMaxUniqueKeyNameSize() - 1));
            } else {
                unqConstraint.setName(name);
            }
        }

        return unqConstraint;
    }

    /**
     * Return unique key constraint name built from the table name and sequence
     * number with the specified maximum length. To make the name short enough we
     * 1. Drop the "UNQ_" prefix.
     * 2. Drop the underscore characters if any.
     * 3. Drop the vowels from the table name.
     * 4. Truncate the table name to zero length if necessary.
     */
    protected String buildUniqueKeyConstraintName(String tableName, int serialNumber, int maximumNameLength) {
        String uniqueKeyName = "UNQ_" + tableName + "_" + serialNumber;
        if (uniqueKeyName.length() > maximumNameLength) {
            // First Remove the "UNQ_" prefix.
            uniqueKeyName = tableName + serialNumber;
            if (uniqueKeyName.length() > maximumNameLength) {
                // Still too long: remove the underscore characters
                uniqueKeyName = Helper.removeAllButAlphaNumericToFit(tableName + serialNumber, maximumNameLength);
                if (uniqueKeyName.length() > maximumNameLength) {
                    // Still too long: remove vowels from the table name
                    String onlyAlphaNumericTableName = Helper.removeAllButAlphaNumericToFit(tableName, 0);
                    String serialName = String.valueOf(serialNumber);
                    uniqueKeyName = Helper.shortenStringsByRemovingVowelsToFit(onlyAlphaNumericTableName, serialName, maximumNameLength);
                    if (uniqueKeyName.length() > maximumNameLength) {
                        // Still too long: remove vowels from the table name and truncate the table name.
                        String shortenedTableName = Helper.removeVowels(onlyAlphaNumericTableName);
                        uniqueKeyName = Helper.truncate(shortenedTableName, maximumNameLength - serialName.length()) + serialName;
                    }
                }
            }
        }
        return uniqueKeyName;
    }

    /**
     * Return key constraint name built from the table and key name with the
     * specified maximum length and index prefix. If indexPrefix is null,
     * "IX_" is used for prefix. To make the name short enough we:
     *
     * <pre>
     * 1. Drop the prefix.
     * 2. Drop the underscore characters if any.
     * 3. Drop the vowels from the table and key name.
     * 4. Truncate the table name to zero length if necessary.
     * </pre>
     */
    protected String buildIndexName(String tableName, String key, String indexPrefix, int maximumNameLength, DatabasePlatform platform) {
        String startDelimiter = "";
        String endDelimiter = "";
        boolean useDelimiters = !platform.getStartDelimiter().equals("") && (tableName.startsWith(platform.getStartDelimiter()) || key.startsWith(platform.getStartDelimiter()));
        // we will only delimit our generated indices if either of the names that composes them is already delimited
        if (useDelimiters){
            startDelimiter = platform.getStartDelimiter();
            endDelimiter = platform.getEndDelimiter();
        }
        String adjustedTableName = tableName;
        if(adjustedTableName.indexOf(' ') != -1 || adjustedTableName.indexOf('\"') != -1 || adjustedTableName.indexOf('`') != -1) {
            //if table name has spaces and/or is quoted, remove this from the constraint name.
            StringBuilder buff = new StringBuilder();
            for(int i = 0; i < tableName.length(); i++) {
                char c = tableName.charAt(i);
                if(c != ' ' && c != '\"' && c != '`') {
                    buff.append(c);
                }
            }
            adjustedTableName = buff.toString();
        }
        StringBuilder buff = new StringBuilder();
        for(int i = 0; i < key.length(); i++) {
            char c = key.charAt(i);
            if(c != ' ' && c != '\"' && c != '`') {
                buff.append(c);
            }
        }
        String adjustedFieldName = buff.toString();
        if (indexPrefix == null) {
            indexPrefix = "IX_";
        }
        String indexName = startDelimiter + indexPrefix + adjustedTableName + "_" + adjustedFieldName + endDelimiter;
        if (indexName.length() > maximumNameLength) {
            // First Remove the prefix.
            indexName = startDelimiter + adjustedTableName + "_" + adjustedFieldName + endDelimiter;
            if (indexName.length() > maximumNameLength) {
                // Still too long: remove the underscore characters
                indexName = startDelimiter + Helper.removeAllButAlphaNumericToFit(adjustedTableName + adjustedFieldName, maximumNameLength) + endDelimiter;
                if (indexName.length() > maximumNameLength) {
                    // Still too long: remove vowels from the table name and field name.
                    String onlyAlphaNumericTableName = Helper.removeAllButAlphaNumericToFit(adjustedTableName, 0);
                    String onlyAlphaNumericFieldName = Helper.removeAllButAlphaNumericToFit(adjustedFieldName, 0);
                    indexName = startDelimiter + Helper.shortenStringsByRemovingVowelsToFit(onlyAlphaNumericTableName, onlyAlphaNumericFieldName, maximumNameLength) + endDelimiter;
                    if (indexName.length() > maximumNameLength) {
                        // Still too long: remove vowels from the table name and field name and truncate the table name.
                        String shortenedFieldName = Helper.removeVowels(onlyAlphaNumericFieldName);
                        String shortenedTableName = Helper.removeVowels(onlyAlphaNumericTableName);
                        int delimiterLength = startDelimiter.length() + endDelimiter.length();
                        if (shortenedFieldName.length() + delimiterLength >= maximumNameLength) {
                            indexName = startDelimiter + Helper.truncate(shortenedFieldName, maximumNameLength - delimiterLength) + endDelimiter;
                        } else {
                            indexName = startDelimiter + Helper.truncate(shortenedTableName, maximumNameLength - shortenedFieldName.length() - delimiterLength) + shortenedFieldName + endDelimiter;
                        }
                    }
                }
            }
        }
        return indexName;
    }

    /**
     * PUBLIC:
     * Performs a deep copy of this table definition.
     */
    @Override
    public Object clone() {
        TableDefinition clone = (TableDefinition)super.clone();
        if (fields != null) {
            clone.setFields(new ArrayList<>(fields.size()));
            for (FieldDefinition fieldDef : getFields()) {
                clone.addField((FieldDefinition)fieldDef.clone());
            }
        }
        if (foreignKeyMap != null) {
            clone.setForeignKeyMap(new HashMap<>(this.foreignKeyMap));
        }
        if (uniqueKeys != null) {
            clone.setUniqueKeys(new ArrayList<>(this.uniqueKeys));
        }
        return clone;
    }

    /**
     * INTERNAL:
     * Execute the SQL alter table constraint creation string.
     */
    public void createConstraints(AbstractSession session, Writer schemaWriter) throws EclipseLinkException {
        createUniqueConstraints(session, schemaWriter);
        createForeignConstraints(session, schemaWriter);
    }

    void createUniqueConstraints(final AbstractSession session, final Writer schemaWriter) throws ValidationException {
        if (schemaWriter == null) {
            createUniqueConstraintsOnDatabase(session);
            return;
        }

        if ((!session.getPlatform().supportsUniqueKeyConstraints())
                || getUniqueKeys().isEmpty()
                || session.getPlatform().requiresUniqueConstraintCreationOnTableCreate()) {
            return;
        }
        for (UniqueKeyConstraint uniqueKey : getUniqueKeys()) {
            buildUniqueConstraintCreationWriter(session, uniqueKey, schemaWriter);
            writeLineSeperator(session, schemaWriter);
        }
    }

    void createForeignConstraints(final AbstractSession session, final Writer schemaWriter) throws ValidationException {
        if (schemaWriter == null) {
            createForeignConstraintsOnDatabase(session);
            return;
        }

        if (session.getPlatform().supportsForeignKeyConstraints()) {
            for (ForeignKeyConstraint foreignKey : getForeignKeyMap().values()) {
                if (! foreignKey.disableForeignKey()) {
                    buildConstraintCreationWriter(session, foreignKey, schemaWriter);
                    writeLineSeperator(session, schemaWriter);
                }
            }
        }
    }

    /**
     * INTERNAL:
     * Execute the SQL alter table constraint creation string.
     */
    public void createConstraintsOnDatabase(AbstractSession session) throws EclipseLinkException {
        createUniqueConstraintsOnDatabase(session);
        createForeignConstraintsOnDatabase(session);
    }

    /**
     * INTERNAL:
     * Execute the DDL to create the database schema for this object.
     */
    @Override
    public void createDatabaseSchema(AbstractSession session, Writer writer, Set<String> createdDatabaseSchemas) throws EclipseLinkException {
        buildDatabaseSchemaCreationWriter(session, writer, createdDatabaseSchemas);
    }

    /**
     * INTERNAL:
     * Execute the DDL to create the database schema for this object.
     */
    @Override
    public void createDatabaseSchemaOnDatabase(AbstractSession session, Set<String> createdDatabaseSchemas) throws EclipseLinkException {
        session.priviledgedExecuteNonSelectingCall(new SQLCall(buildDatabaseSchemaCreationWriter(session, new StringWriter(), createdDatabaseSchemas).toString()));
    }

    void createUniqueConstraintsOnDatabase(final AbstractSession session) throws ValidationException, DatabaseException {
        if ((!session.getPlatform().supportsUniqueKeyConstraints())
                || getUniqueKeys().isEmpty()
                || session.getPlatform().requiresUniqueConstraintCreationOnTableCreate()) {
            return;
        }

        for (UniqueKeyConstraint uniqueKey : getUniqueKeys()) {
            session.priviledgedExecuteNonSelectingCall(new org.eclipse.persistence.queries.SQLCall(buildUniqueConstraintCreationWriter(session, uniqueKey, new StringWriter()).toString()));
        }
    }

    void createForeignConstraintsOnDatabase(final AbstractSession session) throws ValidationException, DatabaseException {
        if ((!session.getPlatform().supportsForeignKeyConstraints()) || getForeignKeyMap().isEmpty()) {
            return;
        }

        for (ForeignKeyConstraint foreignKey : getForeignKeyMap().values()) {
            if (! foreignKey.disableForeignKey()) {
                session.priviledgedExecuteNonSelectingCall(new SQLCall(buildConstraintCreationWriter(session, foreignKey, new StringWriter()).toString()));
            }
        }
    }

    /**
     * INTERNAL:<br>
     * Write the SQL create index string to create index if
     * passed a writer, else delegate to a method that executes the string on
     * the database.
     *
     * @throws ValidationException wraps any IOException from the writer
     */
    public void createIndexes(AbstractSession session, Writer writer) {
        if (!session.getPlatform().supportsIndexes()) {
            return;
        }
        // Primary key
        if (session.getPlatform().shouldCreateIndicesForPrimaryKeys()) {
            List<String> primKeyList = getPrimaryKeyFieldNames();
            if (!primKeyList.isEmpty()) {
                IndexDefinition index = buildIndex(session, primKeyList.get(0), primKeyList, false);
                if (writer == null) {
                    index.createOnDatabase(session);
                } else {
                    index.buildCreationWriter(session, writer);
                    writeLineSeperator(session, writer);
                }
            }
        }
        // Unique keys
        if (session.getPlatform().shouldCreateIndicesOnUniqueKeys()) {
            // indices for columns in unique key constraint declarations
            for (UniqueKeyConstraint uniqueKey : getUniqueKeys()) {
                IndexDefinition index = buildIndex(session, uniqueKey.getName(), uniqueKey.getSourceFields(), false);
                if (writer == null) {
                    index.createOnDatabase(session);
                } else {
                    index.buildCreationWriter(session, writer);
                    writeLineSeperator(session, writer);
                }
            }

            // indices for columns with unique=true declarations
            for (FieldDefinition field : getFields()) {
                if (field.isUnique()) {
                    List<String> columnAsList = new ArrayList<>();
                    columnAsList.add(field.getName());
                    IndexDefinition index = buildIndex(session, field.getName(), columnAsList, true);
                    if (writer == null) {
                        index.createOnDatabase(session);
                    } else {
                        index.buildCreationWriter(session, writer);
                        writeLineSeperator(session, writer);
                    }
                }
            }
        }
        // Foreign keys
        if (session.getPlatform().shouldCreateIndicesOnForeignKeys()) {
            // indices for columns in foreign key constraint declarations
            for (ForeignKeyConstraint foreignKey : getForeignKeys()) {
                if (!foreignKey.isDisableForeignKey()) {
                    // Do not re-index pk.
                    boolean alreadyIndexed = false;
                    List<String> primaryKeys = getPrimaryKeyFieldNames();
                    if ((primaryKeys.size() == foreignKey.getSourceFields().size())
                            && primaryKeys.containsAll(foreignKey.getSourceFields())) {
                        alreadyIndexed = true;
                    }
                    // Also check unique fields.
                    if (foreignKey.getSourceFields().size() == 1) {
                        FieldDefinition field = getField(foreignKey.getSourceFields().get(0));
                        if ((field != null) && field.isUnique()) {
                            alreadyIndexed = true;
                        }
                    }
                    for (UniqueKeyConstraint uniqueConstraint : getUniqueKeys()) {
                        if ((uniqueConstraint.getSourceFields().size() == foreignKey.getSourceFields().size())
                                && uniqueConstraint.getSourceFields().containsAll(foreignKey.getSourceFields())) {
                            alreadyIndexed = true;
                        }
                    }
                    if (!alreadyIndexed) {
                        IndexDefinition index = buildIndex(session, foreignKey.getName(), foreignKey.getSourceFields(), false);
                        if (writer == null) {
                            try {
                                index.createOnDatabase(session);
                            } catch (Exception failed) {
                                //ignore
                            }
                        } else {
                            index.buildCreationWriter(session, writer);
                            writeLineSeperator(session, writer);
                        }
                    }
                }
            }
        }
        // Indexes
        for (IndexDefinition index : getIndexes()) {
            if (writer == null) {
                index.createOnDatabase(session);
            } else {
                index.buildCreationWriter(session, writer);
                writeLineSeperator(session, writer);
            }
        }
    }

    public void writeLineSeperator(AbstractSession session, Writer writer) {
        try {
            if (this.createSQLFiles) {
                writer.write(session.getPlatform().getStoredProcedureTerminationToken());
            }
            writer.write("\n");
        } catch (IOException exception) {
            throw ValidationException.fileError(exception);
        }
    }

    /**
     * INTERNAL:
     * Return the delete SQL string.
     */
    public String deletionStringFor(DatabaseAccessor accessor) {
        return "DROP TABLE " + this.getName();
    }

    /**
     * INTERNAL:
     * Execute the DDL to drop the database schema for this object.
     */
    @Override
    public void dropDatabaseSchema(AbstractSession session, Writer writer) throws EclipseLinkException {
        buildDatabaseSchemaDeletionWriter(session, writer);
    }

    /**
     * INTERNAL:
     * Execute the DDL to drop the database schema for this object.
     */
    @Override
    public void dropDatabaseSchemaOnDatabase(AbstractSession session) throws EclipseLinkException {
        session.priviledgedExecuteNonSelectingCall(new SQLCall(buildDatabaseSchemaDeletionWriter(session, new StringWriter()).toString()));
    }

    /**
     * INTERNAL:
     * Execute the SQL alter table constraint creation string.
     */
    public void dropConstraints(AbstractSession session, Writer schemaWriter) throws EclipseLinkException {
        if (schemaWriter == null) {
            dropConstraintsOnDatabase(session);
        } else {
            if (session.getPlatform().supportsForeignKeyConstraints()){
                for (ForeignKeyConstraint foreignKey : getForeignKeyMap().values()) {
                    buildConstraintDeletionWriter(session, foreignKey, schemaWriter);
                    writeLineSeperator(session, schemaWriter);
                }
            }
            if (session.getPlatform().supportsUniqueKeyConstraints()
                    && (!session.getPlatform().requiresUniqueConstraintCreationOnTableCreate())) {
                for (UniqueKeyConstraint uniqueKey : getUniqueKeys()) {
                    buildUniqueConstraintDeletionWriter(session, uniqueKey, schemaWriter);
                    writeLineSeperator(session, schemaWriter);
                }
            }
        }
    }

    /**
     * INTERNAL:
     * Execute the SQL alter table constraint creation string. Exceptions are caught and masked so that all
     * the foreign keys are dropped (even if they don't exist).
     */
    public void dropConstraintsOnDatabase(AbstractSession session) throws EclipseLinkException {
        dropForeignConstraintsOnDatabase(session);
        dropUniqueConstraintsOnDatabase(session);
    }

    private void dropUniqueConstraintsOnDatabase(final AbstractSession session) throws ValidationException {
        if ((!session.getPlatform().supportsUniqueKeyConstraints())
                || getUniqueKeys().isEmpty()
                || session.getPlatform().requiresUniqueConstraintCreationOnTableCreate()) {
            return;
        }

        for (UniqueKeyConstraint uniqueKey : getUniqueKeys()) {
            try {
                session.priviledgedExecuteNonSelectingCall(new SQLCall(buildUniqueConstraintDeletionWriter(session, uniqueKey, new StringWriter()).toString()));
            } catch (DatabaseException ex) {/* ignore */
            }
        }
    }

    private void dropForeignConstraintsOnDatabase(final AbstractSession session) throws ValidationException {
        if ((!session.getPlatform().supportsForeignKeyConstraints()) || getForeignKeyMap().isEmpty()) {
            return;
        }

        for (ForeignKeyConstraint foreignKey : getForeignKeyMap().values()) {
            try {
                session.priviledgedExecuteNonSelectingCall(new SQLCall(buildConstraintDeletionWriter(session, foreignKey, new StringWriter()).toString()));
            } catch (DatabaseException ex) {/* ignore */
            }
        }
    }

    /**
     * INTERNAL:<br>
     * Write the SQL drop index string to drop indexes if passed a writer,
     * else delegate to a method that executes the string on the database.
     * @throws ValidationException wraps any IOException from the writer
     */
    public void dropIndexes(AbstractSession session, Writer writer) {
        if (!session.getPlatform().supportsIndexes()) {
            return;
        }
        // Primary key
        if (session.getPlatform().shouldCreateIndicesForPrimaryKeys()) {
            List<String> primKeyList = getPrimaryKeyFieldNames();
            if (!primKeyList.isEmpty()) {
                IndexDefinition index = buildIndex(session, primKeyList.get(0), primKeyList, false);
                if (writer == null) {
                    try {
                        index.dropFromDatabase(session);
                    } catch (Exception notThere) {
                        //ignore
                    }
                } else {
                    index.buildDeletionWriter(session, writer);
                    writeLineSeperator(session, writer);
                }
            }
        }
        // Unique keys
        if (session.getPlatform().shouldCreateIndicesOnUniqueKeys()) {
            // indices for columns in unique key constraint declarations
            for (UniqueKeyConstraint uniqueKey : getUniqueKeys()) {
                IndexDefinition index = buildIndex(session, uniqueKey.getName(), uniqueKey.getSourceFields(), false);
                if (writer == null) {
                    try {
                        index.dropFromDatabase(session);
                    } catch (Exception notThere) {
                        //ignore
                    }
                } else {
                    index.buildDeletionWriter(session, writer);
                    writeLineSeperator(session, writer);
                }
            }

            // indices for columns with unique=true declarations
            for (FieldDefinition field : getFields()) {
                if (field.isUnique()) {
                    List<String> columnAsList = new ArrayList<>();
                    columnAsList.add(field.getName());
                    IndexDefinition index = buildIndex(session, field.getName(), columnAsList, true);
                    if (writer == null) {
                        try {
                            index.dropFromDatabase(session);
                        } catch (Exception notThere) {
                            //ignore
                        }
                    } else {
                        index.buildDeletionWriter(session, writer);
                        writeLineSeperator(session, writer);
                    }
                }
            }
        }
        // Foreign keys
        if (session.getPlatform().shouldCreateIndicesOnForeignKeys()) {
            // indices for columns in foreign key constraint declarations
            for (ForeignKeyConstraint foreignKey : getForeignKeys()) {
                if (!foreignKey.isDisableForeignKey()) {
                    // Do not re-index pk.
                    boolean alreadyIndexed = false;
                    List<String> primaryKeys = getPrimaryKeyFieldNames();
                    if ((primaryKeys.size() == foreignKey.getSourceFields().size())
                            && primaryKeys.containsAll(foreignKey.getSourceFields())) {
                        alreadyIndexed = true;
                    }
                    // Also check unique fields.
                    if (foreignKey.getSourceFields().size() == 1) {
                        FieldDefinition field = getField(foreignKey.getSourceFields().get(0));
                        if ((field != null) && field.isUnique()) {
                            alreadyIndexed = true;
                        }
                    }
                    for (UniqueKeyConstraint uniqueConstraint : getUniqueKeys()) {
                        if ((uniqueConstraint.getSourceFields().size() == foreignKey.getSourceFields().size())
                                && uniqueConstraint.getSourceFields().containsAll(foreignKey.getSourceFields())) {
                            alreadyIndexed = true;
                        }
                    }
                    if (!alreadyIndexed) {
                        IndexDefinition index = buildIndex(session, foreignKey.getName(), foreignKey.getSourceFields(), false);
                        if (writer == null) {
                            try {
                                index.dropFromDatabase(session);
                            } catch (Exception notThere) {
                                //ignore
                            }
                        } else {
                            index.buildDeletionWriter(session, writer);
                            writeLineSeperator(session, writer);
                        }
                    }
                }
            }
        }
        // Indexes
        for (IndexDefinition index : getIndexes()) {
            if (writer == null) {
                try {
                    index.dropFromDatabase(session);
                } catch (Exception notThere) {
                    //ignore
                }
            } else {
                index.buildDeletionWriter(session, writer);
                writeLineSeperator(session, writer);
            }
        }
    }

    /**
     * INTERNAL:
     */
    public Map<String, ForeignKeyConstraint> getForeignKeyMap() {
        return foreignKeyMap;
    }

    /**
     * INTERNAL:
     */
    public void setForeignKeyMap(Map<String, ForeignKeyConstraint> foreignKeyMap) {
        this.foreignKeyMap = foreignKeyMap;
    }

    /**
     * PUBLIC:
     * Return the field the corresponds to the name.
     */
    public FieldDefinition getField(String fieldName) {
        for (FieldDefinition field : getFields()) {
            if (field.getName().equals(fieldName)) {
                return field;
            }
        }
        return null;
    }

    /**
     * PUBLIC:
     */
    public List<FieldDefinition> getFields() {
        return fields;
    }

    /**
     * PUBLIC:
     * Returns the ForeignKeyConstraint list.
     */
    public Collection<ForeignKeyConstraint> getForeignKeys() {
        return this.foreignKeyMap.values();
    }

    /**
     * PUBLIC:
     */
    public List<UniqueKeyConstraint> getUniqueKeys() {
        return uniqueKeys;
    }

    /**
     * PUBLIC:
     */
    public void setIndexes(List<IndexDefinition> indexes) {
        this.indexes = indexes;
    }

    /**
     * PUBLIC:
     */
    public void setCreateVPDCalls(boolean createVPDCalls, String tenantFieldName) {
        this.createVPDCalls = createVPDCalls;
        this.tenantFieldName = tenantFieldName;
    }

    /**
     * PUBLIC:
     */
    public List<IndexDefinition> getIndexes() {
        return indexes;
    }

    /**
     * PUBLIC:
     */
    public List<String> getPrimaryKeyFieldNames() {
        List<String> keyNames = new ArrayList<>();

        for (FieldDefinition field : getFields()) {
            if (field.isPrimaryKey()) {
                keyNames.add(field.getName());
            }
        }
        return keyNames;
    }


    /**
     * Execute any statements required after the creation of the object
     */
    @Override
    public void postCreateObject(AbstractSession session, Writer createSchemaWriter, boolean createSQLFiles){
        // create indices on table's primary and unique keys (if required)
        setCreateSQLFiles(createSQLFiles);
        createIndexes(session, createSchemaWriter);
    }

    /**
     * Execute any statements required before the deletion of the object
     */
    @Override
    public void preDropObject(AbstractSession session, Writer dropSchemaWriter, boolean createSQLFiles) {
        // drop indices on table's primary and unique keys (if required)
        setCreateSQLFiles(createSQLFiles);
        dropIndexes(session, dropSchemaWriter);
    }

    /**
     * PUBLIC:
     */
    public void setFields(List<FieldDefinition> fields) {
        this.fields = fields;
    }

    /**
     * PUBLIC:
     * Set the ForeignKeyConstraint list.
     * If the list contains the same name foreign key constraints, only the first one of that name will be added.
     */
    public void setForeignKeys(List<ForeignKeyConstraint> foreignKeys) {
        this.foreignKeyMap.clear();
        if (foreignKeys != null) {
            for( ForeignKeyConstraint foreignKey : foreignKeys) {
                this.foreignKeyMap.put(foreignKey.getName(), foreignKey);
            }
        }
    }

    /**
     * PUBLIC:
     */
    public void setUniqueKeys(List<UniqueKeyConstraint> uniqueKeys) {
        this.uniqueKeys = uniqueKeys;
    }

    /**
     * PUBLIC:
     * Set the foreign key constraints for this table.
     */
    public void setUserDefinedForeignKeyConstraints(Map<String, ForeignKeyConstraint> foreignKeyConstraints) {
        foreignKeyMap = foreignKeyConstraints;
        hasUserDefinedForeignKeyConstraints = true;
    }

    /**
     * If this table has a schema (and catalog specified) make sure it is
     * created.
     */
    @Override
    public boolean shouldCreateDatabaseSchema(Set<String> createdDatabaseSchemas) {
        return hasDatabaseSchema() && ! createdDatabaseSchemas.contains(getDatabaseSchema());
    }

    /**
     * INTERNAL:
     * Subclasses who care should override this method.
     */
    @Override
    public boolean shouldCreateVPDCalls(AbstractSession session) {
        if (createVPDCalls) {
            if (! session.getPlatform().supportsVPD()) {
                throw ValidationException.vpdNotSupported(session.getPlatform().getClass().getName());
            }
        }

        return createVPDCalls;
    }

    /**
     * PUBLIC:
     */
    public void setCreateSQLFiles(boolean genFlag) {
        this.createSQLFiles = genFlag;
    }

    public DatabaseTable getTable() {
        return table;
    }

    public void setTable(DatabaseTable table) {
        this.table = table;
    }
}
