/*******************************************************************************
 * Copyright (c) 2007, 2010 Oracle. All rights reserved.
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v1.0, which accompanies this distribution
 * and is available at http://www.eclipse.org/legal/epl-v10.html.
 * 
 * Contributors:
 *     Oracle - initial API and implementation
 ******************************************************************************/
package org.eclipse.jpt.core.internal.context.java;

import java.util.Iterator;
import java.util.ListIterator;
import java.util.Vector;

import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jpt.core.context.Table;
import org.eclipse.jpt.core.context.UniqueConstraint;
import org.eclipse.jpt.core.context.java.JavaJpaContextNode;
import org.eclipse.jpt.core.context.java.JavaUniqueConstraint;
import org.eclipse.jpt.core.resource.java.BaseTableAnnotation;
import org.eclipse.jpt.core.resource.java.UniqueConstraintAnnotation;
import org.eclipse.jpt.core.utility.TextRange;
import org.eclipse.jpt.db.Catalog;
import org.eclipse.jpt.db.Database;
import org.eclipse.jpt.db.Schema;
import org.eclipse.jpt.db.SchemaContainer;
import org.eclipse.jpt.utility.Filter;
import org.eclipse.jpt.utility.internal.CollectionTools;
import org.eclipse.jpt.utility.internal.NameTools;
import org.eclipse.jpt.utility.internal.StringTools;
import org.eclipse.jpt.utility.internal.iterables.EmptyIterable;
import org.eclipse.jpt.utility.internal.iterables.FilteringIterable;
import org.eclipse.jpt.utility.internal.iterators.CloneListIterator;
import org.eclipse.jpt.utility.internal.iterators.EmptyIterator;

/**
 * Java table
 */
public abstract class AbstractJavaTable
	extends AbstractJavaJpaContextNode
	implements Table, UniqueConstraint.Owner
{
	protected String specifiedName;
	protected String defaultName;

	protected String specifiedSchema;
	protected String defaultSchema;

	protected String specifiedCatalog;
	protected String defaultCatalog;

	protected final Vector<JavaUniqueConstraint> uniqueConstraints = new Vector<JavaUniqueConstraint>();


	// ********** constructor **********

	protected AbstractJavaTable(JavaJpaContextNode parent) {
		super(parent);
	}


	// ********** abstract methods **********

	/**
	 * Return the Java table annotation. Do not return null if the Java
	 * annotation does not exist; return a null table annotation instead.
	 */
	protected abstract BaseTableAnnotation getAnnotation();

	/**
	 * Return the name of the Java annotation.
	 */
	protected abstract String getAnnotationName();

	protected abstract String buildDefaultName();

	protected abstract String buildDefaultSchema();

	protected abstract String buildDefaultCatalog();


	// ********** name **********

	public String getName() {
		return (this.specifiedName != null) ? this.specifiedName : this.defaultName;
	}

	public String getSpecifiedName() {
		return this.specifiedName;
	}

	public void setSpecifiedName(String name) {
		String old = this.specifiedName;
		this.specifiedName = name;
		this.getAnnotation().setName(name);
		this.firePropertyChanged(SPECIFIED_NAME_PROPERTY, old, name);
	}

	/**
	 * internal setter used only for updating from the resource model.
	 * There were problems with InvalidThreadAccess exceptions in the UI
	 * when you set a value from the UI and the annotation doesn't exist yet.
	 * Adding the annotation causes an update to occur and then the exception.
	 */
	protected void setSpecifiedName_(String name) {
		String old = this.specifiedName;
		this.specifiedName = name;
		this.firePropertyChanged(SPECIFIED_NAME_PROPERTY, old, name);
	}

	public String getDefaultName() {
		return this.defaultName;
	}

	protected void setDefaultName(String name) {
		String old = this.defaultName;
		this.defaultName = name;
		this.firePropertyChanged(DEFAULT_NAME_PROPERTY, old, name);
	}


	// ********** schema **********

	public String getSchema() {
		return (this.specifiedSchema != null) ? this.specifiedSchema : this.defaultSchema;
	}

	public String getSpecifiedSchema() {
		return this.specifiedSchema;
	}

	public void setSpecifiedSchema(String schema) {
		String old = this.specifiedSchema;
		this.specifiedSchema = schema;
		this.getAnnotation().setSchema(schema);
		this.firePropertyChanged(SPECIFIED_SCHEMA_PROPERTY, old, schema);
	}

	/**
	 * internal setter used only for updating from the resource model.
	 * There were problems with InvalidThreadAccess exceptions in the UI
	 * when you set a value from the UI and the annotation doesn't exist yet.
	 * Adding the annotation causes an update to occur and then the exception.
	 */
	protected void setSpecifiedSchema_(String newSpecifiedSchema) {
		String oldSpecifiedSchema = this.specifiedSchema;
		this.specifiedSchema = newSpecifiedSchema;
		firePropertyChanged(SPECIFIED_SCHEMA_PROPERTY, oldSpecifiedSchema, newSpecifiedSchema);
	}

	public String getDefaultSchema() {
		return this.defaultSchema;
	}

	protected void setDefaultSchema(String schema) {
		String old = this.defaultSchema;
		this.defaultSchema = schema;
		this.firePropertyChanged(DEFAULT_SCHEMA_PROPERTY, old, schema);
	}


	// ********** catalog **********

	public String getCatalog() {
		return (this.specifiedCatalog != null) ? this.specifiedCatalog : this.defaultCatalog;
	}

	public String getSpecifiedCatalog() {
		return this.specifiedCatalog;
	}

	public void setSpecifiedCatalog(String catalog) {
		String old = this.specifiedCatalog;
		this.specifiedCatalog = catalog;
		this.getAnnotation().setCatalog(catalog);
		this.firePropertyChanged(SPECIFIED_CATALOG_PROPERTY, old, catalog);
	}

	/**
	 * internal setter used only for updating from the resource model.
	 * There were problems with InvalidThreadAccess exceptions in the UI
	 * when you set a value from the UI and the annotation doesn't exist yet.
	 * Adding the annotation causes an update to occur and then the exception.
	 */
	protected void setSpecifiedCatalog_(String catalog) {
		String old = this.specifiedCatalog;
		this.specifiedCatalog = catalog;
		this.firePropertyChanged(SPECIFIED_CATALOG_PROPERTY, old, catalog);
	}

	public String getDefaultCatalog() {
		return this.defaultCatalog;
	}

	protected void setDefaultCatalog(String catalog) {
		String old = this.defaultCatalog;
		this.defaultCatalog = catalog;
		this.firePropertyChanged(DEFAULT_CATALOG_PROPERTY, old, catalog);
	}


	// ********** unique constraints **********

	public @SuppressWarnings("unchecked") ListIterator<JavaUniqueConstraint> uniqueConstraints() {
		return new CloneListIterator<JavaUniqueConstraint>(this.uniqueConstraints);
	}

	public int uniqueConstraintsSize() {
		return this.uniqueConstraints.size();
	}

	public JavaUniqueConstraint addUniqueConstraint(int index) {
		JavaUniqueConstraint uniqueConstraint = getJpaFactory().buildJavaUniqueConstraint(this, this);
		this.uniqueConstraints.add(index, uniqueConstraint);
		UniqueConstraintAnnotation uniqueConstraintAnnotation = this.getAnnotation().addUniqueConstraint(index);
		uniqueConstraint.initialize(uniqueConstraintAnnotation);
		fireItemAdded(UNIQUE_CONSTRAINTS_LIST, index, uniqueConstraint);
		return uniqueConstraint;
	}

	public void removeUniqueConstraint(UniqueConstraint uniqueConstraint) {
		this.removeUniqueConstraint(this.uniqueConstraints.indexOf(uniqueConstraint));
	}

	public void removeUniqueConstraint(int index) {
		JavaUniqueConstraint removedUniqueConstraint = this.uniqueConstraints.remove(index);
		this.getAnnotation().removeUniqueConstraint(index);
		fireItemRemoved(UNIQUE_CONSTRAINTS_LIST, index, removedUniqueConstraint);
	}

	public void moveUniqueConstraint(int targetIndex, int sourceIndex) {
		CollectionTools.move(this.uniqueConstraints, targetIndex, sourceIndex);
		this.getAnnotation().moveUniqueConstraint(targetIndex, sourceIndex);
		fireItemMoved(UNIQUE_CONSTRAINTS_LIST, targetIndex, sourceIndex);
	}

	protected void addUniqueConstraint(int index, JavaUniqueConstraint uniqueConstraint) {
		addItemToList(index, uniqueConstraint, this.uniqueConstraints, UNIQUE_CONSTRAINTS_LIST);
	}

	protected void addUniqueConstraint(JavaUniqueConstraint uniqueConstraint) {
		this.addUniqueConstraint(this.uniqueConstraints.size(), uniqueConstraint);
	}

	protected void removeUniqueConstraint_(JavaUniqueConstraint uniqueConstraint) {
		removeItemFromList(uniqueConstraint, this.uniqueConstraints, UNIQUE_CONSTRAINTS_LIST);
	}

	protected void initializeUniqueConstraints(BaseTableAnnotation baseTableAnnotation) {
		for (Iterator<UniqueConstraintAnnotation> stream = baseTableAnnotation.uniqueConstraints(); stream.hasNext(); ) {
			this.uniqueConstraints.add(buildUniqueConstraint(stream.next()));
		}
	}

	protected void updateUniqueConstraints(BaseTableAnnotation baseTableAnnotation) {
		ListIterator<UniqueConstraintAnnotation> constraintAnnotations = baseTableAnnotation.uniqueConstraints();
		ListIterator<JavaUniqueConstraint> constraints = this.uniqueConstraints();
		while (constraints.hasNext()) {
			JavaUniqueConstraint uniqueConstraint = constraints.next();
			if (constraintAnnotations.hasNext()) {
				uniqueConstraint.update(constraintAnnotations.next());
			} else {
				this.removeUniqueConstraint_(uniqueConstraint);
			}
		}

		while (constraintAnnotations.hasNext()) {
			this.addUniqueConstraint(this.buildUniqueConstraint(constraintAnnotations.next()));
		}
	}

	protected JavaUniqueConstraint buildUniqueConstraint(UniqueConstraintAnnotation uniqueConstraintAnnotation) {
		JavaUniqueConstraint uniqueConstraint = this.getJpaFactory().buildJavaUniqueConstraint(this, this);
		uniqueConstraint.initialize(uniqueConstraintAnnotation);
		return uniqueConstraint;
	}


	// ********** convenience methods **********

	protected TextRange getTextRange(TextRange textRange, CompilationUnit astRoot) {
		return (textRange != null) ? textRange : this.getParent().getValidationTextRange(astRoot);
	}

	protected TextRange getNameTextRange(CompilationUnit astRoot) {
		return this.getTextRange(this.getAnnotation().getNameTextRange(astRoot), astRoot);
	}

	protected boolean nameTouches(int pos, CompilationUnit astRoot) {
		return this.getAnnotation().nameTouches(pos, astRoot);
	}

	protected TextRange getSchemaTextRange(CompilationUnit astRoot) {
		return this.getTextRange(this.getAnnotation().getSchemaTextRange(astRoot), astRoot);
	}

	protected boolean schemaTouches(int pos, CompilationUnit astRoot) {
		return this.getAnnotation().schemaTouches(pos, astRoot);
	}

	protected TextRange getCatalogTextRange(CompilationUnit astRoot) {
		return this.getTextRange(this.getAnnotation().getCatalogTextRange(astRoot), astRoot);
	}

	protected boolean catalogTouches(int pos, CompilationUnit astRoot) {
		return this.getAnnotation().catalogTouches(pos, astRoot);
	}


	// ********** resource => context **********

	protected void initialize(BaseTableAnnotation baseTableAnnotation) {
		this.defaultName = this.buildDefaultName();
		this.specifiedName = baseTableAnnotation.getName();

		this.defaultSchema = this.buildDefaultSchema();
		this.specifiedSchema = baseTableAnnotation.getSchema();

		this.defaultCatalog = this.buildDefaultCatalog();
		this.specifiedCatalog = baseTableAnnotation.getCatalog();

		this.initializeUniqueConstraints(baseTableAnnotation);
	}

	protected void update(BaseTableAnnotation baseTableAnnotation) {
		this.setDefaultName(this.buildDefaultName());
		this.setSpecifiedName_(baseTableAnnotation.getName());

		this.setDefaultSchema(this.buildDefaultSchema());
		this.setSpecifiedSchema_(baseTableAnnotation.getSchema());

		this.setDefaultCatalog(this.buildDefaultCatalog());
		this.setSpecifiedCatalog_(baseTableAnnotation.getCatalog());

		this.updateUniqueConstraints(baseTableAnnotation);
	}


	// ********** database **********

	public org.eclipse.jpt.db.Table getDbTable() {
		Schema dbSchema = this.getDbSchema();
		return (dbSchema == null) ? null : dbSchema.getTableForIdentifier(this.getName());
	}

	public Schema getDbSchema() {
		SchemaContainer dbSchemaContainer = this.getDbSchemaContainer();
		return (dbSchemaContainer == null) ? null : dbSchemaContainer.getSchemaForIdentifier(this.getSchema());
	}

	/**
	 * If we don't have a catalog (i.e. we don't even have a <em>default</em> catalog),
	 * then the database probably does not support catalogs; and we need to
	 * get the schema directly from the database.
	 */
	public SchemaContainer getDbSchemaContainer() {
		String catalog = this.getCatalog();
		return (catalog != null) ? this.getDbCatalog(catalog) : this.getDatabase();
	}

	/**
	 * If we don't have a catalog (i.e. we don't even have a <em>default</em>
	 * catalog), then the database probably does not support catalogs.
	 */
	public Catalog getDbCatalog() {
		String catalog = this.getCatalog();
		return (catalog == null) ? null : this.getDbCatalog(catalog);
	}

	public boolean isResolved() {
		return this.getDbTable() != null;
	}

	public boolean hasResolvedSchema() {
		return this.getDbSchema() != null;
	}

	/**
	 * If we don't have a catalog (i.e. we don't even have a <em>default</em>
	 * catalog), then the database probably does not support catalogs.
	 */
	public boolean hasResolvedCatalog() {
		String catalog = this.getCatalog();
		return (catalog == null) || (this.getDbCatalog(catalog) != null);
	}


	// ********** UniqueConstraint.Owner implementation **********

	public Iterator<String> candidateUniqueConstraintColumnNames() {
		org.eclipse.jpt.db.Table dbTable = this.getDbTable();
		return (dbTable != null) ? dbTable.getSortedColumnIdentifiers().iterator() : EmptyIterator.<String>instance();
	}


	// ********** validation **********

	public TextRange getValidationTextRange(CompilationUnit astRoot) {
		return this.getTextRange(this.getAnnotation().getTextRange(astRoot), astRoot);
	}


	// ********** Java completion proposals **********

	@Override
	public Iterator<String> javaCompletionProposals(int pos, Filter<String> filter, CompilationUnit astRoot) {
		Iterator<String> result = super.javaCompletionProposals(pos, filter, astRoot);
		if (result != null) {
			return result;
		}
		for (JavaUniqueConstraint constraint : CollectionTools.iterable(this.uniqueConstraints())) {
			result = constraint.javaCompletionProposals(pos, filter, astRoot);
			if (result != null) {
				return result;
			}
		}
		return null;
	}

	/**
	 * called if the database is connected:
	 * name, schema, catalog
	 */
	@Override
	public Iterator<String> connectedJavaCompletionProposals(int pos, Filter<String> filter, CompilationUnit astRoot) {
		Iterator<String> result = super.connectedJavaCompletionProposals(pos, filter, astRoot);
		if (result != null) {
			return result;
		}
		if (this.nameTouches(pos, astRoot)) {
			return this.getJavaCandidateNames(filter).iterator();
		}
		if (this.schemaTouches(pos, astRoot)) {
			return this.getJavaCandidateSchemata(filter).iterator();
		}
		if (this.catalogTouches(pos, astRoot)) {
			return this.getJavaCandidateCatalogs(filter).iterator();
		}
		return null;
	}

	protected Iterable<String> getJavaCandidateNames(Filter<String> filter) {
		return StringTools.convertToJavaStringLiterals(this.getCandidateNames(filter));
	}

	protected Iterable<String> getCandidateNames(Filter<String> filter) {
		return new FilteringIterable<String>(this.getCandidateNames(), filter);
	}

	protected Iterable<String> getCandidateNames() {
		Schema dbSchema = this.getDbSchema();
		return (dbSchema != null) ? dbSchema.getSortedTableIdentifiers() : EmptyIterable.<String> instance();
	}

	protected Iterable<String> getJavaCandidateSchemata(Filter<String> filter) {
		return StringTools.convertToJavaStringLiterals(this.getCandidateSchemata(filter));
	}

	protected Iterable<String> getCandidateSchemata(Filter<String> filter) {
		return new FilteringIterable<String>(this.getCandidateSchemata(), filter);
	}

	protected Iterable<String> getCandidateSchemata() {
		return this.getDbSchemaContainer().getSortedSchemaIdentifiers();
	}

	protected Iterable<String> getJavaCandidateCatalogs(Filter<String> filter) {
		return StringTools.convertToJavaStringLiterals(this.getCandidateCatalogs(filter));
	}

	protected Iterable<String> getCandidateCatalogs(Filter<String> filter) {
		return new FilteringIterable<String>(this.getCandidateCatalogs(), filter);
	}

	protected Iterable<String> getCandidateCatalogs() {
		Database db = this.getDatabase();
		return (db != null) ? db.getSortedCatalogIdentifiers() : EmptyIterable.<String> instance();
	}


	// ********** misc **********

	/**
	 * covariant override
	 */
	@Override
	public JavaJpaContextNode getParent() {
		return (JavaJpaContextNode) super.getParent();
	}

	@Override
	public void toString(StringBuilder sb) {
		super.toString(sb);
		sb.append(this.getQualifiedName());
	}

	protected String getQualifiedName() {
		return NameTools.buildQualifiedDatabaseObjectName(this.getCatalog(), this.getSchema(), this.getName());
	}

}
