SWTException when switching comparisons in a compare dialog

Change-Id: I7829f70a6f63079afd8f7e607e7a76770a30861d
diff --git a/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/configuration/EMFCompareConfiguration.java b/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/configuration/EMFCompareConfiguration.java
index 5eb77a7..895521c 100644
--- a/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/configuration/EMFCompareConfiguration.java
+++ b/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/configuration/EMFCompareConfiguration.java
@@ -167,17 +167,62 @@
 	}
 
 	/**
-	 * {@inheritDoc}
+	 * {@inheritDoc}.
+	 * <p>
+	 * The lifecycle of the EMFCompareConfiguration (ECC) does not follow the lifecycle of its delegate
+	 * CompareConfiguration (CC). CC are created once per comparison editor instance. The comparison editor
+	 * lives from the moment the user starts a comparison to the moment the user closes the editor.
+	 * In-between, the user will be able to switch from one content merge viewer (CMV) to another by changing
+	 * his selection in the structure merge viewer (SMW). For example, selecting an EObject in the SMV will
+	 * show tree representations of these EObject in the CMV, whilst selecting a text attribute in the SMW
+	 * will switch the CMV representation to textual viewers. When switching CMV, the ECC needs a partial
+	 * dispose in order to change its installed listeners (this will also happen when mirroring the
+	 * comparison). Furthermore, the user will be able to switch the whole comparison from one file to another
+	 * if he has selected multiple files for comparison (for example, by comparing in a compare dialog). When
+	 * switching from one file to another, the whole EMF Compare comparison needs to change, and thus we need
+	 * to dispose of the ECC, but the CC cannot be disposed at that time since its own lifecycle hasn't come
+	 * to an end.
+	 * </p>
+	 * <p>
+	 * Because of this, there are three separate 'dispose' methods on an ECC. First is the inherited
+	 * {@link #dispose()} which will dispose of this whole ECC after disposing its delegate CC. Second is
+	 * {@link #disposeListeners()} which will only undertake a partial clean up of this ECC : listeners of the
+	 * ECC are disposed, but not the Comparison itself, nor the delegate CC. Finally,
+	 * {@link #disposeComparison()} will discard both the listeners and Comparison, but not the delegate CC.
+	 * </p>
 	 * 
 	 * @see org.eclipse.emf.compare.rcp.ui.internal.configuration.IEMFCompareConfiguration#dispose()
 	 */
 	@Override
 	public void dispose() {
 		super.dispose();
-		disposeSelf();
+		disposeListeners();
 		// CompareConfiguration does not clear its properties list...
 		// Lets clean our own mess ourselves
 		// EVENT_BUS must not be set to null
+		disposeComparison();
+	}
+
+	/**
+	 * {@link #dispose()} is only called when the comparison editor is closed, whereas EMFCompareConfiguration
+	 * are created and discarded on each change of the ContentMergeViewer input. This will be called to
+	 * dispose of the specific setup that was made by the EMFCompareConfiguration wrapper to its underlying
+	 * CompareConfiguration. See documentation of {@link #dispose()}.
+	 * 
+	 * @see #dispose()
+	 */
+	public void disposeListeners() {
+		compareConfiguration.removePropertyChangeListener(propertyChangeListener);
+	}
+
+	/**
+	 * {@link #dispose()} is only called when the comparison editor is closed, whereas EMFCompareComparison
+	 * follows its own separate lifecycle. See documentation of {@link #dispose()}.
+	 * 
+	 * @see #dispose()
+	 */
+	public void disposeComparison() {
+		disposeListeners();
 		compareConfiguration.setProperty(COMPARISON_SCOPE, null);
 		compareConfiguration.setProperty(COMPARE_RESULT, null);
 		compareConfiguration.setProperty(SMV_FILTERS, null);
@@ -192,16 +237,6 @@
 		compareConfiguration.setProperty(DISPLAY_SELECT_UNRESOLVED_DIFF_ACTIONS, null);
 	}
 
-	/**
-	 * {@link #dispose()} is only called when the comparison editor is closed, whereas EMFCompareConfiguration
-	 * are created and discarded on each change of the ContentMergeViewer input. This will be called to
-	 * dispose of the specific setup that was made by the EMFCompareConfiguration wrapper to its underlying
-	 * CompareConfiguration.
-	 */
-	public void disposeSelf() {
-		compareConfiguration.removePropertyChangeListener(propertyChangeListener);
-	}
-
 	public boolean getBooleanProperty(String key, boolean dflt) {
 		final boolean ret;
 		Object value = getProperty(key);
diff --git a/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/contentmergeviewer/EMFCompareContentMergeViewer.java b/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/contentmergeviewer/EMFCompareContentMergeViewer.java
index 97d14e3..871b82b 100644
--- a/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/contentmergeviewer/EMFCompareContentMergeViewer.java
+++ b/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/contentmergeviewer/EMFCompareContentMergeViewer.java
@@ -870,7 +870,7 @@
 		editingDomainChange(compareConfiguration.getEditingDomain(), null);
 		compareConfiguration.getEventBus().unregister(this);
 		compareConfiguration.getPreferenceStore().removePropertyChangeListener(propertyChangeListener);
-		compareConfiguration.disposeSelf();
+		compareConfiguration.disposeListeners();
 		differenceGroupProvider = null;
 		undoAction = null;
 		redoAction = null;
diff --git a/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/contentmergeviewer/fallback/TextFallbackMergeViewer.java b/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/contentmergeviewer/fallback/TextFallbackMergeViewer.java
index a053ebc..a0f0c7f 100644
--- a/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/contentmergeviewer/fallback/TextFallbackMergeViewer.java
+++ b/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/contentmergeviewer/fallback/TextFallbackMergeViewer.java
@@ -676,7 +676,7 @@
 		configuration.getEventBus().unregister(this);
 
 		// Stop using this configuration.
-		configuration.disposeSelf();
+		configuration.disposeListeners();
 
 		// Clean up the inputs.
 		setOriginalInput(null);
diff --git a/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/contentmergeviewer/label/LabelContentViewer.java b/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/contentmergeviewer/label/LabelContentViewer.java
index 440040a..cd4b172 100644
--- a/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/contentmergeviewer/label/LabelContentViewer.java
+++ b/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/contentmergeviewer/label/LabelContentViewer.java
@@ -206,7 +206,7 @@
 
 	protected void handleDisposed() {
 		configuration.getEventBus().unregister(this);
-		configuration.disposeSelf();
+		configuration.disposeListeners();
 		editingDomainChange(configuration.getEditingDomain(), null);
 	}
 }
diff --git a/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/contentmergeviewer/text/EMFCompareTextMergeViewer.java b/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/contentmergeviewer/text/EMFCompareTextMergeViewer.java
index 4cc22c9..da7e2d5 100644
--- a/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/contentmergeviewer/text/EMFCompareTextMergeViewer.java
+++ b/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/contentmergeviewer/text/EMFCompareTextMergeViewer.java
@@ -482,7 +482,7 @@
 		EMFCompareConfiguration compareConfiguration = getCompareConfiguration();
 		compareConfiguration.getEventBus().unregister(this);
 		editingDomainChange(compareConfiguration.getEditingDomain(), null);
-		compareConfiguration.disposeSelf();
+		compareConfiguration.disposeListeners();
 
 		fRedoAction = null;
 		fUndoAction = null;
diff --git a/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/structuremergeviewer/EMFCompareStructureMergeViewer.java b/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/structuremergeviewer/EMFCompareStructureMergeViewer.java
index c766967..fe3300a 100644
--- a/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/structuremergeviewer/EMFCompareStructureMergeViewer.java
+++ b/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/structuremergeviewer/EMFCompareStructureMergeViewer.java
@@ -1839,7 +1839,7 @@
 		}
 
 		if (getCompareConfiguration() != null) {
-			getCompareConfiguration().dispose();
+			getCompareConfiguration().disposeComparison();
 		}
 		getViewer().setInput(null);
 	}