blob: 3ed9da4e5dd0797e8e0fc1a1cf5293e9a0ff2c9b [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2006, 2012 Oracle. All rights reserved.
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0, which accompanies this distribution
* and is available at https://www.eclipse.org/legal/epl-2.0/.
*
* 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.datatools.modelbase.sql.schema.SQLObject;
import org.eclipse.jpt.common.utility.internal.ObjectTools;
import org.eclipse.jpt.jpa.db.DatabaseObject;
import org.eclipse.jpt.jpa.db.internal.driver.DTPDriverAdapter;
/**
* DTP Object Wrapper base class
*/
abstract class DTPDatabaseObjectWrapper<P extends DTPDatabaseObject, S extends SQLObject>
implements DTPDatabaseObject
{
/** we need a way to get to the connection profile */
final P parent;
/** the wrapped DTP SQL object */
final S dtpObject;
/** listen for the "catalog object" to be refreshed */
private final ICatalogObjectListener catalogObjectListener;
// ********** constructor **********
DTPDatabaseObjectWrapper(P parent, S dtpObject) {
super();
this.parent = parent;
this.dtpObject = dtpObject;
ICatalogObject catalogObject = this.getCatalogObject();
if ((catalogObject != null) && 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.catalogObjectListener = this.buildCatalogObjectListener();
if (this.getConnectionProfile().hasAnyListeners()) {
this.startListening(catalogObject);
}
} else {
this.catalogObjectListener = null;
}
}
// ********** names vs. identifiers **********
public String getName() {
return this.dtpObject.getName();
}
/**
* 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 final String getIdentifier(String defaultName) {
return this.getDTPDriverAdapter().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>
* <li>MySQL<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 final String getIdentifier() {
return this.convertNameToIdentifier(this.getName());
}
/**
* @see DTPDatabaseWrapper#convertNameToIdentifier(String)
*/
String convertNameToIdentifier(String name) {
return this.getDTPDriverAdapter().convertNameToIdentifier(name);
}
// ********** DTP database object listener **********
private ICatalogObjectListener buildCatalogObjectListener() {
return new CatalogObjectListener();
}
/* CU private */ class CatalogObjectListener
implements ICatalogObjectListener
{
public void notifyChanged(ICatalogObject dmElement, int eventType) {
// 'eventType' doesn't seem to be very useful, so drop it
DTPDatabaseObjectWrapper.this.catalogObjectChanged();
}
@Override
public String toString() {
return ObjectTools.toString(this);
}
}
/**
* Return the wrapped DTP database object if it is a DTP "catalog" object;
* otherwise, return <code>null</code>.
*/
final ICatalogObject getCatalogObject() {
return (this.dtpObject instanceof ICatalogObject) ? (ICatalogObject) this.dtpObject : null;
}
/**
* Typically, a subclass will override this method to
* call <code>super.catalogObjectChanged()</code> and
* 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();
/**
* This should only be called when the connection profile is "live" and has
* listeners.
*/
void startListening() {
ICatalogObject catalogObject = this.getCatalogObject();
if (catalogObject != null) {
this.checkListener();
this.startListening(catalogObject);
}
}
/**
* Pre-conditions: catalog listener and object are both present
*/
private void startListening(ICatalogObject catalogObject) {
RefreshManager.getInstance().AddListener(catalogObject, this.catalogObjectListener);
}
/**
* This should only be called when the connection profile is "live" and has
* no listeners.
*/
void stopListening() {
ICatalogObject catalogObject = this.getCatalogObject();
if (catalogObject != null) {
this.checkListener();
RefreshManager.getInstance().removeListener(catalogObject, this.catalogObjectListener);
}
}
/**
* We only build {@link #catalogObjectListener} when the connection
* profile is "live". If we get here and it is <code>null</code>,
* something is wrong.
*/
private void checkListener() {
if (this.catalogObjectListener == null) {
throw new IllegalStateException("the catalog listener is null"); //$NON-NLS-1$
}
}
// ********** misc **********
/**
* @see DTPConnectionProfileWrapper#getConnectionProfile()
*/
public final DTPConnectionProfileWrapper getConnectionProfile() {
return this.parent.getConnectionProfile();
}
/**
* @see DTPDatabaseWrapper#getDatabase()
*/
public DTPDatabaseWrapper getDatabase() {
return this.parent.getDatabase();
}
public final void refresh() {
ICatalogObject catalogObject = this.getCatalogObject();
if (catalogObject != null) {
catalogObject.refresh();
}
}
DTPDriverAdapter getDTPDriverAdapter() {
return this.getDatabase().getDTPDriverAdapter();
}
/**
* Convenience method.
*/
final <T extends DatabaseObject> T selectDatabaseObjectNamed(Iterable<T> databaseObjects, String name) {
for (T databaseObject : databaseObjects) {
if (databaseObject.getName().equals(name)) {
return databaseObject;
}
}
return null;
}
@Override
public String toString() {
return ObjectTools.toString(this, this.getName());
}
}