| /******************************************************************************* |
| * 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(); |
| } |
| |
| } |