blob: fc7992e1ae6140f66425dc383cff7f01d67d9154 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2006, 2009 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.jpa.db.internal;
import org.eclipse.datatools.connectivity.sqm.core.rte.ICatalogObject;
import org.eclipse.datatools.connectivity.sqm.core.rte.ICatalogObjectListener;
import org.eclipse.datatools.connectivity.sqm.core.rte.RefreshManager;
import org.eclipse.jpt.common.utility.internal.StringTools;
import org.eclipse.jpt.jpa.db.DatabaseObject;
/**
* DTP Catalog Object Wrapper base class
*/
abstract class DTPDatabaseObjectWrapper
implements DTPDatabaseObject
{
/** we need a way to get to the connection profile */
private final DTPDatabaseObject parent;
/** listen for the "catalog object" being refreshed */
private final ICatalogObjectListener catalogObjectListener;
/** listen for this DTP catalog object to refresh */
final ICatalogObject catalogObject;
// ********** construction/initialization **********
DTPDatabaseObjectWrapper(DTPDatabaseObject parent, Object dtpObject) {
super();
this.parent = parent;
if (this.getConnectionProfile().isConnected()) {
// we only listen to "live" connections (as opposed to "off-line" connections);
// and the model is rebuilt when the connection connects or disconnects
this.catalogObject = (ICatalogObject) dtpObject;
this.catalogObjectListener = this.buildCatalogObjectListener();
if (this.getConnectionProfile().hasAnyListeners()) {
this.startListening();
}
} else {
this.catalogObject = null;
this.catalogObjectListener = null;
}
}
private ICatalogObjectListener buildCatalogObjectListener() {
return new ICatalogObjectListener() {
public void notifyChanged(ICatalogObject dmElement, int eventType) {
if (dmElement == DTPDatabaseObjectWrapper.this.catalogObject) {
// 'eventType' doesn't seem to be very useful, so drop it
DTPDatabaseObjectWrapper.this.catalogObjectChanged();
}
}
};
}
// typically, notify the connection profile something has changed
void catalogObjectChanged() {
this.clear();
}
/**
* The DTP object has changed, clear the wrapper's state so it will be
* synchronized on-demand.
*/
abstract void clear();
// ********** queries **********
DTPDatabaseObject getParent() {
return this.parent;
}
public DTPConnectionProfileWrapper getConnectionProfile() {
return this.parent.getConnectionProfile();
}
public DTPDatabaseWrapper getDatabase() {
return this.getConnectionProfile().getDatabase();
}
/**
* Return the database object identified by the specified identifier. If
* the identifier is "delimited" (typically with double-quotes), it will be
* used without any folding. If the name is "regular" (i.e. not delimited),
* it will be folded to the appropriate case (typically uppercase).
* This is called by whenever we need to find a component by identifier
* (e.g. {{@link org.eclipse.jpt.jpa.db.Table#getColumnForIdentifier(String)}).
*/
<T extends DatabaseObject> T selectDatabaseObjectForIdentifier(Iterable<T> databaseObjects, String identifier) {
return this.selectDatabaseObjectNamed(databaseObjects, this.convertIdentifierToName(identifier));
}
private String convertIdentifierToName(String identifier) {
return this.getConnectionProfile().convertIdentifierToName(identifier);
}
/**
* Convenience method.
*/
<T extends DatabaseObject> T selectDatabaseObjectNamed(Iterable<T> databaseObjects, String name) {
for (T dbObject : databaseObjects) {
if (dbObject.getName().equals(name)) {
return dbObject;
}
}
return null;
}
/**
* Examples:<ul>
* <li>Oracle etc.<ul><code>
* <li>Table(FOO) vs. "Foo" => null
* <li>Table(BAR) vs. "Foo" => "BAR"
* <li>Table(Foo) vs. "Foo" => "\"Foo\""
* <li>Table(Bar) vs. "Foo" => "\"Bar\""
* </code></ul>
* <li>PostgreSQL etc.<ul><code>
* <li>Table(foo) vs. "Foo" => null
* <li>Table(bar) vs. "Foo" => "bar"
* <li>Table(Foo) vs. "Foo" => "\"Foo\""
* <li>Table(Bar) vs. "Foo" => "\"Bar\""
* </code></ul>
* <li>SQL Server etc.<ul><code>
* <li>Table(Foo) vs. "Foo" => null
* <li>Table(foo) vs. "Foo" => "foo"
* <li>Table(bar) vs. "Foo" => "bar"
* <li>Table(Bar) vs. "Foo" => "Bar"
* </code></ul>
* </ul>
*/
public String getIdentifier(String defaultName) {
return this.getDatabase().convertNameToIdentifier(this.getName(), defaultName);
}
/**
* Examples:<ul>
* <li>Oracle etc.<ul><code>
* <li>Table(FOO) => "FOO"
* <li>Table(Foo) => "\"Foo\""
* <li>Table(foo) => "\"foo\""
* <li>Table(foo++) => "\"foo++\""
* <li>Table(f"o) => "\"f\"\"o\"" (i.e. "f""o")
* </code></ul>
* <li>PostgreSQL etc.<ul><code>
* <li>Table(FOO) => "\"FOO\""
* <li>Table(Foo) => "\"Foo\""
* <li>Table(foo) => "foo"
* <li>Table(foo++) => "\"foo++\""
* <li>Table(f"o) => "\"f\"\"o\"" (i.e. "f""o")
* </code></ul>
* <li>SQL Server etc.<ul><code>
* <li>Table(FOO) => "FOO"
* <li>Table(Foo) => "Foo"
* <li>Table(foo) => "foo"
* <li>Table(foo++) => "\"foo++\""
* <li>Table(f"o) => "\"f\"\"o\"" (i.e. "f""o")
* </code></ul>
* </ul>
*/
public String getIdentifier() {
return this.convertNameToIdentifier(this.getName());
}
String convertNameToIdentifier(String name) {
return this.getConnectionProfile().convertNameToIdentifier(name);
}
@Override
public String toString() {
return StringTools.buildToStringFor(this, this.getName());
}
// ********** listening to DTP database object **********
// this should only be called when the connection profile is "live" and has listeners
void startListening() {
this.checkListener();
RefreshManager.getInstance().AddListener(this.catalogObject, this.catalogObjectListener);
}
// this should only be called when the connection profile is "live" and has no listeners
void stopListening() {
this.checkListener();
RefreshManager.getInstance().removeListener(this.catalogObject, this.catalogObjectListener);
}
private void checkListener() {
if (this.catalogObjectListener == null) {
throw new IllegalStateException("the catalog listener is null"); //$NON-NLS-1$
}
}
}