blob: c567ac4b84cdf32eea3db132bb7f419358f32b0f [file] [log] [blame]
/*******************************************************************************
* 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.orm;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import org.eclipse.jpt.core.context.Table;
import org.eclipse.jpt.core.context.UniqueConstraint;
import org.eclipse.jpt.core.context.XmlContextNode;
import org.eclipse.jpt.core.context.orm.OrmBaseTable;
import org.eclipse.jpt.core.context.orm.OrmUniqueConstraint;
import org.eclipse.jpt.core.internal.context.JptValidator;
import org.eclipse.jpt.core.internal.context.TableTextRangeResolver;
import org.eclipse.jpt.core.resource.orm.AbstractXmlTable;
import org.eclipse.jpt.core.resource.orm.OrmFactory;
import org.eclipse.jpt.core.resource.orm.XmlUniqueConstraint;
import org.eclipse.jpt.core.utility.TextRange;
import org.eclipse.jpt.db.Catalog;
import org.eclipse.jpt.db.Schema;
import org.eclipse.jpt.db.SchemaContainer;
import org.eclipse.jpt.utility.internal.CollectionTools;
import org.eclipse.jpt.utility.internal.NameTools;
import org.eclipse.jpt.utility.internal.iterators.CloneIterator;
import org.eclipse.jpt.utility.internal.iterators.CloneListIterator;
import org.eclipse.jpt.utility.internal.iterators.EmptyIterator;
import org.eclipse.wst.validation.internal.provisional.core.IMessage;
import org.eclipse.wst.validation.internal.provisional.core.IReporter;
/**
*
*/
public abstract class AbstractOrmTable
extends AbstractOrmXmlContextNode
implements OrmBaseTable, UniqueConstraint.Owner
{
protected String specifiedName;
protected String defaultName;
protected String specifiedSchema;
protected String defaultSchema;
protected String specifiedCatalog;
protected String defaultCatalog;
protected final List<OrmUniqueConstraint> uniqueConstraints;
protected final Owner owner;
// ********** constructor **********
protected AbstractOrmTable(XmlContextNode parent, Owner owner) {
super(parent);
this.uniqueConstraints = new ArrayList<OrmUniqueConstraint>();
this.owner = owner;
}
protected Owner getOwner() {
return this.owner;
}
// ********** abstract methods **********
/**
* Return null if no resource table exists.
*/
protected abstract AbstractXmlTable getResourceTable();
/**
* Return the added resource table.
*/
protected abstract AbstractXmlTable addResourceTable();
protected abstract void removeResourceTable();
protected abstract String buildDefaultName();
protected abstract String buildDefaultSchema();
protected abstract String buildDefaultCatalog();
public boolean isResourceSpecified() {
return this.getResourceTable() != null;
}
// ********** 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;
if (this.attributeValueHasChanged(old, name)) {
AbstractXmlTable resourceTable = this.getResourceTable();
if (resourceTable == null) {
resourceTable = this.addResourceTable();
}
resourceTable.setName(name);
if (resourceTable.isUnset()) {
this.removeResourceTable();
}
this.firePropertyChanged(SPECIFIED_NAME_PROPERTY, old, name);
}
}
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;
if (this.attributeValueHasChanged(old, schema)) {
AbstractXmlTable resourceTable = this.getResourceTable();
if (resourceTable == null) {
resourceTable = this.addResourceTable();
}
resourceTable.setSchema(schema);
if (resourceTable.isUnset()) {
this.removeResourceTable();
}
this.firePropertyChanged(SPECIFIED_SCHEMA_PROPERTY, old, schema);
}
}
protected void setSpecifiedSchema_(String schema) {
String old = this.specifiedSchema;
this.specifiedSchema = schema;
this.firePropertyChanged(SPECIFIED_SCHEMA_PROPERTY, old, schema);
}
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;
if (this.attributeValueHasChanged(old, catalog)) {
AbstractXmlTable resourceTable = this.getResourceTable();
if (resourceTable == null) {
resourceTable = this.addResourceTable();
}
resourceTable.setCatalog(catalog);
if (resourceTable.isUnset()) {
this.removeResourceTable();
}
this.firePropertyChanged(SPECIFIED_CATALOG_PROPERTY, old, catalog);
}
}
protected void setSpecifiedCatalog_(String newSpecifiedCatalog) {
String oldSpecifiedCatalog = this.specifiedCatalog;
this.specifiedCatalog = newSpecifiedCatalog;
firePropertyChanged(SPECIFIED_CATALOG_PROPERTY, oldSpecifiedCatalog, newSpecifiedCatalog);
}
public String getDefaultCatalog() {
return this.defaultCatalog;
}
protected void setDefaultCatalog(String newDefaultCatalog) {
String oldDefaultCatalog = this.defaultCatalog;
this.defaultCatalog = newDefaultCatalog;
firePropertyChanged(DEFAULT_CATALOG_PROPERTY, oldDefaultCatalog, newDefaultCatalog);
}
// ********** unique constraints **********
public @SuppressWarnings("unchecked") ListIterator<OrmUniqueConstraint> uniqueConstraints() {
return new CloneListIterator<OrmUniqueConstraint>(this.uniqueConstraints);
}
public int uniqueConstraintsSize() {
return this.uniqueConstraints.size();
}
public OrmUniqueConstraint addUniqueConstraint(int index) {
XmlUniqueConstraint resourceConstraint = OrmFactory.eINSTANCE.createXmlUniqueConstraint();
OrmUniqueConstraint contextConstraint = this.buildUniqueConstraint(resourceConstraint);
this.uniqueConstraints.add(index, contextConstraint);
AbstractXmlTable resourceTable = this.getResourceTable();
if (resourceTable == null) {
resourceTable = this.addResourceTable();
}
resourceTable.getUniqueConstraints().add(index, resourceConstraint);
this.fireItemAdded(UNIQUE_CONSTRAINTS_LIST, index, contextConstraint);
return contextConstraint;
}
protected void addUniqueConstraint(int index, OrmUniqueConstraint uniqueConstraint) {
this.addItemToList(index, uniqueConstraint, this.uniqueConstraints, UNIQUE_CONSTRAINTS_LIST);
}
protected void addUniqueConstraint(OrmUniqueConstraint uniqueConstraint) {
this.addUniqueConstraint(this.uniqueConstraints.size(), uniqueConstraint);
}
public void removeUniqueConstraint(UniqueConstraint uniqueConstraint) {
this.removeUniqueConstraint(this.uniqueConstraints.indexOf(uniqueConstraint));
}
public void removeUniqueConstraint(int index) {
OrmUniqueConstraint removedUniqueConstraint = this.uniqueConstraints.remove(index);
this.getResourceTable().getUniqueConstraints().remove(index);
this.fireItemRemoved(UNIQUE_CONSTRAINTS_LIST, index, removedUniqueConstraint);
}
protected void removeUniqueConstraint_(OrmUniqueConstraint uniqueConstraint) {
this.removeItemFromList(uniqueConstraint, this.uniqueConstraints, UNIQUE_CONSTRAINTS_LIST);
}
public void moveUniqueConstraint(int targetIndex, int sourceIndex) {
CollectionTools.move(this.uniqueConstraints, targetIndex, sourceIndex);
this.getResourceTable().getUniqueConstraints().move(targetIndex, sourceIndex);
this.fireItemMoved(UNIQUE_CONSTRAINTS_LIST, targetIndex, sourceIndex);
}
// ********** convenience methods **********
protected TextRange getTextRange(TextRange textRange) {
return (textRange != null) ? textRange : this.getParent().getValidationTextRange();
}
public TextRange getNameTextRange() {
return this.getTextRange(this.getResourceTableNameTextRange());
}
protected TextRange getResourceTableNameTextRange() {
AbstractXmlTable resourceTable = this.getResourceTable();
return (resourceTable == null) ? null : resourceTable.getNameTextRange();
}
public TextRange getSchemaTextRange() {
return this.getTextRange(this.getResourceTableSchemaTextRange());
}
protected TextRange getResourceTableSchemaTextRange() {
AbstractXmlTable resourceTable = this.getResourceTable();
return (resourceTable == null) ? null : resourceTable.getSchemaTextRange();
}
public TextRange getCatalogTextRange() {
return this.getTextRange(this.getResourceTableCatalogTextRange());
}
protected TextRange getResourceTableCatalogTextRange() {
AbstractXmlTable resourceTable = this.getResourceTable();
return (resourceTable == null) ? null : resourceTable.getCatalogTextRange();
}
protected OrmUniqueConstraint buildUniqueConstraint(XmlUniqueConstraint resourceUniqueConstraint) {
return this.getXmlContextNodeFactory().buildOrmUniqueConstraint(this, this, resourceUniqueConstraint);
}
// ********** resource => context **********
protected void initialize(AbstractXmlTable xmlTable) {
this.defaultName = this.buildDefaultName();
this.specifiedName = this.getResourceTableName(xmlTable);
this.defaultSchema = this.buildDefaultSchema();
this.specifiedSchema = this.getResourceTableSchema(xmlTable);
this.defaultCatalog = this.buildDefaultCatalog();
this.specifiedCatalog = this.getResourceTableCatalog(xmlTable);
this.initializeUniqueContraints(xmlTable);
}
protected void initializeUniqueContraints(AbstractXmlTable xmlTable) {
if (xmlTable == null) {
return;
}
for (XmlUniqueConstraint uniqueConstraint : xmlTable.getUniqueConstraints()) {
this.uniqueConstraints.add(this.buildUniqueConstraint(uniqueConstraint));
}
}
protected void update(AbstractXmlTable xmlTable) {
this.setDefaultName(this.buildDefaultName());
this.setSpecifiedName_(this.getResourceTableName(xmlTable));
this.setDefaultSchema(this.buildDefaultSchema());
this.setSpecifiedSchema_(this.getResourceTableSchema(xmlTable));
this.setDefaultCatalog(this.buildDefaultCatalog());
this.setSpecifiedCatalog_(this.getResourceTableCatalog(xmlTable));
this.updateUniqueConstraints(xmlTable);
}
protected String getResourceTableName(AbstractXmlTable xmlTable) {
return (xmlTable == null) ? null : xmlTable.getName();
}
protected String getResourceTableSchema(AbstractXmlTable xmlTable) {
return (xmlTable == null) ? null : xmlTable.getSchema();
}
protected String getResourceTableCatalog(AbstractXmlTable xmlTable) {
return (xmlTable == null) ? null : xmlTable.getCatalog();
}
protected void updateUniqueConstraints(AbstractXmlTable xmlTable) {
Iterator<XmlUniqueConstraint> xmlConstraints = this.xmlUniqueConstraints(xmlTable);
for (Iterator<OrmUniqueConstraint> contextConstraints = this.uniqueConstraints(); contextConstraints.hasNext(); ) {
OrmUniqueConstraint contextConstraint = contextConstraints.next();
if (xmlConstraints.hasNext()) {
contextConstraint.update(xmlConstraints.next());
} else {
this.removeUniqueConstraint_(contextConstraint);
}
}
while (xmlConstraints.hasNext()) {
this.addUniqueConstraint(this.buildUniqueConstraint(xmlConstraints.next()));
}
}
protected Iterator<XmlUniqueConstraint> xmlUniqueConstraints(AbstractXmlTable xmlTable) {
// make a copy of the XML constraints (to prevent ConcurrentModificationException)
return (xmlTable == null) ? EmptyIterator.<XmlUniqueConstraint>instance()
: new CloneIterator<XmlUniqueConstraint>(xmlTable.getUniqueConstraints());
}
public void initializeFrom(Table oldTable) {
this.setSpecifiedName(oldTable.getSpecifiedName());
this.setSpecifiedCatalog(oldTable.getSpecifiedCatalog());
this.setSpecifiedSchema(oldTable.getSpecifiedSchema());
}
// ********** database stuff **********
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() {
return this.getTextRange(this.getResourceTableValidationTextRange());
}
@Override
public void validate(List<IMessage> messages, IReporter reporter) {
super.validate(messages, reporter);
this.buildTableValidator().validate(messages, reporter);
}
protected JptValidator buildTableValidator() {
return this.getOwner().buildTableValidator(this, buildTextRangeResolver());
}
protected TableTextRangeResolver buildTextRangeResolver() {
return new OrmTableTextRangeResolver(this);
}
protected TextRange getResourceTableValidationTextRange() {
AbstractXmlTable resourceTable = this.getResourceTable();
return (resourceTable == null) ? null : resourceTable.getValidationTextRange();
}
// ********** misc **********
/**
* covariant override
*/
@Override
public XmlContextNode getParent() {
return (XmlContextNode) 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());
}
}