blob: 02eaf79bc4d3a12c0b82195ff571bda1956ea08a [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2003, 2007 IBM Corporation and others.
* 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:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.wst.web.ui.internal.wizards;
import java.lang.reflect.InvocationTargetException;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.wizard.IWizardPage;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.INewWizard;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.wizards.newresource.BasicNewProjectResourceWizard;
import org.eclipse.ui.wizards.newresource.BasicNewResourceWizard;
import org.eclipse.wst.common.componentcore.datamodel.properties.IFacetDataModelProperties;
import org.eclipse.wst.common.componentcore.datamodel.properties.IFacetProjectCreationDataModelProperties;
import org.eclipse.wst.common.frameworks.datamodel.AbstractDataModelOperation;
import org.eclipse.wst.common.frameworks.datamodel.AbstractDataModelProvider;
import org.eclipse.wst.common.frameworks.datamodel.DataModelEvent;
import org.eclipse.wst.common.frameworks.datamodel.IDataModel;
import org.eclipse.wst.common.frameworks.datamodel.IDataModelListener;
import org.eclipse.wst.common.frameworks.datamodel.IDataModelOperation;
import org.eclipse.wst.common.frameworks.internal.datamodel.DataModelPausibleOperationImpl;
import org.eclipse.wst.common.frameworks.internal.datamodel.ui.DataModelWizardPage;
import org.eclipse.wst.common.project.facet.core.FacetedProjectFramework;
import org.eclipse.wst.common.project.facet.core.IFacetedProject;
import org.eclipse.wst.common.project.facet.core.IFacetedProjectTemplate;
import org.eclipse.wst.common.project.facet.core.IFacetedProjectWorkingCopy;
import org.eclipse.wst.common.project.facet.core.IPreset;
import org.eclipse.wst.common.project.facet.core.IProjectFacet;
import org.eclipse.wst.common.project.facet.core.IProjectFacetVersion;
import org.eclipse.wst.common.project.facet.core.events.IFacetedProjectEvent;
import org.eclipse.wst.common.project.facet.core.events.IFacetedProjectListener;
import org.eclipse.wst.common.project.facet.core.runtime.IRuntime;
import org.eclipse.wst.common.project.facet.ui.ModifyFacetedProjectWizard;
import org.eclipse.wst.web.internal.DelegateConfigurationElement;
import org.eclipse.wst.web.ui.internal.Logger;
import org.eclipse.wst.web.ui.internal.WSTWebUIPlugin;
public abstract class NewProjectDataModelFacetWizard extends ModifyFacetedProjectWizard implements INewWizard, IFacetProjectCreationDataModelProperties {
protected IDataModel model = null;
private final IFacetedProjectTemplate template;
private IWizardPage[] beginingPages;
private IConfigurationElement configurationElement;
public NewProjectDataModelFacetWizard(IDataModel model)
{
this.model = ( model == null ? createDataModel() : model );
this.template = getTemplate();
setFacetedProjectWorkingCopy((IFacetedProjectWorkingCopy)this.model.getProperty(FACETED_PROJECT_WORKING_COPY));
getFacetedProjectWorkingCopy().setFixedProjectFacets( this.template.getFixedProjectFacets() );
setDefaultPageImageDescriptor(getDefaultPageImageDescriptor());
setShowFacetsSelectionPage( false );
}
public NewProjectDataModelFacetWizard()
{
this( null );
}
public IDataModel getDataModel() {
return model;
}
protected abstract IDataModel createDataModel();
protected abstract ImageDescriptor getDefaultPageImageDescriptor();
protected abstract IFacetedProjectTemplate getTemplate();
/**
* Returns the first page that shows up before the facets page. If multiple pages are required,
* also override {@link #createBeginingPages()}.
*
* @return
*/
protected abstract IWizardPage createFirstPage();
/**
* Subclasses should override to add more than one page before the facets page. If only one page
* is required, then use {@link #createFirstPage()}. The default implementation will return the
* result of {@link #createFirstPage()}.
*
* @return
*/
protected IWizardPage[] createBeginingPages() {
return new IWizardPage[]{createFirstPage()};
}
public void addPages() {
beginingPages = createBeginingPages();
for (int i = 0; i < beginingPages.length; i++) {
addPage(beginingPages[i]);
}
super.addPages();
getFacetedProjectWorkingCopy().addListener
(
new IFacetedProjectListener()
{
public void handleEvent( final IFacetedProjectEvent event )
{
facetSelectionChangedEvent();
}
},
IFacetedProjectEvent.Type.PROJECT_FACETS_CHANGED
);
}
public void createPageControls(Composite container) {
super.createPageControls(container);
final IPreset preset = this.template.getInitialPreset();
final IRuntime runtime = (IRuntime) model.getProperty( FACET_RUNTIME );
if( preset == null )
{
// If no preset is specified, select the runtime and it's default
// facets.
setRuntimeAndDefaultFacets( runtime );
}
else
{
// If preset is specified, select the runtime only if supports all
// of the facets included in the preset.
getFacetedProjectWorkingCopy().setSelectedPreset( preset.getId() );
boolean supports = false;
if( runtime != null )
{
supports = true;
for( Iterator itr = preset.getProjectFacets().iterator(); itr.hasNext(); )
{
final IProjectFacetVersion fv = (IProjectFacetVersion) itr.next();
if( ! runtime.supports( fv ) )
{
supports = false;
break;
}
}
}
if( supports )
{
getFacetedProjectWorkingCopy().setTargetedRuntimes( Collections.singleton( runtime ) );
}
else
{
model.setProperty( FACET_RUNTIME, null );
}
}
synchRuntimes();
}
public IWizardPage[] getPages() {
final IWizardPage[] base = super.getPages();
final IWizardPage[] pages = new IWizardPage[base.length + beginingPages.length];
for (int i = 0; i < beginingPages.length; i++) {
pages[i] = beginingPages[i];
}
System.arraycopy(base, 0, pages, beginingPages.length, base.length);
return pages;
}
public void init(IWorkbench workbench, IStructuredSelection selection) {
}
protected void synchRuntimes()
{
final Boolean[] suppressBackEvents = { Boolean.FALSE };
model.addListener(new IDataModelListener() {
public void propertyChanged(DataModelEvent event) {
if (IDataModel.VALUE_CHG == event.getFlag() || IDataModel.DEFAULT_CHG == event.getFlag()) {
if (FACET_RUNTIME.equals(event.getPropertyName())) {
if( ! suppressBackEvents[ 0 ].booleanValue() ) {
IRuntime runtime = (IRuntime) event.getProperty();
setRuntimeAndDefaultFacets( runtime );
}
}
}
}
});
getFacetedProjectWorkingCopy().addListener
(
new IFacetedProjectListener()
{
public void handleEvent( final IFacetedProjectEvent event )
{
suppressBackEvents[ 0 ] = Boolean.TRUE;
model.setProperty(FACET_RUNTIME, getFacetedProjectWorkingCopy().getPrimaryRuntime());
suppressBackEvents[ 0 ] = Boolean.FALSE;
}
},
IFacetedProjectEvent.Type.PRIMARY_RUNTIME_CHANGED
);
}
protected void setRuntimeAndDefaultFacets( final IRuntime runtime )
{
final IFacetedProjectWorkingCopy dm = getFacetedProjectWorkingCopy();
dm.setTargetedRuntimes( Collections.<IRuntime>emptySet() );
if( runtime != null )
{
final Set<IProjectFacetVersion> minFacets = new HashSet<IProjectFacetVersion>();
try
{
for( IProjectFacet f : dm.getFixedProjectFacets() )
{
minFacets.add( f.getLatestSupportedVersion( runtime ) );
}
}
catch( CoreException e )
{
throw new RuntimeException( e );
}
dm.setProjectFacets( minFacets );
dm.setTargetedRuntimes( Collections.singleton( runtime ) );
}
dm.setSelectedPreset( FacetedProjectFramework.DEFAULT_CONFIGURATION_PRESET_ID );
}
public String getProjectName() {
return model.getStringProperty(IFacetProjectCreationDataModelProperties.FACET_PROJECT_NAME);
}
protected void performFinish(final IProgressMonitor monitor)
throws CoreException
{
monitor.beginTask("", 10); //$NON-NLS-1$
storeDefaultSettings();
try {
super.performFinish(new SubProgressMonitor(monitor, 8));
try {
getFacetProjectNotificationOperation().execute(new NullProgressMonitor(), null);
} catch (ExecutionException e) {
String msg = e.getMessage();
if( msg == null ) msg = ""; //$NON-NLS-1$
final IStatus st = new Status( IStatus.ERROR, WSTWebUIPlugin.PLUGIN_ID, 0, msg, e );
throw new CoreException( st );
}
} finally {
monitor.done();
}
}
public boolean performFinish() {
if (super.performFinish() == false) {
return false;
}
try {
postPerformFinish();
} catch (InvocationTargetException e) {
Logger.logException(e);
}
return true;
}
/**
* <p>
* Override to return the final perspective ID (if any). The final perspective ID can be
* hardcoded by the subclass or determined programmatically (possibly using the value of a field
* on the Wizard's WTP Operation Data Model).
* </p>
* <p>
* The default implementation returns no perspective id unless overriden by product definition
* via the "wtp.project.final.perspective" property.
* </p>
*
* @return Returns the ID of the Perspective which is preferred by this wizard upon completion.
*/
protected String getFinalPerspectiveID() {
return null;
}
/**
* {@inheritDoc}
*
* <p>
* The configuration element is saved to use when the wizard completes in order to change the
* current perspective using either (1) the value specified by {@link #getFinalPerspectiveID()}
* or (2) the value specified by the finalPerspective attribute in the Wizard's configuration
* element.
* </p>
*
* @see org.eclipse.core.runtime.IExecutableExtension#setInitializationData(org.eclipse.core.runtime.IConfigurationElement,
* java.lang.String, java.lang.Object)
*/
public final void setInitializationData(IConfigurationElement aConfigurationElement, String aPropertyName, Object theData) throws CoreException {
configurationElement = aConfigurationElement;
doSetInitializeData(aConfigurationElement, aPropertyName, theData);
}
/**
* <p>
* Override method for clients that wish to take advantage of the information provided by
* {@see #setInitializationData(IConfigurationElement, String, Object)}.
* </p>
*
* @param aConfigurationElement
* The configuration element provided from the templated method.
* @param aPropertyName
* The property name provided from the templated method.
* @param theData
* The data provided from the templated method.
*/
protected void doSetInitializeData(IConfigurationElement aConfigurationElement, String aPropertyName, Object theData) {
// Default do nothing
}
/**
* <p>
* Returns the an id component used for Activity filtering.
* </p>
*
* <p>
* The Plugin ID is determined from the configuration element specified in
* {@see #setInitializationData(IConfigurationElement, String, Object)}.
* </p>
*
* @return Returns the plugin id associated with this wizard
*/
public final String getPluginId() {
return (configurationElement != null) ? configurationElement.getDeclaringExtension().getNamespace() : ""; //$NON-NLS-1$
}
/**
*
* <p>
* Invoked after the user has clicked the "Finish" button of the wizard. The default
* implementation will attempt to update the final perspective to the value specified by
* {@link #getFinalPerspectiveID() }
* </p>
*
* @throws InvocationTargetException
*
* @see org.eclipse.wst.common.frameworks.internal.ui.wizard.WTPWizard#postPerformFinish()
*/
protected void postPerformFinish() throws InvocationTargetException {
if (getFinalPerspectiveID() != null && getFinalPerspectiveID().length() > 0) {
final IConfigurationElement element = new DelegateConfigurationElement(configurationElement) {
public String getAttribute(String aName) {
if (aName.equals("finalPerspective")) { //$NON-NLS-1$
return getFinalPerspectiveID();
}
return super.getAttribute(aName);
}
};
BasicNewProjectResourceWizard.updatePerspective(element);
} else
BasicNewProjectResourceWizard.updatePerspective(configurationElement);
String projName = getProjectName();
BasicNewResourceWizard.selectAndReveal(ResourcesPlugin.getWorkspace().getRoot().getProject(projName), WSTWebUIPlugin.getDefault().getWorkbench().getActiveWorkbenchWindow());
}
protected IDataModelOperation getFacetProjectNotificationOperation() {
return new DataModelPausibleOperationImpl(new AbstractDataModelOperation(this.model) {
public String getID() {
return NewProjectDataModelFacetWizard.class.getName();
}
public IStatus execute(IProgressMonitor monitor, IAdaptable info) throws ExecutionException {
return AbstractDataModelProvider.OK_STATUS;
}
});
}
/**
* Need to keep the model in sync with the UI. This method will pickup changes coming from the
* UI and push them into the model
*/
protected void facetSelectionChangedEvent() {
Set actions = getFacetedProjectWorkingCopy().getProjectFacetActions();
Iterator iterator = actions.iterator();
Set activeIds = new HashSet();
while (iterator.hasNext()) {
IFacetedProject.Action action = (IFacetedProject.Action) iterator.next();
String id = action.getProjectFacetVersion().getProjectFacet().getId();
activeIds.add(id);
}
// First handle all the actions tracked by IDataModels
FacetDataModelMap dataModelMap = (FacetDataModelMap) model.getProperty(FACET_DM_MAP);
iterator = dataModelMap.keySet().iterator();
while (iterator.hasNext()) {
String id = (String) iterator.next();
IDataModel configDM = (IDataModel) dataModelMap.get(id);
boolean active = activeIds.contains(id);
configDM.setBooleanProperty(IFacetDataModelProperties.SHOULD_EXECUTE, active);
activeIds.remove(id);
}
// Now handle the actions not tracked by IDataModels
FacetActionMap actionMap = (FacetActionMap) model.getProperty(FACET_ACTION_MAP);
actionMap.clear();
iterator = actions.iterator();
while (iterator.hasNext()) {
IFacetedProject.Action action = (IFacetedProject.Action) iterator.next();
String id = action.getProjectFacetVersion().getProjectFacet().getId();
if (activeIds.contains(id)) {
actionMap.add(action);
}
}
model.notifyPropertyChange(FACET_RUNTIME, IDataModel.VALID_VALUES_CHG);
}
protected void storeDefaultSettings() {
IWizardPage[] pages = getPages();
for (int i = 0; i < pages.length; i++)
storeDefaultSettings(pages[i], i);
}
/**
* Subclasses may override if they need to do something special when storing the default
* settings for a particular page.
*
* @param page
* @param pageIndex
*/
protected void storeDefaultSettings(IWizardPage page, int pageIndex) {
if (page instanceof DataModelWizardPage)
((DataModelWizardPage) page).storeDefaultSettings();
}
}