/* * JBoss, Home of Professional Open Source. * * See the LEGAL.txt file distributed with this work for information regarding copyright ownership and licensing. * * See the AUTHORS.txt file distributed with this work for a full listing of individual contributors. */ package org.teiid.designer.transformation.ui.actions; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.mapping.MappingHelper; import org.eclipse.jface.action.Action; import org.eclipse.jface.dialogs.ProgressMonitorDialog; import org.eclipse.jface.viewers.ISelection; import org.eclipse.swt.widgets.Display; import org.eclipse.ui.IEditorPart; import org.eclipse.ui.ISelectionListener; import org.eclipse.ui.IWorkbenchPart; import org.eclipse.ui.actions.WorkspaceModifyOperation; import org.teiid.designer.core.ModelerCore; import org.teiid.designer.core.metamodel.aspect.sql.SqlAspect; import org.teiid.designer.core.metamodel.aspect.sql.SqlTableAspect; import org.teiid.designer.core.query.QueryValidationResult; import org.teiid.designer.core.query.QueryValidator; import org.teiid.designer.core.workspace.ModelResource; import org.teiid.designer.core.workspace.ModelUtil; import org.teiid.designer.core.workspace.ModelWorkspaceException; import org.teiid.designer.metamodels.transformation.SqlTransformation; import org.teiid.designer.metamodels.transformation.SqlTransformationMappingRoot; 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.editors.TransformationObjectEditorPage; import org.teiid.designer.transformation.util.SqlMappingRootCache; import org.teiid.designer.transformation.util.TransformationHelper; import org.teiid.designer.transformation.util.TransformationMappingHelper; import org.teiid.designer.transformation.validation.TransformationValidator; import org.teiid.designer.ui.actions.ISelectionAction; import org.teiid.designer.ui.common.eventsupport.SelectionUtilities; import org.teiid.designer.ui.common.widget.ListMessageDialog; import org.teiid.designer.ui.editors.ModelEditorManager; import org.teiid.designer.ui.editors.ModelObjectEditorPage; import org.teiid.designer.ui.editors.MultiPageModelEditor; import org.teiid.designer.ui.viewsupport.ModelObjectUtilities; import org.teiid.designer.ui.viewsupport.ModelUtilities; /** * @since 8.0 */ public class RevalidateModelTransformationsAction extends Action implements ISelectionListener, Comparable, ISelectionAction { private ModelResource modelResource; List brokenTables = Collections.EMPTY_LIST; private static final String REVALIDATE_TRANS = "Revalidate Transformations"; //$NON-NLS-1$ public RevalidateModelTransformationsAction() { super(); setImageDescriptor(UiPlugin.getDefault().getImageDescriptor(PluginConstants.Images.REVALIDATE_TRANSFORMATION_ICON)); } @Override public void selectionChanged( IWorkbenchPart part, ISelection selection ) { Object selectedObject = SelectionUtilities.getSelectedObject(selection); boolean enable = false; if (selectedObject instanceof IResource && ModelUtilities.isModelFile((IResource)selectedObject)) { try { this.modelResource = ModelUtil.getModelResource(((IFile)selectedObject), false); if (ModelUtilities.isVirtual(this.modelResource)) { enable = true; } } catch (ModelWorkspaceException e) { UiConstants.Util.log(e); } } setEnabled(enable); } /** * @see org.eclipse.ui.IActionDelegate#run(org.eclipse.jface.action.IAction) */ @Override public void run() { // // Get the currently active ModelObjectEditorPage, ensure its TransformationObjEditorPage // IEditorPart editor = UiPlugin.getDefault().getCurrentWorkbenchWindow().getActivePage().getActiveEditor(); if (editor != null && editor instanceof MultiPageModelEditor) { ModelObjectEditorPage moep = ((MultiPageModelEditor)editor).getActiveObjectEditor(); if (moep != null && moep instanceof TransformationObjectEditorPage) { ((MultiPageModelEditor)editor).closeObjectEditor(); } } // Force the modelEditor open, so that changes mark the resource dirty IResource resource = modelResource.getResource(); ModelEditorManager.getModelEditorForFile((IFile)resource, true); final WorkspaceModifyOperation op = new WorkspaceModifyOperation() { @Override public void execute( IProgressMonitor theMonitor ) { brokenTables = revalidate(); theMonitor.done(); } }; try { new ProgressMonitorDialog(Display.getCurrent().getActiveShell()).run(true, true, op); } catch (InterruptedException e) { } catch (InvocationTargetException e) { UiConstants.Util.log(e.getTargetException()); } warnUserAboutInvalidTransformations(brokenTables); brokenTables = Collections.EMPTY_LIST; } List revalidate() { // Keep list of problems List brokenSqlTables = new ArrayList(); if (modelResource != null) { // shut off transformation notifications UiPlugin.getDefault().setIgnoreTransformationNotifications(true); // start txn boolean requiredStart = ModelerCore.startTxn(true, false, REVALIDATE_TRANS, this); boolean succeeded = false; try { Object nextObj = null; List transformations = modelResource.getModelTransformations().getTransformations(); // Clean out the SqlMappingRootCache for these transformations invalidateSqlRootCache(transformations); // Iterate all of the transformation mapping roots for (Iterator iter = transformations.iterator(); iter.hasNext();) { nextObj = iter.next(); if (TransformationHelper.isSqlTransformationMappingRoot(nextObj)) { // Get current mapping root and query validator SqlTransformationMappingRoot mappingRoot = (SqlTransformationMappingRoot)nextObj; QueryValidator qv = new TransformationValidator(mappingRoot, false); // Check if INSERT/UPDATE/DELETE should be validated boolean supportsUpdates = false; EObject mRootTarget = mappingRoot.getTarget(); SqlAspect sqlAspect = org.teiid.designer.core.metamodel.aspect.sql.SqlAspectHelper.getSqlAspect(mRootTarget); if (sqlAspect != null && (sqlAspect instanceof SqlTableAspect)) { supportsUpdates = ((SqlTableAspect)sqlAspect).supportsUpdate(mRootTarget); } // Init query valid flags - will be set to false if problems. boolean selectValid = true; boolean insertValid = true; boolean updateValid = true; boolean deleteValid = true; // Reset Select selectValid = resetTransformation(mappingRoot, QueryValidator.SELECT_TRNS, qv); // Reset Insert, Update, Delete if (supportsUpdates) { // RESET INSERT insertValid = resetTransformation(mappingRoot, QueryValidator.INSERT_TRNS, qv); // RESET UPDATE updateValid = resetTransformation(mappingRoot, QueryValidator.UPDATE_TRNS, qv); // RESET DELETE deleteValid = resetTransformation(mappingRoot, QueryValidator.DELETE_TRNS, qv); } else { clearUUIDSqlString(mappingRoot, QueryValidator.INSERT_TRNS); clearUUIDSqlString(mappingRoot, QueryValidator.UPDATE_TRNS); clearUUIDSqlString(mappingRoot, QueryValidator.DELETE_TRNS); } // If any of the components have a problem, add to broken table list. if (!selectValid || !insertValid || !updateValid || !deleteValid) { brokenSqlTables.add(mRootTarget); } } } succeeded = true; } catch (ModelWorkspaceException e) { UiConstants.Util.log(e); } finally { if (requiredStart) { if (succeeded) { ModelerCore.commitTxn(); } else { ModelerCore.rollbackTxn(); } } // re-enable transformation notifications UiPlugin.getDefault().setIgnoreTransformationNotifications(false); } } return brokenSqlTables; } private boolean resetTransformation( final SqlTransformationMappingRoot mappingRoot, final int cmdType, final QueryValidator qv ) { String userSqlString = TransformationHelper.getSqlString(mappingRoot, cmdType); setUserString(mappingRoot, userSqlString, cmdType); TransformationMappingHelper.reconcileMappingsOnSqlChange(mappingRoot, null); QueryValidationResult result = qv.validateSql(userSqlString, cmdType, false); return result.isParsable() && result.isResolvable() && result.isValidatable(); } private void clearUUIDSqlString( final SqlTransformationMappingRoot mappingRoot, final int cmdType ) { if (mappingRoot != null) { MappingHelper helper = mappingRoot.getHelper(); if (helper != null && helper instanceof SqlTransformation) { SqlTransformation sqlHelper = (SqlTransformation)helper; switch (cmdType) { case QueryValidator.SELECT_TRNS: sqlHelper.setSelectSql(null); break; case QueryValidator.INSERT_TRNS: if (sqlHelper.isInsertAllowed() && !sqlHelper.isInsertSqlDefault()) { sqlHelper.setInsertSql(null); } break; case QueryValidator.UPDATE_TRNS: if (sqlHelper.isUpdateAllowed() && !sqlHelper.isUpdateSqlDefault()) { sqlHelper.setUpdateSql(null); } break; case QueryValidator.DELETE_TRNS: if (sqlHelper.isDeleteAllowed() && !sqlHelper.isDeleteSqlDefault()) { sqlHelper.setDeleteSql(null); } break; default: break; } } } } private void setUserString( final SqlTransformationMappingRoot mappingRoot, final String userSqlStr, final int cmdType ) { if (cmdType == QueryValidator.SELECT_TRNS) { TransformationHelper.setSelectSqlUserString(mappingRoot, userSqlStr, false, false, this); } else if (cmdType == QueryValidator.INSERT_TRNS) { TransformationHelper.setInsertSqlUserString(mappingRoot, userSqlStr, false, false, this); } else if (cmdType == QueryValidator.UPDATE_TRNS) { TransformationHelper.setUpdateSqlUserString(mappingRoot, userSqlStr, false, false, this); } else if (cmdType == QueryValidator.DELETE_TRNS) { TransformationHelper.setDeleteSqlUserString(mappingRoot, userSqlStr, false, false, this); } } public void warnUserAboutInvalidTransformations( List invalidSourceList ) { if (!invalidSourceList.isEmpty()) { String title = UiConstants.Util.getString("RevalidateModelTransformationsAction.invalidTransformationsTitle"); //$NON-NLS-1$ String msg = UiConstants.Util.getString("RevalidateModelTransformationsAction.invalidTransformationsMessage"); //$NON-NLS-1$ List copyOfList = new ArrayList(invalidSourceList.size()); for (Iterator iter = invalidSourceList.iterator(); iter.hasNext();) { Object nextObj = iter.next(); String path = ModelObjectUtilities.getTrimmedFullPath((EObject)nextObj); String name = ModelerCore.getModelEditor().getName((EObject)nextObj); String row = path + "/" + name; //$NON-NLS-1$ copyOfList.add(row); } ListMessageDialog.openWarning(Display.getCurrent().getActiveShell(), title, null, msg, copyOfList, null); } } @Override public int compareTo( Object o ) { if (o instanceof String) { return getText().compareTo((String)o); } if (o instanceof Action) { return getText().compareTo(((Action)o).getText()); } return 0; } @Override public boolean isApplicable( ISelection selection ) { boolean result = false; Object selectedObject = SelectionUtilities.getSelectedObject(selection); if (selectedObject instanceof IResource && ModelUtilities.isModelFile((IResource)selectedObject)) { try { this.modelResource = ModelUtil.getModelResource(((IFile)selectedObject), false); if (ModelUtilities.isVirtual(this.modelResource)) { result = true; } } catch (ModelWorkspaceException e) { UiConstants.Util.log(e); } } return result; } private void invalidateSqlRootCache( List mappingRoots ) { Object nextObj = null; for (Iterator iter = mappingRoots.iterator(); iter.hasNext();) { nextObj = iter.next(); if (nextObj instanceof SqlTransformationMappingRoot) { SqlTransformationMappingRoot mappingRoot = (SqlTransformationMappingRoot)nextObj; SqlMappingRootCache.invalidateSelectStatus(mappingRoot, false, this); } } } }