package org.teiid.designer.transformation.ui.actions;
import java.util.Properties;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.dialogs.TitleAreaDialog;
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.ModelUtil;
import org.teiid.designer.core.workspace.ModelWorkspaceException;
import org.teiid.designer.relational.RelationalConstants;
import org.teiid.designer.relational.model.RelationalModel;
import org.teiid.designer.relational.model.RelationalModelFactory;
import org.teiid.designer.relational.model.RelationalParameter;
import org.teiid.designer.relational.model.RelationalProcedure;
import org.teiid.designer.relational.model.RelationalViewProcedure;
import org.teiid.designer.relational.model.RelationalProcedure.PROCEDURE_TYPE;
import org.teiid.designer.relational.ui.UiConstants;
import org.teiid.designer.relational.ui.UiPlugin;
import org.teiid.designer.relational.ui.edit.RelationalDialogModel;
import org.teiid.designer.relational.ui.editor.EditRelationalObjectDialog;
import org.teiid.designer.relational.ui.textimport.RelationalTableLocationSelectionValidator;
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.transformation.ui.textimport.VirtualModelSelectorDialog;
import org.teiid.designer.transformation.ui.textimport.VirtualTablelLocationSelectionValidator;
import org.teiid.designer.transformation.ui.wizards.RelationalModelSelectorDialog;
import org.teiid.designer.ui.editors.ModelEditor;
import org.teiid.designer.ui.editors.ModelEditorManager;
/**
* This class provides a mechanism to create either a User Defined Function or a Pushdown/Source Function
*
* @author blafond
*
*/
public class CreateFunctionAction extends Action {
/**
*
*/
public CreateFunctionAction() {
super(Messages.createFunctionLabel);
setImageDescriptor(UiPlugin.getDefault().getImageDescriptor( UiConstants.Images.NEW_PROCEDURE_ICON));
}
/**
* @param properties the initial Designer properties
*/
public CreateFunctionAction( Properties properties ) {
this();
}
public void run(String name, int numArgs) {
final Shell shell = UiPlugin.getDefault().getCurrentWorkbenchWindow().getShell();
SelectFunctionTypeDialog procedureTypeDialog = new SelectFunctionTypeDialog(shell);
procedureTypeDialog.open();
if (procedureTypeDialog.getReturnCode() == Window.OK) {
boolean isUDF = procedureTypeDialog.isUDF();
if( isUDF ) {
// TODO: Need to Ask user for a target VIEW model
ModelResource mr = queryUserForViewModel();
if( mr != null ) {
RelationalProcedure relationalProcedure = new RelationalViewProcedure(name);
relationalProcedure.setFunction(true);
for (int i=0; i<numArgs; i++ ) {
RelationalParameter param = new RelationalParameter("arg"+ (i+1)); //$NON-NLS-1$
param.setDatatype("string"); //$NON-NLS-1$
relationalProcedure.addParameter(param);
}
RelationalParameter returnParam = new RelationalParameter("return_param"); //$NON-NLS-1$
returnParam.setDatatype("string"); //$NON-NLS-1$
returnParam.setDirection(RelationalConstants.DIRECTION.RETURN);
relationalProcedure.addParameter(returnParam);
TransformationDialogModel dialogModel = new TransformationDialogModel(relationalProcedure, getCorrespondingResource(mr));
EditRelationalObjectDialog dialog = new EditRelationalObjectDialog(shell, dialogModel);
dialog.open();
if (dialog.getReturnCode() == Window.OK) {
createUDFInTxn(mr, (RelationalViewProcedure)relationalProcedure);
}
}
} else {
// TODO: Need to Ask user for a target SOURCE model
ModelResource mr = queryUserForModel();
if( mr != null ) {
RelationalProcedure relationalProcedure = new RelationalProcedure(name);
relationalProcedure.setProcedureType(PROCEDURE_TYPE.SOURCE_FUNCTION);
for (int i=0; i<numArgs; i++ ) {
RelationalParameter param = new RelationalParameter("arg"+ (i+1)); //$NON-NLS-1$
param.setDatatype("string"); //$NON-NLS-1$
relationalProcedure.addParameter(param);
}
// Hand the table off to the generic edit dialog
RelationalDialogModel dialogModel = new RelationalDialogModel(relationalProcedure, getCorrespondingResource(mr));
EditRelationalObjectDialog dialog = new EditRelationalObjectDialog(shell, dialogModel);
dialog.open();
if (dialog.getReturnCode() == Window.OK) {
createFunctionInTxn(mr, relationalProcedure);
}
}
}
}
}
private void createUDFInTxn( ModelResource modelResource, RelationalViewProcedure viewProcedure ) {
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;
}
} 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;
} finally {
// if we started the txn, commit it.
if (requiredStart) {
if (succeeded) {
ModelerCore.commitTxn();
} else {
ModelerCore.rollbackTxn();
}
}
}
}
private void createFunctionInTxn(ModelResource modelResource, RelationalProcedure procedure) {
boolean requiredStart = ModelerCore.startTxn(true, true, "Create Source Function", this); //$NON-NLS-1$
boolean succeeded = false;
try {
ModelEditor editor = ModelEditorManager.getModelEditorForFile((IFile)modelResource.getCorrespondingResource(), true);
if (editor != null) {
boolean isDirty = editor.isDirty();
RelationalModelFactory factory = new RelationalModelFactory();
RelationalModel relModel = new RelationalModel("dummy"); //$NON-NLS-1$
relModel.addChild(procedure);
factory.build(modelResource, relModel, new NullProgressMonitor());
//factory.buildObject(table, modelResource, new NullProgressMonitor());
if (!isDirty && editor.isDirty()) {
editor.doSave(new NullProgressMonitor());
}
succeeded = true;
}
} catch (Exception e) {
MessageDialog.openError(Display.getCurrent().getActiveShell(), Messages.createRelationalProcedureExceptionMessage, e.getMessage());
IStatus status = new Status(IStatus.ERROR, UiConstants.PLUGIN_ID, Messages.createRelationalProcedureExceptionMessage, e);
UiConstants.Util.log(status);
return;
} finally {
// if we started the txn, commit it.
if (requiredStart) {
if (succeeded) {
ModelerCore.commitTxn();
} else {
ModelerCore.rollbackTxn();
}
}
}
}
private IFile getCorrespondingResource(ModelResource mr) {
IFile file = null;
try {
file = (IFile)mr.getCorrespondingResource();
} catch (ModelWorkspaceException e) {
UiConstants.Util.log(e);
}
return file;
}
class SelectFunctionTypeDialog extends TitleAreaDialog {
boolean isUDF = false;
public SelectFunctionTypeDialog(Shell parentShell) {
super(parentShell);
}
/**
* @see org.eclipse.jface.window.Window#constrainShellSize()
*/
@Override
protected void constrainShellSize() {
super.constrainShellSize();
final Shell shell = getShell();
shell.setText("Choose Function Type");
{ // 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);
{ // source function
final Button sourceFunctionRB = new Button(panel, SWT.RADIO);
sourceFunctionRB.setSelection(true);
sourceFunctionRB.setLayoutData(new GridData(SWT.LEFT, SWT.TOP, false, false));
sourceFunctionRB.setText(Messages.sourceFunctionLabel);
sourceFunctionRB.addSelectionListener(new SelectionAdapter() {
/**
* {@inheritDoc}
* @see org.eclipse.swt.events.SelectionAdapter#widgetSelected(org.eclipse.swt.events.SelectionEvent)
*/
@Override
public void widgetSelected( SelectionEvent e ) {
isUDF = !sourceFunctionRB.getSelection();
}
});
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.createRelationalSourceFunctionDescription);
}
{ // user defined function
final Button 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 ) {
isUDF = userDefinedFunctionRB.getSelection();
}
});
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;
}
public boolean isUDF() {
return this.isUDF;
}
}
private ModelResource queryUserForViewModel() {
VirtualModelSelectorDialog mwdDialog = new VirtualModelSelectorDialog(
UiPlugin.getDefault().getCurrentWorkbenchWindow().getShell());
mwdDialog.setValidator(new VirtualTablelLocationSelectionValidator());
mwdDialog.setAllowMultiple(false);
mwdDialog.open();
if (mwdDialog.getReturnCode() == Window.OK) {
Object[] oSelectedObjects = mwdDialog.getResult();
// add the selected location to this Relationship
try {
if (oSelectedObjects.length == 1 && oSelectedObjects[0] instanceof IFile) {
return ModelUtil.getModelResource((IFile)(IFile)oSelectedObjects[0], false);
}
} catch (ModelWorkspaceException e) {
UiConstants.Util.log(e);
}
}
return null;
}
private ModelResource queryUserForModel() {
RelationalModelSelectorDialog mwdDialog = new RelationalModelSelectorDialog(
UiPlugin.getDefault().getCurrentWorkbenchWindow().getShell());
mwdDialog.setValidator(new RelationalTableLocationSelectionValidator());
mwdDialog.setAllowMultiple(false);
mwdDialog.open();
if (mwdDialog.getReturnCode() == Window.OK) {
Object[] oSelectedObjects = mwdDialog.getResult();
// add the selected location to this Relationship
try {
if (oSelectedObjects.length == 1 && oSelectedObjects[0] instanceof IFile) {
return ModelUtil.getModelResource((IFile)(IFile)oSelectedObjects[0], false);
}
} catch (ModelWorkspaceException e) {
UiConstants.Util.log(e);
}
}
return null;
}
}