/* * 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.mapping.ui.model; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.draw2d.geometry.Dimension; import org.eclipse.draw2d.geometry.Point; import org.eclipse.emf.common.notify.Notification; import org.eclipse.emf.ecore.EObject; import org.eclipse.swt.graphics.Image; import org.eclipse.xsd.XSDSimpleTypeDefinition; import org.teiid.core.designer.util.I18nUtil; import org.teiid.designer.core.ModelerCore; import org.teiid.designer.core.notification.util.NotificationUtilities; import org.teiid.designer.core.transaction.SourcedNotification; import org.teiid.designer.core.workspace.ModelResource; import org.teiid.designer.diagram.ui.DiagramUiConstants; import org.teiid.designer.diagram.ui.connection.NodeConnectionModel; import org.teiid.designer.diagram.ui.editor.DiagramEditor; import org.teiid.designer.diagram.ui.editor.DiagramEditorUtil; import org.teiid.designer.diagram.ui.editor.DiagramViewer; import org.teiid.designer.diagram.ui.model.DiagramModelNode; import org.teiid.designer.diagram.ui.notation.uml.model.UmlAttributeNode; import org.teiid.designer.diagram.ui.notation.uml.model.UmlClassifierContainerNode; import org.teiid.designer.diagram.ui.notation.uml.model.UmlClassifierNode; import org.teiid.designer.diagram.ui.part.DiagramEditPart; import org.teiid.designer.diagram.ui.util.DiagramEntityManager; import org.teiid.designer.diagram.ui.util.DiagramUiUtilities; import org.teiid.designer.mapping.factory.ModelMapperFactory; import org.teiid.designer.mapping.ui.PluginConstants; import org.teiid.designer.mapping.ui.UiConstants; import org.teiid.designer.mapping.ui.UiPlugin; import org.teiid.designer.mapping.ui.actions.MergeMappingClassesAction; import org.teiid.designer.mapping.ui.actions.SplitMappingClassAction; import org.teiid.designer.mapping.ui.connection.EnumeratedTypeLink; import org.teiid.designer.mapping.ui.connection.MappingLink; import org.teiid.designer.mapping.ui.diagram.MappingDiagramUtil; import org.teiid.designer.mapping.ui.editor.MappingAdapterFilter; import org.teiid.designer.mapping.ui.editor.MappingExtent; import org.teiid.designer.mapping.ui.editor.SummaryExtent; import org.teiid.designer.mapping.ui.util.MappingUiUtil; import org.teiid.designer.metamodels.diagram.Diagram; import org.teiid.designer.metamodels.transformation.InputBinding; import org.teiid.designer.metamodels.transformation.InputParameter; import org.teiid.designer.metamodels.transformation.InputSet; import org.teiid.designer.metamodels.transformation.MappingClass; import org.teiid.designer.metamodels.transformation.MappingClassColumn; import org.teiid.designer.metamodels.transformation.MappingClassSet; import org.teiid.designer.metamodels.transformation.StagingTable; import org.teiid.designer.transformation.ui.actions.TransformationSourceManager; import org.teiid.designer.transformation.ui.model.TransformationDiagramModelFactory; import org.teiid.designer.transformation.ui.model.TransformationNode; import org.teiid.designer.transformation.util.TransformationHelper; import org.teiid.designer.ui.viewsupport.ModelUtilities; import org.teiid.designer.xsd.util.ModelerXsdUtils; /** * MappingDiagramModelFactory * * @since 8.0 */ public class MappingDiagramModelFactory extends TransformationDiagramModelFactory { private static final String KEY_MAPPING_DIAGRAM_NAME = "DiagramNames.mappingDiagram"; //$NON-NLS-1$ private static final String THIS_CLASS = "MappingDiagramModelFactory"; //$NON-NLS-1$ // private String errorMessage; // private static DiagramFactory diagramFactory; static { // diagramFactory = DiagramFactory.eINSTANCE; } /** * Construct an instance of TransformModelFactory. */ public MappingDiagramModelFactory() { super(); super.setHideLinksAlways(true); } /** * Create a DiagramModelNode. */ @Override public DiagramModelNode createModel( Object baseObject ) { return null; } /** * Create a DiagramModelNode. */ @Override public DiagramModelNode createModel( Object baseObject, String sNotationId, IProgressMonitor monitor ) { setNotationId(sNotationId); // Return null if the baseObject is not a org.teiid.designer.metamodels.diagram.Diagram if (!(baseObject instanceof Diagram)) { return null; } Diagram diagram = (Diagram)baseObject; DiagramModelNode diagramModelNode = null; // Create the DiagramNode diagramModelNode = new MappingDiagramNode(diagram, UiConstants.Util.getString(KEY_MAPPING_DIAGRAM_NAME)); if (isDetailedDiagram(diagramModelNode)) { DiagramModelNode transDiagramNode = super.createModel(baseObject, sNotationId, monitor); diagramModelNode.addChildren(transDiagramNode.getChildren()); // We need to get the "Virtual" table and tell it to add Recursion here. DiagramModelNode baseVirtualTableNode = getBaseNode(diagramModelNode); if (baseVirtualTableNode != null) addRecursionImage(baseVirtualTableNode); addInputSet(baseVirtualTableNode, diagramModelNode); } // if it's not DETAILED, then we wait for the refresh() method from the MappingDiagramController to // call the refresh() method in this factory to do all the extent dirty work. return diagramModelNode; } private void addInputSet( DiagramModelNode baseVirtualTableNode, DiagramModelNode diagramNode ) { // Let's add the Input Set if it exists... DiagramModelNode tNode = super.getTransformationNode(diagramNode); MappingClass mappingClass = (MappingClass)baseVirtualTableNode.getModelObject(); if (tNode != null && mappingClass != null) { // EObject inputSet = mappingClass.getInputSet(); if (inputSet != null && getGenerator() != null) { DiagramModelNode inputSetModelNode = getGenerator().createModel(inputSet, (Diagram)diagramNode.getModelObject()); if (inputSetModelNode != null) { inputSetModelNode.setHideLocation(true); addEditInputSetImage(inputSetModelNode); diagramNode.addChild(inputSetModelNode); // TransformationLink sourceLink = getSourceConnectionModel(inputSetModelNode, tNode); // ((DiagramModelNode)sourceLink.getSourceNode()).addSourceConnection(sourceLink); // ((DiagramModelNode)sourceLink.getTargetNode()).addTargetConnection(sourceLink); // // if( UiConstants.Util.isDebugEnabled(DebugConstants.TX_DIAGRAM_MODEL_NODE)) { // String message = "Adding Connection \n" + sourceLink.toString(); //$NON-NLS-1$ // UiConstants.Util.print(DebugConstants.TX_DIAGRAM_MODEL_NODE, message); // } // // inputSetModelNode.updateAssociations(); // inputSetModelNode.updateAssociations(); } } } } private MappingLink getMappingLinkConnectionModel( DiagramModelNode sourceMappingClassNode, DiagramModelNode targetExtentNode ) { MappingLink association = new MappingLink(sourceMappingClassNode, targetExtentNode); return association; } private boolean isDetailedDiagram( DiagramModelNode diagramNode ) { if (diagramNode.getModelObject() instanceof Diagram) { if (((Diagram)diagramNode.getModelObject()).getType() != null && ((Diagram)diagramNode.getModelObject()).getType().equals(PluginConstants.MAPPING_TRANSFORMATION_DIAGRAM_TYPE_ID)) return true; } return false; } private boolean isDetailedDiagram( Diagram diagram ) { if (diagram.getType() != null && diagram.getType().equals(PluginConstants.MAPPING_TRANSFORMATION_DIAGRAM_TYPE_ID)) return true; return false; } private DiagramModelNode getBaseNode( DiagramModelNode diagramModelNode ) { // find the base virtual group object in this detailed diagram. EObject virtualGroupEObject = ((Diagram)diagramModelNode.getModelObject()).getTarget(); Iterator iter = diagramModelNode.getChildren().iterator(); DiagramModelNode nextNode = null; while (iter.hasNext()) { nextNode = (DiagramModelNode)iter.next(); if (nextNode.getModelObject().equals(virtualGroupEObject)) return nextNode; } return null; } private boolean isValidDiagram( DiagramModelNode diagramModelNode ) { boolean result = false; Diagram diagram = (Diagram)diagramModelNode.getModelObject(); if (diagram != null && diagram.getTarget() != null) { ModelResource mr = ModelUtilities.getModelResourceForModelObject(diagram); if (mr != null) { String type = diagram.getType(); if (type != null) { if (type.equals(PluginConstants.MAPPING_DIAGRAM_TYPE_ID) || type.equals(PluginConstants.MAPPING_TRANSFORMATION_DIAGRAM_TYPE_ID)) result = true; } } } return result; } /* (non-Javadoc) * @See org.teiid.designer.diagram.ui.model.DiagramModelFactory#notifyModel(org.eclipse.emf.common.notify.Notification) */ @Override public boolean notifyModel( Notification notification, DiagramModelNode diagramModelNode, String sDiagramTypeId ) { boolean currentDiagramOK = true; Diagram diagram = (Diagram)diagramModelNode.getModelObject(); if (currentDiagramRemoved(diagram)) currentDiagramOK = false; if (currentDiagramOK && isValidDiagram(diagramModelNode) && sourceIsNotThis(notification) && shouldHandleNotification(notification, diagramModelNode)) { boolean requiredStart = false; boolean succeeded = false; boolean handleConstruction = !DiagramEditorUtil.isDiagramUnderConstruction(diagram); try { if (handleConstruction) { DiagramEditorUtil.setDiagramUnderConstruction(diagram); } // ------------------------------------------------- // Let's wrap this in a transaction!!! that way all constructed objects and layout properties // will result in only one transaction? // ------------------------------------------------- requiredStart = ModelerCore.startTxn(false, false, "Update Mapping Diagram", this); //$NON-NLS-1$$ handleNotification(notification, diagramModelNode); succeeded = true; } catch (Exception ex) { UiConstants.Util.log(IStatus.ERROR, ex, ex.getClass().getName() + ":" + THIS_CLASS + ".notifyModel()"); //$NON-NLS-1$ //$NON-NLS-2$ } finally { if (requiredStart) { if (succeeded) { ModelerCore.commitTxn(); } else { ModelerCore.rollbackTxn(); } } if (handleConstruction) { DiagramEditorUtil.setDiagramConstructionComplete(diagram, true); } } } return currentDiagramOK; } private boolean shouldHandleNotification( Notification notification, DiagramModelNode diagramModelNode ) { boolean shouldHandle = false; Diagram currentDiagram = (Diagram)diagramModelNode.getModelObject(); boolean isDetailed = isDetailedDiagram(currentDiagram); ModelResource diagramMR = ModelUtilities.getModelResourceForModelObject(currentDiagram); if (diagramMR != null) { if (notification instanceof SourcedNotification) { Object source = ((SourcedNotification)notification).getSource(); if (source == null || !source.equals(this)) { Collection notifications = ((SourcedNotification)notification).getNotifications(); Iterator iter = notifications.iterator(); Notification nextNotification = null; while (iter.hasNext() && !shouldHandle) { nextNotification = (Notification)iter.next(); Object targetObject = ModelerCore.getModelEditor().getChangedObject(nextNotification); if (targetObject != null && targetObject instanceof EObject && !DiagramUiUtilities.isDiagramObject((EObject)targetObject)) { // If detailed, we can cross model resources, so we go ahead here. if (isDetailed) { shouldHandle = true; } else { // If notification is from another "model resource" we don't care for Coarse // Mapping diagram. All objects are in same model. // Check here if the targetObject and document have the same resource, then set to TRUE; ModelResource mr = ModelUtilities.getModelResourceForModelObject((EObject)targetObject); if (mr != null && mr.equals(diagramMR)) { shouldHandle = true; } } } } } } else { // SINGLE NOTIFICATION Object targetObject = ModelerCore.getModelEditor().getChangedObject(notification); if (targetObject != null && targetObject instanceof EObject && !DiagramUiUtilities.isDiagramObject((EObject)targetObject)) { // If detailed, we can cross model resources, so we go ahead here. if (isDetailed) { shouldHandle = true; } else { // If notification is from another "model resource" we don't care for Coarse // Mapping diagram. All objects are in same model. // Check here if the targetObject and document have the same resource, then set to TRUE; ModelResource mr = ModelUtilities.getModelResourceForModelObject((EObject)targetObject); if (mr != null && mr.equals(diagramMR)) { shouldHandle = true; } } } } } return shouldHandle; } @Override protected boolean currentDiagramRemoved( Diagram diagram ) { boolean isRemoved = false; if (diagram == null) isRemoved = true; else if (diagram.eResource() == null) { isRemoved = true; if (diagram.getTarget() != null && diagram.getTarget().eResource() != null) isRemoved = false; // check the eContainer. // if( diagram.eContainer() == null ) { // if( diagram.getType() != null && diagram.getType().equals(PluginConstants.MAPPING_TRANSFORMATION_DIAGRAM_TYPE_ID) ) // isRemoved = false; // else // isRemoved = true; // } } return isRemoved; } private boolean sourceIsNotThis( Notification notification ) { if (notification instanceof SourcedNotification) { Object source = ((SourcedNotification)notification).getSource(); if (source == null) return true; return !(source.equals(this)); } return true; } private void handleSingleNotification( Notification notification, DiagramModelNode transformationDiagramModelNode, Object source ) { if (!isDiagramNotifier(notification)) { if (NotificationUtilities.isAdded(notification)) { performAdd(notification, transformationDiagramModelNode, source); } else if (NotificationUtilities.isRemoved(notification)) { performRemove(notification, transformationDiagramModelNode); } else if (NotificationUtilities.isChanged(notification)) { performChange(notification, transformationDiagramModelNode); } } } /** * @param notification * @param transformationDiagramModelNode */ private void handleNotification( Notification notification, DiagramModelNode mappingDiagramModelNode ) { boolean isTransformation = isDetailedDiagram(mappingDiagramModelNode); if (notification instanceof SourcedNotification) { Object source = ((SourcedNotification)notification).getSource(); if (isTransformation) reconcileSourceTables(mappingDiagramModelNode); Collection notifications = ((SourcedNotification)notification).getNotifications(); Iterator iter = notifications.iterator(); while (iter.hasNext()) { handleSingleNotification((Notification)iter.next(), mappingDiagramModelNode, source); } // let's just update the T Node associations if (isTransformation) { DiagramModelNode transNode = getTransformationNode(mappingDiagramModelNode); if (transNode != null) transNode.updateAssociations(); } else { addLockedImages(mappingDiagramModelNode); } } else { if (isTransformation) reconcileSourceTables(mappingDiagramModelNode); handleSingleNotification(notification, mappingDiagramModelNode, null); // let's just update the T Node associations if (isTransformation) { DiagramModelNode transNode = getTransformationNode(mappingDiagramModelNode); if (transNode != null) transNode.updateAssociations(); } } } protected void performAdd( Notification notification, DiagramModelNode mappingDiagramModelNode, Object source ) { if (isDetailedDiagram(mappingDiagramModelNode)) super.performAdd(notification, mappingDiagramModelNode); EObject targetObject = getEObjectTarget(notification); // Need to tell the editor to tell the controller to refresh()! // we know that the object is not a child of a model resource !!!!! // Now we check to see if the target object is already in diagram DiagramModelNode targetNode = getModelNode(mappingDiagramModelNode, targetObject); if (targetNode != null && !(targetNode instanceof TransformationNode) && !isDetailedDiagram(mappingDiagramModelNode)) { if (isNestedClassifier(targetNode)) { // We have a match, get the added children and hand them off to the generator to construct // and add to this the corresponding targetNode EObject[] newChildren = NotificationUtilities.getAddedChildren(notification); for (int iChild = 0; iChild < newChildren.length; iChild++) { if (isDrawable(newChildren[iChild])) { DiagramModelNode newNode = getGenerator().createChildModel(targetNode, newChildren[iChild]); if (newChildren.length == 1 && newNode instanceof UmlAttributeNode && isValidRenameSource(source)) { // Need to force an Edit in place?? // Let's get it's edit part ((UmlAttributeNode)newNode).rename(); } } } targetNode.getParent().getParent().updateForChild(false); } else if (!isDetailedDiagram(mappingDiagramModelNode)) { EObject[] newChildren = NotificationUtilities.getAddedChildren(notification); for (int iChild = 0; iChild < newChildren.length; iChild++) { if (isDrawable(newChildren[iChild])) { DiagramModelNode newNode = getGenerator().createChildModel(targetNode, newChildren[iChild]); if (newChildren.length == 1 && newNode instanceof UmlAttributeNode && isValidRenameSource(source)) { // Need to force an Edit in place?? // Let's get it's edit part targetNode.updateForChild(false); ((UmlAttributeNode)newNode).rename(); } } } MappingDiagramUtil.layoutDiagram(mappingDiagramModelNode); } } else if (isDetailedDiagram(mappingDiagramModelNode) && targetObject instanceof MappingClassSet) { // Defect 22008: New InputSet Parameter Does Not Show In Diagram Until Diagram Is Refreshed // If this IS DETAILED, we have to cover the case where a New Input Set Parameter & Binding is created // Target Object is the MappingClassSet // New Value is an InputBinding // Get the Binding, get the InputSetParameter // Get it's parent, treat as target, then add a new child for it? (use code from TransformationDiagramModelFactory) EObject[] newChildren = NotificationUtilities.getAddedChildren(notification); if (newChildren.length > 0) { for (int i = 0; i < newChildren.length; i++) { if (newChildren[i] instanceof InputBinding) { InputParameter newInputParameter = ((InputBinding)newChildren[i]).getInputParameter(); if (newInputParameter != null) { InputSet inputSet = newInputParameter.getInputSet(); // InputSet available, get it's diagram node and reconcile! if (inputSet != null) { DiagramModelNode parentNode = getModelNode(mappingDiagramModelNode, inputSet); if (parentNode != null) { // ((UmlClassifierNode)parentNode).reconcile(); DiagramModelNode dNode = getGenerator().createChildModel(parentNode, newInputParameter); dNode.update(DiagramUiConstants.DiagramNodeProperties.CHILDREN); dNode.update(DiagramUiConstants.DiagramNodeProperties.LAYOUT); } } } } } } MappingDiagramUtil.layoutDiagram(mappingDiagramModelNode); } } private boolean isNestedClassifier( DiagramModelNode targetNode ) { if (targetNode.getParent() instanceof UmlClassifierContainerNode) return true; return false; } @Override protected void performRemove( Notification notification, DiagramModelNode mappingDiagramModelNode ) { if (isDetailedDiagram(mappingDiagramModelNode) && isRemovingSqlObjects(notification)) super.performRemove(notification, mappingDiagramModelNode); EObject targetObject = getEObjectTarget(notification); // Need to tell the editor to tell the controller to refresh()! if (isValidTarget(targetObject)) { // Adding/removing Mapping Classes for Coarse mode, is performed by the refresh() method // This really only updates existing mapping classes that have changed children. List diagramSourceEObjects = getDiagramEObjects(mappingDiagramModelNode); DiagramModelNode parentNode = null; DiagramModelNode removedNode = null; boolean childrenRemoved = false; EObject[] removedChildren = NotificationUtilities.getRemovedChildren(notification); for (int iChild = 0; iChild < removedChildren.length; iChild++) { if (diagramSourceEObjects.contains(removedChildren[iChild])) { // Do nothing here. Should be taken care of by refresh() method so the contents can be // reconciled with the document model. } else { removedNode = getModelNode(mappingDiagramModelNode, removedChildren[iChild]); if (removedNode != null) { parentNode = removedNode.getParent(); if (parentNode != null) { parentNode.removeChild(removedNode, false); childrenRemoved = true; DiagramModelNode topClassifierNode = DiagramUiUtilities.getTopClassifierParentNode(parentNode); if (topClassifierNode != null) { topClassifierNode.updateForChild(false); topClassifierNode.update(DiagramUiConstants.DiagramNodeProperties.SIZE); topClassifierNode.update(DiagramUiConstants.DiagramNodeProperties.CHILDREN); topClassifierNode.update(DiagramUiConstants.DiagramNodeProperties.LAYOUT); } } } } } if (childrenRemoved) MappingDiagramUtil.layoutDiagram(mappingDiagramModelNode, childrenRemoved); else MappingDiagramUtil.layoutDiagram(mappingDiagramModelNode); } } @Override protected void performChange( Notification notification, DiagramModelNode mappingDiagramModelNode ) { if (isDetailedDiagram(mappingDiagramModelNode)) super.performChange(notification, mappingDiagramModelNode); EObject targetObject = getEObjectTarget(notification); if (isValidTarget(targetObject)) { DiagramModelNode targetNode = getModelNode(mappingDiagramModelNode, targetObject); if (targetNode != null) { // If object's parent is in our current model // Assume this is a rename for now. getGenerator().performUpdate(targetNode, notification); addRecursionImage(targetNode); targetNode.update(DiagramUiConstants.DiagramNodeProperties.IMAGES); } } } public void updateNodes( Collection inputExtentList, // NO_UCD DiagramModelNode mappingDiagramModelNode ) { // Not implemented } public void removeNodes( Collection inputExtentList, // NO_UCD DiagramModelNode mappingDiagramModelNode ) { MappingExtent nextExtent = null; List removeList = new ArrayList(1); List extentList = new ArrayList(inputExtentList); Iterator iter = extentList.iterator(); while (iter.hasNext()) { nextExtent = (MappingExtent)iter.next(); DiagramModelNode existingMappingNode = getExtentNode(mappingDiagramModelNode, nextExtent.getMappingReference(), nextExtent.getMappingReference()); if (existingMappingNode != null) removeList.add(existingMappingNode); } if (!removeList.isEmpty()) mappingDiagramModelNode.removeChildren(removeList, false); } public void updateMappingLinks( Collection inputExtentList ) { // NO_UCD } private List getExistingMappingExtentNodes( DiagramModelNode mappingDiagramModelNode ) { if (mappingDiagramModelNode == null) return Collections.EMPTY_LIST; Iterator iter = mappingDiagramModelNode.getChildren().iterator(); List existingExtentNodes = new ArrayList(10); DiagramModelNode nextDMN = null; while (iter.hasNext()) { nextDMN = (DiagramModelNode)iter.next(); if (nextDMN instanceof MappingExtentNode) existingExtentNodes.add(nextDMN); } if (existingExtentNodes.isEmpty()) return Collections.EMPTY_LIST; return existingExtentNodes; } private List getExistingMappingExtents( DiagramModelNode mappingDiagramModelNode ) { if (mappingDiagramModelNode == null) return Collections.EMPTY_LIST; Iterator iter = mappingDiagramModelNode.getChildren().iterator(); List existingExtents = new ArrayList(10); DiagramModelNode nextDMN = null; while (iter.hasNext()) { nextDMN = (DiagramModelNode)iter.next(); if (nextDMN instanceof MappingExtentNode) existingExtents.add(((MappingExtentNode)nextDMN).getExtent()); } if (existingExtents.isEmpty()) return Collections.EMPTY_LIST; return existingExtents; } public int getNumberOfMappingExtents( Object mappingDiagramModelNode ) { int nExt = 0; Iterator iter = ((DiagramModelNode)mappingDiagramModelNode).getChildren().iterator(); DiagramModelNode nextDMN = null; while (iter.hasNext()) { nextDMN = (DiagramModelNode)iter.next(); if (nextDMN instanceof MappingExtentNode) nExt++; } return nExt; } /* (non-Javadoc) * @See org.teiid.designer.diagram.ui.model.DiagramModelFactory#refresh(org.teiid.designer.metamodels.diagram.Diagram) */ public void refresh( DiagramModelNode diagramModelNode, Diagram diagram, MappingAdapterFilter xmlFilter, boolean reconcileMappingClasses, IProgressMonitor monitor ) { // use the filter to get the Visible Mapping classes and extents. boolean showProgress = (monitor != null); if (diagram.getType() != null) { DiagramEditor editor = DiagramEditorUtil.getDiagramEditor(diagram); DiagramEditPart diagramEP = null; if (editor != null && editor.getDiagramViewer() != null) { ((MappingDiagramNode)diagramModelNode).setViewer(editor.getDiagramViewer()); diagramEP = (DiagramEditPart)editor.getDiagramViewer().getContents(); } // get DiagramEditPart and set it's construction state if (diagramEP != null) { diagramEP.setUnderConstruction(true); } if (diagram.getType().equals(PluginConstants.MAPPING_DIAGRAM_TYPE_ID)) { // we have a coarse Mapping here if (reconcileMappingClasses) { if (showProgress) { monitor.subTask("Reconciling Coarse Mapping Classes"); //$NON-NLS-1$ monitor.worked(20); } reconcileCoarseMappingClasses(diagramModelNode, diagram, xmlFilter); } if (showProgress) { monitor.subTask("Reconciling Coarse Extents"); //$NON-NLS-1$ monitor.worked(20); } List coarseExents = reconcileCoarseExtents(diagramModelNode, diagram, xmlFilter, monitor); if (showProgress) { monitor.subTask("Update Coarse Mapping Links"); //$NON-NLS-1$ monitor.worked(30); } updateCoarseMappingLinks(diagramModelNode, coarseExents); // only create XSD enumerated type diagram objects if we have a logical model type if (MappingUiUtil.isLogicalModelType(diagram)) { showEnumeratedTypes(diagramModelNode, diagram); } } else { removeStaleSourceNodeEntities(diagramModelNode); // DETAILED MAPPING HERE!! if (showProgress) { monitor.subTask("Reconciling Detailed Extents"); //$NON-NLS-1$ monitor.worked(35); } List detailedExents = reconcileDetailedExtents(diagramModelNode, diagram, xmlFilter); if (showProgress) { monitor.subTask("Update Detailed Mapping LInks"); //$NON-NLS-1$ monitor.worked(35); } updateDetailedMappingLinks(diagramModelNode, detailedExents); } // get DiagramEditPart and set it's construction state if (diagramEP != null) { diagramEP.constructionCompleted(false); } } } /** * Deletes all {@link EnumeratedTypeLink}s on the specified diagram. * * @param theDiagramModelNode the diagram on which all enumerated type links are being deleted * @since 5.0.2 */ private void deleteAllEnumeratedTypeLinks( DiagramModelNode theDiagramModelNode ) { List links = getCurrentEnumeratedTypeLinks(theDiagramModelNode); if (!links.isEmpty()) { List processedNodes = new ArrayList(); for (int numLinks = links.size(), i = 0; i < numLinks; ++i) { NodeConnectionModel link = (NodeConnectionModel)links.get(i); // delete source DiagramModelNode source = (DiagramModelNode)link.getSourceNode(); source.removeSourceConnection(link); if (!processedNodes.contains(source)) { processedNodes.add(source); source.updateAssociations(); } // delete target DiagramModelNode target = (DiagramModelNode)link.getTargetNode(); target.removeTargetConnection(link); if (!processedNodes.contains(target)) { processedNodes.add(target); target.updateAssociations(); } } } } /** * Creates diagram nodes for the enumerated types. * * @param theDiagramNode the diagram node where the enumerated type nodes will be contained * @param theDiagram the diagram * @since 5.0.2 */ private void showEnumeratedTypes( DiagramModelNode theDiagramNode, Diagram theDiagram ) { List mappingClassNodes = getCurrentMappingClassNodes(theDiagramNode); if (!mappingClassNodes.isEmpty()) { deleteAllEnumeratedTypeLinks(theDiagramNode); // key=XSDSimpleTypeDefinition, value=diagram node for the enumerated type Map typeNodeMap = new HashMap(); // if a mapping class a column that has a type that is an enumerated type create the // enumerated type diagram model node if necessary for (int size = mappingClassNodes.size(), i = 0; i < size; ++i) { DiagramModelNode mcModelNode = (DiagramModelNode)mappingClassNodes.get(i); MappingClass mappingClass = (MappingClass)mcModelNode.getModelObject(); List columns = mappingClass.getColumns(); // find mapping class columns that have a type that is an enumerated type if (!columns.isEmpty()) { // keep track of the types already processed for the current mapping class in order // to not create duplicate links List processedTypes = new ArrayList(); for (int numCols = columns.size(), j = 0; j < numCols; ++j) { MappingClassColumn col = (MappingClassColumn)columns.get(j); EObject type = col.getType(); if ((type instanceof XSDSimpleTypeDefinition) && ModelerXsdUtils.isEnumeratedType(type)) { DiagramModelNode node = null; // ensure only process type once for each mapping class if (!processedTypes.contains(type)) { processedTypes.add(type); // create model node for type if needed if (typeNodeMap.containsKey(type)) { node = (DiagramModelNode)typeNodeMap.get(type); } else { node = getGenerator().createModel(type, theDiagram); if (node != null) { typeNodeMap.put(type, node); } } // created diagram link between mapping class node and new enumerated type node if (node != null) { createEnumeratedTypeLink(node, mcModelNode); node.updateAssociations(); mcModelNode.updateAssociations(); } else { // should not happen if model factory is working String msgKey = I18nUtil.getPropertyPrefix(MappingDiagramModelFactory.class) + "enumeratedTypeModelNodeNotFound"; //$NON-NLS-1$ String msg = UiConstants.Util.getString(msgKey, ((XSDSimpleTypeDefinition)type).getName()); UiConstants.Util.log(IStatus.ERROR, msg); } } } } } } // add all new model nodes to the diagram if (!typeNodeMap.isEmpty()) { theDiagramNode.addChildren(new ArrayList(typeNodeMap.values())); } } } /** * Creates the diagram link object from the mapping class to the enumerated type. * * @param theEnumeratedType the enumerated type diagram model node * @param theMappingClass the mapping class diagram model node * @since 5.0.2 */ private void createEnumeratedTypeLink( DiagramModelNode theEnumeratedType, DiagramModelNode theMappingClass ) { EnumeratedTypeLink link = new EnumeratedTypeLink(theEnumeratedType, theMappingClass); ((DiagramModelNode)link.getSourceNode()).addSourceConnection(link); ((DiagramModelNode)link.getTargetNode()).addTargetConnection(link); } private void removeStaleSourceNodeEntities( DiagramModelNode diagramModelNode ) { DiagramEntityManager.cleanUpDiagram((Diagram)diagramModelNode.getModelObject()); } private MappingExtent getMatchingMappingExtent( List extentList, MappingExtent extent ) { Iterator iter = extentList.iterator(); MappingExtent nextExtent = null; while (iter.hasNext()) { nextExtent = (MappingExtent)iter.next(); if (extentsAreEqual(nextExtent, extent)) { return nextExtent; } } return null; } private List reconcileDetailedExtents( DiagramModelNode diagramModelNode, Diagram diagram, MappingAdapterFilter xmlFilter ) { List expectedExtents = new ArrayList(getAllDetailedExtents(diagram, xmlFilter)); List existingExtents = new ArrayList(getExistingMappingExtents(diagramModelNode)); List currentMappingExtentNodes = getExistingMappingExtentNodes(diagramModelNode); // create add and remove lists (try to do this all at once); List removeExtentList = new ArrayList(); List addExtentList = new ArrayList(); List updateExtentList = new ArrayList(); MappingExtent nextExtent = null; // Walk through existing extents and check to see if any don't belong anymore. Iterator iter = existingExtents.iterator(); while (iter.hasNext()) { nextExtent = (MappingExtent)iter.next(); // Do we have an extent already showing? if (!extentListContains(expectedExtents, nextExtent)) { removeExtentList.add(nextExtent); } else { // Need to add the "updated" or recent extent here, so we get the geometry right. MappingExtent updatedExtent = getMatchingMappingExtent(expectedExtents, nextExtent); if (updatedExtent != null) { updateExtentList.add(updatedExtent); } } } // remove old extents from existing list. iter = removeExtentList.iterator(); while (iter.hasNext()) existingExtents.remove(iter.next()); // Walk through expected extents and check to see if any don't exist yet. iter = expectedExtents.iterator(); while (iter.hasNext()) { nextExtent = (MappingExtent)iter.next(); // Do we have an extent already showing? if (!extentListContains(existingExtents, nextExtent)) addExtentList.add(nextExtent); } // Now we need to do the work here, remove old, and create new. if (!removeExtentList.isEmpty()) { List removeNodeList = new ArrayList(removeExtentList.size()); iter = removeExtentList.iterator(); MappingExtentNode nextNode = null; while (iter.hasNext()) { nextExtent = (MappingExtent)iter.next(); nextNode = getExtentNode(diagramModelNode, nextExtent, currentMappingExtentNodes); removeNodeList.add(nextNode); } if (!removeNodeList.isEmpty()) diagramModelNode.removeChildren(removeNodeList, false); } // Now we need to call "update" to update list if (!updateExtentList.isEmpty()) { iter = updateExtentList.iterator(); MappingExtentNode nextNode = null; while (iter.hasNext()) { nextExtent = (MappingExtent)iter.next(); nextNode = getExtentNode(diagramModelNode, nextExtent, currentMappingExtentNodes); updateExtentNode(nextNode, nextExtent); } } // Last we need to create new extents for the missing ones. if (!addExtentList.isEmpty()) { addExentNodes(diagramModelNode, addExtentList, null); } return expectedExtents; } private List reconcileCoarseExtents( DiagramModelNode diagramModelNode, Diagram diagram, MappingAdapterFilter xmlFilter, IProgressMonitor monitor ) { boolean showProgress = (monitor != null); if (showProgress) monitor.subTask("Getting all coarse extents from XmlFilter."); //$NON-NLS-1$ List expectedExtents = new ArrayList(getAllCoarseExtents(xmlFilter, monitor)); // Check if there are NO mapping classes, then set the expected list to EMPTY if (getCurrentMappingClasses(diagramModelNode).isEmpty()) { expectedExtents = Collections.EMPTY_LIST; } if (showProgress) monitor.subTask("Getting existing extents in diagram."); //$NON-NLS-1$ List existingExtents = new ArrayList(getExistingMappingExtents(diagramModelNode)); List currentMappingExtentNodes = getExistingMappingExtentNodes(diagramModelNode); // create add and remove lists (try to do this all at once); List removeExtentList = new ArrayList(); List addExtentList = new ArrayList(); List updateExtentList = new ArrayList(); MappingExtent nextExtent = null; if (showProgress) monitor.subTask("Find old extents"); //$NON-NLS-1$ // Walk through existing extents and check to see if any don't belong anymore. Iterator iter = existingExtents.iterator(); while (iter.hasNext()) { nextExtent = (MappingExtent)iter.next(); // Do we have an extent already showing? if (!extentListContains(expectedExtents, nextExtent)) { removeExtentList.add(nextExtent); } else { // Need to add the "updated" or recent extent here, so we get the geometry right. MappingExtent updatedExtent = getMatchingMappingExtent(expectedExtents, nextExtent); if (updatedExtent != null) { updateExtentList.add(updatedExtent); } } } if (showProgress) monitor.subTask("Find new extents"); //$NON-NLS-1$ // remove old extents from existing list. iter = removeExtentList.iterator(); while (iter.hasNext()) existingExtents.remove(iter.next()); // Walk through expected extents and check to see if any don't exist yet. /* * jh Lyran enh: I sense an issue here. If the basic logic does not recreate an Extent * when it already exists, will we fail to refresh the count on a SummaryExtent * when more expanding is done after it is first displayed? */ iter = expectedExtents.iterator(); while (iter.hasNext()) { nextExtent = (MappingExtent)iter.next(); // Do we have an extent already showing? if (!extentListContains(existingExtents, nextExtent)) addExtentList.add(nextExtent); } // Now we need to do the work here, remove old, and create new. if (showProgress) monitor.subTask("Remove old extents from diagram"); //$NON-NLS-1$ if (!removeExtentList.isEmpty()) { List removeNodeList = new ArrayList(removeExtentList.size()); iter = removeExtentList.iterator(); MappingExtentNode nextNode = null; while (iter.hasNext()) { nextExtent = (MappingExtent)iter.next(); nextNode = getExtentNode(diagramModelNode, nextExtent, currentMappingExtentNodes); removeNodeList.add(nextNode); } if (!removeNodeList.isEmpty()) diagramModelNode.removeChildren(removeNodeList, false); } if (showProgress) monitor.subTask("Update existing extents"); //$NON-NLS-1$ // Now we need to call "update" to update list if (!updateExtentList.isEmpty()) { iter = updateExtentList.iterator(); MappingExtentNode nextNode = null; while (iter.hasNext()) { nextExtent = (MappingExtent)iter.next(); nextNode = getExtentNode(diagramModelNode, nextExtent, currentMappingExtentNodes); updateExtentNode(nextNode, nextExtent); } } // Last we need to create new extents for the missing ones. if (!addExtentList.isEmpty()) { addExentNodes(diagramModelNode, addExtentList, monitor); } return expectedExtents; } private void reconcileCoarseMappingClasses( DiagramModelNode diagramModelNode, Diagram diagram, MappingAdapterFilter xmlFilter ) { /* * jh Lyra enh: Issue: do we need Lyra-specific behavior in this method????? */ // System.out.println("[MappingDiagramModelFactory.reconcileCoarseMappingClasses] TOP " ); List removeNodeList = new ArrayList(); List currentMappingClassNodes = getCurrentMappingClassNodes(diagramModelNode); List visibleMappingClasses = xmlFilter.getMappedClassifiers(); DiagramModelNode nextNode = null; Iterator iter = currentMappingClassNodes.iterator(); while (iter.hasNext()) { nextNode = (DiagramModelNode)iter.next(); if (!visibleMappingClasses.contains(nextNode.getModelObject())) { removeNodeList.add(nextNode); } } diagramModelNode.removeChildren(removeNodeList, false); boolean bDefaultFoldedState = MappingDiagramUtil.getCurrentMappingDiagramBehavior().getDefaultMappingClassFoldedState(); // System.out.println("[MappingDiagramModelFactory.reconcileCoarseMappingClasses] Retrieved DefaultFoldedState: " + // bDefaultFoldedState ); List addedNodes = new ArrayList(); List currentMappingClasses = getCurrentMappingClasses(diagramModelNode); iter = visibleMappingClasses.iterator(); while (iter.hasNext()) { Object nextObj = iter.next(); if (!currentMappingClasses.contains(nextObj)) { DiagramModelNode childModelNode = getGenerator().createModel(nextObj, diagram); if (childModelNode != null) { addedNodes.add(childModelNode); addRecursionImage(childModelNode); if (childModelNode instanceof UmlClassifierNode) { // System.out.println("[MappingDiagramModelFactory.reconcileCoarseMappingClasses] About to set a classifier's expanded state to: " // + bDefaultFoldedState ); // jhTODO Is this an issue? When can we turn this off so that we leave // MCs expanded as the user made them, rather than make them all // expand or collapse per the global derault? ((UmlClassifierNode)childModelNode).setExpandedState(!bDefaultFoldedState); } } } } diagramModelNode.addChildren(addedNodes); addLockedImages(diagramModelNode); } /** * Sets the column properties of this tree viewer. The properties must correspond with the columns of the tree control. They * are used to identify the column in a cell modifier. * * @param columnProperties the list of column properties * @since 3.1 */ private MappingExtentNode getDetailedExtentNode( DiagramModelNode diagramModelNode, EObject mappingReferenceEObject, EObject locationEObject ) { Iterator iter = getExistingMappingExtentNodes(diagramModelNode).iterator(); MappingExtentNode nextNode = null; while (iter.hasNext()) { nextNode = (MappingExtentNode)iter.next(); if (nextNode.getModelObject().equals(locationEObject) && nextNode.getExtent().getMappingReference() != null && nextNode.getExtent().getMappingReference().equals(mappingReferenceEObject)) { return nextNode; } } return null; } private MappingExtentNode getExtentNode( DiagramModelNode diagramModelNode, EObject mappingClassEObject, EObject locationEObject ) { Iterator iter = getExistingMappingExtentNodes(diagramModelNode).iterator(); MappingExtentNode nextNode = null; while (iter.hasNext()) { nextNode = (MappingExtentNode)iter.next(); // Defect 21744: adding null checks to avoid NPEs if (nextNode == null) { continue; } if (nextNode.getModelObject() == null) { continue; } if (nextNode.getMappingClass() == null) { continue; } // jh Lyra enh: if (nextNode instanceof SummaryExtentNode) { continue; } if (nextNode.getModelObject().equals(locationEObject) && nextNode.getMappingClass().equals(mappingClassEObject)) { return nextNode; } } return null; } private MappingExtentNode getSummaryExtentNode( DiagramModelNode diagramModelNode, EObject mappingClassEObject, EObject locationEObject ) { Iterator iter = getExistingMappingExtentNodes(diagramModelNode).iterator(); SummaryExtentNode seNode = null; while (iter.hasNext()) { Object oNextNode = iter.next(); if (oNextNode instanceof SummaryExtentNode) { seNode = (SummaryExtentNode)oNextNode; if (seNode.getModelObject().equals(locationEObject) && ((SummaryExtent)seNode.getExtent()).getMappingClasses().keySet().contains(mappingClassEObject)) { return seNode; } } } return null; } private MappingExtentNode getExtentNode( DiagramModelNode diagramModelNode, MappingExtent mappingExtent, List mappingExtentNodes ) { Iterator iter = mappingExtentNodes.iterator(); MappingExtentNode nextNode = null; while (iter.hasNext()) { nextNode = (MappingExtentNode)iter.next(); if (extentsAreEqual(nextNode.getExtent(), mappingExtent)) return nextNode; } return null; } private void updateExtentNode( MappingExtentNode extentNode, MappingExtent currentExtent ) { double zoomFactor = DiagramEditorUtil.getCurrentZoomFactor(); extentNode.setExtent(currentExtent); extentNode.setExtentPosition(0); int newH = (int)(currentExtent.getHeight() / zoomFactor); // defect 17002 - mapping extents would grow or shrink, depending on the zoom, as // the document tree is expanded/collapsed. The current node's width is already // set correctly from when the zoom factor was set. int oldW = extentNode.getWidth(); extentNode.setSize(new Dimension(oldW, newH)); } /** * Returns newly created and linked MappingExtentNode Note that the object still has to be added to a parent and the node's * updateAssociations() method has to be called to get the links to show up. * * @param diagramModelNode * @param currentExtent * @return */ private MappingExtentNode createExtentNode( DiagramModelNode diagramModelNode, MappingExtent currentExtent ) { MappingExtentNode mappingExtentNode = null; if (((Diagram)diagramModelNode.getModelObject()).getType() != null && ((Diagram)diagramModelNode.getModelObject()).getType().equals(PluginConstants.MAPPING_DIAGRAM_TYPE_ID)) { EObject mappingClassEObject = currentExtent.getMappingReference(); EObject locationEObject = currentExtent.getDocumentNodeReference(); DiagramModelNode mappingClassNode = getModelNode(diagramModelNode, mappingClassEObject); if (mappingClassNode != null) { mappingExtentNode = new MappingExtentNode(diagramModelNode, locationEObject, currentExtent, true); mappingExtentNode.setMappingClass(mappingClassEObject); mappingExtentNode.setParent(diagramModelNode); // Add link from MC to Extent MappingLink targetLink = getMappingLinkConnectionModel(mappingClassNode, mappingExtentNode); ((DiagramModelNode)targetLink.getSourceNode()).addSourceConnection(targetLink); ((DiagramModelNode)targetLink.getTargetNode()).addTargetConnection(targetLink); mappingClassNode.updateAssociations(); mappingExtentNode.updateAssociations(); } else { mappingExtentNode = new MappingExtentNode(diagramModelNode, locationEObject, currentExtent, true); // mappingExtentNode.setMappingClass(mappingClassEObject); mappingExtentNode.setParent(diagramModelNode); } } else { // DETAILED EObject mappingReference = currentExtent.getMappingReference(); EObject locationEObject = currentExtent.getDocumentNodeReference(); EObject mappingClassReference = null; if (mappingReference != null) mappingClassReference = mappingReference.eContainer(); // DiagramModelNode attributeNode = getModelNode(diagramModelNode, mappingReference); DiagramModelNode mappingClassNode = getModelNode(diagramModelNode, mappingClassReference); mappingExtentNode = new MappingExtentNode(diagramModelNode, locationEObject, currentExtent, false); mappingExtentNode.setParent(diagramModelNode); if (mappingClassNode != null) { // Add link from MC to Extent MappingLink targetLink = getMappingLinkConnectionModel(mappingClassNode, mappingExtentNode); ((DiagramModelNode)targetLink.getSourceNode()).addSourceConnection(targetLink); ((DiagramModelNode)targetLink.getTargetNode()).addTargetConnection(targetLink); mappingClassNode.updateAssociations(); mappingExtentNode.updateAssociations(); } } return mappingExtentNode; } /** * Returns newly created and linked SummaryExtentNode Note that the object still has to be added to a parent and the node's * updateAssociations() method has to be called to get the links to show up. * * @param diagramModelNode * @param currentExtent * @return */ private SummaryExtentNode createSummaryExtentNode( DiagramModelNode diagramModelNode, SummaryExtent currentExtent ) { SummaryExtentNode mappingExtentNode = null; if (((Diagram)diagramModelNode.getModelObject()).getType() != null && ((Diagram)diagramModelNode.getModelObject()).getType().equals(PluginConstants.MAPPING_DIAGRAM_TYPE_ID)) { EObject locationEObject = currentExtent.getDocumentNodeReference(); /* * jh Lyra ISSUE: fix this: For a Summary, there might be multiple MCs * BUT, we only wish to create a single SummaryExtentNode. Hmmmm.... * -- Create the single SummaryExtentNode * -- Leave 'setMappingClass( null ) * -- Create a MappingLink for each MC */ // jh: revision of this next line should be to test all mappingClassObjects in array // to see if one exists? No, I don't think so. By definition, shouldn't the // Summary extent appear whether or not its MCs are visible? So we must revise // with the goal of creating links WHEN the MC is visible. HashMap hmapMappingClasses = currentExtent.getMappingClasses(); if (hmapMappingClasses == null) { return null; } // create the SummaryExtentNode whether or not any of its MCs are in the diagram mappingExtentNode = new SummaryExtentNode(diagramModelNode, locationEObject, currentExtent, true); mappingExtentNode.setParent(diagramModelNode); mappingExtentNode.setMappingClasses(hmapMappingClasses); Iterator itMCs = hmapMappingClasses.keySet().iterator(); // walk this SummaryExtent's MCs, and create links to any that are visible: while (itMCs.hasNext()) { EObject nextMappingClassEObject = (EObject)itMCs.next(); DiagramModelNode nextMappingClassNode = getModelNode(diagramModelNode, nextMappingClassEObject); if (nextMappingClassNode != null) { // Create a link from each MC to the Extent MappingLink targetLink = getMappingLinkConnectionModel(nextMappingClassNode, mappingExtentNode); ((DiagramModelNode)targetLink.getSourceNode()).addSourceConnection(targetLink); ((DiagramModelNode)targetLink.getTargetNode()).addTargetConnection(targetLink); nextMappingClassNode.updateAssociations(); mappingExtentNode.updateAssociations(); } } } return mappingExtentNode; } private void addExentNodes( DiagramModelNode diagramModelNode, List newExtents, IProgressMonitor monitor ) { boolean showProgress = (monitor != null); List newChildren = new ArrayList(newExtents.size()); String message = null; int nExtents = newExtents.size(); Iterator iter = newExtents.iterator(); MappingExtent nextExtent = null; int iExtent = 0; while (iter.hasNext()) { if (showProgress) { if (iExtent % 10 == 0) { message = "Create node for missing extent " + iExtent + " of " + nExtents; //$NON-NLS-1$ //$NON-NLS-2$ monitor.subTask(message); } } nextExtent = (MappingExtent)iter.next(); // jh Lyra ISSUE: we could revise this to call the right create method: MappingExtentNode meNode = null; if (nextExtent instanceof SummaryExtent) { meNode = createSummaryExtentNode(diagramModelNode, (SummaryExtent)nextExtent); } else { meNode = createExtentNode(diagramModelNode, nextExtent); } if (meNode != null) { newChildren.add(meNode); } iExtent++; } if (showProgress) { message = "Adding " + newChildren.size() + " extent nodes to diagram."; //$NON-NLS-1$ //$NON-NLS-2$ monitor.subTask(message); } diagramModelNode.addChildren(newChildren); // call updateExtentNode and updateAssociations on each node. iter = newChildren.iterator(); MappingExtentNode nextNode = null; iExtent = 0; while (iter.hasNext()) { if (showProgress) { if (iExtent % 10 == 0) { message = "Updating extent " + iExtent + " of " + nExtents; //$NON-NLS-1$ //$NON-NLS-2$ monitor.subTask(message); } } nextNode = (MappingExtentNode)iter.next(); nextNode.updateAssociations(); updateExtentNode(nextNode, nextNode.getExtent()); iExtent++; } } private List getCurrentMappingClasses( DiagramModelNode diagramModelNode ) { Iterator iter = diagramModelNode.getChildren().iterator(); DiagramModelNode nextNode = null; List returnList = new ArrayList(); while (iter.hasNext()) { nextNode = (DiagramModelNode)iter.next(); if (nextNode instanceof UmlClassifierNode) { if (!MappingDiagramUtil.isInputSet(nextNode.getModelObject())) returnList.add(nextNode.getModelObject()); } } return returnList; } @Override protected void clearAllSourceNodes( DiagramModelNode transformationDiagramModelNode ) { EObject transformationEObject = TransformationSourceManager.getTransformationFromDiagram((Diagram)transformationDiagramModelNode.getModelObject()); Iterator iter = getCurrentSourceNodes(transformationDiagramModelNode).iterator(); DiagramModelNode nextSourceNode = null; while (iter.hasNext()) { nextSourceNode = (DiagramModelNode)iter.next(); if (!TransformationHelper.isSqlInputSet(nextSourceNode.getModelObject())) removeSourceTable(transformationEObject, transformationDiagramModelNode, nextSourceNode.getModelObject()); } } private List getCurrentMappingClassNodes( DiagramModelNode diagramModelNode ) { Iterator iter = diagramModelNode.getChildren().iterator(); DiagramModelNode nextNode = null; List returnList = new ArrayList(); while (iter.hasNext()) { nextNode = (DiagramModelNode)iter.next(); if (nextNode instanceof UmlClassifierNode) { if (!MappingDiagramUtil.isInputSet(nextNode.getModelObject())) returnList.add(nextNode); } } return returnList; } private List getAllCoarseExtents( MappingAdapterFilter xmlFilter, IProgressMonitor monitor ) { boolean showProgress = (monitor != null); List totalExtentList = new ArrayList(); if (showProgress) { monitor.subTask("Getting mapping classes from XmlFilter"); //$NON-NLS-1$ } // get the extents from the MappingAdapterFilter totalExtentList.addAll(xmlFilter.getCoarseMappingExtents(monitor)); return totalExtentList; } private List getAllDetailedExtents( Diagram diagram, MappingAdapterFilter xmlFilter ) { // THis diagram's target is assumed to be the mapping class MappingClass targetMappingClass = (MappingClass)diagram.getTarget(); List detailedExtentList = new ArrayList(xmlFilter.getDetailedMappingExtents(targetMappingClass)); return detailedExtentList; } // MAPPING LINK METHODS public void updateCoarseMappingLinks( DiagramModelNode mappingDiagramModelNode, List currentExtents ) { List realMappingLinks = getRealCoarseMappingLinks(mappingDiagramModelNode, currentExtents); /* * jh Lyra enh: I like this, pass the common list of Extents into both the original get...Links * method and the new getRealCoarseMappingLinksForSummaryExtents() method, * and the Summary method is the only one that pays attention to the Summary Extents. */ List realSummaryLinks = getRealCoarseMappingLinksForSummaryExtents(mappingDiagramModelNode, currentExtents); // now combind these two Lists ArrayList arylRealLinks = new ArrayList(); arylRealLinks.addAll(realMappingLinks); arylRealLinks.addAll(realSummaryLinks); List staleMappingLinks = getStaleMappingLinks(arylRealLinks, mappingDiagramModelNode); List updatedNodes = new ArrayList(cleanUpStaleMappingLinks(staleMappingLinks, mappingDiagramModelNode)); Iterator iter = arylRealLinks.iterator(); while (iter.hasNext()) { NodeConnectionModel nextAssociation = (NodeConnectionModel)iter.next(); if (!mappingLinkExists(mappingDiagramModelNode, nextAssociation)) { ((DiagramModelNode)nextAssociation.getSourceNode()).addSourceConnection(nextAssociation); ((DiagramModelNode)nextAssociation.getTargetNode()).addTargetConnection(nextAssociation); // Keep a list of new end nodes so we can tell them to fire // an updateAssociations() call... if (!updatedNodes.contains(nextAssociation.getSourceNode())) updatedNodes.add(nextAssociation.getSourceNode()); if (!updatedNodes.contains(nextAssociation.getTargetNode())) updatedNodes.add(nextAssociation.getTargetNode()); List labelNodes = nextAssociation.getLabelNodes(); if (labelNodes != null && !labelNodes.isEmpty()) { mappingDiagramModelNode.addChildren(labelNodes); } } } if (!updatedNodes.isEmpty()) { iter = updatedNodes.iterator(); DiagramModelNode nextNode = null; while (iter.hasNext()) { nextNode = (DiagramModelNode)iter.next(); nextNode.updateAssociations(); } } } public void updateDetailedMappingLinks( DiagramModelNode mappingDiagramModelNode, List currentExtents ) { List realMappingLinks = getRealDetailedMappingLinks(mappingDiagramModelNode, currentExtents); List staleMappingLinks = getStaleMappingLinks(realMappingLinks, mappingDiagramModelNode); List updatedNodes = new ArrayList(cleanUpStaleMappingLinks(staleMappingLinks, mappingDiagramModelNode)); Iterator iter = realMappingLinks.iterator(); while (iter.hasNext()) { NodeConnectionModel nextAssociation = (NodeConnectionModel)iter.next(); if (!mappingLinkExists(mappingDiagramModelNode, nextAssociation)) { ((DiagramModelNode)nextAssociation.getSourceNode()).addSourceConnection(nextAssociation); ((DiagramModelNode)nextAssociation.getTargetNode()).addTargetConnection(nextAssociation); // Keep a list of new end nodes so we can tell them to fire // an updateAssociations() call... if (!updatedNodes.contains(nextAssociation.getSourceNode())) updatedNodes.add(nextAssociation.getSourceNode()); if (!updatedNodes.contains(nextAssociation.getTargetNode())) updatedNodes.add(nextAssociation.getTargetNode()); List labelNodes = nextAssociation.getLabelNodes(); if (labelNodes != null && !labelNodes.isEmpty()) { mappingDiagramModelNode.addChildren(labelNodes); } } } if (!updatedNodes.isEmpty()) { iter = updatedNodes.iterator(); DiagramModelNode nextNode = null; while (iter.hasNext()) { nextNode = (DiagramModelNode)iter.next(); nextNode.updateAssociations(); } } } protected List getRealDetailedMappingLinks( DiagramModelNode mappingDiagramModelNode, List extentList ) { // THis method takes the coarse extent list, and creates a set of temporary MappingLinks // to compare to the existing ones on the diagram... List realMappingLinks = new ArrayList(); Iterator extentIter = extentList.iterator(); // Each coarse extent should have a MappingReference (Mapping Class) and a // Document reference (location) EObject nextMappingReference = null; EObject nextExtentLocation = null; MappingExtent nextExtent = null; DiagramModelNode mappingClassNode = null; DiagramModelNode extentNode = null; while (extentIter.hasNext()) { nextExtent = (MappingExtent)extentIter.next(); nextMappingReference = nextExtent.getMappingReference(); nextExtentLocation = nextExtent.getDocumentNodeReference(); if (nextMappingReference != null && nextExtentLocation != null) { mappingClassNode = DiagramUiUtilities.getDiagramModelNode(nextMappingReference.eContainer(), mappingDiagramModelNode); extentNode = getDetailedExtentNode(mappingDiagramModelNode, nextExtent.getMappingReference(), nextExtent.getDocumentNodeReference()); if (extentNode != null && mappingClassNode != null) { realMappingLinks.add(new MappingLink(mappingClassNode, extentNode)); } } } return realMappingLinks; } protected List getRealCoarseMappingLinks( DiagramModelNode mappingDiagramModelNode, List extentList ) { // THis method takes the coarse extent list, and creates a set of temporary MappingLinks // to compare to the existing ones on the diagram... List realMappingLinks = new ArrayList(); Iterator extentIter = extentList.iterator(); // Each coarse extent should have a MappingReference (Mapping Class) and a // Document reference (location) EObject nextMappingClass = null; EObject nextExtentLocation = null; MappingExtent nextExtent = null; DiagramModelNode mappingClassNode = null; DiagramModelNode extentNode = null; while (extentIter.hasNext()) { nextExtent = (MappingExtent)extentIter.next(); // this method should NOT process SummaryExtents if (nextExtent instanceof SummaryExtent) { continue; } nextMappingClass = nextExtent.getMappingReference(); nextExtentLocation = nextExtent.getDocumentNodeReference(); if (nextMappingClass != null && nextExtentLocation != null) { mappingClassNode = DiagramUiUtilities.getDiagramModelNode(nextMappingClass, mappingDiagramModelNode); extentNode = getExtentNode(mappingDiagramModelNode, nextExtent.getMappingReference(), nextExtent.getDocumentNodeReference()); if (extentNode != null && mappingClassNode != null) { realMappingLinks.add(new MappingLink(mappingClassNode, extentNode)); } } } return realMappingLinks; } protected List getRealCoarseMappingLinksForSummaryExtents( DiagramModelNode mappingDiagramModelNode, List extentList ) { /* * new code for jh Lyra enh: * Should we use this new method to handle Links for Summary Extents, * Or should we just go ahead and create them in the getAllCoarseExtents() method? */ // THis method takes the coarse extent list, and creates a set of temporary MappingLinks // to compare to the existing ones on the diagram... List realMappingLinks = new ArrayList(); Iterator extentIter = extentList.iterator(); // Each coarse extent should have a MappingReference (Mapping Class) and a // Document reference (location) EObject nextMappingClass = null; EObject nextExtentLocation = null; MappingExtent nextExtent = null; SummaryExtent nextSummaryExtent = null; DiagramModelNode mappingClassNode = null; DiagramModelNode extentNode = null; while (extentIter.hasNext()) { nextExtent = (MappingExtent)extentIter.next(); // this method only processes SummaryExtents if (nextExtent instanceof SummaryExtent) { nextSummaryExtent = (SummaryExtent)nextExtent; nextExtentLocation = nextExtent.getDocumentNodeReference(); HashMap hmapMappingClasses = nextSummaryExtent.getMappingClasses(); Iterator itMCs = hmapMappingClasses.keySet().iterator(); while (itMCs.hasNext()) { nextMappingClass = (EObject)itMCs.next(); if (nextMappingClass != null && nextExtentLocation != null) { // get any existing node from the diagram mappingClassNode = DiagramUiUtilities.getDiagramModelNode(nextMappingClass, mappingDiagramModelNode); extentNode = getSummaryExtentNode(mappingDiagramModelNode, nextMappingClass, nextExtentLocation); // if both of those nodes exist, add a new MappingLink node to our collection of links if (extentNode != null && mappingClassNode != null) { realMappingLinks.add(new MappingLink(mappingClassNode, extentNode)); } } } } } return realMappingLinks; } protected List getStaleMappingLinks( List expectedMappingLinks, DiagramModelNode diagramModelNode ) { List staleAssociations = new ArrayList(); // get all connections from model // walk through expected associations. Iterator iter = getCurrentMappingLinks(diagramModelNode).iterator(); Iterator expectedIter = null; MappingLink nextCurrentAssociation = null; MappingLink nextExpectedAssociation = null; boolean foundMatch = false; while (iter.hasNext()) { foundMatch = false; nextCurrentAssociation = (MappingLink)iter.next(); expectedIter = expectedMappingLinks.iterator(); while (expectedIter.hasNext() && !foundMatch) { nextExpectedAssociation = (MappingLink)expectedIter.next(); if (associationsMatch(nextExpectedAssociation, nextCurrentAssociation)) { foundMatch = true; } } if (!foundMatch) { staleAssociations.add(nextCurrentAssociation); } } return staleAssociations; } protected boolean mappingLinkExists( DiagramModelNode diagramModelNode, NodeConnectionModel targetAssociation ) { // get all connections from model List currentChildren = diagramModelNode.getChildren(); Iterator iter = currentChildren.iterator(); while (iter.hasNext()) { DiagramModelNode childModelNode = (DiagramModelNode)iter.next(); List sourceConnections = childModelNode.getSourceConnections(); // Walk through the source connections and check if the same info. NodeConnectionModel nextAssociation = null; Iterator sIter = sourceConnections.iterator(); while (sIter.hasNext()) { nextAssociation = (NodeConnectionModel)sIter.next(); if (associationsMatch(targetAssociation, nextAssociation)) return true; } // Walk through the target connections and check if the same info. List targetConnections = childModelNode.getTargetConnections(); sIter = targetConnections.iterator(); while (sIter.hasNext()) { nextAssociation = (NodeConnectionModel)sIter.next(); if (associationsMatch(targetAssociation, nextAssociation)) return true; } } return false; } protected List cleanUpStaleMappingLinks( List staleLinks, DiagramModelNode diagramModelNode ) { List updatedNodes = new ArrayList(); Iterator iter = staleLinks.iterator(); NodeConnectionModel nextLink = null; while (iter.hasNext()) { nextLink = (NodeConnectionModel)iter.next(); if (nextLink instanceof MappingLink) { ((DiagramModelNode)nextLink.getSourceNode()).removeSourceConnection(nextLink); ((DiagramModelNode)nextLink.getTargetNode()).removeTargetConnection(nextLink); if (!updatedNodes.contains(nextLink.getSourceNode())) updatedNodes.add(nextLink.getSourceNode()); if (!updatedNodes.contains(nextLink.getTargetNode())) updatedNodes.add(nextLink.getTargetNode()); } } return updatedNodes; } protected List getCurrentMappingLinks( DiagramModelNode diagramModelNode ) { List currentAssociations = new ArrayList(); Iterator iter = diagramModelNode.getChildren().iterator(); while (iter.hasNext()) { DiagramModelNode childModelNode = (DiagramModelNode)iter.next(); List sourceConnections = childModelNode.getSourceConnections(); // Walk through the source connections and check if the same info. NodeConnectionModel nextAssociation = null; Iterator sIter = sourceConnections.iterator(); while (sIter.hasNext()) { nextAssociation = (NodeConnectionModel)sIter.next(); if (nextAssociation instanceof MappingLink && !currentAssociations.contains(nextAssociation)) currentAssociations.add(nextAssociation); } // Walk through the target connections and check if the same info. List targetConnections = childModelNode.getTargetConnections(); sIter = targetConnections.iterator(); while (sIter.hasNext()) { nextAssociation = (NodeConnectionModel)sIter.next(); if (nextAssociation instanceof MappingLink && !currentAssociations.contains(nextAssociation)) currentAssociations.add(nextAssociation); } } return currentAssociations; } /** * Obtain all the {@link EnumeratedTypeLink}s currently on the diagram. * * @param theDiagramModelNode the diagram whose enumerated type links are being requested * @return the links * @since 5.0.2 */ private List getCurrentEnumeratedTypeLinks( DiagramModelNode theDiagramModelNode ) { List associations = new ArrayList(); Iterator itr = theDiagramModelNode.getChildren().iterator(); while (itr.hasNext()) { DiagramModelNode child = (DiagramModelNode)itr.next(); // Walk through the source connections NodeConnectionModel nextAssociation = null; Iterator connectionItr = child.getSourceConnections().iterator(); while (connectionItr.hasNext()) { nextAssociation = (NodeConnectionModel)connectionItr.next(); if ((nextAssociation instanceof EnumeratedTypeLink) && !associations.contains(nextAssociation)) { associations.add(nextAssociation); } } // Walk through the target connections connectionItr = child.getTargetConnections().iterator(); while (connectionItr.hasNext()) { nextAssociation = (NodeConnectionModel)connectionItr.next(); if ((nextAssociation instanceof EnumeratedTypeLink) && !associations.contains(nextAssociation)) { associations.add(nextAssociation); } } } return associations; } public void resetExtentLocations( DiagramModelNode mappingDiagramModelNode, Diagram diagram, MappingAdapterFilter xmlFilter, int newY ) { if (diagram.getType() != null) { DiagramEditPart diagramEP = null; DiagramViewer viewer = ((MappingDiagramNode)mappingDiagramModelNode).getViewer(); if (viewer != null) { diagramEP = (DiagramEditPart)viewer.getContents(); } // get DiagramEditPart and set it's construction state if (diagramEP != null) { diagramEP.setUnderConstruction(true); } // use the filter to get the Visible Mapping classes and extents. if (diagram.getType().equals(PluginConstants.MAPPING_DIAGRAM_TYPE_ID)) { // we have a coarse Mapping here ((MappingDiagramNode)mappingDiagramModelNode).setCurrentYOrigin(newY); resetExtents(mappingDiagramModelNode, newY); } else { // DETAILED MAPPING HERE!! ((MappingDiagramNode)mappingDiagramModelNode).setCurrentYOrigin(newY); resetExtents(mappingDiagramModelNode, newY); } // get DiagramEditPart and set it's construction state if (diagramEP != null) { diagramEP.constructionCompleted(false); } } } private boolean extentsAreEqual( MappingExtent extent1, MappingExtent extent2 ) { boolean result = false; if ((extent1.getDocumentNodeReference() != null && extent2.getDocumentNodeReference() != null && extent1.getDocumentNodeReference().equals(extent2.getDocumentNodeReference()))) { if ((extent1.getMappingReference() != null && extent2.getMappingReference() != null && extent1.getMappingReference().equals(extent2.getMappingReference()))) result = true; else if (extent1.getMappingReference() == null) result = true; } else if (extent1.getDocumentNodeReference() == null && extent2.getDocumentNodeReference() == null) { if ((extent1.getMappingReference() != null && extent2.getMappingReference() != null && extent1.getMappingReference().equals(extent2.getMappingReference()))) result = true; } return result; } private boolean extentListContains( List extentList, MappingExtent extent ) { Iterator iter = extentList.iterator(); MappingExtent nextExtent = null; while (iter.hasNext()) { nextExtent = (MappingExtent)iter.next(); if (extentsAreEqual(extent, nextExtent)) return true; } return false; } private void resetExtents( DiagramModelNode mappingDiagramModelNode, int newY ) { Iterator iter = getExistingMappingExtentNodes(mappingDiagramModelNode).iterator(); MappingExtentNode nextExtentNode = null; while (iter.hasNext()) { nextExtentNode = (MappingExtentNode)iter.next(); if (nextExtentNode != null) { nextExtentNode.setExtentPosition(newY); } } } private void addRecursionImage( DiagramModelNode diagramNode ) { if (diagramNode instanceof UmlClassifierNode && diagramNode.getModelObject() instanceof MappingClass) { MappingClass mc = (MappingClass)diagramNode.getModelObject(); if (mc.isRecursionAllowed()) { Image image = UiPlugin.getDefault().getImage(UiConstants.Images.RECURSION_IMAGE); if (image != null) { diagramNode.setFirstOverlayImage(image, PluginConstants.RECURSION_EDITOR_ID); } } else { diagramNode.setFirstOverlayImage(null, null); } } } private void addEditInputSetImage( DiagramModelNode diagramNode ) { // Image image = UiPlugin.getDefault().getImage(UiConstants.Images.EDIT_OBJECT_ICON); // if (image != null) diagramNode.setFirstOverlayImage(image, PluginConstants.INPUT_SET_EDITOR_ID); } /** * Method which determines whether this EObject can be represented in a diagram or not. * * @return boolean */ @Override public boolean isDrawable( EObject object ) { boolean bResult = true; if (ModelMapperFactory.isXmlTreeNode(object)) { bResult = false; } return bResult; } /** * @see java.lang.Object#toString() * @since 4.2 */ @Override public String toString() { return "MappingDiagamModelFactory()"; //$NON-NLS-1$ } /** * @see org.teiid.designer.transformation.ui.model.TransformationDiagramModelFactory#addSourceTable(org.eclipse.emf.ecore.EObject, * org.teiid.designer.diagram.ui.model.DiagramModelNode, org.eclipse.emf.ecore.EObject) * @since 4.2 */ @Override public void addSourceTable( EObject transformationEObject, DiagramModelNode transformationDiagramModelNode, EObject sourceEObject ) { super.addSourceTable(transformationEObject, transformationDiagramModelNode, sourceEObject); // This override method allows the factory to check if the added table is a Staging table and locate it's initial position // better. if (sourceEObject instanceof StagingTable) { DiagramModelNode dmn = getStagingTableNode(transformationDiagramModelNode, sourceEObject); DiagramModelNode tNode = getTransformationNode(transformationDiagramModelNode); Point tNodePos = tNode.getPosition(); if (dmn != null) { Point newPosition = new Point(tNodePos.x + tNode.getWidth() + 40, tNodePos.y + tNode.getHeight() + 40); dmn.setPosition(newPosition); // dmn.update(DiagramUiConstants.DiagramNodePropertis.LOCATION); } } } private DiagramModelNode getStagingTableNode( DiagramModelNode transformationDiagramModelNode, EObject sourceEObject ) { Collection contents = transformationDiagramModelNode.getChildren(); Iterator iter = contents.iterator(); Object nextChild = null; while (iter.hasNext()) { nextChild = iter.next(); if (nextChild instanceof DiagramModelNode && nextChild instanceof UmlClassifierNode) { EObject nodeEObject = ((DiagramModelNode)nextChild).getModelObject(); if (nodeEObject == sourceEObject) { return (DiagramModelNode)nextChild; } } } return null; } private boolean isValidRenameSource( Object source ) { if (source != null && (source instanceof MergeMappingClassesAction || source instanceof SplitMappingClassAction)) { return false; } return true; } }