/*******************************************************************************
 * Copyright (c) 1998, 2012 Oracle. All rights reserved.
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
 * which accompanies this distribution.
 * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
 * and the Eclipse Distribution License is available at
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * Contributors:
 *     Oracle - initial API and implementation from Oracle TopLink
******************************************************************************/
package org.eclipse.persistence.tools.db.relational;

import java.util.Collection;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;
import org.eclipse.persistence.tools.db.relational.platformsmodel.DatabasePlatform;
import org.eclipse.persistence.tools.db.relational.spi.ExternalColumn;
import org.eclipse.persistence.tools.db.relational.spi.ExternalForeignKey;
import org.eclipse.persistence.tools.db.relational.spi.ExternalForeignKeyColumnPair;
import org.eclipse.persistence.tools.db.relational.spi.ExternalTable;
import org.eclipse.persistence.tools.db.relational.spi.ExternalTableDescription;
import org.eclipse.persistence.tools.utility.NameTools;
import org.eclipse.persistence.tools.utility.StringTools;
import org.eclipse.persistence.tools.utility.iterable.LiveCloneIterable;
import org.eclipse.persistence.tools.utility.iterator.CompositeIterator;
import org.eclipse.persistence.tools.utility.iterator.FilteringIterator;
import org.eclipse.persistence.tools.utility.iterator.TransformationIterator;
import org.eclipse.persistence.tools.utility.node.Node;

/**
 * @version 2.5
 */
@SuppressWarnings("nls")
public final class ELTable extends ELModel {

	/** the catalog should never be empty - it can be null, but not empty */
	private volatile String catalog;
		public static final String CATALOG_PROPERTY = "catalog";

	/** the schema should never be empty - it can be null, but not empty */
	private volatile String schema;
		public static final String SCHEMA_PROPERTY = "schema";

	/** the short name should never be null OR empty */
	private volatile String shortName;
		public static final String SHORT_NAME_PROPERTY = "shortName";

		public static final String QUALIFIED_NAME_PROPERTY = "qualifiedName";

	/** this will be null if it is not known */
	private Date lastRefreshTimestamp;
		public static final String LAST_REFRESH_TIMESTAMP_PROPERTY = "lastRefreshTimestamp";

	private Collection<ELColumn> columns;
		public static final String COLUMNS_COLLECTION = "columns";

	private Collection<ELReference> references;
		public static final String REFERENCES_COLLECTION = "references";

	private boolean legacyIsFullyQualified;

	// ********** constructors **********

	ELTable(ELDatabase database, String catalog, String schema, String shortName) {
		super(database);
		this.catalog = catalog;
		this.schema = schema;
		this.shortName = shortName;
	}


	// ********** initialization **********

	/**
	 * initialize persistent state
	 */
	@Override
	protected void initialize(Node parent) {
		super.initialize(parent);
		this.lastRefreshTimestamp = null;	// if the table is built by hand, this is left null
		this.columns = new Vector<ELColumn>();
		this.references = new Vector<ELReference>();
	}


	// ********** name: catalog, schema, shortName **********

	public String getCatalog() {
		return this.catalog;
	}

	/**
	 * private - @see #rename(String, String, String)
	 */
	private void setCatalog(String catalog) {
		Object old = this.catalog;
		this.catalog = catalog;
		if (this.attributeValueHasChanged(old, catalog)) {
			this.firePropertyChanged(CATALOG_PROPERTY, old, catalog);
			this.qualifiedNameChanged();
		}
	}

	public String getSchema() {
		return this.schema;
	}

	/**
	 * private - @see #rename(String, String, String)
	 */
	private void setSchema(String schema) {
		Object old = this.schema;
		this.schema = schema;
		if (this.attributeValueHasChanged(old, schema)) {
			this.firePropertyChanged(SCHEMA_PROPERTY, old, schema);
			this.qualifiedNameChanged();
		}
	}

	public String getShortName() {
		return this.shortName;
	}

	/**
	 * private - @see #rename(String, String, String)
	 */
	private void setShortName(String shortName) {
		Object old = this.shortName;
		this.shortName = shortName;
		if (this.attributeValueHasChanged(old, shortName)) {
			this.firePropertyChanged(SHORT_NAME_PROPERTY, old, shortName);
			this.qualifiedNameChanged();
		}
	}

	private void qualifiedNameChanged() {
		this.firePropertyChanged(QUALIFIED_NAME_PROPERTY, this.qualifiedName());
		this.getParent().nodeRenamed(this);
		for (ELColumn column : this.columns()) {
			column.qualifiedNameChanged();
		}
	}


	// ********** columns **********

	/**
	 * this will be null if it is not known
	 */
	public Date getLastRefreshTimestamp() {
		return this.lastRefreshTimestamp;
	}

	/**
	 * PRIVATE - this can only be set internally
	 */
	private void setLastRefreshTimestamp(Date lastRefreshTimestamp) {
		Object old = this.lastRefreshTimestamp;
		this.lastRefreshTimestamp = lastRefreshTimestamp;
		this.firePropertyChanged(LAST_REFRESH_TIMESTAMP_PROPERTY, old, lastRefreshTimestamp);
	}


	// ********** columns **********

	public Iterable<ELColumn> columns() {
		return new LiveCloneIterable<ELColumn>(this.columns) {
			@Override
			protected void remove(ELColumn current) {
				ELTable.this.removeColumn(current);
			}
		};
	}

	public int columnsSize() {
		return this.columns.size();
	}

	public ELColumn addColumn(String name) {
		this.checkColumnName(name);
		return this.addColumn(new ELColumn(this, name));
	}

	private ELColumn addColumn(ELColumn column) {
		this.addItemToCollection(column, this.columns, COLUMNS_COLLECTION);
		return column;
	}

	public void removeColumn(ELColumn column) {
		this.removeNodeFromCollection(column, this.columns, COLUMNS_COLLECTION);
	}

	public void removeColumns(Iterator<ELColumn> cols) {
		while (cols.hasNext()) {
			this.removeColumn(cols.next());
		}
	}

	public void removeColumns(Collection<ELColumn> cols) {
		this.removeColumns(cols.iterator());
	}

	public boolean containsColumnNamed(String columnName) {
		return this.columnNamed(columnName) != null;
	}

	/**
	 * only used for unqualified column names
	 * @see #columnWithQualifiedName(String qualifiedName)
	 */
	public ELColumn columnNamed(String unqualifiedColumnName) {
		synchronized (this.columns) {
			for (Iterator<ELColumn> stream = this.columns.iterator(); stream.hasNext(); ) {
				ELColumn column = stream.next();
				if (column.getName().equals(unqualifiedColumnName)) {
					return column;
				}
			}
		}
		return null;
	}

	/**
	 * Returns the column with the specified "qualified" name
	 */
	public ELColumn columnWithQualifiedName(String name) {
		if ( ! ELColumn.parseTableNameFromQualifiedName(name).equals(this.getName())) {
			throw new IllegalArgumentException();
		}
		return this.columnNamed(ELColumn.parseColumnNameFromQualifiedName(name));
	}

	public Iterator<String> columnNames() {
		return new TransformationIterator<ELColumn, String>(this.columns()) {
			@Override
			protected String transform(ELColumn next) {
				return next.getName();
			}
		};
	}

	public int primaryKeyColumnsSize() {
		int size = 0;
		synchronized (this.columns) {
			for (ELColumn column : this.columns) {
				if (column.isPrimaryKey()) {
					size++;
				}
			}
		}
		return size;
	}

	public Iterator<ELColumn> primaryKeyColumns() {
		return new FilteringIterator<ELColumn>(this.columns()) {
			@Override
			protected boolean accept(ELColumn o) {
				return o.isPrimaryKey();
			}
		};
	}

	public Iterator<String> primaryKeyColumnNames() {
		return new TransformationIterator<ELColumn, String>(this.primaryKeyColumns()) {
			@Override
			protected String transform(ELColumn next) {
				return next.getName();
			}
		};
	}

	public Iterator<ELColumn> nonPrimaryKeyColumns() {
		return new FilteringIterator<ELColumn>(this.columns()) {
			@Override
			protected boolean accept(ELColumn o) {
				return ! o.isPrimaryKey();
			}
		};
	}

	/**
	 * used by table generation
	 */
	public ELColumn addColumnLike(ELColumn original) {
		ELColumn copy = this.addColumn(original.getName());
		copy.copySettingsFrom(original);
		return copy;
	}


	// ********** references **********

	public Iterable<ELReference> references() {
		return new LiveCloneIterable<ELReference>(this.references) {
			@Override
			protected void remove(ELReference current) {
				ELTable.this.removeReference(current);
			}
		};
	}

	public int referencesSize() {
		return this.references.size();
	}

	public ELReference addReference(String name, ELTable targetTable) {
		this.checkReferenceName(name);
		return this.addReference(new ELReference(this, name, targetTable));
	}

	private ELReference addReference(ELReference reference) {
		this.addItemToCollection(reference, this.references, REFERENCES_COLLECTION);
		return reference;
	}

	public void removeReference(ELReference reference) {
		this.removeNodeFromCollection(reference, this.references, REFERENCES_COLLECTION);
	}

	public void removeReferences(Iterator<ELReference> refs) {
		while (refs.hasNext()) {
			this.removeReference(refs.next());
		}
	}

	public void removeReferences(Collection<ELReference> refs) {
		this.removeReferences(refs.iterator());
	}

	/**
	 * remove only the references among those specified
	 * that are defined on the database; leave any "virtual"
	 * user-defined references
	 */
	private void removeDatabaseReferences(Iterator<ELReference> refs) {
		while (refs.hasNext()) {
			ELReference ref = refs.next();
			if (ref.isOnDatabase()) {
				this.removeReference(ref);
			}
		}
	}

	/**
	 * remove only the references among those specified
	 * that are defined on the database; leave any "virtual"
	 * user-defined references
	 */
	private void removeDatabaseReferences(Collection<ELReference> refs) {
		this.removeDatabaseReferences(refs.iterator());
	}

	public boolean containsReferenceNamed(String referenceName) {
		return this.referenceNamed(referenceName) != null;
	}

	public ELReference referenceNamed(String referenceName) {
		synchronized (this.references) {
			for (Iterator<ELReference> stream = this.references.iterator(); stream.hasNext(); ) {
				ELReference reference = stream.next();
				if (reference.getName().equals(referenceName)) {
					return reference;
				}
			}
			return null;
		}
	}

	public Iterator<String> referenceNames(){
		return new TransformationIterator<ELReference, String>(this.references()) {
			@Override
			protected String transform(ELReference next) {
				return next.getName();
			}
		};
	}

	/**
	 * Returns the references that are actually present
	 * as constraints on the database
	 */
	public Iterator<ELReference> databaseReferences() {
		return new FilteringIterator<ELReference>(this.references()) {
			@Override
			protected boolean accept(ELReference o) {
				return o.isOnDatabase();
			}
		};
	}

	/**
	 * Returns all the references between the table and the
	 * specified table (either table can be the source and/or target)
	 */
	@SuppressWarnings("unchecked")
	public Iterator<ELReference> referencesBetween(ELTable table) {
		return new CompositeIterator<ELReference>(
			this.referencesTo(table),
			table.referencesTo(this)
		);
	}

	/**
	 * Returns all the references with the table as the source and the
	 * specified table as the target
	 */
	public Iterator<ELReference> referencesTo(final ELTable targetTable) {
		return new FilteringIterator<ELReference>(this.references()) {
			@Override
			protected boolean accept(ELReference o) {
				return o.getTargetTable() == targetTable;
			}
		};
	}


	// ********** Nominative implementation **********

	/**
	 * Returns the appropriately-qualified name
	 */
	public String getName() {
		return this.qualifiedName();
	}

	//  ********** queries **********

	public DatabasePlatform databasePlatform() {
		 return this.getParent().getDatabasePlatform();
	}

	boolean nameMatches(String cat, String sch, String sn) {
		return this.valuesAreEqual(this.catalog, cat) &&
			this.valuesAreEqual(this.schema, sch) &&
			this.valuesAreEqual(this.shortName, sn);
	}

	boolean nameMatchesIgnoreCase(String cat, String sch, String sn) {
		return StringTools.equalsIgnoreCase(this.catalog, cat) &&
		       StringTools.equalsIgnoreCase(this.schema, sch) &&
		       StringTools.equalsIgnoreCase(this.shortName, sn);
	}

	/**
	 * if either the 'catalog' or 'schema' are specified,
	 * the table's name is "qualified"
	 */
	public boolean nameIsQualified() {
		if (this.catalog != null) {
			return true;
		}
		if (this.schema != null) {
			return true;
		}
		return false;
	}

	public boolean nameIsUnqualified() {
		return ! this.nameIsQualified();
	}

	public String qualifiedName() {
		return NameTools.buildQualifiedName(this.catalog, this.schema, this.shortName);
	}

	public String unqualifiedName() {
		return this.shortName;
	}

	/**
	 * used for table generation:
	 *     catalog.schema
	 *     catalog.
	 *     schema
	 */
	private String qualifier() {
		if (this.nameIsUnqualified()) {
			return StringTools.EMPTY_STRING;
		}
		StringBuffer sb = new StringBuffer(100);
		if (this.catalog != null) {
			sb.append(this.catalog);
		}
		if (this.schema != null) {
			if (this.catalog != null) {
			sb.append('.');
		}
			sb.append(this.schema);
		}
		return sb.toString();
	}


	// ********** miscellaneous behavior **********

	/**
	 * {@inheritDoc}
	 */
	@Override
	public ELDatabase getParent() {
		return (ELDatabase)super.getParent();
	}

	@Override
	protected void addChildrenTo(List<Node> children) {
		super.addChildrenTo(children);
		synchronized (this.columns) { children.addAll(this.columns); }
		synchronized (this.references) { children.addAll(this.references); }
	}

	public void rename(String newCatalog, String newSchema, String newShortName) {
		if (this.nameMatches(newCatalog, newSchema, newShortName)) {
			// if someone is tryng to rename a table to its existing name, ignore it
			return;
		}
		this.getParent().checkTableName(newCatalog, newSchema, newShortName, this);
		this.setCatalog(newCatalog);
		this.setSchema(newSchema);
		this.setShortName(newShortName);
	}

	/**
	 * disallow duplicate column names
	 */
	void checkColumnName(String columnName) {
		if ((columnName == null) || (columnName.length() == 0)) {
			throw new IllegalArgumentException();
		}
		if (this.containsColumnNamed(columnName)) {
			throw new IllegalArgumentException("duplicate column name: " + columnName);
		}
	}

	/**
	 * disallow duplicate reference names
	 */
	void checkReferenceName(String referenceName) {
		if ((referenceName == null) || (referenceName.length() == 0)) {
			throw new IllegalArgumentException();
		}
		if (this.containsReferenceNamed(referenceName)) {
			throw new IllegalArgumentException("duplicate reference name: " + referenceName);
		}
	}

	void databasePlatformChanged() {
		synchronized (this.columns) {
			for (Iterator<ELColumn> stream = this.columns.iterator(); stream.hasNext(); ) {
				stream.next().databasePlatformChanged();
			}
		}
	}


	// ********** importing/refreshing **********

	/**
	 * Returns the "external" table descriptions that share the table's name;
	 * Returns multiple entries only when the table's name
	 * is unqualified
	 */
	public Iterator<ExternalTableDescription> matchingExternalTableDescriptions() {
		return this.getParent().externalTableDescriptions(this.catalog, this.schema, this.shortName, null);
	}

	/**
	 * refresh the table's columns (but not the table's references - that
	 * must be performed separately);
	 */
	void refreshColumns(ExternalTable externalTable) {
		// after we have looped through the external columns,
		// 'removedColumns' will be left with the columns that need to be removed
		Collection<ELColumn> removedColumns;
		synchronized (this.columns) {
			removedColumns = new HashSet<ELColumn>(this.columns);
		}
		ExternalColumn[] externalColumns = externalTable.getColumns();
		for (int i = externalColumns.length; i-- > 0; ) {
			this.refreshColumn(externalColumns[i], removedColumns);
		}
		this.removeColumns(removedColumns);
		this.setLastRefreshTimestamp(new Date());
	}

	/**
	 * refresh the column corresponding to the specified "external" column
	 */
	private void refreshColumn(ExternalColumn externalColumn, Collection<ELColumn> removedColumns) {
		ELColumn existingColumn = this.columnNamed(externalColumn.getName());
		if (existingColumn == null) {
			// we have a new column
			existingColumn = this.addColumn(externalColumn.getName());
		} else {
			// retain the existing column
			removedColumns.remove(existingColumn);
		}
		existingColumn.refresh(externalColumn);
	}

	/**
	 * refresh the table's references - this should be called after
	 * the table's columns have been refreshed and any target tables
	 * have had their columns refreshed - this will allow us to build
	 * the references properly
	 */
	void refreshReferences(ExternalTable externalTable) {
		// after we have looped through the foreign keys,
		// 'removedReferences' will be left with the references that need to be removed
		Collection<ELReference> removedReferences;
		synchronized (this.references) {
			removedReferences = new HashSet<ELReference>(this.references);
		}
		ExternalForeignKey[] externalForeignKeys = externalTable.getForeignKeys();
		for (int i = externalForeignKeys.length; i-- > 0; ) {
			this.refreshReference(externalForeignKeys[i], removedReferences);
		}

		// remove *only* the remaining references that were originally defined on the database;
		// leave the "virtual" user-defined references intact
		this.removeDatabaseReferences(removedReferences);
	}

	/**
	 * refresh the reference corresponding to the specified "external" foreign key;
	 * search the 'removedReferences' so that we don't ever
	 * refresh the same reference twice; first search for a match based
	 * on name, then search for a match based on the column pairs - this
	 * should prevent us from getting a match based on columns that has
	 * the same name as another reference with different columns that
	 * is further down the list
	 */
	private void refreshReference(ExternalForeignKey externalForeignKey, Collection<ELReference> removedReferences) {
		// first, find the target table
		ExternalTableDescription ttd = externalForeignKey.getTargetTableDescription();
		ELTable targetTable = this.getParent().tableNamed(ttd.getCatalogName(), ttd.getSchemaName(), ttd.getName());
		if (targetTable == null) {
			// the target table may have been imported without
			// a fully-qualified name, so try that also
			targetTable = this.getParent().tableNamed(null, null, ttd.getName());
		}
		// if we don't have the target table, we can't build a reference to it
		if (targetTable == null) {
			return;
		}

		// look for a match based on name
		for (Iterator<ELReference> stream = removedReferences.iterator(); stream.hasNext(); ) {
			ELReference ref = stream.next();
			if (ref.getName().equals(externalForeignKey.getName())) {
				ref.setTargetTable(targetTable);
				ref.refreshColumnPairs(externalForeignKey);
				ref.setOnDatabase(true);
				removedReferences.remove(ref);
				return;
			}
		}

		// look for a match based on column pairs
		for (Iterator<ELReference> stream = removedReferences.iterator(); stream.hasNext(); ) {
			ELReference ref = stream.next();
			if (ref.matchesColumnPairs(externalForeignKey)) {
				ref.setName(externalForeignKey.getName());
				ref.setTargetTable(targetTable);
				ref.setOnDatabase(true);
				removedReferences.remove(ref);
				return;
			}
		}

		// no match - we have a new reference
		ELReference ref = this.addReference(externalForeignKey.getName(), targetTable);
		ExternalForeignKeyColumnPair[] pairs = externalForeignKey.getColumnPairs();
		for (int i = pairs.length; i-- > 0; ) {
			ref.addColumnPair(this.column(pairs[i].getSourceColumn()), targetTable.column(pairs[i].getTargetColumn()));
		}
		ref.setOnDatabase(true);
	}

	/**
	 * Returns the column with the same name as the specified "external" column
	 */
	ELColumn column(ExternalColumn externalColumn) {
		return (externalColumn == null) ? null : this.columnNamed(externalColumn.getName());
	}

	// ********** printing and displaying **********

	public void toString(StringBuffer sb) {
		sb.append(this.qualifiedName());
	}

	@Override
	public String displayString() {
		return this.qualifiedName();
	}
}