/*
* 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.ui.actions;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.MultiStatus;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.window.Window;
import org.eclipse.jface.wizard.WizardDialog;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IViewReference;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.dialogs.ISelectionStatusValidator;
import org.teiid.core.designer.ModelerCoreException;
import org.teiid.designer.core.ModelerCore;
import org.teiid.designer.core.util.ModelVisitor;
import org.teiid.designer.core.util.ModelVisitorProcessor;
import org.teiid.designer.core.workspace.ModelResource;
import org.teiid.designer.core.workspace.ModelWorkspaceException;
import org.teiid.designer.metamodels.relational.Catalog;
import org.teiid.designer.metamodels.relational.Procedure;
import org.teiid.designer.metamodels.relational.Schema;
import org.teiid.designer.metamodels.relational.Table;
import org.teiid.designer.ui.PluginConstants;
import org.teiid.designer.ui.UiConstants;
import org.teiid.designer.ui.UiPlugin;
import org.teiid.designer.ui.common.eventsupport.SelectionUtilities;
import org.teiid.designer.ui.common.product.ProductCustomizerMgr;
import org.teiid.designer.ui.common.viewsupport.StatusInfo;
import org.teiid.designer.ui.common.widget.ListMessageDialog;
import org.teiid.designer.ui.editors.ModelEditor;
import org.teiid.designer.ui.editors.ModelEditorManager;
import org.teiid.designer.ui.explorer.ModelExplorerContentProvider;
import org.teiid.designer.ui.explorer.ModelExplorerLabelProvider;
import org.teiid.designer.ui.viewsupport.ModelIdentifier;
import org.teiid.designer.ui.viewsupport.ModelUtilities;
import org.teiid.designer.ui.viewsupport.ModelWorkspaceDialog;
import org.teiid.designer.ui.wizards.GenerateXsdWizard;
/**
* @since 8.0
*/
public class GenerateXsdSchemaAction2 extends SortableSelectionAction {
static final IStatus STATUS_OK = new StatusInfo(UiConstants.PLUGIN_ID);
static final IStatus STATUS_ERROR = new StatusInfo(UiConstants.PLUGIN_ID, IStatus.ERROR,
"Invalid selection. Must be relational models and/or tables"); //$NON-NLS-1$
//UiConstants.Util.getString("validationError")); //$NON-NLS-1$
private static final String SELECTION_DIALOG_TITLE = UiConstants.Util.getString("GenerateXsdSchemaAction.selectionDialog.title"); //$NON-NLS-1$
private static final String SELECTION_DIALOG_MESSAGE = UiConstants.Util.getString("GenerateXsdSchemaAction.selectionDialog.initialMessage"); //$NON-NLS-1$
private static final String KEY_NO_SEL_DLG_MSG = "GenerateXsdSchemaAction.noSelMsg"; //$NON-NLS-1$
private static final String NO_SEL_DLG_TITLE = UiConstants.Util.getString("GenerateXsdSchemaAction.noSelTitle"); //$NON-NLS-1$
private static final String DEFAULT_EXPLORER_TITLE = UiConstants.Util.getString("GenerateXsdSchemaAction.defaultViewName"); //$NON-NLS-1$;
private boolean canIgnoreSelection = false;
public GenerateXsdSchemaAction2() {
super();
setImageDescriptor(UiPlugin.getDefault().getImageDescriptor(PluginConstants.Images.CREATE_WEB_SERVICE_ICON));
}
@Override
public void run() {
IWorkbenchWindow iww = UiPlugin.getDefault().getCurrentWorkbenchWindow();
// ----------------------------------------------------
// Defect 22355: added preProcess() check to see if VDB is dirty or any Models are Dirty.
// We need to pre-process this through product characteristics
// ----------------------------------------------------
if (!ProductCustomizerMgr.getInstance().getProductCharacteristics().preProcess(this, iww.getShell())) {
notifyResult(false);
return;
}
// ----------------------------------------------------
ISelection selection = getSelection();
// We can handle single selection, multiple selection AND NO selection.
// 1) If a document or document root is NOT selected we
// go ahead and process.
// 2) If Document Model selected ONLY, we present dialog to select document or document root within model
// 3) If NULL, NONE OF THE ABOVE are selected, we present a dialog to document or document root within model
// from the whole workspace/VDB
IStructuredSelection thisSelection = null;
if (isValidSelection(selection)) {
thisSelection = (IStructuredSelection)selection;
if( ! checkDirtyRelationalModel(thisSelection, iww.getShell()) ) {
return;
}
} else if (canIgnoreSelection) {
// Set to false in case there's an exception and it doesn't get set back.
canIgnoreSelection = false;
// Present user a selection dialog to get selection
ILabelProvider labelProvider = new ModelExplorerLabelProvider();
ITreeContentProvider contentProvider = new ModelExplorerContentProvider();
ModelWorkspaceDialog wsDialog = new ModelWorkspaceDialog(
UiPlugin.getDefault().getCurrentWorkbenchWindow().getShell(),
null, labelProvider, contentProvider);
wsDialog.setValidator(new Validator());
wsDialog.setTitle(SELECTION_DIALOG_TITLE);
wsDialog.setMessage(SELECTION_DIALOG_MESSAGE);
wsDialog.open();
if (wsDialog.getReturnCode() == Window.OK) {
Object[] oSelectedObjects = wsDialog.getResult();
// add the selected location to this Relationship
if (oSelectedObjects.length > 0) {
thisSelection = new StructuredSelection(oSelectedObjects);
} else {
// ERROR !!!!!
String title = UiConstants.Util.getString("GenerateWebServiceModelAction.selectionError.title"); //$NON-NLS-1$
String dlgMsg = UiConstants.Util.getString("GenerateWebServiceModelAction.selectionError.emptySelection"); //$NON-NLS-1$
MessageDialog.openError(iww.getShell(), title, dlgMsg);
notifyResult(false);
return;
}
if (!isValidSelection(thisSelection)) {
// ERROR !!!!!
String title = UiConstants.Util.getString("GenerateWebServiceModelAction.selectionError.title"); //$NON-NLS-1$
String dlgMsg = UiConstants.Util.getString("GenerateWebServiceModelAction.selectionError.wrongType"); //$NON-NLS-1$
MessageDialog.openError(iww.getShell(), title, dlgMsg);
notifyResult(false);
}
} else {
return;
}
} else {
// selection empty, tell user to select something:
IViewReference ivr = iww.getActivePage().findViewReference(ProductCustomizerMgr.getInstance().getProductCharacteristics().getPrimaryNavigationViewId());
String viewTitle;
if (ivr != null) {
viewTitle = ivr.getTitle();
} else {
// don't have a view ref, use a default name:
viewTitle = DEFAULT_EXPLORER_TITLE;
} // endif
// show the dialog:
String dlgMsg = UiConstants.Util.getString(KEY_NO_SEL_DLG_MSG, viewTitle);
MessageDialog.openError(iww.getShell(), NO_SEL_DLG_TITLE, dlgMsg);
return;
}
final GenerateXsdWizard wizard = new GenerateXsdWizard();
wizard.init(iww.getWorkbench(), thisSelection);
final WizardDialog dialog = new WizardDialog(wizard.getShell(), wizard);
int rc = dialog.open();
if (rc != Window.CANCEL) {
final MultiStatus result = wizard.getResult();
final int severity = result.getSeverity();
if (severity == IStatus.ERROR) {
final String errTitle = UiConstants.Util.getString("GenerateXsdSchemaAction.errTitle"); //$NON-NLS-1$
final String err = UiConstants.Util.getString("GenerateXsdSchemaAction.errFinish"); //$NON-NLS-1$
ErrorDialog.openError(wizard.getShell(), errTitle, err, result);
} else if (severity == IStatus.WARNING) {
final String warnTitle = UiConstants.Util.getString("GenerateXsdSchemaAction.warnTitle"); //$NON-NLS-1$
final String warn = UiConstants.Util.getString("GenerateXsdSchemaAction.warnFinish"); //$NON-NLS-1$
ErrorDialog.openError(wizard.getShell(), warnTitle, warn, result);
} else {
final String okTitle = UiConstants.Util.getString("GenerateXsdSchemaAction.successTitle"); //$NON-NLS-1$
final String ok = UiConstants.Util.getString("GenerateXsdSchemaAction.successFinish"); //$NON-NLS-1$
List msgs = new ArrayList(result.getChildren().length);
for (int i = 0; i < result.getChildren().length; i++) {
msgs.add(result.getChildren()[i].getMessage());
}
// Defect 20589 - Thread off this dialog, so it shows up AFTER auto-build and other jobs which are
// causing more Progress monitors to appear (lots of flashing).
final List messgs = msgs;
Display.getCurrent().asyncExec(new Runnable() {
@Override
public void run() {
ListMessageDialog.openInformation(wizard.getShell(), okTitle, null, ok, messgs, null);
if (wizard.getWebServiceModel() != null) {
// Changed to use method that insures Object editor mode is on
ModelEditorManager.openInEditMode(wizard.getWebServiceModel(),
true,
UiConstants.ObjectEditor.IGNORE_OPEN_EDITOR);
}
}
});
}
notifyResult(severity < IStatus.ERROR);
}
}
/**
* Valid selections include Relational Tables, Procedures or Relational Models. The roots instance variable will populated
* with all Tables and Procedures contained within the current selection.
*
* @return
* @since 4.1
*/
@Override
protected boolean isValidSelection( ISelection selection ) {
boolean isValid = true;
if (SelectionUtilities.isEmptySelection(selection)) {
isValid = false;
}
if( !SelectionUtilities.isAllEObjects(selection) &&
!SelectionUtilities.isAllIResourceObjects(selection) ) {
isValid = false;
}
if( SelectionUtilities.isAllIResourceObjects(selection) &&
!SelectionUtilities.isSingleSelection(selection) ) {
isValid = false;
}
if (isValid) {
final Collection objs = SelectionUtilities.getSelectedObjects(selection);
final Iterator selections = objs.iterator();
while (selections.hasNext() && isValid) {
final Object next = selections.next();
if (next instanceof Table) {
isValid = true;
} else if (next instanceof Procedure) {
isValid = true;
} else if (next instanceof IFile) {
final ModelResource modelResource = ModelerCore.getModelWorkspace().findModelResource((IFile)next);
if (modelResource != null) {
try {
// defect 19183 - do not load models on selection:
isValid = ModelUtilities.isRelationalModel(modelResource) && hasTableOrProcedure(modelResource);
} catch (ModelWorkspaceException err) {
UiConstants.Util.log(err);
isValid = false;
} catch (ModelerCoreException err) {
UiConstants.Util.log(err);
isValid = false;
}
} else {
isValid = false;
}
} else {
isValid = false;
}
// stop processing if no longer valid:
if (!isValid) {
break;
} // endif -- valid
} // endwhile -- all selected
} // endif -- is empty sel
return isValid;
}
@Override
public boolean isApplicable( ISelection selection ) {
return isValidSelection(selection);
}
private boolean checkDirtyRelationalModel( ISelection selection, Shell shell ) {
if( SelectionUtilities.isSingleSelection(selection)) {
final Object obj = SelectionUtilities.getSelectedObject(selection);
if (obj instanceof IFile) {
final ModelResource modelResource = ModelerCore.getModelWorkspace().findModelResource((IFile)obj);
if (modelResource != null &&
(ModelIdentifier.isRelationalSourceModel(modelResource) ||
ModelIdentifier.isRelationalViewModel(modelResource) ) ) {
ModelEditor openEditor = ModelEditorManager.getModelEditorForFile((IFile)obj, false);
if( openEditor != null && openEditor.isDirty() ) {
MessageDialog.openWarning(shell, UiConstants.Util.getString("GenerateXsdSchemaAction.unsavedChangesTitle"), //$NON-NLS-1$
UiConstants.Util.getString("GenerateXsdSchemaAction.unsavedChangesMessage", modelResource.getItemName())); //$NON-NLS-1$
return false;
}
}
}
}
return true;
}
/*
* A relational model may be Empty or have no tables or procedures. In this case the wizard can't create anything.
*/
private boolean hasTableOrProcedure(ModelResource mr) throws ModelWorkspaceException, ModelerCoreException {
TableOrProcedureFinder visitor = new TableOrProcedureFinder();
final int mode = ModelVisitorProcessor.MODE_VISIBLE_CONTAINMENTS; // show only those objects visible to user
final ModelVisitorProcessor processor = new ModelVisitorProcessor(visitor,mode);
processor.walk(mr, ModelVisitorProcessor.DEPTH_INFINITE);
return visitor.hasTableOrProcedure();
// for( Object eObj : mr.getEObjects() ) {
// if( eObj instanceof Table || eObj instanceof Procedure ) {
// return true;
// }
// }
//
// return false;
}
/**
* Validates the selection ensuring there is no .project file in the selected directory or in an ancestor directory.
*
* @since 4.2
*/
class Validator implements ISelectionStatusValidator {
/**
* @see org.eclipse.ui.dialogs.ISelectionStatusValidator#validate(java.lang.Object[])
* @since 4.2
*/
@Override
public IStatus validate( Object[] theSelection ) {
IStructuredSelection selection = new StructuredSelection(theSelection);
IStatus result = STATUS_OK;
if (!isValidSelection(selection)) {
result = STATUS_ERROR;
}
return result;
}
}
/**
* @param theCanIgnoreSelection The canIgnoreSelection to set.
* @since 5.0
*/
public void setCanIgnoreSelection( boolean theCanIgnoreSelection ) {
this.canIgnoreSelection = theCanIgnoreSelection;
}
class TableOrProcedureFinder implements ModelVisitor {
boolean hasTableOrProcedure = false;
@SuppressWarnings("unused")
@Override
public boolean visit(EObject object) throws ModelerCoreException {
// Tables are contained by Catalogs, Schemas and Resources
if (object instanceof Table) {
hasTableOrProcedure = true;
return false;
}
if (object instanceof Procedure) {
hasTableOrProcedure = true;
return true;
}
if (object instanceof Catalog) {
// catalogs will contain tables
return true;
}
if (object instanceof Schema) {
// schemas will contain tables
return true;
}
return false;
}
@SuppressWarnings("unused")
@Override
public boolean visit(Resource resource) throws ModelerCoreException {
return true;
}
public boolean hasTableOrProcedure() {
return hasTableOrProcedure;
}
}
}