/*
* 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.editors;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.EventObject;
import java.util.Iterator;
import java.util.List;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.draw2d.EventListenerList;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.edit.provider.INotifyChangedListener;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.ControlContribution;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.action.ToolBarManager;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.text.IFindReplaceTarget;
import org.eclipse.jface.text.TextViewer;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CLabel;
import org.eclipse.swt.custom.CTabFolder;
import org.eclipse.swt.custom.CTabItem;
import org.eclipse.swt.custom.StackLayout;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.dnd.DND;
import org.eclipse.swt.dnd.DropTarget;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.MessageBox;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IPropertyListener;
import org.eclipse.ui.IWorkbenchWindow;
import org.teiid.core.designer.event.EventObjectListener;
import org.teiid.designer.core.ModelerCore;
import org.teiid.designer.core.notification.util.NotificationUtilities;
import org.teiid.designer.core.query.QueryValidator;
import org.teiid.designer.core.query.SetQueryUtil;
import org.teiid.designer.core.transaction.SourcedNotification;
import org.teiid.designer.core.workspace.ModelResource;
import org.teiid.designer.diagram.ui.DiagramUiPlugin;
import org.teiid.designer.diagram.ui.actions.DiagramActionService;
import org.teiid.designer.diagram.ui.editor.DiagramEditor;
import org.teiid.designer.metamodels.diagram.Diagram;
import org.teiid.designer.metamodels.transformation.InputSet;
import org.teiid.designer.metamodels.transformation.MappingClass;
import org.teiid.designer.metamodels.transformation.SqlTransformation;
import org.teiid.designer.metamodels.transformation.SqlTransformationMappingRoot;
import org.teiid.designer.query.sql.lang.ICommand;
import org.teiid.designer.query.sql.lang.IExpression;
import org.teiid.designer.query.sql.lang.IQueryCommand;
import org.teiid.designer.query.sql.lang.ISetQuery;
import org.teiid.designer.query.sql.lang.util.CommandHelper;
import org.teiid.designer.transformation.ui.Messages;
import org.teiid.designer.transformation.ui.PluginConstants;
import org.teiid.designer.transformation.ui.UiConstants;
import org.teiid.designer.transformation.ui.UiPlugin;
import org.teiid.designer.transformation.ui.actions.EditTransformationAction;
import org.teiid.designer.transformation.ui.actions.ITransformationDiagramActionConstants;
import org.teiid.designer.transformation.ui.actions.ReconcileTransformationAction;
import org.teiid.designer.transformation.ui.builder.criteria.QueryCriteriaStrategy;
import org.teiid.designer.transformation.ui.editors.sqleditor.SqlEditorEvent;
import org.teiid.designer.transformation.ui.editors.sqleditor.SqlEditorPanel;
import org.teiid.designer.transformation.ui.editors.sqleditor.SqlEditorPanelWrapper;
import org.teiid.designer.transformation.ui.editors.sqleditor.actions.ToggleOptimizer;
import org.teiid.designer.transformation.ui.search.OpenTransformationSearchPageAction2;
import org.teiid.designer.transformation.ui.util.BuilderTreeProvider;
import org.teiid.designer.transformation.ui.util.TransformationUiResourceHelper;
import org.teiid.designer.transformation.util.SqlMappingRootCache;
import org.teiid.designer.transformation.util.SqlTransformationStatusChangeEvent;
import org.teiid.designer.transformation.util.TransformationHelper;
import org.teiid.designer.transformation.util.TransformationMappingHelper;
import org.teiid.designer.transformation.util.TransformationSqlHelper;
import org.teiid.designer.transformation.validation.SqlTransformationResult;
import org.teiid.designer.transformation.validation.TransformationValidator;
import org.teiid.designer.ui.actions.ModelerActionBarIdManager;
import org.teiid.designer.ui.actions.ModelerSpecialActionManager;
import org.teiid.designer.ui.actions.SortableSelectionAction;
import org.teiid.designer.ui.common.util.UiUtil;
import org.teiid.designer.ui.common.util.WidgetFactory;
import org.teiid.designer.ui.common.widget.Label;
import org.teiid.designer.ui.editors.ModelEditor;
import org.teiid.designer.ui.editors.ModelEditorPage;
import org.teiid.designer.ui.editors.ModelObjectEditorPage;
import org.teiid.designer.ui.editors.MultiPageModelEditor;
import org.teiid.designer.ui.undo.IUndoManager;
import org.teiid.designer.ui.viewsupport.ModelObjectUtilities;
import org.teiid.designer.ui.viewsupport.ModelUtilities;
import org.teiid.designer.ui.viewsupport.StatusBarUpdater;
import org.teiid.query.ui.builder.util.ElementViewerFactory;
/**
* TransformationObjectEditorPage is the class for editing Transformation Objects.
*
* @since 8.0
*/
public class TransformationObjectEditorPage
implements ModelObjectEditorPage, UiConstants, ITransformationDiagramActionConstants, IAdaptable, EventObjectListener,
INotifyChangedListener, SelectionListener, IUndoManager {
private static final String SQL_UPDATE_TXN_DESCRIPTION = getString("sqlUpdateTxnDescription"); //$NON-NLS-1$
private static final String BLANK = ""; //$NON-NLS-1$
private static final String SPACE = " "; //$NON-NLS-1$
private static final String COMMA_SPACE = ", "; //$NON-NLS-1$
private static final String RIGHT_PARENTH = ")"; //$NON-NLS-1$
private static final String NAME = getString("name"); //$NON-NLS-1$
private static final String TITLE_TEXT = "title.text"; //$NON-NLS-1$
private static final String TITLE_TOOLTIP = "title.toolTip"; //$NON-NLS-1$
private static final String SELECT_TAB_TEXT = getString("selectTab.text"); //$NON-NLS-1$
private static final String SELECT_TAB_TOOLTIP = getString("selectTab.toolTip"); //$NON-NLS-1$
private static final String UPDATE_TAB_TEXT = getString("updateTab.text"); //$NON-NLS-1$
private static final String UPDATE_TAB_TOOLTIP = getString("updateTab.toolTip"); //$NON-NLS-1$
private static final String SELECT_SQL_MSG = getString("selectSqlMsg.text"); //$NON-NLS-1$
private static final String INSERT_SQL_MSG = getString("insertSqlMsg.text"); //$NON-NLS-1$
private static final String UPDATE_SQL_MSG = getString("updateSqlMsg.text"); //$NON-NLS-1$
private static final String DELETE_SQL_MSG = getString("deleteSqlMsg.text"); //$NON-NLS-1$
private static final String IS_VALID_MSG = getString("isValidMsg.text"); //$NON-NLS-1$
private static final String INSERT_TAB_TEXT = getString("insertTab.text"); //$NON-NLS-1$
private static final String INSERT_TAB_TOOLTIP = getString("insertTab.toolTip"); //$NON-NLS-1$
private static final String DELETE_TAB_TEXT = getString("deleteTab.text"); //$NON-NLS-1$
private static final String DELETE_TAB_TOOLTIP = getString("deleteTab.toolTip"); //$NON-NLS-1$
private static final String SAVE_PENDING_TITLE = getString("savePendingChanges.title"); //$NON-NLS-1$
private static final String SAVE_PENDING_MSG = getString("savePendingChanges.msg"); //$NON-NLS-1$
private static final String SQL_CHANGES_PENDING_MSG = getString("sqlChangesPending.msg"); //$NON-NLS-1$
private static final String USE_DEFAULT_CHECKBOX_TEXT = getString("useDefaultCheckbox.text"); //$NON-NLS-1$
private static final String USE_DEFAULT_CHECKBOX_TOOLTIP = getString("useDefaultCheckbox.toolTip"); //$NON-NLS-1$
// strings for warning message
private static final String UPDATE_SQL_TYPE = getString("update.sqlType"); //$NON-NLS-1$
private static final String INSERT_SQL_TYPE = getString("insert.sqlType"); //$NON-NLS-1$
private static final String DELETE_SQL_TYPE = getString("delete.sqlType"); //$NON-NLS-1$
private static final String LOST_SQL_TITLE = getString("lostSql.title"); //$NON-NLS-1$
private static final String IS_VALID_AND_RECONCILABLE = getString("isValidAndReconcilableMsg"); //$NON-NLS-1$
private static final String IS_VALID_NOT_RECONCILABLE = getString("isValidNotReconcilableMsg"); //$NON-NLS-1$
private static final String QUERY_SIZE_MISMATCH_MSG = getString("querySizeMismatchMsg"); //$NON-NLS-1$
private static final String QUERY_SIZE_MISMATCH_NO_PROJECTED_SYMBOLS_MSG = getString("querySizeMismatchNoProjectedSymbolsMsg"); //$NON-NLS-1$
private static final String QUERY_NAME_MISMATCH_MSG = getString("queryNameMismatchMsg"); //$NON-NLS-1$
private static final String QUERY_TYPE_MISMATCH_MSG = getString("queryTypeMismatchMsg"); //$NON-NLS-1$
private static final String COMMAND_HAS_REFERENCES_MSG = getString("commandHasReferencesMsg"); //$NON-NLS-1$
private static final String NUMBER_REFERENCES_MSG = getString("numberReferencesMsg"); //$NON-NLS-1$
private static final String TRANSFORMATION_AUTO_ADJUSTED_MSG = getString("transformationAutoAdjusted"); //$NON-NLS-1$
static final String SUPPORTS_UPDATE_TEXT = getString("supportsUpdatesCheckBox.text"); //$NON-NLS-1$
private static final String CURSOR_AT_TEXT = getString("cursorAt.text"); //$NON-NLS-1$
private static final String PREVIEW_DATA_TOOLTIP = getString("previewDataTooltip"); //$NON-NLS-1$
public static final String TRANSACTIONS = "modelerTransactions"; //$NON-NLS-1$
public static final String THIS_CLASS = "TransformationObjectEditorPage"; //$NON-NLS-1$
private static final Image ERROR_IMAGE = UiPlugin.getDefault().getImage(UiConstants.Images.ERROR);
private static final Image WARNING_IMAGE = UiPlugin.getDefault().getImage(UiConstants.Images.WARNING);
private static final Image NOT_ALLOWED_IMAGE = UiPlugin.getDefault().getImage(UiConstants.Images.NOT_ALLOWED);
private static String getString( String key ) {
return UiConstants.Util.getString(THIS_CLASS + '.' + key);
}
private static String getString( String key,
String parameter ) {
return UiConstants.Util.getString(THIS_CLASS + '.' + key, parameter);
}
SqlEditorPanelWrapper sqlEditorPanelWrapper;
private QueryValidator validator;
private Composite parent;
private CTabFolder tabFolderWithUpdateTabs;
Composite objEditorParent;
private StackLayout objEditorParentLayout;
private Composite sqlSelectPanelForUpdate;
private Composite sqlSelectPanelForNoUpdate;
private Composite sqlOuterUpdatePanel;
private Composite sqlOuterInsertPanel;
private Composite sqlOuterDeletePanel;
private Object currentItem;
private CTabItem selectTabForUpdate;
CTabItem insertTab;
CTabItem updateTab;
CTabItem deleteTab;
private SqlEditorPanel currentSqlEditor;
private SqlEditorPanel sqlSelectEditorForUpdate;
private SqlEditorPanel sqlSelectEditorForNoUpdate;
private SqlEditorPanel sqlInsertEditor;
private SqlEditorPanel sqlUpdateEditor;
private SqlEditorPanel sqlDeleteEditor;
private SqlPanelDropTargetListener seSelectUpdateDropListener;
private SqlPanelDropTargetListener seSelectNoUpdateDropListener;
Button chkUseDefaultForInsert;
Label useDefaultForInsertLabel;
Button chkUseDefaultForUpdate;
Label useDefaultForUpdateLabel;
Button chkUseDefaultForDelete;
Label useDefaultForDeleteLabel;
private boolean bUseDefaultForInsert;
private boolean bUseDefaultForUpdate;
private boolean bUseDefaultForDelete;
private boolean targetAllowsUpdates = false;
private SqlTransformationMappingRoot currentMappingRoot;
private boolean isDirty = false;
private ModelObjectEditorPage override;
private ModelEditor parentModelEditor;
/** List of listeners registered for this panels events */
private List eventListeners;
private EventListenerList propListeners = new EventListenerList();
// Actions and other Toolbar controls
CheckBoxContribution chkSupportsUpdatesContribution;
CLabel cursorPositionLabel;
private LabelContribution lblCursorPositionContribution;
private ToggleOptimizer toggleOptimizerAction;
private SortableSelectionAction previewDataAction;
private Action searchTransformationsAction;
private EditTransformationAction editTransformationAction;
private boolean noUpdatesAllowed = false;
private boolean currentReadonlyState = false;
private boolean deactivated = true;
// SelectionListener for CheckBox controls
private SelectionListener checkBoxListener = new SelectionListener() {
@Override
public void widgetDefaultSelected( SelectionEvent e ) {
handleCheckBoxStateChanged(e);
}
@Override
public void widgetSelected( SelectionEvent e ) {
handleCheckBoxStateChanged(e);
}
};
/**
* @see org.teiid.designer.ui.editors.ModelObjectEditorPage#canClose()
* @since 5.0.1
*/
@Override
public boolean canClose() {
return true;
}
/**
* @see org.teiid.designer.ui.editors.ModelObjectEditorPage#createControl(org.eclipse.swt.widgets.Composite)
*/
@Override
public void createControl( Composite parent ) {
this.parent = parent;
objEditorParent = new Composite(parent, SWT.NONE);
objEditorParentLayout = new StackLayout();
objEditorParent.setLayout(objEditorParentLayout);
GridData gridData0 = new GridData(GridData.FILL_BOTH);
objEditorParent.setLayoutData(gridData0);
createCTabFolderWithUpdateTabs(objEditorParent);
createSqlControl(objEditorParent);
GridData gridData2 = new GridData(GridData.FILL_BOTH);
if (tabFolderWithUpdateTabs != null) {
tabFolderWithUpdateTabs.setLayoutData(gridData2);
}
objEditorParentLayout.topControl = sqlSelectPanelForNoUpdate;
// establish listening
registerListeners();
}
private Object getTopControl() {
return objEditorParentLayout.topControl;
}
@Override
public ModelEditor getParentModelEditor() {
return this.parentModelEditor;
}
private void createSqlControl( Composite parent ) {
createSelectControlForNoUpdate(parent);
setCurrentSqlEditor(sqlSelectEditorForNoUpdate);
}
private void createCTabFolderWithUpdateTabs( Composite parent ) {
if (!allowsMultipleTabs()) {
return;
}
tabFolderWithUpdateTabs = new CTabFolder(parent, SWT.BOTTOM);
// --------------------------------------------
// Create Tabs
// --------------------------------------------
createSelectTabForUpdate(tabFolderWithUpdateTabs);
createUpdateTab(tabFolderWithUpdateTabs);
createInsertTab(tabFolderWithUpdateTabs);
createDeleteTab(tabFolderWithUpdateTabs);
tabFolderWithUpdateTabs.setSelection(selectTabForUpdate);
tabFolderWithUpdateTabs.setLayoutData(createTextViewGridData());
addCheckBoxListeners(selectTabForUpdate);
}
/**
* Create the Select Tab
*
* @param tabFolder the CTabFolder parent
*/
private void createSelectTabForUpdate( CTabFolder tabFolder ) {
// Set overall grid layout
GridLayout glOuterGridLayout = new GridLayout();
// build the SELECT tab
sqlSelectPanelForUpdate = new Composite(tabFolder, SWT.NONE);
sqlSelectPanelForUpdate.setLayout(glOuterGridLayout);
sqlSelectPanelForUpdate.setLayoutData(createTextViewGridData());
sqlSelectEditorForUpdate = createEditorPanel(sqlSelectPanelForUpdate, QueryValidator.SELECT_TRNS);
sqlSelectEditorForUpdate.setPanelType(UiConstants.SQLPanels.UPDATE_SELECT);
sqlSelectEditorForUpdate.setEditable(true);
selectTabForUpdate = new CTabItem(tabFolder, SWT.NONE);
selectTabForUpdate.setControl(sqlSelectPanelForUpdate);
selectTabForUpdate.setText(SELECT_TAB_TEXT);
selectTabForUpdate.setToolTipText(SELECT_TAB_TOOLTIP);
seSelectUpdateDropListener = createDropTargetListener(sqlSelectEditorForUpdate, currentMappingRoot);
if (seSelectUpdateDropListener != null) {
DropTarget dropTarget = new DropTarget(sqlSelectEditorForUpdate.getTextViewer().getTextWidget(), DND.DROP_COPY
| DND.DROP_MOVE);
dropTarget.setTransfer(seSelectUpdateDropListener.getTransfers());
dropTarget.addDropListener(seSelectUpdateDropListener);
}
// remove the undo caused by setting the text the first time
resetUndoManager(sqlSelectEditorForUpdate);
}
/**
* Create the Select control
*
* @param parent the parent
*/
private void createSelectControlForNoUpdate( Composite parent ) {
// Set overall grid layout
GridLayout glOuterGridLayout = new GridLayout();
// build the SELECT tab
sqlSelectPanelForNoUpdate = new Composite(parent, SWT.NONE);
sqlSelectPanelForNoUpdate.setLayout(glOuterGridLayout);
sqlSelectPanelForNoUpdate.setLayoutData(createTextViewGridData());
sqlSelectEditorForNoUpdate = createSelectEditorForNoUpdate(this.sqlSelectPanelForNoUpdate);
sqlSelectEditorForNoUpdate.setPanelType(UiConstants.SQLPanels.SELECT);
sqlSelectEditorForNoUpdate.setEditable(true);
seSelectNoUpdateDropListener = createDropTargetListener(sqlSelectEditorForNoUpdate, currentMappingRoot);
if (seSelectNoUpdateDropListener != null) {
DropTarget dropTarget = new DropTarget(sqlSelectEditorForNoUpdate.getTextViewer().getTextWidget(), DND.DROP_COPY
| DND.DROP_MOVE);
dropTarget.setTransfer(seSelectNoUpdateDropListener.getTransfers());
dropTarget.addDropListener(seSelectNoUpdateDropListener);
}
// remove the undo caused by setting the text the first time
resetUndoManager(sqlSelectEditorForNoUpdate);
}
protected SqlEditorPanel createSelectEditorForNoUpdate( Composite parent ) {
return createEditorPanel(parent, QueryValidator.SELECT_TRNS);
}
/**
* Create the Update Tab
*
* @param tabFolder the CTabFolder parent
*/
private void createUpdateTab( CTabFolder tabFolder ) {
GridLayout glEditorGridLayout = new GridLayout();
glEditorGridLayout.numColumns = 2;
// create a composite to hold the controls and the textviewer
sqlOuterUpdatePanel = new Composite(tabFolder, SWT.NONE);
sqlOuterUpdatePanel.setLayout(glEditorGridLayout);
sqlOuterUpdatePanel.setLayoutData(createTextViewGridData());
// create/add the controls
chkUseDefaultForUpdate = WidgetFactory.createCheckBox(sqlOuterUpdatePanel, USE_DEFAULT_CHECKBOX_TEXT, true);
chkUseDefaultForUpdate.setToolTipText(USE_DEFAULT_CHECKBOX_TOOLTIP);
useDefaultForUpdateLabel = WidgetFactory.createLabel(sqlOuterUpdatePanel);
useDefaultForUpdateLabel.setText(Messages.DefaultUpdateMessageOK);
sqlUpdateEditor = createEditorPanel(sqlOuterUpdatePanel, QueryValidator.UPDATE_TRNS);
sqlUpdateEditor.setPanelType(UiConstants.SQLPanels.UPDATE_UPDATE);
GridData gd = new GridData(GridData.FILL_BOTH);
gd.horizontalSpan = 2;
sqlUpdateEditor.setLayoutData(gd);
updateTab = new CTabItem(tabFolder, SWT.NONE);
updateTab.setControl(sqlOuterUpdatePanel);
if (TransformationHelper.isUpdateAllowed(currentMappingRoot)) {
updateTab.getControl().setEnabled(true);
// try this:
sqlUpdateEditor.setEditable(true);
sqlUpdateEditor.getTextViewer().getTextWidget().setEnabled(true);
new DropTarget(sqlUpdateEditor.getTextViewer().getTextWidget(), DND.DROP_NONE);
}
updateTab.setText(UPDATE_TAB_TEXT);
updateTab.setToolTipText(UPDATE_TAB_TOOLTIP);
// remove the undo caused by setting the text the first time
resetUndoManager(sqlUpdateEditor);
}
/**
* Create the Insert Tab
*
* @param tabFolder the CTabFolder parent
*/
private void createInsertTab( CTabFolder tabFolder ) {
GridLayout glEditorGridLayout = new GridLayout();
glEditorGridLayout.numColumns = 2;
// create a composite to hold the controls and the textviewer
sqlOuterInsertPanel = new Composite(tabFolder, SWT.NONE);
sqlOuterInsertPanel.setLayout(glEditorGridLayout);
sqlOuterInsertPanel.setLayoutData(createTextViewGridData());
// create/add the controls
chkUseDefaultForInsert = WidgetFactory.createCheckBox(sqlOuterInsertPanel, USE_DEFAULT_CHECKBOX_TEXT, true);
chkUseDefaultForInsert.setToolTipText(USE_DEFAULT_CHECKBOX_TOOLTIP);
useDefaultForInsertLabel = WidgetFactory.createLabel(sqlOuterInsertPanel);
useDefaultForInsertLabel.setText(Messages.DefaultUpdateMessageOK);
sqlInsertEditor = createEditorPanel(sqlOuterInsertPanel, QueryValidator.INSERT_TRNS);
sqlInsertEditor.setPanelType(UiConstants.SQLPanels.UPDATE_INSERT);
GridData gd = new GridData(GridData.FILL_BOTH);
gd.horizontalSpan = 2;
sqlInsertEditor.setLayoutData(gd);
insertTab = new CTabItem(tabFolder, SWT.NONE);
insertTab.setControl(sqlOuterInsertPanel);
if (TransformationHelper.isInsertAllowed(currentMappingRoot)) {
insertTab.getControl().setEnabled(true);
sqlInsertEditor.setEditable(true);
sqlInsertEditor.getTextViewer().getTextWidget().setEnabled(true);
new DropTarget(sqlInsertEditor.getTextViewer().getTextWidget(), DND.DROP_NONE);
}
insertTab.setText(INSERT_TAB_TEXT);
insertTab.setToolTipText(INSERT_TAB_TOOLTIP);
// remove the undo caused by setting the text the first time
resetUndoManager(sqlInsertEditor);
}
/**
* Create the Delete Tab
*
* @param tabFolder the CTabFolder parent
*/
private void createDeleteTab( CTabFolder tabFolder ) {
GridLayout glEditorGridLayout = new GridLayout();
glEditorGridLayout.numColumns = 2;
// create a composite to hold the controls and the textviewer
sqlOuterDeletePanel = new Composite(tabFolder, SWT.NONE);
sqlOuterDeletePanel.setLayout(glEditorGridLayout);
sqlOuterDeletePanel.setLayoutData(createTextViewGridData());
// create/add the controls
chkUseDefaultForDelete = WidgetFactory.createCheckBox(sqlOuterDeletePanel, USE_DEFAULT_CHECKBOX_TEXT, true);
chkUseDefaultForDelete.setToolTipText(USE_DEFAULT_CHECKBOX_TOOLTIP);
useDefaultForDeleteLabel = WidgetFactory.createLabel(sqlOuterDeletePanel);
useDefaultForDeleteLabel.setText(Messages.DefaultUpdateMessageOK);
sqlDeleteEditor = createEditorPanel(sqlOuterDeletePanel, QueryValidator.DELETE_TRNS);
sqlDeleteEditor.setPanelType(UiConstants.SQLPanels.UPDATE_DELETE);
GridData gd = new GridData(GridData.FILL_BOTH);
gd.horizontalSpan = 2;
sqlDeleteEditor.setLayoutData(gd);
deleteTab = new CTabItem(tabFolder, SWT.NONE);
deleteTab.setControl(sqlOuterDeletePanel);
if (TransformationHelper.isDeleteAllowed(currentMappingRoot)) {
deleteTab.getControl().setEnabled(true);
sqlDeleteEditor.getTextViewer().setEditable(false);
sqlDeleteEditor.setEditable(false);
sqlDeleteEditor.getTextViewer().getTextWidget().setEnabled(false);
new DropTarget(sqlDeleteEditor.getTextViewer().getTextWidget(), DND.DROP_NONE);
}
getSqlEditorForItem(deleteTab).setEditable(false);
deleteTab.setText(DELETE_TAB_TEXT);
deleteTab.setToolTipText(DELETE_TAB_TOOLTIP);
// remove the undo caused by setting the text the first time
resetUndoManager(sqlDeleteEditor);
}
/**
* Create a SqlEditorPanel in the supplied Composite.
*
* @param cmpSqlPanel the composite that it is contained in
* @return the SqlEditorPanel
*/
protected SqlEditorPanel createEditorPanel( Composite cmpSqlPanel,
int queryType ) {
List aList = SqlEditorPanel.getDefaultActionList();
customizeActionList(aList);
SqlEditorPanel sepNewSqlEditor = new SqlEditorPanel(cmpSqlPanel, validator, queryType, aList);
sepNewSqlEditor.setLayoutData(createTextViewGridData());
// add listening
sepNewSqlEditor.addEventListener(this);
return sepNewSqlEditor;
}
/**
* Create GridData for Text Panel
*
* @return GridData
*/
private GridData createTextViewGridData() {
GridData gridData = new GridData(GridData.FILL_BOTH);
return gridData;
}
/**
* Register this class to listen for Metadata Change Notifications and Tab Selections
*/
private void registerListeners() {
deactivated = false;
ModelUtilities.addNotifyChangedListener(this);
SqlMappingRootCache.addEventListener(this);
if (tabFolderWithUpdateTabs != null) {
tabFolderWithUpdateTabs.addSelectionListener(this);
}
}
/**
* Remove the checkBox listener from the checkBox controls
*/
private void removeCheckBoxListeners( Object item ) {
if (item == insertTab) {
if (!chkUseDefaultForInsert.isDisposed()) {
chkUseDefaultForInsert.removeSelectionListener(checkBoxListener);
}
} else if (item == updateTab) {
if (!chkUseDefaultForUpdate.isDisposed()) {
chkUseDefaultForUpdate.removeSelectionListener(checkBoxListener);
}
} else if (item == deleteTab) {
if (!chkUseDefaultForDelete.isDisposed()) {
chkUseDefaultForDelete.removeSelectionListener(checkBoxListener);
}
}
}
/**
* Add the checkBox listener to all checkBox controls
*/
private void addCheckBoxListeners( Object item ) {
if (item == insertTab) {
if (!chkUseDefaultForInsert.isDisposed()) {
chkUseDefaultForInsert.addSelectionListener(checkBoxListener);
}
} else if (item == updateTab) {
if (!chkUseDefaultForUpdate.isDisposed()) {
chkUseDefaultForUpdate.addSelectionListener(checkBoxListener);
}
} else if (item == deleteTab) {
if (!chkUseDefaultForDelete.isDisposed()) {
chkUseDefaultForDelete.addSelectionListener(checkBoxListener);
}
}
}
protected void showMessageArea( boolean doShow ) {
getSqlEditorPanelWrapper().showMessageArea(doShow);
}
/**
* Get the SqlEditorPanel wrapper
*
* @return the SqlEditorPanelWrapper
*/
private SqlEditorPanelWrapper getSqlEditorPanelWrapper() {
// create the editor panel wrapper:
if (sqlEditorPanelWrapper == null) {
List aList = SqlEditorPanel.getDefaultActionList();
customizeActionList(aList);
sqlEditorPanelWrapper = new SqlEditorPanelWrapper(parent, null, aList);
sqlEditorPanelWrapper.setCurrentSqlEditorPanel(getCurrentSqlEditor());
}
Display display = this.getControl().getDisplay();
if (display != null) {
display.asyncExec(new Runnable() {
@Override
public void run() {
sqlEditorPanelWrapper.refreshFontManager();
}
});
}
return sqlEditorPanelWrapper;
}
/**
* Set the current SqlEditorPanel
*
* @return the current SqlEditorPanel
*/
private void setCurrentSqlEditor( SqlEditorPanel sep ) {
if (this.currentSqlEditor != sep) {
this.currentSqlEditor = sep;
getSqlEditorPanelWrapper().setCurrentSqlEditorPanel(currentSqlEditor);
}
}
/**
* Get the current SqlEditorPanel
*
* @return the current SqlEditorPanel
*/
public SqlEditorPanel getCurrentSqlEditor() {
return this.currentSqlEditor;
}
/**
* Determine if currently selected tab is the SELECT tab
*
* @return 'true' if the selected tab is SELECT, 'false' if not.
*/
public boolean isCurrentTabSelect() {
// update the current editor to match the tab selected
Object selectedItem = getSelectedItem();
return (selectedItem == this.sqlSelectPanelForNoUpdate || selectedItem == this.selectTabForUpdate);
}
/**
* Determine if current editor has pending changes
*
* @return 'true' if has pending changes, 'false' if not.
*/
public boolean hasPendingChanges() {
boolean result = false;
SqlEditorPanel currentEditor = getCurrentSqlEditor();
if (currentEditor != null && currentEditor.hasPendingChanges()) {
result = true;
}
return result;
}
public StyledText getTextWidget() {
return currentSqlEditor.getTextViewer().getTextWidget();
}
/**
* @see org.teiid.designer.ui.editors.ModelObjectEditorPage#getControl()
*/
@Override
public Control getControl() {
return this.objEditorParent;
}
/**
* @see org.teiid.designer.ui.editors.ModelObjectEditorPage#getTitle()
*/
@Override
public String getTitle() {
return getString(TITLE_TEXT, getTransformationName());
}
/**
* @see org.teiid.designer.ui.editors.ModelObjectEditorPage#getTitleToolTip()
*/
@Override
public String getTitleToolTip() {
return getString(TITLE_TOOLTIP, getTransformationName());
}
protected String getTransformationName() {
return NAME;
}
/**
* @see org.teiid.designer.ui.editors.ModelObjectEditorPage#getTitleImage()
*/
@Override
public Image getTitleImage() {
return null;
}
/**
* @see org.teiid.designer.ui.editors.ModelObjectEditorPage#canEdit(java.lang.Object, org.eclipse.ui.IEditorPart)
* @since 5.0.1
*/
@Override
public boolean canEdit( Object modelObject,
IEditorPart editor ) {
if (this.override != null && this.override.canEdit(modelObject, editor)) {
return false;
}
if (modelObject != null) {
if (modelObject instanceof InputSet || !(editor instanceof DiagramEditor)) {
return false;
}
if (TransformationHelper.isOperation(modelObject)) {
return false;
}
if (TransformationHelper.isSqlTransformationMappingRoot(modelObject)) {
EObject target = ((SqlTransformationMappingRoot)modelObject).getTarget();
if (TransformationHelper.isOperation(target)) {
return false;
}
return true;
} else if ((TransformationHelper.isVirtualSqlTable(modelObject) || TransformationHelper.isSqlVirtualProcedure(modelObject))) {
// One last check here, because XMLDocuments are SqlTableAspect eObjects. Must be a valid t-target
if (TransformationHelper.isValidSqlTransformationTarget(modelObject)
&& TransformationHelper.getMappingRoot((EObject)modelObject, false, true) != null) return true;
}
}
return false;
}
/**
* @see org.teiid.designer.ui.editors.ModelObjectEditorPage#edit(org.eclipse.emf.ecore.EObject)
*/
@Override
public void edit( Object rootOrVirtualSqlTable ) {
Object obj = getEditableObject(rootOrVirtualSqlTable);
if (obj instanceof SqlTransformationMappingRoot) {
SqlTransformationMappingRoot workingMappingRoot = (SqlTransformationMappingRoot)obj;
// Wire listeners
if( deactivated ) {
registerListeners();
}
currentMappingRoot = workingMappingRoot;
this.validator = new TransformationValidator(currentMappingRoot, false);
// establish builder tree
/*
* jh note: BuilderTreeProvider must always be created in this method,
* and NEVER maintained in an instance variable between uses.
* This is because its constructor modifies the state of the
* static class ElementViewerFactory.
*/
new BuilderTreeProvider();
ElementViewerFactory.setCriteriaStrategy(new QueryCriteriaStrategy());
// Inits the useDefault states
setUseDefaultStates(currentMappingRoot);
// Refresh Tab selection
refreshTabs();
// Set the Editor Panel contents based on selectedTab
setEditorContent(this.currentItem, true, this, true, false);
objEditorParent.layout();
setEditorFocus(this.currentSqlEditor);
} else if (obj == null) {
// -------------------------------------------------------------------------------------------------------------------
// DEFECT 23230
// If NULL is the input, we assume this is a "clear" editor call.
// -------------------------------------------------------------------------------------------------------------------
// Need to clear the SQL
this.currentMappingRoot = null;
this.validator = null;
clearSqlEditors();
}
// we don't want the user to be able to undo the first time the document text was set
resetUndoManager(this.getCurrentSqlEditor());
// All actions to update state based on setting of contents
updateActions();
}
/**
* Refresh tabs, ensuring that selected tab is compatible with target 'allowsUpdate' property
*/
void refreshTabs() {
if (!isEditorValid()) return;
// Get target supportsUpdates state
this.targetAllowsUpdates = getTargetAllowsUpdates();
// target allowsUpdates
if (!noUpdatesAllowed && targetAllowsUpdates) {
Object selectedItem = getSelectedItem();
// Use Update tab folder
objEditorParentLayout.topControl = tabFolderWithUpdateTabs;
// update the current editor to match the tab selected
if (selectTabForUpdate != null && selectedItem == selectTabForUpdate && sqlSelectEditorForUpdate != null) {
setCurrentSqlEditor(sqlSelectEditorForUpdate);
tabFolderWithUpdateTabs.setSelection(selectTabForUpdate);
} else if (insertTab != null && selectedItem == insertTab && sqlInsertEditor != null) {
setCurrentSqlEditor(sqlInsertEditor);
tabFolderWithUpdateTabs.setSelection(insertTab);
} else if (updateTab != null && selectedItem == updateTab && sqlUpdateEditor != null) {
setCurrentSqlEditor(sqlUpdateEditor);
tabFolderWithUpdateTabs.setSelection(updateTab);
} else if (deleteTab != null && selectedItem == deleteTab && sqlDeleteEditor != null) {
setCurrentSqlEditor(sqlDeleteEditor);
tabFolderWithUpdateTabs.setSelection(deleteTab);
} else {
setCurrentSqlEditor(sqlSelectEditorForUpdate);
tabFolderWithUpdateTabs.setSelection(selectTabForUpdate);
}
// Update current transform for drop listeners
if (seSelectUpdateDropListener != null && sqlSelectEditorForUpdate != null) {
seSelectUpdateDropListener.setTransformation(currentMappingRoot);
}
// target doesnt allow updates - selectTab, regardless of current selection
} else {
objEditorParentLayout.topControl = sqlSelectPanelForNoUpdate;
setCurrentSqlEditor(sqlSelectEditorForNoUpdate);
if (seSelectNoUpdateDropListener != null) {
seSelectNoUpdateDropListener.setTransformation(currentMappingRoot);
}
}
// Update currentItem variable
this.currentItem = getSelectedItem();
}
private void setEditorFocus( final SqlEditorPanel editor ) {
Display.getDefault().asyncExec(new Runnable() {
@Override
public void run() {
if (editor != null) {
TextViewer tv = editor.getTextViewer();
if (tv != null) {
StyledText st = tv.getTextWidget();
if (st != null && !st.isDisposed()) {
boolean gotFocus = st.setFocus();
if (gotFocus) {
editor.setCaretOffset(0);
handleCursorPositionChanged();
}
}
}
}
}
});
}
/**
* Method provides quick way to refresh the current editor content and insure that sql strings are all up to date with model
*
* @since 4.2
*/
public void refreshEditorContent() {
setEditorContent(getSelectedItem(), false, this, true, false);
}
private void resetUndoManager( SqlEditorPanel editor ) {
editor.resetUndoRedoHistory();
}
private void resetAllUndoManagers() {
if (this.sqlSelectEditorForUpdate != null) resetUndoManager(this.sqlSelectEditorForUpdate);
if (this.sqlSelectEditorForNoUpdate != null) resetUndoManager(this.sqlSelectEditorForNoUpdate);
if (this.sqlInsertEditor != null) resetUndoManager(this.sqlInsertEditor);
if (this.sqlUpdateEditor != null) resetUndoManager(this.sqlUpdateEditor);
if (this.sqlDeleteEditor != null) resetUndoManager(this.sqlDeleteEditor);
}
/**
* Set the Editor Panel based on the selectedTab
*
* @param int the selected tab.
*/
public void setEditorContent( Object item,
boolean reconcileTarget,
Object txnSource,
boolean overwriteDirty,
boolean sourceIsEvent ) {
int cmdType = getCommandTypeForItem(item);
boolean showMessage = false;
if (isResourceValid() && getControl() != null && !getControl().isDisposed()) {
// Get the current SQL for the Selected Tab and set on QueryEditorPanel
String sqlString = TransformationHelper.getSqlString(currentMappingRoot, cmdType);
// Get valid status for the transformation
boolean isValid = TransformationHelper.isValid(currentMappingRoot, cmdType);
//System.out.println(" TOEP.setEditorContent() QUERY VALID = " + isValid);
if( sourceIsEvent ) {
showMessage = TransformationHelper.setSqlString(currentMappingRoot, sqlString, cmdType, false, txnSource);
}
if( !showMessage && !isValid ) {
showMessage = true;
}
// If the command is a SetQuery (UNION), update the reconciled status on the editorPanel
// Go ahead and check the command regardless if it's resolved or not.
ICommand newCommand = TransformationHelper.getCommand(currentMappingRoot, cmdType);
if (newCommand instanceof ISetQuery) {
updateEditorSetQueryStates((ISetQuery)newCommand);
}
// Update the external groups for SqlEditor Builder tree
Collection externalGroups = getExternalBuilderGroups(currentMappingRoot);
// Set external Symbols on the SqlEditorPanel
currentSqlEditor.setExternalBuilderGroups(externalGroups);
SqlEditorPanel editor = getSqlEditorForItem(item);
// Create TransformationValidator and set validator on all editors
resetValidators();
boolean isSelectCached = SqlMappingRootCache.containsStatus(currentMappingRoot, QueryValidator.SELECT_TRNS);
SqlTransformationResult selectStatus = SqlMappingRootCache.getSqlTransformationStatus(currentMappingRoot,
QueryValidator.SELECT_TRNS,
true,
null);
// Create an existing status to pass to the SQL Editor Panel to prevent re-validation of SQL if already validated
SqlTransformationResult existingStatus = selectStatus;
// If the tab is NOT SELECT TAB, then get the status of that command type so we can pass it to the SQL Editor Panel
if (cmdType != QueryValidator.SELECT_TRNS) {
existingStatus = SqlMappingRootCache.getSqlTransformationStatus(currentMappingRoot, cmdType, true, null);
}
boolean statusExists = selectStatus != null;
if (overwriteDirty || !editor.hasPendingChanges()) {
// we are authorized to overwrite, or there are no pending changes:
editor.setText(sqlString, this, !statusExists, existingStatus);
// don't want this text to be undoable
// resetUndoManager(editor);
// Set Message and Message Visibility on EditorPanel
setEditorMessage(item);
} // endif
// Get Allows properties and setCheckBoxes accordingly
setCheckBoxStates(currentMappingRoot, item);
// Set editable state based on allows checkbox for this tab
setEditableStatus(item);
// Get the Target for this MappingRoot
EObject targetGroup = TransformationHelper.getTransformationTarget(currentMappingRoot);
boolean allowsUpdates = TransformationHelper.tableSupportsUpdate(targetGroup);
// Reconcile targetAttributes first
// Now we need to check read-only status here..
if (!ModelObjectUtilities.isReadOnly(currentMappingRoot) && !(txnSource instanceof ReconcileTransformationAction)) {
if (reconcileTarget) {
// defect 16739 - Alert user if we've automatically changed something:
int changeCode = TransformationMappingHelper.reconcileTargetAttributes(currentMappingRoot, this).getCode();
if (changeCode == TransformationMappingHelper.TRANSFORMATION_CHANGED) {
// a change occurred:
SqlEditorPanelWrapper sepw = getSqlEditorPanelWrapper();
// make sure there is no other message of note:
if (!sepw.isMessageAreaVisible()) {
// not currently visible, show the new message:
sepw.setMessage(TRANSFORMATION_AUTO_ADJUSTED_MSG);
sepw.showMessageArea(true);
} // endif
} // endif
}
if (allowsUpdates) {
if (!sourceIsEvent || !isSelectCached) {
// Get the current SQL for the Selected Tab and set on QueryEditorPanel
String sString = TransformationHelper.getSqlString(currentMappingRoot, QueryValidator.INSERT_TRNS);
boolean change_1 = TransformationHelper.setSqlString(currentMappingRoot,
sString,
QueryValidator.INSERT_TRNS,
false,
txnSource);
sString = TransformationHelper.getSqlString(currentMappingRoot, QueryValidator.UPDATE_TRNS);
boolean change_2 = TransformationHelper.setSqlString(currentMappingRoot,
sString,
QueryValidator.UPDATE_TRNS,
false,
txnSource);
sString = TransformationHelper.getSqlString(currentMappingRoot, QueryValidator.DELETE_TRNS);
boolean change_3 = TransformationHelper.setSqlString(currentMappingRoot,
sString,
QueryValidator.DELETE_TRNS,
false,
txnSource);
if (change_1 || change_2 || change_3) showMessage = true;
} else {
if (!SqlMappingRootCache.containsStatus(currentMappingRoot, QueryValidator.INSERT_TRNS)) {
String sString = TransformationHelper.getSqlString(currentMappingRoot, QueryValidator.INSERT_TRNS);
showMessage = TransformationHelper.setSqlString(currentMappingRoot,
sString,
QueryValidator.INSERT_TRNS,
false,
txnSource);
}
if (!SqlMappingRootCache.containsStatus(currentMappingRoot, QueryValidator.UPDATE_TRNS)) {
String sString = TransformationHelper.getSqlString(currentMappingRoot, QueryValidator.UPDATE_TRNS);
boolean show = TransformationHelper.setSqlString(currentMappingRoot,
sString,
QueryValidator.UPDATE_TRNS,
false,
txnSource);
if (!showMessage && show) showMessage = true;
}
if (!SqlMappingRootCache.containsStatus(currentMappingRoot, QueryValidator.DELETE_TRNS)) {
String sString = TransformationHelper.getSqlString(currentMappingRoot, QueryValidator.DELETE_TRNS);
boolean show = TransformationHelper.setSqlString(currentMappingRoot,
sString,
QueryValidator.DELETE_TRNS,
false,
txnSource);
if (!showMessage && show) showMessage = true;
}
}
if (showMessage) {
// a change occurred:
SqlEditorPanelWrapper sepw = getSqlEditorPanelWrapper();
// make sure there is no other message of note:
if (!sepw.isMessageAreaVisible()) {
// not currently visible, show the new message:
sepw.setMessage(TRANSFORMATION_AUTO_ADJUSTED_MSG);
sepw.showMessageArea(true);
}
}
}
}
// Notify Listeners of Status
if (isValid) {
notifyEventListeners(new QueryEditorStatusEvent(this, QueryEditorStatusEvent.QUERY_VALIDATABLE));
} else if (TransformationHelper.isResolvable(currentMappingRoot, cmdType)) {
notifyEventListeners(new QueryEditorStatusEvent(this, QueryEditorStatusEvent.QUERY_RESOLVABLE));
} else if (TransformationHelper.isParsable(currentMappingRoot, cmdType)) {
notifyEventListeners(new QueryEditorStatusEvent(this, QueryEditorStatusEvent.QUERY_PARSABLE));
} else {
notifyEventListeners(new QueryEditorStatusEvent(this, QueryEditorStatusEvent.QUERY_NOT_PARSABLE));
}
setDirty(editor.hasPendingChanges());
if( allowsUpdates ) {
final SqlTransformationResult currentSelectStatus = SqlMappingRootCache.getSqlTransformationStatus(currentMappingRoot,QueryValidator.SELECT_TRNS, true, null);
if( selectStatus != null ) {
UiUtil.runInSwtThread(new Runnable() {
@Override
public void run() {
updateUpdateTabs(currentSelectStatus);
}
}, true);
}
}
updateReadOnlyState();
}
}
private void updateUpdateTabs(SqlTransformationResult validationResult) {
// ASSUME SUPPORTS UPDATE == TRUE
if( validationResult == null ) return; // DO NOTHING
// -------------
// WORK ON EACH TAB TYPE
// -------------
// -----------------------------
// SELECT TAB
// -----------------------------
boolean selectSqlOk = validationResult.isOkToUpdate(QueryValidator.SELECT_TRNS);
if( selectSqlOk ) { // NO ERRORS WITH TYPE = QueryValidator.ALL_UPDATE_SQL_PROBLEM
this.selectTabForUpdate.setImage(null);
this.selectTabForUpdate.setToolTipText(null);
} else { // ERRORS FOUND WITH TYPE = QueryValidator.ALL_UPDATE_SQL_PROBLEM
this.selectTabForUpdate.setImage(UiPlugin.getDefault().getImage(UiConstants.Images.WARNING));
IStatus firstStatus = validationResult.getUpdateStatusList(QueryValidator.SELECT_TRNS).iterator().next();
this.selectTabForUpdate.setToolTipText(firstStatus.getMessage());
}
insertTab.setImage(null);
updateTab.setImage(null);
deleteTab.setImage(null);
// -----------------------------
// UPDATE TAB
// -----------------------------
// If USE DEFAULT is Checked, decorate with NOT_ALLOWED else check for specific UPDATE errors, then decorate with error or NONE
// and if error, set the message based on first Update Error.
// But if SELECT has ERRORS FOUND WITH TYPE = QueryValidator.ALL_UPDATE_SQL_PROBLEM then set message from the SELECT status if NO Update Errors.
String toolTipText = null;
Image displayImage = null;
String tabText = INSERT_TAB_TEXT;
if( isUseDefault(QueryValidator.INSERT_TRNS) ) {
tabText = INSERT_TAB_TEXT + " (default)"; //$NON-NLS-1$
// Now we check for "insert" default errors and warnings
IStatus displayStatus = null;
if( !validationResult.isOkToUpdate(QueryValidator.INSERT_TRNS) ) {
displayStatus = validationResult.getUpdateStatusList(QueryValidator.INSERT_TRNS).iterator().next();
} else if(!selectSqlOk) {
displayStatus = validationResult.getUpdateStatusList(QueryValidator.SELECT_TRNS).iterator().next();
}
if( displayStatus != null ) {
toolTipText = displayStatus.getMessage();
displayImage = NOT_ALLOWED_IMAGE;
useDefaultForInsertLabel.setText(Messages.DefaultUpdateMessageAmbigious);
} else {
useDefaultForInsertLabel.setText(Messages.DefaultUpdateMessageOK);
}
} else {
// Now we check for "insert" SQL errors and warnings
SqlTransformationResult insertResult = SqlMappingRootCache.getSqlTransformationStatus(currentMappingRoot, QueryValidator.INSERT_TRNS, true, null);
IStatus displayStatus = null;
if( insertResult != null && !insertResult.getStatusList().isEmpty() ) {
displayStatus = insertResult.getStatusList().iterator().next();
}
if( displayStatus != null ) {
displayImage = getSeverityImage(insertResult.getMaxSeverity());
toolTipText = displayStatus.getMessage();
}
}
this.insertTab.setImage(displayImage);
this.insertTab.setToolTipText(toolTipText);
this.insertTab.setText(tabText);
// -----------------------------
// INSERT TAB
// -----------------------------
displayImage = null;
toolTipText = null;
tabText = UPDATE_TAB_TEXT;
if( isUseDefault(QueryValidator.UPDATE_TRNS) ) {
tabText = UPDATE_TAB_TEXT + " (default)"; //$NON-NLS-1$
// Now we check for "insert" default errors and warnings
IStatus displayStatus = null;
if( !validationResult.isOkToUpdate(QueryValidator.UPDATE_TRNS) ) {
displayStatus = validationResult.getUpdateStatusList(QueryValidator.UPDATE_TRNS).iterator().next();
} else if(!selectSqlOk) {
displayStatus = validationResult.getUpdateStatusList(QueryValidator.SELECT_TRNS).iterator().next();
}
if( displayStatus != null ) {
toolTipText = displayStatus.getMessage();
displayImage = NOT_ALLOWED_IMAGE;
useDefaultForUpdateLabel.setText(Messages.DefaultUpdateMessageAmbigious);
} else {
useDefaultForUpdateLabel.setText(Messages.DefaultUpdateMessageOK);
}
} else {
// Now we check for "insert" SQL errors and warnings
SqlTransformationResult updateResult = SqlMappingRootCache.getSqlTransformationStatus(currentMappingRoot, QueryValidator.UPDATE_TRNS, true, null);
IStatus displayStatus = null;
if( updateResult != null && !updateResult.getStatusList().isEmpty()) {
displayStatus = updateResult.getStatusList().iterator().next();
}
if( displayStatus != null ) {
displayImage = getSeverityImage(updateResult.getMaxSeverity());
toolTipText = displayStatus.getMessage();
}
}
this.updateTab.setImage(displayImage);
this.updateTab.setToolTipText(toolTipText);
this.updateTab.setText(tabText);
// -----------------------------
// DELETE TAB
// -----------------------------
displayImage = null;
toolTipText = null;
tabText = DELETE_TAB_TEXT;
if( isUseDefault(QueryValidator.DELETE_TRNS) ) {
tabText = DELETE_TAB_TEXT + " (default)"; //$NON-NLS-1$
// Now we check for "insert" default errors and warnings
IStatus displayStatus = null;
if( !validationResult.isOkToUpdate(QueryValidator.DELETE_TRNS) ) {
displayStatus = validationResult.getUpdateStatusList(QueryValidator.DELETE_TRNS).iterator().next();
} else if( !selectSqlOk) {
displayStatus = validationResult.getUpdateStatusList(QueryValidator.SELECT_TRNS).iterator().next();
}
if( displayStatus != null ) {
toolTipText = displayStatus.getMessage();
displayImage = NOT_ALLOWED_IMAGE;
useDefaultForDeleteLabel.setText(Messages.DefaultUpdateMessageAmbigious);
} else {
useDefaultForDeleteLabel.setText(Messages.DefaultUpdateMessageOK);
}
} else {
// Now we check for "insert" SQL errors and warnings
SqlTransformationResult deleteResult = SqlMappingRootCache.getSqlTransformationStatus(currentMappingRoot, QueryValidator.DELETE_TRNS, true, null);
IStatus displayStatus = null;
if( deleteResult != null && !deleteResult.getStatusList().isEmpty()) {
displayStatus = deleteResult.getStatusList().iterator().next();
}
if( displayStatus != null ) {
displayImage = getSeverityImage(deleteResult.getMaxSeverity());
toolTipText = displayStatus.getMessage();
}
}
this.deleteTab.setImage(displayImage);
this.deleteTab.setToolTipText(toolTipText);
this.deleteTab.setText(tabText);
}
private boolean isUseDefault(int updateType) {
SqlTransformation helper = ((SqlTransformation)currentMappingRoot.getHelper());
if( helper == null ) {
return false;
}
switch( updateType ) {
case QueryValidator.INSERT_TRNS: return helper.isInsertSqlDefault();
case QueryValidator.UPDATE_TRNS: return helper.isUpdateSqlDefault();
case QueryValidator.DELETE_TRNS: return helper.isDeleteSqlDefault();
}
return false;
}
private Image getSeverityImage(int severity) {
if( severity == IStatus.ERROR ) {
return ERROR_IMAGE;
} else if( severity == IStatus.WARNING){
return WARNING_IMAGE;
}
return null;
}
/**
* Set editable status for the current editor
*
* @param item
*/
private void setEditableStatus( Object item ) {
boolean isReadOnly = false;
if (currentMappingRoot != null && ModelObjectUtilities.isReadOnly(currentMappingRoot)) {
isReadOnly = true;
}
if (isReadOnly) {
getSqlEditorForItem(item).setEditable(false);
} else {
if (item == selectTabForUpdate || item == sqlSelectPanelForNoUpdate) {
getSqlEditorForItem(item).setEditable(true);
} else if (item == insertTab || item == updateTab || item == deleteTab) {
boolean allowed = isEnableSelected(item);
boolean useDefault = isUseDefaultSelected(item);
if (allowed && !useDefault) {
getSqlEditorForItem(item).setEditable(true);
} else {
getSqlEditorForItem(item).setEditable(false);
}
}
}
}
/**
* Set transformation editor message for the current editor
*
* @param item
*/
private void setEditorMessage( Object item ) {
int cmdType = getCommandTypeForItem(item);
// This is the "Editor message panel" at the bottom of each SQL Editor.
// We need to Display the panel if ERRORS/Warnings exist for the specific cmdType
String message = null;
boolean showMessage = false;
boolean isTargetValid = TransformationHelper.isTargetValid(currentMappingRoot, cmdType);
//boolean isValid = TransformationHelper.isValid(currentMappingRoot, cmdType);
switch( cmdType ) {
case QueryValidator.SELECT_TRNS: {
SqlTransformationResult statusResult = SqlMappingRootCache.getSqlTransformationStatus(currentMappingRoot,QueryValidator.SELECT_TRNS, true, null);
if( !isTargetValid ) {
IStatus status = TransformationHelper.getTargetValidStatus(currentMappingRoot, cmdType);
if (status != null) {
message = status.getMessage();
showMessage = true;
}
} else if( statusResult != null && statusResult.getMaxSeverity() > IStatus.OK ) {
message = statusResult.getFullMessage();
showMessage = true;
}
} break;
case QueryValidator.INSERT_TRNS: {
if( !isUseDefault(QueryValidator.INSERT_TRNS)) {
SqlTransformationResult statusResult = SqlMappingRootCache.getSqlTransformationStatus(currentMappingRoot,QueryValidator.INSERT_TRNS, true, null);
if( statusResult != null && statusResult.getMaxSeverity() > IStatus.OK ) {
message = statusResult.getFullMessage();
showMessage = true;
}
} else {
SqlTransformationResult statusResult = SqlMappingRootCache.getSqlTransformationStatus(currentMappingRoot,QueryValidator.SELECT_TRNS, true, null);
if( statusResult != null && statusResult.getUpdateMaxSeverity(QueryValidator.INSERT_TRNS) > IStatus.OK ) {
message = statusResult.getUpdateFullMessage(QueryValidator.INSERT_TRNS);
showMessage = true;
}
}
} break;
case QueryValidator.UPDATE_TRNS: {
if( !isUseDefault(QueryValidator.UPDATE_TRNS)) {
SqlTransformationResult statusResult = SqlMappingRootCache.getSqlTransformationStatus(currentMappingRoot,QueryValidator.UPDATE_TRNS, true, null);
if( statusResult != null && statusResult.getMaxSeverity() > IStatus.OK ) {
message = statusResult.getFullMessage();
showMessage = true;
}
} else {
SqlTransformationResult statusResult = SqlMappingRootCache.getSqlTransformationStatus(currentMappingRoot,QueryValidator.SELECT_TRNS, true, null);
if( statusResult != null && statusResult.getUpdateMaxSeverity(QueryValidator.UPDATE_TRNS) > IStatus.OK ) {
message = statusResult.getUpdateFullMessage(QueryValidator.UPDATE_TRNS);
showMessage = true;
}
}
} break;
case QueryValidator.DELETE_TRNS: {
if( !isUseDefault(QueryValidator.DELETE_TRNS)) {
SqlTransformationResult statusResult = SqlMappingRootCache.getSqlTransformationStatus(currentMappingRoot,QueryValidator.DELETE_TRNS, true, null);
if( statusResult != null && statusResult.getMaxSeverity() > IStatus.OK ) {
message = statusResult.getFullMessage();
showMessage = true;
}
} else {
SqlTransformationResult statusResult = SqlMappingRootCache.getSqlTransformationStatus(currentMappingRoot,QueryValidator.SELECT_TRNS, true, null);
if( statusResult != null && statusResult.getUpdateMaxSeverity(QueryValidator.DELETE_TRNS) > IStatus.OK ) {
message = statusResult.getUpdateFullMessage(QueryValidator.DELETE_TRNS);
showMessage = true;
}
}
} break;
}
if( message != null ) {
currentSqlEditor.setMessage(message);
currentSqlEditor.showMessageArea(showMessage);
} else if( isTargetValid ){
setMessageDisplayForValidSQL();
}
}
/**
* Update the External groups for the supplied TransformationMappingRoot. The external Groups must be supplied for the
* Builders. Example of this is the InputSets for Mapping Classes, since the inputSets are no longer in the SQL FROM
*
* @param transMappingRoot the TransformationMappingRoot
*/
private Collection getExternalBuilderGroups( Object transMappingRoot ) {
Collection externalGroups = null;
if (transMappingRoot != null && TransformationHelper.isSqlTransformationMappingRoot(transMappingRoot)) {
EObject targetGroup = TransformationHelper.getTransformationLinkTarget((EObject)transMappingRoot);
if (targetGroup instanceof MappingClass) {
externalGroups = new ArrayList(1);
EObject inputSet = ((MappingClass)targetGroup).getInputSet();
externalGroups.add(inputSet);
} else if (TransformationHelper.isSqlProcedure(targetGroup)) {
// If the procedure has any IN or INOUT parameters, add it
List inParams = TransformationHelper.getInAndInoutParameters(targetGroup);
if (!inParams.isEmpty()) {
externalGroups = new ArrayList(1);
externalGroups.add(targetGroup);
}
}
}
if (externalGroups == null) {
externalGroups = Collections.EMPTY_LIST;
}
return externalGroups;
}
/**
* @param item
* @return The command type enumeration for the supplied item
*/
private int getCommandTypeForItem( Object item ) {
int type = QueryValidator.SELECT_TRNS;
if (item == insertTab) {
type = QueryValidator.INSERT_TRNS;
} else if (item == updateTab) {
type = QueryValidator.UPDATE_TRNS;
} else if (item == deleteTab) {
type = QueryValidator.DELETE_TRNS;
}
return type;
}
/**
* @param item
* @return The SqlEditorPanel instance for the supplied item
*/
private SqlEditorPanel getSqlEditorForItem( Object item ) {
if (noUpdatesAllowed) {
return sqlSelectEditorForNoUpdate;
}
SqlEditorPanel editor = null;
if (item == sqlSelectPanelForNoUpdate) {
editor = sqlSelectEditorForNoUpdate;
} else if (item == selectTabForUpdate) {
editor = sqlSelectEditorForUpdate;
} else if (item == insertTab) {
editor = sqlInsertEditor;
} else if (item == updateTab) {
editor = sqlUpdateEditor;
} else if (item == deleteTab) {
editor = sqlDeleteEditor;
}
return editor;
}
public String getObjectText() {
String result = null;
if (currentMappingRoot != null) {
result = StatusBarUpdater.formatEObjectMessage(currentMappingRoot);
}
return result;
}
private boolean isEditorValid() {
return getControl() != null && !getControl().isDisposed();
}
/**
* @see org.teiid.designer.ui.editors.ModelObjectEditorPage#deactivate()
*/
@Override
public boolean deactivate() {
// this editor is being closed so perform save
// Defect 17115 involved a problem where the doSave() call resulted in an NPE
// As a result, the page was not removed as a listener and it continued to recieve
// events and trying to process them.
// Fix is to catch the exception, log it and continue on with deactivation.
try {
doSave(true);
} catch (Exception err) {
Util.log(err);
}
ModelUtilities.removeNotifyChangedListener(this);
SqlMappingRootCache.removeEventListener(this);
// clear all undo histories
resetAllUndoManagers();
deactivated = true;
// -----------------------------------------------------------------------------------------------------------------------
// DEFECT 23230
// Added this call to clean up the SQL Editor SQL text so when re-opened, the text will be reset and validated correctly
// -----------------------------------------------------------------------------------------------------------------------
edit(null);
return true;
}
// -----------------------------------------------------------------------------------------------------------------------
// DEFECT 23230
// convienence method to set the sql edtior's text to NULL. Initial use is during deactivate() call.
// -----------------------------------------------------------------------------------------------------------------------
private void clearSqlEditors() {
if (!parent.isDisposed()) {
if (sqlSelectEditorForNoUpdate != null) {
sqlSelectEditorForNoUpdate.clear();
}
if (sqlSelectEditorForUpdate != null) {
sqlSelectEditorForUpdate.clear();
}
if (sqlInsertEditor != null) {
sqlInsertEditor.clear();
}
if (sqlUpdateEditor != null) {
sqlUpdateEditor.clear();
}
if (sqlDeleteEditor != null) {
sqlDeleteEditor.clear();
}
if (sqlEditorPanelWrapper != null) {
sqlEditorPanelWrapper.clear();
}
}
if (sqlSelectEditorForNoUpdate != null) {
sqlSelectEditorForNoUpdate.setQueryValidator(null);
}
if (sqlSelectEditorForUpdate != null) {
sqlSelectEditorForUpdate.setQueryValidator(null);
}
if (sqlInsertEditor != null) {
sqlInsertEditor.setQueryValidator(null);
}
if (sqlUpdateEditor != null) {
sqlUpdateEditor.setQueryValidator(null);
}
if (sqlDeleteEditor != null) {
sqlDeleteEditor.setQueryValidator(null);
}
if (sqlEditorPanelWrapper != null) {
sqlEditorPanelWrapper.setQueryValidator(null);
}
}
/**
* @see org.teiid.designer.ui.editors.ModelObjectEditorPage#addPropertyListener(org.eclipse.ui.IPropertyListener)
*/
@Override
public void addPropertyListener( IPropertyListener listener ) {
propListeners.addListener(IPropertyListener.class, listener);
}
/**
* @see org.teiid.designer.ui.editors.ModelObjectEditorPage#removePropertyListener(org.eclipse.ui.IPropertyListener)
*/
@Override
public void removePropertyListener( IPropertyListener listener ) {
propListeners.removeListener(IPropertyListener.class, listener);
}
/**
* Handler method for transformation status change. Basically, this does a refresh when the status of the current query
* changes. If the allowsUpdate status of the target changes, this will result in a tab change.
*/
void handleTransformationStatusChangeEvent( final boolean reconcileTarget,
final Object txnSource,
final boolean overwriteDirty ) {
if (txnSource != this && !(txnSource instanceof SqlEditorPanel)) {
if (this.validator != null) {
boolean didSetText = false;
// synchronize the SELECT for noUpdates / Updates first...
if (isCurrentTabSelect()) {
if (objEditorParentLayout.topControl == tabFolderWithUpdateTabs && sqlSelectEditorForNoUpdate != null) {
sqlSelectEditorForNoUpdate.setQueryValidator(this.validator);
// Call setEditorContent() instead of setText() to force validation.
// We want to do this because the txnSource is NOT this T-Editor and we need to assume that the SQL has
// changed and we need to re-set the Editor from the SQL T-Root object and it's SQL
setEditorContent(getSelectedItem(), reconcileTarget, txnSource, overwriteDirty, true);
didSetText = true;
} else if (sqlSelectEditorForUpdate != null) {
sqlSelectEditorForUpdate.setQueryValidator(this.validator);
// Call setEditorContent() instead of setText() to force validation.
// We want to do this because the txnSource is NOT this T-Editor and we need to assume that the SQL has
// changed and we need to re-set the Editor from the SQL T-Root object and it's SQL
UiUtil.runInSwtThread(new Runnable() {
@Override
public void run() {
setEditorContent(getSelectedItem(), reconcileTarget, txnSource, overwriteDirty, true);
}
}, true);
didSetText = true;
}
}
// Refresh Tab selection
// FIX for Invalid SWT Thread Access
// put on SWT thread
UiUtil.runInSwtThread(new Runnable() {
@Override
public void run() {
refreshTabs();
}
}, true);
// defect 15131: if dirty, keep the editor dirty.
// ONLY set content if we hadn't already done so above
if (!didSetText) {
setEditorContent(getSelectedItem(), reconcileTarget, txnSource, overwriteDirty, true);
}
// FIX for Invalid SWT Thread Access. Was coming through processEvent() listener
// put on SWT thread
UiUtil.runInSwtThread(new Runnable() {
@Override
public void run() {
objEditorParent.layout();
}
}, true);
}
} else {
setEditorMessage(getSelectedItem());
}
// Allow actions to update state based on changes in SQL and validation status
updateActions();
}
/**
* Create TransformationValidator with current root and set validator on all editors
*
* @since 5.0
*/
private void resetValidators() {
this.validator = new TransformationValidator(currentMappingRoot, false);
if (sqlSelectEditorForUpdate != null) {
sqlSelectEditorForUpdate.setQueryValidator(this.validator);
}
if (sqlSelectEditorForNoUpdate != null) {
sqlSelectEditorForNoUpdate.setQueryValidator(this.validator);
}
if (sqlSelectEditorForUpdate != null) {
sqlSelectEditorForUpdate.setQueryValidator(this.validator);
}
if (sqlInsertEditor != null) {
sqlInsertEditor.setQueryValidator(this.validator);
}
if (sqlUpdateEditor != null) {
sqlUpdateEditor.setQueryValidator(this.validator);
}
if (sqlDeleteEditor != null) {
sqlDeleteEditor.setQueryValidator(this.validator);
}
}
/**
* @see org.eclipse.emf.edit.provider.INotifyChangedListener#notifyChanged(org.eclipse.emf.common.notify.Notification)
*/
@Override
public void notifyChanged( Notification notification ) {
if (!isEditorValid()) return;
// Check for SourcedNotification (we should only get SourcedNotifications)
if (notification instanceof SourcedNotification) {
Object source = ((SourcedNotification)notification).getSource();
Collection notifications = ((SourcedNotification)notification).getNotifications();
handleNotifications(notifications, source);
} else { // handle single Notification
Collection notifications = new ArrayList(1);
notifications.add(notification);
handleNotifications(notifications, null);
}
}
/**
* Notifications handler. Gathers all like notifications and handles them together. Only the relevant notifications will be
* processed by this listener. Currently the only notification that is handle here is "allowsUpdates" changes to the target
* tables.
*
* @param notifications the collection of all notifications
*/
public void handleNotifications( Collection notifications,
final Object txnSource ) {
// --------------------------------------------------------
// Do a first-pass - ignore irrelevant notifications
// --------------------------------------------------------
Collection validNotifications = getValidNotifications(notifications);
// -------------------------------------------------
// Process remaining valid notifications
// Dont respond to events caused by this class
// -------------------------------------------------
if (!validNotifications.isEmpty() && !(txnSource instanceof TransformationObjectEditorPage)) {
// if (Thread.currentThread() == getControl().getDisplay().getThread()) {
// handleTransformationStatusChangeEvent(true, txnSource, true); // should this be true? I'm not sure when this
// // method is called...
// } else {
// getControl().getDisplay().syncExec(new Runnable() {
// public void run() {
// handleTransformationStatusChangeEvent(true, txnSource, true); // should this be true? I'm not sure when
// // this method is called...
// }
// });
// }
}
}
/**
* Do a first pass to remove totally irrelevant notifications. This editorPage is only interested in 1) changes to the target
* table 'allowUpdates' feature
*
* @param notifications the collection of all notifications
* @return new collection of relevant notifications
*/
private Collection getValidNotifications( Collection notifications ) {
Collection validNotifications = new ArrayList(notifications.size());
Iterator iter = notifications.iterator();
while (iter.hasNext()) {
Notification notification = (Notification)iter.next();
// Only need to keep change notifications
if (NotificationUtilities.isChanged(notification)) {
// If the changedObject is one of the following, process it
// (1) the target Virtual Group
final Object changedObject = ModelerCore.getModelEditor().getChangedObject(notification);
if (changedObject != null && changedObject instanceof EObject) {
// jh Defect 21479 - accept notifications for sql mods
// (this fixes Undo Clear Transformation so that SQL is restored)
if (changedObject instanceof SqlTransformation) {
validNotifications.add(notification);
continue;
}
// ChangedObject is current MappingRoot or SqlTransformation
if (isCurrentTransformationLinkTarget((EObject)changedObject)) {
// Get the target allowsUpdate State - see if it's different than editor state
boolean targetSupportsUpdateState = TransformationHelper.tableSupportsUpdate((EObject)changedObject);
// If different, then respond to the notification
if (targetSupportsUpdateState != this.targetAllowsUpdates) {
validNotifications.add(notification);
continue;
}
}
}
}
}
return validNotifications;
}
/**
* Helper method to determine if the supplied EObject is the current SqlTransformation link target
*
* @param eObj the EObject to test
* @return 'true' if it's the current SqlTransformation link target, 'false' if not.
*/
private boolean isCurrentTransformationLinkTarget( EObject eObj ) {
boolean result = false;
if (currentMappingRoot != null) {
EObject linkTarget = TransformationHelper.getTransformationLinkTarget(currentMappingRoot);
if (linkTarget != null && linkTarget.equals(eObj)) {
result = true;
}
}
return result;
}
/**
* Get the currently selected item
*
* @return the selected item
*/
private Object getSelectedItem() {
Object item = getTopControl();
if (item instanceof CTabFolder) {
CTabFolder folder = (CTabFolder)item;
CTabItem ti = folder.getSelection();
if (ti != null) {
return ti;
}
return folder.getItem(0);
}
return item;
}
/**
* Determine if the current transformation target allows Updates
*
* @return 'true' if the target allows updates, 'false' if not. from other model views.
* @param theMenuMgr the context menu being contributed to
*/
boolean getTargetAllowsUpdates() {
boolean allowsUpdates = false;
// Get current transformation target
EObject targetEObj = TransformationHelper.getTransformationTarget(currentMappingRoot);
// get target allowsUpdates state
if (targetEObj != null) {
allowsUpdates = TransformationHelper.tableSupportsUpdate(targetEObj);
}
return allowsUpdates;
}
/**
* Set the value for current transformation target allows Updates 'true' if the target allows updates, 'false' if not.
*
* @param allowsUPdates
*/
private void setTargetAllowsUpdates( boolean allowsUpdates ) {
// Get current transformation target
EObject targetEObj = TransformationHelper.getTransformationTarget(currentMappingRoot);
// get target allowsUpdates state
if (targetEObj != null) {
TransformationHelper.setTableSupportsUpdate(targetEObj, allowsUpdates);
resetAllUndoManagers();
}
}
/**
* Offers the editor a chance to contribute actions which will be made available to context menus from other model views.
*
* @param theMenuMgr the context menu being contributed to
*/
@Override
public void contributeExportedActions( IMenuManager theMenuMgr ) {
IAction action = null;
IWorkbenchWindow window = UiPlugin.getDefault().getWorkbench().getActiveWorkbenchWindow();
DiagramActionService service = (DiagramActionService)DiagramUiPlugin.getDefault().getActionService(window.getActivePage());
// -----------------------------------------
// Contribute the AddToSqlSelect Action
// -----------------------------------------
try {
IEditorPart editorPart = window.getActivePage().getActiveEditor();
if (editorPart instanceof ModelEditor) {
ModelEditorPage editorPage = (ModelEditorPage)((ModelEditor)editorPart).getCurrentPage();
String actionKey = DiagramActionService.constructKey(DiagramActions.ADD_TO_SQL_SELECT, editorPage);
if (service.isRegistered(actionKey)) {
action = service.getAction(actionKey);
}
}
} catch (final CoreException err) {
Util.log(err);
}
if (action != null) {
// check to see if menu is edit menu or just a context menu
if (theMenuMgr.find(ModelerActionBarIdManager.getMenuAdditionsMarkerId()) == null) {
// must be a context menu. just add to end.
theMenuMgr.add(action);
} else {
// edit menu. add before end marker.
theMenuMgr.insertBefore(ModelerActionBarIdManager.getMenuAdditionsMarkerId(), action);
}
}
// -----------------------------------------
// Contribute the AddJoinExpression Action
// -----------------------------------------
try {
IEditorPart editorPart = window.getActivePage().getActiveEditor();
if (editorPart instanceof ModelEditor) {
ModelEditorPage editorPage = (ModelEditorPage)((ModelEditor)editorPart).getCurrentPage();
String actionKey = DiagramActionService.constructKey(DiagramActions.ADD_JOIN_EXPRESSION, editorPage);
if (service.isRegistered(actionKey)) {
action = service.getAction(actionKey);
}
}
} catch (final CoreException err) {
Util.log(err);
}
if (action != null) {
// check to see if menu is edit menu or just a context menu
if (theMenuMgr.find(ModelerActionBarIdManager.getMenuAdditionsMarkerId()) == null) {
// must be a context menu. just add to end.
theMenuMgr.add(action);
} else {
// edit menu. add before end marker.
theMenuMgr.insertBefore(ModelerActionBarIdManager.getMenuAdditionsMarkerId(), action);
}
}
}
/**
* @see org.teiid.designer.ui.editors.IEditorActionExporter#getAdditionalModelingActions(org.eclipse.jface.viewers.ISelection)
* @since 5.0
*/
@Override
public List<IAction> getAdditionalModelingActions( ISelection selection ) {
List<IAction> addedActions = new ArrayList<IAction>();
IAction action = null;
IWorkbenchWindow window = UiPlugin.getDefault().getWorkbench().getActiveWorkbenchWindow();
DiagramActionService service = (DiagramActionService)DiagramUiPlugin.getDefault().getActionService(window.getActivePage());
// -----------------------------------------
// Contribute the AddToSqlSelect Action
// -----------------------------------------
try {
IEditorPart editorPart = window.getActivePage().getActiveEditor();
if (editorPart instanceof ModelEditor) {
ModelEditorPage editorPage = (ModelEditorPage)((ModelEditor)editorPart).getCurrentPage();
String actionKey = DiagramActionService.constructKey(DiagramActions.ADD_TO_SQL_SELECT, editorPage);
if (service.isRegistered(actionKey)) {
action = service.getAction(actionKey);
}
}
} catch (final CoreException err) {
Util.log(err);
}
if (action != null && action.isEnabled()) {
addedActions.add(action);
}
// -----------------------------------------
// Contribute the AddJoinExpression Action
// -----------------------------------------
action = null;
try {
IEditorPart editorPart = window.getActivePage().getActiveEditor();
if (editorPart instanceof ModelEditor) {
ModelEditorPage editorPage = (ModelEditorPage)((ModelEditor)editorPart).getCurrentPage();
String actionKey = DiagramActionService.constructKey(DiagramActions.ADD_JOIN_EXPRESSION, editorPage);
if (service.isRegistered(actionKey)) {
action = service.getAction(actionKey);
}
}
} catch (final CoreException err) {
Util.log(err);
}
if (action != null && action.isEnabled()) {
addedActions.add(action);
}
return addedActions;
}
/**
* @see org.teiid.designer.ui.editors.ModelObjectEditorPage#contributeToolbarActions(org.eclipse.jface.action.ToolBarManager)
*/
@Override
public void contributeToolbarActions( ToolBarManager toolBarMgr ) {
if (toolBarMgr == null) return;
int iAction = 0; // Keep track of separator locations
if (this.currentMappingRoot != null) {
boolean addedButton = false;
if (this.currentMappingRoot != null) {
SortableSelectionAction actualPreviewDataAction = ModelerSpecialActionManager.getAction(org.teiid.designer.ui.UiConstants.Extensions.PREVIEW_DATA_ACTION_ID);
if (actualPreviewDataAction != null) {
// This is a special case. Preview action lives in dqp.ui plugin. However we need a separate instanceo of it
// to better manage
// it's enablement state. So we provided a clone() method to get a generic copy of it.
// This is done through the modeler.ui's SortableSelectionAction which is an abstract class that implements a
// default no-op
// clone() method that is overridden by the PreviewTableDataContextAction
previewDataAction = actualPreviewDataAction.getClone();
// Override the image and tooltip since it's behavior is specific to Transformations
previewDataAction.setImageDescriptor(UiPlugin.getDefault().getImageDescriptor(PluginConstants.Images.PREVIEW_VIRTUAL_DATA_ICON));
previewDataAction.setToolTipText(PREVIEW_DATA_TOOLTIP);
// Set the selection to be the mapping root target (i.e. virtual table, operation, whatever
previewDataAction.setSelection(new StructuredSelection(currentMappingRoot.getTarget()));
toolBarMgr.add(previewDataAction);
toolBarMgr.add(new Separator());
iAction++;
addedButton = true;
updateActions();
}
}
searchTransformationsAction = new OpenTransformationSearchPageAction2();
toolBarMgr.add(searchTransformationsAction);
iAction++;
addedButton = true;
if (!TransformationHelper.isOperation(currentMappingRoot.getTarget())) {
editTransformationAction = new EditTransformationAction();
if (isResourceValid()) {
editTransformationAction.setSelection(new StructuredSelection(getTargetResource()));
}
toolBarMgr.add(editTransformationAction);
iAction++;
addedButton = true;
}
if (addedButton) {
toolBarMgr.add(new Separator());
}
}
toolBarMgr.add(getLabelContributionForCursorPosition());
toolBarMgr.add(new Separator());
// We don't want to contribute this if the object is a Mapping Class or Staging Table
if (this.currentMappingRoot != null && !TransformationHelper.isMappingClass(currentMappingRoot.getTarget())
&& !TransformationHelper.isStagingTable(currentMappingRoot.getTarget())
&& !TransformationHelper.isOperation(currentMappingRoot.getTarget())
&& !TransformationHelper.isSqlProcedure(currentMappingRoot.getTarget())) {
toolBarMgr.add(getCheckBoxContributionForSupportsUpdates());
toolBarMgr.add(new Separator());
}
// Put separators after the following actions
List separatorLocs = getSeparatorLocations();
IAction reconcileAction = contributeReconcileAction();
if (reconcileAction != null) {
toolBarMgr.add(reconcileAction);
iAction++;
}
// Get the Actions from the SqlPanel -- sqlEditorPanelWrapper
List sqlActions = getSqlEditorPanelWrapper().getActions();
// Add the Actions
Iterator iter = sqlActions.iterator();
while (iter.hasNext()) {
Object obj = iter.next();
if (obj instanceof ToggleOptimizer) {
this.toggleOptimizerAction = (ToggleOptimizer)obj;
}
// Add the next action
toolBarMgr.add((Action)obj);
// Determine if we need a separator after it
iAction++;
if (separatorLocs.contains(new Integer(iAction))) {
toolBarMgr.add(new Separator());
}
}
}
/* Method should be called any time the content or focus of this editor has changed, as well as when the validation status of the
* SQL could have changed.
*
*/
private void updateActions() {
// update the preview data action
if (previewDataAction != null && currentMappingRoot != null) {
ISelection newSelection = new StructuredSelection(currentMappingRoot.getTarget());
previewDataAction.setSelection(newSelection);
if (isDirty() && previewDataAction.isEnabled()) {
previewDataAction.setEnabled(false);
} else {
previewDataAction.setEnabled(previewDataAction.isApplicable(newSelection));
}
}
if (editTransformationAction != null && isResourceValid()) {
editTransformationAction.setSelection(new StructuredSelection(getTargetResource()));
}
}
/**
* @return The newly created reconcile action if created; <code>null</code> otherwise.
* @since 5.0.1
*/
protected IAction contributeReconcileAction() {
IAction reconcileAction = null;
IWorkbenchWindow window = UiPlugin.getDefault().getWorkbench().getActiveWorkbenchWindow();
DiagramActionService service = (DiagramActionService)DiagramUiPlugin.getDefault().getActionService(window.getActivePage());
try {
IEditorPart editorPart = window.getActivePage().getActiveEditor();
if (editorPart instanceof ModelEditor) {
ModelEditorPage editorPage = (ModelEditorPage)((ModelEditor)editorPart).getCurrentPage();
String actionKey = DiagramActionService.constructKey(DiagramActions.RECONCILE_TRANSFORMATION, editorPage);
reconcileAction = service.getAction(actionKey);
if (reconcileAction instanceof ReconcileTransformationAction) {
((ReconcileTransformationAction)reconcileAction).setTransObjectEditorPage(this);
}
}
} catch (CoreException err) {
Util.log(err);
}
return reconcileAction;
}
CheckBoxContribution getCheckBoxContributionForSupportsUpdates() {
// System.out.println("[ChoicePanel.getComboBoxContributionForDefault] TOP"); //$NON-NLS-1$
if (chkSupportsUpdatesContribution == null) {
chkSupportsUpdatesContribution = new CheckBoxContribution(SUPPORTS_UPDATE_TEXT);
chkSupportsUpdatesContribution.setToolTipText(getString("supportsUpdatesCheckBox.toolTip")); //$NON-NLS-1$
}
return chkSupportsUpdatesContribution;
}
void handleSupportsUpdatesCheckBoxChanged() {
// jh Defect 21528: Do save first, if appropriate
doSave(false);
setTargetAllowsUpdates(getCheckBoxContributionForSupportsUpdates().getSelection());
getCheckBoxContributionForSupportsUpdates().getControl().update();
// refresh content as select editor was clearing the first time button was checked
refreshEditorContent();
}
private LabelContribution getLabelContributionForCursorPosition() {
if (lblCursorPositionContribution == null) {
lblCursorPositionContribution = new LabelContribution("Cursor at (0, 0) "); //$NON-NLS-1$
}
return lblCursorPositionContribution;
}
private String getCurrentCursorPosition() {
String sPosition = CURSOR_AT_TEXT;
int column = 0;
int row = 0;
if (currentSqlEditor != null) {
column = 1 + currentSqlEditor.getCaretXPosition();
row = 1 + currentSqlEditor.getCaretYPosition();
}
sPosition = sPosition + row + COMMA_SPACE + column + RIGHT_PARENTH;
return sPosition;
}
void handleCursorPositionChanged() {
getLabelContributionForCursorPosition().setText(getCurrentCursorPosition());
}
/**
* Builds list of the Separator locations for the toolbar. The separator will be placed following the action count (eg,
* separator at 2 will be placed after the second action)
*/
protected List getSeparatorLocations() {
List separatorLocs = new ArrayList(6);
separatorLocs.add(new Integer(3));
separatorLocs.add(new Integer(5));
separatorLocs.add(new Integer(6));
separatorLocs.add(new Integer(8));
separatorLocs.add(new Integer(10));
return separatorLocs;
}
/**
* @see org.teiid.designer.ui.editors.ModelObjectEditorPage#doSave()
*/
@Override
public void doSave( boolean isClosing ) {
if (this.parent.isDisposed()) return;
boolean saveChanges = true;
SqlEditorPanel theEditor = getCurrentSqlEditor();
if (theEditor.hasPendingChanges()) {
if (isClosing) {
saveChanges = MessageDialog.openQuestion(parent.getShell(), SAVE_PENDING_TITLE, SAVE_PENDING_MSG);
}
if (saveChanges) {
// Set text without source so that it propagates back and sets the metadata
theEditor.setQueryValidator(this.validator);
theEditor.setText(theEditor.getText());
} else {
// need to let property change listeners that the changes have been thrown away
setDirty(false);
}
}
}
@Override
public Object getAdapter( Class key ) {
if (key.equals(IFindReplaceTarget.class) && (this.currentSqlEditor != null)) {
return this.currentSqlEditor.getTextViewer().getFindReplaceTarget();
}
if (key.equals(IUndoManager.class)) {
return this;
}
return null;
}
// ==========================================================
// SelectionListener Interface
// ==========================================================
@Override
public void widgetSelected( SelectionEvent e ) {
Object eventSource = e.getSource();
// ---------------------------------------
// Tab Selection
// ---------------------------------------
if (eventSource == getTopControl()) {
handleTabSelectionChanged();
}
}
@Override
public void widgetDefaultSelected( SelectionEvent e ) {
widgetSelected(e);
}
/**
* Handler method for Tab Selection
*/
private void handleTabSelectionChanged() {
Object previousItem = this.currentItem;
Object selectedItem = getSelectedItem();
// Check whether the tab selection is different
if (selectedItem != previousItem) {
// ---------------------------------------------------
// Save Current Tab Sql first, so changes aren't lost
// ---------------------------------------------------
if (currentSqlEditor.hasPendingChanges()) {
// Get Previous Editor SQL First
String previousSql = this.currentSqlEditor.getText();
int cmdType = getCommandTypeForItem(previousItem);
if (TransformationHelper.isUserSqlDifferent(previousSql, currentMappingRoot, cmdType)) {
TransformationHelper.setSqlString(currentMappingRoot, previousSql, cmdType, true, this);
}
}
if (!this.targetAllowsUpdates) {
selectedItem = sqlSelectPanelForNoUpdate;
setCurrentSqlEditor(sqlSelectEditorForNoUpdate);
} else {
// update the current editor to match the tab selected
if (selectedItem == selectTabForUpdate) {
setCurrentSqlEditor(sqlSelectEditorForUpdate);
} else if (selectedItem == insertTab) {
setCurrentSqlEditor(sqlInsertEditor);
} else if (selectedItem == updateTab) {
setCurrentSqlEditor(sqlUpdateEditor);
} else if (selectedItem == deleteTab) {
setCurrentSqlEditor(sqlDeleteEditor);
}
}
// Update tab variable
this.currentItem = selectedItem;
setEditorContent(currentItem, true, this, true, false);
this.currentSqlEditor.getTextViewer().getTextWidget().setSelection(0);
this.currentSqlEditor.getTextViewer().getTextWidget().setFocus();
handleCursorPositionChanged();
}
}
/**
* handler for check-box state changes
*
* @param e the selection event
*/
void handleCheckBoxStateChanged( SelectionEvent e ) {
Object eventSource = e.getSource();
Object selectedItem = getSelectedItem();
// Get Selected States
boolean allowed = isEnableSelected(selectedItem);
boolean useDefault = isUseDefaultSelected(selectedItem);
// Update class variable
if (selectedItem == insertTab) {
bUseDefaultForInsert = useDefault;
} else if (selectedItem == updateTab) {
bUseDefaultForUpdate = useDefault;
} else if (selectedItem == deleteTab) {
bUseDefaultForDelete = useDefault;
}
// Set enabled states based on selections
setCheckBoxEnabledStates(selectedItem);
// boolean abortedUseDefault = false;
if (eventSource == chkUseDefaultForInsert || eventSource == chkUseDefaultForUpdate
|| eventSource == chkUseDefaultForDelete) {
// abortedUseDefault = handleUseDefaultCheckBoxChanged(eventSource,useDefault,allowed);
handleUseDefaultCheckBoxChanged(eventSource, useDefault, allowed);
}
setEditableStatus(selectedItem);
}
/**
* handler for useDefault check-box state changes
*
* @param eventSource the source of the event
* @param useDefault UseDefault state
* @param isAllowed the isAllowed state
* @return 'true' if aborted
*/
private boolean handleUseDefaultCheckBoxChanged( Object eventSource,
boolean useDefault,
boolean isAllowed ) {
Object selectedItem = getSelectedItem();
boolean abortUseDefault = false;
// ------------------------------
// Current Tab is Insert
// ------------------------------
if ((selectedItem == insertTab && eventSource == chkUseDefaultForInsert)
|| (selectedItem == updateTab && eventSource == chkUseDefaultForUpdate)
|| (selectedItem == deleteTab && eventSource == chkUseDefaultForDelete)) {
String typeStr = BLANK;
int cmdType = QueryValidator.SELECT_TRNS;
if (selectedItem == insertTab) {
typeStr = INSERT_SQL_TYPE;
cmdType = QueryValidator.INSERT_TRNS;
} else if (selectedItem == updateTab) {
typeStr = UPDATE_SQL_TYPE;
cmdType = QueryValidator.UPDATE_TRNS;
} else if (selectedItem == deleteTab) {
typeStr = DELETE_SQL_TYPE;
cmdType = QueryValidator.DELETE_TRNS;
}
// UseDefault was selected, set useDefault flag and SqlString
if (useDefault) {
// Warn user that choosing the default will wipe out the current values
boolean shouldReplace = shouldReplaceSqlText(typeStr);
// Use the Default
if (shouldReplace) {
// Set the UseDefault flag
if (cmdType == QueryValidator.INSERT_TRNS) {
TransformationHelper.setInsertSqlDefault(currentMappingRoot, true, false, this);
if( chkUseDefaultForInsert.getSelection() ) {
useDefaultForInsertLabel.setText(Messages.DefaultUpdateMessageOK);
}
} else if (cmdType == QueryValidator.UPDATE_TRNS) {
TransformationHelper.setUpdateSqlDefault(currentMappingRoot, true, false, this);
if( chkUseDefaultForInsert.getSelection() ) {
useDefaultForUpdateLabel.setText(Messages.DefaultUpdateMessageOK);
}
} else if (cmdType == QueryValidator.DELETE_TRNS) {
TransformationHelper.setDeleteSqlDefault(currentMappingRoot, true, false, this);
if( chkUseDefaultForInsert.getSelection() ) {
useDefaultForDeleteLabel.setText(Messages.DefaultUpdateMessageOK);
}
}
SqlMappingRootCache.invalidateStatus(currentMappingRoot, true, this);
setEditorContent(selectedItem, true, this, true, false);
} else {
// re-enable the check-box
abortUseDefault = true;
removeCheckBoxListeners(selectedItem);
if (selectedItem == insertTab) {
chkUseDefaultForInsert.setSelection(false);
} else if (selectedItem == updateTab) {
chkUseDefaultForUpdate.setSelection(false);
} else if (selectedItem == deleteTab) {
chkUseDefaultForDelete.setSelection(false);
}
addCheckBoxListeners(selectedItem);
}
// UseDefault was de-selected, set the properties from the editorPanel
} else if (!useDefault) {
// Set the UseDefault flag
if (cmdType == QueryValidator.INSERT_TRNS) {
TransformationHelper.setInsertSqlDefault(currentMappingRoot, false, false, this);
useDefaultForInsertLabel.setText(Messages.DefaultUpdateMessageOverride);
} else if (cmdType == QueryValidator.UPDATE_TRNS) {
TransformationHelper.setUpdateSqlDefault(currentMappingRoot, false, false, this);
useDefaultForUpdateLabel.setText(Messages.DefaultUpdateMessageOverride);
} else if (cmdType == QueryValidator.DELETE_TRNS) {
TransformationHelper.setDeleteSqlDefault(currentMappingRoot, false, false, this);
useDefaultForDeleteLabel.setText(Messages.DefaultUpdateMessageOverride);
}
// This gets the text from the EditorPanel and sets properties
SqlMappingRootCache.invalidateStatus(currentMappingRoot, true, this);
String sql = currentSqlEditor.getText();
TransformationHelper.setSqlString(currentMappingRoot, sql, cmdType, false, this);
setEditorContent(selectedItem, true, this, true, false);
}
}
return abortUseDefault;
}
/**
* Update the reconcilable states on the transformation editor based on the supplied SetQuery. The SetQuery passed in is
* resolvable.
*
* @param unionQuery the SetQuery
*/
private void updateEditorSetQueryStates( ISetQuery unionQuery ) {
List queries = SetQueryUtil.getQueryList(unionQuery);
int nQueries = queries.size();
List reconciledList = new ArrayList(nQueries);
for (int i = 0; i < nQueries; i++) {
IQueryCommand qCommand = (IQueryCommand)queries.get(i);
boolean nameMatchReqd = false;
if (i == 0) {
nameMatchReqd = true;
}
boolean isReconciled = TransformationMappingHelper.targetAndCommandReconcile(currentMappingRoot,
qCommand,
nameMatchReqd);
reconciledList.add(new Boolean(isReconciled));
}
getCurrentSqlEditor().setSetQueryReconciledStates(reconciledList);
}
/**
* Set UseDefault boolean states based on the status of the sqlStrings. If the sql is null or empty, the useDefault state is
* set to true;
*
* @param transMappingRoot the SqlTransformationMappingRoot
*/
private void setUseDefaultStates( SqlTransformationMappingRoot transMappingRoot ) {
if (transMappingRoot != null) {
// Set Insert UseDefault state
if (TransformationHelper.isInsertSqlDefault(transMappingRoot)) {
bUseDefaultForInsert = true;
} else {
bUseDefaultForInsert = false;
}
// Set Update UseDefault state
if (TransformationHelper.isUpdateSqlDefault(transMappingRoot)) {
bUseDefaultForUpdate = true;
} else {
bUseDefaultForUpdate = false;
}
// Set Delete UseDefault state
if (TransformationHelper.isDeleteSqlDefault(transMappingRoot)) {
bUseDefaultForDelete = true;
} else {
bUseDefaultForDelete = false;
}
}
}
/**
* Set the check-box states for the supplied mappingRoot and item.
*
* @param transMappingRoot The MappingRoot
* @param item The select, update, insert or delete item
*/
private void setCheckBoxStates( Object transMappingRoot,
Object item ) {
if (TransformationHelper.isSqlTransformationMappingRoot(transMappingRoot)) {
// Remove check-box Listeners
removeCheckBoxListeners(item);
// Get the command type for the tab
int cmdType = getCommandTypeForItem(item);
// -------------------------------------------------------------------
// Set useDefault selection states for the statement type.
// -------------------------------------------------------------------
if (cmdType == QueryValidator.INSERT_TRNS) {
if (TransformationHelper.isInsertSqlDefault((EObject)transMappingRoot)) {
bUseDefaultForInsert = true;
} else {
bUseDefaultForInsert = false;
}
if (!chkUseDefaultForInsert.isDisposed()) {
chkUseDefaultForInsert.setSelection(bUseDefaultForInsert);
}
} else if (cmdType == QueryValidator.UPDATE_TRNS) {
if (TransformationHelper.isUpdateSqlDefault((EObject)transMappingRoot)) {
bUseDefaultForUpdate = true;
} else {
bUseDefaultForUpdate = false;
}
if (!chkUseDefaultForUpdate.isDisposed()) {
chkUseDefaultForUpdate.setSelection(bUseDefaultForUpdate);
}
} else if (cmdType == QueryValidator.DELETE_TRNS) {
if (TransformationHelper.isDeleteSqlDefault((EObject)transMappingRoot)) {
bUseDefaultForDelete = true;
} else {
bUseDefaultForDelete = false;
}
if (!chkUseDefaultForDelete.isDisposed()) {
chkUseDefaultForDelete.setSelection(bUseDefaultForDelete);
}
}
// -------------------------------------------------------------------
// Disable useDefault check-boxes if type not allowed
// -------------------------------------------------------------------
setCheckBoxEnabledStates(item);
// Add check-box listeners
addCheckBoxListeners(item);
setSupportsUpdatesCheckBoxState();
}
}
private void setSupportsUpdatesCheckBoxState() {
// FIX for Invalid SWT Thread Access
// put on SWT thread
UiUtil.runInSwtThread(new Runnable() {
@Override
public void run() {
getCheckBoxContributionForSupportsUpdates().setEnabled(true);
getCheckBoxContributionForSupportsUpdates().setSelection(getTargetAllowsUpdates());
}
}, true);
}
/**
* This just sets the correct check-box enabled states based on selection state of the enable checkboxes.
*/
private void setCheckBoxEnabledStates( final Object item ) {
// FIX for Invalid SWT Thread Access
// put on SWT thread
UiUtil.runInSwtThread(new Runnable() {
@Override
public void run() {
boolean enableState = isEnableSelected(item);
// Set useDefault INSERT CheckBox State
if (item == insertTab && !chkUseDefaultForInsert.isDisposed()) {
chkUseDefaultForInsert.setEnabled(enableState);
// Set useDefault UPDATE CheckBox State
} else if (item == updateTab && !chkUseDefaultForUpdate.isDisposed()) {
chkUseDefaultForUpdate.setEnabled(enableState);
// Set useDefault DELETE CheckBox State
} else if (item == deleteTab && !chkUseDefaultForDelete.isDisposed()) {
chkUseDefaultForDelete.setEnabled(enableState);
}
}
}, true);
}
/**
* Determine if the enabled check-box is selected for this item.
*
* @param item
* @param true if useDefault is selected.
*/
boolean isEnableSelected( Object item ) {
boolean result = false;
if (item == insertTab) {
result = true;
} else if (item == updateTab) {
result = true;
} else if (item == deleteTab) {
result = true;
}
return result;
}
/**
* Determine if the useDefault check-box is selected for this item.
*
* @param item the type to check
* @param true if useDefault is selected.
*/
private boolean isUseDefaultSelected( Object item ) {
boolean result = false;
if (item == insertTab) {
result = chkUseDefaultForInsert.getSelection();
} else if (item == updateTab) {
result = chkUseDefaultForUpdate.getSelection();
} else if (item == deleteTab) {
result = chkUseDefaultForDelete.getSelection();
}
return result;
}
private boolean shouldReplaceSqlText( String typeStr ) {
MessageBox box = new MessageBox(parent.getShell(), SWT.YES | SWT.NO | SWT.APPLICATION_MODAL);
box.setMessage(getString("lostSqlText.text", typeStr)); //$NON-NLS-1$
box.setText(LOST_SQL_TITLE);
Boolean bShouldDropSqlText = new Boolean(box.open() == SWT.YES);
return bShouldDropSqlText.booleanValue();
}
/**
* Method that handles Events from the SqlEditorPanel.
*
* @param e the EventObject
*/
@Override
public void processEvent( final EventObject e ) {
if (!isEditorValid()) return;
// -----------------------------------------
// SqlEditorEvent from QueryEditor Panel
// -----------------------------------------
if (isEditorValid()) {
if (e instanceof SqlEditorEvent && currentMappingRoot != null) {
handleSqlEditorEvent((SqlEditorEvent)e);
} else if (e instanceof SqlTransformationStatusChangeEvent) {
SqlTransformationStatusChangeEvent stsce = (SqlTransformationStatusChangeEvent)e;
EObject eventMappingRoot = stsce.getMappingRoot();
// Defect 23295: Adding check here to make sure eventMappingRoot isn't "stale". We invalidate the SqlRoot cache
// when
// closing/unloading projects/models and the eResource() == NULL in these cases. Was resulting in in-advertent
// validations on stale mapping roots.
if (eventMappingRoot != null && eventMappingRoot.eResource() != null
&& ModelerCore.getModelEditor().equals(eventMappingRoot, currentMappingRoot)) {
handleTransformationStatusChangeEvent(false, e.getSource(), stsce.isOverwriteDirty());
}
}
}
}
/**
* handle Events received from the QueryEditorPanel
*
* @param qeEvent the QueryEditor event
*/
private void handleSqlEditorEvent( SqlEditorEvent sqlEvent ) {
// Only respond if the event was initiated by the SqlEditorPanel
Object eventSource = sqlEvent.getSource();
int eventType = sqlEvent.getType();
if (eventSource instanceof SqlEditorPanel) {
// ----------------------------------------------------------------
// Query Changes Pending Event from EditorPanel
// ----------------------------------------------------------------
if (eventType == SqlEditorEvent.CARET_CHANGED) {
handleCursorPositionChanged();
} else if (eventType == SqlEditorEvent.CHANGES_PENDING) {
handleSqlEditorChangesPending();
} else {
// ------------------------------------------------------------------------
// Query Event from EditorPanel - SQL Validatable, Resolvable or Parsable
// ------------------------------------------------------------------------
if (eventType == SqlEditorEvent.VALIDATABLE || eventType == SqlEditorEvent.RESOLVABLE
|| eventType == SqlEditorEvent.PARSABLE) {
handleSqlEditorCommandEvent(sqlEvent.getCommand(), sqlEvent.getSQLString(), eventType, eventSource);
// ----------------------------------------------------------------
// Query Changed Event from EditorPanel
// ----------------------------------------------------------------
} else if (eventType == SqlEditorEvent.CHANGED) {
handleSqlEditorChanged(sqlEvent.getSQLString(), eventSource);
}
}
} else if (eventType == SqlEditorEvent.CHANGES_PENDING) {
handleSqlEditorChangesPending();
}
}
/**
* handle the case when a validatable, resolvable, or parsable query is received from the editor panel
*
* @param command the new Command language object
* @param eventType the EventType received
* @param eventSource the source of the event
*/
private void handleSqlEditorCommandEvent( final ICommand command,
final String sqlString,
int eventType,
Object eventSource ) {
Object selectedItem = getSelectedItem();
int cmdType = getCommandTypeForItem(selectedItem);
// ------------------------------------------------------------------------------------
// Update the SQL (if necessary) and reconcile Target attributes
// ------------------------------------------------------------------------------------
// start txn
boolean requiredStart = ModelerCore.startTxn(false, false, SQL_UPDATE_TXN_DESCRIPTION, this);
boolean succeeded = false;
try {
// Use this as the source - Handlers will not recognize SqlEditorPanel
TransformationHelper.setSqlString(currentMappingRoot, sqlString, cmdType, false, this);
// Reconcile the mapping root Inputs / Attributes / etc to conform to the SQL
// (TransformationNotificationListener ignores sql Change generated by this panel)
TransformationMappingHelper.reconcileMappingsOnSqlChange(currentMappingRoot, this);
succeeded = true;
} finally {
// if we started the txn, commit it.
if (requiredStart) {
if (succeeded) {
ModelerCore.commitTxn();
} else {
ModelerCore.rollbackTxn();
}
}
}
// If the command is a SetQuery (UNION), update the reconciled status on the editorPanel
// Go ahead and check the command regardless if it's resolved or not.
ICommand newCommand = TransformationHelper.getCommand(currentMappingRoot, cmdType);
if (newCommand instanceof ISetQuery) {
updateEditorSetQueryStates((ISetQuery)newCommand);
}
// Set editor message area
updateMessagePanel();
setDirty(false);
// Fire status event - based on QueryEditorEvent type
if (eventType == SqlEditorEvent.VALIDATABLE) {
notifyEventListeners(new QueryEditorStatusEvent(this, QueryEditorStatusEvent.QUERY_VALIDATABLE));
} else if (eventType == SqlEditorEvent.RESOLVABLE) {
notifyEventListeners(new QueryEditorStatusEvent(this, QueryEditorStatusEvent.QUERY_RESOLVABLE));
} else if (eventType == SqlEditorEvent.PARSABLE) {
notifyEventListeners(new QueryEditorStatusEvent(this, QueryEditorStatusEvent.QUERY_PARSABLE));
}
}
/**
* handle the case when a resolvable query is received from the editor panel
*
* @param sqlString the the new sqlString from the editor
* @param eventSource the source of the event
*/
private void handleSqlEditorChanged( String sqlString,
Object eventSource ) {
int cmdType = getCommandTypeForItem(getSelectedItem());
// ------------------------------------------------------------------------------------
// Update the SQL - only if different than current User SQL
// ------------------------------------------------------------------------------------
if (TransformationHelper.isUserSqlDifferent(sqlString, currentMappingRoot, cmdType)) {
// start txn
boolean requiredStart = ModelerCore.startTxn(false, SQL_UPDATE_TXN_DESCRIPTION, this);
boolean succeeded = false;
try {
// Use this as source - Handlers will not recognize SqlEditorPanel
TransformationHelper.setSqlString(currentMappingRoot, sqlString, cmdType, false, this);
// Reconcile the mapping root Inputs / Attributes / etc to conform to the SQL
// (TransformationNotificationListener ignores sql Change generated by this panel)
// This is here to handle case of empty or initial "SELECT * FROM" query - will clear sources
TransformationMappingHelper.reconcileMappingsOnSqlChange(currentMappingRoot, this);
succeeded = true;
} finally {
// if we started the txn, commit it.
if (requiredStart) {
if (succeeded) {
ModelerCore.commitTxn();
} else {
ModelerCore.rollbackTxn();
}
}
}
}
// Open the Editor MessagePanel
getSqlEditorPanelWrapper().showMessageArea(true);
setDirty(false);
notifyEventListeners(new QueryEditorStatusEvent(this, QueryEditorStatusEvent.QUERY_NOT_PARSABLE));
}
/**
* handle the case when a changes pending notification is received from the editor panel
*/
private void handleSqlEditorChangesPending() {
getSqlEditorPanelWrapper().setMessage(SQL_CHANGES_PENDING_MSG);
getSqlEditorPanelWrapper().showMessageArea(true);
setDirty(true);
notifyEventListeners(new QueryEditorStatusEvent(this, QueryEditorStatusEvent.QUERY_HAS_PENDING_CHANGES));
}
/**
* @see org.teiid.designer.ui.undo.IUndoManager#canRedo()
* @since 5.5.3
*/
@Override
public boolean canRedo() {
return getCurrentSqlEditor().getUndoManager().redoable();
}
/**
* @see org.teiid.designer.ui.undo.IUndoManager#canUndo()
* @since 5.5.3
*/
@Override
public boolean canUndo() {
return getCurrentSqlEditor().getUndoManager().undoable();
}
/**
* @see org.teiid.designer.ui.undo.IUndoManager#getRedoLabel()
* @since 5.5.3
*/
@Override
public String getRedoLabel() {
return getString("redoMenuLabel"); //$NON-NLS-1$
}
/**
* @see org.teiid.designer.ui.undo.IUndoManager#getUndoLabel()
* @since 5.5.3
*/
@Override
public String getUndoLabel() {
return getString("undoMenuLabel"); //$NON-NLS-1$
}
/**
* @see org.teiid.designer.ui.undo.IUndoManager#redo(org.eclipse.core.runtime.IProgressMonitor)
* @since 5.5.3
*/
@Override
public void redo( IProgressMonitor monitor ) {
getCurrentSqlEditor().getUndoManager().redo();
monitor.done();
}
/**
* @see org.teiid.designer.ui.undo.IUndoManager#undo(org.eclipse.core.runtime.IProgressMonitor)
* @since 5.5.3
*/
@Override
public void undo( IProgressMonitor monitor ) {
getCurrentSqlEditor().getUndoManager().undo();
monitor.done();
}
// -------------------------------------------------------------------------
// Methods to Register, UnRegister, Notify Listeners to this Editors Events
// -------------------------------------------------------------------------
/**
* This method will register the listener for all SqlEditorEvents
*
* @param listener the listener to be registered
*/
public void addEventListener( EventObjectListener listener ) {
if (eventListeners == null) {
eventListeners = new ArrayList();
}
if (!eventListeners.contains(listener)) {
eventListeners.add(listener);
}
}
/**
* This method will un-register the listener for all SqlEditorEvents
*
* @param listener the listener to be un-registered
*/
public void removeEventListener( EventObjectListener listener ) {
if (eventListeners != null) {
eventListeners.remove(listener);
}
}
/**
* This method will notify the registered listeners of a SqlEditorEvent
*/
private void notifyEventListeners( EventObject event ) {
// If target is a Virtual Procedure, we need to disable the optimizer button on the SQL panel
if (toggleOptimizerAction != null) {
toggleOptimizerAction.setAllowOptimization(true);
}
if (eventListeners != null) {
Iterator iterator = eventListeners.iterator();
while (iterator.hasNext()) {
EventObjectListener listener = (EventObjectListener)iterator.next();
if (listener != null) {
listener.processEvent(event);
}
}
}
}
/**
* Set SqlEditorPanel Message For a Command. The EditorPanel Message and it's visibility depend on the command, the current
* Object and the tab that is currently selected. If the command is null, that means the SQL couldnt be validated, and the
* EditorPanel Message is not changed (the default editor message is used).
*/
private void setMessageDisplayForValidSQL() {
Object selectedItem = getSelectedItem();
// ------------------------------------------------------------------------
// InsertTab showing, display Insert Valid Message and close messagePanel
// ------------------------------------------------------------------------
if (selectedItem == insertTab) {
getSqlEditorPanelWrapper().setMessage(INSERT_SQL_MSG + SPACE + IS_VALID_MSG);
getSqlEditorPanelWrapper().showMessageArea(false);
// ------------------------------------------------------------------------
// UpdateTab showing, display Update Valid Message and close messagePanel
// ------------------------------------------------------------------------
} else if (selectedItem == updateTab) {
getSqlEditorPanelWrapper().setMessage(UPDATE_SQL_MSG + SPACE + IS_VALID_MSG);
getSqlEditorPanelWrapper().showMessageArea(false);
// ------------------------------------------------------------------------
// DeleteTab showing, display Delete Valid Message and close messagePanel
// ------------------------------------------------------------------------
} else if (selectedItem == deleteTab) {
getSqlEditorPanelWrapper().setMessage(DELETE_SQL_MSG + SPACE + IS_VALID_MSG);
getSqlEditorPanelWrapper().showMessageArea(false);
// ------------------------------------------------------------------------
// SelectTab showing, check target vs SQL projected symbols
// ------------------------------------------------------------------------
// Current MetaObject defines a stored Query
} else {
// Start of Message for Stored Query is different
String sqlTypeMsg = SELECT_SQL_MSG;
// Compare the SQL ProjectedSymbols vs the TargetGroup
int cmdType = getCommandTypeForItem(selectedItem);
boolean[] statusArray = TransformationMappingHelper.compareQueryTargetAndSQLOutput(currentMappingRoot, cmdType);
boolean targetAndSQLOutSizesOK = statusArray[0];
boolean targetAndSQLOutNamesOK = statusArray[1];
boolean targetAndSQLOutTypesOK = statusArray[2];
// Check the command for References
int refCount = TransformationSqlHelper.getReferenceCount(currentMappingRoot, cmdType);
// If all checks are OK, the SQL is Fully Reconciled and NO References
if (targetAndSQLOutSizesOK && targetAndSQLOutNamesOK && targetAndSQLOutTypesOK && refCount == 0) {
getSqlEditorPanelWrapper().setMessage(sqlTypeMsg + SPACE + IS_VALID_AND_RECONCILABLE);
getSqlEditorPanelWrapper().showMessageArea(false);
// If any check is not OK, refine the message further
} else {
StringBuffer buff = new StringBuffer(sqlTypeMsg + SPACE + IS_VALID_NOT_RECONCILABLE);
// Add Query Output Status (if invalid)
if (!targetAndSQLOutSizesOK) {
if (cmdType == QueryValidator.SELECT_TRNS) {
ICommand cmd = TransformationHelper.getCommand(currentMappingRoot, cmdType);
List<IExpression> symbols = CommandHelper.getProjectedSymbols(cmd);
if (symbols.isEmpty()) {
buff.append("\n" + QUERY_SIZE_MISMATCH_NO_PROJECTED_SYMBOLS_MSG); //$NON-NLS-1$
} else {
buff.append("\n" + QUERY_SIZE_MISMATCH_MSG); //$NON-NLS-1$
}
} else {
buff.append("\n" + QUERY_SIZE_MISMATCH_MSG); //$NON-NLS-1$
}
} else if (!targetAndSQLOutNamesOK) {
buff.append("\n" + QUERY_NAME_MISMATCH_MSG); //$NON-NLS-1$
} else if (!targetAndSQLOutTypesOK) {
buff.append("\n" + QUERY_TYPE_MISMATCH_MSG); //$NON-NLS-1$
}
// Add Message if there are references
if (refCount > 0) {
buff.append("\n" + COMMAND_HAS_REFERENCES_MSG); //$NON-NLS-1$
buff.append("\n" + NUMBER_REFERENCES_MSG + refCount); //$NON-NLS-1$
}
getSqlEditorPanelWrapper().setMessage(buff.toString());
getSqlEditorPanelWrapper().showMessageArea(true);
}
}
}
/**
* method that the model object editor can use during setFocus() when it touches the resource file and verifies the read-only
* state of the file. We have no other way to update the editor.
*
* @see org.teiid.designer.ui.editors.ModelObjectEditorPage#updateReadOnlyState(boolean)
* @since 4.2
*/
@Override
public void updateReadOnlyState() {
if (currentMappingRoot != null) {
boolean isReadOnly = ModelObjectUtilities.isReadOnly(currentMappingRoot);
if (isReadOnly != this.currentReadonlyState) {
this.currentReadonlyState = isReadOnly;
if (getCurrentSqlEditor() != null) {
getSqlEditorPanelWrapper().updateReadOnlyState(isReadOnly);
setEditableStatus(currentItem); // defect 13821 - this call respects the state of the checkboxes, unlike the
// old call
}
// Need to notify actions that need to enable/disable
notifyEventListeners(new SqlTransformationStatusChangeEvent(currentMappingRoot, this));
}
getCheckBoxContributionForSupportsUpdates().setEnabled(!isReadOnly);
// Update check boxes on insert/update/delete tabs
updateReadOnlyStateOfCheckBoxes(isReadOnly);
}
}
/* Update check boxes on insert/update/delete tabs */
private void updateReadOnlyStateOfCheckBoxes( final boolean isReadOnly ) {
UiUtil.runInSwtThread(new Runnable() {
@Override
public void run() {
if (chkUseDefaultForInsert != null) chkUseDefaultForInsert.setEnabled(!isReadOnly);
if (chkUseDefaultForUpdate != null) chkUseDefaultForUpdate.setEnabled(!isReadOnly);
if (chkUseDefaultForDelete != null) chkUseDefaultForDelete.setEnabled(!isReadOnly);
}
}, true);
}
/**
* @see org.teiid.designer.ui.editors.ModelObjectEditorPage#isDirty()
*/
@Override
public boolean isDirty() {
return this.isDirty;
}
protected void setDirty( boolean isDirty ) {
this.isDirty = isDirty;
Iterator listeners = propListeners.getListeners(IPropertyListener.class);
while (listeners.hasNext()) {
((IPropertyListener)listeners.next()).propertyChanged(this, IEditorPart.PROP_DIRTY);
}
// Allow actions to disable if they require complete/validate SQL
updateActions();
}
/**
* @see org.teiid.designer.ui.editors.ModelObjectEditorPage#isEditingObject(java.lang.Object)
* @since 4.2
*/
@Override
public boolean isEditingObject( Object modelObject ) {
if (currentMappingRoot != null && modelObject != null) {
if (modelObject instanceof InputSet) {
return false;
}
if (TransformationHelper.isSqlTransformationMappingRoot(modelObject)) {
if (modelObject.equals(currentMappingRoot)) return true;
} else if ((TransformationHelper.isVirtualSqlTable(modelObject) || TransformationHelper.isSqlVirtualProcedure(modelObject))
&& !TransformationHelper.isXmlDocument(modelObject)) {
// get the tRoot object and compare...
SqlTransformationMappingRoot workingMappingRoot = (SqlTransformationMappingRoot)TransformationHelper.getMappingRoot((EObject)modelObject);
if (workingMappingRoot != null && workingMappingRoot.equals(currentMappingRoot)) return true;
}
}
return false;
}
/**
* @see org.teiid.designer.ui.editors.ModelObjectEditorPage#getEditableObject(java.lang.Object)
* @since 4.2
*/
@Override
public Object getEditableObject( Object modelObject ) {
// check edit object type and set mapping root.
SqlTransformationMappingRoot workingMappingRoot = null;
EObject targetObject = null;
if (modelObject instanceof Diagram) {
targetObject = ((Diagram)modelObject).getTarget();
} else {
targetObject = (EObject)modelObject;
}
// Check to see if this is an XML Service model
if (targetObject != null) {
if (targetObject.eResource() != null && TransformationUiResourceHelper.isSqlTransformationResource(targetObject)) {
if (TransformationHelper.isSqlTransformationMappingRoot(targetObject)) workingMappingRoot = (SqlTransformationMappingRoot)targetObject;
else if (TransformationHelper.isVirtualSqlTable(targetObject)
|| TransformationHelper.isSqlVirtualProcedure(targetObject)) {
// One last check here, because XMLDocuments are SqlTableAspect eObjects. Must be a valid t-target
if (TransformationHelper.isValidSqlTransformationTarget(targetObject)) workingMappingRoot = (SqlTransformationMappingRoot)TransformationHelper.getMappingRoot(targetObject);
}
if (workingMappingRoot != null) return workingMappingRoot;
}
}
return null;
}
/**
* @see org.teiid.designer.ui.editors.ModelObjectEditorPage#isResourceValid()
* @since 4.2
*/
@Override
public boolean isResourceValid() {
if (currentMappingRoot != null) {
if (currentMappingRoot.eResource() != null) {
ModelResource mr = ModelUtilities.getModelResourceForModelObject(currentMappingRoot);
if (mr != null) return true;
}
}
return false;
}
private IResource getTargetResource() {
if (currentMappingRoot != null) {
if (currentMappingRoot.eResource() != null) {
ModelResource mr = ModelUtilities.getModelResourceForModelObject(currentMappingRoot);
return mr.getResource();
}
}
return null;
}
/**
* @return Returns the currentMappingRoot.
* @since 5.0.1
*/
public SqlTransformationMappingRoot getCurrentMappingRoot() {
return this.currentMappingRoot;
}
/**
* Does nothing.
*
* @see org.teiid.designer.ui.editors.ModelObjectEditorPage#initialize(org.teiid.designer.ui.editors.MultiPageModelEditor)
* @since 5.0.1
*/
@Override
public void initialize( MultiPageModelEditor editor ) {
if( editor instanceof ModelEditor ) {
this.parentModelEditor = (ModelEditor)editor;
}
}
public void updateMessagePanel() {
setEditorMessage(getSelectedItem());
}
/**
* @see org.teiid.designer.ui.editors.ModelObjectEditorPage#setOverride(org.teiid.designer.ui.editors.ModelObjectEditorPage)
* @since 5.0.1
*/
@Override
public void setOverride( ModelObjectEditorPage editor ) {
this.override = editor;
}
class CheckBoxContribution extends ControlContribution {
private Button chkSupportsUpdates;
private String toolTip;
// Style Contants
private static final int BUTTON_GRID_STYLE = GridData.HORIZONTAL_ALIGN_FILL | GridData.HORIZONTAL_ALIGN_CENTER;
Combo cbx = null;
public CheckBoxContribution( String id ) {
super(id);
}
/**
* @see org.eclipse.jface.action.ControlContribution#createControl(org.eclipse.swt.widgets.Composite)
*/
@Override
protected Control createControl( Composite parent ) {
chkSupportsUpdates = WidgetFactory.createCheckBox(parent, SUPPORTS_UPDATE_TEXT, BUTTON_GRID_STYLE);
if( toolTip != null ) {
chkSupportsUpdates.setToolTipText(toolTip);
}
chkSupportsUpdates.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected( final SelectionEvent event ) {
handleSupportsUpdatesCheckBoxChanged();
}
});
// defect 15601 -- keep track of disposal; we will need to recreate the
// entire contribution when this happens.
// I call this solution evil and messy, but it matches pretty well how
// the rest of the class is written.
chkSupportsUpdates.addDisposeListener(new DisposeListener() {
@Override
public void widgetDisposed( DisposeEvent e ) {
chkSupportsUpdatesContribution = null;
}
});
chkSupportsUpdates.setEnabled(!currentReadonlyState);
chkSupportsUpdates.setSelection(getTargetAllowsUpdates());
return chkSupportsUpdates;
}
public Control getControl() {
return chkSupportsUpdates;
}
public void setSelection( boolean b ) {
if (chkSupportsUpdates != null) {
chkSupportsUpdates.setSelection(b);
} // endif
}
public boolean getSelection() {
if (chkSupportsUpdates != null) {
return chkSupportsUpdates.getSelection();
} // endif
// not initialized yet, default to 'true'
return true;
}
public void setEnabled( boolean enabled ) {
if (chkSupportsUpdates != null) {
chkSupportsUpdates.setEnabled(enabled);
} // endif
}
public void setToolTipText(String text) {
toolTip = text;
}
}
class LabelContribution extends ControlContribution {
private static final int LABEL_GRID_STYLE = GridData.HORIZONTAL_ALIGN_BEGINNING;
Combo cbx = null;
String sText;
public LabelContribution( String sText ) {
super("myId"); //$NON-NLS-1$
this.sText = sText;
}
/**
* @see org.eclipse.jface.action.ControlContribution#createControl(org.eclipse.swt.widgets.Composite)
*/
@Override
protected Control createControl( Composite parent ) {
cursorPositionLabel = WidgetFactory.createLabel(parent, LABEL_GRID_STYLE, sText);
return cursorPositionLabel;
}
public void setText( String text ) {
cursorPositionLabel.setText(text);
}
}
public boolean isNoUpdatesAllowed() {
return this.noUpdatesAllowed;
}
public void setNoUpdatesAllowed( boolean theNoUpdatesAllowed ) {
this.noUpdatesAllowed = theNoUpdatesAllowed;
}
protected List customizeActionList( List initialActionList ) {
return initialActionList;
}
protected boolean allowsMultipleTabs() {
return true;
}
protected SqlPanelDropTargetListener createDropTargetListener( SqlEditorPanel sqlPanel,
SqlTransformationMappingRoot transformation ) {
return new SqlPanelDropTargetListener(sqlPanel, transformation, this);
}
}