/*
* JBoss, Home of Professional Open Source.
*
* See the LEGAL.txt file distributed with this work for information regarding copyright ownership and licensing.
*
* See the AUTHORS.txt file distributed with this work for a full listing of individual contributors.
*/
package org.teiid.designer.webservice.ui.wizard;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.MultiStatus;
import org.eclipse.core.runtime.jobs.IJobChangeEvent;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.core.runtime.jobs.JobChangeAdapter;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.dialogs.IMessageProvider;
import org.eclipse.jface.dialogs.ProgressMonitorDialog;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.wizard.IWizardPage;
import org.eclipse.jface.wizard.WizardPage;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.IImportWizard;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.ide.IDE;
import org.eclipse.ui.internal.ide.IDEWorkbenchMessages;
import org.teiid.core.designer.util.CoreArgCheck;
import org.teiid.core.designer.util.I18nUtil;
import org.teiid.designer.compare.ModelGenerator;
import org.teiid.designer.core.ModelerCore;
import org.teiid.designer.core.metamodel.MetamodelDescriptor;
import org.teiid.designer.core.notification.util.DefaultIgnorableNotificationSource;
import org.teiid.designer.core.transaction.UnitOfWorkImpl;
import org.teiid.designer.core.workspace.ModelUtil;
import org.teiid.designer.metamodels.core.ModelType;
import org.teiid.designer.ui.UiPlugin;
import org.teiid.designer.ui.actions.DeleteAction;
import org.teiid.designer.ui.common.product.ProductCustomizerMgr;
import org.teiid.designer.ui.common.util.UiUtil;
import org.teiid.designer.ui.common.util.WidgetUtil;
import org.teiid.designer.ui.common.viewsupport.JobUtils;
import org.teiid.designer.ui.common.wizard.AbstractWizard;
import org.teiid.designer.ui.common.wizard.NoOpenProjectsWizardPage;
import org.teiid.designer.ui.product.IModelerProductContexts.Metamodel;
import org.teiid.designer.ui.viewsupport.ModelerUiViewUtils;
import org.teiid.designer.webservice.IWebServiceModelBuilder;
import org.teiid.designer.webservice.WebServiceModelProducer;
import org.teiid.designer.webservice.WebServicePlugin;
import org.teiid.designer.webservice.ui.IInternalUiConstants;
import org.teiid.designer.webservice.ui.WebServiceUiPlugin;
import org.teiid.designer.webservice.ui.wizard.WsdlSelectionPage.EditableNameField;
/**
* @since 8.0
*/
public class WsdlFileSystemImportWizard extends AbstractWizard implements IImportWizard, IInternalUiConstants {
static final String I18N_PREFIX = I18nUtil.getPropertyPrefix(WsdlFileSystemImportWizard.class);
private static final String TITLE = getString("title"); //$NON-NLS-1$
private static final ImageDescriptor IMAGE = WebServiceUiPlugin.getDefault().getImageDescriptor(Images.IMPORT_WSDL);
private static final String NOT_LICENSED_MSG = getString("notLicensedMessage"); //$NON-NLS-1$
private static final String WEB_SERVICES_CLASS_ID = "Web Service"; //$NON-NLS-1$
private static final String DEPRECATED_SUFFIX = " (Deprecated)"; //$NON-NLS-1$
private static boolean importLicensed = true;
/**
* @since 4.0
*/
private static String getString( final String id ) {
return UTIL.getString(I18N_PREFIX + id);
}
/** The builder is responsible for building the Web Service model. */
private IWebServiceModelBuilder builder;
/** The page where the namespaces are resolved to a file. */
private WizardPage namespaceResolutionPage;
/** The page where schema target locations are decided. */
private WizardPage schemaLocationPage;
/** The page where the included WSDL file(s) are selected. */
private WizardPage wsdlSelectionPage;
/** The page where the user selects which WSDL operations to build. */
private WizardPage selectWsdlOperationsPage;
/** The page where the XML file where each web service operation generates and XML document. */
private WizardPage xmlSelectionPage;
/**
* The page where the included WSDL file(s) are validated and the results of that validation are displayed. See: Defect 24620
* - missing the WSDL validation page.
*/
private WizardPage wsdlValidationPage;
private IStructuredSelection selection;
private IStatus status;
private IContainer folder;
/** Defect 23075 - needed global rollback and autoBuildOn flags for use in runnable */
boolean rollbackNewResources = false;
private boolean autoBuildOn = false;
/**
* Creates a wizard for importing resources into the workspace from the file system.
*/
public WsdlFileSystemImportWizard() {
super(WebServiceUiPlugin.getDefault(), TITLE, IMAGE);
}
Composite createEmptyPageControl( final Composite parent ) {
return new Composite(parent, SWT.NONE);
}
/**
* @see org.eclipse.jface.wizard.IWizard#createPageControls(org.eclipse.swt.widgets.Composite)
*/
@Override
public void createPageControls( Composite pageContainer ) {
if (importLicensed) {
super.createPageControls(pageContainer);
}
}
/**
* Method declared on IWorkbenchWizard.
*/
@Override
public void init( IWorkbench workbench,
IStructuredSelection currentSelection ) {
this.selection = currentSelection;
if (ProductCustomizerMgr.getInstance().getProductCharacteristics().isHiddenProjectCentric()) {
// get the project
this.selection = new StructuredSelection(
ProductCustomizerMgr.getInstance().getProductCharacteristics().getHiddenProject());
} else {
List selectedResources = IDE.computeSelectedResources(currentSelection);
if (!selectedResources.isEmpty()) {
this.selection = new StructuredSelection(selectedResources);
}
}
if( !ModelerUiViewUtils.workspaceHasOpenModelProjects() ) {
IProject newProject = ModelerUiViewUtils.queryUserToCreateModelProject();
if( newProject != null ) {
this.selection = new StructuredSelection(newProject);
} else {
addPage(NoOpenProjectsWizardPage.getStandardPage());
return;
}
}
if (importLicensed) {
createWizardPages(this.selection);
} else {
// Create empty page
WizardPage page = new WizardPage(WsdlFileSystemImportWizard.class.getSimpleName(), TITLE, null) {
@Override
public void createControl( final Composite parent ) {
setControl(createEmptyPageControl(parent));
}
};
page.setMessage(NOT_LICENSED_MSG, IMessageProvider.ERROR);
page.setPageComplete(false);
addPage(page);
}
setNeedsProgressMonitor(true);
}
public void createWizardPages( ISelection theSelection ) {
if (selection != null && !selection.isEmpty()) {
final Object obj = selection.getFirstElement();
final IContainer someFolder = ModelUtil.getContainer(obj);
try {
if (someFolder != null && someFolder.getProject().getNature(ModelerCore.NATURE_ID) != null) {
this.folder = someFolder;
}
} catch (final CoreException err) {
IInternalUiConstants.UTIL.log(err);
WidgetUtil.showError(err);
}
}
IPath theModelPath = null;
if (folder!=null) {
theModelPath = folder.getFullPath();
}
MetamodelDescriptor theDescriptor = getGenerateFromWsdlDescriptor();
this.builder = WebServicePlugin.createModelBuilder(folder, theModelPath, theDescriptor);
// User new method to wait until finished before saving resources Fixes import problem
this.builder.setSaveAllBeforeFinish(true);
// construct pages
this.wsdlSelectionPage = new WsdlSelectionPage(this.builder, EditableNameField.EDITABLE);
wsdlSelectionPage.setPageComplete(false);
addPage(wsdlSelectionPage);
// Defect 24620 - missing the WSDL validation page.
this.wsdlValidationPage = new ImportWsdlValidationPage(this.builder);
wsdlValidationPage.setPageComplete(true);
addPage(wsdlValidationPage);
this.namespaceResolutionPage = new NamespaceResolutionPage(this.builder);
namespaceResolutionPage.setPageComplete(false);
addPage(namespaceResolutionPage);
this.selectWsdlOperationsPage = new SelectWsdlOperationsPage(this.builder);
selectWsdlOperationsPage.setPageComplete(false);
addPage(selectWsdlOperationsPage);
this.schemaLocationPage = new SchemaLocationPage(this.builder);
addPage(schemaLocationPage);
this.xmlSelectionPage = new XmlModelSelectionPage(this.builder);
addPage(xmlSelectionPage);
// give the WSDL selection page the current workspace selection
((WsdlSelectionPage)this.wsdlSelectionPage).setInitialSelection(theSelection);
}
/**
* @see org.eclipse.jface.wizard.IWizard#performFinish()
* @since 4.0
*/
@Override
public boolean finish() {
boolean result = true;
/*
* 'finish' will use the previously created 'processor' instead of creating a fresh one, if one was previously created.
*/
autoBuildOn = ModelerCore.getWorkspace().isAutoBuilding();
if (autoBuildOn) {
JobUtils.setAutoBuild(false);
}
// Save object selections from previous page
final IRunnableWithProgress op = new IRunnableWithProgress() {
@Override
public void run( final IProgressMonitor monitor ) {
// Wrap in transaction so it doesn't result in Significant Undoable
boolean started = ModelerCore.startTxn(false, false, "Create WS from WSDL on File System", //$NON-NLS-1$
new DefaultIgnorableNotificationSource(WsdlFileSystemImportWizard.this));
boolean succeeded = false;
boolean overrideRollback = false;
if (started) {
overrideRollback = true;
((UnitOfWorkImpl)ModelerCore.getCurrentUoW()).setOverrideRollback(overrideRollback);
}
try {
// Defect 23075 setting succeeded to the return value of runFinish() so we can catch if the operation was
// cancelled or not. We need to delete any new resources if user cancelled.
succeeded = !runFinish(monitor);
} finally {
if (started) {
if (succeeded) {
ModelerCore.commitTxn();
} else {
if (overrideRollback) {
rollbackNewResources = true;
} else {
ModelerCore.rollbackTxn();
}
ModelerCore.rollbackTxn();
}
}
}
}
};
try {
new ProgressMonitorDialog(getShell()).run(true, true, op);
switch (this.status.getSeverity()) {
case IStatus.WARNING:
case IStatus.INFO:
case IStatus.OK:
break;
case IStatus.ERROR:
default:
IInternalUiConstants.UTIL.log(this.status);
// WidgetUtil.showError(IMPORT_ERROR_MESSAGE);
break;
}
result = true;
} catch (Throwable err) {
} finally {
if (rollbackNewResources) {
// Defect 23075 - Process the builder's new resources and DELETE them as part of this rollback.
final List newResources = builder.getAllNewResources();
if (newResources != null && !newResources.isEmpty()) {
DeleteAction action = new DeleteAction();
action.selectionChanged(null, new StructuredSelection(newResources));
action.run();
// Defect 23075 - if auto-build is ON, we need to listen for the DELETE action being DONE, then we can
// re-set the auto-build to ON again. This insures that we don't auto-build on resources that we are going
// to delete anyway.
if (autoBuildOn) {
if (JobUtils.jobExists(IDEWorkbenchMessages.DeleteResourceAction_jobName)) {
Job.getJobManager().addJobChangeListener(new SetAutobuildOnJobListener());
} else {
JobUtils.setAutoBuild(true);
}
}
}
} else {
JobUtils.setAutoBuild(autoBuildOn);
}
dispose();
}
return result;
}
/**
* @see org.eclipse.jface.wizard.IWizard#canFinish()
* @since 4.0
*/
@Override
public boolean canFinish() {
return super.canFinish();
}
/**
* @see org.eclipse.jface.wizard.IWizard#dispose()
* @since 4.0
*/
@Override
public void dispose() {
super.dispose();
}
public boolean runFinish( IProgressMonitor theMonitor ) {
boolean wasCancelled = false;
int severity = this.builder.validateWSDLNamespaces().getSeverity();
CoreArgCheck.isTrue(severity < IStatus.ERROR, "ERROR validating WSDL Namespaces"); //$NON-NLS-1$
severity = this.builder.validateXSDNamespaces().getSeverity();
CoreArgCheck.isTrue(severity < IStatus.ERROR, "ERROR validating XSD Namespaces"); //$NON-NLS-1$;
// Check if user canceled yet (Defect 23075)
if (!theMonitor.isCanceled()) {
try {
this.status = this.builder.getModelGenerator(true).execute(theMonitor);
// Check again if user cancelled yet (Defect 23075)
if (!wasCancelled && !theMonitor.isCanceled()) {
// display & log messages if needed
if (this.status != null) {
// log
logMessage(this.status);
final IStatus filteredStatus = filterStatus(this.status);
if (filteredStatus != null) {
// display
UiUtil.getWorkbenchShellOnlyIfUiThread().getDisplay().asyncExec(new Runnable() {
@Override
public void run() {
// ErrorDialog does not open if status OK. And doesn't ever display embedded OK statuses.
ErrorDialog.openError(UiUtil.getWorkbenchShellOnlyIfUiThread(),
UTIL.getString(I18N_PREFIX + "dialog.messages.title"), //$NON-NLS-1$
null,
filteredStatus,
IStatus.ERROR | IStatus.WARNING | IStatus.INFO);
}
});
}
}
} else {
wasCancelled = true;
}
} catch (CoreException theException) {
UTIL.log(theException);
WidgetUtil.showError(UTIL.getString(I18N_PREFIX + "generateModelProblem")); //$NON-NLS-1$
}
} else {
// Defect 23075
wasCancelled = true;
}
return wasCancelled;
}
private IStatus filterStatus( IStatus theStatus ) {
IStatus result = null;
if (theStatus instanceof MultiStatus) {
result = new MultiStatus(theStatus.getPlugin(), theStatus.getCode(), theStatus.getMessage(), theStatus.getException());
} else {
result = theStatus;
}
if (result instanceof MultiStatus) {
MultiStatus multiStatus = (MultiStatus)result;
IStatus[] kids = multiStatus.getChildren();
for (int i = 0; i < kids.length; i++) {
IStatus kidStatus = filterStatus(kids[i]);
if (kidStatus != null) {
multiStatus.add(kidStatus);
}
}
if (multiStatus.getChildren().length == 0) {
result = null;
}
} else {
// filter here
if (result.getSeverity() == IStatus.WARNING) {
int code = result.getCode();
if ((code == WebServiceModelProducer.WARNING_NO_WSDL_OBJECTS) || (code == ModelGenerator.COMPLETED_WITH_WARNINGS)) {
result = null;
}
}
}
return result;
}
/**
* Writes the specified <code>IStatus</code> severity, code, and message to the log. <code>IStatus.OK</code> messages are not
* logged.
*
* @param theStatus the status being logged
* @since 4.2
*/
private void logMessage( IStatus theStatus ) {
if (theStatus.getSeverity() != IStatus.OK) {
UTIL.log(theStatus.getSeverity(), UTIL.getString(I18N_PREFIX + "logMessage", //$NON-NLS-1$
new Object[] {String.valueOf(theStatus.getCode()),
theStatus.getMessage()}));
if (theStatus.isMultiStatus()) {
IStatus[] kids = theStatus.getChildren();
for (int i = 0; i < kids.length; i++) {
logMessage(kids[i]);
}
}
}
}
protected MetamodelDescriptor getGenerateFromWsdlDescriptor() {
// this method is called during contruction
Collection /*<MetamodelDescriptor>*/mmdescs = Arrays.asList(ModelerCore.getMetamodelRegistry().getMetamodelDescriptors());
MetamodelDescriptor wsmmd = null;
Iterator it = mmdescs.iterator();
while (it.hasNext() && wsmmd == null) {
MetamodelDescriptor mmd = (MetamodelDescriptor)it.next();
String baseDisplayName = mmd.getDisplayName();
if( baseDisplayName.endsWith(DEPRECATED_SUFFIX) ) {
int length = baseDisplayName.length();
baseDisplayName = baseDisplayName.substring(0, length - DEPRECATED_SUFFIX.length());
}
if (UiPlugin.getDefault().isProductContextValueSupported(Metamodel.URI, mmd.getNamespaceURI())
&& mmd.supportsNewModel()) {
List typeList = new ArrayList(Arrays.asList(mmd.getAllowableModelTypes()));
typeList.remove(ModelType.METAMODEL_LITERAL);
if (mmd.getName().equalsIgnoreCase(WEB_SERVICES_CLASS_ID )
|| baseDisplayName.equalsIgnoreCase(WEB_SERVICES_CLASS_ID)) {
wsmmd = mmd;
}
}
}
return wsmmd;
}
class SetAutobuildOnJobListener extends JobChangeAdapter {
@Override
public void done( IJobChangeEvent theEvent ) {
if (theEvent.getJob().getName() != null
&& theEvent.getJob().getName().equals(IDEWorkbenchMessages.DeleteResourceAction_jobName)) {
Job.getJobManager().removeJobChangeListener(this);
Display.getDefault().asyncExec(new Runnable() {
@Override
public void run() {
JobUtils.setAutoBuild(true);
}
});
}
}
}
/**
* Overriding so we can set the messages in the validation page See: Defect 24620 - missing the WSDL validation page.
*
* @see org.eclipse.jface.wizard.IWizard#getNextPage(org.eclipse.jface.wizard.IWizardPage)
* @since 5.0
*/
@Override
public IWizardPage getNextPage( IWizardPage page ) {
CoreArgCheck.isNotNull(page);
final int ndx = indexOf(page);
List pgs = Arrays.asList(getPages());
// Return null if last page or page not found
if (ndx == pgs.size() - 1 || ndx < 0) {
return null;
}
IWizardPage nextPage = (IWizardPage)pgs.get(ndx + 1);
if (nextPage instanceof ImportWsdlValidationPage) {
Map wsdlMessages = ((WsdlSelectionPage)page).getWsdlValidationMessages();
ImportWsdlValidationPage validationPage = (ImportWsdlValidationPage)nextPage;
validationPage.clearValidationMessages();
if (wsdlMessages.size() > 0) {
validationPage.setValidationMessages(wsdlMessages);
validationPage.setPageComplete(false);
} else {
/*
* if there are no validation messages, we skip this page and move on
* to the next. nothing to show.
*/
// If page complete isn't set to
validationPage.setPageComplete(true);
nextPage = (IWizardPage)pgs.get(ndx + 2);
}
}
return nextPage;
}
}