| /******************************************************************************* |
| * Copyright (c) 2006, 2008 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 java.util.Iterator; |
| import java.util.SortedSet; |
| |
| import org.eclipse.jface.dialogs.Dialog; |
| 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.JptDbPlugin; |
| import org.eclipse.jpt.db.Schema; |
| import org.eclipse.jpt.db.SchemaContainer; |
| import org.eclipse.jpt.db.ui.internal.DTPUiTools; |
| import org.eclipse.jpt.ui.internal.JpaHelpContextIds; |
| import org.eclipse.jpt.ui.internal.JptUiMessages; |
| import org.eclipse.jpt.utility.internal.CollectionTools; |
| import org.eclipse.jpt.utility.internal.ListenerList; |
| import org.eclipse.jpt.utility.internal.iterators.EmptyIterator; |
| 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; |
| |
| /** |
| * 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 DatabaseConnectionWizardPage extends WizardPage { |
| |
| final JpaProject jpaProject; |
| |
| private final ListenerList<Listener> listenerList = new ListenerList<Listener>(Listener.class); |
| |
| private DatabaseGroup databaseGroup; |
| |
| |
| public DatabaseConnectionWizardPage(JpaProject jpaProject) { |
| super("Database Settings"); //$NON-NLS-1$ |
| if (jpaProject == null) { |
| throw new NullPointerException(); |
| } |
| this.jpaProject = jpaProject; |
| this.setTitle(JptUiMessages.DatabaseConnectionWizardPage_databaseConnection); |
| this.setMessage(JptUiMessages.DatabaseConnectionWizardPage_connectToDatabase); |
| } |
| |
| 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 getSelectedConnectionProfile() { |
| return this.databaseGroup.getSelectedConnectionProfile(); |
| } |
| |
| 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 fireConnectionProfileChanged(ConnectionProfile connectionProfile) { |
| for (Listener listener : this.listenerList.getListeners()) { |
| listener.selectedConnectionProfileChanged(connectionProfile); |
| } |
| } |
| |
| 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 selectedConnectionProfileChanged(ConnectionProfile connectionProfile); |
| void selectedSchemaChanged(Schema schema); |
| } |
| |
| |
| // ********** database group ********** |
| |
| /** |
| * connection combo-box |
| * schema combo-box |
| * add connection link |
| * reconnect link |
| */ |
| class DatabaseGroup { |
| |
| // these are kept in synch with the selection |
| private ConnectionProfile selectedConnectionProfile; |
| private Schema selectedSchema; |
| |
| private final Combo connectionComboBox; |
| |
| private final Combo schemaComboBox; |
| |
| private final Link reconnectLink; |
| |
| 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.DatabaseConnectionWizardPage_database); |
| // TODO PlatformUI.getWorkbench().getHelpSystem().setHelp(this.group, JpaHelpContextIds.XXX); |
| |
| // connection combo-box |
| this.buildLabel(group, 1, JptUiMessages.DatabaseConnectionWizardPage_connection); |
| this.connectionComboBox = this.buildComboBox(group, this.buildConnectionComboBoxSelectionListener()); |
| |
| // schema combo-box |
| this.buildLabel(group, 1, JptUiMessages.DatabaseConnectionWizardPage_schema); |
| this.schemaComboBox = this.buildComboBox(group, this.buildSchemaComboBoxSelectionListener()); |
| this.buildLabel(group, 2, JptUiMessages.DatabaseConnectionWizardPage_schemaInfo); |
| |
| // add connection link |
| this.buildLink(group, JptUiMessages.DatabaseConnectionWizardPage_addConnectionLink, this.buildAddConnectionLinkSelectionListener()); |
| |
| // reconnect link |
| this.reconnectLink = this.buildLink(group, JptUiMessages.DatabaseConnectionWizardPage_connectLink, this.buildReconnectLinkSelectionListener()); |
| |
| this.connectionListener = this.buildConnectionListener(); |
| |
| // initialize state, based on JPA project |
| this.selectedConnectionProfile = this.getJpaProjectConnectionProfile(); |
| this.selectedSchema = this.getDefaultSchema(); |
| |
| if (this.selectedSchema != null) { |
| DatabaseConnectionWizardPage.this.fireSchemaChanged(this.selectedSchema); |
| } |
| if (this.selectedConnectionProfile != null) { |
| this.selectedConnectionProfile.addConnectionListener(this.connectionListener); |
| DatabaseConnectionWizardPage.this.fireConnectionProfileChanged(this.selectedConnectionProfile); |
| } |
| |
| this.updateConnectionComboBox(); |
| this.updateSchemaComboBox(); |
| this.updateReconnectLink(); |
| } |
| |
| |
| // ********** intra-wizard methods ********** |
| |
| ConnectionProfile getSelectedConnectionProfile() { |
| return this.selectedConnectionProfile; |
| } |
| |
| Schema getSelectedSchema() { |
| return this.selectedSchema; |
| } |
| |
| void dispose() { |
| if (this.selectedConnectionProfile != null) { |
| this.selectedConnectionProfile.removeConnectionListener(this.connectionListener); |
| } |
| } |
| |
| |
| // ********** internal methods ********** |
| |
| /** |
| * this can return null; |
| * called at start-up and when the selected connection profile changes |
| */ |
| private ConnectionProfile getJpaProjectConnectionProfile() { |
| return DatabaseConnectionWizardPage.this.jpaProject.getConnectionProfile(); |
| } |
| |
| /** |
| * this can return null; |
| * called at start-up and when the selected connection profile changes |
| */ |
| private Schema getDefaultSchema() { |
| return (this.selectedConnectionProfile == this.getJpaProjectConnectionProfile()) ? |
| DatabaseConnectionWizardPage.this.jpaProject.getDefaultDbSchema() |
| : |
| null; |
| } |
| |
| /** |
| * the connection combo-box is updated at start-up and when the user |
| * adds a connection profile |
| */ |
| private void updateConnectionComboBox() { |
| this.connectionComboBox.removeAll(); |
| for (String cpName : this.buildSortedConnectionProfileNames()) { |
| this.connectionComboBox.add(cpName); |
| } |
| if (this.selectedConnectionProfile != null) { |
| this.connectionComboBox.select(this.connectionComboBox.indexOf(this.selectedConnectionProfile.getName())); |
| } |
| } |
| |
| private SortedSet<String> buildSortedConnectionProfileNames() { |
| return CollectionTools.sortedSet(JptDbPlugin.instance().getConnectionProfileFactory().connectionProfileNames()); |
| } |
| |
| /** |
| * called at start-up and when the selected connection profile changes |
| */ |
| private void updateReconnectLink() { |
| this.reconnectLink.setEnabled(this.reconnectLinkCanBeEnabled()); |
| } |
| |
| private boolean reconnectLinkCanBeEnabled() { |
| return (this.selectedConnectionProfile != null) && this.selectedConnectionProfile.isInactive(); |
| } |
| |
| /** |
| * the schema combo-box is updated at start-up and |
| * when the selected connection profile changes |
| */ |
| private void updateSchemaComboBox() { |
| this.schemaComboBox.removeAll(); |
| for (Iterator<String> stream = this.getSchemata(); stream.hasNext(); ) { |
| this.schemaComboBox.add(stream.next()); |
| } |
| // the current schema *should* be in the current connection profile |
| if (this.selectedSchema != null) { |
| this.schemaComboBox.select(this.schemaComboBox.indexOf(this.selectedSchema.getIdentifier())); |
| } |
| } |
| |
| private Iterator<String> getSchemata() { |
| SchemaContainer sc = DatabaseConnectionWizardPage.this.jpaProject.getDefaultDbSchemaContainer(); |
| return (sc == null) ? EmptyIterator.<String>instance() : sc.sortedSchemaIdentifiers(); |
| } |
| |
| /** |
| * If the specified name matches the name of the JPA project's |
| * connection profile, return it; otherwise, build a new connection |
| * profile. |
| */ |
| private ConnectionProfile checkJpaProjectConnectionProfile(String cpName) { |
| ConnectionProfile cp = this.getJpaProjectConnectionProfile(); |
| if ((cp != null) && cp.getName().equals(cpName)) { |
| return cp; |
| } |
| return this.buildConnectionProfile(cpName); |
| } |
| |
| private ConnectionProfile buildConnectionProfile(String name) { |
| return JptDbPlugin.instance().getConnectionProfileFactory().buildConnectionProfile(name); |
| } |
| |
| |
| // ********** listener callbacks ********** |
| |
| void selectedConnectionChanged() { |
| String text = this.connectionComboBox.getText(); |
| if (text.length() == 0) { |
| if (this.selectedConnectionProfile == null) { |
| return; // no change |
| } |
| this.selectedConnectionProfile.removeConnectionListener(this.connectionListener); |
| this.selectedConnectionProfile = null; |
| } else { |
| if (this.selectedConnectionProfile == null) { |
| this.selectedConnectionProfile = this.checkJpaProjectConnectionProfile(text); |
| } else { |
| if (text.equals(this.selectedConnectionProfile.getName())) { |
| return; // no change |
| } |
| this.selectedConnectionProfile.removeConnectionListener(this.connectionListener); |
| this.selectedConnectionProfile = this.checkJpaProjectConnectionProfile(text); |
| } |
| this.selectedConnectionProfile.addConnectionListener(this.connectionListener); |
| } |
| this.connectionChanged(); |
| DatabaseConnectionWizardPage.this.fireConnectionProfileChanged(this.selectedConnectionProfile); |
| } |
| |
| void selectedSchemaChanged() { |
| Schema old = this.selectedSchema; |
| this.selectedSchema = this.selectedConnectionProfile.getDatabase().getSchemaForIdentifier(this.schemaComboBox.getText()); |
| if (this.selectedSchema != old) { |
| DatabaseConnectionWizardPage.this.fireSchemaChanged(this.selectedSchema); |
| } |
| } |
| |
| /** |
| * Open the DTP New Connection Profile wizard. |
| * If the user creates a new connection profile, start using it and |
| * connect it |
| */ |
| void addConnection() { |
| String addedProfileName = DTPUiTools.createNewConnectionProfile(); |
| if (addedProfileName == null) { |
| return; // user pressed "Cancel" |
| } |
| if (this.selectedConnectionProfile != null) { |
| this.selectedConnectionProfile.removeConnectionListener(this.connectionListener); |
| } |
| this.selectedConnectionProfile = this.buildConnectionProfile(addedProfileName); |
| this.selectedConnectionProfile.addConnectionListener(this.connectionListener); |
| this.updateConnectionComboBox(); |
| this.selectedConnectionProfile.connect(); |
| // everything else should be synchronized when we get the resulting open event |
| DatabaseConnectionWizardPage.this.fireConnectionProfileChanged(this.selectedConnectionProfile); |
| } |
| |
| void reconnect() { |
| this.selectedConnectionProfile.connect(); |
| // everything should be synchronized when we get the resulting open event |
| } |
| |
| /** |
| * called when |
| * - the user selects a new connection |
| * - 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) { |
| DatabaseConnectionWizardPage.this.fireSchemaChanged(this.selectedSchema); |
| } |
| this.updateSchemaComboBox(); |
| this.updateReconnectLink(); |
| } |
| |
| |
| // ********** listeners ********** |
| |
| private SelectionListener buildConnectionComboBoxSelectionListener() { |
| return new SelectionListener() { |
| public void widgetDefaultSelected(SelectionEvent event) { |
| // nothing special for "default" (double-click?) |
| this.widgetSelected(event); |
| } |
| public void widgetSelected(SelectionEvent event) { |
| DatabaseGroup.this.selectedConnectionChanged(); |
| } |
| @Override |
| public String toString() { |
| return "DatabaseConnectionWizardPage connection combo-box selection listener"; //$NON-NLS-1$ |
| } |
| }; |
| } |
| |
| 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 "DatabaseConnectionWizardPage schema combo-box selection listener"; //$NON-NLS-1$ |
| } |
| }; |
| } |
| |
| private SelectionListener buildAddConnectionLinkSelectionListener() { |
| return new SelectionAdapter() { |
| @Override |
| public void widgetSelected(SelectionEvent event) { |
| DatabaseGroup.this.addConnection(); |
| } |
| @Override |
| public String toString() { |
| return "DatabaseConnectionWizardPage add connection link 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 "DatabaseConnectionWizardPage 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 "DatabaseConnectionWizardPage connection listener"; //$NON-NLS-1$ |
| } |
| }; |
| } |
| |
| |
| // ********** 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; |
| } |
| |
| } |
| |
| } |