blob: ae844d24df5b0a8e18246b4cfe4bd0f3d0893bf5 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2007, 2015 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.ui.internal.properties;
import static org.eclipse.jst.common.project.facet.ui.libprov.LibraryProviderFrameworkUi.createInstallLibraryPanel;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.jdt.core.ElementChangedEvent;
import org.eclipse.jdt.core.IElementChangedListener;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaElementDelta;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jpt.common.core.internal.utility.ICUStringCollator;
import org.eclipse.jpt.common.ui.internal.WorkbenchTools;
import org.eclipse.jpt.common.ui.internal.properties.JptProjectPropertiesPage;
import org.eclipse.jpt.common.ui.internal.swt.bindings.SWTBindingTools;
import org.eclipse.jpt.common.ui.internal.swt.listeners.SWTListenerTools;
import org.eclipse.jpt.common.ui.internal.swt.widgets.ControlTools;
import org.eclipse.jpt.common.utility.internal.BitTools;
import org.eclipse.jpt.common.utility.internal.ObjectTools;
import org.eclipse.jpt.common.utility.internal.StringTools;
import org.eclipse.jpt.common.utility.internal.collection.CollectionTools;
import org.eclipse.jpt.common.utility.internal.iterable.EmptyIterable;
import org.eclipse.jpt.common.utility.internal.iterable.IterableTools;
import org.eclipse.jpt.common.utility.internal.model.value.AbstractCollectionValueModel;
import org.eclipse.jpt.common.utility.internal.model.value.AspectCollectionValueModelAdapter;
import org.eclipse.jpt.common.utility.internal.model.value.AspectPropertyValueModelAdapter;
import org.eclipse.jpt.common.utility.internal.model.value.BufferedModifiablePropertyValueModel;
import org.eclipse.jpt.common.utility.internal.model.value.CompositeCollectionValueModel;
import org.eclipse.jpt.common.utility.internal.model.value.CompositePropertyValueModel;
import org.eclipse.jpt.common.utility.internal.model.value.DoublePropertyValueModel;
import org.eclipse.jpt.common.utility.internal.model.value.ExtendedListValueModelWrapper;
import org.eclipse.jpt.common.utility.internal.model.value.PredicatePropertyValueModel;
import org.eclipse.jpt.common.utility.internal.model.value.PropertyAspectAdapter;
import org.eclipse.jpt.common.utility.internal.model.value.PropertyCollectionValueModelAdapter;
import org.eclipse.jpt.common.utility.internal.model.value.SetCollectionValueModel;
import org.eclipse.jpt.common.utility.internal.model.value.SortedListValueModelAdapter;
import org.eclipse.jpt.common.utility.internal.model.value.StaticCollectionValueModel;
import org.eclipse.jpt.common.utility.internal.model.value.TransformationModifiablePropertyValueModel;
import org.eclipse.jpt.common.utility.internal.model.value.TransformationPropertyValueModel;
import org.eclipse.jpt.common.utility.internal.predicate.PredicateAdapter;
import org.eclipse.jpt.common.utility.internal.predicate.PredicateTools;
import org.eclipse.jpt.common.utility.internal.transformer.AbstractTransformer;
import org.eclipse.jpt.common.utility.internal.transformer.TransformerAdapter;
import org.eclipse.jpt.common.utility.internal.transformer.TransformerTools;
import org.eclipse.jpt.common.utility.model.Model;
import org.eclipse.jpt.common.utility.model.event.PropertyChangeEvent;
import org.eclipse.jpt.common.utility.model.listener.PropertyChangeAdapter;
import org.eclipse.jpt.common.utility.model.listener.PropertyChangeListener;
import org.eclipse.jpt.common.utility.model.value.CollectionValueModel;
import org.eclipse.jpt.common.utility.model.value.ListValueModel;
import org.eclipse.jpt.common.utility.model.value.ModifiablePropertyValueModel;
import org.eclipse.jpt.common.utility.model.value.PropertyValueModel;
import org.eclipse.jpt.common.utility.predicate.Predicate;
import org.eclipse.jpt.common.utility.transformer.Transformer;
import org.eclipse.jpt.jpa.core.JpaDataSource;
import org.eclipse.jpt.jpa.core.JpaModel;
import org.eclipse.jpt.jpa.core.JpaPlatform;
import org.eclipse.jpt.jpa.core.JpaPreferences;
import org.eclipse.jpt.jpa.core.JpaProject;
import org.eclipse.jpt.jpa.core.JpaWorkspace;
import org.eclipse.jpt.jpa.core.JptJpaCoreMessages;
import org.eclipse.jpt.jpa.core.jpa2.JpaProject2_0;
import org.eclipse.jpt.jpa.core.libprov.JpaLibraryProviderInstallOperationConfig;
import org.eclipse.jpt.jpa.core.platform.JpaPlatformManager;
import org.eclipse.jpt.jpa.db.Catalog;
import org.eclipse.jpt.jpa.db.ConnectionAdapter;
import org.eclipse.jpt.jpa.db.ConnectionListener;
import org.eclipse.jpt.jpa.db.ConnectionProfile;
import org.eclipse.jpt.jpa.db.ConnectionProfileAdapter;
import org.eclipse.jpt.jpa.db.ConnectionProfileFactory;
import org.eclipse.jpt.jpa.db.ConnectionProfileListener;
import org.eclipse.jpt.jpa.db.Database;
import org.eclipse.jpt.jpa.db.SchemaContainer;
import org.eclipse.jpt.jpa.db.ui.internal.DTPUiTools;
import org.eclipse.jpt.jpa.ui.JpaProjectModel;
import org.eclipse.jpt.jpa.ui.JpaWorkbench;
import org.eclipse.jpt.jpa.ui.JptJpaUiMessages;
import org.eclipse.jpt.jpa.ui.internal.JpaHelpContextIds;
import org.eclipse.jpt.jpa.ui.internal.plugin.JptJpaUiPlugin;
import org.eclipse.jst.common.project.facet.core.libprov.ILibraryProvider;
import org.eclipse.jst.common.project.facet.core.libprov.LibraryInstallDelegate;
import org.eclipse.jst.common.project.facet.core.libprov.LibraryProviderOperationConfig;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Link;
import org.eclipse.ui.preferences.IWorkbenchPreferenceContainer;
import org.eclipse.wst.common.project.facet.core.IFacetedProject;
import org.eclipse.wst.common.project.facet.core.IProjectFacetVersion;
/**
* Way more complicated UI than you would think....
*/
public class JpaProjectPropertiesPage
extends JptProjectPropertiesPage
{
public static final String PROP_ID = "org.eclipse.jpt.jpa.ui.jpaProjectProperties"; //$NON-NLS-1$
private PropertyValueModel<JpaProject> jpaProjectModel;
private PropertyValueModel<Boolean> jpaProjectIsNotNullFlagModel;
private BufferedModifiablePropertyValueModel<JpaPlatform.Config> jpaPlatformConfigModel;
private PropertyChangeListener jpaPlatformConfigListener;
private BufferedModifiablePropertyValueModel<String> connectionModel;
private PropertyValueModel<ConnectionProfile> connectionProfileModel;
private PropertyValueModel<Boolean> disconnectedModel;
private PropertyChangeListener disconnectedModelListener;
private Link connectLink;
private BufferedModifiablePropertyValueModel<Boolean> userOverrideDefaultCatalogFlagModel;
private BufferedModifiablePropertyValueModel<String> userOverrideDefaultCatalogModel;
private ModifiablePropertyValueModel<String> defaultCatalogModel;
private ListValueModel<String> catalogChoicesModel;
private BufferedModifiablePropertyValueModel<Boolean> userOverrideDefaultSchemaFlagModel;
private BufferedModifiablePropertyValueModel<String> userOverrideDefaultSchemaModel;
private ModifiablePropertyValueModel<String> defaultSchemaModel;
private ListValueModel<String> schemaChoicesModel;
private BufferedModifiablePropertyValueModel<Boolean> discoverAnnotatedClassesModel;
private ModifiablePropertyValueModel<Boolean> listAnnotatedClassesModel;
private PropertyValueModel<Boolean> jpa2_0ProjectFlagModel;
private BufferedModifiablePropertyValueModel<String> metamodelSourceFolderModel;
private ListValueModel<String> javaSourceFolderChoicesModel;
private static final String BUILD_PATHS_PROPERTY_PAGE_ID = "org.eclipse.jdt.ui.propertyPages.BuildPathsPropertyPage"; //$NON-NLS-1$
/* private */ static final Comparator<String> STRING_COMPARATOR = new ICUStringCollator();
// ************ construction ************
public JpaProjectPropertiesPage() {
super();
}
@Override
protected void buildModels() {
this.jpaProjectModel = this.buildJpaProjectModel();
this.jpaProjectIsNotNullFlagModel = this.buildJpaProjectIsNotNullFlagModel();
this.jpaPlatformConfigModel = this.buildJpaPlatformConfigModel();
this.jpaPlatformConfigListener = this.buildJpaPlatformConfigListener();
this.connectionModel = this.buildConnectionModel();
this.connectionProfileModel = this.buildConnectionProfileModel();
this.disconnectedModel = this.buildDisconnectedModel();
this.disconnectedModelListener = this.buildDisconnectedModelListener();
this.userOverrideDefaultCatalogFlagModel = this.buildUserOverrideDefaultCatalogFlagModel();
this.userOverrideDefaultCatalogModel = this.buildUserOverrideDefaultCatalogModel();
this.defaultCatalogModel = this.buildDefaultCatalogModel();
this.catalogChoicesModel = this.buildCatalogChoicesModel();
this.userOverrideDefaultSchemaFlagModel = this.buildUserOverrideDefaultSchemaFlagModel();
this.userOverrideDefaultSchemaModel = this.buildUserOverrideDefaultSchemaModel();
this.defaultSchemaModel = this.buildDefaultSchemaModel();
this.schemaChoicesModel = this.buildSchemaChoicesModel();
this.discoverAnnotatedClassesModel = this.buildDiscoverAnnotatedClassesModel();
this.listAnnotatedClassesModel = this.buildListAnnotatedClassesModel();
this.jpa2_0ProjectFlagModel = this.buildJpa2_0ProjectFlagModel();
this.metamodelSourceFolderModel = this.buildMetamodelSourceFolderModel();
this.javaSourceFolderChoicesModel = this.buildJavaSourceFolderChoicesModel();
}
// ***** JPA project model
private PropertyValueModel<JpaProject> buildJpaProjectModel() {
return new DoublePropertyValueModel<JpaProject>(this.buildJpaProjectModelModel());
}
private PropertyValueModel<PropertyValueModel<JpaProject>> buildJpaProjectModelModel() {
return new TransformationPropertyValueModel<IProject, PropertyValueModel<JpaProject>>(this.projectModel, JPA_PROJECT_MODEL_TRANSFORMER);
}
private static final Transformer<IProject, PropertyValueModel<JpaProject>> JPA_PROJECT_MODEL_TRANSFORMER = new JpaProjectModelTransformer();
/* CU private */ static class JpaProjectModelTransformer
extends AbstractTransformer<IProject, PropertyValueModel<JpaProject>>
{
@Override
protected PropertyValueModel<JpaProject> transform_(IProject project) {
return (JpaProjectModel) project.getAdapter(JpaProjectModel.class);
}
}
// ***** JPA project is not null model
private PropertyValueModel<Boolean> buildJpaProjectIsNotNullFlagModel() {
return new PredicatePropertyValueModel<JpaProject>(this.jpaProjectModel, PredicateTools.isNotNull());
}
// ***** JPA platform config model
private BufferedModifiablePropertyValueModel<JpaPlatform.Config> buildJpaPlatformConfigModel() {
return new BufferedModifiablePropertyValueModel<JpaPlatform.Config>(new JpaPlatformConfigModel(this.jpaProjectModel), this.trigger);
}
private PropertyChangeListener buildJpaPlatformConfigListener(){
return new JpaPlatformConfigListener();
}
/* CU private */ class JpaPlatformConfigListener
extends PropertyChangeAdapter
{
@Override
public void propertyChanged(PropertyChangeEvent event) {
JpaProjectPropertiesPage.this.jpaPlatformConfigChanged();
}
}
void jpaPlatformConfigChanged() {
if ( ! this.getControl().isDisposed()) {
// handle null, in the case the jpa facet is changed via the facets page,
// the library install delegate is temporarily null
this.adjustLibraryProviders();
}
}
// ***** connection models
private BufferedModifiablePropertyValueModel<String> buildConnectionModel() {
return new BufferedModifiablePropertyValueModel<String>(new ConnectionModel(this.jpaProjectModel), this.trigger);
}
private PropertyValueModel<ConnectionProfile> buildConnectionProfileModel() {
return new ConnectionProfileModel(this.connectionModel);
}
private PropertyValueModel<Boolean> buildDisconnectedModel() {
return new DisconnectedModel(this.connectionProfileModel);
}
// ***** catalog models
private BufferedModifiablePropertyValueModel<Boolean> buildUserOverrideDefaultCatalogFlagModel() {
return new BufferedModifiablePropertyValueModel<Boolean>(new UserOverrideDefaultCatalogFlagModel(this.jpaProjectModel), this.trigger);
}
private BufferedModifiablePropertyValueModel<String> buildUserOverrideDefaultCatalogModel() {
return new BufferedModifiablePropertyValueModel<String>(new UserOverrideDefaultCatalogModel(this.jpaProjectModel), this.trigger);
}
private ModifiablePropertyValueModel<String> buildDefaultCatalogModel() {
return new DefaultModel(
this.userOverrideDefaultCatalogFlagModel,
this.userOverrideDefaultCatalogModel,
this.buildDatabaseDefaultCatalogModel()
);
}
private PropertyValueModel<String> buildDatabaseDefaultCatalogModel() {
return new DatabaseDefaultCatalogModel(this.connectionProfileModel);
}
/**
* Add the default catalog if it is not on the list from the database
*/
private ListValueModel<String> buildCatalogChoicesModel() {
return new SortedListValueModelAdapter<String>(this.buildUnsortedCatalogChoicesModel(), STRING_COMPARATOR);
}
/**
* Add the default catalog if it is not on the list from the database
*/
@SuppressWarnings("unchecked")
private CollectionValueModel<String> buildUnsortedCatalogChoicesModel() {
return new SetCollectionValueModel<String>(
CompositeCollectionValueModel.forModels(
new PropertyCollectionValueModelAdapter<String>(this.defaultCatalogModel),
this.buildDatabaseCatalogChoicesModel()
)
);
}
private CollectionValueModel<String> buildDatabaseCatalogChoicesModel() {
return new DatabaseCatalogChoicesModel(this.connectionProfileModel);
}
// ***** schema models
private BufferedModifiablePropertyValueModel<Boolean> buildUserOverrideDefaultSchemaFlagModel() {
return new BufferedModifiablePropertyValueModel<Boolean>(new UserOverrideDefaultSchemaFlagModel(this.jpaProjectModel), this.trigger);
}
private BufferedModifiablePropertyValueModel<String> buildUserOverrideDefaultSchemaModel() {
return new BufferedModifiablePropertyValueModel<String>(new UserOverrideDefaultSchemaModel(this.jpaProjectModel), this.trigger);
}
private ModifiablePropertyValueModel<String> buildDefaultSchemaModel() {
return new DefaultModel(
this.userOverrideDefaultSchemaFlagModel,
this.userOverrideDefaultSchemaModel,
this.buildDatabaseDefaultSchemaModel()
);
}
private PropertyValueModel<String> buildDatabaseDefaultSchemaModel() {
return new DatabaseDefaultSchemaModel(this.connectionProfileModel, this.defaultCatalogModel);
}
/**
* Add the default catalog if it is not on the list from the database
*/
private ListValueModel<String> buildSchemaChoicesModel() {
return new SortedListValueModelAdapter<String>(this.buildUnsortedSchemaChoicesModel(), STRING_COMPARATOR);
}
@SuppressWarnings("unchecked")
private CollectionValueModel<String> buildUnsortedSchemaChoicesModel() {
return new SetCollectionValueModel<String>(
CompositeCollectionValueModel.forModels(
new PropertyCollectionValueModelAdapter<String>(this.defaultSchemaModel),
this.buildDatabaseSchemaChoicesModel()
)
);
}
private CollectionValueModel<String> buildDatabaseSchemaChoicesModel() {
return new DatabaseSchemaChoicesModel(this.connectionProfileModel, this.defaultCatalogModel);
}
// ***** discover/list annotated classes models
private BufferedModifiablePropertyValueModel<Boolean> buildDiscoverAnnotatedClassesModel() {
return new BufferedModifiablePropertyValueModel<Boolean>(new DiscoverAnnotatedClassesModel(this.jpaProjectModel), this.trigger);
}
/**
* The opposite of the "discover annotated classes" flag.
*/
private ModifiablePropertyValueModel<Boolean> buildListAnnotatedClassesModel() {
return new TransformationModifiablePropertyValueModel<Boolean, Boolean>(this.discoverAnnotatedClassesModel, TransformerTools.notBooleanTransformer(), TransformerTools.notBooleanTransformer());
}
// ***** JPA 2.0 project flag
private PropertyValueModel<Boolean> buildJpa2_0ProjectFlagModel() {
return new PredicatePropertyValueModel<JpaProject>(this.jpaProjectModel, IS_COMPATIBLE_WITH_JPA_2_0);
}
private static final Predicate<JpaModel> IS_COMPATIBLE_WITH_JPA_2_0 = PredicateTools.nullCheck(new JpaModel.JpaVersionIsCompatibleWith(JpaProject2_0.FACET_VERSION_STRING));
// ***** metamodel models
private BufferedModifiablePropertyValueModel<String> buildMetamodelSourceFolderModel() {
return new BufferedModifiablePropertyValueModel<String>(new MetamodelSourceFolderModel(this.jpaProjectModel), this.trigger);
}
private ListValueModel<String> buildJavaSourceFolderChoicesModel() {
// by default, ExtendedListValueModelWrapper puts a null at the top of the list
return new ExtendedListValueModelWrapper<String>(
new SortedListValueModelAdapter<String>(
new JavaSourceFolderChoicesModel(this.jpaProjectModel),
STRING_COMPARATOR
)
);
}
// ********** convenience methods **********
private String getConnectionName() {
return this.connectionModel.getValue();
}
private ConnectionProfile getConnectionProfile() {
return this.connectionProfileModel.getValue();
}
private boolean userOverrideDefaultCatalogFlagIsSet() {
return flagIsSet(this.userOverrideDefaultCatalogFlagModel);
}
private String getUserOverrideDefaultCatalog() {
return this.userOverrideDefaultCatalogModel.getValue();
}
private boolean userOverrideDefaultSchemaFlagIsSet() {
return flagIsSet(this.userOverrideDefaultSchemaFlagModel);
}
private String getUserOverrideDefaultSchema() {
return this.userOverrideDefaultSchemaModel.getValue();
}
private IWorkbenchPreferenceContainer getWorkbenchPreferenceContainer() {
IWorkbenchPreferenceContainer container= (IWorkbenchPreferenceContainer) this.getContainer();
return container;
}
// ********** LibraryFacetPropertyPage implementation **********
@Override
public IProjectFacetVersion getProjectFacetVersion() {
return this.getFacetedProject().getInstalledVersion(JpaProject.FACET);
}
@Override
protected LibraryInstallDelegate createLibraryInstallDelegate(IFacetedProject project, IProjectFacetVersion fv) {
Map<String, Object> enablementVariables = new HashMap<String, Object>();
//TODO Ask Paul about these empty enablement variables - trying to reproduce Helios functionality
enablementVariables.put(JpaLibraryProviderInstallOperationConfig.JPA_PLATFORM_ENABLEMENT_EXP, ""); //$NON-NLS-1$
enablementVariables.put(JpaLibraryProviderInstallOperationConfig.JPA_PLATFORM_DESCRIPTION_ENABLEMENT_EXP, new EmptyJpaPlatformConfig());
LibraryInstallDelegate lid = new LibraryInstallDelegate(project, fv, enablementVariables);
lid.addListener(this.buildLibraryProviderListener());
return lid;
}
/* CU private */ class EmptyJpaPlatformConfig
implements JpaPlatform.Config
{
public JpaPlatformManager getJpaPlatformManager() {
return null;
}
public JpaPlatform getJpaPlatform() {
return null;
}
public IProjectFacetVersion getJpaFacetVersion() {
return null;
}
public boolean supportsJpaFacetVersion(IProjectFacetVersion jpaFacetVersion) {
return false;
}
public boolean isDefault() {
return false;
}
public String getPluginId() {
return null;
}
public String getLabel() {
return null;
}
public String getId() {
return null;
}
public JpaPlatform.GroupConfig getGroupConfig() {
return null;
}
public String getFactoryClassName() {
return null;
}
}
@Override
protected void adjustLibraryProviders() {
LibraryInstallDelegate lid = this.getLibraryInstallDelegate();
if (lid == null) {
return;
}
JpaPlatform.Config jpaPlatformConfig = this.jpaPlatformConfigModel.getValue();
String jpaPlatformID = (jpaPlatformConfig == null) ? "" : jpaPlatformConfig.getId(); //$NON-NLS-1$
lid.setEnablementContextVariable(JpaLibraryProviderInstallOperationConfig.JPA_PLATFORM_ENABLEMENT_EXP, jpaPlatformID);
lid.setEnablementContextVariable(JpaLibraryProviderInstallOperationConfig.JPA_PLATFORM_DESCRIPTION_ENABLEMENT_EXP, jpaPlatformConfig);
ArrayList<JpaLibraryProviderInstallOperationConfig> jpaConfigs = new ArrayList<JpaLibraryProviderInstallOperationConfig>();
// add the currently selected one first
JpaLibraryProviderInstallOperationConfig currentJpaConfig = null;
LibraryProviderOperationConfig config = lid.getLibraryProviderOperationConfig();
if (config instanceof JpaLibraryProviderInstallOperationConfig) {
currentJpaConfig = (JpaLibraryProviderInstallOperationConfig) config;
jpaConfigs.add(currentJpaConfig);
}
for (ILibraryProvider lp : lid.getLibraryProviders()) {
config = lid.getLibraryProviderOperationConfig(lp);
if ((config instanceof JpaLibraryProviderInstallOperationConfig)
&& ! config.equals(currentJpaConfig)) {
jpaConfigs.add((JpaLibraryProviderInstallOperationConfig) config);
}
}
for (JpaLibraryProviderInstallOperationConfig jpaConfig : jpaConfigs) {
jpaConfig.setJpaPlatformConfig(jpaPlatformConfig);
}
}
// ********** page **********
@Override
protected void createWidgets(Composite parent) {
this.buildPlatformGroup(parent);
Control libraryProviderComposite = createInstallLibraryPanel(
parent,
this.getLibraryInstallDelegate(),
JptJpaUiMessages.JPA_FACET_WIZARD_PAGE_JPA_IMPLEMENTATION_LABEL);
libraryProviderComposite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
SWTBindingTools.bindEnabledState(this.jpaProjectIsNotNullFlagModel, libraryProviderComposite);
this.buildConnectionGroup(parent);
this.buildPersistentClassManagementGroup(parent);
this.buildMetamodelGroup(parent);
WorkbenchTools.setHelp(parent, JpaHelpContextIds.PROPERTIES_JAVA_PERSISTENCE);
}
@Override
protected void engageListeners_() {
super.engageListeners_();
this.jpaPlatformConfigModel.addPropertyChangeListener(PropertyValueModel.VALUE, this.jpaPlatformConfigListener);
this.disconnectedModel.addPropertyChangeListener(PropertyValueModel.VALUE, this.disconnectedModelListener);
}
@Override
protected void disengageListeners_() {
this.jpaPlatformConfigModel.removePropertyChangeListener(PropertyValueModel.VALUE, this.jpaPlatformConfigListener);
this.disconnectedModel.removePropertyChangeListener(PropertyValueModel.VALUE, this.disconnectedModelListener);
super.disengageListeners_();
}
// ********** platform group **********
private void buildPlatformGroup(Composite composite) {
Group group = new Group(composite, SWT.NONE);
group.setText(JptJpaUiMessages.JPA_FACET_WIZARD_PAGE_PLATFORM_LABEL);
group.setLayout(new GridLayout());
group.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
Combo jpaPlatformDropDown = this.buildDropDown(group);
SWTBindingTools.bindDropDownListBox(
this.buildJpaPlatformConfigChoicesModel(),
this.jpaPlatformConfigModel,
jpaPlatformDropDown,
JPA_PLATFORM_CONFIG_LABEL_CONVERTER);
Link facetsPageLink = this.buildFacetsPageLink(group, JptJpaUiMessages.JPA_FACET_WIZARD_PAGE_FACETS_PAGE_LINK);
SWTBindingTools.bindEnabledState(this.jpaProjectIsNotNullFlagModel, group, jpaPlatformDropDown, facetsPageLink);
}
/**
* Add the project's JPA platform if it is not on the list of valid
* JPA platforms.
* <p>
* This is probably only useful if the project is corrupted
* and has a JPA platform that exists in the registry but is not on the
* list of valid JPA platforms for the project's JPA facet version.
* Because, if the project's JPA platform is completely invalid, there
* would be no JPA project!
*/
private ListValueModel<JpaPlatform.Config> buildJpaPlatformConfigChoicesModel() {
return new SortedListValueModelAdapter<JpaPlatform.Config>(
new SetCollectionValueModel<JpaPlatform.Config>(
CompositeCollectionValueModel.forModels(
this.buildJpaPlatformConfigChoicesModels()
)
),
JPA_PLATFORM_CONFIG_COMPARATOR
);
}
@SuppressWarnings("unchecked")
private CollectionValueModel<JpaPlatform.Config>[] buildJpaPlatformConfigChoicesModels() {
return new CollectionValueModel[] {
new PropertyCollectionValueModelAdapter<JpaPlatform.Config>(this.jpaPlatformConfigModel),
this.buildEnabledJpaPlatformConfigsModel()
};
}
/**
* Return only the JPA platform configs that support the project's
* JPA facet version.
*/
private CollectionValueModel<JpaPlatform.Config> buildEnabledJpaPlatformConfigsModel() {
return new StaticCollectionValueModel<JpaPlatform.Config>(
IterableTools.filter(
getJpaPlatformConfigs(),
new JpaPlatformConfigIsEnabled()
)
);
}
/* CU private */ class JpaPlatformConfigIsEnabled
extends PredicateAdapter<JpaPlatform.Config>
{
@Override
public boolean evaluate(JpaPlatform.Config config) {
return config.supportsJpaFacetVersion(JpaProjectPropertiesPage.this.getProjectFacetVersion());
}
}
private static final Comparator<JpaPlatform.Config> JPA_PLATFORM_CONFIG_COMPARATOR = new JpaPlatformConfigComparator();
/* CU private */ static class JpaPlatformConfigComparator
implements Comparator<JpaPlatform.Config>
{
public int compare(JpaPlatform.Config config1, JpaPlatform.Config config2) {
return STRING_COMPARATOR.compare(config1.getLabel(), config2.getLabel());
}
@Override
public String toString() {
return this.getClass().getSimpleName();
}
}
private static final Transformer<JpaPlatform.Config, String> JPA_PLATFORM_CONFIG_LABEL_CONVERTER = new JpaPlatformConfigLabelConverter();
/* CU private */ static class JpaPlatformConfigLabelConverter
extends TransformerAdapter<JpaPlatform.Config, String>
{
@Override
public String transform(JpaPlatform.Config config) {
return config.getLabel();
}
}
/* CU private */ static ConnectionProfileFactory getConnectionProfileFactory() {
JpaWorkspace jpaWorkspace = getJpaWorkspace();
return (jpaWorkspace == null) ? null : jpaWorkspace.getConnectionProfileFactory();
}
/* CU private */ static Iterable<JpaPlatform.Config> getJpaPlatformConfigs() {
JpaPlatformManager jpaPlatformManager = getJpaPlatformManager();
return (jpaPlatformManager != null) ? jpaPlatformManager.getJpaPlatformConfigs() : IterableTools.<JpaPlatform.Config>emptyIterable();
}
/* CU private */ static JpaPlatformManager getJpaPlatformManager() {
JpaWorkspace jpaWorkspace = getJpaWorkspace();
return (jpaWorkspace == null) ? null : jpaWorkspace.getJpaPlatformManager();
}
/* CU private */ static JpaWorkspace getJpaWorkspace() {
JpaWorkbench jpaWorkbench = getJpaWorkbench();
return (jpaWorkbench == null) ? null : jpaWorkbench.getJpaWorkspace();
}
/* CU private */ static JpaWorkbench getJpaWorkbench() {
return WorkbenchTools.getAdapter(JpaWorkbench.class);
}
// ********** connection group **********
private void buildConnectionGroup(Composite composite) {
Group group = new Group(composite, SWT.NONE);
group.setText(JptJpaUiMessages.JPA_FACET_WIZARD_PAGE_CONNECTION_LABEL);
group.setLayout(new GridLayout(3, false));
group.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
WorkbenchTools.setHelp(group, JpaHelpContextIds.PROPERTIES_JAVA_PERSISTENCE_CONNECTION);
Combo connectionDropDown = this.buildDropDown(group, 3);
SWTBindingTools.bindDropDownListBox(
CONNECTION_CHOICES_MODEL,
this.connectionModel,
connectionDropDown,
SIMPLE_STRING_TRANSFORMER
);
Link addConnectionLink = this.buildLink(group, JptJpaUiMessages.JPA_FACET_WIZARD_PAGE_CONNECTION_LINK);
addConnectionLink.addSelectionListener(new AddConnectionLinkListener()); // the link will be GCed
this.connectLink = this.buildLink(group, this.buildConnectLinkText());
SWTBindingTools.bindEnabledState(this.disconnectedModel, this.connectLink);
this.connectLink.addSelectionListener(new ConnectLinkListener()); // the link will be GCed
// override default catalog
Button overrideDefaultCatalogCheckBox = this.buildCheckBox(group, 3, JptJpaUiMessages.JPA_FACET_WIZARD_PAGE_OVERRIDE_DEFAULT_CATALOG_LABEL);
SWTBindingTools.bind(this.userOverrideDefaultCatalogFlagModel, overrideDefaultCatalogCheckBox);
Label defaultCatalogLabel = this.buildLabel(group, JptJpaUiMessages.JPA_FACET_WIZARD_PAGE_DEFAULT_CATALOG_LABEL);
Combo defaultCatalogDropDown = this.buildDropDown(group);
SWTBindingTools.bindDropDownListBox(this.catalogChoicesModel, this.defaultCatalogModel, defaultCatalogDropDown);
SWTBindingTools.bindEnabledState(this.userOverrideDefaultCatalogFlagModel, defaultCatalogLabel, defaultCatalogDropDown);
// override default schema
Button overrideDefaultSchemaButton = this.buildCheckBox(group, 3, JptJpaUiMessages.JPA_FACET_WIZARD_PAGE_OVERRIDE_DEFAULT_SCHEMA_LABEL);
SWTBindingTools.bind(this.userOverrideDefaultSchemaFlagModel, overrideDefaultSchemaButton);
Label defaultSchemaLabel = this.buildLabel(group, JptJpaUiMessages.JPA_FACET_WIZARD_PAGE_DEFAULT_SCHEMA_LABEL);
Combo defaultSchemaDropDown = this.buildDropDown(group);
SWTBindingTools.bindDropDownListBox(this.schemaChoicesModel, this.defaultSchemaModel, defaultSchemaDropDown);
SWTBindingTools.bindEnabledState(this.userOverrideDefaultSchemaFlagModel, defaultSchemaLabel, defaultSchemaDropDown);
SWTBindingTools.bindEnabledState(this.jpaProjectIsNotNullFlagModel, group, connectionDropDown, addConnectionLink, overrideDefaultCatalogCheckBox, overrideDefaultSchemaButton);
}
private static final Transformer<String, String> SIMPLE_STRING_TRANSFORMER = TransformerTools.passThruTransformer(JptJpaUiMessages.JPA_FACET_WIZARD_PAGE_NONE);
private PropertyChangeListener buildDisconnectedModelListener() {
return SWTListenerTools.wrap(new DisconnectedModelListener());
}
/* CU private */ class DisconnectedModelListener
extends PropertyChangeAdapter
{
@Override
public void propertyChanged(PropertyChangeEvent event) {
JpaProjectPropertiesPage.this.updateConnectLinkText();
}
}
/* CU private */ void updateConnectLinkText() {
this.updateConnectLinkText(this.buildConnectLinkText());
}
private String buildConnectLinkText() {
ConnectionProfile connectionProfile = this.getConnectionProfile();
return ((connectionProfile != null) && connectionProfile.isConnected()) ?
JptJpaUiMessages.JPA_FACET_WIZARD_PAGE_CONNECTED_TEXT :
JptJpaUiMessages.JPA_FACET_WIZARD_PAGE_CONNECT_LINK;
}
private void updateConnectLinkText(String text) {
if (this.connectLink.isDisposed()) {
return;
}
this.connectLink.setText(text);
ControlTools.reflow(this.connectLink);
}
/* CU private */ class AddConnectionLinkListener
extends SelectionAdapter
{
@Override
public void widgetSelected(SelectionEvent e) {
JpaProjectPropertiesPage.this.openNewConnectionWizard();
}
@Override
public String toString() {
return ObjectTools.toString(this);
}
}
void openNewConnectionWizard() {
String connectionName = DTPUiTools.createNewConnectionProfile();
if (connectionName != null) {
this.connectionModel.setValue(connectionName);
}
}
/* CU private */ class ConnectLinkListener
extends SelectionAdapter
{
@Override
public void widgetSelected(SelectionEvent e) {
JpaProjectPropertiesPage.this.openConnectionProfile();
}
@Override
public String toString() {
return ObjectTools.toString(this);
}
}
void openConnectionProfile() {
ConnectionProfile cp = this.getConnectionProfile();
if (cp != null) {
cp.connect();
}
}
// ********** persistent class management group **********
private void buildPersistentClassManagementGroup(Composite composite) {
Group group = new Group(composite, SWT.NONE);
group.setText(JptJpaUiMessages.JPA_FACET_WIZARD_PAGE_PERSISTENT_CLASS_MANAGEMENT_LABEL);
group.setLayout(new GridLayout());
group.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
Button discoverClassesRadioButton = this.buildRadioButton(group, 1, JptJpaUiMessages.JPA_FACET_WIZARD_PAGE_DISCOVER_CLASSES_BUTTON);
SWTBindingTools.bind(this.discoverAnnotatedClassesModel, discoverClassesRadioButton);
Button listClassesRadioButton = this.buildRadioButton(group, 1, JptJpaUiMessages.JPA_FACET_WIZARD_PAGE_LIST_CLASSES_BUTTON);
SWTBindingTools.bind(this.listAnnotatedClassesModel, listClassesRadioButton);
SWTBindingTools.bindEnabledState(this.jpaProjectIsNotNullFlagModel, group, discoverClassesRadioButton, listClassesRadioButton);
}
// ********** metamodel group **********
private void buildMetamodelGroup(Composite composite) {
Group group = new Group(composite, SWT.NONE);
group.setText(JptJpaUiMessages.JPA_FACET_WIZARD_PAGE_METAMODEL_LABEL);
group.setLayout(new GridLayout(3, false));
group.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
Link metamodelSourceFolderLink = this.buildLink(group, JptJpaUiMessages.JPA_FACET_WIZARD_PAGE_METAMODEL_SOURCE_FOLDER_LINK);
metamodelSourceFolderLink.addSelectionListener(new MetamodelSourceFolderLinkListener()); // the link will be GCed
Combo metamodelSourceFolderDropDown = this.buildDropDown(group);
SWTBindingTools.bindDropDownListBox(
this.javaSourceFolderChoicesModel,
this.metamodelSourceFolderModel,
metamodelSourceFolderDropDown,
SIMPLE_STRING_TRANSFORMER
);
WorkbenchTools.setHelp(group, JpaHelpContextIds.PROPERTIES_JAVA_PERSISTENCE_METAMODEL);
SWTBindingTools.bindVisibleState(this.jpa2_0ProjectFlagModel, group, metamodelSourceFolderLink, metamodelSourceFolderDropDown);
}
/* CU private */ class MetamodelSourceFolderLinkListener
extends SelectionAdapter
{
@Override
public void widgetSelected(SelectionEvent e) {
JpaProjectPropertiesPage.this.openJavaBuildPathPage();
}
@Override
public String toString() {
return ObjectTools.toString(this);
}
}
void openJavaBuildPathPage() {
IWorkbenchPreferenceContainer container = this.getWorkbenchPreferenceContainer();
container.openPage(BUILD_PATHS_PROPERTY_PAGE_ID, null);
}
// ********** OK/Revert/Apply behavior **********
@Override
protected boolean projectRebuildRequired() {
return this.jpaPlatformConfigModel.isBuffering();
}
@Override
protected void rebuildProject() throws CoreException {
// if the JPA platform is changed, we need to completely rebuild the JPA project
try {
this.rebuildProject_();
} catch (InterruptedException ex) {
throw new CoreException(JptJpaUiPlugin.instance().buildStatus(IStatus.CANCEL, ex));
}
}
private void rebuildProject_() throws InterruptedException {
JpaProject.Reference ref = this.getJpaProjectReference();
if (ref != null) {
ref.rebuild();
}
}
private JpaProject.Reference getJpaProjectReference() {
return ((JpaProject.Reference) this.getProject().getAdapter(JpaProject.Reference.class));
}
@Override
protected BufferedModifiablePropertyValueModel<?>[] buildBufferedModels() {
return new BufferedModifiablePropertyValueModel[] {
this.jpaPlatformConfigModel,
this.connectionModel,
this.userOverrideDefaultCatalogFlagModel,
this.userOverrideDefaultCatalogModel,
this.userOverrideDefaultSchemaFlagModel,
this.userOverrideDefaultSchemaModel,
this.discoverAnnotatedClassesModel,
this.metamodelSourceFolderModel
};
}
// ********** validation **********
@Override
protected Model[] buildValidationModels() {
return new Model[] {
this.jpaPlatformConfigModel,
this.connectionModel,
this.userOverrideDefaultCatalogFlagModel,
this.defaultCatalogModel,
this.userOverrideDefaultSchemaFlagModel,
this.defaultSchemaModel,
this.discoverAnnotatedClassesModel
};
}
@Override
protected void performValidation(Map<Integer, ArrayList<IStatus>> statuses) {
JpaProject jpaProject = this.jpaProjectModel.getValue();
if (jpaProject == null) {
return;
}
/* platform */
// user is unable to unset the platform, so no validation necessary
/* library provider */
this.validateLibraryProvider(statuses);
/* connection */
ConnectionProfile connectionProfile = this.getConnectionProfile();
String connectionName = this.getConnectionName();
if ( ! StringTools.isBlank(connectionName)) {
if (connectionProfile == null) {
statuses.get(ERROR_STATUS).add(this.buildErrorStatus(NLS.bind(
JptJpaCoreMessages.VALIDATE_CONNECTION_INVALID,
connectionName)));
}
else if ( ! connectionProfile.isActive()) {
statuses.get(INFO_STATUS).add(this.buildInfoStatus(JptJpaCoreMessages.VALIDATE_CONNECTION_NOT_CONNECTED));
}
}
/* default catalog */
if (this.userOverrideDefaultCatalogFlagIsSet()) {
String defaultCatalog = this.getUserOverrideDefaultCatalog();
if (StringTools.isBlank(defaultCatalog)) {
statuses.get(ERROR_STATUS).add(this.buildErrorStatus(JptJpaCoreMessages.VALIDATE_DEFAULT_CATALOG_NOT_SPECIFIED));
}
else if ((connectionProfile != null)
&& connectionProfile.isConnected()
&& ! IterableTools.contains(this.catalogChoicesModel, defaultCatalog)) {
statuses.get(WARNING_STATUS).add(this.buildWarningStatus(NLS.bind(
JptJpaCoreMessages.VALIDATE_CONNECTION_DOESNT_CONTAIN_CATALOG,
defaultCatalog
)));
}
}
/* default schema */
if (this.userOverrideDefaultSchemaFlagIsSet()) {
String defaultSchema = this.getUserOverrideDefaultSchema();
if (StringTools.isBlank(defaultSchema)) {
statuses.get(ERROR_STATUS).add(this.buildErrorStatus(JptJpaCoreMessages.VALIDATE_DEFAULT_SCHEMA_NOT_SPECIFIED));
}
else if ((connectionProfile != null)
&& connectionProfile.isConnected()
&& ! IterableTools.contains(this.schemaChoicesModel, defaultSchema)) {
statuses.get(WARNING_STATUS).add(this.buildWarningStatus(NLS.bind(
JptJpaCoreMessages.VALIDATE_CONNECTION_DOESNT_CONTAIN_SCHEMA,
defaultSchema
)));
}
}
}
private void validateLibraryProvider(Map<Integer, ArrayList<IStatus>> statuses) {
LibraryInstallDelegate libInstallDelegate = this.getLibraryInstallDelegate();
if (libInstallDelegate == null) {
return;
}
JpaPlatform.Config jpaPlatformConfig = this.jpaPlatformConfigModel.getValue();
String jpaPlatformID = (jpaPlatformConfig == null) ? "" : jpaPlatformConfig.getId(); //$NON-NLS-1$
Map<String, Object> enablementVariables = new HashMap<String, Object>();
enablementVariables.put(JpaLibraryProviderInstallOperationConfig.JPA_PLATFORM_ENABLEMENT_EXP, jpaPlatformID);
enablementVariables.put(JpaLibraryProviderInstallOperationConfig.JPA_PLATFORM_DESCRIPTION_ENABLEMENT_EXP, this.jpaProjectModel.getValue().getJpaPlatform().getConfig());
if ( ! libInstallDelegate.getLibraryProvider().isEnabledFor(
this.getFacetedProject(), this.getProjectFacetVersion(), enablementVariables)) {
this.addStatus(this.buildErrorStatus(JptJpaCoreMessages.VALIDATE_LIBRARY_PROVIDER_INVALID), statuses);
}
}
// ********** UI model adapters **********
/**
* The JPA project's data source is an auxiliary object that never changes;
* so if we have a JPA project, we have a JPA data source also.
*/
static class DataSourceModel
extends TransformationPropertyValueModel<JpaProject, JpaDataSource>
{
DataSourceModel(PropertyValueModel<JpaProject> jpaProjectModel) {
super(jpaProjectModel);
}
@Override
protected JpaDataSource transform_(JpaProject v) {
return v.getDataSource();
}
}
/**
* The DTP connection profile name is an aspect of the JPA project's
* data source
*/
static class ConnectionModel
extends PropertyAspectAdapter<JpaDataSource, String>
{
ConnectionModel(PropertyValueModel<JpaProject> jpaProjectModel) {
super(new DataSourceModel(jpaProjectModel), JpaDataSource.CONNECTION_PROFILE_NAME_PROPERTY);
}
@Override
protected String buildValue_() {
return this.subject.getConnectionProfileName();
}
@Override
public void setValue_(String connection) {
this.subject.setConnectionProfileName(connection);
}
}
/**
* Convert the selected connection profile name to a connection profile
*/
static class ConnectionProfileModel
extends TransformationPropertyValueModel<String, ConnectionProfile>
{
ConnectionProfileModel(PropertyValueModel<String> connectionModel) {
super(connectionModel);
}
@Override
protected ConnectionProfile transform_(String connectionName) {
ConnectionProfileFactory factory = getConnectionProfileFactory();
return (factory == null) ? null : factory.buildConnectionProfile(connectionName);
}
}
/**
* Treat the JPA platform config as an "aspect" of the JPA project.
* The JPA platform ID is stored in the project preferences.
* The JPA platform does not change for a JPA project - if the user wants a
* different JPA platform, we build an entirely new JPA project.
*/
static class JpaPlatformConfigModel
extends AspectPropertyValueModelAdapter<JpaProject, JpaPlatform.Config>
{
JpaPlatformConfigModel(PropertyValueModel<JpaProject> jpaProjectModel) {
super(jpaProjectModel);
}
@Override
protected JpaPlatform.Config buildValue_() {
String jpaPlatformID = JpaPreferences.getJpaPlatformID(this.subject.getProject());
JpaPlatformManager jpaPlatformManager = getJpaPlatformManager();
return (jpaPlatformManager == null) ? null : jpaPlatformManager.getJpaPlatformConfig(jpaPlatformID);
}
@Override
public void setValue_(JpaPlatform.Config jpaPlatformConfig) {
String jpaPlatformID = jpaPlatformConfig.getId();
JpaPreferences.setJpaPlatformID(this.subject.getProject(), jpaPlatformID);
}
@Override
protected void engageSubject_() {
// the JPA platform does not change
}
@Override
protected void disengageSubject_() {
// the JPA platform does not change
}
}
/**
* The connections are held by a singleton, so the model can be a singleton
* also.
*/
// by default, ExtendedListValueModelWrapper puts a null at the top of the list
private static final ListValueModel<String> CONNECTION_CHOICES_MODEL =
new ExtendedListValueModelWrapper<String>(
new SortedListValueModelAdapter<String>(
new ConnectionChoicesModel(),
STRING_COMPARATOR
)
);
/**
* Wrap the connection profile names held by the connection profile
* factory singleton.
*/
static class ConnectionChoicesModel
extends AbstractCollectionValueModel
implements CollectionValueModel<String>
{
private final ConnectionProfileFactory connectionProfileFactory;
private final ConnectionProfileListener connectionProfileListener;
ConnectionChoicesModel() {
super();
this.connectionProfileFactory = getConnectionProfileFactory();
this.connectionProfileListener = new LocalConnectionProfileListener();
}
/* class private */ class LocalConnectionProfileListener
extends ConnectionProfileAdapter
{
@Override
public void connectionProfileAdded(String name) {
ConnectionChoicesModel.this.collectionChanged();
}
@Override
public void connectionProfileRemoved(String name) {
ConnectionChoicesModel.this.collectionChanged();
}
@Override
public void connectionProfileRenamed(String oldName, String newName) {
// Ignore this event for now. Connecting a profile actually
// throws a connection renamed event, which messes up the
// list selection. There shouldn't be a connection renamed
// within the scope of this dialog anyhow.
// ConnectionChoicesModel.this.collectionChanged();
}
}
void collectionChanged() {
this.fireCollectionChanged(CollectionValueModel.VALUES, CollectionTools.hashBag(this.iterator()));
}
public Iterator<String> iterator() {
return this.getConnectionProfileNames().iterator();
}
private Iterable<String> getConnectionProfileNames() {
return (this.connectionProfileFactory != null) ? this.connectionProfileFactory.getConnectionProfileNames() : IterableTools.<String>emptyIterable();
}
public int size() {
return IterableTools.size(this.getConnectionProfileNames());
}
@Override
protected void engageModel() {
if (this.connectionProfileFactory != null) {
this.connectionProfileFactory.addConnectionProfileListener(this.connectionProfileListener);
}
}
@Override
protected void disengageModel() {
if (this.connectionProfileFactory != null) {
this.connectionProfileFactory.removeConnectionProfileListener(this.connectionProfileListener);
}
}
}
/**
* Adapt whether the JPA project has a user override specified
* (either catalog or schema);
*/
abstract static class UserOverrideDefaultFlagModel
extends PropertyAspectAdapter<JpaProject, Boolean>
{
UserOverrideDefaultFlagModel(PropertyValueModel<JpaProject> jpaProjectModel, String propertyName) {
super(jpaProjectModel, propertyName);
}
@Override
protected Boolean buildValue_() {
return Boolean.valueOf(this.specifiesUserOverrideDefault());
}
boolean specifiesUserOverrideDefault() {
return ! StringTools.isBlank(this.getUserOverrideDefault());
}
abstract String getUserOverrideDefault();
@Override
protected void setValue_(Boolean value) {
// ignore
}
}
/**
* Whether the JPA project has a user override default catalog specified.
*/
static class UserOverrideDefaultCatalogFlagModel
extends UserOverrideDefaultFlagModel
{
UserOverrideDefaultCatalogFlagModel(PropertyValueModel<JpaProject> jpaProjectModel) {
super(jpaProjectModel, JpaProject.USER_OVERRIDE_DEFAULT_CATALOG_PROPERTY);
}
@Override
public String getUserOverrideDefault() {
return this.subject.getUserOverrideDefaultCatalog();
}
}
/**
* Whether the JPA project has a user override default schema specified.
*/
static class UserOverrideDefaultSchemaFlagModel
extends UserOverrideDefaultFlagModel
{
UserOverrideDefaultSchemaFlagModel(PropertyValueModel<JpaProject> jpaProjectModel) {
super(jpaProjectModel, JpaProject.USER_OVERRIDE_DEFAULT_SCHEMA_PROPERTY);
}
@Override
public String getUserOverrideDefault() {
return this.subject.getUserOverrideDefaultSchema();
}
}
/**
* The JPA project's user override default catalog
*/
static class UserOverrideDefaultCatalogModel
extends PropertyAspectAdapter<JpaProject, String>
{
UserOverrideDefaultCatalogModel(PropertyValueModel<JpaProject> jpaProjectModel) {
super(jpaProjectModel, JpaProject.USER_OVERRIDE_DEFAULT_CATALOG_PROPERTY);
}
@Override
protected String buildValue_() {
return this.subject.getUserOverrideDefaultCatalog();
}
@Override
public void setValue_(String catalog) {
this.subject.setUserOverrideDefaultCatalog(catalog);
}
}
/**
* The JPA project's user override default catalog
*/
static class UserOverrideDefaultSchemaModel
extends PropertyAspectAdapter<JpaProject, String>
{
UserOverrideDefaultSchemaModel(PropertyValueModel<JpaProject> jpaProjectModel) {
super(jpaProjectModel, JpaProject.USER_OVERRIDE_DEFAULT_SCHEMA_PROPERTY);
}
@Override
protected String buildValue_() {
return this.subject.getUserOverrideDefaultSchema();
}
@Override
public void setValue_(String schema) {
this.subject.setUserOverrideDefaultSchema(schema);
}
}
/**
* Flag on the JPA project indicating whether it should discover annotated
* classes
*/
static class DiscoverAnnotatedClassesModel
extends PropertyAspectAdapter<JpaProject, Boolean>
{
DiscoverAnnotatedClassesModel(PropertyValueModel<JpaProject> jpaProjectModel) {
super(jpaProjectModel, JpaProject.DISCOVERS_ANNOTATED_CLASSES_PROPERTY);
}
@Override
protected Boolean buildValue_() {
return Boolean.valueOf(this.subject.discoversAnnotatedClasses());
}
@Override
protected void setValue_(Boolean value) {
this.subject.setDiscoversAnnotatedClasses(value.booleanValue());
}
}
/**
* The folder where the source for the generated Canonical Metamodel
* is written.
*/
static class MetamodelSourceFolderModel
extends PropertyAspectAdapter<JpaProject, String>
{
MetamodelSourceFolderModel(PropertyValueModel<JpaProject> jpaProjectModel) {
super(jpaProjectModel, JpaProject2_0.METAMODEL_SOURCE_FOLDER_NAME_PROPERTY);
}
@Override
protected String buildValue_() {
return this.subjectIsInJpa2_0Project() ? ((JpaProject2_0) this.subject).getMetamodelSourceFolderName() : null;
}
@Override
protected void setValue_(String value) {
if (this.subjectIsInJpa2_0Project()) {
((JpaProject2_0) this.subject).setMetamodelSourceFolderName(value);
}
}
private boolean subjectIsInJpa2_0Project() {
return this.subject.getJpaProject().getJpaPlatform().getJpaVersion().isCompatibleWithJpaVersion(JpaProject2_0.FACET_VERSION_STRING);
}
}
/**
* Java project source folders.
* We keep the metamodel source folder in sync with the Java source folders
* (i.e. if a Java source folder is deleted or removed from the build path,
* we remove the metamodel source folder); therefore the list of folder
* choices does not need to be augmented with the current folder (as we do
* when the current folder is not in the list of choices).
*/
static class JavaSourceFolderChoicesModel
extends AspectCollectionValueModelAdapter<JpaProject, String>
{
private final IElementChangedListener javaElementChangedListener;
JavaSourceFolderChoicesModel(PropertyValueModel<JpaProject> jpaProjectModel) {
super(jpaProjectModel);
this.javaElementChangedListener = new JavaElementChangedListener();
}
/* class private */ class JavaElementChangedListener
implements IElementChangedListener
{
public void elementChanged(ElementChangedEvent event) {
JavaSourceFolderChoicesModel.this.processJavaDelta(event.getDelta());
}
@Override
public String toString() {
return ObjectTools.toString(this);
}
}
void processJavaDelta(IJavaElementDelta delta) {
switch (delta.getElement().getElementType()) {
case IJavaElement.JAVA_MODEL :
this.processJavaDeltaChildren(delta);
break;
case IJavaElement.JAVA_PROJECT :
this.processJavaProjectDelta(delta);
break;
default :
break; // ignore everything else
}
}
private void processJavaDeltaChildren(IJavaElementDelta delta) {
for (IJavaElementDelta child : delta.getAffectedChildren()) {
this.processJavaDelta(child); // recurse
}
}
private void processJavaProjectDelta(IJavaElementDelta delta) {
IJavaProject javaProject = (IJavaProject) delta.getElement();
if (javaProject.equals(this.subject.getJavaProject()) && this.classpathHasChanged(delta)) {
this.fireCollectionChanged(CollectionValueModel.VALUES, CollectionTools.hashBag(this.iterator()));
}
}
private boolean classpathHasChanged(IJavaElementDelta delta) {
return this.deltaFlagIsSet(delta, IJavaElementDelta.F_RESOLVED_CLASSPATH_CHANGED);
}
private boolean deltaFlagIsSet(IJavaElementDelta delta, int flag) {
return (delta.getKind() == IJavaElementDelta.CHANGED) &&
BitTools.flagIsSet(delta.getFlags(), flag);
}
@Override
protected Iterable<String> getIterable() {
return this.subjectIsInJpa2_0Project() ?
((JpaProject2_0) this.subject).getJavaSourceFolderNames() :
EmptyIterable.<String>instance();
}
private boolean subjectIsInJpa2_0Project() {
return this.subject.getJpaProject().getJpaPlatform().getJpaVersion().isCompatibleWithJpaVersion(JpaProject2_0.FACET_VERSION_STRING);
}
@Override
protected void engageSubject_() {
JavaCore.addElementChangedListener(this.javaElementChangedListener);
}
@Override
protected void disengageSubject_() {
JavaCore.removeElementChangedListener(this.javaElementChangedListener);
}
}
/**
* Abstract property aspect adapter for DTP connection profile connection/database
*/
abstract static class ConnectionProfilePropertyAspectAdapter<V>
extends AspectPropertyValueModelAdapter<ConnectionProfile, V>
{
private final ConnectionListener connectionListener;
ConnectionProfilePropertyAspectAdapter(PropertyValueModel<ConnectionProfile> connectionProfileModel) {
super(connectionProfileModel);
this.connectionListener = this.buildConnectionListener();
}
// the connection opening is probably the only thing that will happen...
private ConnectionListener buildConnectionListener() {
return new LocalConnectionListener();
}
class LocalConnectionListener
extends ConnectionAdapter
{
@Override
public void opened(ConnectionProfile profile) {
ConnectionProfilePropertyAspectAdapter.this.connectionOpened(profile);
}
}
void connectionOpened(ConnectionProfile profile) {
if (profile.equals(this.subject)) {
this.aspectChanged();
}
}
@Override
protected void engageSubject_() {
this.subject.addConnectionListener(this.connectionListener);
}
@Override
protected void disengageSubject_() {
this.subject.removeConnectionListener(this.connectionListener);
}
}
/**
* Monitor the connection profile's connection to the database
* (used to enable the "Connect" link)
*/
static class DisconnectedModel
extends ConnectionProfilePropertyAspectAdapter<Boolean>
{
DisconnectedModel(PropertyValueModel<ConnectionProfile> connectionProfileModel) {
super(connectionProfileModel);
}
@Override
protected Boolean buildValue_() {
return Boolean.valueOf((this.subject != null) && this.subject.isDisconnected());
}
}
/**
* Database-determined default catalog
*/
static class DatabaseDefaultCatalogModel
extends ConnectionProfilePropertyAspectAdapter<String>
{
DatabaseDefaultCatalogModel(PropertyValueModel<ConnectionProfile> connectionProfileModel) {
super(connectionProfileModel);
}
@Override
protected String buildValue_() {
Database db = this.subject.getDatabase();
return (db == null) ? null : db.getDefaultCatalogIdentifier();
}
}
/**
* The default schema is not derived purely from the database; it is also dependent
* on the current value of the default catalog (which may be overridden
* by the user).
*/
static class DatabaseDefaultSchemaModel
extends ConnectionProfilePropertyAspectAdapter<String>
{
private final PropertyValueModel<String> defaultCatalogModel;
private final PropertyChangeListener catalogListener;
DatabaseDefaultSchemaModel(
PropertyValueModel<ConnectionProfile> connectionProfileModel,
PropertyValueModel<String> defaultCatalogModel
) {
super(connectionProfileModel);
this.defaultCatalogModel = defaultCatalogModel;
this.catalogListener = new CatalogListener();
}
/* class private */ class CatalogListener
extends PropertyChangeAdapter
{
@Override
public void propertyChanged(PropertyChangeEvent event) {
DatabaseDefaultSchemaModel.this.catalogChanged();
}
}
void catalogChanged() {
this.aspectChanged();
}
@Override
protected void engageSubject_() {
super.engageSubject_();
this.defaultCatalogModel.addPropertyChangeListener(PropertyValueModel.VALUE, this.catalogListener);
}
@Override
protected void disengageSubject_() {
this.defaultCatalogModel.removePropertyChangeListener(PropertyValueModel.VALUE, this.catalogListener);
super.disengageSubject_();
}
@Override
protected String buildValue_() {
SchemaContainer sc = this.getSchemaContainer();
return (sc == null) ? null : sc.getDefaultSchemaIdentifier();
}
private SchemaContainer getSchemaContainer() {
return this.databaseSupportsCatalogs() ? this.getCatalog() : this.getDatabase();
}
private boolean databaseSupportsCatalogs() {
Database db = this.getDatabase();
return (db != null) && db.supportsCatalogs();
}
private Catalog getCatalog() {
String name = this.defaultCatalogModel.getValue();
// if we get here we know the database is not null
return (name == null) ? null : this.getDatabase().getCatalogForIdentifier(name);
}
private Database getDatabase() {
return this.subject.getDatabase();
}
}
/**
* Abstract collection aspect adapter for DTP connection profile connection/database
*/
abstract static class ConnectionProfileCollectionAspectAdapter<E>
extends AspectCollectionValueModelAdapter<ConnectionProfile, E>
{
private final ConnectionListener connectionListener;
ConnectionProfileCollectionAspectAdapter(PropertyValueModel<ConnectionProfile> connectionProfileModel) {
super(connectionProfileModel);
this.connectionListener = this.buildConnectionListener();
}
// the connection opening is probably the only thing that will happen...
private ConnectionListener buildConnectionListener() {
return new LocalConnectionListener();
}
class LocalConnectionListener
extends ConnectionAdapter
{
@Override
public void opened(ConnectionProfile profile) {
ConnectionProfileCollectionAspectAdapter.this.connectionOpened(profile);
}
}
void connectionOpened(ConnectionProfile profile) {
if (profile.equals(this.subject)) {
this.aspectChanged();
}
}
@Override
protected void engageSubject_() {
this.subject.addConnectionListener(this.connectionListener);
}
@Override
protected void disengageSubject_() {
this.subject.removeConnectionListener(this.connectionListener);
}
}
/**
* Catalogs on the database.
*/
static class DatabaseCatalogChoicesModel
extends ConnectionProfileCollectionAspectAdapter<String>
{
DatabaseCatalogChoicesModel(PropertyValueModel<ConnectionProfile> connectionProfileModel) {
super(connectionProfileModel);
}
@Override
protected Iterable<String> getIterable() {
Database db = this.subject.getDatabase();
// use catalog *identifiers* since the string ends up being the "default" for various text entries
return (db != null) ? db.getSortedCatalogIdentifiers() : EmptyIterable.<String>instance();
}
}
/**
* Schemas on the database or catalog.
* This list is not derived purely from the database; it is also dependent
* on the current value of the default catalog (which may be overridden
* by the user).
*/
static class DatabaseSchemaChoicesModel
extends ConnectionProfileCollectionAspectAdapter<String>
{
private final PropertyValueModel<String> defaultCatalogModel;
private final PropertyChangeListener catalogListener;
DatabaseSchemaChoicesModel(
PropertyValueModel<ConnectionProfile> connectionProfileModel,
PropertyValueModel<String> defaultCatalogModel
) {
super(connectionProfileModel);
this.defaultCatalogModel = defaultCatalogModel;
this.catalogListener = new CatalogListener();
}
/* class private */ class CatalogListener
extends PropertyChangeAdapter
{
@Override
public void propertyChanged(PropertyChangeEvent event) {
DatabaseSchemaChoicesModel.this.catalogChanged();
}
}
void catalogChanged() {
this.aspectChanged();
}
@Override
protected void engageSubject_() {
super.engageSubject_();
this.defaultCatalogModel.addPropertyChangeListener(PropertyValueModel.VALUE, this.catalogListener);
}
@Override
protected void disengageSubject_() {
this.defaultCatalogModel.removePropertyChangeListener(PropertyValueModel.VALUE, this.catalogListener);
super.disengageSubject_();
}
@Override
protected Iterable<String> getIterable() {
SchemaContainer sc = this.getSchemaContainer();
// use schema *identifiers* since the string ends up being the "default" for various text entries
return (sc != null) ? sc.getSortedSchemaIdentifiers() : EmptyIterable.<String>instance();
}
private SchemaContainer getSchemaContainer() {
return this.databaseSupportsCatalogs() ? this.getCatalog() : this.getDatabase();
}
private boolean databaseSupportsCatalogs() {
Database db = this.getDatabase();
return (db != null) && db.supportsCatalogs();
}
private Catalog getCatalog() {
String name = this.defaultCatalogModel.getValue();
// if we get here we know the database is not null
return (name == null) ? null : this.getDatabase().getCatalogForIdentifier(name);
}
private Database getDatabase() {
return this.subject.getDatabase();
}
}
/**
* Combine various models to determine the default catalog or schema.
* If the user has checked the "Override Default" check-box, the default
* is the JPA project's user override default, otherwise the default is
* determined by the database.
*/
static class DefaultModel
extends CompositePropertyValueModel<String, Object>
implements ModifiablePropertyValueModel<String>
{
private final PropertyValueModel<Boolean> userOverrideDefaultFlagModel;
private final ModifiablePropertyValueModel<String> userOverrideDefaultModel;
private final PropertyValueModel<String> databaseDefaultModel;
@SuppressWarnings("unchecked")
DefaultModel(
PropertyValueModel<Boolean> userOverrideDefaultFlagModel,
ModifiablePropertyValueModel<String> userOverrideDefaultModel,
PropertyValueModel<String> databaseDefaultModel
) {
super(userOverrideDefaultFlagModel, userOverrideDefaultModel, databaseDefaultModel);
this.userOverrideDefaultFlagModel = userOverrideDefaultFlagModel;
this.userOverrideDefaultModel = userOverrideDefaultModel;
this.databaseDefaultModel = databaseDefaultModel;
}
/**
* If the checkbox has been unchecked, we need to clear out the JPA
* project's user override.
*/
@Override
protected void componentChanged(PropertyChangeEvent event) {
super.componentChanged(event);
if (event.getSource() == this.userOverrideDefaultFlagModel) {
if ( ! this.userOverrideDefaultFlagIsSet()) {
this.userOverrideDefaultModel.setValue(null);
}
}
}
/**
* If the checkbox is checked, return the user override from the JPA project;
* otherwise return the default from the database
*/
@Override
protected String buildValue() {
return this.userOverrideDefaultFlagIsSet() ?
this.userOverrideDefaultModel.getValue() :
this.databaseDefaultModel.getValue();
}
/**
* This will be called when the user makes a selection from the
* drop-down; which is only possible when the checkbox is checked
* (and the drop-down is enabled).
*/
public void setValue(String value) {
this.userOverrideDefaultModel.setValue(value);
this.propertyChanged();
}
private boolean userOverrideDefaultFlagIsSet() {
return flagIsSet(this.userOverrideDefaultFlagModel);
}
}
}