/*
 * 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) {
        Vector sourceFields = new Vector();
        Vector 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<FieldDefinition>(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;
    }
}
