| /******************************************************************************* |
| * 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.ui.internal.wizards; |
| |
| import java.util.EventListener; |
| |
| import org.eclipse.jface.dialogs.Dialog; |
| import org.eclipse.jface.preference.PreferenceDialog; |
| import org.eclipse.jface.wizard.WizardPage; |
| import org.eclipse.jpt.core.JpaProject; |
| import org.eclipse.jpt.db.ConnectionAdapter; |
| import org.eclipse.jpt.db.ConnectionListener; |
| import org.eclipse.jpt.db.ConnectionProfile; |
| import org.eclipse.jpt.db.Schema; |
| import org.eclipse.jpt.db.SchemaContainer; |
| import org.eclipse.jpt.ui.internal.JpaHelpContextIds; |
| import org.eclipse.jpt.ui.internal.JptUiMessages; |
| import org.eclipse.jpt.ui.internal.properties.JpaProjectPropertiesPage; |
| import org.eclipse.jpt.utility.internal.ListenerList; |
| import org.eclipse.jpt.utility.internal.iterables.EmptyIterable; |
| import org.eclipse.swt.SWT; |
| import org.eclipse.swt.events.SelectionAdapter; |
| import org.eclipse.swt.events.SelectionEvent; |
| import org.eclipse.swt.events.SelectionListener; |
| import org.eclipse.swt.layout.GridData; |
| import org.eclipse.swt.layout.GridLayout; |
| import org.eclipse.swt.widgets.Combo; |
| import org.eclipse.swt.widgets.Composite; |
| import org.eclipse.swt.widgets.Control; |
| import org.eclipse.swt.widgets.Display; |
| import org.eclipse.swt.widgets.Group; |
| import org.eclipse.swt.widgets.Label; |
| import org.eclipse.swt.widgets.Link; |
| import org.eclipse.ui.PlatformUI; |
| import org.eclipse.ui.dialogs.PreferencesUtil; |
| |
| /** |
| * Most of the behavior is in DatabaseGroup.... |
| * |
| * We open the wizard page with the JPA project's connection profile and |
| * default schema selected (if possible), but then the selections are driven |
| * by the user. If the user re-selects the JPA project's connection profile, |
| * we will pre-select the project's default schema if possible. |
| */ |
| public class DatabaseSchemaWizardPage extends WizardPage { |
| |
| final JpaProject jpaProject; |
| |
| private final ListenerList<Listener> listenerList = new ListenerList<Listener>(Listener.class); |
| |
| private DatabaseGroup databaseGroup; |
| |
| |
| public DatabaseSchemaWizardPage(JpaProject jpaProject) { |
| super("Database Schema"); //$NON-NLS-1$ |
| if (jpaProject == null) { |
| throw new NullPointerException(); |
| } |
| this.jpaProject = jpaProject; |
| this.setTitle(JptUiMessages.DatabaseSchemaWizardPage_title); |
| this.setMessage(JptUiMessages.DatabaseSchemaWizardPage_desc); |
| } |
| |
| public void createControl(Composite parent) { |
| this.setPageComplete(false); |
| this.setControl(this.buildTopLevelControl(parent)); |
| } |
| |
| private Control buildTopLevelControl(Composite parent) { |
| Composite composite = new Composite(parent, SWT.NULL); |
| composite.setLayout(new GridLayout()); |
| this.databaseGroup = new DatabaseGroup(composite); |
| Dialog.applyDialogFont(parent); |
| PlatformUI.getWorkbench().getHelpSystem().setHelp(composite, JpaHelpContextIds.PROPERTIES_JAVA_PERSISTENCE_CONNECTION); |
| return composite; |
| } |
| |
| public ConnectionProfile getJpaProjectConnectionProfile() { |
| return this.jpaProject.getConnectionProfile(); |
| } |
| |
| public Schema getSelectedSchema() { |
| return this.databaseGroup.getSelectedSchema(); |
| } |
| |
| @Override |
| public void dispose() { |
| this.databaseGroup.dispose(); |
| super.dispose(); |
| } |
| |
| |
| // ********** listeners ********** |
| |
| public void addListener(Listener listener) { |
| this.listenerList.add(listener); |
| } |
| |
| public void removeListener(Listener listener) { |
| this.listenerList.remove(listener); |
| } |
| |
| void fireSchemaChanged(Schema schema) { |
| this.setPageComplete(schema != null); |
| for (Listener listener : this.listenerList.getListeners()) { |
| listener.selectedSchemaChanged(schema); |
| } |
| } |
| |
| |
| // ********** listener interface ********** |
| |
| /** |
| * Allows clients to listen for changes to the selected connection profile |
| * and schema. |
| */ |
| public interface Listener extends EventListener { |
| void selectedSchemaChanged(Schema schema); |
| } |
| |
| |
| // ********** database group ********** |
| |
| /** |
| * schema combo-box |
| * add project connection link |
| * reconnect link |
| */ |
| class DatabaseGroup { |
| |
| // these are kept in synch with the selection |
| private Schema selectedSchema; |
| |
| private final Combo schemaComboBox; |
| |
| private final Link reconnectLink; |
| |
| private Link addJpaProjectConnectionLink; |
| |
| private final ConnectionListener connectionListener; |
| |
| |
| // ********** construction ********** |
| |
| DatabaseGroup(Composite composite) { |
| super(); |
| |
| Group group = new Group(composite, SWT.NONE); |
| group.setLayout(new GridLayout(2, false)); // false = do not make columns equal width |
| group.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); |
| group.setText(JptUiMessages.DatabaseSchemaWizardPage_schemaSettings); |
| // TODO PlatformUI.getWorkbench().getHelpSystem().setHelp(this.group, JpaHelpContextIds.XXX); |
| |
| // schema combo-box |
| this.buildLabel(group, 1, JptUiMessages.DatabaseSchemaWizardPage_schema); |
| this.schemaComboBox = this.buildComboBox(group, this.buildSchemaComboBoxSelectionListener()); |
| |
| String message = (this.projectHasAConnection()) ? |
| JptUiMessages.DatabaseSchemaWizardPage_schemaInfo : |
| JptUiMessages.DatabaseSchemaWizardPage_connectionInfo; |
| |
| this.buildLabel(group, 2, message); |
| |
| // add project's connection link |
| if( ! this.projectHasAConnection()) { |
| this.addJpaProjectConnectionLink = this.buildLink(group, |
| JptUiMessages.DatabaseSchemaWizardPage_addConnectionToProject, |
| this.buildAddJpaProjectConnectionLinkListener()); |
| } |
| |
| // reconnect link |
| this.reconnectLink = this.buildLink(group, JptUiMessages.DatabaseSchemaWizardPage_connectLink, this.buildReconnectLinkSelectionListener()); |
| this.reconnectLink.setEnabled(true); |
| |
| this.selectedSchema = this.getDefaultSchema(); |
| |
| if (this.selectedSchema != null) { |
| DatabaseSchemaWizardPage.this.fireSchemaChanged(this.selectedSchema); |
| } |
| |
| this.connectionListener = this.buildConnectionListener(); |
| this.addJpaProjectConnectionProfileListener(this.connectionListener); |
| |
| this.updateSchemaComboBox(); |
| this.updateReconnectLink(); |
| } |
| |
| |
| // ********** intra-wizard methods ********** |
| |
| Schema getSelectedSchema() { |
| return this.selectedSchema; |
| } |
| |
| void dispose() { |
| if(this.projectHasAConnection()) { |
| this.getJpaProjectConnectionProfile().removeConnectionListener(this.connectionListener); |
| } |
| } |
| |
| |
| // ********** internal methods ********** |
| |
| void addJpaProjectConnectionListener() { |
| this.addJpaProjectConnectionProfileListener(this.connectionListener); |
| } |
| |
| |
| private void addJpaProjectConnectionProfileListener(ConnectionListener listener) { |
| if(this.projectHasAConnection()) { |
| this.getJpaProjectConnectionProfile().addConnectionListener(listener); |
| } |
| } |
| |
| private boolean projectHasAConnection() { |
| return this.getJpaProjectConnectionProfile() != null; |
| } |
| |
| /** |
| * this can return null; |
| * called at start-up and when the selected connection profile changes |
| */ |
| private ConnectionProfile getJpaProjectConnectionProfile() { |
| return DatabaseSchemaWizardPage.this.jpaProject.getConnectionProfile(); |
| } |
| |
| /** |
| * this can return null; |
| * called at start-up and when the selected connection profile changes |
| */ |
| private Schema getDefaultSchema() { |
| return DatabaseSchemaWizardPage.this.jpaProject.getDefaultDbSchema(); |
| } |
| |
| private SchemaContainer getDefaultSchemaContainer() { |
| return DatabaseSchemaWizardPage.this.jpaProject.getDefaultDbSchemaContainer(); |
| } |
| |
| /** |
| * called at start-up and when the selected connection profile changes |
| */ |
| private void updateReconnectLink() { |
| this.reconnectLink.setEnabled(this.reconnectLinkCanBeEnabled()); |
| } |
| |
| void updateAddJpaProjectConnectionLink() { |
| this.addJpaProjectConnectionLink.setEnabled(this.addJpaProjectConnectionLinkCanBeEnabled()); |
| } |
| |
| private boolean reconnectLinkCanBeEnabled() { |
| if(this.projectHasAConnection()) { |
| return this.getJpaProjectConnectionProfile().isInactive(); |
| } |
| return false; |
| } |
| |
| private boolean addJpaProjectConnectionLinkCanBeEnabled() { |
| return ! this.projectHasAConnection(); |
| } |
| |
| /** |
| * the schema combo-box is updated at start-up and |
| * when the selected connection profile changes |
| */ |
| private void updateSchemaComboBox() { |
| this.schemaComboBox.removeAll(); |
| for (String name : this.getSchemaNames()) { |
| this.schemaComboBox.add(name); |
| } |
| // the current schema *should* be in the current connection profile |
| if (this.selectedSchema != null) { |
| this.schemaComboBox.select(this.schemaComboBox.indexOf(this.selectedSchema.getName())); |
| } |
| } |
| |
| private Iterable<String> getSchemaNames() { |
| SchemaContainer sc = this.getDefaultSchemaContainer(); |
| // use schema *names* since the combo-box is read-only |
| return (sc != null) ? sc.getSortedSchemaNames() : EmptyIterable.<String>instance(); |
| } |
| |
| // ********** listener callbacks ********** |
| |
| void selectedSchemaChanged() { |
| Schema old = this.selectedSchema; |
| this.selectedSchema = this.getDefaultSchemaContainer().getSchemaNamed(this.schemaComboBox.getText()); |
| if (this.selectedSchema != old) { |
| DatabaseSchemaWizardPage.this.fireSchemaChanged(this.selectedSchema); |
| } |
| } |
| |
| void reconnect() { |
| this.getJpaProjectConnectionProfile().connect(); |
| // everything should be synchronized when we get the resulting open event |
| } |
| |
| /** |
| * called when |
| * - a connection is set to the Jpa project |
| * - the connection was opened |
| * - the connection was closed (never happens?) |
| * we need to update the schema stuff and the reconnect link |
| */ |
| void connectionChanged() { |
| Schema old = this.selectedSchema; |
| this.selectedSchema = this.getDefaultSchema(); |
| if (this.selectedSchema != old) { |
| DatabaseSchemaWizardPage.this.fireSchemaChanged(this.selectedSchema); |
| } |
| this.updateSchemaComboBox(); |
| this.updateReconnectLink(); |
| } |
| |
| |
| // ********** listeners ********** |
| |
| private SelectionListener buildSchemaComboBoxSelectionListener() { |
| return new SelectionListener() { |
| public void widgetDefaultSelected(SelectionEvent event) { |
| // nothing special for "default" (double-click?) |
| this.widgetSelected(event); |
| } |
| public void widgetSelected(SelectionEvent event) { |
| DatabaseGroup.this.selectedSchemaChanged(); |
| } |
| @Override |
| public String toString() { |
| return "DatabaseSchemaWizardPage schema combo-box selection listener"; //$NON-NLS-1$ |
| } |
| }; |
| } |
| |
| private SelectionListener buildReconnectLinkSelectionListener() { |
| return new SelectionAdapter() { |
| @Override |
| public void widgetSelected(SelectionEvent event) { |
| DatabaseGroup.this.reconnect(); |
| } |
| @Override |
| public String toString() { |
| return "DatabaseSchemaWizardPage reconnect link selection listener"; //$NON-NLS-1$ |
| } |
| }; |
| } |
| |
| private ConnectionListener buildConnectionListener() { |
| return new ConnectionAdapter() { |
| @Override |
| public void opened(ConnectionProfile cp) { |
| this.connectionChanged(); |
| } |
| @Override // this probably won't ever get called... |
| public void closed(ConnectionProfile cp) { |
| this.connectionChanged(); |
| } |
| private void connectionChanged() { |
| Display.getDefault().asyncExec( |
| new Runnable() { |
| public void run() { |
| DatabaseGroup.this.connectionChanged(); |
| } |
| } |
| ); |
| } |
| @Override |
| public String toString() { |
| return "DatabaseSchemaWizardPage connection listener"; //$NON-NLS-1$ |
| } |
| }; |
| } |
| |
| private SelectionListener buildAddJpaProjectConnectionLinkListener() { |
| return new SelectionAdapter() { |
| @Override |
| public void widgetSelected(SelectionEvent e) { |
| DatabaseGroup.this.promptToConfigJpaProjectConnection(); |
| |
| DatabaseGroup.this.addJpaProjectConnectionListener(); |
| DatabaseGroup.this.updateAddJpaProjectConnectionLink(); |
| DatabaseGroup.this.connectionChanged(); |
| } |
| @Override |
| public String toString() { |
| return "DatabaseSchemaWizardPage AddProjectConnection link selection listener"; //$NON-NLS-1$ |
| } |
| }; |
| } |
| |
| void promptToConfigJpaProjectConnection() { |
| PreferenceDialog dialog = |
| PreferencesUtil.createPropertyDialogOn( |
| getShell(), DatabaseSchemaWizardPage.this.jpaProject.getProject(), |
| JpaProjectPropertiesPage.PROP_ID, |
| null, |
| null); |
| dialog.open(); |
| } |
| |
| // ********** UI components ********** |
| |
| /** |
| * build and return a label |
| */ |
| private Label buildLabel(Composite parent, int span, String text) { |
| Label label = new Label(parent, SWT.NONE); |
| label.setText(text); |
| GridData gd = new GridData(); |
| gd.horizontalSpan = span; |
| label.setLayoutData(gd); |
| return label; |
| } |
| |
| /** |
| * build and return a combo-box |
| */ |
| private Combo buildComboBox(Composite parent, SelectionListener listener) { |
| Combo combo = new Combo(parent, SWT.BORDER | SWT.READ_ONLY); |
| combo.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); |
| combo.addSelectionListener(listener); |
| return combo; |
| } |
| |
| /** |
| * build and return a link |
| */ |
| private Link buildLink(Composite parent, String text, SelectionListener listener) { |
| Link link = new Link(parent, SWT.NONE); |
| GridData data = new GridData(GridData.END, GridData.CENTER, false, false); |
| data.horizontalSpan = 2; |
| link.setLayoutData(data); |
| link.setText(text); |
| link.addSelectionListener(listener); |
| return link; |
| } |
| |
| } |
| |
| } |