/* * 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.ui.util; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.Iterator; import java.util.List; import org.eclipse.core.resources.IResource; import org.eclipse.emf.common.notify.Notification; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.resource.Resource; import org.eclipse.emf.edit.provider.INotifyChangedListener; import org.eclipse.jface.viewers.ITreeContentProvider; import org.eclipse.jface.viewers.TreeViewer; import org.eclipse.swt.widgets.Display; import org.eclipse.xsd.XSDModelGroup; import org.eclipse.xsd.XSDParticle; import org.teiid.designer.core.ModelerCore; import org.teiid.designer.core.notification.util.NotificationUtilities; import org.teiid.designer.core.workspace.ModelResource; import org.teiid.designer.metamodels.core.ModelAnnotation; import org.teiid.designer.metamodels.diagram.Diagram; import org.teiid.designer.metamodels.diagram.DiagramContainer; import org.teiid.designer.ui.viewsupport.ModelUtilities; /** * ModelObjectTreeViewerNotificationHandler * * @since 8.0 */ public class ModelObjectTreeViewerNotificationHandler implements INotifyChangedListener { // ///////////////////////////////////////////////////////////////////////////////////////////// // FIELDS // ///////////////////////////////////////////////////////////////////////////////////////////// //private static final String THIS_CLASS = "ModelObjectTreeViewerNotificationHandler"; //$NON-NLS-1$ // private boolean logDebug = false; private TreeViewer treeViewer; private static int nNotifications = 0; // ///////////////////////////////////////////////////////////////////////////////////////////// // CONSTRUCTORS // ///////////////////////////////////////////////////////////////////////////////////////////// /** * Construct an instance of ModelObjectTreeViewerNotificationHandler. */ public ModelObjectTreeViewerNotificationHandler( TreeViewer tv ) { super(); this.treeViewer = tv; } // ///////////////////////////////////////////////////////////////////////////////////////////// // METHODS // ///////////////////////////////////////////////////////////////////////////////////////////// /* (non-Javadoc) * @see org.eclipse.emf.edit.provider.INotifyChangedListener#notifyChanged(org.eclipse.emf.common.notify.Notification) */ @Override public void notifyChanged( final Notification notification ) { // This check verifies that a tree exists, and it isn't disposed. if (!treeIsValid()) return; // for all other events, just refresh the tree in the UI thread. Display.getDefault().asyncExec(new Runnable() { @Override public void run() { handleNotification(notification); } }); } protected ModelObjectNotificationHelper handleNotification( Notification notification ) { ModelObjectNotificationHelper notificationHelper = new ModelObjectNotificationHelper(notification); // System.out.println(" MOTVNH.handleNotification() Notifications = " + (nNotifications + 1)); // System.out.println(" MOTVNH.handleNotification() HELPER = \n" + notificationHelper.toString()); if (notificationHelper.shouldHandleNotification() && treeIsValid() && !notificationHelper.allChangesAreIgnorable()) { Iterator iter = notificationHelper.getAddOrRemoveTargets().iterator(); EObject nextTarget = null; while (iter.hasNext()) { nextTarget = (EObject)iter.next(); getTreeViewer().refresh(nextTarget); // The tree view of an XSD resource that contains compositors (sequence/choice/all) // has tree nodes backed by XSDParticles and not the XSDModelGroup, XSDElementDeclaration // etc. associated with the XSDParticle. So attempt a second refresh using the // the XSDParticle instance (see defect 21088) if (nextTarget instanceof XSDModelGroup) { nextTarget = ((XSDModelGroup)nextTarget).eContainer(); getTreeViewer().refresh(nextTarget); } if (nextTarget.eContainer() instanceof XSDParticle) { nextTarget = nextTarget.eContainer(); getTreeViewer().refresh(nextTarget); } } iter = notificationHelper.getChangeTargets().iterator(); while (iter.hasNext()) { nextTarget = (EObject)iter.next(); getTreeViewer().refresh(nextTarget); // The tree view of an XSD resource that contains compositors (sequence/choice/all) // has tree nodes backed by XSDParticles and not the XSDModelGroup, XSDElementDeclaration // etc. associated with the XSDParticle. So attempt a second refresh using the // the XSDParticle instance (see defect 21088) if (nextTarget instanceof XSDModelGroup) { nextTarget = ((XSDModelGroup)nextTarget).eContainer(); getTreeViewer().refresh(nextTarget); } if (nextTarget.eContainer() instanceof XSDParticle) { nextTarget = nextTarget.eContainer(); getTreeViewer().refresh(nextTarget); } } iter = notificationHelper.getLeftoverNotifications().iterator(); while (iter.hasNext()) { handleSingleNotification((Notification)iter.next()); } List refreshedResources = new ArrayList(); // Now we ask to see if the model has changed if (!notificationHelper.getModifiedResources().isEmpty()) { iter = notificationHelper.getModifiedResources().iterator(); IResource nextResource = null; while (iter.hasNext()) { nextResource = (IResource)iter.next(); // System.out.println(" -->> [" + nNotifications + // "] MOTVNH.handleNotification(1) calling Refresh for Resource = " + nextResource.getName()); getTreeViewer().refresh(nextResource); refreshedResources.add(nextResource); } } // Now we ask to see if the model has changed if (notificationHelper.getModelChildrenChanged()) { iter = notificationHelper.getChangeModels().iterator(); IResource nextResource = null; while (iter.hasNext()) { nextResource = (IResource)iter.next(); if (!refreshedResources.contains(nextResource)) { // System.out.println(" -->> [" + nNotifications + // "] MOTVNH.handleNotification(2) calling Refresh for Resource = " + nextResource.getName()); getTreeViewer().refresh(nextResource); } } } } nNotifications++; return notificationHelper; } public boolean shouldHandleNotification( Notification notification ) { return true; } // ------------------------------------------------------------------ // private helper methods. // ------------------------------------------------------------------ private void handleSingleNotification( Notification notification ) { if (NotificationUtilities.isAdded(notification)) { performAdd(notification); } else if (NotificationUtilities.isRemoved(notification)) { performRemove(notification); } else if (NotificationUtilities.isChanged(notification)) { performChange(notification); } } private void performAdd( Notification notification ) { Object targetObject = ModelerCore.getModelEditor().getChangedObject(notification); // if( logDebug ) // UiConstants.Util.print(THIS_CLASS + ".performAdd() START: TargetObject = " + targetObject ); //$NON-NLS-1$ if (targetObject != null && targetObject instanceof EObject && treeIsValid()) { // we know that the object is not a child of a model resource !!!!! // if( logDebug ) // UiConstants.Util.print(THIS_CLASS + ".performAdd() TargetEObject = " + targetObject ); //$NON-NLS-1$ if (targetObject instanceof DiagramContainer) { // get the added objects, get their target's and Collection refreshTargets = new HashSet(); EObject targetEObject = null; EObject[] newChildren = NotificationUtilities.getAddedChildren(notification); for (int i = 0; i < newChildren.length; i++) { targetEObject = ((Diagram)newChildren[i]).getTarget(); if (targetEObject != null) { if (!(targetEObject instanceof ModelAnnotation)) { refreshTargets.add(targetEObject); } } } refreshTree(refreshTargets); } } // if( logDebug ) // UiConstants.Util.print(THIS_CLASS + ".performAdd() END" ); //$NON-NLS-1$ } private void refreshTree( Collection objects ) { for (Iterator iter = objects.iterator(); iter.hasNext();) { Object nextObj = iter.next(); if (nextObj != null) { getTreeViewer().refresh(nextObj); } } } private void performRemove( Notification notification ) { Object targetObject = ModelerCore.getModelEditor().getChangedObject(notification); // if( logDebug ) // UiConstants.Util.print(THIS_CLASS + ".performRemove() START: TargetObject = " + targetObject ); //$NON-NLS-1$ if (targetObject instanceof DiagramContainer) { // get the added objects, get their target's and Collection refreshTargets = new HashSet(); EObject targetEObject = null; EObject[] oldChildren = NotificationUtilities.getRemovedChildren(notification); for (int i = 0; i < oldChildren.length; i++) { targetEObject = ((Diagram)oldChildren[i]).getTarget(); if (targetEObject != null) { if (!(targetEObject instanceof ModelAnnotation)) { refreshTargets.add(targetEObject); } } } refreshTree(refreshTargets); } else if (targetObject != null && targetObject instanceof EObject && treeIsValid()) { // we know that the object is not a child of a model resource !!!!! // if( logDebug ) // UiConstants.Util.print(THIS_CLASS + ".performRemove() TargetEObject = " + targetObject ); //$NON-NLS-1$ // if an annotation then a ModelImport was deleted. getParent(ModelAnnotation) gets the model so // refresh the model. if (targetObject instanceof ModelAnnotation) { ITreeContentProvider cp = (ITreeContentProvider)treeViewer.getContentProvider(); targetObject = cp.getParent(targetObject); } getTreeViewer().refresh(targetObject); } // if( logDebug ) // UiConstants.Util.print(THIS_CLASS + ".performRemove() END" ); //$NON-NLS-1$ } private void performChange( Notification notification ) { Object targetObject = ModelerCore.getModelEditor().getChangedObject(notification); if (targetObject instanceof Resource) { ModelResource modelResource; modelResource = ModelUtilities.getModelResource((Resource)targetObject, false); if (modelResource == null || modelResource.getModelProject().isOpen()) { // don't process notifications on items in closed projects return; } } // if( logDebug ) // UiConstants.Util.print(THIS_CLASS + ".performChange() START: TargetObject = " + targetObject ); //$NON-NLS-1$ if (targetObject != null && targetObject instanceof EObject && treeIsValid()) { // we know that the object is not a child of a model resource !!!!! // if( logDebug ) // UiConstants.Util.print(THIS_CLASS + ".performChange() TargetEObject = " + targetObject ); //$NON-NLS-1$ if (targetObject instanceof Diagram) { EObject targetEObject = ((Diagram)targetObject).getTarget(); if (!(targetEObject instanceof ModelAnnotation)) { getTreeViewer().refresh(targetEObject); } } else { EObject parentObject = ((EObject)targetObject).eContainer(); if (parentObject == null) { if (!(targetObject instanceof ModelAnnotation)) { getTreeViewer().refresh(null); } } else { getTreeViewer().refresh(parentObject); } } } // if( logDebug ) // UiConstants.Util.print(THIS_CLASS + ".performChange() END" ); //$NON-NLS-1$ } protected TreeViewer getTreeViewer() { return this.treeViewer; } private boolean treeIsValid() { if (getTreeViewer() != null && getTreeViewer().getTree() != null && !getTreeViewer().getTree().isDisposed()) return true; return false; } }