/* * 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.wizards; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Stack; import org.eclipse.core.resources.IFile; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.emf.ecore.EObject; import org.teiid.core.designer.ModelerCoreException; import org.teiid.designer.core.ModelerCore; import org.teiid.designer.core.util.NewModelObjectHelperManager; import org.teiid.designer.core.workspace.ModelResource; import org.teiid.designer.metamodels.core.AnnotationContainer; import org.teiid.designer.metamodels.relational.BaseTable; import org.teiid.designer.transformation.ui.UiConstants; import org.teiid.designer.transformation.util.TransformationHelper; import org.teiid.designer.ui.common.widget.InheritanceCheckboxTreeViewer; import org.teiid.designer.ui.viewsupport.ModelObjectUtilities; import org.teiid.designer.ui.wizards.ICheckboxTreeViewerListenerController; import org.teiid.designer.ui.wizards.StructuralCopyModelFeaturePopulator; /** * TransformationCopyModelFeaturePopulator * * @since 8.0 */ public class TransformationCopyModelFeaturePopulator extends StructuralCopyModelFeaturePopulator implements UiConstants { ////////////////////////////////////////////////////////////////////////////////////// // Instance variables ////////////////////////////////////////////////////////////////////////////////////// private Stack /*<List of EObject>*/ copies; private Stack /*<Integer>*/ curParentIndex; private Stack /*<List of Boolean>*/ skippingDescendants; private List /*<EObject>*/ copiedSiblings; ////////////////////////////////////////////////////////////////////////////////////// // Constructors ////////////////////////////////////////////////////////////////////////////////////// /** * Constructor * * @param sourceFile the source file */ public TransformationCopyModelFeaturePopulator(IFile sourceFile) { super(sourceFile); } /** * Constructor * * @param sourceFile the source file * @param listenerController controller for checkbox selection changes made * in the tree viewer */ public TransformationCopyModelFeaturePopulator(IFile sourceFile, ICheckboxTreeViewerListenerController listenerController) { super(sourceFile, listenerController); } ////////////////////////////////////////////////////////////////////////////////////// // Instance methods ////////////////////////////////////////////////////////////////////////////////////// /** * Overridden method from {@link StructuralCopyModelFeaturePopulator}. Copy * selected nodes of the source model to the target. Overridden because also * have to do transformations on tables and procedures. * * @param sourceModelResource modelResource containing the old information * @param targetResource the target * @param viewer the tree viewer; root is the ModelResource * @param extraProperties optional properties to tweak creation of objects. * Currently, this only deals with whether virtual tables have their supportsUpdate * properties cleared. See TransformationNewModelObjectHelper for details. * @param copyAllDescriptions option to copy or suppress copying all descriptions * @param monitor a progress monitor * @throws ModelerCoreException */ @Override public void copyModel(ModelResource sourceModelResource, ModelResource targetModelResource, InheritanceCheckboxTreeViewer viewer, Map extraProperties, boolean copyAllDescriptions, IProgressMonitor monitor) { // This method is being revoked due to inadequate design and implementation. throw new UnsupportedOperationException(); } /** * Overridden method from {@link StructuralCopyModelFeaturePopulator}. Copy * selected nodes of the source model to the target. Overridden because also * have to do transformations on tables and procedures. * * @param sourceModelResource modelResource containing the old information * @param targetResource the target * @param extraProperties optional properties to tweak creation of objects. * Currently, this only deals with whether virtual tables have their supportsUpdate * properties cleared. See TransformationNewModelObjectHelper for details. * @param copyAllDescriptions option to copy or suppress copying all descriptions * @param monitor a progress monitor * @throws ModelerCoreException */ @Override public void copyModel(ModelResource sourceModelResource, ModelResource targetModelResource, Map extraProperties, boolean copyAllDescriptions, IProgressMonitor monitor) throws ModelerCoreException { //Since we cannot modify the original list of children, we must make //a deep copy of the children. // Copy model description if( copyAllDescriptions ) { String desc = sourceModelResource.getDescription(); if( desc != null ) { targetModelResource.getModelAnnotation().setDescription(desc); } } List /*<EObject>*/ sourceFirstLevelChildren = sourceModelResource.getEObjects(); // JIRA Issue JBEDSP-249 - Remove the JDBC Source object when copying from Source to Virtual model // Remove the JDBC Source object int jdbcSourceIndex = -1; for( int i=0; i<sourceFirstLevelChildren.size(); i++ ) { EObject nextObj = (EObject)sourceFirstLevelChildren.get(i); if( ModelObjectUtilities.isJdbcSource(nextObj) ) { jdbcSourceIndex = i; break; } } if( jdbcSourceIndex > -1) { sourceFirstLevelChildren.remove(jdbcSourceIndex); } Collection /*<EObject>*/ sourceFirstLevelChildrenCopies = null; final Map originalsToCopies = new HashMap(); try { sourceFirstLevelChildrenCopies = ModelerCore.getModelEditor().copyAll( sourceFirstLevelChildren, originalsToCopies); } catch (ModelerCoreException ex) { throw ex; } //What we really need is not a map of originals to copies, but a map of //copies to originals. So create it. final Map copiesToOriginals = invertMap(originalsToCopies); //Allow for any nodes already inserted into the target List /*<EObject>*/targetFirstLevelChildren = targetModelResource.getEmfResource().getContents(); int numInitialFirstLevelNodes = targetFirstLevelChildren.size(); //Add the selected nodes to the target targetModelResource.getEmfResource().getContents().addAll(sourceFirstLevelChildrenCopies); //Do the transformations where needed List copiedFirstLevelChildrenList = targetModelResource.getEmfResource().getContents(); List modifiedCopiedFirstLevelChildrenList = new ArrayList( copiedFirstLevelChildrenList.size() - numInitialFirstLevelNodes); //Create a list of the first level nodes in the target, excluding nodes //that had already been inserted for (int i = numInitialFirstLevelNodes; i < copiedFirstLevelChildrenList.size(); i++) { modifiedCopiedFirstLevelChildrenList.add(copiedFirstLevelChildrenList.get(i)); } doTransformations(copiesToOriginals, modifiedCopiedFirstLevelChildrenList, extraProperties); if( copyAllDescriptions ) { copyDescriptions(copiesToOriginals, targetModelResource); } } private Map invertMap(Map originalsToCopies) { Map copiesToOriginals = new HashMap(); Iterator it = originalsToCopies.entrySet().iterator(); while (it.hasNext()) { Map.Entry me = (Map.Entry)it.next(); copiesToOriginals.put(me.getValue(), me.getKey()); } return copiesToOriginals; } /** * Do the transformations where needed. * * @param copiesToOriginals map of copied nodes to their originals * @param copiedFirstLevelEObjects the first level nodes of the target * @param clearSupportsUpdate whether to clear (set to false) the supportsUpdate * property of any copied tables. */ private void doTransformations( Map /*<EObject copied node to EObject original node>*/ copiesToOriginals, List /*<EObject>*/ copiedFirstLevelEObjects, Map extraProperties) { // Commit the current transaction at this point. This ensures that the new target // attributes can be found when the relational-procedure sql is validated. ModelerCore.commitTxn(); // Start a new transaction to set the new SQL /* * jh mod for 19567: * Check all the places this class is used to verify that we NEVER need this txn * to be undoable. */ ModelerCore.startTxn(false, false, "NewModel Transform - set the SQL",null); //$NON-NLS-1$ copies = new Stack(); curParentIndex = new Stack(); skippingDescendants = new Stack(); copiedSiblings = copiedFirstLevelEObjects; boolean done = false; // long starttime = System.currentTimeMillis(); // System.out.println("started making transformations at "+starttime); while (!done) { copies.push(copiedSiblings); //System.err.println("pushed copies, size is now " + copies.size()); List /*<Boolean>*/ descendantsToSkip = new ArrayList(copiedSiblings.size()); //See if any of current level of siblings need to have a transformation done. //Also, flag any nodes that had a transformation done-- we do not have to check //their descendants. int index = 0; while ((index < copiedSiblings.size()) && (!done)) { EObject curCopy = (EObject)copiedSiblings.get(index); EObject curOriginal = (EObject)copiesToOriginals.get(curCopy); boolean originalIsTable = org.teiid.designer.core.metamodel.aspect.sql.SqlAspectHelper.isTable(curOriginal); boolean copyIsTable = TransformationHelper.isVirtualSqlTable(curCopy); if (originalIsTable && (!copyIsTable)) { Util.log(IStatus.ERROR, Util.getString("TransformationCopyModelFeaturePopulator.doTransformationsInconsistencyError")); //$NON-NLS-1$ done = true; } else if (copyIsTable && (!originalIsTable)) { Util.log(IStatus.ERROR, Util.getString("TransformationCopyModelFeaturePopulator.doTransformationsInconsistencyError")); //$NON-NLS-1$ done = true; } else { boolean originalIsProcedure = false; boolean copyIsProcedure = false; if (!originalIsTable) { originalIsProcedure = org.teiid.designer.core.metamodel.aspect.sql.SqlAspectHelper.isProcedure(curOriginal); copyIsProcedure = TransformationHelper.isSqlProcedure( curCopy); } if (originalIsProcedure && (!copyIsProcedure)) { Util.log(IStatus.ERROR, Util.getString("TransformationCopyModelFeaturePopulator.doTransformationsInconsistencyError")); //$NON-NLS-1$ done = true; } else if (copyIsProcedure && (!originalIsProcedure)) { Util.log(IStatus.ERROR, Util.getString("TransformationCopyModelFeaturePopulator.doTransformationsInconsistencyError")); //$NON-NLS-1$ done = true; } else { boolean doTransformation = (originalIsTable || originalIsProcedure); Boolean skipDescendants = new Boolean(doTransformation); descendantsToSkip.add(skipDescendants); if (doTransformation) { try { NewModelObjectHelperManager.helpCreate(curCopy, extraProperties); } catch (ModelerCoreException err) { Util.log(IStatus.ERROR, Util.getString("TransformationCopyModelFeaturePopulator.doTransformationsHelpCreateError")); //$NON-NLS-1$ } TransformationHelper.createTransformation(curCopy, curOriginal); } } } index++; // System.out.println("made transformation #"+index); } skippingDescendants.push(descendantsToSkip); //Find the next node to process. boolean descendantsFound = getNextDescendantNodeOfSiblings(0, descendantsToSkip); while ((!done) && (!descendantsFound)) { //No descendant node found. See if we can find a sibling of an ancestor that //has descendants. if (copies.size() == 1) { done = true; } else { Integer prevChildIndexInteger = (Integer)curParentIndex.pop(); int prevChildIndex = prevChildIndexInteger.intValue(); //System.err.println("popped from curParentIndex, size is now " + curParentIndex.size()); copies.pop(); copiedSiblings = (List)copies.peek(); //System.err.println("popped from copies, size is now " + copies.size()); skippingDescendants.pop(); descendantsToSkip = (List)skippingDescendants.peek(); index = prevChildIndex + 1; //System.err.println("index set to value incremented from previous top of curParentIndex: " + index); descendantsFound = getNextDescendantNodeOfSiblings(index, descendantsToSkip); } } } // System.out.println("finished making transformations at "+new Date()+"; took "+(System.currentTimeMillis()-starttime)); } private boolean getNextDescendantNodeOfSiblings(int startingIndex, List /*<Boolean>*/ descendantsToSkip) { boolean descendantsFound = false; int index = startingIndex; int numCopiedSiblings = copiedSiblings.size(); while ((index < numCopiedSiblings) && (!descendantsFound)) { Boolean curSkipDescendantsBoolean = (Boolean)descendantsToSkip.get(index); boolean curSkipDescendants = curSkipDescendantsBoolean.booleanValue(); if (!curSkipDescendants) { EObject curCopy = (EObject)copiedSiblings.get(index); copiedSiblings = curCopy.eContents(); numCopiedSiblings = copiedSiblings.size(); //System.err.println("setting copiedSiblings to children of " + curCopy + ", numCopiedSiblings is " + numCopiedSiblings); curParentIndex.push(new Integer(index)); //String str = ""; //for (int i = 0; i < curParentIndex.size(); i++) { // Integer tempInteger = (Integer)curParentIndex.get(i); // str += " " + tempInteger.toString(); //} //System.err.println("pushed value of " + index + " onto curParentIndex, values are now " + str); descendantsFound = true; } index++; } return descendantsFound; } private void copyDescriptions(Map copiesToOriginals, ModelResource targetResource) throws ModelerCoreException { for( Object key : copiesToOriginals.keySet() ) { EObject eObj = (EObject)key; EObject originalEObj = (EObject)copiesToOriginals.get(key); String description = ModelerCore.getModelEditor().getDescription(originalEObj); if( description != null ) { ModelerCore.getModelEditor().setDescription(eObj, description); } } } }