[571249] Avoid potential SWTException exception: "Widget is disposed"

This commit fixes the problem seen during validation (comment 7 [1] of
the issue):
* To avoid the "Widget is disposed" problem that occurs during the
UpdateRequest runnable launched in async by the DeferredUpdateManager,
the executions of them are forced before cleaning a the offscreen
diagram EditPart.
* The dispose of the shell is now done in
MappingBasedSiriusFormatManagerFactory.cleanAndDispose(DiagramEditPart).
Indeed, running it in async caused a problem with the above change.
* All the diagramEditPart are disposed. This is a not a problem detected
but a potential problem seen during analysis.

[1] https://bugs.eclipse.org/bugs/show_bug.cgi?id=571249#c7

Bug: 571249
Change-Id: Ib58067fd0cdceb77d42fd9f53ab4118a5525e4dd
Signed-off-by: Laurent Redor <laurent.redor@obeo.fr>
diff --git a/plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/tools/api/format/MappingBasedSiriusFormatManagerFactory.java b/plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/tools/api/format/MappingBasedSiriusFormatManagerFactory.java
index 719533e..1032c07 100644
--- a/plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/tools/api/format/MappingBasedSiriusFormatManagerFactory.java
+++ b/plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/tools/api/format/MappingBasedSiriusFormatManagerFactory.java
@@ -42,6 +42,7 @@
 import org.eclipse.sirius.business.api.session.CustomDataConstants;
 import org.eclipse.sirius.business.api.session.Session;
 import org.eclipse.sirius.common.tools.api.util.EqualityHelper;
+import org.eclipse.sirius.common.ui.tools.api.util.EclipseUIUtil;
 import org.eclipse.sirius.diagram.DDiagram;
 import org.eclipse.sirius.diagram.DDiagramElement;
 import org.eclipse.sirius.diagram.DNode;
@@ -71,7 +72,7 @@
 import org.eclipse.sirius.viewpoint.description.RepresentationDescription;
 import org.eclipse.sirius.viewpoint.description.Viewpoint;
 import org.eclipse.sirius.viewpoint.provider.SiriusEditPlugin;
-import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Control;
 import org.eclipse.swt.widgets.Shell;
 
 /**
@@ -222,9 +223,11 @@
         synchronizeTargetDiagram(targetSession, (DSemanticDiagram) targetDiagram);
         DiagramEditPart sourceDiagramEditPart = null;
         DiagramEditPart targetDiagramEditPart = null;
+        Collection<DiagramEditPart> sourceDiagramEditParts = null;
+        Collection<DiagramEditPart> targetDiagramEditParts = null;
         try {
-            Collection<DiagramEditPart> sourceDiagramEditParts = getDiagramEditPart(sourceSession, sourceDiagram);
-            Collection<DiagramEditPart> targetDiagramEditParts = getDiagramEditPart(targetSession, targetDiagram);
+            sourceDiagramEditParts = getDiagramEditPart(sourceSession, sourceDiagram);
+            targetDiagramEditParts = getDiagramEditPart(targetSession, targetDiagram);
 
             if (!sourceDiagramEditParts.isEmpty() && !targetDiagramEditParts.isEmpty()) {
                 sourceDiagramEditPart = sourceDiagramEditParts.stream().findFirst().get();
@@ -244,11 +247,18 @@
                 synchronizeTargetDiagram(targetSession, (DSemanticDiagram) targetDiagram);
             }
         } finally {
-            if (sourceDiagramEditPart != null) {
-                cleanAndDispose(sourceDiagramEditPart);
+            // Several org.eclipse.draw2d.DeferredUpdateManager (UpdateRequest) could be launched, in async, during the
+            // paste process.
+            // We should execute them to avoid potential "Widget is disposed" during the cleanAndDispose.
+            EclipseUIUtil.synchronizeWithUIThread();
+            // Even if in theory, only one diagram is created, the above code can create several DiagramEditParts for
+            // source and target, so we clean all of them and not directly sourceDiagramEditPart and
+            // targetDiagramEditPart
+            if (sourceDiagramEditParts != null) {
+                sourceDiagramEditParts.stream().forEach(dep -> cleanAndDispose(dep));
             }
-            if (targetDiagramEditPart != null) {
-                cleanAndDispose(targetDiagramEditPart);
+            if (targetDiagramEditParts != null) {
+                targetDiagramEditParts.stream().forEach(dep -> cleanAndDispose(dep));
             }
         }
     }
@@ -536,6 +546,7 @@
     private Collection<DiagramEditPart> getDiagramEditPart(Session session, DRepresentation representation) {
         final List<DiagramEditPart> result = new ArrayList<DiagramEditPart>();
         final Collection<EObject> data = session.getServices().getCustomData(CustomDataConstants.GMF_DIAGRAMS, representation);
+        // Create a new shell for the diagramEditPart, it will be disposed later in cleanAndDispose(DiagramEditPart).
         Shell shell = new Shell();
         for (final EObject dataElement : data) {
             if (dataElement instanceof Diagram) {
@@ -545,12 +556,6 @@
                 result.add(diagramEditPart);
             }
         }
-        Display.getCurrent().asyncExec(new Runnable() {
-            @Override
-            public void run() {
-                shell.dispose();
-            }
-        });
         return result;
     }
 
@@ -744,16 +749,26 @@
      * Clean {@code diagramEditPart} element to avoid memory leaks.
      * 
      * @param diagramEditPart
+     *            The diagram edit part to dispose and to use to also dispose associated elements.
      */
     private void cleanAndDispose(DiagramEditPart diagramEditPart) {
-        // Clean to avoid memory leaks
-        diagramEditPart.deactivate();
-        // Memory leak : also disposing the
-        // DiagramGraphicalViewer associated to this
-        // DiagramEditPart
-        diagramEditPart.getViewer().flush();
-        diagramEditPart.getViewer().getEditDomain().getCommandStack().flush();
-        diagramEditPart.getViewer().getControl().dispose();
-        ((DiagramEditDomain) diagramEditPart.getViewer().getEditDomain()).removeViewer(diagramEditPart.getViewer());
+        if (diagramEditPart != null) {
+            // Clean to avoid memory leaks
+            diagramEditPart.deactivate();
+            // Memory leak : also disposing the
+            // DiagramGraphicalViewer associated to this
+            // DiagramEditPart
+            diagramEditPart.getViewer().flush();
+            diagramEditPart.getViewer().getEditDomain().getCommandStack().flush();
+            Control control = diagramEditPart.getViewer().getControl();
+            if (control.getParent() != null) {
+                // Dispose the shell created in method getDiagramEditPart(Session, DRepresentation).
+                control.getParent().dispose();
+            } else {
+                // This code should not occurred, but it's just to be sure.
+                control.isDisposed();
+            }
+            ((DiagramEditDomain) diagramEditPart.getViewer().getEditDomain()).removeViewer(diagramEditPart.getViewer());
+        }
     }
 }