/*
* 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.transformation.ui.actions;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Properties;
import java.util.Set;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Status;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.dialogs.TitleAreaDialog;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.teiid.designer.core.ModelerCore;
import org.teiid.designer.core.workspace.ModelResource;
import org.teiid.designer.core.workspace.ModelWorkspaceException;
import org.teiid.designer.relational.model.RelationalModel;
import org.teiid.designer.relational.model.RelationalProcedure;
import org.teiid.designer.relational.model.RelationalViewProcedure;
import org.teiid.designer.relational.ui.UiConstants;
import org.teiid.designer.relational.ui.UiPlugin;
import org.teiid.designer.relational.ui.editor.EditRelationalObjectDialog;
import org.teiid.designer.transformation.model.RelationalViewModelFactory;
import org.teiid.designer.transformation.ui.Messages;
import org.teiid.designer.transformation.ui.editors.TransformationDialogModel;
import org.teiid.designer.type.IDataTypeManagerService;
import org.teiid.designer.ui.actions.INewChildAction;
import org.teiid.designer.ui.actions.INewSiblingAction;
import org.teiid.designer.ui.common.eventsupport.SelectionUtilities;
import org.teiid.designer.ui.editors.ModelEditor;
import org.teiid.designer.ui.editors.ModelEditorManager;
import org.teiid.designer.ui.viewsupport.DesignerPropertiesUtil;
import org.teiid.designer.ui.viewsupport.ModelIdentifier;
import org.teiid.designer.ui.viewsupport.ModelUtilities;
/**
* @since 8.0
*/
public class CreateViewProcedureAction extends Action implements INewChildAction, INewSiblingAction {
private IFile selectedModel;
private Collection<String> datatypes;
private Properties designerProperties;
private EObject newViewProcedure;
private RelationalViewProcedure relationalViewProcedure;
Button procedureRB;
Button userDefinedFunctionRB;
/**
*
*/
public CreateViewProcedureAction() {
super(Messages.createRelationalViewProcedureActionText);
setImageDescriptor(UiPlugin.getDefault().getImageDescriptor( UiConstants.Images.NEW_VIRTUAL_PROCEDURE_ICON));
IDataTypeManagerService service = ModelerCore.getTeiidDataTypeManagerService();
Set<String> unsortedDatatypes = service.getAllDataTypeNames();
datatypes = new ArrayList<String>();
String[] sortedStrings = unsortedDatatypes.toArray(new String[unsortedDatatypes.size()]);
Arrays.sort(sortedStrings);
for( String dType : sortedStrings ) {
datatypes.add(dType);
}
}
/**
* @param properties the intial Designer properties
*/
public CreateViewProcedureAction( Properties properties ) {
this();
this.designerProperties = properties;
}
/* (non-Javadoc)
* @See org.teiid.designer.ui.actions.INewChildAction#canCreateChild(org.eclipse.emf.ecore.EObject)
*/
@Override
public boolean canCreateChild(EObject parent) {
return false;
}
/* (non-Javadoc)
* @See org.teiid.designer.ui.actions.INewChildAc
tion#canCreateChild(org.eclipse.core.resources.IFile)
*/
@Override
public boolean canCreateChild(IFile modelFile) {
return isApplicable(new StructuredSelection(modelFile));
}
/* (non-Javadoc)
* @See org.teiid.designer.ui.actions.INewSiblingAction#canCreateChild(org.eclipse.emf.ecore.EObject)
*/
@Override
public boolean canCreateSibling(EObject parent) {
//Convert eObject selection to IFile
ModelResource mr = ModelUtilities.getModelResourceForModelObject(parent);
if( mr != null ) {
IFile modelFile = null;
try {
modelFile = (IFile)mr.getCorrespondingResource();
} catch (ModelWorkspaceException ex) {
UiConstants.Util.log(ex);
}
if( modelFile != null ) {
return isApplicable(new StructuredSelection(modelFile));
}
}
return false;
}
/**
* @param selection the selection
* @return if selection is applicable for this action
*/
public boolean isApplicable(ISelection selection) {
boolean result = false;
if (!SelectionUtilities.isMultiSelection(selection)) {
Object obj = SelectionUtilities.getSelectedObject(selection);
if (obj instanceof IResource) {
IResource iRes = (IResource) obj;
if (ModelIdentifier.isRelationalViewModel(iRes)) {
this.selectedModel = (IFile) obj;
result = true;
}
}
}
return result;
}
@Override
public void run() {
// If properties were passed in, use it's model as the selection - if available
if (this.designerProperties != null) {
IFile propsViewModel = DesignerPropertiesUtil.getViewModel(this.designerProperties);
if (propsViewModel != null) this.selectedModel = propsViewModel;
}
if( selectedModel != null ) {
ModelResource mr = ModelUtilities.getModelResource(selectedModel);
final Shell shell = UiPlugin.getDefault().getCurrentWorkbenchWindow().getShell();
relationalViewProcedure = new RelationalViewProcedure();
SelectProcedureTypeDialog procedureTypeDialog = new SelectProcedureTypeDialog(shell, relationalViewProcedure);
procedureTypeDialog.open();
if (procedureTypeDialog.getReturnCode() == Window.OK) {
TransformationDialogModel dialogModel = new TransformationDialogModel(relationalViewProcedure, selectedModel);
EditRelationalObjectDialog dialog = new EditRelationalObjectDialog(shell, dialogModel);
dialog.open();
if (dialog.getReturnCode() == Window.OK) {
this.newViewProcedure = createViewProcedureInTxn(mr, relationalViewProcedure);
} else {
this.relationalViewProcedure = null;
this.newViewProcedure = null;
}
}
}
}
private EObject createViewProcedureInTxn( ModelResource modelResource, RelationalViewProcedure viewProcedure ) {
EObject newTable = null;
boolean requiredStart = ModelerCore.startTxn(true, true, Messages.createRelationalViewProcedureTitle, this);
boolean succeeded = false;
try {
ModelEditor editor = ModelEditorManager.getModelEditorForFile((IFile)modelResource.getCorrespondingResource(), true);
if (editor != null) {
boolean isDirty = editor.isDirty();
RelationalViewModelFactory factory = new RelationalViewModelFactory();
RelationalModel relModel = new RelationalModel("dummy"); //$NON-NLS-1$
relModel.addChild(viewProcedure);
factory.build(modelResource, relModel, new NullProgressMonitor());
if (!isDirty && editor.isDirty()) {
editor.doSave(new NullProgressMonitor());
}
succeeded = true;
for( Object child : modelResource.getEObjects() ) {
EObject eObj = (EObject)child;
if( ModelerCore.getModelEditor().getName(eObj).equalsIgnoreCase(this.relationalViewProcedure.getName()) ) {
newTable = eObj;
break;
}
}
}
} catch (Exception e) {
MessageDialog.openError(Display.getCurrent().getActiveShell(),
Messages.createRelationalViewProcedureExceptionMessage,
e.getMessage());
IStatus status = new Status(IStatus.ERROR, UiConstants.PLUGIN_ID, Messages.createRelationalViewProcedureExceptionMessage, e);
UiConstants.Util.log(status);
return null;
} finally {
// if we started the txn, commit it.
if (requiredStart) {
if (succeeded) {
ModelerCore.commitTxn();
} else {
ModelerCore.rollbackTxn();
}
}
}
return newTable;
}
/**
* @return the new view procedure EObject
*/
public EObject getNewViewProcedure() {
return this.newViewProcedure;
}
class SelectProcedureTypeDialog extends TitleAreaDialog {
RelationalProcedure relationalProcedure;
public SelectProcedureTypeDialog(Shell parentShell, RelationalViewProcedure procedure) {
super(parentShell);
relationalProcedure = procedure;
}
/**
* @see org.eclipse.jface.window.Window#constrainShellSize()
*/
@Override
protected void constrainShellSize() {
super.constrainShellSize();
final Shell shell = getShell();
shell.setText(Messages.selectProcedureTypeDialogTitle);
{ // set size
final Rectangle r = shell.getBounds();
shell.setBounds(r.x, r.y, (int)(r.width * 0.67), r.height);
}
{ // center on parent
final Shell parentShell = (Shell)shell.getParent();
final Rectangle parentBounds = parentShell.getBounds();
final Point parentCenter = new Point(parentBounds.x + (parentBounds.width/2), parentBounds.y + parentBounds.height/2);
final Rectangle r = shell.getBounds();
final Point shellLocation = new Point(parentCenter.x - r.width/2, parentCenter.y - r.height/2);
shell.setBounds(Math.max(0, shellLocation.x), Math.max(0, shellLocation.y), r.width, r.height);
}
}
/**
* @see org.eclipse.jface.dialogs.TitleAreaDialog#createDialogArea(org.eclipse.swt.widgets.Composite)
* @since 5.5.3
*/
@Override
protected Control createDialogArea(Composite parent) {
Composite pnlOuter = (Composite) super.createDialogArea(parent);
Composite panel = new Composite(pnlOuter, SWT.NONE);
GridLayout gridLayout = new GridLayout();
gridLayout.marginLeft = 20;
gridLayout.marginRight = 20;
panel.setLayout(gridLayout);
panel.setLayoutData(new GridData(GridData.FILL_BOTH));
// set title
setTitle(Messages.selectProcedureTypeDialogSubTitle);
{ // simple procedure
procedureRB = new Button(panel, SWT.RADIO);
procedureRB.setLayoutData(new GridData(SWT.LEFT, SWT.TOP, false, false));
procedureRB.setText(Messages.procedureLabel);
procedureRB.addSelectionListener(new SelectionAdapter() {
/**
* {@inheritDoc}
* @see org.eclipse.swt.events.SelectionAdapter#widgetSelected(org.eclipse.swt.events.SelectionEvent)
*/
@Override
public void widgetSelected( SelectionEvent e ) {
handleInfoChanged();
}
});
procedureRB.setSelection(!relationalProcedure.isFunction());
Text descText = new Text(panel, SWT.MULTI | SWT.WRAP | SWT.READ_ONLY);
descText.setBackground(parent.getBackground());
descText.setForeground(Display.getCurrent().getSystemColor(SWT.COLOR_DARK_BLUE));
descText.setLayoutData(new GridData(SWT.LEFT, SWT.TOP, true, true));
((GridData)descText.getLayoutData()).horizontalIndent = 20;
((GridData)descText.getLayoutData()).heightHint = (3 * descText.getLineHeight());
descText.setText(Messages.createRelationalViewProcedureDescription);
}
{ // user defined function
userDefinedFunctionRB = new Button(panel, SWT.RADIO);
userDefinedFunctionRB.setLayoutData(new GridData(SWT.LEFT, SWT.TOP, false, false));
userDefinedFunctionRB.setText(Messages.userDefinedFunctionLabel);
userDefinedFunctionRB.addSelectionListener(new SelectionAdapter() {
/**
* {@inheritDoc}
* @see org.eclipse.swt.events.SelectionAdapter#widgetSelected(org.eclipse.swt.events.SelectionEvent)
*/
@Override
public void widgetSelected( SelectionEvent e ) {
handleInfoChanged();
}
});
Text descText = new Text(panel, SWT.MULTI | SWT.WRAP | SWT.READ_ONLY);
descText.setBackground(parent.getBackground());
descText.setForeground(Display.getCurrent().getSystemColor(SWT.COLOR_DARK_BLUE));
descText.setLayoutData(new GridData(SWT.LEFT, SWT.TOP, true, true));
((GridData)descText.getLayoutData()).horizontalIndent = 20;
((GridData)descText.getLayoutData()).heightHint = (3 * descText.getLineHeight());
descText.setText(Messages.createRelationalViewUserDefinedFunctionDescription);
}
return pnlOuter;
}
private void handleInfoChanged( ) {
if( procedureRB.getSelection() ) {
relationalProcedure.setProcedureType(RelationalProcedure.PROCEDURE_TYPE.PROCEDURE);
} else {
relationalProcedure.setProcedureType(RelationalProcedure.PROCEDURE_TYPE.FUNCTION);
}
}
}
}