blob: 950de6c0459d84bcbbe1401e70a3b72c546f1dde [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2008, 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.ui.internal.details.db;
import org.eclipse.jpt.core.JpaDataSource;
import org.eclipse.jpt.core.JpaNode;
import org.eclipse.jpt.core.JpaProject;
import org.eclipse.jpt.db.Catalog;
import org.eclipse.jpt.db.Column;
import org.eclipse.jpt.db.ConnectionListener;
import org.eclipse.jpt.db.ConnectionProfile;
import org.eclipse.jpt.db.Database;
import org.eclipse.jpt.db.ForeignKey;
import org.eclipse.jpt.db.Schema;
import org.eclipse.jpt.db.Sequence;
import org.eclipse.jpt.db.Table;
import org.eclipse.jpt.ui.WidgetFactory;
import org.eclipse.jpt.ui.internal.Tracing;
import org.eclipse.jpt.ui.internal.listeners.SWTConnectionListenerWrapper;
import org.eclipse.jpt.ui.internal.listeners.SWTPropertyChangeListenerWrapper;
import org.eclipse.jpt.ui.internal.widgets.ComboPane;
import org.eclipse.jpt.ui.internal.widgets.Pane;
import org.eclipse.jpt.utility.internal.iterables.EmptyIterable;
import org.eclipse.jpt.utility.model.event.PropertyChangeEvent;
import org.eclipse.jpt.utility.model.listener.PropertyChangeListener;
import org.eclipse.jpt.utility.model.value.PropertyValueModel;
import org.eclipse.swt.widgets.Composite;
/**
* This abstract pane keeps a combo in sync with the database objects
* when a connection is active.
*
* @see CatalogCombo
* @see ColumnCombo
* @see SchemaCombo
* @see SequenceCombo
* @see TableCombo
*/
@SuppressWarnings("nls")
public abstract class DatabaseObjectCombo<T extends JpaNode>
extends ComboPane<T>
{
/**
* The listener added to the <code>ConnectionProfile</code>.
* It keeps the combo in sync with the database metadata.
*/
private ConnectionListener connectionListener;
private PropertyChangeListener connectionProfileListener;
// ********** constructors **********
protected DatabaseObjectCombo(
Pane<? extends T> parentPane,
Composite parent) {
super(parentPane, parent);
}
protected DatabaseObjectCombo(
Pane<?> parentPane,
PropertyValueModel<? extends T> subjectHolder,
Composite parent) {
super(parentPane, subjectHolder, parent);
}
protected DatabaseObjectCombo(
PropertyValueModel<? extends T> subjectHolder,
Composite parent,
WidgetFactory widgetFactory) {
super(subjectHolder, parent, widgetFactory);
}
// ********** initialization **********
@Override
protected void initialize() {
super.initialize();
this.connectionListener = this.buildConnectionListener();
this.connectionProfileListener = this.buildConnectionProfileListener();
}
protected ConnectionListener buildConnectionListener() {
return new SWTConnectionListenerWrapper(this.buildConnectionListener_());
}
protected ConnectionListener buildConnectionListener_() {
return new LocalConnectionListener();
}
protected PropertyChangeListener buildConnectionProfileListener() {
return new SWTPropertyChangeListenerWrapper(this.buildConnectionProfileListener_());
}
protected PropertyChangeListener buildConnectionProfileListener_() {
return new PropertyChangeListener(){
public void propertyChanged(PropertyChangeEvent event) {
connectionProfileChanged(event);
}
};
}
protected void connectionProfileChanged(PropertyChangeEvent event) {
if (event.getOldValue() != null) {
((ConnectionProfile) event.getOldValue()).removeConnectionListener(this.connectionListener);
}
if (event.getNewValue() != null) {
((ConnectionProfile) event.getNewValue()).addConnectionListener(this.connectionListener);
}
this.repopulateComboBox();
}
// ********** overrides **********
@Override
protected void engageListeners_(T subject) {
super.engageListeners_(subject);
subject.getJpaProject().getDataSource().addPropertyChangeListener(JpaDataSource.CONNECTION_PROFILE_PROPERTY, this.connectionProfileListener);
ConnectionProfile cp = subject.getJpaProject().getConnectionProfile();
if (cp != null) {
cp.addConnectionListener(this.connectionListener);
}
}
@Override
protected void disengageListeners_(T subject) {
ConnectionProfile cp = subject.getJpaProject().getConnectionProfile();
if (cp != null) {
cp.removeConnectionListener(this.connectionListener);
}
subject.getJpaProject().getDataSource().removePropertyChangeListener(JpaDataSource.CONNECTION_PROFILE_PROPERTY, this.connectionProfileListener);
super.disengageListeners_(subject);
}
@Override
protected final Iterable<String> getValues() {
return this.connectionProfileIsActive() ? this.getValues_() : EmptyIterable.<String>instance();
}
/**
* Called only when connection profile is active
*/
protected abstract Iterable<String> getValues_();
// ********** convenience methods **********
/**
* Return the subject's JPA project.
* Allow subclasses to override this method, so we can still get the JPA
* project even when the subject is null.
*/
protected JpaProject getJpaProject() {
T subject = this.getSubject();
return (subject == null) ? null : subject.getJpaProject();
}
/**
* Return the subject's connection profile.
*/
protected final ConnectionProfile getConnectionProfile() {
JpaProject jpaProject = this.getJpaProject();
return (jpaProject == null) ? null : jpaProject.getConnectionProfile();
}
/**
* Return whether the subject's connection profile is active.
*/
protected final boolean connectionProfileIsActive() {
ConnectionProfile cp = this.getConnectionProfile();
return (cp != null) && cp.isActive();
}
/**
* Returns the subject's database.
*/
protected final Database getDatabase() {
ConnectionProfile cp = this.getConnectionProfile();
return (cp == null) ? null : cp.getDatabase();
}
// ********** connection listener callbacks **********
protected final void databaseChanged(Database database) {
if ( ! this.comboBox.isDisposed()) {
this.databaseChanged_(database);
}
}
protected void databaseChanged_(@SuppressWarnings("unused") Database database) {
// do nothing by default
}
protected final void catalogChanged(Catalog catalog) {
if ( ! this.comboBox.isDisposed()) {
this.catalogChanged_(catalog);
}
}
protected void catalogChanged_(@SuppressWarnings("unused") Catalog catalog) {
// do nothing by default
}
protected final void schemaChanged(Schema schema) {
if ( ! this.comboBox.isDisposed()) {
this.schemaChanged_(schema);
}
}
protected void schemaChanged_(@SuppressWarnings("unused") Schema schema) {
// do nothing by default
}
protected final void sequenceChanged(Sequence sequence) {
if ( ! this.comboBox.isDisposed()) {
this.sequenceChanged_(sequence);
}
}
protected void sequenceChanged_(@SuppressWarnings("unused") Sequence sequence) {
// do nothing by default
}
protected final void tableChanged(Table table) {
if ( ! this.comboBox.isDisposed()) {
this.tableChanged_(table);
}
}
protected void tableChanged_(@SuppressWarnings("unused") Table table) {
// do nothing by default
}
protected final void columnChanged(Column column) {
if ( ! this.comboBox.isDisposed()) {
this.columnChanged_(column);
}
}
protected void columnChanged_(@SuppressWarnings("unused") Column column) {
// do nothing by default
}
protected final void foreignKeyChanged(ForeignKey foreignKey) {
if ( ! this.comboBox.isDisposed()) {
this.foreignKeyChanged_(foreignKey);
}
}
protected void foreignKeyChanged_(@SuppressWarnings("unused") ForeignKey foreignKey) {
// do nothing by default
}
@Override
protected void log(String flag, String message) {
if (flag.equals(Tracing.UI_DB) && Tracing.booleanDebugOption(Tracing.UI_DB)) {
this.log(message);
} else {
super.log(flag, message);
}
}
// broaden accessibility a bit
@Override
protected void repopulateComboBox() {
super.repopulateComboBox();
}
// ********** connection listener **********
protected class LocalConnectionListener
implements ConnectionListener
{
protected LocalConnectionListener() {
super();
}
public void opened(ConnectionProfile profile) {
this.log("opened: " + profile.getName());
DatabaseObjectCombo.this.repopulateComboBox();
}
public void modified(ConnectionProfile profile) {
this.log("modified: " + profile.getName());
DatabaseObjectCombo.this.repopulateComboBox();
}
public boolean okToClose(ConnectionProfile profile) {
this.log("OK to close: " + profile.getName());
return true;
}
public void aboutToClose(ConnectionProfile profile) {
this.log("about to close: " + profile.getName());
}
public void closed(ConnectionProfile profile) {
this.log("closed: " + profile.getName());
DatabaseObjectCombo.this.repopulateComboBox();
}
public void databaseChanged(ConnectionProfile profile, Database database) {
this.log("database changed: " + database.getName());
DatabaseObjectCombo.this.databaseChanged(database);
}
public void catalogChanged(ConnectionProfile profile, Catalog catalog) {
this.log("catalog changed: " + catalog.getName());
DatabaseObjectCombo.this.catalogChanged(catalog);
}
public void schemaChanged(ConnectionProfile profile, Schema schema) {
this.log("schema changed: " + schema.getName());
DatabaseObjectCombo.this.schemaChanged(schema);
}
public void sequenceChanged(ConnectionProfile profile, Sequence sequence) {
this.log("sequence changed: " + sequence.getName());
DatabaseObjectCombo.this.sequenceChanged(sequence);
}
public void tableChanged(ConnectionProfile profile, Table table) {
this.log("table changed: " + table.getName());
DatabaseObjectCombo.this.tableChanged(table);
}
public void columnChanged(ConnectionProfile profile, Column column) {
this.log("column changed: " + column.getName());
DatabaseObjectCombo.this.columnChanged(column);
}
public void foreignKeyChanged(ConnectionProfile profile, ForeignKey foreignKey) {
this.log("foreign key changed: " + foreignKey.getName());
DatabaseObjectCombo.this.foreignKeyChanged(foreignKey);
}
protected void log(String message) {
DatabaseObjectCombo.this.log(Tracing.UI_DB, message);
}
}
}