/* * 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.editor; import java.util.Collection; import java.util.Iterator; import org.eclipse.emf.common.notify.Notification; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.mapping.Mapping; import org.eclipse.emf.mapping.MappingHelper; import org.teiid.designer.core.ModelerCore; import org.teiid.designer.core.notification.util.IgnorableNotificationSource; 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.model.DiagramModelNode; import org.teiid.designer.diagram.ui.util.DiagramUiUtilities; import org.teiid.designer.mapping.factory.IMappableTree; import org.teiid.designer.metamodels.diagram.Diagram; import org.teiid.designer.metamodels.transformation.MappingClass; import org.teiid.designer.metamodels.transformation.MappingClassColumn; import org.teiid.designer.metamodels.transformation.MappingClassObject; import org.teiid.designer.metamodels.transformation.MappingClassSet; import org.teiid.designer.metamodels.transformation.TransformationMappingRoot; import org.teiid.designer.ui.viewsupport.ModelUtilities; /** * DocumentNotificationHandler * * @since 8.0 */ public class DocumentNotificationHandler { private static final String[] notificationTypes = {"CREATE", //$NON-NLS-1$ "SET", //$NON-NLS-1$ "UNSET", //$NON-NLS-1$ "ADD", //$NON-NLS-1$ "REMOVE", //$NON-NLS-1$ "ADD_MANY", //$NON-NLS-1$ "REMOVE_MANY", //$NON-NLS-1$ "MOVE", //$NON-NLS-1$ "REMOVING_ADAPTER", //$NON-NLS-1$ "RESOLVE" //$NON-NLS-1$ }; // ///////////////////////////////////////////////////////////////////////////////////////////// // FIELDS // ///////////////////////////////////////////////////////////////////////////////////////////// private MappingDiagramController mappingDiagramController; private IMappableTree mappableTree; // private boolean logDebug = false; /** * Construct an instance of DocumentNotificationHandler. */ public DocumentNotificationHandler( MappingDiagramController controller, IMappableTree theTree ) { super(); mappingDiagramController = controller; mappableTree = theTree; } public void handleNotification( Notification notification ) { // logDebug = false; boolean somethingChanged = false; boolean ignoreNotification = (notification instanceof SourcedNotification) && ((SourcedNotification)notification).getSource() instanceof IgnorableNotificationSource; if (!ignoreNotification) { if (notification instanceof SourcedNotification) { if (((SourcedNotification)notification).getSource() != mappingDiagramController) { Collection notifications = ((SourcedNotification)notification).getNotifications(); Iterator iter = notifications.iterator(); boolean singleChange = false; while (iter.hasNext()) { singleChange = handleSingleNotification((Notification)iter.next()); if (!somethingChanged && singleChange) somethingChanged = true; } } } else { somethingChanged = handleSingleNotification(notification); } } if (somethingChanged && shouldRefreshDiagram(notification)) { mappingDiagramController.refresh(true); } } private boolean shouldHandleMappingClassSet( MappingClassSet theMappingClassSet ) { return theMappingClassSet.getTarget().equals(mappableTree.getTreeRoot()); } private boolean isMappingObject( EObject eObject ) { boolean result = false; if (eObject instanceof Mapping || eObject instanceof MappingClass || eObject instanceof MappingClassColumn || eObject instanceof MappingClassSet || eObject instanceof MappingHelper) result = true; return result; } // should not be called with SourcedNotification public boolean shouldHandleNotification( Notification notification ) { boolean result = false; boolean isDiagramObject = false; if (NotificationUtilities.isEObjectNotifier(notification)) { EObject notifier = (EObject)ModelerCore.getModelEditor().getChangedObject(notification); isDiagramObject = DiagramUiUtilities.isDiagramObject(notifier); if (!isDiagramObject) { if (mappableTree.isAncestorOf(mappableTree.getTreeRoot(), notifier)) { // node is ancestor of tree root result = true; } else { // if node or ancestor is MappingClassSet whose target is tree root EObject parent = notifier.eContainer(); if (notifier instanceof MappingClassSet) { result = shouldHandleMappingClassSet((MappingClassSet)notifier); } else if (notifier instanceof MappingClassObject && parent != null && parent instanceof MappingClassSet) { result = shouldHandleMappingClassSet((MappingClassSet)notifier.eContainer()); } else if (notifier instanceof MappingClassColumn) { result = true; } else if (parent instanceof MappingClassObject && parent.eContainer() != null) { result = shouldHandleMappingClassSet((MappingClassSet)parent.eContainer()); } else if (parent instanceof Mapping) { result = true; } } } } return result; } // ------------------------------------------------------------------ // private helper methods. // ------------------------------------------------------------------ // should not be called with SourcedNotification private boolean handleSingleNotification( Notification notification ) { boolean result = false; if (shouldHandleNotification(notification)) { if (NotificationUtilities.isAdded(notification)) { result = performAdd(notification); } else if (NotificationUtilities.isRemoved(notification)) { result = performRemove(notification); } else if (NotificationUtilities.isChanged(notification)) { result = performChange(notification); } } return result; } private boolean performAdd( Notification notification ) { boolean somethingChanged = false; Object targetObject = ModelerCore.getModelEditor().getChangedObject(notification); if (targetObject != null && targetObject instanceof EObject) { // we know that the object is not a child of a model resource !!!!! if ((targetObject instanceof MappingClassSet) && shouldHandleMappingClassSet((MappingClassSet)targetObject)) { somethingChanged = true; } else { mappingDiagramController.getDocumentTreeController().getViewer().refresh(targetObject, true); somethingChanged = true; } } return somethingChanged; } private boolean performRemove( Notification notification ) { boolean somethingChanged = false; Object targetObject = ModelerCore.getModelEditor().getChangedObject(notification); if (targetObject != null && targetObject instanceof EObject) { // we know that the object is not a child of a model resource !!!!! if ((targetObject instanceof MappingClassSet) && shouldHandleMappingClassSet((MappingClassSet)targetObject)) { somethingChanged = true; } else if (targetObject instanceof Mapping) { somethingChanged = true; } else if ((targetObject instanceof MappingClass) || (targetObject instanceof MappingClassColumn)) { somethingChanged = true; } else { mappingDiagramController.getDocumentTreeController().getViewer().refresh(targetObject, true); somethingChanged = true; } } return somethingChanged; } private boolean performChange( Notification notification ) { boolean somethingChanged = false; Object targetObject = ModelerCore.getModelEditor().getChangedObject(notification); if (targetObject != null && targetObject instanceof EObject) { if ((targetObject instanceof MappingClassSet) && shouldHandleMappingClassSet((MappingClassSet)targetObject)) { somethingChanged = true; } else if (isMappingObject((EObject)targetObject)) { somethingChanged = true; } else { mappingDiagramController.getDocumentTreeController().getViewer().refresh(targetObject, true); somethingChanged = true; } } return somethingChanged; } private boolean shouldRefreshDiagram( Notification notification ) { boolean shouldRefresh = false; ModelResource documentMR = mappingDiagramController.getCurrentModelResource(); if (documentMR != null) { if (notification instanceof SourcedNotification) { Collection notifications = ((SourcedNotification)notification).getNotifications(); Iterator iter = notifications.iterator(); Notification nextNotification = null; while (iter.hasNext() && !shouldRefresh) { nextNotification = (Notification)iter.next(); Object targetObject = ModelerCore.getModelEditor().getChangedObject(nextNotification); if (targetObject != null && targetObject instanceof EObject && !DiagramUiUtilities.isDiagramObject((EObject)targetObject)) { // 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(documentMR)) { // make sure this didn't come from the current editor: SourcedNotification sn = (SourcedNotification)notification; Object src = sn.getSource(); // check source: if (src instanceof DiagramModelNode) { DiagramModelNode dmn = (DiagramModelNode)src; Diagram diag = findDiagram(dmn); if (mappingDiagramController.getCurrentDiagram().equals(diag)) { shouldRefresh = false; } // endif -- same diagram } else if (targetObject instanceof TransformationMappingRoot) { // src is not a DiagramModelNode, make sure we want to process this mappingClassSet: MappingClassSet mapSet = findMappingClassSet(((TransformationMappingRoot)targetObject).getTarget()); shouldRefresh = shouldHandleMappingClassSet(mapSet); } else if (targetObject instanceof MappingClassObject) { // src is not a DiagramModelNode, make sure we want to process this mappingClassSet: MappingClassSet mapSet = findMappingClassSet(targetObject); shouldRefresh = shouldHandleMappingClassSet(mapSet); } else { shouldRefresh = true; } // endif -- src is DiagramModelNode } // endif -- modelResource the same } // endif -- target is eobject and not diagram object } // endwhile -- notifications } else { // SINGLE NOTIFICATION Object targetObject = ModelerCore.getModelEditor().getChangedObject(notification); if (targetObject != null && targetObject instanceof EObject && !DiagramUiUtilities.isDiagramObject((EObject)targetObject)) { // 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(documentMR)) { shouldRefresh = true; } } } } return shouldRefresh; } private MappingClassSet findMappingClassSet( Object targetObject ) { MappingClassSet result = null; if (targetObject instanceof EObject) { EObject parent = ((EObject)targetObject).eContainer(); if (targetObject instanceof MappingClassSet) { result = (MappingClassSet)targetObject; } else if (parent instanceof MappingClassSet) { result = (MappingClassSet)parent; } else { result = findMappingClassSet(parent); } // endif -- instance check } // endif return result; } public static Diagram findDiagram( DiagramModelNode dmn ) { DiagramModelNode nextNode = dmn; Diagram diag = nextNode.getDiagram(); while (diag == null) { nextNode = nextNode.getParent(); diag = nextNode.getDiagram(); } // endwhile return diag; } /** * Gets a string representation of the properties of the given <code>Notification</code>. * * @param theNotification the notification being processed * @return the string representation */ public static String paramString2( Notification theNotification ) { if (theNotification.getEventType() == Notification.ADD) { return new StringBuffer().append("\n Notification: TYPE =").append(notificationTypes[theNotification.getEventType()]) //$NON-NLS-1$ .append("\n NOTIFIER =").append(NotificationUtilities.getEObject(theNotification)) //$NON-NLS-1$ .append("\n getAddedChildren=").append(getAddedChildrenPrintString(theNotification)) //$NON-NLS-1$ .toString(); } else if (theNotification.getEventType() == Notification.REMOVE) { return new StringBuffer().append("\n Notification: TYPE =").append(notificationTypes[theNotification.getEventType()]) //$NON-NLS-1$ .append("\n NOTIFIER =").append(NotificationUtilities.getEObject(theNotification)) //$NON-NLS-1$ .append("\n getRemovedChildren=").append(getRemovedChildrenPrintString(theNotification)) //$NON-NLS-1$ .toString(); } else if (theNotification.getEventType() == Notification.SET) { return new StringBuffer().append("\n Notification: TYPE =").append(notificationTypes[theNotification.getEventType()]) //$NON-NLS-1$ .append("\n NOTIFIER =").append(NotificationUtilities.getEObject(theNotification)) //$NON-NLS-1$ .toString(); } else { return NotificationUtilities.paramString(theNotification); } } private static String getAddedChildrenPrintString( Notification notification ) { if (NotificationUtilities.getAddedChildren(notification) == null || NotificationUtilities.getAddedChildren(notification).length == 0) return "EMPTY"; //$NON-NLS-1$ StringBuffer returnString = new StringBuffer().append(" "); //$NON-NLS-1$ for (int i = 0; i < NotificationUtilities.getAddedChildren(notification).length; i++) { returnString.append("\n child =").append(NotificationUtilities.getAddedChildren(notification)[i]); //$NON-NLS-1$ } return returnString.toString(); } private static String getRemovedChildrenPrintString( Notification notification ) { if (NotificationUtilities.getRemovedChildren(notification) == null || NotificationUtilities.getRemovedChildren(notification).length == 0) return "EMPTY"; //$NON-NLS-1$ StringBuffer returnString = new StringBuffer().append(" "); //$NON-NLS-1$ for (int i = 0; i < NotificationUtilities.getRemovedChildren(notification).length; i++) { returnString.append("\n child =").append(NotificationUtilities.getRemovedChildren(notification)[i]); //$NON-NLS-1$ } return returnString.toString(); } }