package org.apache.ddlutils.model;

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

import java.io.Serializable;
import java.text.Collator;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Collection;

import org.apache.commons.collections.Predicate;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;

/**
 * Represents a table in the database model.
 * 
 * @version $Revision$
 */
public class Table implements Serializable
{
    /** Unique ID for serialization purposes. */
    private static final long serialVersionUID = -5541154961302342608L;

    /** The catalog of this table as read from the database. */
    private String _catalog = null;
    /** The table's schema. */
    private String _schema = null;
    /** The name. */
    private String _name = null;
    /** A description of the table. */
    private String _description = null;
    /** The table's type as read from the database. */
    private String _type = null;
    /** The columns in this table. */
    private ArrayList _columns = new ArrayList();
    /** The foreign keys associated to this table. */
    private ArrayList _foreignKeys = new ArrayList();
    /** The indices applied to this table. */
    private ArrayList _indices = new ArrayList();

    /**
     * Returns the catalog of this table as read from the database.
     * 
     * @return The catalog
     */
    public String getCatalog()
    {
        return _catalog;
    }

    /**
     * Sets the catalog of this table.
     * 
     * @param catalog The catalog
     */
    public void setCatalog(String catalog)
    {
        _catalog = catalog;
    }

    /**
     * Returns the schema of this table as read from the database.
     * 
     * @return The schema
     */
    public String getSchema()
    {
        return _schema;
    }

    /**
     * Sets the schema of this table.
     * 
     * @param schema The schema
     */
    public void setSchema(String schema)
    {
        _schema = schema;
    }

    /**
     * Returns the type of this table as read from the database.
     * 
     * @return The type
     */
    public String getType()
    {
        return _type;
    }

    /**
     * Sets the type of this table.
     * 
     * @param type The type
     */
    public void setType(String type)
    {
        _type = type;
    }

    /**
     * Returns the name of the table.
     * 
     * @return The name
     */
    public String getName()
    {
        return _name;
    }

    /**
     * Sets the name of the table.
     * 
     * @param name The name
     */
    public void setName(String name)
    {
        _name = name;
    }

    /**
     * Returns the description of the table.
     *
     * @return The description
     */
    public String getDescription()
    {
        return _description;
    }

    /**
     * Sets the description of the table.
     *
     * @param description The description
     */
    public void setDescription(String description)
    {
        _description = description;
    }

    /**
     * Returns the number of columns in this table.
     * 
     * @return The number of columns
     */
    public int getColumnCount()
    {
        return _columns.size();
    }

    /**
     * Returns the column at the specified position.
     * 
     * @param idx The column index
     * @return The column at this position
     */
    public Column getColumn(int idx)
    {
        return (Column)_columns.get(idx);
    }

    /**
     * Returns the columns in this table.
     * 
     * @return The columns
     */
    public Column[] getColumns()
    {
        return (Column[])_columns.toArray(new Column[_columns.size()]);
    }

    /**
     * Adds the given column.
     * 
     * @param column The column
     */
    public void addColumn(Column column)
    {
        if (column != null)
        {
            _columns.add(column);
        }
    }

    /**
     * Adds the given column at the specified position.
     * 
     * @param idx    The index where to add the column
     * @param column The column
     */
    public void addColumn(int idx, Column column)
    {
        if (column != null)
        {
            _columns.add(idx, column);
        }
    }

    /**
     * Adds the column after the given previous column.
     * 
     * @param previousColumn The column to add the new column after; use
     *                       <code>null</code> for adding at the begin
     * @param column         The column
     */
    public void addColumn(Column previousColumn, Column column)
    {
        if (column != null)
        {
            if (previousColumn == null)
            {
                _columns.add(0, column);
            }
            else
            {
                _columns.add(_columns.indexOf(previousColumn), column);
            }
        }
    }

    /**
     * Adds the given columns.
     * 
     * @param columns The columns
     */
    public void addColumns(Collection columns)
    {
        for (Iterator it = columns.iterator(); it.hasNext();)
        {
            addColumn((Column)it.next());
        }
    }

    /**
     * Removes the given column.
     * 
     * @param column The column to remove
     */
    public void removeColumn(Column column)
    {
        if (column != null)
        {
            _columns.remove(column);
        }
    }

    /**
     * Removes all columns of this table. Note that this does not change
     * indexes or foreign keys, so it might leave the table object in
     * an illegal state.
     */
    public void removeAllColumns()
    {
        _columns.clear();
    }

    /**
     * Removes the indicated column.
     * 
     * @param idx The index of the column to remove
     */
    public void removeColumn(int idx)
    {
        _columns.remove(idx);
    }

    /**
     * Returns the number of foreign keys.
     * 
     * @return The number of foreign keys
     */
    public int getForeignKeyCount()
    {
        return _foreignKeys.size();
    }

    /**
     * Returns the foreign key at the given position.
     * 
     * @param idx The foreign key index
     * @return The foreign key
     */
    public ForeignKey getForeignKey(int idx)
    {
        return (ForeignKey)_foreignKeys.get(idx);
    }

    /**
     * Returns the foreign keys of this table.
     * 
     * @return The foreign keys
     */
    public ForeignKey[] getForeignKeys()
    {
        return (ForeignKey[])_foreignKeys.toArray(new ForeignKey[_foreignKeys.size()]);
    }

    /**
     * Adds the given foreign key.
     * 
     * @param foreignKey The foreign key
     */
    public void addForeignKey(ForeignKey foreignKey)
    {
        if (foreignKey != null)
        {
            _foreignKeys.add(foreignKey);
        }
    }

    /**
     * Adds the given foreign key at the specified position.
     * 
     * @param idx        The index to add the foreign key at
     * @param foreignKey The foreign key
     */
    public void addForeignKey(int idx, ForeignKey foreignKey)
    {
        if (foreignKey != null)
        {
            _foreignKeys.add(idx, foreignKey);
        }
    }

    /**
     * Adds the given foreign keys.
     * 
     * @param foreignKeys The foreign keys
     */
    public void addForeignKeys(Collection foreignKeys)
    {
        for (Iterator it = foreignKeys.iterator(); it.hasNext();)
        {
            addForeignKey((ForeignKey)it.next());
        }
    }

    /**
     * Removes all foreign keys.
     */
    public void removeAllForeignKeys()
    {
        _foreignKeys.clear();
    }

    /**
     * Removes the given foreign key.
     * 
     * @param foreignKey The foreign key to remove
     */
    public void removeForeignKey(ForeignKey foreignKey)
    {
        if (foreignKey != null)
        {
            _foreignKeys.remove(foreignKey);
        }
    }

    /**
     * Removes the indicated foreign key.
     * 
     * @param idx The index of the foreign key to remove
     */
    public void removeForeignKey(int idx)
    {
        _foreignKeys.remove(idx);
    }

    /**
     * Returns the number of indices.
     * 
     * @return The number of indices
     */
    public int getIndexCount()
    {
        return _indices.size();
    }

    /**
     * Returns the index at the specified position.
     * 
     * @param idx The position
     * @return The index
     */
    public Index getIndex(int idx)
    {
        return (Index)_indices.get(idx);
    }

    /**
     * Adds the given index.
     * 
     * @param index The index
     */
    public void addIndex(Index index)
    {
        if (index != null)
        {
            _indices.add(index);
        }
    }

    /**
     * Adds the given index at the specified position.
     * 
     * @param idx   The position to add the index at
     * @param index The index
     */
    public void addIndex(int idx, Index index)
    {
        if (index != null)
        {
            _indices.add(idx, index);
        }
    }

    /**
     * Adds the given indices.
     * 
     * @param indices The indices
     */
    public void addIndices(Collection indices)
    {
        for (Iterator it = indices.iterator(); it.hasNext();)
        {
            addIndex((Index)it.next());
        }
    }

    /**
     * Returns the indices of this table.
     * 
     * @return The indices
     */
    public Index[] getIndices()
    {
        return (Index[])_indices.toArray(new Index[_indices.size()]);
    }

    /**
     * Gets a list of non-unique indices on this table.
     * 
     * @return The unique indices
     */
    public Index[] getNonUniqueIndices()
    {
        Collection nonUniqueIndices = CollectionUtils.select(_indices, new Predicate() {
            public boolean evaluate(Object input) {
                return !((Index)input).isUnique();
            }
        });

        return (Index[])nonUniqueIndices.toArray(new Index[nonUniqueIndices.size()]);
    }

    /**
     * Gets a list of unique indices on this table.
     * 
     * @return The unique indices
     */
    public Index[] getUniqueIndices()
    {
        Collection uniqueIndices = CollectionUtils.select(_indices, new Predicate() {
            public boolean evaluate(Object input) {
                return ((Index)input).isUnique();
            }
        });

        return (Index[])uniqueIndices.toArray(new Index[uniqueIndices.size()]);
    }

    /**
     * Removes the given index.
     * 
     * @param index The index to remove
     */
    public void removeIndex(Index index)
    {
        if (index != null)
        {
            _indices.remove(index);
        }
    }

    /**
     * Removes the indicated index.
     * 
     * @param idx The position of the index to remove
     */
    public void removeIndex(int idx)
    {
        _indices.remove(idx);
    }

    // Helper methods
    //-------------------------------------------------------------------------

    /**
     * Determines whether there is at least one primary key column on this table.
     * 
     * @return <code>true</code> if there are one or more primary key columns
     */
    public boolean hasPrimaryKey()
    {
        for (Iterator it = _columns.iterator(); it.hasNext(); )
        {
            Column column = (Column)it.next();

            if (column.isPrimaryKey())
            {
                return true;
            }
        }
        return false;
    }

    /**
     * Finds the column with the specified name, using case insensitive matching.
     * Note that this method is not called getColumn(String) to avoid introspection
     * problems.
     * 
     * @param name The name of the column
     * @return The column or <code>null</code> if there is no such column
     */
    public Column findColumn(String name)
    {
        return findColumn(name, false);
    }

    /**
     * Finds the column with the specified name, using case insensitive matching.
     * Note that this method is not called getColumn(String) to avoid introspection
     * problems.
     * 
     * @param name          The name of the column
     * @param caseSensitive Whether case matters for the names
     * @return The column or <code>null</code> if there is no such column
     */
    public Column findColumn(String name, boolean caseSensitive)
    {
        for (Iterator it = _columns.iterator(); it.hasNext(); )
        {
            Column column = (Column)it.next();

            if (caseSensitive)
            {
                if (column.getName().equals(name))
                {
                    return column;
                }
            }
            else
            {
                if (column.getName().equalsIgnoreCase(name))
                {
                    return column;
                }
            }
        }
        return null;
    }

    /**
     * Determines the index of the given column.
     * 
     * @param column The column
     * @return The index or <code>-1</code> if it is no column of this table
     */
    public int getColumnIndex(Column column)
    {
        int idx = 0;

        for (Iterator it = _columns.iterator(); it.hasNext(); idx++)
        {
            if (column == it.next())
            {
                return idx;
            }
        }
        return -1;
    }

    /**
     * Finds the index with the specified name, using case insensitive matching.
     * Note that this method is not called getIndex to avoid introspection
     * problems.
     * 
     * @param name The name of the index
     * @return The index or <code>null</code> if there is no such index
     */
    public Index findIndex(String name)
    {
        return findIndex(name, false);
    }

    /**
     * Finds the index with the specified name, using case insensitive matching.
     * Note that this method is not called getIndex to avoid introspection
     * problems.
     * 
     * @param name          The name of the index
     * @param caseSensitive Whether case matters for the names
     * @return The index or <code>null</code> if there is no such index
     */
    public Index findIndex(String name, boolean caseSensitive)
    {
        for (int idx = 0; idx < getIndexCount(); idx++)
        {
            Index index = getIndex(idx);

            if (caseSensitive)
            {
                if (index.getName().equals(name))
                {
                    return index;
                }
            }
            else
            {
                if (index.getName().equalsIgnoreCase(name))
                {
                    return index;
                }
            }
        }
        return null;
    }

    /**
     * Finds the foreign key in this table that is equal to the supplied foreign key.
     * 
     * @param key The foreign key to search for
     * @return The found foreign key
     */
    public ForeignKey findForeignKey(ForeignKey key)
    {
        for (int idx = 0; idx < getForeignKeyCount(); idx++)
        {
            ForeignKey fk = getForeignKey(idx);

            if (fk.equals(key))
            {
                return fk;
            }
        }
        return null;
    }

    /**
     * Finds the foreign key in this table that is equal to the supplied foreign key.
     * 
     * @param key           The foreign key to search for
     * @param caseSensitive Whether case matters for the names
     * @return The found foreign key
     */
    public ForeignKey findForeignKey(ForeignKey key, boolean caseSensitive)
    {
        for (int idx = 0; idx < getForeignKeyCount(); idx++)
        {
            ForeignKey fk = getForeignKey(idx);

            if ((caseSensitive  && fk.equals(key)) ||
                (!caseSensitive && fk.equalsIgnoreCase(key)))
            {
                return fk;
            }
        }
        return null;
    }

    /**
     * Returns the foreign key referencing this table if it exists.
     * 
     * @return The self-referencing foreign key if any
     */
    public ForeignKey getSelfReferencingForeignKey()
    {
        for (int idx = 0; idx < getForeignKeyCount(); idx++)
        {
            ForeignKey fk = getForeignKey(idx);

            if (this.equals(fk.getForeignTable()))
            {
                return fk;
            }
        }
        return null;
    }

    /**
     * Returns the primary key columns of this table.
     * 
     * @return The primary key columns
     */
    public Column[] getPrimaryKeyColumns()
    {
        Collection pkColumns = CollectionUtils.select(_columns, new Predicate() {
            public boolean evaluate(Object input) {
                return ((Column)input).isPrimaryKey();
            }
        });

        return (Column[])pkColumns.toArray(new Column[pkColumns.size()]);
    }

    /**
     * Returns the names of the primary key columns of this table.
     * 
     * @return The primary key column names
     */
    public String[] getPrimaryKeyColumnNames()
    {
        Column[] pkColumns = getPrimaryKeyColumns();
        String[] names     = new String[pkColumns.length];

        for (int colIdx = 0; colIdx < pkColumns.length; colIdx++)
        {
            names[colIdx] = pkColumns[colIdx].getName();
        }

        return names;
    }

    /**
     * Returns the auto increment columns in this table. If no incrementcolumns
     * are found, it will return an empty array.
     * 
     * @return The columns
     */
    public Column[] getAutoIncrementColumns()
    {
        Collection autoIncrColumns = CollectionUtils.select(_columns, new Predicate() {
            public boolean evaluate(Object input) {
                return ((Column)input).isAutoIncrement();
            }
        });

        return (Column[])autoIncrColumns.toArray(new Column[autoIncrColumns.size()]);
    }

    /**
     * Sorts the foreign keys alphabetically.
     * 
     * @param caseSensitive Whether case matters
     */
    public void sortForeignKeys(final boolean caseSensitive)
    {
        if (!_foreignKeys.isEmpty())
        {
            final Collator collator = Collator.getInstance();
    
            Collections.sort(_foreignKeys, new Comparator() {
                public int compare(Object obj1, Object obj2)
                {
                    String fk1Name = ((ForeignKey)obj1).getName();
                    String fk2Name = ((ForeignKey)obj2).getName();

                    if (!caseSensitive)
                    {
                        fk1Name = (fk1Name != null ? fk1Name.toLowerCase() : null);
                        fk2Name = (fk2Name != null ? fk2Name.toLowerCase() : null);
                    }
                    return collator.compare(fk1Name, fk2Name);
                }
            });
        }
    }
    
    /**
     * {@inheritDoc}
     */
    public boolean equals(Object obj)
    {
        if (obj instanceof Table)
        {
            Table other = (Table)obj;

            // Note that this compares case sensitive
            // TODO: For now we ignore catalog and schema (type should be irrelevant anyways)
            return new EqualsBuilder().append(_name,                     other._name)
                                      .append(_columns,                  other._columns)
                                      .append(new HashSet(_foreignKeys), new HashSet(other._foreignKeys))
                                      .append(new HashSet(_indices),     new HashSet(other._indices))
                                      .isEquals();
        }
        else
        {
            return false;
        }
    }

    /**
     * {@inheritDoc}
     */
    public int hashCode()
    {
        // TODO: For now we ignore catalog and schema (type should be irrelevant anyways)
        return new HashCodeBuilder(17, 37).append(_name)
                                          .append(_columns)
                                          .append(new HashSet(_foreignKeys))
                                          .append(new HashSet(_indices))
                                          .toHashCode();
    }

    /**
     * {@inheritDoc}
     */
    public String toString()
    {
        StringBuffer result = new StringBuffer();

        result.append("Table [name=");
        result.append(getName());
        result.append("; ");
        result.append(getColumnCount());
        result.append(" columns]");

        return result.toString();
    }

    /**
     * Returns a verbose string representation of this table.
     * 
     * @return The string representation
     */
    public String toVerboseString()
    {
        StringBuffer result = new StringBuffer();

        result.append("Table [name=");
        result.append(getName());
        result.append("; catalog=");
        result.append(getCatalog());
        result.append("; schema=");
        result.append(getCatalog());
        result.append("; type=");
        result.append(getType());
        result.append("] columns:");
        for (int idx = 0; idx < getColumnCount(); idx++)
        {
            result.append(" ");
            result.append(getColumn(idx).toVerboseString());
        }
        result.append("; indices:");
        for (int idx = 0; idx < getIndexCount(); idx++)
        {
            result.append(" ");
            result.append(getIndex(idx).toVerboseString());
        }
        result.append("; foreign keys:");
        for (int idx = 0; idx < getForeignKeyCount(); idx++)
        {
            result.append(" ");
            result.append(getForeignKey(idx).toVerboseString());
        }

        return result.toString();
    }
}
