/*
* 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.relational.ui.actions;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
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.metamodels.relational.Index;
import org.teiid.designer.metamodels.relational.Procedure;
import org.teiid.designer.metamodels.relational.Table;
import org.teiid.designer.relational.model.RelationalColumn;
import org.teiid.designer.relational.model.RelationalModel;
import org.teiid.designer.relational.model.RelationalModelFactory;
import org.teiid.designer.relational.model.RelationalProcedure;
import org.teiid.designer.relational.model.RelationalProcedureResultSet;
import org.teiid.designer.relational.ui.Messages;
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.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.ModelIdentifier;
import org.teiid.designer.ui.viewsupport.ModelUtilities;
/**
*
*/
public class CreateRelationalProcedureAction extends Action implements INewChildAction, INewSiblingAction {
private IFile selectedModel;
private Collection<String> datatypes;
protected int currentProcedureType = RelationalProcedure.PROCEDURE_TYPE.FUNCTION.ordinal();
Button procedureRB;
Button sourceFunctionRB;
Button nativeQueryProcedureRB;
/**
*
*/
public CreateRelationalProcedureAction() {
super(Messages.createRelationalProcedureActionText);
setImageDescriptor(UiPlugin.getDefault().getImageDescriptor( UiConstants.Images.NEW_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);
}
}
/* (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.INewChildAction#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) {
// has to be a table, view, procedure or function
if( !(parent instanceof Table || parent instanceof Procedure || parent instanceof Index) ) {
return false;
}
//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 selected object
* @return if applicable to selection
*/
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.isRelationalSourceModel(iRes)) {
this.selectedModel = (IFile) obj;
result = true;
}
}
}
return result;
}
@Override
public void run() {
if( selectedModel != null ) {
ModelResource mr = ModelUtilities.getModelResource(selectedModel);
final Shell shell = UiPlugin.getDefault().getCurrentWorkbenchWindow().getShell();
RelationalProcedure procedure = new RelationalProcedure();
SelectProcedureTypeDialog procedureTypeDialog = new SelectProcedureTypeDialog(shell, procedure);
procedureTypeDialog.open();
if (procedureTypeDialog.getReturnCode() == Window.OK) {
if( procedure.isNativeQueryProcedure() ) {
RelationalProcedureResultSet resultSet = new RelationalProcedureResultSet("ResultSet");
RelationalColumn column = new RelationalColumn("output");
column.setDatatype("object");
resultSet.addColumn(column);
procedure.setResultSet(resultSet);
}
// Hand the table off to the generic edit dialog
RelationalDialogModel dialogModel = new RelationalDialogModel(procedure, selectedModel);
EditRelationalObjectDialog dialog = new EditRelationalObjectDialog(shell, dialogModel);
dialog.open();
if (dialog.getReturnCode() == Window.OK) {
createProcedureInTxn(mr, procedure);
}
}
}
}
private void createProcedureInTxn(ModelResource modelResource, RelationalProcedure procedure) {
boolean requiredStart = ModelerCore.startTxn(true, true, Messages.createRelationalProcedureTitle, this);
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();
}
}
}
}
class SelectProcedureTypeDialog extends TitleAreaDialog {
RelationalProcedure relationalProcedure;
public SelectProcedureTypeDialog(Shell parentShell, RelationalProcedure 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(SWT.LEFT, SWT.TOP, true, true));
// 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.createRelationalProcedureDescription);
}
{ // source function
sourceFunctionRB = new Button(panel, SWT.RADIO);
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 ) {
handleInfoChanged();
}
});
if (this.relationalProcedure.isSourceFunction()) {
sourceFunctionRB.setSelection(relationalProcedure.isSourceFunction());
}
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);
}
{ // Native Query PRocedure
nativeQueryProcedureRB = new Button(panel, SWT.RADIO);
nativeQueryProcedureRB.setLayoutData(new GridData(SWT.LEFT, SWT.TOP, false, false));
nativeQueryProcedureRB.setText(Messages.nativeQueryProcedureLabel);
nativeQueryProcedureRB.addSelectionListener(new SelectionAdapter() {
/** nativeQueryProcedureRB
* {@inheritDoc}
* @see org.eclipse.swt.events.SelectionAdapter#widgetSelected(org.eclipse.swt.events.SelectionEvent)
*/
@Override
public void widgetSelected( SelectionEvent e ) {
handleInfoChanged();
}
});
if (this.relationalProcedure.isNativeQueryProcedure()) {
nativeQueryProcedureRB.setSelection(relationalProcedure.isNativeQueryProcedure());
}
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.createRelationalNativeQueryProcedureDescription);
}
return pnlOuter;
}
private void handleInfoChanged() {
if( procedureRB.getSelection() ) {
relationalProcedure.setProcedureType(RelationalProcedure.PROCEDURE_TYPE.PROCEDURE);
} else if( sourceFunctionRB.getSelection()) {
relationalProcedure.setProcedureType(RelationalProcedure.PROCEDURE_TYPE.SOURCE_FUNCTION);
} else {
relationalProcedure.setProcedureType(RelationalProcedure.PROCEDURE_TYPE.NATIVE_QUERY_PROCEDURE);
}
}
}
}