normalize EOLs in the core (third pass)
diff --git a/plugins/org.eclipse.emf.compare.doc/src/FAQ.mediawiki b/plugins/org.eclipse.emf.compare.doc/src/FAQ.mediawiki
index 3173701..b621f13 100644
--- a/plugins/org.eclipse.emf.compare.doc/src/FAQ.mediawiki
+++ b/plugins/org.eclipse.emf.compare.doc/src/FAQ.mediawiki
@@ -1,151 +1,151 @@
-= FAQs =

-

-These FAQs will be aimed at EMF Compare 2 and subsequent versions. Since this version largely differs from the previous 1.* stream, answers related to version 1 cannot apply in most case.

-

-=== Users FAQ ===

-

-==== Which files should be compared via EMF Compare ? ====

-

-'''Q''' : My model is compared as a text-file, how can EMF compare know the files it should handle ?

-

-'''A''' : EMF Compare will be triggered for any files being recognized as an EMF model. Technically, it will be files recognized with the content types XMI (org.eclipse.emf.ecore.xmi) or "EMF Compare" (org.eclipse.emf.compare.content.type).

-

-If your models are compared with the text compare editor and you want EMF Compare to be used instead, you should add your own extension using the Preferences view / General / Content-types and add your file extension in the "EMF Compare" content-type.

-

-[[Image:images/EMF_Compare_Preferences_Content_Type.png]]

-

-==== How to force text comparison? ====

-

-'''Q''': I want my models to be compared as text but I can't remove its association to XMI Content Type or EMF Compare content type because they are locked (e.g. Ecore, UML, etc…)

-

-'''A''': Every files locked with XMI content type (i.e. their content type is "org.eclipse.emf.ecore.xmi" or one of its subtype) or EMF Compare content type can not be forced to use the text compare editor. This is a Eclipse Compare platform limitation. You can, however, see the text comparison from the EMF Compare editor. Deactivate the "Empty Resource Mappings" filter and then select the appropriate resource mapping. The bottom panes will display the comparison of the textual content of the mapped resources.

-

-[[Image:images/EMF_Compare_Text_Comparison.png]]

-

-==== EMF Compare compatibility ? ====

-

-'''Q''' : Which Java/Eclipse versions can EMF Compare run on?

-

-'''A''' : EMF Compare is built against JDK 1.5 and makes use of the features it introduced such as foreach and generics. It is therefore incompatible with a JDK < 1.5. EMF Compare can also be used with both JDK 1.6 and JDK 1.7.

-

-We strive to keep the [[./user/user-guide.html#Compatibility|compatibility chart]] updated so that you can determine which version of EMF Compare can be used in conjunction with your Eclipse of choice.

-

-==== Where can I find EMF Compare ? ====

-

-'''Q''' : Where can I download the latest version of EMF Compare?

-

-'''A''' : The [[./user/user-guide.html#Installing_EMF_Compare|Installation instruction]] present a set of update sites useable to install.

-The [http://www.eclipse.org/emf/compare/downloads/ Download page] lists more specific update sites if you wish to try one of the latest integration builds.

-

-== Developers FAQ ==

-

-=== How can I programmatically add my model file extension in EMF Compare so that it is called automatically ? ===

-

-'''Q''' : How can I programatically add my model file extension to EMF Compare so that it is called automatically ? 

-

-'''A''' : You can do so using the exore XMI content-type, here is a sample from a plugin.xml:

-

-<source lang="xml">

-<extension

-    point="org.eclipse.core.contenttype.contentTypes">

-  <file-association

-      content-type="org.eclipse.emf.ecore.xmi"

-      file-extensions="uml"

-      file-names="*"/>

-</extension>

-</source>

-

-=== How can I use EMF Compare programmatically ? ===

-

-'''Q''' : How can I use EMF Compare programmatically, to compare either files or "in-memory" objects?

-

-'''A''' : Many samples of how to compare objects can be found within [http://git.eclipse.org/c/emfcompare/org.eclipse.emf.compare.git/tree/plugins/org.eclipse.emf.compare.tests the unit tests of EMF Compare] (see also [[EMF_Compare/Contributor_Guide#Checking_out_the_code|how to checkout the source code]]). Here is a sample that should cover the basic use case (the class with this method should have a dependency towards the ''org.eclipse.emf.compare'' plugin) :

-

-<source lang="java">

-public void compare(File model1, File model2) {

-	URI uri1 = URI.createFileURI("path/to/first/model.xmi");

-	URI uri2 = URI.createFileURI("path/to/second/model.xmi");

-

-	Resource.Factory.Registry.INSTANCE.getExtensionToFactoryMap().put("xmi", new XMIResourceFactoryImpl());

-

-	ResourceSet resourceSet1 = new ResourceSetImpl();

-	ResourceSet resourceSet2 = new ResourceSetImpl();

-

-	resourceSet1.getResource(uri1, true);

-	resourceSet2.getResource(uri2, true);

-

-	IComparisonScope scope = new DefaultComparisonScope(resourceSet1, resourceSet2);

-	Comparison comparison = EMFCompare.builder().build().compare(scope);

-

-	List<Diff> differences = comparison.getDifferences();

-	// Let's merge every single diff

-	IMerger.Registry mergerRegistry = new IMerger.RegistryImpl();

-	IBatchMerger merger = new BatchMerger(mergerRegistry);

-	merger.copyAllLeftToRight(differences, new BasicMonitor());

-}

-</source>

-

-=== Can EMF Compare be used standalone ? ===

-

-'''Q''' : Is EMF Compare able to compare "in-memory" objects, and can it be run without Eclipse ?

-

-'''A''': Yes, the core of EMF Compare is developed primarily for standalone, the integration with Eclipse being built on top of that. All of the classes and utilities located in the ''org.eclipse.emf.compare'' plugin are pure Java with no dependency towards Eclipse, and can thus safely be used within a Java application running outside of Eclipse.

-

-The following is the minimal set of dependencies you will need for EMF Compare.

-

- * org.eclipse.emf.common 2.5 or higher

- * org.eclipse.emf.ecore 2.5 or higher

- * org.eclipse.emf.ecore.xmi 2.5 or higher

- * org.eclipse.emf.compare 2.0 or higher

- * com.google.guava 11.0 (EMF Compare should also be compatible with Guava 12, 13 and 14 as far as we tested our integration)

-

-=== Custom data types are always marked as modified by EMF Compare ===

-

-'''Q''' : A model based on a custom meta-model always shows elements of a custom data type as being changed. How can I have EMF Compare behave correctly?

-

-'''A''' : The differencing process of EMF Compare is based on equality helpers. For data types, this depends upon the return value of these data types' ''equals(Object)'' method. It will thus fail to determine whether two objects match if their ''equals(Object)'' methods has not been overriden in the custom data type's instance class. Remember to also override ''hashCode()'' when overriding ''equals(Object)''. A Typical example of this is [https://bugs.eclipse.org/bugs/show_bug.cgi?id=226152 bug 226152].

-

-Another way around this problem would be to contribute your own equality helper to EMF Compare so that it knows how to compare these kind of data types. That could be done through the EMFCompare builder :

-

-<source lang="java">

-IEqualityHelperFactory helperFactory = new DefaultEqualityHelperFactory() {

-	@Override

-	public org.eclipse.emf.compare.utils.IEqualityHelper createEqualityHelper() {

-		final Cache<EObject, URI> cache = EqualityHelper.createDefaultCache(getCacheBuilder());

-		return new EqualityHelper(cache) {

-			@Override

-			public boolean matchingValues(Object object1, Object object2) {

-				if (object1 instanceof MyDataType && object2 instanceof MyDataType) {

-					// custom code

-				}

-				return super.matchingValues(object1, object2);

-			}

-		};

-	}

-};

-IComparisonFactory comparisonFactory = new DefaultComparisonFactory(helperFactory);

-Comparison comparison = EMFCompare.builder().setMatchEngine(new DefaultMatchEngine(DefaultMatchEngine

-		.createDefaultEObjectMatcher(UseIdentifiers.WHEN_AVAILABLE), comparisonFactory)).build().compare(scope);

-</source>

-

-=== Can I programmatically open a comparison editor or dialog ? ===

-

-'''Q''' : I need to call EMF Compare programmatically from within my own plugin, but I'd like to be able to show my users a comparison editor. Is there a way?

-

-'''A''' : Since EMF Compare 2.1.0M4, there is. As the answer to this question is a little complex, it deserves [[./developer/how-to-open-compare-dialog.html|its own page]].

-

-=== Can I use custom identifiers for my objects ? ===

-

-'''Q''' : I have my own custom elements, and I'd like to tell EMF Compare what to use to uniquely identify them. For example, their name.

-

-'''A''' : EMF Compare internally uses a function in order to compute the identifier of an EObject. You can override this function with your own, or compose your own with it so that EMF Compare will use your function for your elements, and fall back to the default behavior for any other element it needs to match.

-

-How to do this is outlined on the [[./developer/developer-guide.html#Defining custom identifiers|Developer Guide]].

-

-=== Can I ignore differences on a specific reference, or ignore ordering differences ? ===

-

-'''Q''' : I want to ignore all differences on a given structural feature, can I tell EMF Compare not to look at these features?<br/>

-'''Q''' : EMF Compare detects many ''ordering'' differences on my models, but I do not care about them. Is there a way to ignore all ordering changes?

-

-'''A''' : You can override the ''FeatureFilter'' to tell EMF Compare that some references should be ignored, there is an example doing just that in the [[./developer/developer-guide.html#Changing the FeatureFilter|Developer Guide]].

-

+= FAQs =
+
+These FAQs will be aimed at EMF Compare 2 and subsequent versions. Since this version largely differs from the previous 1.* stream, answers related to version 1 cannot apply in most case.
+
+=== Users FAQ ===
+
+==== Which files should be compared via EMF Compare ? ====
+
+'''Q''' : My model is compared as a text-file, how can EMF compare know the files it should handle ?
+
+'''A''' : EMF Compare will be triggered for any files being recognized as an EMF model. Technically, it will be files recognized with the content types XMI (org.eclipse.emf.ecore.xmi) or "EMF Compare" (org.eclipse.emf.compare.content.type).
+
+If your models are compared with the text compare editor and you want EMF Compare to be used instead, you should add your own extension using the Preferences view / General / Content-types and add your file extension in the "EMF Compare" content-type.
+
+[[Image:images/EMF_Compare_Preferences_Content_Type.png]]
+
+==== How to force text comparison? ====
+
+'''Q''': I want my models to be compared as text but I can't remove its association to XMI Content Type or EMF Compare content type because they are locked (e.g. Ecore, UML, etc…)
+
+'''A''': Every files locked with XMI content type (i.e. their content type is "org.eclipse.emf.ecore.xmi" or one of its subtype) or EMF Compare content type can not be forced to use the text compare editor. This is a Eclipse Compare platform limitation. You can, however, see the text comparison from the EMF Compare editor. Deactivate the "Empty Resource Mappings" filter and then select the appropriate resource mapping. The bottom panes will display the comparison of the textual content of the mapped resources.
+
+[[Image:images/EMF_Compare_Text_Comparison.png]]
+
+==== EMF Compare compatibility ? ====
+
+'''Q''' : Which Java/Eclipse versions can EMF Compare run on?
+
+'''A''' : EMF Compare is built against JDK 1.5 and makes use of the features it introduced such as foreach and generics. It is therefore incompatible with a JDK < 1.5. EMF Compare can also be used with both JDK 1.6 and JDK 1.7.
+
+We strive to keep the [[./user/user-guide.html#Compatibility|compatibility chart]] updated so that you can determine which version of EMF Compare can be used in conjunction with your Eclipse of choice.
+
+==== Where can I find EMF Compare ? ====
+
+'''Q''' : Where can I download the latest version of EMF Compare?
+
+'''A''' : The [[./user/user-guide.html#Installing_EMF_Compare|Installation instruction]] present a set of update sites useable to install.
+The [http://www.eclipse.org/emf/compare/downloads/ Download page] lists more specific update sites if you wish to try one of the latest integration builds.
+
+== Developers FAQ ==
+
+=== How can I programmatically add my model file extension in EMF Compare so that it is called automatically ? ===
+
+'''Q''' : How can I programatically add my model file extension to EMF Compare so that it is called automatically ? 
+
+'''A''' : You can do so using the exore XMI content-type, here is a sample from a plugin.xml:
+
+<source lang="xml">
+<extension
+    point="org.eclipse.core.contenttype.contentTypes">
+  <file-association
+      content-type="org.eclipse.emf.ecore.xmi"
+      file-extensions="uml"
+      file-names="*"/>
+</extension>
+</source>
+
+=== How can I use EMF Compare programmatically ? ===
+
+'''Q''' : How can I use EMF Compare programmatically, to compare either files or "in-memory" objects?
+
+'''A''' : Many samples of how to compare objects can be found within [http://git.eclipse.org/c/emfcompare/org.eclipse.emf.compare.git/tree/plugins/org.eclipse.emf.compare.tests the unit tests of EMF Compare] (see also [[EMF_Compare/Contributor_Guide#Checking_out_the_code|how to checkout the source code]]). Here is a sample that should cover the basic use case (the class with this method should have a dependency towards the ''org.eclipse.emf.compare'' plugin) :
+
+<source lang="java">
+public void compare(File model1, File model2) {
+	URI uri1 = URI.createFileURI("path/to/first/model.xmi");
+	URI uri2 = URI.createFileURI("path/to/second/model.xmi");
+
+	Resource.Factory.Registry.INSTANCE.getExtensionToFactoryMap().put("xmi", new XMIResourceFactoryImpl());
+
+	ResourceSet resourceSet1 = new ResourceSetImpl();
+	ResourceSet resourceSet2 = new ResourceSetImpl();
+
+	resourceSet1.getResource(uri1, true);
+	resourceSet2.getResource(uri2, true);
+
+	IComparisonScope scope = new DefaultComparisonScope(resourceSet1, resourceSet2);
+	Comparison comparison = EMFCompare.builder().build().compare(scope);
+
+	List<Diff> differences = comparison.getDifferences();
+	// Let's merge every single diff
+	IMerger.Registry mergerRegistry = new IMerger.RegistryImpl();
+	IBatchMerger merger = new BatchMerger(mergerRegistry);
+	merger.copyAllLeftToRight(differences, new BasicMonitor());
+}
+</source>
+
+=== Can EMF Compare be used standalone ? ===
+
+'''Q''' : Is EMF Compare able to compare "in-memory" objects, and can it be run without Eclipse ?
+
+'''A''': Yes, the core of EMF Compare is developed primarily for standalone, the integration with Eclipse being built on top of that. All of the classes and utilities located in the ''org.eclipse.emf.compare'' plugin are pure Java with no dependency towards Eclipse, and can thus safely be used within a Java application running outside of Eclipse.
+
+The following is the minimal set of dependencies you will need for EMF Compare.
+
+ * org.eclipse.emf.common 2.5 or higher
+ * org.eclipse.emf.ecore 2.5 or higher
+ * org.eclipse.emf.ecore.xmi 2.5 or higher
+ * org.eclipse.emf.compare 2.0 or higher
+ * com.google.guava 11.0 (EMF Compare should also be compatible with Guava 12, 13 and 14 as far as we tested our integration)
+
+=== Custom data types are always marked as modified by EMF Compare ===
+
+'''Q''' : A model based on a custom meta-model always shows elements of a custom data type as being changed. How can I have EMF Compare behave correctly?
+
+'''A''' : The differencing process of EMF Compare is based on equality helpers. For data types, this depends upon the return value of these data types' ''equals(Object)'' method. It will thus fail to determine whether two objects match if their ''equals(Object)'' methods has not been overriden in the custom data type's instance class. Remember to also override ''hashCode()'' when overriding ''equals(Object)''. A Typical example of this is [https://bugs.eclipse.org/bugs/show_bug.cgi?id=226152 bug 226152].
+
+Another way around this problem would be to contribute your own equality helper to EMF Compare so that it knows how to compare these kind of data types. That could be done through the EMFCompare builder :
+
+<source lang="java">
+IEqualityHelperFactory helperFactory = new DefaultEqualityHelperFactory() {
+	@Override
+	public org.eclipse.emf.compare.utils.IEqualityHelper createEqualityHelper() {
+		final Cache<EObject, URI> cache = EqualityHelper.createDefaultCache(getCacheBuilder());
+		return new EqualityHelper(cache) {
+			@Override
+			public boolean matchingValues(Object object1, Object object2) {
+				if (object1 instanceof MyDataType && object2 instanceof MyDataType) {
+					// custom code
+				}
+				return super.matchingValues(object1, object2);
+			}
+		};
+	}
+};
+IComparisonFactory comparisonFactory = new DefaultComparisonFactory(helperFactory);
+Comparison comparison = EMFCompare.builder().setMatchEngine(new DefaultMatchEngine(DefaultMatchEngine
+		.createDefaultEObjectMatcher(UseIdentifiers.WHEN_AVAILABLE), comparisonFactory)).build().compare(scope);
+</source>
+
+=== Can I programmatically open a comparison editor or dialog ? ===
+
+'''Q''' : I need to call EMF Compare programmatically from within my own plugin, but I'd like to be able to show my users a comparison editor. Is there a way?
+
+'''A''' : Since EMF Compare 2.1.0M4, there is. As the answer to this question is a little complex, it deserves [[./developer/how-to-open-compare-dialog.html|its own page]].
+
+=== Can I use custom identifiers for my objects ? ===
+
+'''Q''' : I have my own custom elements, and I'd like to tell EMF Compare what to use to uniquely identify them. For example, their name.
+
+'''A''' : EMF Compare internally uses a function in order to compute the identifier of an EObject. You can override this function with your own, or compose your own with it so that EMF Compare will use your function for your elements, and fall back to the default behavior for any other element it needs to match.
+
+How to do this is outlined on the [[./developer/developer-guide.html#Defining custom identifiers|Developer Guide]].
+
+=== Can I ignore differences on a specific reference, or ignore ordering differences ? ===
+
+'''Q''' : I want to ignore all differences on a given structural feature, can I tell EMF Compare not to look at these features?<br/>
+'''Q''' : EMF Compare detects many ''ordering'' differences on my models, but I do not care about them. Is there a way to ignore all ordering changes?
+
+'''A''' : You can override the ''FeatureFilter'' to tell EMF Compare that some references should be ignored, there is an example doing just that in the [[./developer/developer-guide.html#Changing the FeatureFilter|Developer Guide]].
+
diff --git a/plugins/org.eclipse.emf.compare.doc/src/developer/developer-guide.mediawiki b/plugins/org.eclipse.emf.compare.doc/src/developer/developer-guide.mediawiki
index 322f124..ad6cddf 100644
--- a/plugins/org.eclipse.emf.compare.doc/src/developer/developer-guide.mediawiki
+++ b/plugins/org.eclipse.emf.compare.doc/src/developer/developer-guide.mediawiki
@@ -1,1005 +1,1005 @@
-= Developer Guide =

-

-== Architecture ==

-

-=== Comparison Process ===

-

-[[Image:./../images/EMF_Compare_Process_Full.png|center]]

-

-The above figure represents the comparison process of EMF Compare. It can be roughly divided in 6 main phases.

-

-==== Model Resolving ====

-From a given "starting point" (the file a user decided to compare), finding all other fragments required for the comparison of the whole logical model.

-==== Matching ====

-Iterating over the two (or three) loaded logical models in order to map elements together two-by-two (or three-by-three). For example, determine that class Class1 from the first model corresponds to class Class1' from the second model.

-==== Differencing ====

-The matching phase told us which elements were matching together. The differencing phase will browse through these mappings and determine whether the two (or three) elements are equal or if they present differences (for example, the name of the class changed from Class1 to Class1').

-==== Equivalences ====

-The differencing phases detected a number of differences between the compared models. However, two distinct differences might actually represent the same change. This phase will browse through all differences and link them together when they can be seen as equivalent (for example, differences on opposite references).

-==== Requirements ====

-For the purpose of merging differences, there might be dependencies between them. For example, the addition of a class C1 in package P1 depends on the addition of package P1 itself. During this phase, we'll browse through all detected differences and link them together when we determine that one cannot be merged without the other.

-==== Conflicts ====

-When we're comparing our file with one from a Version Control System (CVS, SVN, Git, Clearcase...), there might actually be conflicts between the changes we've made locally, and the changes that were made to the file on the remote repository. This phase will browse through all detected differences and detect these conflicts.

-

-The Model resolving phase itself can be further decomposed in its own two distinct phases. More on the logical model and its resolution can be found on the [[./logical-model.html|dedicated page]].

-

-[[Image:./../images/EMF_Compare_Model_Resolving.png|center]]

-

-=== Project Architecture ===

-

-[[Image:./../images/EMF_Compare_2_Architecture.png|center]]

-

-EMF Compare is built on top of the Eclipse platform. We depend on the Eclipse Modeling Framework (EMF), the Eclipse Compare framework and, finally, Eclipse Team, the framework upon which the repository providers (EGit, CVS, Subversive...) are built.

-

-The EMF Compare extensions target specific extensions of the modeling framework: UML, the Graphical Modeling Framework (and its own extensions, papyrus, ecoretools, ...).

-

-Whilst we are built atop bricks that are tightly coupled with the eclipse platform, it should be noted that the core of EMF Compare can be run in a standalone application with no runtime dependencies towards Eclipse; as can EMF itself.

-

-=== The Comparison Model ===

-EMF Compare uses a single model, which root is a ''Comparison'' object, to represent all of the information regarding the comparison: matched objects, matched resources, detected differences, links between these references, etc. The root ''Comparison'' is created at the beginning of the Match process, and will undergo a set of successive refinings during the remainder of the Comparison: Diff, Equivalence, Dependencies... will all add their own information to the ''Comparison''.

-

-So, how exactly is represented all of the information the Comparison model can hold, and how to make sense of it all?

-

-===Match===

-

-A ''Match'' element is how we represent that the ''n'' compared versions have elements that are basically the same. For example, if we are comparing two different versions ''v1'' and ''v2'' of a given model which look like:

-

-{| border="1" cellpadding="5" cellspacing="0" align="center"

-|-

-! align="center" | Master

-! align="center" | Borrowables

-|-

-| [[Image:./../images/v1.png|center]]

-| [[Image:./../images/v2.png|center]]

-|}

-

-Comparing these two models, we'll have a Comparison model containing three matches:

-

-# library <-> library

-# Book <-> Novel

-# title <-> title

-

-In other words, the comparison model contains an aggregate of the two or three compared models, in the form of ''Match'' elements linking the elements of all versions together. Differences will then be detected on these ''Match'' and added under them, thus allowing us to know both:

-

-* what the difference is (for example, "attribute name has been changed from ''Book'' to ''Novel''"), and

-* what the original elements were.

-

-==== Diff ====

-

-''Diff'' elements are created during the differencing process in order to represent the actual modifications that can be detected within the source model(s). The ''Diff'' concept itself is only there as the super-class of the three main kind of differences EMF Compare can detect in a model, namely ''ReferenceChange'', ''AttributeChange'' and ''ResourceAttachmentChange''. We'll go back to these three sub-classes in a short while.

-

-Whatever their type, the differences share a number of common elements:

-* a parent ''match'': differences are detected on a given ''Match''. Having a difference basically means that one of the elements paired through this ''Match'' differs from its "reference" side (see ''source'' description below). 

-* a ''source'': differences are detected on one side of their match. The source really only holds meaning in three-way comparisons, where a difference can be detected in either right or left. All differences detected through two-way comparisons have their source in the left side. This is because we always compare according to a "reference" side. During two-way comparisons, the reference side is the right: differences will always be detected on the left side as compared with the right side. During three-way comparisons though, differences can be detected on either left or right side as compared with their common ancestor; but never as compared to themselves (in other words, this is ''roughly'' equivalent to two two-way comparisons, first the left as compared to the origin, then the right as compared to the origin).

-* a current ''state'': all differences start off in their initial ''unresolved'' state. The user can then choose to:

-** merge the difference (towards either right or left, applying or reverting the difference in the process), in which case the difference becomes ''merged'', or

-** discard it, thus marking the change as ''discarded''. For example, if there is a conflicting edit of a textual attribute, the user can decide that neither right nor left are satisfying, and instead settle for a mix of the two.

-* a ''kind'': this is used by the engine to describe the type of difference it detected. Differences can be of four general types:

-** ''Add'': There are two distinct things that EMF Compare considers as an "addition". First, adding a new element within the values of a '''multi-valued feature''' is undeniably an addition. Second, any change in a '''containment reference''', even if that reference is mono-valued, that represents a "new" element in the model is considered to be an addition. Note that this second case is an exception to the rule for ''change'' differences outlined below.

-** ''Delete'': this is used as the counterpart of ''add'' differences, and it presents the same exception for '''mono-valued containment references'''.

-** ''Change'': any modification to a '''mono-valued feature''' is considered as a ''change'' difference by the engine. Take note that containment references are an exception to this rule: no ''change'' will ever be detected on those.

-** ''Move'': once again, two distinct things are represented as ''move'' differences in the comparison model. First, '''reordering''' the values of a multi-valued feature is considered as a series of MOVE: one difference for each moved value (EMF Compare computes the smallest number of differences needed between the two sides' values). Second, moving an object from '''one container to another''' (changing the containing feature of the EObject) will be detected as a ''move''.

-

-In order to ensure that the model stays coherent through individual merge operations, we've also decided to link differences together through a number of associations and references. For example, there are times when one difference cannot be merged without first merging another, or some differences which are exactly equivalent to one another. In no specific order:

-

-* ''dependency'': EMF Compare uses two oppposite references in order to track dependencies between differences. Namely, ''requires'' and ''requiredBy'' represent the two ends of this association. If the user has added a package ''P1'', then added a new Class ''C1'' within this package, we will detect both differences. However the addition of ''C1'' cannot be merged without first adding its container ''P1''. In such a case, the addition of ''C1'' '''requires''' the addition of ''P1'', and the later is '''requiredBy''' the former.

-* ''refinement'': this link is mainly used by extensions of EMF Compare in order to create high-level differences to hide the complexity of the comparison model. For example, this is used by the UML extension of EMF Compare to tell that the three differences "adding an association ''A1''", "adding a property ''P1'' in association ''A1''" and "adding a property ''P2'' in association ''A1''" is actually one single high-level difference, "adding an association ''A1''". This high-level difference is '''refinedBy''' the others, which all '''refines''' it.

-* ''equivalence'': this association is used by the comparison engine in order to link together differences which are equivalent in terms of merging. For example, Ecore has a concept of '''eOpposite''' references. Updating one of the two sides of an ''eOpposite'' will automatically update the other. In such an event, EMF Compare will detect both sides as an individual difference. However, merging one of the two will trigger the update of the other side of the ''eOpposite'' as well. In such cases, the two differences are set to be ''equivalent'' to one another. Merging one difference part of an equivalence relationship will automatically mark all of the others as ''merged'' (see ''state'' above).

-* ''implication'': implications are a special kind of "directed equivalence". A difference D1 that is linked as "implied by" another D2 means that merging D1 requires us to merge D1 instead. In other words, D2 will be automatically merged if we merge D1, but D1 will not be automatically merged if we merge D2. Implications are mostly used with UML models, where subsets and supersets may trigger such linked changes.

-* ''conflict'': during three-way comparisons, we compare two versions of a given model with their common ancestor. We can thus detect changes that were made in either left or right side (see the description of ''source'' above). However, there are cases when changes in the left conflict with changes in the right. For example, a class named "Book" in the origin model can have been renamed to "Novel" in the left model whereas it has been renamed to "Essay" in the right model. In such a case, the two differences will be marked as being in conflict with one another.

-

-As mentionned above, there are only three kind of differences that we will detect through EMF Compare, which will be sufficient for all use cases. ''ReferenceChange'' differences will be detected for every value of a reference for which we detect a change. Either the value was added, deleted, or moved (within the reference or between distinct references). ''AttributeChange'' differences are the same, but for attributes instead of references. Lastly, the ''ResourceAttachmentChange'' differences, though very much alike the ReferenceChanges we create for containment references, are specifically aimed at describing changes within the roots of one of the compared resources.

-

-==== Conflict ====

-

-'''Conflict''' will only be detected during three-way comparisons. There can only be "conflicts" when we are comparing two different versions of a same model along with their common ancestor. In other words, we need to able to compare two versions of a common element with a "reference" version of that element.

-

-There are many different kinds of conflicts; to name a few:

-* changing an element on one side (in any way, for example, renaming it) whilst that element has been removed from the other side

-* changing the same attribute of an element on both sides, to different values (for example, renaming "Book" to "Novel" on the left while be renamed "Book" to "Essay" on the right)

-* creating a new reference to an element on one side whilst it had been deleted from the other side

-

-Conflicts can be of two kinds. We call ''PSEUDO'' conflict a conflict where the two sides of a comparison have changed as compared to their common ancestor, but where the two sides are actually now equal. In other words, the end result is that the left is now equal to the right, even though they are both different from their ancestor. This is the opposite of ''REAL'' conflict where the value on all three sides is different. In terms of merging, pseudo conflicts do not need any particular action, whilst real conflicts actually need resolution.

-

-There can be more than two differences conflicting with each other. For example, the deletion of an element from one side will most likely conflict with a number of differences from the other side.

-

-==== Equivalence ====

-

-EMF Compare uses '''Equivalence''' elements in order to link together a number of differences which can ultimately be considered to be the same. For example, ecore's ''eOpposite'' references will be maintained in sync with one another. As such, modifying one of the two references will automatically update the second one accordingly. The manual modification and the automatic update are two distinct modifications of the model, resulting in two differences detected. However, merging any of these two differences will automatically merge the other one. Therefore both are marked as being equivalent to each other.

-

-There can be more than two differences equivalent with each other; in which case all will be added to a single ''Equivalence'' object, representing their relations.

-

-== Core Concepts ==

-

-=== Proxy Resolution ===

-

-When cross-referencing objects from another resource, EMF may use proxies instead of the actual object. As long as you do not access the element in question, EMF does not need to load the resource in which it is contained. The proxy is kind of a placeholder that tells EMF what resource should be loaded, and which of this resource's objects referenced, when we actually need to access its value.

-

-Proxy resolution is generally transparent, but a lot of tools based on EMF do not consider these proxies as first-class citizens: they simply resolve it without considering that it might not be needed. On the other hand, EMF Compare will never resolve proxies except for those strictly necessary. Whatever the phase of comparison, we strive to never hold the whole model in memory.

-

-The [[#Model Resolving|initial resolution phase]] is the most intensive in terms of proxy resolution and I/O operations. Though we will never hold the whole logical model in memory at any given time, we do resolve all cross-references of the compared resources, on all sides of the comparison. Since the logical model may be located in a lot of different files on disk, it might also be very heavy in memory if loaded at once. However, even if EMF Compare does resolve all fragments composing that logical model, it also unloads them as soon as the cross-references are registered. In other words, what we create is a dependency graph between the resources, not a loaded model. Afterwards, we only reload in memory those resources that have actually changed, and can thus contain differences. There will be proxies between these "changed" resources and the unchanged ones we have decided not to reload, but EMF Compare will never resolve these proxies again (and, in fact, will prevent their resolving from other tools).

-

-At the time of writing, the user interface will never resolve any proxies either. This might change in the future for a better user experience since proxies usually end up displayed in strange manners.

-

-=== Equality Helper ===

-

-The equality helper is a very central concept of EMF Compare. Of course, EMF Compare's aim is to be able to compare objects together, objects which comparison is not trivial and cannot be done through a mere "equal or not" concept. However, we still need to be able to compare these objects at all time and, whenever possible, without a full-fledged comparison.

-

-The equality helper will be used in all phases of the comparison, from matching to merging (please see the [[#Comparison Process|comparison process]] for a bird's eye view of the different comparison phases, or their detailled descriptions down below). The matching phase is precisely the time when EMF Compare is trying to match two-by-two the elements from one side to the elements from the other side. As such, we do not have -yet- the knowledge of whichi element matches with which other. However, for all subsequent phases, the equality helper will rely on information from the comparison itself (the ''Match'' elements) to make a fail-fast test for element 'equality'.

-

-When we do not have this information, the equality helper will resort to less optimal algorithms. For any object that is not an EMF EObject, we will use strict equality through ''=='' and ''Object#equals()'' calls. One of the cause for EMF Compare failing to match attribute values together is in fact the lack of implementation of the ''equals'' method on custom datatypes (see the [[./../FAQ.html#Custom data types are always marked as modified by EMF Compare|FAQ]] for more on that particular issue).

-

-Note that the equality helper will be used extensively, and that any performance hit or improvement here will make a huge difference for the whole comparison process. Likewise, any mistake you make when implementing a custom equality helper will introduce a lot of bugs.

-

-=== Comparison Scope ===

-

-As seen above, EMF Compare consider proxies as real citizens of the EMF realm. This mainly shows in the matching mechanism. EMF Compare uses a scoping mechanism to determine which elements should be matched together, and which others should be ignored. Any element that is outside of the comparison scope will be ignored by the comparison engine and left alone (if it is a proxy, it won't even be loaded). This also means that we won't really have a way to compare these proxy (or otherwise out-of-scope values) when the Diff process encounters them.

-

-For example, an element that is outside of the comparison scope, but referenced by another element which ''is'' in the scope will need specific comparison means: we've ignored it during the matching phase, so we don't know which 'out-of-scope' element corresponds to which 'other out-of-scope' element. Consider the following: in the first model, a package ''P1'' contains another package ''P2''. In the right, a package ''P1' '' contains a package ''P2' ''. We've told EMF Compare that ''P2'' and ''P2' '' are out of the comparison scope. Now how do we determine that the reference from ''P1'' to ''P2'' has changed (or, in this example, that it did not change)?

-

-This is a special case that is handled by the IEqualityHelper. Specifically, when such cases are encountered, EMF Compare falls back to using the URI of the two objects to check for equality. This behavior can be changed by customizing the IEqualityHelper (see [[#Equality Helper|above]]).

-

-By default, the only thing that EMF Compare considers "out of scope" are Ecore's "EGenericType" elements. These are usually meaningless as far as comparison is concerned (as they are located in derived references and will be merged along with their "true" difference anyway). Please take note that, when used from the user interface, EMF Compare will narrow down the scope even further through the resolution of the [[./../developer/logical-model.html|logical model]] and determining which resources are actually candidates for differences.

-

-The comparison scope provides EMF Compare with information on the content of ResourceSets, Resources or EObjects, according to the entry point of the comparison. Take note that '''the scope is only used during the matching phase'''. The differencing phase only uses the result of the matching phase to proceed.

-

-=== Longest Common Subsequence ===

-

-PENDING description of the algorithm, why do we use it, references

-

-== Default Behavior and Extensibility ==

-

-All main components of EMF Compare have been designed for extensibility. Some are only extensible when comparing models through your own actions, some can be customized globally for a given kind of model or metamodel... We'll outline the customization options of all 6 comparison phases in this section. (Any dead link? Report them on the [http://www.eclipse.org/forums/index.php/f/164/ forum]!)

-

-=== Model Resolving ===

-

-PENDING description of the phase, extensibility (use of the modelProviders extension point, custom ext point of compare)

-

-=== Match ===

-

-Before we can compute differences between two versions of a same Object, we must determine which are actually the "same" Object. For example, let's consider that my first model contains a Package P1 which itself contains a class C1; and that my second model contains a package P1 which contains a class C1. It may seem obvious for a human reader that "P1" and "C1" are the same object in both models. However, since their features might have changed in-between the two versions (for example, the "C1" might now be abstract, or it could have been converted to an Interface), this "equality" is not that obvious for a computer.

-

-The goal of the "Match" phase is to discover which of the objects from model 2 match with which objects of model 1. In other words, this is when we'll say that two objects are one and the same, and that any difference between the two sides of this couple is actually a difference that should be reported as such to the user.

-

-By default, EMF Compare browses through elements that are within the scope, and matches them through their identifier if they have one, or through a distance mechanism for all elements that have none. If the scope contains resources, EMF Compare will first match those two-by-two before browsing through all of their contained objects.

-

-EMF Compare "finds" the identifier of given object through a basic function that can be found in [http://git.eclipse.org/c/emfcompare/org.eclipse.emf.compare.git/tree/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/match/eobject/IdentifierEObjectMatcher.java#n268 IdentifierEObjectMatcher.DefaultIDFunction]. In short, if the object is a proxy, its identifier is its URI fragment. Otherwise its functional ID (in ecore, an attribute that serves as an identifier) takes precedence over its XMI ID (the identifier it was given in the XMI file). If the object is not a proxy and has neither functional nor XMI identifier, then the default behavior will simply pass that object over to the proximity algorithms so that it can be matched through its distance with other objects.

-

-PENDING: brief description of the proximity algorithm

-

-This behavior can be customized in a number of ways.

-

-==== Overriding the Match engine ====

-

-The most powerful (albeit most cumbersome) customization you can implement is to override the match engine EMF Compare uses. To this end you can either [http://git.eclipse.org/c/emfcompare/org.eclipse.emf.compare.git/tree/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/match/IMatchEngine.java implement the whole contract, ''IMatchEngine''], in which case you will have to carefully follow the javadoc's recommandations, or extend the [http://git.eclipse.org/c/emfcompare/org.eclipse.emf.compare.git/tree/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/match/DefaultMatchEngine.java default implementation, ''DefaultMatchEngine''].

-

-A custom match engine can be used for your model comparison needs:

-

-<source lang="java">

-// for standalone usage

-IMatchEngine.Factory.Registry registry === MatchEngineFactoryRegistryImpl.createStandaloneInstance();

-// for OSGi (IDE, RCP) usage

-// IMatchEngine.Factory.Registry registry === EMFCompareRCPPlugin.getMatchEngineFactoryRegistry();

-final IMatchEngine customMatchEngine === new MyMatchEngine(...);

-IMatchEngine.Factory engineFactory === new MatchEngineFactoryImpl() {

-  public IMatchEngine getMatchEngine() {

-    return customMatchEngine;

-  }

-};

-engineFactory.setRanking(20); // default engine ranking is 10, must be higher to override.

-registry.add(engineFactory);

-EMFCompare.builder().setMatchEngineFactoryRegistry(registry).build().compare(scope);

-</source>

-

-==== Changing how resources are matched ====

-

-By default, the logic EMF Compare uses to match resources together is very simple: if two resources have the same name (strict equality on the name, without considering folders), they match. When this is not sufficient, EMF Compare will look at the XMI ID of the resources' root(s). If the two resources share at least one root with an equal XMI ID, they match.

-

-This can be changed only by implementing your own subclass of the DefaultMatchEngine and overriding its resource matcher. The method of interest here is [http://git.eclipse.org/c/emfcompare/org.eclipse.emf.compare.git/tree/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/match/DefaultMatchEngine.java#n319 DefaultMatchEngine#createResourceMatcher()].

-

-==== Defining custom identifiers ====

-

-In some cases, there might be ways to identify your objects via the use of "identifiers" that cannot be identified as such by the default mechanism. For example, you might want each of your objects to be matched through their name alone, or through the composition of their name and their type... This can be achieved through code by simply redefining the function EMF Compare uses to find the ID of an object. The following code will tell EMF Compare that the identifier of all "MyEObject" elements is their name, and that any other element should go through the default behavior.

-

-<source lang="java">

-Function<EObject, String> idFunction === new Function<EObject, String>() {

-	public String apply(EObject input) {

-		if (input instanceof MyEObject) {

-			return ((MyEObject)input).getName();

-		}

-		// a null return here tells the match engine to fall back to the other matchers

-		return null;

-	}

-};

-// Using this matcher as fall back, EMF Compare will still search for XMI IDs on EObjects

-// for which we had no custom id function.

-IEObjectMatcher fallBackMatcher === DefaultMatchEngine.createDefaultEObjectMatcher(UseIdentifiers.WHEN_AVAILABLE);

-IEObjectMatcher customIDMatcher === new IdentifierEObjectMatcher(fallBackMatcher, idFunction);

- 

-IComparisonFactory comparisonFactory === new DefaultComparisonFactory(new DefaultEqualityHelperFactory());

- 

-IMatchEngine matchEngine === new DefaultMatchEngine(customIDMatcher, comparisonFactory);

-IMatchEngine.Factory.Registry registry === MatchEngineFactoryRegistryImpl.createStandaloneInstance();

-// for OSGi (IDE, RCP) usage

-// IMatchEngine.Factory.Registry registry === EMFCompareRCPPlugin.getMatchEngineFactoryRegistry();

-engineFactory.setRanking(20); // default engine ranking is 10, must be higher to override.

-registry.add(engineFactory);

-EMFCompare.builder().setMatchEngineFactoryRegistry(registry).build().compare(scope);

-</source>

-

-==== Ignoring identifiers ====

-

-There are some cases where you do not want the identifiers of your elements to be taken into account when matching the objects. This can easily be done when calling for comparisons programmatically:

-

-'''Through code'''

-

-<source lang="java">

-IEObjectMatcher matcher === DefaultMatchEngine.createDefaultEObjectMatcher(UseIdentifiers.NEVER);

-IComparisonFactory comparisonFactory === new DefaultComparisonFactory(new DefaultEqualityHelperFactory());

-

-IMatchEngine matchEngine === new DefaultMatchEngine(matcher , comparisonFactory);

-EMFCompare.builder().setMatchEngine(matchEngine).build().compare(scope);

-</source>

-

-'''From the user interface'''

-

-PENDING: preference page

-

-==== Refine the default Match result ====

-

-If you are happy with most of what the default behavior does, but would like to refine some of it, you can do so by post-processing the result of the match phase. The original models are only used when matching, and will never be queried again afterwards. All remaining phases are incremental refinings of the "Comparison" model that's been created by the matching phase.

-

-As such, you can impact all of the differencing process through this. Within this post-processing implementation, you can:

-* Remove ''Match'' elements

-: no difference will be detected on those: neither additions, nor deletions, nor conflicts... They'll simply be entirely ignored by the remaining process. Do note that elements for which we have no match will be considered "distinct" by the innards of EMF Compare: if a couple "B<->B'" references a couple "C<->C'" through one of their references, but you have removed the ''Match'' "C<->C'", we will consider that this reference has been "changed" from C to C' and this difference within the references of B will be shown as such.

-* Add new ''Match'' element

-: the new couples of elements will be considered by the remaining comparison process and difference may be detected on them.

-* Change existing ''Match'' elements

-: unmatched elements have two or three associated ''Match'' objects. For example if you are comparing three version of a model which all contain a different version of a given package, and all three version change the name of this package: version 1 has package "P1", version 2 has package "P2" and version three has package "P3". This package is actually the same, but EMF Compare did not manage to match it. We will thus have three ''Match'' objects: one that references "P1" as ''left'', one that references "P2" as ''right'' and one that references "P3" as ''origin''.

-: You may remove two of those three elements and change the third one so that it references P1 as ''left'', P2 as ''right'' and P3 as ''origin''. In such a case, those three will be considered to Match for the remainder of the comparison process. Make sure that there are not two different ''Match'' referencing the same object though, as this would yield unspecified results.

-

-Defining a custom post-processor requires you to implement [http://git.eclipse.org/c/emfcompare/org.eclipse.emf.compare.git/tree/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/postprocessor/IPostProcessor.java IPostProcessor] and registering this sub-class against EMF Compare. The latter can be done via either an extension point, in which case it will be considered for '''all''' comparisons on models that match its enablement, or programmatically if you only want it active for your own actions:

-

-'''Through code'''

-

-The following registers a post-processor for all UML models. This post-processor will not be triggered if there are no UML models (matching the given namespace URI) within the compared scope.

-

-<source lang="java">

-IPostProcessor customPostProcessor === new CustomPostProcessor();

-IPostProcessor.Descriptor descriptor === new BasicPostProcessorDescriptorImpl(customPostProcessor, Pattern.compile("http://www.eclipse.org/uml2/\\d\\.0\\.0/UML"), null);

-

-PostProcessor.Registry registry === new PostProcessorDescriptorRegistryImpl();

-registry.put(CustomPostProcessor.class.getName(), descriptor);

-Comparison comparison === EMFCompare.builder().setPostProcessorRegistry(registry).build().compare(scope);

-</source>

-

-'''Through extension point'''

-

-This accomplishes the exact same task, but it registers the post-processor globally. Any comparison through EMF Compare on a scope that contains models matching the given namespace URI will trigger that post-processor.

-

-<source lang="xml">

-<extension point="org.eclipse.emf.compare.rcp.postProcessor">

-      <postProcessor class="my.package.CustomPostProcessor">

-         <nsURI value="http://www.eclipse.org/uml2/\\d\\.0\\.0/UML">

-         </nsURI>

-      </postProcessor>

-</source>

-

-=== Diff ===

-

-Now that the Matching phase has completed and that we know how our objects are coupled together, EMF Compare no longer requires the two (or three) input models. It will no longer iterate over them or the comparison's input scope. From this point onward, only the result of our comparison, the ''Comparison'' object, will be refined through the successive remaining phases, starting by the '''Diff'''.

-

-The goal of this phase is to iterate over all of our ''Match'' elements, be they unmatched (only one side has this object), couples (two of the three sides contain this object) or trios (all three sides have this object) and compute any difference that may appear between the sides. For example, an object that is only on one side of the comparison is an object that has been added, or deleted. But a couple might also represent a deletion: during three way comparisons, if we have an object in the common ancestor (origin) and in the left side, but not in the right side, then it has been deleted from the right version. However, this latter example might also be a conflict: we have determined that the object has been removed from the right side... but there might also be differences between the original version and the "left" version.

-

-The differencing phase does not care about conflicts though: all it does is refine the comparison to tell that this particular ''Match'' has ''n'' diffs: one ''DELETE'' difference on the right side, and ''n'' differences on the left. Detecting conflicts between these differences will come at a later time, during the conflict resolution phase.

-

-Customizations of this phase usually aim at ignoring specific differences.

-

-==== Overriding the Diff engine ====

-

-As is the case for the Match phase, the most powerful customization you can implement for the differencing process is to override the diff engine EMF Compare uses. To this end you can either [http://git.eclipse.org/c/emfcompare/org.eclipse.emf.compare.git/tree/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/diff/IDiffEngine.java implement the whole contract, ''IDiffEngine''], in which case you will have to carefully follow the javadoc's recommandations, or extend the [http://git.eclipse.org/c/emfcompare/org.eclipse.emf.compare.git/tree/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/diff/DefaultDiffEngine.java default implementation, ''DefaultDiffEngine''].

-

-A custom diff engine can then be used for your comparisons:

-

-<source lang="java">

-IDiffEngine customDiffEngine === new MyDiffEngine(...);

-EMFCompare.builder().setDiffEngine(customDiffEngine).build().compare(scope);

-</source>

-

-==== Changing the FeatureFilter ====

-

-One of the differencing engine's responsibilities is to iterate over all features of a given object in order to check for potential differences on its value(s). However, there are some features that we decide do ignore by default: derived features, transient features... or some features on which we would like to check for ordering changes even though they are marked as non-ordered.

-

-The logic to determine whether a feature should be checked for differences has been extracted into its own class, and is quite easy to alter. For example, if you would like to ignore the ''name'' feature of your elements or never detect any ordering change:

-

-<source lang="java">

-IDiffProcessor diffProcessor === new DiffBuilder();

-IDiffEngine diffEngine === new DefaultDiffEngine(diffProcessor) {

-	@Override

-	protected FeatureFilter createFeatureFilter() {

-		return new FeatureFilter() {

-			@Override

-			protected boolean isIgnoredReference(Match match, EReference reference) {

-				return reference ==== EcorePackage.Literals.ENAMED_ELEMENT__NAME ||

-						super.isIgnoredReference(match, reference);

-			}

-

-			@Override

-			public boolean checkForOrderingChanges(EStructuralFeature feature) {

-				return false;

-			}

-		};

-	}

-};

-EMFCompare.builder().setDiffEngine(diffEngine).build().compare(scope);

-</source>

-

-You could also [[#Changing the Diff Processor|change the diff processor]] to achieve a similar goal. The difference between the two approaches is that changing the ''FeatureFilter'' will ignore the structural feature altogether, whereas replacing the diff processor would let EMF Compare check the feature and detect that diff, but ignore the notification that there is a change.

-

-==== Changing the Diff Processor ====

-

-The diff engine browses over all of the objects that have been matched, and checks all of their features in order to check for changes between the two (or three) versions' feature values. When it detects a change, it delegates all of the corresponding information to its associated ''Diff Processor'', which is in charge of actually creating the ''Diff'' object and appending it to the resulting ''Comparison''.

-

-Replacing the ''Diff Processor'' gives you a simple entry point to ignore some of the differences the default engine detects, or to slightly alter the ''Diff'' information. You might want to ignore the differences detected on some references for example. Or you might want to react to the detected diff without actually creating the ''Comparison'' model... The implementation is up to you. You can either reimplement the [http://git.eclipse.org/c/emfcompare/org.eclipse.emf.compare.git/tree/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/diff/IDiffProcessor.java whole contract] or extend the default implementation, [http://git.eclipse.org/c/emfcompare/org.eclipse.emf.compare.git/tree/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/diff/DiffBuilder.java ''DiffBuilder'']

-

-Here is a simple example that provides EMF Compare with a diff processor that will ignore all differences detected on the "name" attribute of our objects, yet keep the default behavior for all other differences.

-

-<source lang="java">

-IDiffProcessor customDiffProcessor === new DiffBuilder() {

-	@Override

-	public void attributeChange(Match match, EAttribute attribute, Object value, DifferenceKind kind, DifferenceSource source) {

-		if (attribute !== EcorePackage.Literals.ENAMED_ELEMENT__NAME) {

-			super.attributeChange(match, attribute, value, kind, source);

-		}

-	}

-};

-

-IDiffEngine diffEngine === new DefaultDiffEngine(customDiffProcessor);

-EMFCompare.builder().setDiffEngine(diffEngine).build().compare(scope);

-</source>

-

-==== Refine the default Diff result ====

-

-The last possibility offered by EMF Compare to alter the result of the differencing phase is to post-process it. The remaining comparison phases -equivalence detection, detection of dependencies between diffs and conflict detection- all use the result of the Diff engine and refine it even further. As such, all of these phases can be impacted through the refining of the Diff result.

-

-Example uses of the post-processing would include:

-

-* Remove ''Diff'' elements

-: If you'd rather code your logic to ignore differences here as a post-process instead of changing the ''FeatureFilter'' or ''IDiffProcessor''. Though that is not the best way to ignore differences, it can still be done here.

-

-* Add new ''Diff'' elements

-: If you want to create new differences without implementing a whole differencing engine, new differences can still be created here as a post-process. You will need to implement the iteration over model elements and specific checks yourself though. This workaround can also be used to create new differences that the default differencing engine does not know.

-

-* Alter the detected differences

-: If some of the differences have been detected in a way you do not like, and you did not use a custom ''IDiffProcessor'' to change the ''Diff'' information, you can do so here.

-

-The post-processor for the diff engine is implemented exactly in the same way as for the match engine post-processors (the interface and extension point are the same). Please refer to [[#Refine the default Match result|Refining the Match result]].

-

-=== Equivalences ===

-

-Now that the Differencing phase has ended, we've computed all of the individual differences within the compared models. However, all of these differences are still isolated, we now need to determine if there are any connections between them.

-

-An ''equivalence'' is one kind of potential connections between differences. For example, Ecore has a concept of ''eOpposite'' references, which be maintained in sync with one another. Modifying one of the two references will automatically update the other side of the opposition accordingly. Both the manual modification and the automatic update are considered as distinct modifications of the model when looking at it after the fact, resulting in two differences detected. However, merging any of these two differences will automatically merge the other one. Therefore, both are marked as being ''equivalent'' to each other.

-

-Though that is an example with two, more than two differences can be considered equivalent with each other. When we merge one difference, all of the other diffs that have been marked as being equivalent to it will be marked as ''MERGED'', though no actual work needs to be done to merge them : EMF will have automatically updated them when merging the first.

-

-Do note that EMF Compare detects and understand two different kind of relations that could be considered "equivalences". Described above are plain equivalences, when merging one of the differences will automatically update the model in such a way that all other sides of the equivalence are redundant and automatically merged. However, equivalences might not always be that easy. Let's take for example the case of UML : UML has concepts of ''subset'' and ''superset'' references. Adding an object into a subset will automatically update the related superset so that it also contains the added element. However, adding that same element to the superset will _not_ automatically update the related subset.

-

-This can be seen as a "directional" equivalence, where one difference D1 ''implies'' another D2, but is not ''implied by'' D2. Implications will be detected at the same time as the equivalences, but they do not use an ''Equivalence'' element, they are filled under the ''Diff#implies'' reference instead.

-

-==== Refine the default equivalences ====

-

-This phase does not offer as many customization options as the previous ones; though post-processing should be enough for most needs. All of the phases that come after the differencing are further refinements of the comparison model, totally independent from one another. From here, any client of the API can refine the comparison model any way he'd like to, even by removing all of the default results.

-

-A few examples of customizations that could be made from here :

-* Partly break existing equivalences

-: You can modify the equivalences we've detected by default by removing elements from individual differences' equivalences (Diff#getEquivalence()) or by changing the ''Equivalence'' elements directly.

-* Remove existing ''Equivalence'' elements

-: If you'd rather remove the ''Equivalence'' elements altogether, it can also be done from here without impact down the line. The individual differences will be merged individually (potentially twice if EMF automatically updates the references) if the mergers do not have this to tell them what's equivalent to what.

-* Detect your own equivalences

-: If you have specific rules on your metamodel or implementation that make some differences redundant or otherwise fully equivalent to one another, you can add your own equivalences from here.

-

-The post-processor for the equivalence detection engine is implemented exactly in the same way as for the match engine post-processors (the interface and extension point are the same). Please refer to [[#Refine the default Match result|Refining the Match result]].

-

-=== Requirements ===

-

-A requirement will be used to deal with structural constraints (to prevent dangling references or objects without parent) and to insure the model integrity.

-A difference requires other ones if the merge of this one needs the other ones not to "break" the model.

-The merge of a difference involves the merge of the required differences. All these differences will be merged by EMF Compare.

-For example, the add of a reference requires the add of the referenced object and the add of the object containing this reference.

-

-{| cellspacing="1" cellpadding="1" border="1"

-|-

-! align="center" | Change kind

-! align="center" | Reference kind to a graphical object

-! align="left"   | &nbsp; Requires:

-|-

-| rowspan="2" align="center" | ADD

-| align="center" | content

-| &nbsp; ADD of its container<br>&nbsp; DELETE of the origin value on the same containment mono-valued reference

-|-

-| align="center" | reference

-| &nbsp; ADD of the target object<br>&nbsp; ADD of the source object e.g. The ADD of a reference to the target or source of an edge requires the ADD of the edge itself and the ADD of the target and source objects, the ADD of a reference to the semantic object from a graphical one requires the ADD of the graphical and semantic object.

-|-

-| align="center" | DELETE

-| align="center" | content

-| &nbsp; DELETE of the outgoing references and contained objects<br>&nbsp; DELETE/CHANGE of the incoming references<br>&nbsp; MOVE of the contained objects

-|-

-| align="center" | MOVE

-| align="center" | content

-| &nbsp; ADD of the new container of the object<br>&nbsp; MOVE of the new container of the object

-|-

-| align="center" | CHANGE

-| align="center" | reference permutation

-| &nbsp; ADD of the target object

-|}

-

-

-Requirements can be added during a post-process.

-

-=== Refinement ===

-

-A refinement enables to group a set of unit differences into a macroscopic change.

-<br>A unit difference refines a macroscopic one if it belongs to this macroscopic change. In other words, a macroscopic change is refined by a set of unit differences.

-<br>The merge of a macroscopic change involves the merge of the refining differences. All these differences will be merged by EMF Compare.

-<br>The use of the refinement allows to improve (simplify) the reading of the comparison from a business viewpoint, to accelerate the manual merging for the end-user and to insure some consistency.

-<br>For example, the add of an association, in UML, is refined by the add of the UML Association itself but also the add of the UML properties with the update of references...

-

-Refinement can be added during a post-process.

-

-=== Conflicts ===

-

-PENDING description of the phase, extensibility options (post-process)

-

-=== Merging ===

-

-==== Which references are followed during merging ====

-

-{| border="1"

-|-

-! &nbsp; 

-! Merge from Left to Right

-! Merge from Right to Left

-|-

-! Source === Left

-| align="center" | requires  

-| align="center" | requiredBy  

-|-

-! Source === Right

-| align="center" | requiredBy  

-| align="center" | requires  

-|}

-

-

-PENDING how to provide custom mergers, override existing ones?

-

-=== User Interface ===

-

-==== Add your own filter ====

-

-You can provide your own filters by adding an extension of type ''org.eclipse.emf.compare.rcp.ui.filters'' to your plugin.

-

-[[Image:./../images/EMF_Compare_Developer_New_Extension_Filter.png|center]]

-

-This extension has three fields:

-* class: a class that implements ''org.eclipse.emf.compare.rcp.ui.structuremergeviewer.filters.IDifferenceFilter''

-* label: the label that will be displayed in the UI.

-* activeByDefault: true if you want your filter be active by default, false otherwise.

-* description: A human-readable description for this filter. It will be displayed in the EMF Compare UI.

-

-The ''org.eclipse.emf.compare.rcp.ui.structuremergeviewer.filters.IDifferenceFilter'''s contract is:

-

-<source lang="java">

-/**

- * Instances of this class will be used by EMF Compare in order to provide difference filter facilities to the

- * structural differences view.

- * @since 4.0

- */

-public interface IDifferenceFilter {

-

-	/**

-	 * Returns the predicate that will filter out objects in the structural differences view when this filter

-	 * will be selected.

-	 * 

-	 * @return the predicate that will filter out objects in the structural differences view when this filter

-	 *         will be selected.

-	 */

-	Predicate<? super EObject> getPredicateWhenSelected();

-

-	/**

-	 * Returns the predicate that will filter out objects in the structural differences view when this filter

-	 * will be unselected.

-	 * 

-	 * @return the predicate that will filter out objects in the structural differences view when this filter

-	 *         will be unselected.

-	 */

-	Predicate<? super EObject> getPredicateWhenUnselected();

-

-	/**

-	 * A human-readable label for this filter. This will be displayed in the EMF Compare UI.

-	 * 

-	 * @return The label for this filter.

-	 */

-	String getLabel();

-

-	/**

-	 * Set the label for this filter. This will be displayed in the EMF Compare UI.

-	 * 

-	 * @param label

-	 *            A human-readable label for this filter.

-	 */

-	void setLabel(String label);

-

-	/**

-	 * Returns the initial activation state that the filter should have.

-	 * 

-	 * @return The initial activation state that the filter should have.

-	 */

-	boolean defaultSelected();

-

-	/**

-	 * Set the initial activation state that the filter should have.

-	 * 

-	 * @param defaultSelected

-	 *            The initial activation state that the filter should have (true if the filter should be

-	 *            active by default).

-	 */

-	void setDefaultSelected(boolean defaultSelected);

-

-	/**

-	 * Returns the activation condition based on the scope and comparison objects.

-	 * 

-	 * @param scope

-	 *            The scope on which the filter will be applied.

-	 * @param comparison

-	 *            The comparison which is to be displayed in the structural view.

-	 * @return The activation condition based on the scope and comparison objects.

-	 */

-	boolean isEnabled(IComparisonScope scope, Comparison comparison);

-}

-</source>

-

-A default abstract implementation named ''org.eclipse.emf.compare.rcp.ui.structuremergeviewer.filters.impl.AbstractDifferenceFilter'' is available in the ''org.eclipse.emf.compare.rcp.ui'' plugin. With this abstract implementation, all you have to do is to subclass it and implements the ''getPredicateWhenSelected()'' method.

-

-==== Add your own group ====

-

-You can provide your own groups by adding an extension of type ''org.eclipse.emf.compare.rcp.ui.groups'' to your plugin.

-

-[[Image:./../images/EMF_Compare_Developer_New_Extension_Group.png|center]]

-

-This extension has three fields:

-* class: a class that implements ''org.eclipse.emf.compare.rcp.ui.structuremergeviewer.groups.IDifferenceGroupProvider''

-* label: the label that will be displayed in the UI.

-* description: A description of the group. (Used in interface)

-* rank: The rank of the group. The highest rank enabled for a comparison is used. ( Default value : 0)

-* type: Type of comparison this group can handle (Default value: BOTH).

-** THREE_WAY: This group can only handle three way comparison.

-** TWO_WAY: This group can handle two way comparison.

-** BOTH: This group can handle two and three way comparisons.

-

-The ''org.eclipse.emf.compare.rcp.ui.structuremergeviewer.groups.IDifferenceGroupProvider'''s contract is:

-

-<source lang="java">

-/**

- * Instances of this class will be used by EMF Compare in order to provide difference grouping facilities to

- * the structural differences view.

- * @since 4.0

- */

-public interface IDifferenceGroupProvider extends Adapter {

-

-	/**

-	 * This will be called internally by the grouping actions in order to determine how the differences should

-	 * be grouped in the structural view.

-	 * 

-	 * @param comparison

-	 *            The comparison which is to be displayed in the structural view. By default, its containment

-	 *            tree will be displayed.

-	 * @return The collection of difference groups that are to be displayed in the structural viewer. An empty

-	 *         group will not be displayed at all. If {@code null}, we'll fall back to the default behavior.

-	 */

-	Collection<? extends IDifferenceGroup> getGroups(Comparison comparison);

-

-	/**

-	 * A human-readable label for this group. This will be displayed in the EMF Compare UI.

-	 * 

-	 * @return The label for this group.

-	 */

-	String getLabel();

-

-	/**

-	 * Set the label for this group. This will be displayed in the EMF Compare UI.

-	 * 

-	 * @param label

-	 *            A human-readable label for this group.

-	 */

-	void setLabel(String label);

-

-	/**

-	 * Returns the initial activation state that the group should have.

-	 * 

-	 * @return The initial activation state that the group should have.

-	 */

-	boolean defaultSelected();

-

-	/**

-	 * Set the initial activation state that the group should have.

-	 * 

-	 * @param defaultSelected

-	 *            The initial activation state that the group should have (true if the group should be active

-	 *            by default).

-	 */

-	void setDefaultSelected(boolean defaultSelected);

-

-	/**

-	 * Returns the activation condition based on the scope and comparison objects.

-	 * 

-	 * @param scope

-	 *            The scope on which the group provider will be applied.

-	 * @param comparison

-	 *            The comparison which is to be displayed in the structural view.

-	 * @return The activation condition based on the scope and comparison objects.

-	 */

-	boolean isEnabled(IComparisonScope scope, Comparison comparison);

-

-	/**

-	 * Dispose this difference group provider.

-	 */

-	void dispose();

-	

-	/**

-	 * Returns all {@link TreeNode}s that are wrapping the given {@code eObject}. It internally use a cross

-	 * reference adapter.

-	 * 

-	 * @param eObject

-	 *            the object from which we want inverse reference.

-	 * @return all {@link TreeNode}s targeting the given {@code eObject} through

-	 *         {@link TreePackage.Literals#TREE_NODE__DATA}.

-	 */

-	List<TreeNode> getTreeNodes(EObject eObject);

-}

-</source>

-

-An ''IDifferenceGroupProvider'' provides a set of ''IDifferenceGroup''.

-A group provider's default abstract implementation named ''org.eclipse.emf.compare.rcp.ui.structuremergeviewer.groups.impl.AbstractDifferenceGroupProvider'' is available in the ''org.eclipse.emf.compare.rcp.ui'' plugin. With this abstract implementation, all you have to do is to subclass it and implements the ''getGroups()'' method.

-

-For example, the ''By Kind'' group provider has 4 groups: Additions, Deletions, Changes and Moves.

-

-A group's default implementation named ''org.eclipse.emf.compare.rcp.ui.internal.structuremergeviewer.groups.BasicDifferenceGroupImpl'' is available in the ''org.eclipse.emf.compare.rcp.ui'' plugin. With this default implementation, all you have to do is to subclass it and overrides the ''getChildren()'' method.

-Note that default implementation is ''internal'' and subject to modifications.

-

-==== Customize display of differences inside an existing group ====

-

-You can customize display of differences inside an existing group by adding an extension of type ''org.eclipse.emf.compare.rcp.ui.differenceGroupExtender'' to your plugin.

-

-[[Image:./../images/EMF_Compare_Developer_New_Extension_Extender.png|center]]

-

-This extension has one field:

-* class: a class that implements ''org.eclipse.emf.compare.rcp.ui.structuremergeviewer.groups.extender.IDifferenceGroupExtender''

-

-The ''org.eclipse.emf.compare.rcp.ui.structuremergeviewer.groups.extender.IDifferenceGroupExtender'''s contract is:

-

-<source lang="java">

-/**

- * Instances of this class will be used by EMF Compare in order to extend the children of TreeNodes containing

- * in the structure merge viewer.

- * 

- * @since 4.0

- */

-public interface IDifferenceGroupExtender {

-

-	/**

-	 * Checks if the given TreeNode have to be handled by the extender.

-	 * 

-	 * @param treeNode

-	 *            the given TreeNode.

-	 * @return true if the TreeNode have to be handled, false otherwise.

-	 */

-	boolean handle(TreeNode treeNode);

-

-	/**

-	 * Add children to the given TreeNode.

-	 * 

-	 * @param treeNode

-	 *            the given TreeNode.

-	 */

-	void addChildren(TreeNode treeNode);

-}

-</source>

-

-There is no default implementation of extender. Examples of extender implementations are available in the ''org.eclipse.emf.compare.diagram.ide.ui'' plugin.

-

-==== Add your own accessor factory ====

-

-You can add your own accessor factory by adding an extension of type ''org.eclipse.emf.compare.rcp.ui.accessorFactory'' to your plugin.

-

-[[Image:./../images/EMF_Compare_Developer_New_Extension_AccessorFactory.png|center]]

-

-This extension has one field:

-* class: a class that implements ''org.eclipse.emf.compare.rcp.ui.contentmergeviewer.accessor.factory.IAccessorFactory''

-* ranking : the ranking of this accessor factory.

-

-The ''org.eclipse.emf.compare.rcp.ui.contentmergeviewer.accessor.factory.IAccessorFactory'''s contract is:

-

-<source lang="java">

-/**

- * A factory of {@link ITypedElement}s.

- * 

- * @since 4.0

- */

-public interface IAccessorFactory {

-

-	/**

-	 * Checks if the target object is applicable to the factory.

-	 * 

-	 * @param target

-	 *            the object for which we want to know if it is applicable to the factory.

-	 * @return true if the object is applicable to the factory, false otherwise.

-	 */

-	boolean isFactoryFor(Object target);

-

-	/**

-	 * The ranking of the factory.

-	 * 

-	 * @return the ranking of the factory.

-	 */

-	int getRanking();

-

-	/**

-	 * Set the ranking of the factory.

-	 * 

-	 * @param value

-	 *            the ranking value.

-	 */

-	void setRanking(int value);

-

-	/**

-	 * Creates an {@link ITypedElement} from an {@link AdapterFactory} and a given object. This accessor is

-	 * specific for the left side of the comparison.

-	 * 

-	 * @param adapterFactory

-	 *            the given adapter factory.

-	 * @param target

-	 *            the given object.

-	 * @return an ITypedElement.

-	 */

-	ITypedElement createLeft(AdapterFactory adapterFactory, Object target);

-

-	/**

-	 * Creates an {@link ITypedElement} from an {@link AdapterFactory} and a given object. This accessor is

-	 * specific for the right side of the comparison.

-	 * 

-	 * @param adapterFactory

-	 *            the given adapter factory.

-	 * @param target

-	 *            the given object.

-	 * @return an ITypedElement.

-	 */

-	ITypedElement createRight(AdapterFactory adapterFactory, Object target);

-

-	/**

-	 * Creates an {@link ITypedElement} from an {@link AdapterFactory} and a given object. This accessor is

-	 * specific for the ancestor side of the comparison.

-	 * 

-	 * @param adapterFactory

-	 *            the given adapter factory.

-	 * @param target

-	 *            the given object.

-	 * @return an ITypedElement.

-	 */

-	ITypedElement createAncestor(AdapterFactory adapterFactory, Object target);

-}

-</source>

-

-An ITypedElement is an interface for getting the name, image, and type for an object. An ITypedElement is used to present an input object in the compare UI (getName and getImage) and for finding a viewer for a given input type (getType).

-

-There is no default implementation of accessor factory. Examples of accessor factories implementations are available in the ''org.eclipse.emf.compare.rcp.ui'' plugin. There is several existing accessor factories in EMF Compare: for Matches, ReferenceChanges, AttibuteChanges, ResourceAttachmentChanges...

-

-PENDING customize display of custom differences, add custom menu entries, add export options, provide custom content viewer

-

-== Using The Compare APIs ==

-

-The main entry point of EMF Compare is the ''org.eclipse.emf.compare.EMFCompare'' class. It is what should be used in order to configure and launch a comparison. That is not all though. Once you have compared two models, you want to query the differences, maybe merge some of them, display the comparison result in the comparison editor... The following section will list the main entry points for each of these actions, along with a brief description of what can be done and what should be avoided.

-

-Most of these examples are set-up as "standalone" examples, and will include extra instructions for IDE use: pay attention to the environment in which you are using EMF Compare. Are you using it from an Eclipse plugin, in which case you'd like all of the extra features provided through extension points and contribution to be available to you? Or are you using it from a standalone environment, in which case you'd need to reduce the dependencies to the bare minimum and avoid OSGi-related code and extensions?

-

-=== Compare two models ===

-

-==== Loading your models ====

-

-Whether you wish to compare two or three models, the first thing you need is to load them. We won't detail in-depth how to do that as this is standard EMF practice, you might want to look at EMF tutorial for detailled instructions on this point. Here, we'll use a simple method that loads an xmi file at a given URL into a resourceSet, expecting the given URL to be an absolute file URL:

-

-<source lang="java">

-public void load(String absolutePath, ResourceSet resourceSet) {

-  URI uri === URI.createFileURI(absolutePath);

-

-  resourceSet.getResourceFactoryRegistry().getExtensionToFactoryMap().put("xmi", new XMIResourceFactoryImpl());

-

-  // Resource will be loaded within the resource set

-  resourceSet.getResource(uri, true);

-}

-</source>

-

-==== Creating the comparison scope ====

-

-EMF Compare uses a scoping mechanism to determine which elements should be compared, and which others should be ignored. Any element that is outside of the comparison scope will be ignored by the comparison engine and left alone (if it is a proxy, it won't even be loaded). As such, extra care should be taken to determine the proper scope of the comparison or customize the IEqualityHelper to handle the specific elements you remove from the scope. Refer to the [[#Comparison Scope|appropriate section]] above for more on the scoping mechanism.

-

-By default, the only thing that EMF Compare considers "out of scope" are Ecore's "EGenericType" elements. These are usually meaningless as far as comparison is concerned (as they are located in derived references and will be merged along with their "true" difference anyway). Other than that, Please note that EMF Compare will leave unresolved proxies alone: more on this can be found in the [[#Proxy Resolution|related section]].

-

-The default scope can be easily created through:

-

-<source lang="java">

-IComparisonScope scope === EMFCompare.createDefaultScope(resourceSet1, resourceSet2);

-</source>

-

-==== Configuring the comparison ====

-

-EMF Compare can be customized in a number of ways, the most important of which were described [[#Default Behavior and Extensibility|above]]. Most of them re-use the same entry point, the ''org.eclipse.emf.compare.EMFCompare'' class. We won't customize much here, please see the afore-mentionned section for extensibility means.

-

-All we will tell EMF Compare is not to use identifiers, and rely on its proximity algorithms instead (after all, we're comparing plain XMI files):

-

-<source lang="java">

-IEObjectMatcher matcher === DefaultMatchEngine.createDefaultEObjectMatcher(UseIdentifiers.NEVER);

-IComparisonFactory comparisonFactory === new DefaultComparisonFactory(new DefaultEqualityHelperFactory());

- 

-IMatchEngine.Factory matchEngineFactory === new MatchEngineFactoryImpl(matcher, comparisonFactory);

-matchEngineFactory.setRanking(20);

-IMatchEngine.Factory.Registry matchEngineRegistry === new MatchEngineFactoryRegistryImpl();

-matchEngineRegistry.add(factory);

-

-EMFCompare comparator === EMFCompare.builder().setMatchEngineFactoryRegistry(matchEngineRegistry).build();

-

-</source>

-

-==== Putting it all together ====

-

-The following takes two input xmi files, loads them in their own resource sets, then calls the comparison without using identifiers:

-

-<source lang="java">

-public Comparison compare(File model1, File model2) {

-	// Load the two input models

-	ResourceSet resourceSet1 === new ResourceSetImpl();

-	ResourceSet resourceSet2 === new ResourceSetImpl();

-	String xmi1 === "path/to/first/model.xmi";

-	String xmi2 === "path/to/second/model.xmi";

-	load(xmi1, resourceSet1);

-	load(xmi2, resourceSet2);

-

-	// Configure EMF Compare

-	IEObjectMatcher matcher === DefaultMatchEngine.createDefaultEObjectMatcher(UseIdentifiers.NEVER);

-	IComparisonFactory comparisonFactory === new DefaultComparisonFactory(new DefaultEqualityHelperFactory());

-	IMatchEngine.Factory matchEngineFactory === new MatchEngineFactoryImpl(matcher, comparisonFactory);

-        matchEngineFactory.setRanking(20);

-        IMatchEngine.Factory.Registry matchEngineRegistry === new MatchEngineFactoryRegistryImpl();

-        matchEngineRegistry.add(matchEngineFactory);

-	EMFCompare comparator === EMFCompare.builder().setMatchEngineFactoryRegistry(matchEngineRegistry).build();

-

-	// Compare the two models

-	IComparisonScope scope === EMFCompare.createDefaultScope(resourceSet1, resourceSet2);

-	return comparator.compare(scope);

-}

-

-private void load(String absolutePath, ResourceSet resourceSet) {

-  URI uri === URI.createFileURI(absolutePath);

-

-  resourceSet.getResourceFactoryRegistry().getExtensionToFactoryMap().put("xmi", new XMIResourceFactoryImpl());

-

-  // Resource will be loaded within the resource set

-  resourceSet.getResource(uri, true);

-}

-</source>

-

-==== Comparing from an Eclipse plugin ====

-

-The above example is for standalone usage, and as such will require extra work if you wish to compare UML models, benefit from EMF Compare extensions, provide your own mergers... The following represents the same example, but uses IDE-specific utilities (can you spot the two differences?):

-

-<source lang="java">

-public Comparison compare(File model1, File model2) {

-	// Load the two input models

-	ResourceSet resourceSet1 === new ResourceSetImpl();

-	ResourceSet resourceSet2 === new ResourceSetImpl();

-	String xmi1 === "path/to/first/model.xmi";

-	String xmi2 === "path/to/second/model.xmi";

-	load(xmi1, resourceSet1);

-	load(xmi2, resourceSet2);

-

-	// Configure EMF Compare

-	IEObjectMatcher matcher === DefaultMatchEngine.createDefaultEObjectMatcher(UseIdentifiers.NEVER);

-	IComparisonFactory comparisonFactory === new DefaultComparisonFactory(new DefaultEqualityHelperFactory());

-	IMatchEngine matchEngine === new DefaultMatchEngine(matcher, comparisonFactory);

-        IMatchEngine.Factory.Registry matchEngineRegistry === EMFCompareRCPPlugin.getDefault().getMatchEngineFactoryRegistry();

-        IPostProcessor.Descriptor.Registry<String> postProcessorRegistry === EMFCompareRCPPlugin.getDefault().getPostProcessorRegistry();

-	EMFCompare comparator === EMFCompare.builder()

-                                           .setMatchEngineFactoryRegistry(matchEngineRegistry)

-                                           .setPostProcessorRegistry(postProcessorRegistry)

-                                           .build();

-

-	// Compare the two models

-	IComparisonScope scope === EMFCompare.createDefaultScope(resourceSet1, resourceSet2);

-	return comparator.compare(scope);

-}

-

-private void load(String absolutePath, ResourceSet resourceSet) {

-  URI uri === URI.createFileURI(absolutePath);

-

-  // Resource will be loaded within the resource set

-  resourceSet.getResource(uri, true);

-}

-</source>

-

-=== Query the differences ===

-

-Once you have the result of a comparison (in the form of a ''Comparison'' object), what you are interested in are most likely the differences between your models. We will detail the merging process later on it its own section, but before anything we need to retrieve the list of differences of interest. Within the Comparison model, differences are spread under the elements on which they've been detected, more precisely, under the ''Match'' of the element on which they were detected.

-

-Let's use a complex example as reference. Consider the three following models:

-

-{| border="1" cellpadding="5" cellspacing="0" align="center"

-|-

-! colspan="2" align="center" | Origin

-|-

-| colspan="2" align="center" | [[Image:./../images/EMF_Compare_Origin_Model.png|center]]

-|-

-! align="center" | Left

-! align="center" | Right

-|-

-| [[Image:./../images/EMF_Compare_Use_Compare_Master.png|center]]

-| [[Image:./../images/EMF_Compare_Use_Compare_5.png|center]]

-|}

-

-==== All differences ====

-

-What we need is usually to retrieve the list of ''all'' differences, wherever they were detected, or whatever their source (the left model, or the right model). Instead of iterating all over the Comparison model to collect them, you can use:

-

-<source lang="java">

-List<Diff> differences === comparison.getDifferences();

-</source>

-

-==== Differences related to element X ====

-

-Sometimes, we need to retrieve all of the differences that were detected on (or that are related to) a given model element. For example, with the above example, we might want to retrieve the list of all differences that relate to ''Borrowable''. Well, there are a number of them, which can all be collected through:

-

-<source lang="java">

-// borrowable is a reference on the like-named EObject

-List<Diff> differencesOnBorrowable === comparison.getDifferences(borrowable);

-</source>

-

-This will return a list containing a number of differences:

-

-* ''Borrowable'' has been added in the right model

-* ''copies'' has been added to reference ''ownedProperties'' of Borrowable

-* ''Borrowable'' has been added to the generalization reference of ''Book''

-* ''Borrowable'' has been added as the ''borrowed'' target of an association with ''Person''

-

-In other words, this method will return differences '''under''' the target (here, ''copies'' has been added), as well as differences which '''changed value''' is the target.

-

-==== Filtering differences ====

-

-EMF Compare depends on guava for many of its internals. A number of "common" difference filtering predicates have been extracted to the ''org.eclipse.emf.compare.utils.EMFComparePredicates'' utility class. Using this class, it is trivial to filter the list of differences so as to keep only those we are interested in. For example, what if we wish to retrieve the list of all '''non-conflictual''' differences that originate from the '''left''' side? (This is the case when you use the "copy all non-conflicting from left to right" action from the comparison editor for example.)

-

-<source lang="java">

-// Construct the predicate

-Predicate<? super Diff> predicate === and(fromSide(DifferenceSource.LEFT), not(hasConflict(ConflictKind.REAL, ConflictKind.PSEUDO));

-// Filter out the diff that do not satisfy the predicate

-Iterable<Diff> nonConflictualDifferencesFromLeft === filter(comparison.getDifferences(), predicate);

-</source>

-

-Note that for clarity, we've made static references to a number of methods here. This particular snippet requires the following imports:

-

-<source lang="java">

-import static com.google.common.base.Predicates.and;

-import static com.google.common.base.Predicates.not;

-import static com.google.common.collect.Iterables.filter;

-import static org.eclipse.emf.compare.utils.EMFComparePredicates.fromSide;

-import static org.eclipse.emf.compare.utils.EMFComparePredicates.hasConflict;

-</source>

-

-We strongly encourage you to look around more in these classes: ''Predicates'' provides a number of basic, general-purpose predicates while ''EMFComparePredicates'' provides EMF Compare specific predicates used throughout both core and user-interface of EMF Compare.

-

-=== Merge differences ===

-

-PENDING how to re-implement ''copyDiff'' and ''copyAllNonConflicting''

-

-entry points: org.eclipse.emf.compare.merge.IMerger and org.eclipse.emf.compare.merge.IBatchMerger

-

-=== Open a compare editor ===

-

-PENDING description of the need (dialog and editor), link to [[./how-to-open-compare-dialog.html|appropriate page]]

+= Developer Guide =
+
+== Architecture ==
+
+=== Comparison Process ===
+
+[[Image:./../images/EMF_Compare_Process_Full.png|center]]
+
+The above figure represents the comparison process of EMF Compare. It can be roughly divided in 6 main phases.
+
+==== Model Resolving ====
+From a given "starting point" (the file a user decided to compare), finding all other fragments required for the comparison of the whole logical model.
+==== Matching ====
+Iterating over the two (or three) loaded logical models in order to map elements together two-by-two (or three-by-three). For example, determine that class Class1 from the first model corresponds to class Class1' from the second model.
+==== Differencing ====
+The matching phase told us which elements were matching together. The differencing phase will browse through these mappings and determine whether the two (or three) elements are equal or if they present differences (for example, the name of the class changed from Class1 to Class1').
+==== Equivalences ====
+The differencing phases detected a number of differences between the compared models. However, two distinct differences might actually represent the same change. This phase will browse through all differences and link them together when they can be seen as equivalent (for example, differences on opposite references).
+==== Requirements ====
+For the purpose of merging differences, there might be dependencies between them. For example, the addition of a class C1 in package P1 depends on the addition of package P1 itself. During this phase, we'll browse through all detected differences and link them together when we determine that one cannot be merged without the other.
+==== Conflicts ====
+When we're comparing our file with one from a Version Control System (CVS, SVN, Git, Clearcase...), there might actually be conflicts between the changes we've made locally, and the changes that were made to the file on the remote repository. This phase will browse through all detected differences and detect these conflicts.
+
+The Model resolving phase itself can be further decomposed in its own two distinct phases. More on the logical model and its resolution can be found on the [[./logical-model.html|dedicated page]].
+
+[[Image:./../images/EMF_Compare_Model_Resolving.png|center]]
+
+=== Project Architecture ===
+
+[[Image:./../images/EMF_Compare_2_Architecture.png|center]]
+
+EMF Compare is built on top of the Eclipse platform. We depend on the Eclipse Modeling Framework (EMF), the Eclipse Compare framework and, finally, Eclipse Team, the framework upon which the repository providers (EGit, CVS, Subversive...) are built.
+
+The EMF Compare extensions target specific extensions of the modeling framework: UML, the Graphical Modeling Framework (and its own extensions, papyrus, ecoretools, ...).
+
+Whilst we are built atop bricks that are tightly coupled with the eclipse platform, it should be noted that the core of EMF Compare can be run in a standalone application with no runtime dependencies towards Eclipse; as can EMF itself.
+
+=== The Comparison Model ===
+EMF Compare uses a single model, which root is a ''Comparison'' object, to represent all of the information regarding the comparison: matched objects, matched resources, detected differences, links between these references, etc. The root ''Comparison'' is created at the beginning of the Match process, and will undergo a set of successive refinings during the remainder of the Comparison: Diff, Equivalence, Dependencies... will all add their own information to the ''Comparison''.
+
+So, how exactly is represented all of the information the Comparison model can hold, and how to make sense of it all?
+
+===Match===
+
+A ''Match'' element is how we represent that the ''n'' compared versions have elements that are basically the same. For example, if we are comparing two different versions ''v1'' and ''v2'' of a given model which look like:
+
+{| border="1" cellpadding="5" cellspacing="0" align="center"
+|-
+! align="center" | Master
+! align="center" | Borrowables
+|-
+| [[Image:./../images/v1.png|center]]
+| [[Image:./../images/v2.png|center]]
+|}
+
+Comparing these two models, we'll have a Comparison model containing three matches:
+
+# library <-> library
+# Book <-> Novel
+# title <-> title
+
+In other words, the comparison model contains an aggregate of the two or three compared models, in the form of ''Match'' elements linking the elements of all versions together. Differences will then be detected on these ''Match'' and added under them, thus allowing us to know both:
+
+* what the difference is (for example, "attribute name has been changed from ''Book'' to ''Novel''"), and
+* what the original elements were.
+
+==== Diff ====
+
+''Diff'' elements are created during the differencing process in order to represent the actual modifications that can be detected within the source model(s). The ''Diff'' concept itself is only there as the super-class of the three main kind of differences EMF Compare can detect in a model, namely ''ReferenceChange'', ''AttributeChange'' and ''ResourceAttachmentChange''. We'll go back to these three sub-classes in a short while.
+
+Whatever their type, the differences share a number of common elements:
+* a parent ''match'': differences are detected on a given ''Match''. Having a difference basically means that one of the elements paired through this ''Match'' differs from its "reference" side (see ''source'' description below). 
+* a ''source'': differences are detected on one side of their match. The source really only holds meaning in three-way comparisons, where a difference can be detected in either right or left. All differences detected through two-way comparisons have their source in the left side. This is because we always compare according to a "reference" side. During two-way comparisons, the reference side is the right: differences will always be detected on the left side as compared with the right side. During three-way comparisons though, differences can be detected on either left or right side as compared with their common ancestor; but never as compared to themselves (in other words, this is ''roughly'' equivalent to two two-way comparisons, first the left as compared to the origin, then the right as compared to the origin).
+* a current ''state'': all differences start off in their initial ''unresolved'' state. The user can then choose to:
+** merge the difference (towards either right or left, applying or reverting the difference in the process), in which case the difference becomes ''merged'', or
+** discard it, thus marking the change as ''discarded''. For example, if there is a conflicting edit of a textual attribute, the user can decide that neither right nor left are satisfying, and instead settle for a mix of the two.
+* a ''kind'': this is used by the engine to describe the type of difference it detected. Differences can be of four general types:
+** ''Add'': There are two distinct things that EMF Compare considers as an "addition". First, adding a new element within the values of a '''multi-valued feature''' is undeniably an addition. Second, any change in a '''containment reference''', even if that reference is mono-valued, that represents a "new" element in the model is considered to be an addition. Note that this second case is an exception to the rule for ''change'' differences outlined below.
+** ''Delete'': this is used as the counterpart of ''add'' differences, and it presents the same exception for '''mono-valued containment references'''.
+** ''Change'': any modification to a '''mono-valued feature''' is considered as a ''change'' difference by the engine. Take note that containment references are an exception to this rule: no ''change'' will ever be detected on those.
+** ''Move'': once again, two distinct things are represented as ''move'' differences in the comparison model. First, '''reordering''' the values of a multi-valued feature is considered as a series of MOVE: one difference for each moved value (EMF Compare computes the smallest number of differences needed between the two sides' values). Second, moving an object from '''one container to another''' (changing the containing feature of the EObject) will be detected as a ''move''.
+
+In order to ensure that the model stays coherent through individual merge operations, we've also decided to link differences together through a number of associations and references. For example, there are times when one difference cannot be merged without first merging another, or some differences which are exactly equivalent to one another. In no specific order:
+
+* ''dependency'': EMF Compare uses two oppposite references in order to track dependencies between differences. Namely, ''requires'' and ''requiredBy'' represent the two ends of this association. If the user has added a package ''P1'', then added a new Class ''C1'' within this package, we will detect both differences. However the addition of ''C1'' cannot be merged without first adding its container ''P1''. In such a case, the addition of ''C1'' '''requires''' the addition of ''P1'', and the later is '''requiredBy''' the former.
+* ''refinement'': this link is mainly used by extensions of EMF Compare in order to create high-level differences to hide the complexity of the comparison model. For example, this is used by the UML extension of EMF Compare to tell that the three differences "adding an association ''A1''", "adding a property ''P1'' in association ''A1''" and "adding a property ''P2'' in association ''A1''" is actually one single high-level difference, "adding an association ''A1''". This high-level difference is '''refinedBy''' the others, which all '''refines''' it.
+* ''equivalence'': this association is used by the comparison engine in order to link together differences which are equivalent in terms of merging. For example, Ecore has a concept of '''eOpposite''' references. Updating one of the two sides of an ''eOpposite'' will automatically update the other. In such an event, EMF Compare will detect both sides as an individual difference. However, merging one of the two will trigger the update of the other side of the ''eOpposite'' as well. In such cases, the two differences are set to be ''equivalent'' to one another. Merging one difference part of an equivalence relationship will automatically mark all of the others as ''merged'' (see ''state'' above).
+* ''implication'': implications are a special kind of "directed equivalence". A difference D1 that is linked as "implied by" another D2 means that merging D1 requires us to merge D1 instead. In other words, D2 will be automatically merged if we merge D1, but D1 will not be automatically merged if we merge D2. Implications are mostly used with UML models, where subsets and supersets may trigger such linked changes.
+* ''conflict'': during three-way comparisons, we compare two versions of a given model with their common ancestor. We can thus detect changes that were made in either left or right side (see the description of ''source'' above). However, there are cases when changes in the left conflict with changes in the right. For example, a class named "Book" in the origin model can have been renamed to "Novel" in the left model whereas it has been renamed to "Essay" in the right model. In such a case, the two differences will be marked as being in conflict with one another.
+
+As mentionned above, there are only three kind of differences that we will detect through EMF Compare, which will be sufficient for all use cases. ''ReferenceChange'' differences will be detected for every value of a reference for which we detect a change. Either the value was added, deleted, or moved (within the reference or between distinct references). ''AttributeChange'' differences are the same, but for attributes instead of references. Lastly, the ''ResourceAttachmentChange'' differences, though very much alike the ReferenceChanges we create for containment references, are specifically aimed at describing changes within the roots of one of the compared resources.
+
+==== Conflict ====
+
+'''Conflict''' will only be detected during three-way comparisons. There can only be "conflicts" when we are comparing two different versions of a same model along with their common ancestor. In other words, we need to able to compare two versions of a common element with a "reference" version of that element.
+
+There are many different kinds of conflicts; to name a few:
+* changing an element on one side (in any way, for example, renaming it) whilst that element has been removed from the other side
+* changing the same attribute of an element on both sides, to different values (for example, renaming "Book" to "Novel" on the left while be renamed "Book" to "Essay" on the right)
+* creating a new reference to an element on one side whilst it had been deleted from the other side
+
+Conflicts can be of two kinds. We call ''PSEUDO'' conflict a conflict where the two sides of a comparison have changed as compared to their common ancestor, but where the two sides are actually now equal. In other words, the end result is that the left is now equal to the right, even though they are both different from their ancestor. This is the opposite of ''REAL'' conflict where the value on all three sides is different. In terms of merging, pseudo conflicts do not need any particular action, whilst real conflicts actually need resolution.
+
+There can be more than two differences conflicting with each other. For example, the deletion of an element from one side will most likely conflict with a number of differences from the other side.
+
+==== Equivalence ====
+
+EMF Compare uses '''Equivalence''' elements in order to link together a number of differences which can ultimately be considered to be the same. For example, ecore's ''eOpposite'' references will be maintained in sync with one another. As such, modifying one of the two references will automatically update the second one accordingly. The manual modification and the automatic update are two distinct modifications of the model, resulting in two differences detected. However, merging any of these two differences will automatically merge the other one. Therefore both are marked as being equivalent to each other.
+
+There can be more than two differences equivalent with each other; in which case all will be added to a single ''Equivalence'' object, representing their relations.
+
+== Core Concepts ==
+
+=== Proxy Resolution ===
+
+When cross-referencing objects from another resource, EMF may use proxies instead of the actual object. As long as you do not access the element in question, EMF does not need to load the resource in which it is contained. The proxy is kind of a placeholder that tells EMF what resource should be loaded, and which of this resource's objects referenced, when we actually need to access its value.
+
+Proxy resolution is generally transparent, but a lot of tools based on EMF do not consider these proxies as first-class citizens: they simply resolve it without considering that it might not be needed. On the other hand, EMF Compare will never resolve proxies except for those strictly necessary. Whatever the phase of comparison, we strive to never hold the whole model in memory.
+
+The [[#Model Resolving|initial resolution phase]] is the most intensive in terms of proxy resolution and I/O operations. Though we will never hold the whole logical model in memory at any given time, we do resolve all cross-references of the compared resources, on all sides of the comparison. Since the logical model may be located in a lot of different files on disk, it might also be very heavy in memory if loaded at once. However, even if EMF Compare does resolve all fragments composing that logical model, it also unloads them as soon as the cross-references are registered. In other words, what we create is a dependency graph between the resources, not a loaded model. Afterwards, we only reload in memory those resources that have actually changed, and can thus contain differences. There will be proxies between these "changed" resources and the unchanged ones we have decided not to reload, but EMF Compare will never resolve these proxies again (and, in fact, will prevent their resolving from other tools).
+
+At the time of writing, the user interface will never resolve any proxies either. This might change in the future for a better user experience since proxies usually end up displayed in strange manners.
+
+=== Equality Helper ===
+
+The equality helper is a very central concept of EMF Compare. Of course, EMF Compare's aim is to be able to compare objects together, objects which comparison is not trivial and cannot be done through a mere "equal or not" concept. However, we still need to be able to compare these objects at all time and, whenever possible, without a full-fledged comparison.
+
+The equality helper will be used in all phases of the comparison, from matching to merging (please see the [[#Comparison Process|comparison process]] for a bird's eye view of the different comparison phases, or their detailled descriptions down below). The matching phase is precisely the time when EMF Compare is trying to match two-by-two the elements from one side to the elements from the other side. As such, we do not have -yet- the knowledge of whichi element matches with which other. However, for all subsequent phases, the equality helper will rely on information from the comparison itself (the ''Match'' elements) to make a fail-fast test for element 'equality'.
+
+When we do not have this information, the equality helper will resort to less optimal algorithms. For any object that is not an EMF EObject, we will use strict equality through ''=='' and ''Object#equals()'' calls. One of the cause for EMF Compare failing to match attribute values together is in fact the lack of implementation of the ''equals'' method on custom datatypes (see the [[./../FAQ.html#Custom data types are always marked as modified by EMF Compare|FAQ]] for more on that particular issue).
+
+Note that the equality helper will be used extensively, and that any performance hit or improvement here will make a huge difference for the whole comparison process. Likewise, any mistake you make when implementing a custom equality helper will introduce a lot of bugs.
+
+=== Comparison Scope ===
+
+As seen above, EMF Compare consider proxies as real citizens of the EMF realm. This mainly shows in the matching mechanism. EMF Compare uses a scoping mechanism to determine which elements should be matched together, and which others should be ignored. Any element that is outside of the comparison scope will be ignored by the comparison engine and left alone (if it is a proxy, it won't even be loaded). This also means that we won't really have a way to compare these proxy (or otherwise out-of-scope values) when the Diff process encounters them.
+
+For example, an element that is outside of the comparison scope, but referenced by another element which ''is'' in the scope will need specific comparison means: we've ignored it during the matching phase, so we don't know which 'out-of-scope' element corresponds to which 'other out-of-scope' element. Consider the following: in the first model, a package ''P1'' contains another package ''P2''. In the right, a package ''P1' '' contains a package ''P2' ''. We've told EMF Compare that ''P2'' and ''P2' '' are out of the comparison scope. Now how do we determine that the reference from ''P1'' to ''P2'' has changed (or, in this example, that it did not change)?
+
+This is a special case that is handled by the IEqualityHelper. Specifically, when such cases are encountered, EMF Compare falls back to using the URI of the two objects to check for equality. This behavior can be changed by customizing the IEqualityHelper (see [[#Equality Helper|above]]).
+
+By default, the only thing that EMF Compare considers "out of scope" are Ecore's "EGenericType" elements. These are usually meaningless as far as comparison is concerned (as they are located in derived references and will be merged along with their "true" difference anyway). Please take note that, when used from the user interface, EMF Compare will narrow down the scope even further through the resolution of the [[./../developer/logical-model.html|logical model]] and determining which resources are actually candidates for differences.
+
+The comparison scope provides EMF Compare with information on the content of ResourceSets, Resources or EObjects, according to the entry point of the comparison. Take note that '''the scope is only used during the matching phase'''. The differencing phase only uses the result of the matching phase to proceed.
+
+=== Longest Common Subsequence ===
+
+PENDING description of the algorithm, why do we use it, references
+
+== Default Behavior and Extensibility ==
+
+All main components of EMF Compare have been designed for extensibility. Some are only extensible when comparing models through your own actions, some can be customized globally for a given kind of model or metamodel... We'll outline the customization options of all 6 comparison phases in this section. (Any dead link? Report them on the [http://www.eclipse.org/forums/index.php/f/164/ forum]!)
+
+=== Model Resolving ===
+
+PENDING description of the phase, extensibility (use of the modelProviders extension point, custom ext point of compare)
+
+=== Match ===
+
+Before we can compute differences between two versions of a same Object, we must determine which are actually the "same" Object. For example, let's consider that my first model contains a Package P1 which itself contains a class C1; and that my second model contains a package P1 which contains a class C1. It may seem obvious for a human reader that "P1" and "C1" are the same object in both models. However, since their features might have changed in-between the two versions (for example, the "C1" might now be abstract, or it could have been converted to an Interface), this "equality" is not that obvious for a computer.
+
+The goal of the "Match" phase is to discover which of the objects from model 2 match with which objects of model 1. In other words, this is when we'll say that two objects are one and the same, and that any difference between the two sides of this couple is actually a difference that should be reported as such to the user.
+
+By default, EMF Compare browses through elements that are within the scope, and matches them through their identifier if they have one, or through a distance mechanism for all elements that have none. If the scope contains resources, EMF Compare will first match those two-by-two before browsing through all of their contained objects.
+
+EMF Compare "finds" the identifier of given object through a basic function that can be found in [http://git.eclipse.org/c/emfcompare/org.eclipse.emf.compare.git/tree/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/match/eobject/IdentifierEObjectMatcher.java#n268 IdentifierEObjectMatcher.DefaultIDFunction]. In short, if the object is a proxy, its identifier is its URI fragment. Otherwise its functional ID (in ecore, an attribute that serves as an identifier) takes precedence over its XMI ID (the identifier it was given in the XMI file). If the object is not a proxy and has neither functional nor XMI identifier, then the default behavior will simply pass that object over to the proximity algorithms so that it can be matched through its distance with other objects.
+
+PENDING: brief description of the proximity algorithm
+
+This behavior can be customized in a number of ways.
+
+==== Overriding the Match engine ====
+
+The most powerful (albeit most cumbersome) customization you can implement is to override the match engine EMF Compare uses. To this end you can either [http://git.eclipse.org/c/emfcompare/org.eclipse.emf.compare.git/tree/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/match/IMatchEngine.java implement the whole contract, ''IMatchEngine''], in which case you will have to carefully follow the javadoc's recommandations, or extend the [http://git.eclipse.org/c/emfcompare/org.eclipse.emf.compare.git/tree/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/match/DefaultMatchEngine.java default implementation, ''DefaultMatchEngine''].
+
+A custom match engine can be used for your model comparison needs:
+
+<source lang="java">
+// for standalone usage
+IMatchEngine.Factory.Registry registry === MatchEngineFactoryRegistryImpl.createStandaloneInstance();
+// for OSGi (IDE, RCP) usage
+// IMatchEngine.Factory.Registry registry === EMFCompareRCPPlugin.getMatchEngineFactoryRegistry();
+final IMatchEngine customMatchEngine === new MyMatchEngine(...);
+IMatchEngine.Factory engineFactory === new MatchEngineFactoryImpl() {
+  public IMatchEngine getMatchEngine() {
+    return customMatchEngine;
+  }
+};
+engineFactory.setRanking(20); // default engine ranking is 10, must be higher to override.
+registry.add(engineFactory);
+EMFCompare.builder().setMatchEngineFactoryRegistry(registry).build().compare(scope);
+</source>
+
+==== Changing how resources are matched ====
+
+By default, the logic EMF Compare uses to match resources together is very simple: if two resources have the same name (strict equality on the name, without considering folders), they match. When this is not sufficient, EMF Compare will look at the XMI ID of the resources' root(s). If the two resources share at least one root with an equal XMI ID, they match.
+
+This can be changed only by implementing your own subclass of the DefaultMatchEngine and overriding its resource matcher. The method of interest here is [http://git.eclipse.org/c/emfcompare/org.eclipse.emf.compare.git/tree/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/match/DefaultMatchEngine.java#n319 DefaultMatchEngine#createResourceMatcher()].
+
+==== Defining custom identifiers ====
+
+In some cases, there might be ways to identify your objects via the use of "identifiers" that cannot be identified as such by the default mechanism. For example, you might want each of your objects to be matched through their name alone, or through the composition of their name and their type... This can be achieved through code by simply redefining the function EMF Compare uses to find the ID of an object. The following code will tell EMF Compare that the identifier of all "MyEObject" elements is their name, and that any other element should go through the default behavior.
+
+<source lang="java">
+Function<EObject, String> idFunction === new Function<EObject, String>() {
+	public String apply(EObject input) {
+		if (input instanceof MyEObject) {
+			return ((MyEObject)input).getName();
+		}
+		// a null return here tells the match engine to fall back to the other matchers
+		return null;
+	}
+};
+// Using this matcher as fall back, EMF Compare will still search for XMI IDs on EObjects
+// for which we had no custom id function.
+IEObjectMatcher fallBackMatcher === DefaultMatchEngine.createDefaultEObjectMatcher(UseIdentifiers.WHEN_AVAILABLE);
+IEObjectMatcher customIDMatcher === new IdentifierEObjectMatcher(fallBackMatcher, idFunction);
+ 
+IComparisonFactory comparisonFactory === new DefaultComparisonFactory(new DefaultEqualityHelperFactory());
+ 
+IMatchEngine matchEngine === new DefaultMatchEngine(customIDMatcher, comparisonFactory);
+IMatchEngine.Factory.Registry registry === MatchEngineFactoryRegistryImpl.createStandaloneInstance();
+// for OSGi (IDE, RCP) usage
+// IMatchEngine.Factory.Registry registry === EMFCompareRCPPlugin.getMatchEngineFactoryRegistry();
+engineFactory.setRanking(20); // default engine ranking is 10, must be higher to override.
+registry.add(engineFactory);
+EMFCompare.builder().setMatchEngineFactoryRegistry(registry).build().compare(scope);
+</source>
+
+==== Ignoring identifiers ====
+
+There are some cases where you do not want the identifiers of your elements to be taken into account when matching the objects. This can easily be done when calling for comparisons programmatically:
+
+'''Through code'''
+
+<source lang="java">
+IEObjectMatcher matcher === DefaultMatchEngine.createDefaultEObjectMatcher(UseIdentifiers.NEVER);
+IComparisonFactory comparisonFactory === new DefaultComparisonFactory(new DefaultEqualityHelperFactory());
+
+IMatchEngine matchEngine === new DefaultMatchEngine(matcher , comparisonFactory);
+EMFCompare.builder().setMatchEngine(matchEngine).build().compare(scope);
+</source>
+
+'''From the user interface'''
+
+PENDING: preference page
+
+==== Refine the default Match result ====
+
+If you are happy with most of what the default behavior does, but would like to refine some of it, you can do so by post-processing the result of the match phase. The original models are only used when matching, and will never be queried again afterwards. All remaining phases are incremental refinings of the "Comparison" model that's been created by the matching phase.
+
+As such, you can impact all of the differencing process through this. Within this post-processing implementation, you can:
+* Remove ''Match'' elements
+: no difference will be detected on those: neither additions, nor deletions, nor conflicts... They'll simply be entirely ignored by the remaining process. Do note that elements for which we have no match will be considered "distinct" by the innards of EMF Compare: if a couple "B<->B'" references a couple "C<->C'" through one of their references, but you have removed the ''Match'' "C<->C'", we will consider that this reference has been "changed" from C to C' and this difference within the references of B will be shown as such.
+* Add new ''Match'' element
+: the new couples of elements will be considered by the remaining comparison process and difference may be detected on them.
+* Change existing ''Match'' elements
+: unmatched elements have two or three associated ''Match'' objects. For example if you are comparing three version of a model which all contain a different version of a given package, and all three version change the name of this package: version 1 has package "P1", version 2 has package "P2" and version three has package "P3". This package is actually the same, but EMF Compare did not manage to match it. We will thus have three ''Match'' objects: one that references "P1" as ''left'', one that references "P2" as ''right'' and one that references "P3" as ''origin''.
+: You may remove two of those three elements and change the third one so that it references P1 as ''left'', P2 as ''right'' and P3 as ''origin''. In such a case, those three will be considered to Match for the remainder of the comparison process. Make sure that there are not two different ''Match'' referencing the same object though, as this would yield unspecified results.
+
+Defining a custom post-processor requires you to implement [http://git.eclipse.org/c/emfcompare/org.eclipse.emf.compare.git/tree/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/postprocessor/IPostProcessor.java IPostProcessor] and registering this sub-class against EMF Compare. The latter can be done via either an extension point, in which case it will be considered for '''all''' comparisons on models that match its enablement, or programmatically if you only want it active for your own actions:
+
+'''Through code'''
+
+The following registers a post-processor for all UML models. This post-processor will not be triggered if there are no UML models (matching the given namespace URI) within the compared scope.
+
+<source lang="java">
+IPostProcessor customPostProcessor === new CustomPostProcessor();
+IPostProcessor.Descriptor descriptor === new BasicPostProcessorDescriptorImpl(customPostProcessor, Pattern.compile("http://www.eclipse.org/uml2/\\d\\.0\\.0/UML"), null);
+
+PostProcessor.Registry registry === new PostProcessorDescriptorRegistryImpl();
+registry.put(CustomPostProcessor.class.getName(), descriptor);
+Comparison comparison === EMFCompare.builder().setPostProcessorRegistry(registry).build().compare(scope);
+</source>
+
+'''Through extension point'''
+
+This accomplishes the exact same task, but it registers the post-processor globally. Any comparison through EMF Compare on a scope that contains models matching the given namespace URI will trigger that post-processor.
+
+<source lang="xml">
+<extension point="org.eclipse.emf.compare.rcp.postProcessor">
+      <postProcessor class="my.package.CustomPostProcessor">
+         <nsURI value="http://www.eclipse.org/uml2/\\d\\.0\\.0/UML">
+         </nsURI>
+      </postProcessor>
+</source>
+
+=== Diff ===
+
+Now that the Matching phase has completed and that we know how our objects are coupled together, EMF Compare no longer requires the two (or three) input models. It will no longer iterate over them or the comparison's input scope. From this point onward, only the result of our comparison, the ''Comparison'' object, will be refined through the successive remaining phases, starting by the '''Diff'''.
+
+The goal of this phase is to iterate over all of our ''Match'' elements, be they unmatched (only one side has this object), couples (two of the three sides contain this object) or trios (all three sides have this object) and compute any difference that may appear between the sides. For example, an object that is only on one side of the comparison is an object that has been added, or deleted. But a couple might also represent a deletion: during three way comparisons, if we have an object in the common ancestor (origin) and in the left side, but not in the right side, then it has been deleted from the right version. However, this latter example might also be a conflict: we have determined that the object has been removed from the right side... but there might also be differences between the original version and the "left" version.
+
+The differencing phase does not care about conflicts though: all it does is refine the comparison to tell that this particular ''Match'' has ''n'' diffs: one ''DELETE'' difference on the right side, and ''n'' differences on the left. Detecting conflicts between these differences will come at a later time, during the conflict resolution phase.
+
+Customizations of this phase usually aim at ignoring specific differences.
+
+==== Overriding the Diff engine ====
+
+As is the case for the Match phase, the most powerful customization you can implement for the differencing process is to override the diff engine EMF Compare uses. To this end you can either [http://git.eclipse.org/c/emfcompare/org.eclipse.emf.compare.git/tree/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/diff/IDiffEngine.java implement the whole contract, ''IDiffEngine''], in which case you will have to carefully follow the javadoc's recommandations, or extend the [http://git.eclipse.org/c/emfcompare/org.eclipse.emf.compare.git/tree/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/diff/DefaultDiffEngine.java default implementation, ''DefaultDiffEngine''].
+
+A custom diff engine can then be used for your comparisons:
+
+<source lang="java">
+IDiffEngine customDiffEngine === new MyDiffEngine(...);
+EMFCompare.builder().setDiffEngine(customDiffEngine).build().compare(scope);
+</source>
+
+==== Changing the FeatureFilter ====
+
+One of the differencing engine's responsibilities is to iterate over all features of a given object in order to check for potential differences on its value(s). However, there are some features that we decide do ignore by default: derived features, transient features... or some features on which we would like to check for ordering changes even though they are marked as non-ordered.
+
+The logic to determine whether a feature should be checked for differences has been extracted into its own class, and is quite easy to alter. For example, if you would like to ignore the ''name'' feature of your elements or never detect any ordering change:
+
+<source lang="java">
+IDiffProcessor diffProcessor === new DiffBuilder();
+IDiffEngine diffEngine === new DefaultDiffEngine(diffProcessor) {
+	@Override
+	protected FeatureFilter createFeatureFilter() {
+		return new FeatureFilter() {
+			@Override
+			protected boolean isIgnoredReference(Match match, EReference reference) {
+				return reference ==== EcorePackage.Literals.ENAMED_ELEMENT__NAME ||
+						super.isIgnoredReference(match, reference);
+			}
+
+			@Override
+			public boolean checkForOrderingChanges(EStructuralFeature feature) {
+				return false;
+			}
+		};
+	}
+};
+EMFCompare.builder().setDiffEngine(diffEngine).build().compare(scope);
+</source>
+
+You could also [[#Changing the Diff Processor|change the diff processor]] to achieve a similar goal. The difference between the two approaches is that changing the ''FeatureFilter'' will ignore the structural feature altogether, whereas replacing the diff processor would let EMF Compare check the feature and detect that diff, but ignore the notification that there is a change.
+
+==== Changing the Diff Processor ====
+
+The diff engine browses over all of the objects that have been matched, and checks all of their features in order to check for changes between the two (or three) versions' feature values. When it detects a change, it delegates all of the corresponding information to its associated ''Diff Processor'', which is in charge of actually creating the ''Diff'' object and appending it to the resulting ''Comparison''.
+
+Replacing the ''Diff Processor'' gives you a simple entry point to ignore some of the differences the default engine detects, or to slightly alter the ''Diff'' information. You might want to ignore the differences detected on some references for example. Or you might want to react to the detected diff without actually creating the ''Comparison'' model... The implementation is up to you. You can either reimplement the [http://git.eclipse.org/c/emfcompare/org.eclipse.emf.compare.git/tree/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/diff/IDiffProcessor.java whole contract] or extend the default implementation, [http://git.eclipse.org/c/emfcompare/org.eclipse.emf.compare.git/tree/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/diff/DiffBuilder.java ''DiffBuilder'']
+
+Here is a simple example that provides EMF Compare with a diff processor that will ignore all differences detected on the "name" attribute of our objects, yet keep the default behavior for all other differences.
+
+<source lang="java">
+IDiffProcessor customDiffProcessor === new DiffBuilder() {
+	@Override
+	public void attributeChange(Match match, EAttribute attribute, Object value, DifferenceKind kind, DifferenceSource source) {
+		if (attribute !== EcorePackage.Literals.ENAMED_ELEMENT__NAME) {
+			super.attributeChange(match, attribute, value, kind, source);
+		}
+	}
+};
+
+IDiffEngine diffEngine === new DefaultDiffEngine(customDiffProcessor);
+EMFCompare.builder().setDiffEngine(diffEngine).build().compare(scope);
+</source>
+
+==== Refine the default Diff result ====
+
+The last possibility offered by EMF Compare to alter the result of the differencing phase is to post-process it. The remaining comparison phases -equivalence detection, detection of dependencies between diffs and conflict detection- all use the result of the Diff engine and refine it even further. As such, all of these phases can be impacted through the refining of the Diff result.
+
+Example uses of the post-processing would include:
+
+* Remove ''Diff'' elements
+: If you'd rather code your logic to ignore differences here as a post-process instead of changing the ''FeatureFilter'' or ''IDiffProcessor''. Though that is not the best way to ignore differences, it can still be done here.
+
+* Add new ''Diff'' elements
+: If you want to create new differences without implementing a whole differencing engine, new differences can still be created here as a post-process. You will need to implement the iteration over model elements and specific checks yourself though. This workaround can also be used to create new differences that the default differencing engine does not know.
+
+* Alter the detected differences
+: If some of the differences have been detected in a way you do not like, and you did not use a custom ''IDiffProcessor'' to change the ''Diff'' information, you can do so here.
+
+The post-processor for the diff engine is implemented exactly in the same way as for the match engine post-processors (the interface and extension point are the same). Please refer to [[#Refine the default Match result|Refining the Match result]].
+
+=== Equivalences ===
+
+Now that the Differencing phase has ended, we've computed all of the individual differences within the compared models. However, all of these differences are still isolated, we now need to determine if there are any connections between them.
+
+An ''equivalence'' is one kind of potential connections between differences. For example, Ecore has a concept of ''eOpposite'' references, which be maintained in sync with one another. Modifying one of the two references will automatically update the other side of the opposition accordingly. Both the manual modification and the automatic update are considered as distinct modifications of the model when looking at it after the fact, resulting in two differences detected. However, merging any of these two differences will automatically merge the other one. Therefore, both are marked as being ''equivalent'' to each other.
+
+Though that is an example with two, more than two differences can be considered equivalent with each other. When we merge one difference, all of the other diffs that have been marked as being equivalent to it will be marked as ''MERGED'', though no actual work needs to be done to merge them : EMF will have automatically updated them when merging the first.
+
+Do note that EMF Compare detects and understand two different kind of relations that could be considered "equivalences". Described above are plain equivalences, when merging one of the differences will automatically update the model in such a way that all other sides of the equivalence are redundant and automatically merged. However, equivalences might not always be that easy. Let's take for example the case of UML : UML has concepts of ''subset'' and ''superset'' references. Adding an object into a subset will automatically update the related superset so that it also contains the added element. However, adding that same element to the superset will _not_ automatically update the related subset.
+
+This can be seen as a "directional" equivalence, where one difference D1 ''implies'' another D2, but is not ''implied by'' D2. Implications will be detected at the same time as the equivalences, but they do not use an ''Equivalence'' element, they are filled under the ''Diff#implies'' reference instead.
+
+==== Refine the default equivalences ====
+
+This phase does not offer as many customization options as the previous ones; though post-processing should be enough for most needs. All of the phases that come after the differencing are further refinements of the comparison model, totally independent from one another. From here, any client of the API can refine the comparison model any way he'd like to, even by removing all of the default results.
+
+A few examples of customizations that could be made from here :
+* Partly break existing equivalences
+: You can modify the equivalences we've detected by default by removing elements from individual differences' equivalences (Diff#getEquivalence()) or by changing the ''Equivalence'' elements directly.
+* Remove existing ''Equivalence'' elements
+: If you'd rather remove the ''Equivalence'' elements altogether, it can also be done from here without impact down the line. The individual differences will be merged individually (potentially twice if EMF automatically updates the references) if the mergers do not have this to tell them what's equivalent to what.
+* Detect your own equivalences
+: If you have specific rules on your metamodel or implementation that make some differences redundant or otherwise fully equivalent to one another, you can add your own equivalences from here.
+
+The post-processor for the equivalence detection engine is implemented exactly in the same way as for the match engine post-processors (the interface and extension point are the same). Please refer to [[#Refine the default Match result|Refining the Match result]].
+
+=== Requirements ===
+
+A requirement will be used to deal with structural constraints (to prevent dangling references or objects without parent) and to insure the model integrity.
+A difference requires other ones if the merge of this one needs the other ones not to "break" the model.
+The merge of a difference involves the merge of the required differences. All these differences will be merged by EMF Compare.
+For example, the add of a reference requires the add of the referenced object and the add of the object containing this reference.
+
+{| cellspacing="1" cellpadding="1" border="1"
+|-
+! align="center" | Change kind
+! align="center" | Reference kind to a graphical object
+! align="left"   | &nbsp; Requires:
+|-
+| rowspan="2" align="center" | ADD
+| align="center" | content
+| &nbsp; ADD of its container<br>&nbsp; DELETE of the origin value on the same containment mono-valued reference
+|-
+| align="center" | reference
+| &nbsp; ADD of the target object<br>&nbsp; ADD of the source object e.g. The ADD of a reference to the target or source of an edge requires the ADD of the edge itself and the ADD of the target and source objects, the ADD of a reference to the semantic object from a graphical one requires the ADD of the graphical and semantic object.
+|-
+| align="center" | DELETE
+| align="center" | content
+| &nbsp; DELETE of the outgoing references and contained objects<br>&nbsp; DELETE/CHANGE of the incoming references<br>&nbsp; MOVE of the contained objects
+|-
+| align="center" | MOVE
+| align="center" | content
+| &nbsp; ADD of the new container of the object<br>&nbsp; MOVE of the new container of the object
+|-
+| align="center" | CHANGE
+| align="center" | reference permutation
+| &nbsp; ADD of the target object
+|}
+
+
+Requirements can be added during a post-process.
+
+=== Refinement ===
+
+A refinement enables to group a set of unit differences into a macroscopic change.
+<br>A unit difference refines a macroscopic one if it belongs to this macroscopic change. In other words, a macroscopic change is refined by a set of unit differences.
+<br>The merge of a macroscopic change involves the merge of the refining differences. All these differences will be merged by EMF Compare.
+<br>The use of the refinement allows to improve (simplify) the reading of the comparison from a business viewpoint, to accelerate the manual merging for the end-user and to insure some consistency.
+<br>For example, the add of an association, in UML, is refined by the add of the UML Association itself but also the add of the UML properties with the update of references...
+
+Refinement can be added during a post-process.
+
+=== Conflicts ===
+
+PENDING description of the phase, extensibility options (post-process)
+
+=== Merging ===
+
+==== Which references are followed during merging ====
+
+{| border="1"
+|-
+! &nbsp; 
+! Merge from Left to Right
+! Merge from Right to Left
+|-
+! Source === Left
+| align="center" | requires  
+| align="center" | requiredBy  
+|-
+! Source === Right
+| align="center" | requiredBy  
+| align="center" | requires  
+|}
+
+
+PENDING how to provide custom mergers, override existing ones?
+
+=== User Interface ===
+
+==== Add your own filter ====
+
+You can provide your own filters by adding an extension of type ''org.eclipse.emf.compare.rcp.ui.filters'' to your plugin.
+
+[[Image:./../images/EMF_Compare_Developer_New_Extension_Filter.png|center]]
+
+This extension has three fields:
+* class: a class that implements ''org.eclipse.emf.compare.rcp.ui.structuremergeviewer.filters.IDifferenceFilter''
+* label: the label that will be displayed in the UI.
+* activeByDefault: true if you want your filter be active by default, false otherwise.
+* description: A human-readable description for this filter. It will be displayed in the EMF Compare UI.
+
+The ''org.eclipse.emf.compare.rcp.ui.structuremergeviewer.filters.IDifferenceFilter'''s contract is:
+
+<source lang="java">
+/**
+ * Instances of this class will be used by EMF Compare in order to provide difference filter facilities to the
+ * structural differences view.
+ * @since 4.0
+ */
+public interface IDifferenceFilter {
+
+	/**
+	 * Returns the predicate that will filter out objects in the structural differences view when this filter
+	 * will be selected.
+	 * 
+	 * @return the predicate that will filter out objects in the structural differences view when this filter
+	 *         will be selected.
+	 */
+	Predicate<? super EObject> getPredicateWhenSelected();
+
+	/**
+	 * Returns the predicate that will filter out objects in the structural differences view when this filter
+	 * will be unselected.
+	 * 
+	 * @return the predicate that will filter out objects in the structural differences view when this filter
+	 *         will be unselected.
+	 */
+	Predicate<? super EObject> getPredicateWhenUnselected();
+
+	/**
+	 * A human-readable label for this filter. This will be displayed in the EMF Compare UI.
+	 * 
+	 * @return The label for this filter.
+	 */
+	String getLabel();
+
+	/**
+	 * Set the label for this filter. This will be displayed in the EMF Compare UI.
+	 * 
+	 * @param label
+	 *            A human-readable label for this filter.
+	 */
+	void setLabel(String label);
+
+	/**
+	 * Returns the initial activation state that the filter should have.
+	 * 
+	 * @return The initial activation state that the filter should have.
+	 */
+	boolean defaultSelected();
+
+	/**
+	 * Set the initial activation state that the filter should have.
+	 * 
+	 * @param defaultSelected
+	 *            The initial activation state that the filter should have (true if the filter should be
+	 *            active by default).
+	 */
+	void setDefaultSelected(boolean defaultSelected);
+
+	/**
+	 * Returns the activation condition based on the scope and comparison objects.
+	 * 
+	 * @param scope
+	 *            The scope on which the filter will be applied.
+	 * @param comparison
+	 *            The comparison which is to be displayed in the structural view.
+	 * @return The activation condition based on the scope and comparison objects.
+	 */
+	boolean isEnabled(IComparisonScope scope, Comparison comparison);
+}
+</source>
+
+A default abstract implementation named ''org.eclipse.emf.compare.rcp.ui.structuremergeviewer.filters.impl.AbstractDifferenceFilter'' is available in the ''org.eclipse.emf.compare.rcp.ui'' plugin. With this abstract implementation, all you have to do is to subclass it and implements the ''getPredicateWhenSelected()'' method.
+
+==== Add your own group ====
+
+You can provide your own groups by adding an extension of type ''org.eclipse.emf.compare.rcp.ui.groups'' to your plugin.
+
+[[Image:./../images/EMF_Compare_Developer_New_Extension_Group.png|center]]
+
+This extension has three fields:
+* class: a class that implements ''org.eclipse.emf.compare.rcp.ui.structuremergeviewer.groups.IDifferenceGroupProvider''
+* label: the label that will be displayed in the UI.
+* description: A description of the group. (Used in interface)
+* rank: The rank of the group. The highest rank enabled for a comparison is used. ( Default value : 0)
+* type: Type of comparison this group can handle (Default value: BOTH).
+** THREE_WAY: This group can only handle three way comparison.
+** TWO_WAY: This group can handle two way comparison.
+** BOTH: This group can handle two and three way comparisons.
+
+The ''org.eclipse.emf.compare.rcp.ui.structuremergeviewer.groups.IDifferenceGroupProvider'''s contract is:
+
+<source lang="java">
+/**
+ * Instances of this class will be used by EMF Compare in order to provide difference grouping facilities to
+ * the structural differences view.
+ * @since 4.0
+ */
+public interface IDifferenceGroupProvider extends Adapter {
+
+	/**
+	 * This will be called internally by the grouping actions in order to determine how the differences should
+	 * be grouped in the structural view.
+	 * 
+	 * @param comparison
+	 *            The comparison which is to be displayed in the structural view. By default, its containment
+	 *            tree will be displayed.
+	 * @return The collection of difference groups that are to be displayed in the structural viewer. An empty
+	 *         group will not be displayed at all. If {@code null}, we'll fall back to the default behavior.
+	 */
+	Collection<? extends IDifferenceGroup> getGroups(Comparison comparison);
+
+	/**
+	 * A human-readable label for this group. This will be displayed in the EMF Compare UI.
+	 * 
+	 * @return The label for this group.
+	 */
+	String getLabel();
+
+	/**
+	 * Set the label for this group. This will be displayed in the EMF Compare UI.
+	 * 
+	 * @param label
+	 *            A human-readable label for this group.
+	 */
+	void setLabel(String label);
+
+	/**
+	 * Returns the initial activation state that the group should have.
+	 * 
+	 * @return The initial activation state that the group should have.
+	 */
+	boolean defaultSelected();
+
+	/**
+	 * Set the initial activation state that the group should have.
+	 * 
+	 * @param defaultSelected
+	 *            The initial activation state that the group should have (true if the group should be active
+	 *            by default).
+	 */
+	void setDefaultSelected(boolean defaultSelected);
+
+	/**
+	 * Returns the activation condition based on the scope and comparison objects.
+	 * 
+	 * @param scope
+	 *            The scope on which the group provider will be applied.
+	 * @param comparison
+	 *            The comparison which is to be displayed in the structural view.
+	 * @return The activation condition based on the scope and comparison objects.
+	 */
+	boolean isEnabled(IComparisonScope scope, Comparison comparison);
+
+	/**
+	 * Dispose this difference group provider.
+	 */
+	void dispose();
+	
+	/**
+	 * Returns all {@link TreeNode}s that are wrapping the given {@code eObject}. It internally use a cross
+	 * reference adapter.
+	 * 
+	 * @param eObject
+	 *            the object from which we want inverse reference.
+	 * @return all {@link TreeNode}s targeting the given {@code eObject} through
+	 *         {@link TreePackage.Literals#TREE_NODE__DATA}.
+	 */
+	List<TreeNode> getTreeNodes(EObject eObject);
+}
+</source>
+
+An ''IDifferenceGroupProvider'' provides a set of ''IDifferenceGroup''.
+A group provider's default abstract implementation named ''org.eclipse.emf.compare.rcp.ui.structuremergeviewer.groups.impl.AbstractDifferenceGroupProvider'' is available in the ''org.eclipse.emf.compare.rcp.ui'' plugin. With this abstract implementation, all you have to do is to subclass it and implements the ''getGroups()'' method.
+
+For example, the ''By Kind'' group provider has 4 groups: Additions, Deletions, Changes and Moves.
+
+A group's default implementation named ''org.eclipse.emf.compare.rcp.ui.internal.structuremergeviewer.groups.BasicDifferenceGroupImpl'' is available in the ''org.eclipse.emf.compare.rcp.ui'' plugin. With this default implementation, all you have to do is to subclass it and overrides the ''getChildren()'' method.
+Note that default implementation is ''internal'' and subject to modifications.
+
+==== Customize display of differences inside an existing group ====
+
+You can customize display of differences inside an existing group by adding an extension of type ''org.eclipse.emf.compare.rcp.ui.differenceGroupExtender'' to your plugin.
+
+[[Image:./../images/EMF_Compare_Developer_New_Extension_Extender.png|center]]
+
+This extension has one field:
+* class: a class that implements ''org.eclipse.emf.compare.rcp.ui.structuremergeviewer.groups.extender.IDifferenceGroupExtender''
+
+The ''org.eclipse.emf.compare.rcp.ui.structuremergeviewer.groups.extender.IDifferenceGroupExtender'''s contract is:
+
+<source lang="java">
+/**
+ * Instances of this class will be used by EMF Compare in order to extend the children of TreeNodes containing
+ * in the structure merge viewer.
+ * 
+ * @since 4.0
+ */
+public interface IDifferenceGroupExtender {
+
+	/**
+	 * Checks if the given TreeNode have to be handled by the extender.
+	 * 
+	 * @param treeNode
+	 *            the given TreeNode.
+	 * @return true if the TreeNode have to be handled, false otherwise.
+	 */
+	boolean handle(TreeNode treeNode);
+
+	/**
+	 * Add children to the given TreeNode.
+	 * 
+	 * @param treeNode
+	 *            the given TreeNode.
+	 */
+	void addChildren(TreeNode treeNode);
+}
+</source>
+
+There is no default implementation of extender. Examples of extender implementations are available in the ''org.eclipse.emf.compare.diagram.ide.ui'' plugin.
+
+==== Add your own accessor factory ====
+
+You can add your own accessor factory by adding an extension of type ''org.eclipse.emf.compare.rcp.ui.accessorFactory'' to your plugin.
+
+[[Image:./../images/EMF_Compare_Developer_New_Extension_AccessorFactory.png|center]]
+
+This extension has one field:
+* class: a class that implements ''org.eclipse.emf.compare.rcp.ui.contentmergeviewer.accessor.factory.IAccessorFactory''
+* ranking : the ranking of this accessor factory.
+
+The ''org.eclipse.emf.compare.rcp.ui.contentmergeviewer.accessor.factory.IAccessorFactory'''s contract is:
+
+<source lang="java">
+/**
+ * A factory of {@link ITypedElement}s.
+ * 
+ * @since 4.0
+ */
+public interface IAccessorFactory {
+
+	/**
+	 * Checks if the target object is applicable to the factory.
+	 * 
+	 * @param target
+	 *            the object for which we want to know if it is applicable to the factory.
+	 * @return true if the object is applicable to the factory, false otherwise.
+	 */
+	boolean isFactoryFor(Object target);
+
+	/**
+	 * The ranking of the factory.
+	 * 
+	 * @return the ranking of the factory.
+	 */
+	int getRanking();
+
+	/**
+	 * Set the ranking of the factory.
+	 * 
+	 * @param value
+	 *            the ranking value.
+	 */
+	void setRanking(int value);
+
+	/**
+	 * Creates an {@link ITypedElement} from an {@link AdapterFactory} and a given object. This accessor is
+	 * specific for the left side of the comparison.
+	 * 
+	 * @param adapterFactory
+	 *            the given adapter factory.
+	 * @param target
+	 *            the given object.
+	 * @return an ITypedElement.
+	 */
+	ITypedElement createLeft(AdapterFactory adapterFactory, Object target);
+
+	/**
+	 * Creates an {@link ITypedElement} from an {@link AdapterFactory} and a given object. This accessor is
+	 * specific for the right side of the comparison.
+	 * 
+	 * @param adapterFactory
+	 *            the given adapter factory.
+	 * @param target
+	 *            the given object.
+	 * @return an ITypedElement.
+	 */
+	ITypedElement createRight(AdapterFactory adapterFactory, Object target);
+
+	/**
+	 * Creates an {@link ITypedElement} from an {@link AdapterFactory} and a given object. This accessor is
+	 * specific for the ancestor side of the comparison.
+	 * 
+	 * @param adapterFactory
+	 *            the given adapter factory.
+	 * @param target
+	 *            the given object.
+	 * @return an ITypedElement.
+	 */
+	ITypedElement createAncestor(AdapterFactory adapterFactory, Object target);
+}
+</source>
+
+An ITypedElement is an interface for getting the name, image, and type for an object. An ITypedElement is used to present an input object in the compare UI (getName and getImage) and for finding a viewer for a given input type (getType).
+
+There is no default implementation of accessor factory. Examples of accessor factories implementations are available in the ''org.eclipse.emf.compare.rcp.ui'' plugin. There is several existing accessor factories in EMF Compare: for Matches, ReferenceChanges, AttibuteChanges, ResourceAttachmentChanges...
+
+PENDING customize display of custom differences, add custom menu entries, add export options, provide custom content viewer
+
+== Using The Compare APIs ==
+
+The main entry point of EMF Compare is the ''org.eclipse.emf.compare.EMFCompare'' class. It is what should be used in order to configure and launch a comparison. That is not all though. Once you have compared two models, you want to query the differences, maybe merge some of them, display the comparison result in the comparison editor... The following section will list the main entry points for each of these actions, along with a brief description of what can be done and what should be avoided.
+
+Most of these examples are set-up as "standalone" examples, and will include extra instructions for IDE use: pay attention to the environment in which you are using EMF Compare. Are you using it from an Eclipse plugin, in which case you'd like all of the extra features provided through extension points and contribution to be available to you? Or are you using it from a standalone environment, in which case you'd need to reduce the dependencies to the bare minimum and avoid OSGi-related code and extensions?
+
+=== Compare two models ===
+
+==== Loading your models ====
+
+Whether you wish to compare two or three models, the first thing you need is to load them. We won't detail in-depth how to do that as this is standard EMF practice, you might want to look at EMF tutorial for detailled instructions on this point. Here, we'll use a simple method that loads an xmi file at a given URL into a resourceSet, expecting the given URL to be an absolute file URL:
+
+<source lang="java">
+public void load(String absolutePath, ResourceSet resourceSet) {
+  URI uri === URI.createFileURI(absolutePath);
+
+  resourceSet.getResourceFactoryRegistry().getExtensionToFactoryMap().put("xmi", new XMIResourceFactoryImpl());
+
+  // Resource will be loaded within the resource set
+  resourceSet.getResource(uri, true);
+}
+</source>
+
+==== Creating the comparison scope ====
+
+EMF Compare uses a scoping mechanism to determine which elements should be compared, and which others should be ignored. Any element that is outside of the comparison scope will be ignored by the comparison engine and left alone (if it is a proxy, it won't even be loaded). As such, extra care should be taken to determine the proper scope of the comparison or customize the IEqualityHelper to handle the specific elements you remove from the scope. Refer to the [[#Comparison Scope|appropriate section]] above for more on the scoping mechanism.
+
+By default, the only thing that EMF Compare considers "out of scope" are Ecore's "EGenericType" elements. These are usually meaningless as far as comparison is concerned (as they are located in derived references and will be merged along with their "true" difference anyway). Other than that, Please note that EMF Compare will leave unresolved proxies alone: more on this can be found in the [[#Proxy Resolution|related section]].
+
+The default scope can be easily created through:
+
+<source lang="java">
+IComparisonScope scope === EMFCompare.createDefaultScope(resourceSet1, resourceSet2);
+</source>
+
+==== Configuring the comparison ====
+
+EMF Compare can be customized in a number of ways, the most important of which were described [[#Default Behavior and Extensibility|above]]. Most of them re-use the same entry point, the ''org.eclipse.emf.compare.EMFCompare'' class. We won't customize much here, please see the afore-mentionned section for extensibility means.
+
+All we will tell EMF Compare is not to use identifiers, and rely on its proximity algorithms instead (after all, we're comparing plain XMI files):
+
+<source lang="java">
+IEObjectMatcher matcher === DefaultMatchEngine.createDefaultEObjectMatcher(UseIdentifiers.NEVER);
+IComparisonFactory comparisonFactory === new DefaultComparisonFactory(new DefaultEqualityHelperFactory());
+ 
+IMatchEngine.Factory matchEngineFactory === new MatchEngineFactoryImpl(matcher, comparisonFactory);
+matchEngineFactory.setRanking(20);
+IMatchEngine.Factory.Registry matchEngineRegistry === new MatchEngineFactoryRegistryImpl();
+matchEngineRegistry.add(factory);
+
+EMFCompare comparator === EMFCompare.builder().setMatchEngineFactoryRegistry(matchEngineRegistry).build();
+
+</source>
+
+==== Putting it all together ====
+
+The following takes two input xmi files, loads them in their own resource sets, then calls the comparison without using identifiers:
+
+<source lang="java">
+public Comparison compare(File model1, File model2) {
+	// Load the two input models
+	ResourceSet resourceSet1 === new ResourceSetImpl();
+	ResourceSet resourceSet2 === new ResourceSetImpl();
+	String xmi1 === "path/to/first/model.xmi";
+	String xmi2 === "path/to/second/model.xmi";
+	load(xmi1, resourceSet1);
+	load(xmi2, resourceSet2);
+
+	// Configure EMF Compare
+	IEObjectMatcher matcher === DefaultMatchEngine.createDefaultEObjectMatcher(UseIdentifiers.NEVER);
+	IComparisonFactory comparisonFactory === new DefaultComparisonFactory(new DefaultEqualityHelperFactory());
+	IMatchEngine.Factory matchEngineFactory === new MatchEngineFactoryImpl(matcher, comparisonFactory);
+        matchEngineFactory.setRanking(20);
+        IMatchEngine.Factory.Registry matchEngineRegistry === new MatchEngineFactoryRegistryImpl();
+        matchEngineRegistry.add(matchEngineFactory);
+	EMFCompare comparator === EMFCompare.builder().setMatchEngineFactoryRegistry(matchEngineRegistry).build();
+
+	// Compare the two models
+	IComparisonScope scope === EMFCompare.createDefaultScope(resourceSet1, resourceSet2);
+	return comparator.compare(scope);
+}
+
+private void load(String absolutePath, ResourceSet resourceSet) {
+  URI uri === URI.createFileURI(absolutePath);
+
+  resourceSet.getResourceFactoryRegistry().getExtensionToFactoryMap().put("xmi", new XMIResourceFactoryImpl());
+
+  // Resource will be loaded within the resource set
+  resourceSet.getResource(uri, true);
+}
+</source>
+
+==== Comparing from an Eclipse plugin ====
+
+The above example is for standalone usage, and as such will require extra work if you wish to compare UML models, benefit from EMF Compare extensions, provide your own mergers... The following represents the same example, but uses IDE-specific utilities (can you spot the two differences?):
+
+<source lang="java">
+public Comparison compare(File model1, File model2) {
+	// Load the two input models
+	ResourceSet resourceSet1 === new ResourceSetImpl();
+	ResourceSet resourceSet2 === new ResourceSetImpl();
+	String xmi1 === "path/to/first/model.xmi";
+	String xmi2 === "path/to/second/model.xmi";
+	load(xmi1, resourceSet1);
+	load(xmi2, resourceSet2);
+
+	// Configure EMF Compare
+	IEObjectMatcher matcher === DefaultMatchEngine.createDefaultEObjectMatcher(UseIdentifiers.NEVER);
+	IComparisonFactory comparisonFactory === new DefaultComparisonFactory(new DefaultEqualityHelperFactory());
+	IMatchEngine matchEngine === new DefaultMatchEngine(matcher, comparisonFactory);
+        IMatchEngine.Factory.Registry matchEngineRegistry === EMFCompareRCPPlugin.getDefault().getMatchEngineFactoryRegistry();
+        IPostProcessor.Descriptor.Registry<String> postProcessorRegistry === EMFCompareRCPPlugin.getDefault().getPostProcessorRegistry();
+	EMFCompare comparator === EMFCompare.builder()
+                                           .setMatchEngineFactoryRegistry(matchEngineRegistry)
+                                           .setPostProcessorRegistry(postProcessorRegistry)
+                                           .build();
+
+	// Compare the two models
+	IComparisonScope scope === EMFCompare.createDefaultScope(resourceSet1, resourceSet2);
+	return comparator.compare(scope);
+}
+
+private void load(String absolutePath, ResourceSet resourceSet) {
+  URI uri === URI.createFileURI(absolutePath);
+
+  // Resource will be loaded within the resource set
+  resourceSet.getResource(uri, true);
+}
+</source>
+
+=== Query the differences ===
+
+Once you have the result of a comparison (in the form of a ''Comparison'' object), what you are interested in are most likely the differences between your models. We will detail the merging process later on it its own section, but before anything we need to retrieve the list of differences of interest. Within the Comparison model, differences are spread under the elements on which they've been detected, more precisely, under the ''Match'' of the element on which they were detected.
+
+Let's use a complex example as reference. Consider the three following models:
+
+{| border="1" cellpadding="5" cellspacing="0" align="center"
+|-
+! colspan="2" align="center" | Origin
+|-
+| colspan="2" align="center" | [[Image:./../images/EMF_Compare_Origin_Model.png|center]]
+|-
+! align="center" | Left
+! align="center" | Right
+|-
+| [[Image:./../images/EMF_Compare_Use_Compare_Master.png|center]]
+| [[Image:./../images/EMF_Compare_Use_Compare_5.png|center]]
+|}
+
+==== All differences ====
+
+What we need is usually to retrieve the list of ''all'' differences, wherever they were detected, or whatever their source (the left model, or the right model). Instead of iterating all over the Comparison model to collect them, you can use:
+
+<source lang="java">
+List<Diff> differences === comparison.getDifferences();
+</source>
+
+==== Differences related to element X ====
+
+Sometimes, we need to retrieve all of the differences that were detected on (or that are related to) a given model element. For example, with the above example, we might want to retrieve the list of all differences that relate to ''Borrowable''. Well, there are a number of them, which can all be collected through:
+
+<source lang="java">
+// borrowable is a reference on the like-named EObject
+List<Diff> differencesOnBorrowable === comparison.getDifferences(borrowable);
+</source>
+
+This will return a list containing a number of differences:
+
+* ''Borrowable'' has been added in the right model
+* ''copies'' has been added to reference ''ownedProperties'' of Borrowable
+* ''Borrowable'' has been added to the generalization reference of ''Book''
+* ''Borrowable'' has been added as the ''borrowed'' target of an association with ''Person''
+
+In other words, this method will return differences '''under''' the target (here, ''copies'' has been added), as well as differences which '''changed value''' is the target.
+
+==== Filtering differences ====
+
+EMF Compare depends on guava for many of its internals. A number of "common" difference filtering predicates have been extracted to the ''org.eclipse.emf.compare.utils.EMFComparePredicates'' utility class. Using this class, it is trivial to filter the list of differences so as to keep only those we are interested in. For example, what if we wish to retrieve the list of all '''non-conflictual''' differences that originate from the '''left''' side? (This is the case when you use the "copy all non-conflicting from left to right" action from the comparison editor for example.)
+
+<source lang="java">
+// Construct the predicate
+Predicate<? super Diff> predicate === and(fromSide(DifferenceSource.LEFT), not(hasConflict(ConflictKind.REAL, ConflictKind.PSEUDO));
+// Filter out the diff that do not satisfy the predicate
+Iterable<Diff> nonConflictualDifferencesFromLeft === filter(comparison.getDifferences(), predicate);
+</source>
+
+Note that for clarity, we've made static references to a number of methods here. This particular snippet requires the following imports:
+
+<source lang="java">
+import static com.google.common.base.Predicates.and;
+import static com.google.common.base.Predicates.not;
+import static com.google.common.collect.Iterables.filter;
+import static org.eclipse.emf.compare.utils.EMFComparePredicates.fromSide;
+import static org.eclipse.emf.compare.utils.EMFComparePredicates.hasConflict;
+</source>
+
+We strongly encourage you to look around more in these classes: ''Predicates'' provides a number of basic, general-purpose predicates while ''EMFComparePredicates'' provides EMF Compare specific predicates used throughout both core and user-interface of EMF Compare.
+
+=== Merge differences ===
+
+PENDING how to re-implement ''copyDiff'' and ''copyAllNonConflicting''
+
+entry points: org.eclipse.emf.compare.merge.IMerger and org.eclipse.emf.compare.merge.IBatchMerger
+
+=== Open a compare editor ===
+
+PENDING description of the need (dialog and editor), link to [[./how-to-open-compare-dialog.html|appropriate page]]
diff --git a/plugins/org.eclipse.emf.compare.doc/src/user/sample-use-case.mediawiki b/plugins/org.eclipse.emf.compare.doc/src/user/sample-use-case.mediawiki
index 08d674f..2399f46 100644
--- a/plugins/org.eclipse.emf.compare.doc/src/user/sample-use-case.mediawiki
+++ b/plugins/org.eclipse.emf.compare.doc/src/user/sample-use-case.mediawiki
@@ -1,124 +1,124 @@
-= Sample use case =

-

-With the following, we'll follow the life cycle of a metamodel describing a very basic library as it evolves separately in different branches. This will allow us to give more concrete examples of how EMF Compare can be used, and how it can help you.

-

-== Creating a model ==

-

-For this test, we'll suppose that you are trying to use EMF Compare on UML models shared under git. This will not go in details about UML and Git. We'll assume that you know how to manipulate an UML model, create or clone a git repository, share a project under it and use standard Git operations.

-

-The name of our sample project will be "library". It contains a single folder "model" containing two models :

-* library_Types.uml will contain our primitive types,

-* library.uml will contain our actual model.

-

-The two models will be commited to our git clone. The whole thing looks like this :

-

-[[Image:../images/EMF_Compare_Use_Setup.png]]

-

-The model itself is a very simple library. Graphically speaking :

-

-[[Image:../images/EMF_Compare_Use_Model.png]]

-

-Now that this initial model file has been committed, we'd like to improve it a little. For example :

-* Add an ''alias'' property to the ''Writer'' class,

-* Add a new ''History'' Category,

-* Rename the ''pages'' property of ''Book'' into ''length''.

-

-Our model now looks like this :

-

-[[Image:../images/EMF_Compare_Use_Model_Changed.png]]

-

-But how do we know exactly what changed? Let's compare this with the file from the Git Index :

-

-[[Image:../images/EMF_Compare_Use_Compare_1.png]]

-

-This will open a comparison editor that initially looks like the following :

-

-[[Image:../images/EMF_Compare_Use_Compare_2.png]]

-

-There are three main areas of interest in this editor.

-# Displays a structured list of the differences detected between the current version of the model and the version that lies in the Git Index.

-# This will react to the selections in (1) and display the ''left'' side of this comparison. As a rule of thumb, the ''left'' is the ''local'' version of the model. In this example, ''left'' will then be the version we have modified in our workspace. This is originally filled with the first difference that is selected in the top panel (1), more on this section in the example just below.

-# As above, this will react to selections in (1), but this time it will display the ''right'' side of the comparison. This is generally the ''remote'' version of the model; the version to which we've compared ours. In this case, this will represent the version of the model as it is in the Git Index. This is originally empty, more on this section in the example just below.

-

-As stated above, (2) and (3) are initially filled with the values of the difference selected in the top panel (1). These two panels are there to display more information about the differences detected between our models. Let's select another difference displayed in (1) :

-

-[[Image:../images/EMF_Compare_Use_Compare_3.png]]

-

-# We've selected the difference corresponding to the addition of attribute '''alias''' in the class '''Writer'''. A double-click on this difference updated our two panes below.

-# '''alias''' has been added to the properties of Class '''Writer'''. In the model, this corresponds to a change to the reference ''ownedAttributes'' of the ''Writer'' Class. This sub-panel indicates the actual reference that was changed in oder to remind us of the context.

-# This displays all values of the reference outlined in (2) as they are in the ''left'' model. This is where we see the new value, '''alias''' outlined.

-# As for (2), this will display the context of the selected difference. The same reference will usually be displayed in both (2) and (4).

-# This panel displays all values of the reference outlined in (4) as they are in the ''right'' model. In here, we see the location of '''alias''' outlined as an empty space. This rectangle is where the new value will be added if we merge it... Though in this case, it is not possible to merge towards the ''right'' : it is a version located on a repository and is thus non-editable.

-

-This is useful in order to determine exactly what changed in our version, but serves no other purpose : merging changes here would only mean reverting back our modifications to the "clean" state from the repository. Let's commit our changes.

-

-== Branching ==

-

-Now, we'd like to create a new feature for our library : we'd like clients to be able to borrow our books. We'll branch our repository in order to create this new feature and name this new branch ''borrowables'' :

-

-[[Image:../images/EMF_Compare_Use_Compare_4.png]]

-

-Starting right away, we add the necessary new concepts to our model to represent the possibility of lending books. We "may" later need to have more than books to be lendable, so let's make a ''Borrowable'' interface to hold this concept. We'll also need a ''Person'' class, as well as a new data type to represent the person's birth date :

-

-[[Image:../images/EMF_Compare_Use_Compare_5.png]]

-

-In a tree viewer, our models now look like (highlighted in red, the concepts we added with this step) :

-

-[[Image:../images/EMF_Compare_Use_Compare_6.png]]

-

-However, while we are working on our ''borrowables'' branch, the ''master'' branch may still evolve : other people on the project might be adding new concepts of their own, or we could be switching to the main branch for a high priority fix ourselves. Let's imagine that two features have been added since we branched our repository. First, someone needed to have the library hold not only Books, but also Magazines. Second, we needed the publication date of our Books and magazines to be recorded.

-

-The first of these two commits will add the following concepts to our ''master'' branch's model :

-

-[[Image:../images/EMF_Compare_Use_Compare_7.png]]

-

-While the second only adds a primitive type and a property :

-

-[[Image:../images/EMF_Compare_Use_Compare_8.png]]

-

-== Merge ==

-

-If you have followed to this point, we now have two diverging branches, ''master'' and ''borrowables'' which both hold a different version of our ''library.uml'' model. Here is how these two models look like at this point :

-

-{| border="1" cellpadding="5" cellspacing="0" align="center"

-|-

-! align="center" | Master

-! align="center" | Borrowables

-|-

-| [[Image:../images/EMF_Compare_Use_Compare_Master.png|center]]

-| [[Image:../images/EMF_Compare_Use_Compare_5.png|center]]

-|}

-

-Before we continue working on our Borrowables branch, we'd like to retrieve all modifications that have been pushed to master. With the "Borrowables" branch checked out, we'll use the ''Compare With > Branch, Tag or Reference'' action :

-

-[[Image:../images/EMF_Compare_Use_Compare_With_Master_1.png|center]]

-

-and compare with master :

-

-[[Image:../images/EMF_Compare_Use_Compare_With_Master_2.png|center]]

-

-This shows us all differences between our local copy and the master branch that were made since the 'branching' point.

-

-[[Image:../images/EMF_Compare_Merge.png|center]]

-

-Same as previously, you can navigate through the differences via the top panel, the structural view. There are three main kind of elements displayed here. '''Regular''' elements, that mimic the containment tree of your input models, are there to separate the various differences and let you know where they were actually detected. Then there are '''incoming''' differences, decorated with a blue arrow ([[Image:../images/EMF_Compare_Incoming_Change.gif]]) or a derived icon, and '''outgoing''' differences decorated with a green arrow ([[Image:../images/EMF_Compare_Outgoing_Change.gif]]) or a derived icon.

-

- * '''Incoming''' differences are changes that were made in the remote branch (here, ''master'') since the branching point (common ancestor).

- * '''Outgoing''' differences are changes taht were made in the local copy (here, the ''borrowables'' branch) since the branching point.

-

-There are no conflicts here, since UML uses computed identifiers (XMI ID) for the model elements. Thus, what looks like a conflict (the "Date" type that's been added on both branch in the types packages) is actually two distinct differences.

-

-The interface also lets you display the common ancestor of both models through the [[Image:../images/EMF_Compare_Ancestor.gif]] icon. For example, if we select the '''Book''' class, we can see how it looks like on all three versions :

-

-[[Image:../images/EMF_Compare_Merge_Book_Ancestor.png|center]]

-

-You can navigate through the differences using the appropriate actions, either the previous ([[Image:../images/EMF_Compare_Prev_Diff.gif]]) or the next ([[Image:../images/EMF_Compare_Next_Diff.gif]]) difference.

-

-The remaining two actions are those that actually interest us here we can either merge all non-conflicting differences to the local copy through [[Image:../images/EMF_Compare_Copy_All.gif]] or merge them one after the other through [[Image:../images/EMF_Compare_Copy.gif]].

-

-Merging '''all''' differences is not what we seek : we want to keep the changes we made locally, not revert them to the state they had before the branching point (which is their current state on ''master'', the right side). We will then select all ''incoming'' differences one after the other and merge them one by one. This gives us our merged model :

-

-[[Image:../images/EMF_Compare_Merged.png|center]]

-

-Notice that ''merged'' differences are displayed in ''italics'' and have a distinct icon. All that's left is to save, our model now contains both our local changes and the changes that were made on master.

-

+= Sample use case =
+
+With the following, we'll follow the life cycle of a metamodel describing a very basic library as it evolves separately in different branches. This will allow us to give more concrete examples of how EMF Compare can be used, and how it can help you.
+
+== Creating a model ==
+
+For this test, we'll suppose that you are trying to use EMF Compare on UML models shared under git. This will not go in details about UML and Git. We'll assume that you know how to manipulate an UML model, create or clone a git repository, share a project under it and use standard Git operations.
+
+The name of our sample project will be "library". It contains a single folder "model" containing two models :
+* library_Types.uml will contain our primitive types,
+* library.uml will contain our actual model.
+
+The two models will be commited to our git clone. The whole thing looks like this :
+
+[[Image:../images/EMF_Compare_Use_Setup.png]]
+
+The model itself is a very simple library. Graphically speaking :
+
+[[Image:../images/EMF_Compare_Use_Model.png]]
+
+Now that this initial model file has been committed, we'd like to improve it a little. For example :
+* Add an ''alias'' property to the ''Writer'' class,
+* Add a new ''History'' Category,
+* Rename the ''pages'' property of ''Book'' into ''length''.
+
+Our model now looks like this :
+
+[[Image:../images/EMF_Compare_Use_Model_Changed.png]]
+
+But how do we know exactly what changed? Let's compare this with the file from the Git Index :
+
+[[Image:../images/EMF_Compare_Use_Compare_1.png]]
+
+This will open a comparison editor that initially looks like the following :
+
+[[Image:../images/EMF_Compare_Use_Compare_2.png]]
+
+There are three main areas of interest in this editor.
+# Displays a structured list of the differences detected between the current version of the model and the version that lies in the Git Index.
+# This will react to the selections in (1) and display the ''left'' side of this comparison. As a rule of thumb, the ''left'' is the ''local'' version of the model. In this example, ''left'' will then be the version we have modified in our workspace. This is originally filled with the first difference that is selected in the top panel (1), more on this section in the example just below.
+# As above, this will react to selections in (1), but this time it will display the ''right'' side of the comparison. This is generally the ''remote'' version of the model; the version to which we've compared ours. In this case, this will represent the version of the model as it is in the Git Index. This is originally empty, more on this section in the example just below.
+
+As stated above, (2) and (3) are initially filled with the values of the difference selected in the top panel (1). These two panels are there to display more information about the differences detected between our models. Let's select another difference displayed in (1) :
+
+[[Image:../images/EMF_Compare_Use_Compare_3.png]]
+
+# We've selected the difference corresponding to the addition of attribute '''alias''' in the class '''Writer'''. A double-click on this difference updated our two panes below.
+# '''alias''' has been added to the properties of Class '''Writer'''. In the model, this corresponds to a change to the reference ''ownedAttributes'' of the ''Writer'' Class. This sub-panel indicates the actual reference that was changed in oder to remind us of the context.
+# This displays all values of the reference outlined in (2) as they are in the ''left'' model. This is where we see the new value, '''alias''' outlined.
+# As for (2), this will display the context of the selected difference. The same reference will usually be displayed in both (2) and (4).
+# This panel displays all values of the reference outlined in (4) as they are in the ''right'' model. In here, we see the location of '''alias''' outlined as an empty space. This rectangle is where the new value will be added if we merge it... Though in this case, it is not possible to merge towards the ''right'' : it is a version located on a repository and is thus non-editable.
+
+This is useful in order to determine exactly what changed in our version, but serves no other purpose : merging changes here would only mean reverting back our modifications to the "clean" state from the repository. Let's commit our changes.
+
+== Branching ==
+
+Now, we'd like to create a new feature for our library : we'd like clients to be able to borrow our books. We'll branch our repository in order to create this new feature and name this new branch ''borrowables'' :
+
+[[Image:../images/EMF_Compare_Use_Compare_4.png]]
+
+Starting right away, we add the necessary new concepts to our model to represent the possibility of lending books. We "may" later need to have more than books to be lendable, so let's make a ''Borrowable'' interface to hold this concept. We'll also need a ''Person'' class, as well as a new data type to represent the person's birth date :
+
+[[Image:../images/EMF_Compare_Use_Compare_5.png]]
+
+In a tree viewer, our models now look like (highlighted in red, the concepts we added with this step) :
+
+[[Image:../images/EMF_Compare_Use_Compare_6.png]]
+
+However, while we are working on our ''borrowables'' branch, the ''master'' branch may still evolve : other people on the project might be adding new concepts of their own, or we could be switching to the main branch for a high priority fix ourselves. Let's imagine that two features have been added since we branched our repository. First, someone needed to have the library hold not only Books, but also Magazines. Second, we needed the publication date of our Books and magazines to be recorded.
+
+The first of these two commits will add the following concepts to our ''master'' branch's model :
+
+[[Image:../images/EMF_Compare_Use_Compare_7.png]]
+
+While the second only adds a primitive type and a property :
+
+[[Image:../images/EMF_Compare_Use_Compare_8.png]]
+
+== Merge ==
+
+If you have followed to this point, we now have two diverging branches, ''master'' and ''borrowables'' which both hold a different version of our ''library.uml'' model. Here is how these two models look like at this point :
+
+{| border="1" cellpadding="5" cellspacing="0" align="center"
+|-
+! align="center" | Master
+! align="center" | Borrowables
+|-
+| [[Image:../images/EMF_Compare_Use_Compare_Master.png|center]]
+| [[Image:../images/EMF_Compare_Use_Compare_5.png|center]]
+|}
+
+Before we continue working on our Borrowables branch, we'd like to retrieve all modifications that have been pushed to master. With the "Borrowables" branch checked out, we'll use the ''Compare With > Branch, Tag or Reference'' action :
+
+[[Image:../images/EMF_Compare_Use_Compare_With_Master_1.png|center]]
+
+and compare with master :
+
+[[Image:../images/EMF_Compare_Use_Compare_With_Master_2.png|center]]
+
+This shows us all differences between our local copy and the master branch that were made since the 'branching' point.
+
+[[Image:../images/EMF_Compare_Merge.png|center]]
+
+Same as previously, you can navigate through the differences via the top panel, the structural view. There are three main kind of elements displayed here. '''Regular''' elements, that mimic the containment tree of your input models, are there to separate the various differences and let you know where they were actually detected. Then there are '''incoming''' differences, decorated with a blue arrow ([[Image:../images/EMF_Compare_Incoming_Change.gif]]) or a derived icon, and '''outgoing''' differences decorated with a green arrow ([[Image:../images/EMF_Compare_Outgoing_Change.gif]]) or a derived icon.
+
+ * '''Incoming''' differences are changes that were made in the remote branch (here, ''master'') since the branching point (common ancestor).
+ * '''Outgoing''' differences are changes taht were made in the local copy (here, the ''borrowables'' branch) since the branching point.
+
+There are no conflicts here, since UML uses computed identifiers (XMI ID) for the model elements. Thus, what looks like a conflict (the "Date" type that's been added on both branch in the types packages) is actually two distinct differences.
+
+The interface also lets you display the common ancestor of both models through the [[Image:../images/EMF_Compare_Ancestor.gif]] icon. For example, if we select the '''Book''' class, we can see how it looks like on all three versions :
+
+[[Image:../images/EMF_Compare_Merge_Book_Ancestor.png|center]]
+
+You can navigate through the differences using the appropriate actions, either the previous ([[Image:../images/EMF_Compare_Prev_Diff.gif]]) or the next ([[Image:../images/EMF_Compare_Next_Diff.gif]]) difference.
+
+The remaining two actions are those that actually interest us here we can either merge all non-conflicting differences to the local copy through [[Image:../images/EMF_Compare_Copy_All.gif]] or merge them one after the other through [[Image:../images/EMF_Compare_Copy.gif]].
+
+Merging '''all''' differences is not what we seek : we want to keep the changes we made locally, not revert them to the state they had before the branching point (which is their current state on ''master'', the right side). We will then select all ''incoming'' differences one after the other and merge them one by one. This gives us our merged model :
+
+[[Image:../images/EMF_Compare_Merged.png|center]]
+
+Notice that ''merged'' differences are displayed in ''italics'' and have a distinct icon. All that's left is to save, our model now contains both our local changes and the changes that were made on master.
+
diff --git a/plugins/org.eclipse.emf.compare.doc/src/user/user-guide.mediawiki b/plugins/org.eclipse.emf.compare.doc/src/user/user-guide.mediawiki
index d394c8b..7cf4087 100644
--- a/plugins/org.eclipse.emf.compare.doc/src/user/user-guide.mediawiki
+++ b/plugins/org.eclipse.emf.compare.doc/src/user/user-guide.mediawiki
@@ -1,661 +1,661 @@
-= User Guide =

-

-== Getting Started ==

-

-=== Installing EMF Compare ===

-

-==== Marketplace Client ====

-

-Using the bundled Eclipse marketplace client you can install EMF Compare in one click. Just type "emf compare", click on search, and then on install. 

-

-[[Image:./../images/Marketplace.png]] 

-

-==== Update Site ====

-

-EMF has been part of the Eclipse release train since Galileo, you can install it using the following update sites, depending on your platform. '''Note''' that the following are not meant to be visited in your internet browser; they must be pasted in the ''Help > Install New Software'' dialog of your Eclipse, as p2 repositories.

-

-  http://download.eclipse.org/releases/juno

-  http://download.eclipse.org/releases/indigo

-  http://download.eclipse.org/releases/helios

-  http://download.eclipse.org/releases/galileo

-

-The [http://www.eclipse.org/emf/compare/downloads/ Download page] lists more specific update sites if you wish to try one of the latest integration builds.

-

-==== Compatibility ====

-

-Please note that the EMF Compare development team does its best to maintain downward compatibility towards Galileo (Eclipse 3.5). Following is the compatibility chart : 

-

-{| border="1"

-|-

-! EMF Compare 

-! bgcolor="#cccccc" align="center" | Eclipse 4.3 - EMF 2.9

-! align="center" | Eclipse 4.2 - EMF 2.8

-! align="center" | Eclipse 3.8 - EMF 2.8 

-! align="center" | Eclipse 3.7 - EMF 2.7 

-! align="center" | Eclipse 3.6 - EMF 2.6 

-! align="center" | Eclipse 3.5 - EMF 2.5 

-! align="center" | Eclipse 3.4 - EMF 2.4

-! align="center" | Eclipse 3.3 - EMF 2.3

-! align="center" | Eclipse 3.2 - EMF 2.2 

-|-

-| bgcolor="#cccccc" align="center" | 2.1

-| bgcolor="#46a546" | &nbsp;

-| bgcolor="#46a546" | &nbsp;

-| bgcolor="#46a546" | &nbsp;

-| bgcolor="#46a546" | &nbsp;

-| bgcolor="#46a546" | &nbsp;

-| bgcolor="#46a546" | &nbsp;

-| bgcolor="#9d261d" | &nbsp;

-| bgcolor="#9d261d" | &nbsp;

-| bgcolor="#9d261d" | &nbsp;

-|-

-| align="center" | 2.0

-| bgcolor="#ffffff" | &nbsp;

-| bgcolor="#46a546" | &nbsp;

-| bgcolor="#46a546" | &nbsp;

-| bgcolor="#46a546" | &nbsp;

-| bgcolor="#46a546" | &nbsp;

-| bgcolor="#46a546" | &nbsp;

-| bgcolor="#9d261d" | &nbsp;

-| bgcolor="#9d261d" | &nbsp;

-| bgcolor="#9d261d" | &nbsp;

-|-

-| align="center" | 1.3

-| bgcolor="#9d261d" | &nbsp;

-| bgcolor="#9d261d" | &nbsp;

-| bgcolor="#46a546" | &nbsp;

-| bgcolor="#46a546" | &nbsp;

-| bgcolor="#46a546" | &nbsp;

-| bgcolor="#46a546" | &nbsp;

-| bgcolor="#9d261d" | &nbsp;

-| bgcolor="#9d261d" | &nbsp;

-| bgcolor="#9d261d" | &nbsp;

-|-

-| align="center" | 1.2 

-| bgcolor="#ffffff" | &nbsp;

-| bgcolor="#ffffff" | &nbsp;

-| bgcolor="#46a546" | &nbsp;

-| bgcolor="#46a546" | &nbsp;

-| bgcolor="#46a546" | &nbsp;

-| bgcolor="#46a546" | &nbsp;

-| bgcolor="#46a546" | &nbsp;

-| bgcolor="#9d261d" | &nbsp;

-| bgcolor="#9d261d" | &nbsp;

-|-

-| align="center" | 1.1 

-| bgcolor="#ffffff" | &nbsp;

-| bgcolor="#ffffff" | &nbsp;

-| bgcolor="#46a546" | &nbsp;

-| bgcolor="#46a546" | &nbsp;

-| bgcolor="#46a546" | &nbsp;

-| bgcolor="#46a546" | &nbsp;

-| bgcolor="#46a546" | &nbsp;

-| bgcolor="#9d261d" | &nbsp;

-| bgcolor="#9d261d" | &nbsp;

-|-

-| align="center" | 1.0 

-| bgcolor="#ffffff" | &nbsp;

-| bgcolor="#ffffff" | &nbsp;

-| bgcolor="#ffffff" | &nbsp;

-| bgcolor="#ffffff" | &nbsp;

-| bgcolor="#46a546" | &nbsp;

-| bgcolor="#46a546" | &nbsp;

-| bgcolor="#46a546" | &nbsp;

-| bgcolor="#46a546" | &nbsp;

-| bgcolor="#9d261d" | &nbsp;

-|}

-

-An empty cell indicates that the compatibility hasn't been tested for a particular combination.

-

-=== User Interface Breakdown ===

-

-The main points of interest are highlighted in the following picture :

-

-[[Image:./../images/EMF_Compare_User_Interface.png|center|EMF Compare's basic user interface]]

-

-# Overview of the differences detected between the given two (or three) models.

-# First version of the compared models.

-# Second version of the compared models.

-# This button will only be visible in the case of three-way comparisons (for example, comparing with a remote repository). It will make a third version of the compared model (the common ancestor of the two others) visible in the interface.

-# When you select a difference in the top panel, the consequences of the merge of this difference are highlighted in green and red. 

-#* The consequences highlighted in <span style="color:green">green</span>  are the differences that will be merge with the selected difference.

-#* The consequences highlighted in <span style="color:red">red</span>  are the differences that will be not "mergeable" after the merge of the selected difference.

-#* A click on a <span style="color:green">green</span> or <span style="color:red">red</span> rectangle in the right gutter will lead you to the concerned consequence.

-

-==== Toolbar ====

-

-The toolbar displays the current status of the comparison and allows you to act on differences.

-

-[[Image:./../images/EMF_Compare_User_Interface_Toolbar.png|center|EMF Compare's user interface toolbar]]

-

-# Gives the number of differences still to be merged, and the number of differences filtered from the view.

-# Allows to change the direction of consequences that are highlighted in green and red in the top panel. You can either display the consequences of a merge from left to right or right to left.

-# Allows you to merge the single, currently selected difference in a given direction (left to right, or right to left).

-# Allows you to merge all non conflicting differences (left to right, or right to left) at once.

-# Allows you to navigate through the detected differences.

-# Allows to expand/collapse all differences in the top panel.

-# This button will allow you to group differences together in the structural view. For example, grouping all "Additions" or "Deletions" together.

-# This button will allow you to filter some differences out of the view according to a set predicate. For example, filtering out all "Additions" or "Moves".

-# Allows to save the comparison model.

-

-When you compare models with one in a read-only mode, some of actions proposed by the toolbar are slightly different. Indeed, if you compare a model with the local history, or you compare a model with a remote model stored in a repository, the latter is in a read-only mode. You will not able to merge differences to this read-only model. You will only accept or reject changes for your local model.

-

-[[Image:./../images/EMF_Compare_User_Interface_Toolbar_With_Read_Only_Side.png|center|EMF Compare's user interface toolbar]]

-

-# Allows to change the kind of consequences that are highlighted in green and red in the top panel. You can either display the consequences of accepting/rejecting the selected change.

-# Allows you to accept the single, currently selected change.

-# Allows you to reject the single, currently selected change.

-# Allows you to accept all non conflicting changes at once.

-# Allows you to reject all non conflicting changes at once.

-

-==== Signification of icons associated with differences ====

-

-When you run a comparison involving two models (a 2-way comparison), the icons associated with differences are:

-

-* [[Image:./../images/add_ov.gif|Addition]] represent an addition in the left side model of the comparison.

-* [[Image:./../images/del_ov.gif|Deletion]] represent a deletion in the left side model of the comparison.

-* [[Image:./../images/chg_ov.gif|Change]] represent a change (set/unset/move) in the left side model of the comparison.

-

-When you run a comparison involving three models (a 3-way comparison), the icons associated with differences are:

-

-*[[Image:./../images/r_inchg_ov.gif|Incoming change]] incoming differences are changes that were made in the right-side/remote model since common ancestor.

-*[[Image:./../images/r_outchg_ov.gif|Outgoing change]] outgoing differences are changes that were made in the left-side/local model since common ancestor.

-*[[Image:./../images/r_inadd_ov.gif|Incoming addition]] represent an incoming addition difference.

-*[[Image:./../images/r_indel_ov.gif|Incoming deletion]] represent an incoming deletion difference.

-*[[Image:./../images/r_outadd_ov.gif|Outgoing addition]] represent an outgoing addition difference.

-*[[Image:./../images/r_outdel_ov.gif|Outgoing deletion]] represent an outgoing deletion difference.

-*[[Image:./../images/confr_chg_ov.gif|Incoming conflict]] incoming conflict differences are changes that were made in the right-side/remote model since common ancestor, and are in conflict with the left-side/local model.

-*[[Image:./../images/confchg_ov.gif|Outgoing conflict]] outgoing conflict differences are changes that were made in the right-side/remote model since common ancestor, and are in conflict with the right-side/remote model.

-*[[Image:./../images/confr_add_ov.gif|Incoming conflict addition]] represent an incoming addition conflict.

-*[[Image:./../images/confr_del_ov.gif|Incoming conflict deletion]] represent an incoming deletion conflict.

-*[[Image:./../images/confadd_ov.gif|Outgoing conflict addition]] represent an outgoing addition conflict.

-*[[Image:./../images/confdel_ov.gif|Outgoing conflict deletion]] represent an outgoing deletion conflict.

-*[[Image:./../images/pconfr_chg_ov.gif|Incoming pseudo conflict]] incoming pseudo conflict differences are changes that were made in the right-side/remote model since common ancestor, and are in pseudo conflict with the left-side/local model.

-*[[Image:./../images/pconfchg_ov.gif|Outgoing pseudo conflict]] outgoing pseudo conflict differences are changes that were made in the right-side/remote model since common ancestor, and are in pseudo conflict with the right-side/remote model.

-*[[Image:./../images/pconfr_add_ov.gif|Incoming pseudo conflict addition]] represent an incoming pseudo conflict addition.

-*[[Image:./../images/pconfr_del_ov.gif|Incoming pseudo conflict deletion]] represent an incoming pseudo conflict deletion.

-*[[Image:./../images/pconfadd_ov.gif|Outgoing pseudo conflict addition]] represent an outgoing pseudo conflict addition.

-*[[Image:./../images/pconfdel_ov.gif|Outgoing pseudo conflict deletion]] represent an outgoing pseudo conflict deletion.

-

-==== After merge ====

-

-The ''merged'' differences are displayed in <span style="color:gray">gray</span> and have a distinct icon.

-

-*[[Image:./../images/merged_left_ov.gif|Merged difference from right to left]] represent a difference that has been merged from right to left.

-*[[Image:./../images/merged_right_ov.gif|Merged difference from left to right]] represent a difference that has been merged from left to right.

-

-When you compare models with one in a read-only mode, the icons are:

-

-*[[Image:./../images/merged_ov.gif|Accepted change]] represent a change that has been accepted.

-*[[Image:./../images/removed_ov.gif|Rejected change]] represent a change that has been rejected.

-

-

-== Launch Comparison ==

-

-Once installed, you can compare your files (locally or from any Version Control System) as usual using the '''Compare With''' menu.

-

-=== Compare with local models ===

-

-==== Compare with each other ====

-

-You can compare two or three models by selecting them and then using the '''Compare With > Each Other''' menu:

-

-[[Image:./../images/EMF_Compare_With_Each_Other.png|center]]

-

-If you run a 3-way comparison (with 3 models), you have to select the ancestor of the comparison:

-

-[[Image:./../images/EMF_Compare_Select_Common_Ancestor.png|center]]

-

-==== Compare with local history ====

-

-You can also compare your local model with one of its previous version available in the local history. For that, use the '''Compare With > Local History''' menu:

-

-[[Image:./../images/EMFC_Compare_With.png|center]]

-

-=== Compare with remote models ===

-

-The following displays the important part of a model life cycle with regards to the comparison. The full life cycle can be followed on [[./sample-use-case.html| Sample Use Case]]

-

-==== Compare with latest ====

-

-For this test, we'll suppose that you are trying to use EMF Compare on UML models shared under git. This will not go in details about UML and Git. We'll assume that you know how to manipulate an UML model, create or clone a git repository, share a project under it and use standard Git operations.

-

-The name of our sample project will be "library". It contains a single folder "model" containing two models :

-* library_Types.uml will contain our primitive types,

-* library.uml will contain our actual model.

-

-The model itself is a very simple library. Graphically speaking :

-

-[[Image:./../images/EMF_Compare_Use_Model.png]]

-

-We commit this initial file as the original model. We then slightly modify it so that it now looks like :

-

-[[Image:./../images/EMF_Compare_Use_Model_Changed.png]]

-

-But how do we know exactly what changed? Let's compare this with the file from the Git Index :

-

-[[Image:./../images/EMF_Compare_Use_Compare_1.png]]

-

-This will open a comparison editor. Let's select one of the differences displayed on its top half :

-

-[[Image:./../images/EMF_Compare_Use_Compare_3.png]]

-

-# We've selected the difference corresponding to the addition of attribute '''alias''' in the class '''Writer'''. A double-click on this difference updated our two panes below.

-# '''alias''' has been added to the properties of Class '''Writer'''. In the model, this corresponds to a change to the reference ''ownedAttributes'' of the ''Writer'' Class. This sub-panel indicates the actual reference that was changed in oder to remind us of the context.

-# This displays all values of the reference outlined in (2) as they are in the ''left'' model. This is where we see the new value, '''alias''' outlined.

-# As for (2), this will display the context of the selected difference. The same reference will usually be displayed in both (2) and (4).

-# This panel displays all values of the reference outlined in (4) as they are in the ''right'' model. In here, we see the location of '''alias''' outlined as an empty space. This rectangle is where the new value will be added if we merge it. 

-In this case, it is possible to merge towards the ''right'' : the ''index'' version of the model is editable, like any other file in the index. If we merge this difference towards the ''right'', then it will exist an ''unstaged'' version of the model, and a ''staged'' version of the model, that will include the merged difference.

-

-But this comparison with index is mainly useful in order to determine exactly what changed in our version. Let's commit our changes on the ''master'' branch.

-

-==== Compare two differing branches ====

-

-After that, our model can evolve, and evolve separately in multiple branches. Let's consider the case where we would have a ''master'' branch differing from a ''borrowables'' branch such as the two look like this (the branching point was the model we've already displayed above) :

-

-{| border="1" cellpadding="5" cellspacing="0" align="center"

-|-

-! align="center" | Master

-! align="center" | Borrowables

-|-

-| [[Image:./../images/EMF_Compare_Use_Compare_Master.png|center]]

-| [[Image:./../images/EMF_Compare_Use_Compare_5.png|center]]

-|}

-

-Before we continue working on our Borrowables branch, we'd like to retrieve all modifications that have been pushed to master. With the "Borrowables" branch checked out, we'll use the ''Compare With > Branch, Tag or Reference'' action :

-

-[[Image:./../images/EMF_Compare_Use_Compare_With_Master_1.png|center]]

-

-and compare with master :

-

-[[Image:./../images/EMF_Compare_Use_Compare_With_Master_2.png|center]]

-

-This shows us all differences between our local copy and the master branch that were made since the 'branching' point.

-

-[[Image:./../images/EMF_Compare_Merge.png|center]]

-

-Same as previously, you can navigate through the differences via the top panel, the structural view. There are three main kind of elements displayed here. '''Regular''' elements, that mimic the containment tree of your input models, are there to separate the various differences and let you know where they were actually detected. Then there are '''incoming''' differences, decorated with a blue arrow ([[Image:./../images/EMF_Compare_Incoming_Change.gif]]) or a derived icon, and '''outgoing''' differences decorated with a gray arrow ([[Image:./../images/EMF_Compare_Outgoing_Change.gif]]) or a derived icon.

-

-'''Incoming''' differences are changes that were made in the remote branch (here, ''master'') since the branching point (common ancestor).

-'''Outgoing''' differences are changes taht were made in the local copy (here, the ''borrowables'' branch) since the branching point.

-

-There are no conflicts here, since UML uses computed identifiers (XMI ID) for the model elements. Thus, what looks like a conflict (the "Date" type that's been added on both branch in the types packages) is actually two distinct differences.

-

-The interface also lets you display the common ancestor of both models through the [[Image:./../images/EMF_Compare_Ancestor.gif]] icon. For example, if we select the '''Book''' class, we can see how it looks like on all three versions :

-

-[[Image:./../images/EMF_Compare_Merge_Book_Ancestor.png|center]]

-

-You can navigate through the differences using the appropriate actions, either the previous ([[Image:./../images/EMF_Compare_Prev_Diff.gif]]) or the next ([[Image:./../images/EMF_Compare_Next_Diff.gif]]) difference.

-

-The remaining two actions are those that actually interest us here we can either accept all non-conflicting differences to the local copy through [[Image:./../images/accept_all_changes.gif]] or accept them one after the other through [[Image:./../images/accept_change.gif]].

-

-Accept '''all''' differences is not what we seek : we want to keep the changes we made locally, not revert them to the state they had before the branching point (which is their current state on ''master'', the right side). We will then select all ''incoming'' differences (under the ''Right side'' node) one after the other and merge them one by one. This gives us our merged model :

-

-[[Image:./../images/EMF_Compare_Merged.png|center]]

-

-

-== Customization ==

-

-=== Engines ===

-

-During each comparison EMF Compare uses several engines (see [[./../developer/developer-guide.html#Comparison_Process|Comparison process]])

-* Match engine 

-* Difference engine

-* Equivalence engine

-* Requirement engine

-* Conflict detector

-

-EMF Compare offers a way to configure those engines.

-

-==== Match Engine ====

-

-To customize matching phase go to the "Engines" preference page.

-

-* Open preferences: Window > Preferences > EMF Compare

-* Select "Engines" page

-* Open Match tab

-

-[[File:../images/EMF_Compare_Match_Engine_Preference_Page.png]]

-

-===== Configure registered matching engine =====

-

-Some of the registered Matching engines could be configured. If so, an extra panel will be displayed on the left part of the preference page when the Match engine is selected.

-

-====== Matching strategy for default match engine ======

-

-The matching strategy of the default match engine can be configured.

- 

-[[File:../images/EMF_Compare_Match_Engine_Preference_Page_Configuration.png]]

- 

-Basically, you can choose to use either a strategy based on object identifiers or a strategy based on object content or both.

-* Only: Matching strategy based on id only. The match engine will only match two objects together if they have the same identifier. (see [[./../developer/developer-guide.html#Match_2 | Identifiers in Default Match Engine]]).

-* Never: Matching strategy based on object content. Only the structure of the object will define if two objects can match.

-* When available: This strategy will use both of the above strategies. If an identifier is found on an object then it will use the "Identifier Strategy" if not it will use the "Content strategy".

-

- 

-===== Enable/Disable Match Engines =====

-

-Additional Match Engines can be contributed through EMF Compare's extension point (see [[./../developer/developer-guide.html#Overriding_the_Match_engine |Override Match Engine]]). They can be enabled or disabled from the preference page.

-

-[[File:../images/EMF_Compare_Match_Engine_Preference_Page_List.png]]

-

-* On this page you will find all registered match engines. They are ordered by priority (highest priority on top of the list). To enable an engine, check it. Uncheck the engine to disabled it. The first enabled Match engine that handles the comparison will be used.

-

-==== For other engines ====

-To customize one of the other phase, go to the "Engines" preference page.

-

-* Open preferences: Window > Preferences > EMF Compare

-* Select "Engines" page

-* Open the tab corresponding to the phase to customize.

-

-[[File:../images/EMF_Compare_Engines_Preference_Page.png]]

-

-===== Choose the default engine =====

-

-On this tab you can select which engine will be used by the comparison process. To do so, check the engine you want to define as default.

-

-=== Post processors customization ===

-

-Result of each phase of the comparison process (see [[./../developer/developer-guide.html#Comparison_Process|Comparison process]]) can be refined thanks to post processors.

-

-More information:

-* [[./../developer/developer-guide.html#Refine_the_default_Match_result|Refine Match Result]],

-* [[./../developer/developer-guide.html#Refine_the_default_Diff_result|Refine Diff Result]],

-* [[./../developer/developer-guide.html#Refine_the_default_equivalences|Refine Equivalence Result]]

-* etc ...

-

-To customize those post-processors go to the related preference page. 

-* Open preference page: Open Window > Preferences 

-* Select post-processors preference page: Select  EMF Compare > Post Processors

-

-[[File:../images/EMF_Compare_Post_Processor_Preference_Page.png]]

-

-On this page you will find all registered post processors. They have been sorted by ordinal (top element of the list will be executed first). To enable or disable any post processor simply check or uncheck each of them. Unchecked post processors will not be triggered during later comparisons.

-

-==== Model Resolvers ====

-For each comparison, EMF Compare needs to define which resources are about to be compared. This scope is called the logical model (see [[./../developer/logical-model.html#What_is_a_logical_model_.3F | Logical Model]]). Model resolvers are used to define strategies to build this logical model.

-

-To customize the model resolution behavior go to the "Resolution strategy" preference page.

-# Open preferences: Window -> Preferences

-# Open "Resolution strategy" preference page: EMF Compare > Resolution strategy

-

-[[File:../images/EMF_Compare_Model_Resolver_Preference_Page.png]]

-

-===== Disable model resolution =====

-

-EMF Compare can prevent building the logical model. In that case, it will only compare the selected resources. To disable model resolution, uncheck the button called "Enable model resolution".

-

-===== Choose a strategy =====

-

-By default, EMF Compare proposes 3 different strategies:

-* Default: This strategy will use the highest ranking model resolver contributed to the platform. With the basic EMF compare installation, this strategy will be "Resolve in project". 

-* Resolve in project: This strategy will resolve resources referenced by the current resource and all resources referencing the current resource within its containing project.

-* Resolve descendants: This strategy will resolve all resources referenced by the current resource.

-

-In order to ask EMF Compare to use a specific strategy, first enable the model resolution (if it's not already done) and select it in the combobox.

-

-Other external strategies might be contributed to EMF Compare. In that case it may happen that the selected strategy can not handle a comparison. If it is so, EMF Compare will use the default strategy.

-

-=== User Interface customization ===

-

-==== Colors Customization ====

-

-You can customize the colors used by EMF Compare to highlight differences in the user interface.

- 

-# Open preferences: Window -> Preferences

-# Go to Colors and Fonts preferences: Select -> General -> Colors and Fonts

-# Open the EMF Compare Category.

-# Select the color you want to customize and click and edit to pick a new color. Your editor will now use your new colors.

-[[Image:./../images/EMFCompare_ColorPreferences.png]]

-

-

-

-==== Filters ====

-You have already been explained how to use filters to hide or display differences in EMF Compare UI (see [[#Toolbar]]). This chapter teaches you how to customize filter default activation.

-

-First open the filters preference page:

-* Open preferences: Window > Preferences > EMF Compare

-* Select "Filters" page.

-

-[[File:../images/EMF_Compare_Filters_Preference_Page.png]]

-

-The first panel (1) is used to define which filters should be activated by default. Checked elements will be activated for later comparisons. Of course, only filters that can handle the comparison will be activated (for futher explanations see [[./../developer/developer-guide.html#Add_your_own_filter|Add you own filter]]).

-

-The second panel (2) is used to define the synchronization behavior between the filters selection in UI and the preferences. The combobox in the preference page has 3 distinct values:

-* Always: Each time you will modify the filters selection in UI, the selected set of filters will be synchronized with the preferences. This way the filters that you have selected will be kept between comparisons.

-* Never: The selection of filters in UI will never be synchronized with the preferences.

-* Prompt: You will be asked each time that filters selection is modified if you want to synchronize the new set of filters with the preferences. If this option is set, a popup will appear just after each filter activation or deactivation. This popup proposes several ways to handle the newly selected set of filters: [[File:../images/EMF_Compare_Filters_Synchronization_Dialog.png]]

-** If your answer is "Yes", the current set of selected filters will be synchronized with the preferences. In other word, it will become your default actived set of filters.

-** If your answer is "No", nothing will be synchronized. Next time you will launch a comparison, the activated filters will be defined by the preferences.

-** If you check "Do not ask me again", the above behaviors will be executed and the synchronization behavior will change. It will be set to "Always" if you have selected "Yes". It will be set to "Never" if you have selected "No".

-

-==== Groups ====

-

-You have already been explained how to use groups to gather differences in EMF Compare UI (see [[#Toolbar]]). This chapter teaches you how to customize the default activated group in EMF Compare.

-

-First open the Groups preference page:

-* Open preferences: Window > Preferences > EMF Compare

-* Select "Groups" page.

-

-[[File:../images/EMF_Compare_Groups_Preference_Page.png]]

-

-This page is divided in two tabs. The first tab handles 2-way comparisons and the second tab handles 3-way comparisons.

-Each tab contains two panels:

-

-The top panel (1) is used to define the default group. EMF Compare uses an ordered list of groups to determine which group should be the default one. The first group in this list that can handle the comparison is chosen as default group. To change it, simply put the desired group in top of the list. To do so, use the up and down buttons located on the right side of the panel.

-

-The bottom panel (2) is used to define a synchronization behavior between selected group in UI and the preferences. The combo box lets you choose between 3 different behaviors: 

-* Always: Each time you will select a group in UI, it will become the default group.

-* Never: The selection of a group in UI will never modify the default group.

-* Prompt: You will be asked each time you change the active group if you want to synchronize it with the preferences. A popup will appear. It will propose several ways to handle the newly selected group: [[File:../images/EMF_Compare_Groups_Synchronization_Dialog.png]]

-** If your answer is "Yes", the current group will be synchronized with the preferences. In other word, it will become the default group.

-** If your answer is "No", nothing will be synchronized. Next time you will start a comparison, the default group will be defined by the preferences.

-** If you check "Do not ask me again", the above behaviors will be executed and the synchronization behavior will change. It will be set to "Always" if you have selected "Yes". It will be set to "Never" if you have selected "No".

-

-== Features ==

-

-=== Grouping Differences  ===

-

-This feature allows you to group differences together in the structural view according to a set predicate. By default, EMF Compare provides four distinct grouping strategies :

-

-[[Image:./../images/EMF_Compare_Groups_Choice.png]]

-

-; Default : Do not try and group differences together, display them as they were detected.

-

-[[Image:./../images/EMF_Compare_Groups_Default.png]]

-

-; By Kind : Group differences by their kind (''additions'', ''deletions'', ''moves'', ''changes'').

-

-[[Image:./../images/EMF_Compare_Groups_Kind.png]]

-

-; By Side : Group differences according to their side: left or right and a special group regrouping differences in conflicts with other differences together. This grouping strategy is display by default in case of a 3-way comparison.

-

-[[Image:./../images/EMF_Compare_Groups_Side.png]]

-

-; By Resource : Group differences according to their resource: useful when more than two resources involved in comparison and/or resources are split into fragments. 

-

-[[Image:./../images/EMF_Compare_Groups_Resource.png]]

-

-

-PENDING UPDATE, this is a demo displaying EMF Compare 1.3 [http://www.eclipse.org/emf/compare/doc/features/videos/Groups/groups.htm Demo]

-

-New grouping strategies can be provided to EMF Compare through extension points. See [[./../developer/developer-guide.html#Add your own group|Add your own group]] section in developer guide for further details. 

-

-=== Filtering Differences  ===

-

-This features allows you to filter differences out of the structural view according to a set predicate. By default, EMF Compare provides four distinct filters :

-

-[[Image:./../images/EMF_Compare_Filters_Choice.png]]

-

-; Pseudo conflicts differences : Filter out all pseudo conflicts differences (only in case of a 3-way comparison). Enabled by default.

-; Identical elements : Filter out all identical elements (elements with no differences). Enabled by default.

-; Empty Resource Mappings : Filter out all resource mappings with no differences from the view. Enabled by default.

-; Cascading differences : Filter out all differences that are contained under differences (except when in conflict). Enabled by default.

-

-PENDING UPDATE, this is a demo displaying EMF Compare 1.3 [http://www.eclipse.org/emf/compare/doc/features/videos/Filters/filters.htm Demo]

-

-New filters can be provided to EMF Compare through extension points. See [[./../developer/developer-guide.html#Add your own filter|Add your own filter]] section in developer guide for further details.

-

-=== Handling Conflicts  ===

-

-When a 3-way comparison has conflicts, all differences involved in the same conflict are grouped under a Confict node.

-

-In the following case, the Employee Green has his manager reference in conflict. The left side of the comparison shows that the manager of the Employee Green is the employee Smith while the right side side shows that the manager is the Employee Johnson.

-The consequences of a merge from right to left of the selected difference are displayed.

-

-When the left side difference ''Employee Smith [ manager changed ]'' is selected in the top panel, the right side difference ''Employee Johnson [ manager changed ]'' is highlighted in red, that means if the the left side difference ''Employee Smith [ manager changed ]'' is merged from right to left, then it will be impossible to merge the right side difference ''Employee Johnson [ manager changed ]'' from left to right.

-

-[[Image:./../images/EMF_Compare_Handling_Conflict_1.png]]

-

-After the merge of the left side difference from right to left ''Employee Smith [ manager changed ]'', the right side difference ''Employee Johnson [ manager changed ]'' is not "mergeable" from left to right anymore, it has been merged from right to left automatically.

-

-[[Image:./../images/EMF_Compare_Handling_Conflict_2.png]]

-

-=== Text Attribute Comparison  ===

-

-In case of differences made on ''String''-typed attributes, specifics actions are available in the top-right of the content viewer panel.

-

-[[Image:./../images/EMF_Compare_Text_Compare.png]]

-

-# Allows to merge all changes of the current difference.

-# Allows to merge the current change.

-# Allows to move to the next/previous textual difference (in case of multi-valuated ''String''-typed attributes).

-# Allows to move to next/previous change in the current textual difference.

-

-PENDING UPDATE, this demo displays EMF Compare 1.3

-[http://www.eclipse.org/emf/compare/doc/features/videos/Text%20compare/textCompare.htm Demo]

-

-=== Graphical Comparison  ===

-

-EMF compare provides the ability to compare models with Papyrus graphical modeler (GMF Diagrams). To get the graphical comparison, the ''EMF Compare Papyrus integration'' feature and Papyrus have to be installed.

-The graphical comparison will be launched if you compare diagrams files (.di), or if you compare models that have diagrams associated in the same folder.

-In the same way as the semantic model comparison, the graphical model comparison uses the same color coding, to distinguish <span style="color:blue">incoming</span> and <span style="color:gray">outgoing</span> changes, and <span style="color:red">conflicts</span>. To put in relief the graphical differences, some decorators are used:

-*On one hand, to focus on the impacted objects, identifying them with markers. These markers are simple transparent rectangles which are set down above the concerned objects and are lightly larger.

-*On the other hand, through phantoms (place-holders), to locate either the place where objects were deleted or the target location where objects should be added after merging.

-The color of the concerned decorators are highlighted on selection of the difference.

-

-In the following example, a 3-way comparison is run with UML class diagrams. We can see that a Shape associated to a semantic uml class named A has been added on the left side of the comparison. After selected the difference in top panel, we can see the concerned elements in down panels. In the left part, the Shape A is highlighted in gray because it is an incoming change. In the right part, a phantom is drawn at the place the Shape should be after merging from right to left.

-

-[[Image:./../images/EMF_Compare_Graphical_AddClassA.png]]

-

-About phantoms (place-holders):

-

-To ease their readability, in some cases, their context have to be displayed:

-*If they are nested in an other phantom (e.g. due to a delete of the parent object), this last contextual one is displayed at the same time as the main phantom concerned by the current selected change.

-*If they are edges connected to deleted nodes or edges, these last contextual ones are displayed at the same time as the main edge phantom.

-*The color of the contextual phantoms (dependencies) is not highlighted.

-They are drawn as:

-*A simple rectangle for nodes, at the same origin location (and size).

-*A simple line (with the same bend points) for edges, at the same location.

-*A simple line for nodes as element of containment list. For this case, the same LCS computation will be used to locate in the list, at the good index.

-*Particular cases: If the location of the contextual phantoms was changed, the new location of the main phantom is computed.

-**A node place-holder, related to a delete of a node, embedded in a node where the location changed.

-**An edge place-holder between nodes where the location changed. In this case, the display of the line is drawn again.

-

-

-Here is an example of nested phantom:

-* the first capture represent an addition of a lifeline in sequence diagram.

-

-[[Image:./../images/EMF_Compare_Graphical_Phantom.gif]]

-

-* the second capture represent an addition of an execution inside the lifeline. We can see the phantom of the execution element, which is highlighted and the phantom of the lifeline parent, which is not highlighted. 

-

-[[Image:./../images/EMF_Compare_Graphical_Nested_Phantom.gif]]

-

-Have a look on the following demos :

-

-PENDING update videos

-

-[[http://www.eclipse.org/emf/compare/doc/features/videos/EcoreTools-v2/EMFCompareEcoreTools.html | Demo : Comparing Ecore files with diagrams]] 

-

-[[http://www.eclipse.org/emf/compare/doc/features/videos/Papyrus/EMFComparePapyrus.html | Demo : Comparing UML files with diagrams]] 

-

-=== Logical Model  ===

-

-EMF Compare does not act simply on the selected files, but on their whole logical model (a given model can be split through multiple files through EMF ''control'' action). Thanks to that, if you try and compare a model file that reference other model files, the comparison will still be able to take these "other" files into account. For example, if you try and compare a ''genmodel'' file (that depends on its underlying ''ecore'' file) :

-

-[[Image:./../images/EMF_Compare_Logical_Compare_Action.png]]

-

-EMF Compare will actually consider both files when comparing :

-

-[[Image:./../images/EMF_Compare_Logical_Compare_Result.png]]

-

-PENDING UPDATE

-[http://www.eclipse.org/emf/compare/doc/features/videos/LogicalModels/LogicalModels.html Demo]

-

-=== UML Specialization  ===

-

-A specific work has been done with EMF Compare for UML. It consists in an additionnal filter named '''UML refined elements'''. This filter is active by default when a comparison involves UML resources.

-

-[[Image:./../images/EMF_Compare_UML_Filter.png]]

-

-The filter groups UML consistant differences together in one difference. For example, a UML association is modeled by an association element and several sub-elements:

-

-[[Image:./../images/EMF_Compare_UML_Association.png]]

-

-If EMF Compare detects a change on an element of type association, it will group all changes on the sub-elements of the assocation to the association difference.

-The goal of this filter is to ease the merge of differences. Indeed, all you have to do is to merge the association difference and it will merge all the sub-differences with it.

-

-Here is the comparison of two UML model, one with an association (the left side), another whithout (the right side). The '''UML refined elements''' filter has been deactivated:

-

-[[Image:./../images/EMF_Compare_UML_Association_2.png]]

-

-We can see a lot of differences. 

-The same comparison with the '''UML refined elements''' filter activated:

-

-[[Image:./../images/EMF_Compare_UML_Association_3.png]]

-

-PENDING

-

-[[http://www.eclipse.org/emf/compare/doc/features/videos/UML%20comparison/compareUml.htm | Demo : Specific support to encapsulate profiles and stereotypes diffs]]

-

-== Known Bugs and Limitations ==

-

-=== Project names and location ===

-

-'''Project names should match their location'''

-

-==== Cause ====

-

-If you need to compare models that:

-* reference another model in the same project (or another project which also meets the following point), and

-* are located in a project which name (as seen in their '.project' file) does not match their containing folder's name (case sensitive).

-

-Due to [https://bugs.eclipse.org/bugs/show_bug.cgi?id=354801 Bug 354801], we cannot properly support models that are located in Eclipse projects which identifier is distinct from their containing folder, case included. For example, if you have a project named ''EcoreModels'', it '''must''' be contained in a folder named ''EcoreModels''. Any other name, even if changing only the case, such as ''ecoreModels'', will cause issues when comparing fragmented models (or any model which references another).

-

-Note that this only applies to comparisons launched from within Eclipse, which would trigger the opening of the EMF Compare user interface.

-

-==== Observed Symptoms ====

-

-Symptoms vary, but they often include a NullPointerException somewhere in EMFSynchronizationModel such as :

-

- Caused by: java.lang.NullPointerException

- at org.eclipse.emf.compare.ide.ui.logical.RevisionedURIConverter.<init>(RevisionedURIConverter.java:108)

- at org.eclipse.emf.compare.ide.ui.logical.EMFSynchronizationModel.resolveTraversal(EMFSynchronizationModel.java:464)

- at org.eclipse.emf.compare.ide.ui.logical.EMFSynchronizationModel.createSynchronizationModel(EMFSynchronizationModel.java:165)

- at org.eclipse.emf.compare.ide.ui.internal.structuremergeviewer.EMFCompareStructureMergeViewer.compareInputChanged(EMFCompareStructureMergeViewer.java:258)

-

-=== Models out of the workspace ===

-

-'''The models should be imported within the workspace'''

-

-==== Cause ====

-

-Trying to compare models that are not present in the current Eclipse workspace from either the ''Git repositories'' perspective, or from the ''Git Staging'' view.

-

-Note that this only applies to comparisons launched from within Eclipse, which would trigger the opening of the EMF Compare user interface.

-

-==== Observed Symptoms ====

-

-Symptoms are mostly the same here as they would be with the limitation mentionned above regarding project names, and they usually include the same NullPointerException:

-

- Caused by: java.lang.NullPointerException

- at org.eclipse.emf.compare.ide.ui.logical.RevisionedURIConverter.<init>(RevisionedURIConverter.java:108)

- at org.eclipse.emf.compare.ide.ui.logical.EMFSynchronizationModel.resolveTraversal(EMFSynchronizationModel.java:464)

- at org.eclipse.emf.compare.ide.ui.logical.EMFSynchronizationModel.createSynchronizationModel(EMFSynchronizationModel.java:165)

- at org.eclipse.emf.compare.ide.ui.internal.structuremergeviewer.EMFCompareStructureMergeViewer.compareInputChanged(EMFCompareStructureMergeViewer.java:258)

-

-== Other Materials ==

-

-*[http://www.eclipse.org/emf/compare/doc/features/videos/index.html Videos of 2011 new features]

- 

+= User Guide =
+
+== Getting Started ==
+
+=== Installing EMF Compare ===
+
+==== Marketplace Client ====
+
+Using the bundled Eclipse marketplace client you can install EMF Compare in one click. Just type "emf compare", click on search, and then on install. 
+
+[[Image:./../images/Marketplace.png]] 
+
+==== Update Site ====
+
+EMF has been part of the Eclipse release train since Galileo, you can install it using the following update sites, depending on your platform. '''Note''' that the following are not meant to be visited in your internet browser; they must be pasted in the ''Help > Install New Software'' dialog of your Eclipse, as p2 repositories.
+
+  http://download.eclipse.org/releases/juno
+  http://download.eclipse.org/releases/indigo
+  http://download.eclipse.org/releases/helios
+  http://download.eclipse.org/releases/galileo
+
+The [http://www.eclipse.org/emf/compare/downloads/ Download page] lists more specific update sites if you wish to try one of the latest integration builds.
+
+==== Compatibility ====
+
+Please note that the EMF Compare development team does its best to maintain downward compatibility towards Galileo (Eclipse 3.5). Following is the compatibility chart : 
+
+{| border="1"
+|-
+! EMF Compare 
+! bgcolor="#cccccc" align="center" | Eclipse 4.3 - EMF 2.9
+! align="center" | Eclipse 4.2 - EMF 2.8
+! align="center" | Eclipse 3.8 - EMF 2.8 
+! align="center" | Eclipse 3.7 - EMF 2.7 
+! align="center" | Eclipse 3.6 - EMF 2.6 
+! align="center" | Eclipse 3.5 - EMF 2.5 
+! align="center" | Eclipse 3.4 - EMF 2.4
+! align="center" | Eclipse 3.3 - EMF 2.3
+! align="center" | Eclipse 3.2 - EMF 2.2 
+|-
+| bgcolor="#cccccc" align="center" | 2.1
+| bgcolor="#46a546" | &nbsp;
+| bgcolor="#46a546" | &nbsp;
+| bgcolor="#46a546" | &nbsp;
+| bgcolor="#46a546" | &nbsp;
+| bgcolor="#46a546" | &nbsp;
+| bgcolor="#46a546" | &nbsp;
+| bgcolor="#9d261d" | &nbsp;
+| bgcolor="#9d261d" | &nbsp;
+| bgcolor="#9d261d" | &nbsp;
+|-
+| align="center" | 2.0
+| bgcolor="#ffffff" | &nbsp;
+| bgcolor="#46a546" | &nbsp;
+| bgcolor="#46a546" | &nbsp;
+| bgcolor="#46a546" | &nbsp;
+| bgcolor="#46a546" | &nbsp;
+| bgcolor="#46a546" | &nbsp;
+| bgcolor="#9d261d" | &nbsp;
+| bgcolor="#9d261d" | &nbsp;
+| bgcolor="#9d261d" | &nbsp;
+|-
+| align="center" | 1.3
+| bgcolor="#9d261d" | &nbsp;
+| bgcolor="#9d261d" | &nbsp;
+| bgcolor="#46a546" | &nbsp;
+| bgcolor="#46a546" | &nbsp;
+| bgcolor="#46a546" | &nbsp;
+| bgcolor="#46a546" | &nbsp;
+| bgcolor="#9d261d" | &nbsp;
+| bgcolor="#9d261d" | &nbsp;
+| bgcolor="#9d261d" | &nbsp;
+|-
+| align="center" | 1.2 
+| bgcolor="#ffffff" | &nbsp;
+| bgcolor="#ffffff" | &nbsp;
+| bgcolor="#46a546" | &nbsp;
+| bgcolor="#46a546" | &nbsp;
+| bgcolor="#46a546" | &nbsp;
+| bgcolor="#46a546" | &nbsp;
+| bgcolor="#46a546" | &nbsp;
+| bgcolor="#9d261d" | &nbsp;
+| bgcolor="#9d261d" | &nbsp;
+|-
+| align="center" | 1.1 
+| bgcolor="#ffffff" | &nbsp;
+| bgcolor="#ffffff" | &nbsp;
+| bgcolor="#46a546" | &nbsp;
+| bgcolor="#46a546" | &nbsp;
+| bgcolor="#46a546" | &nbsp;
+| bgcolor="#46a546" | &nbsp;
+| bgcolor="#46a546" | &nbsp;
+| bgcolor="#9d261d" | &nbsp;
+| bgcolor="#9d261d" | &nbsp;
+|-
+| align="center" | 1.0 
+| bgcolor="#ffffff" | &nbsp;
+| bgcolor="#ffffff" | &nbsp;
+| bgcolor="#ffffff" | &nbsp;
+| bgcolor="#ffffff" | &nbsp;
+| bgcolor="#46a546" | &nbsp;
+| bgcolor="#46a546" | &nbsp;
+| bgcolor="#46a546" | &nbsp;
+| bgcolor="#46a546" | &nbsp;
+| bgcolor="#9d261d" | &nbsp;
+|}
+
+An empty cell indicates that the compatibility hasn't been tested for a particular combination.
+
+=== User Interface Breakdown ===
+
+The main points of interest are highlighted in the following picture :
+
+[[Image:./../images/EMF_Compare_User_Interface.png|center|EMF Compare's basic user interface]]
+
+# Overview of the differences detected between the given two (or three) models.
+# First version of the compared models.
+# Second version of the compared models.
+# This button will only be visible in the case of three-way comparisons (for example, comparing with a remote repository). It will make a third version of the compared model (the common ancestor of the two others) visible in the interface.
+# When you select a difference in the top panel, the consequences of the merge of this difference are highlighted in green and red. 
+#* The consequences highlighted in <span style="color:green">green</span>  are the differences that will be merge with the selected difference.
+#* The consequences highlighted in <span style="color:red">red</span>  are the differences that will be not "mergeable" after the merge of the selected difference.
+#* A click on a <span style="color:green">green</span> or <span style="color:red">red</span> rectangle in the right gutter will lead you to the concerned consequence.
+
+==== Toolbar ====
+
+The toolbar displays the current status of the comparison and allows you to act on differences.
+
+[[Image:./../images/EMF_Compare_User_Interface_Toolbar.png|center|EMF Compare's user interface toolbar]]
+
+# Gives the number of differences still to be merged, and the number of differences filtered from the view.
+# Allows to change the direction of consequences that are highlighted in green and red in the top panel. You can either display the consequences of a merge from left to right or right to left.
+# Allows you to merge the single, currently selected difference in a given direction (left to right, or right to left).
+# Allows you to merge all non conflicting differences (left to right, or right to left) at once.
+# Allows you to navigate through the detected differences.
+# Allows to expand/collapse all differences in the top panel.
+# This button will allow you to group differences together in the structural view. For example, grouping all "Additions" or "Deletions" together.
+# This button will allow you to filter some differences out of the view according to a set predicate. For example, filtering out all "Additions" or "Moves".
+# Allows to save the comparison model.
+
+When you compare models with one in a read-only mode, some of actions proposed by the toolbar are slightly different. Indeed, if you compare a model with the local history, or you compare a model with a remote model stored in a repository, the latter is in a read-only mode. You will not able to merge differences to this read-only model. You will only accept or reject changes for your local model.
+
+[[Image:./../images/EMF_Compare_User_Interface_Toolbar_With_Read_Only_Side.png|center|EMF Compare's user interface toolbar]]
+
+# Allows to change the kind of consequences that are highlighted in green and red in the top panel. You can either display the consequences of accepting/rejecting the selected change.
+# Allows you to accept the single, currently selected change.
+# Allows you to reject the single, currently selected change.
+# Allows you to accept all non conflicting changes at once.
+# Allows you to reject all non conflicting changes at once.
+
+==== Signification of icons associated with differences ====
+
+When you run a comparison involving two models (a 2-way comparison), the icons associated with differences are:
+
+* [[Image:./../images/add_ov.gif|Addition]] represent an addition in the left side model of the comparison.
+* [[Image:./../images/del_ov.gif|Deletion]] represent a deletion in the left side model of the comparison.
+* [[Image:./../images/chg_ov.gif|Change]] represent a change (set/unset/move) in the left side model of the comparison.
+
+When you run a comparison involving three models (a 3-way comparison), the icons associated with differences are:
+
+*[[Image:./../images/r_inchg_ov.gif|Incoming change]] incoming differences are changes that were made in the right-side/remote model since common ancestor.
+*[[Image:./../images/r_outchg_ov.gif|Outgoing change]] outgoing differences are changes that were made in the left-side/local model since common ancestor.
+*[[Image:./../images/r_inadd_ov.gif|Incoming addition]] represent an incoming addition difference.
+*[[Image:./../images/r_indel_ov.gif|Incoming deletion]] represent an incoming deletion difference.
+*[[Image:./../images/r_outadd_ov.gif|Outgoing addition]] represent an outgoing addition difference.
+*[[Image:./../images/r_outdel_ov.gif|Outgoing deletion]] represent an outgoing deletion difference.
+*[[Image:./../images/confr_chg_ov.gif|Incoming conflict]] incoming conflict differences are changes that were made in the right-side/remote model since common ancestor, and are in conflict with the left-side/local model.
+*[[Image:./../images/confchg_ov.gif|Outgoing conflict]] outgoing conflict differences are changes that were made in the right-side/remote model since common ancestor, and are in conflict with the right-side/remote model.
+*[[Image:./../images/confr_add_ov.gif|Incoming conflict addition]] represent an incoming addition conflict.
+*[[Image:./../images/confr_del_ov.gif|Incoming conflict deletion]] represent an incoming deletion conflict.
+*[[Image:./../images/confadd_ov.gif|Outgoing conflict addition]] represent an outgoing addition conflict.
+*[[Image:./../images/confdel_ov.gif|Outgoing conflict deletion]] represent an outgoing deletion conflict.
+*[[Image:./../images/pconfr_chg_ov.gif|Incoming pseudo conflict]] incoming pseudo conflict differences are changes that were made in the right-side/remote model since common ancestor, and are in pseudo conflict with the left-side/local model.
+*[[Image:./../images/pconfchg_ov.gif|Outgoing pseudo conflict]] outgoing pseudo conflict differences are changes that were made in the right-side/remote model since common ancestor, and are in pseudo conflict with the right-side/remote model.
+*[[Image:./../images/pconfr_add_ov.gif|Incoming pseudo conflict addition]] represent an incoming pseudo conflict addition.
+*[[Image:./../images/pconfr_del_ov.gif|Incoming pseudo conflict deletion]] represent an incoming pseudo conflict deletion.
+*[[Image:./../images/pconfadd_ov.gif|Outgoing pseudo conflict addition]] represent an outgoing pseudo conflict addition.
+*[[Image:./../images/pconfdel_ov.gif|Outgoing pseudo conflict deletion]] represent an outgoing pseudo conflict deletion.
+
+==== After merge ====
+
+The ''merged'' differences are displayed in <span style="color:gray">gray</span> and have a distinct icon.
+
+*[[Image:./../images/merged_left_ov.gif|Merged difference from right to left]] represent a difference that has been merged from right to left.
+*[[Image:./../images/merged_right_ov.gif|Merged difference from left to right]] represent a difference that has been merged from left to right.
+
+When you compare models with one in a read-only mode, the icons are:
+
+*[[Image:./../images/merged_ov.gif|Accepted change]] represent a change that has been accepted.
+*[[Image:./../images/removed_ov.gif|Rejected change]] represent a change that has been rejected.
+
+
+== Launch Comparison ==
+
+Once installed, you can compare your files (locally or from any Version Control System) as usual using the '''Compare With''' menu.
+
+=== Compare with local models ===
+
+==== Compare with each other ====
+
+You can compare two or three models by selecting them and then using the '''Compare With > Each Other''' menu:
+
+[[Image:./../images/EMF_Compare_With_Each_Other.png|center]]
+
+If you run a 3-way comparison (with 3 models), you have to select the ancestor of the comparison:
+
+[[Image:./../images/EMF_Compare_Select_Common_Ancestor.png|center]]
+
+==== Compare with local history ====
+
+You can also compare your local model with one of its previous version available in the local history. For that, use the '''Compare With > Local History''' menu:
+
+[[Image:./../images/EMFC_Compare_With.png|center]]
+
+=== Compare with remote models ===
+
+The following displays the important part of a model life cycle with regards to the comparison. The full life cycle can be followed on [[./sample-use-case.html| Sample Use Case]]
+
+==== Compare with latest ====
+
+For this test, we'll suppose that you are trying to use EMF Compare on UML models shared under git. This will not go in details about UML and Git. We'll assume that you know how to manipulate an UML model, create or clone a git repository, share a project under it and use standard Git operations.
+
+The name of our sample project will be "library". It contains a single folder "model" containing two models :
+* library_Types.uml will contain our primitive types,
+* library.uml will contain our actual model.
+
+The model itself is a very simple library. Graphically speaking :
+
+[[Image:./../images/EMF_Compare_Use_Model.png]]
+
+We commit this initial file as the original model. We then slightly modify it so that it now looks like :
+
+[[Image:./../images/EMF_Compare_Use_Model_Changed.png]]
+
+But how do we know exactly what changed? Let's compare this with the file from the Git Index :
+
+[[Image:./../images/EMF_Compare_Use_Compare_1.png]]
+
+This will open a comparison editor. Let's select one of the differences displayed on its top half :
+
+[[Image:./../images/EMF_Compare_Use_Compare_3.png]]
+
+# We've selected the difference corresponding to the addition of attribute '''alias''' in the class '''Writer'''. A double-click on this difference updated our two panes below.
+# '''alias''' has been added to the properties of Class '''Writer'''. In the model, this corresponds to a change to the reference ''ownedAttributes'' of the ''Writer'' Class. This sub-panel indicates the actual reference that was changed in oder to remind us of the context.
+# This displays all values of the reference outlined in (2) as they are in the ''left'' model. This is where we see the new value, '''alias''' outlined.
+# As for (2), this will display the context of the selected difference. The same reference will usually be displayed in both (2) and (4).
+# This panel displays all values of the reference outlined in (4) as they are in the ''right'' model. In here, we see the location of '''alias''' outlined as an empty space. This rectangle is where the new value will be added if we merge it. 
+In this case, it is possible to merge towards the ''right'' : the ''index'' version of the model is editable, like any other file in the index. If we merge this difference towards the ''right'', then it will exist an ''unstaged'' version of the model, and a ''staged'' version of the model, that will include the merged difference.
+
+But this comparison with index is mainly useful in order to determine exactly what changed in our version. Let's commit our changes on the ''master'' branch.
+
+==== Compare two differing branches ====
+
+After that, our model can evolve, and evolve separately in multiple branches. Let's consider the case where we would have a ''master'' branch differing from a ''borrowables'' branch such as the two look like this (the branching point was the model we've already displayed above) :
+
+{| border="1" cellpadding="5" cellspacing="0" align="center"
+|-
+! align="center" | Master
+! align="center" | Borrowables
+|-
+| [[Image:./../images/EMF_Compare_Use_Compare_Master.png|center]]
+| [[Image:./../images/EMF_Compare_Use_Compare_5.png|center]]
+|}
+
+Before we continue working on our Borrowables branch, we'd like to retrieve all modifications that have been pushed to master. With the "Borrowables" branch checked out, we'll use the ''Compare With > Branch, Tag or Reference'' action :
+
+[[Image:./../images/EMF_Compare_Use_Compare_With_Master_1.png|center]]
+
+and compare with master :
+
+[[Image:./../images/EMF_Compare_Use_Compare_With_Master_2.png|center]]
+
+This shows us all differences between our local copy and the master branch that were made since the 'branching' point.
+
+[[Image:./../images/EMF_Compare_Merge.png|center]]
+
+Same as previously, you can navigate through the differences via the top panel, the structural view. There are three main kind of elements displayed here. '''Regular''' elements, that mimic the containment tree of your input models, are there to separate the various differences and let you know where they were actually detected. Then there are '''incoming''' differences, decorated with a blue arrow ([[Image:./../images/EMF_Compare_Incoming_Change.gif]]) or a derived icon, and '''outgoing''' differences decorated with a gray arrow ([[Image:./../images/EMF_Compare_Outgoing_Change.gif]]) or a derived icon.
+
+'''Incoming''' differences are changes that were made in the remote branch (here, ''master'') since the branching point (common ancestor).
+'''Outgoing''' differences are changes taht were made in the local copy (here, the ''borrowables'' branch) since the branching point.
+
+There are no conflicts here, since UML uses computed identifiers (XMI ID) for the model elements. Thus, what looks like a conflict (the "Date" type that's been added on both branch in the types packages) is actually two distinct differences.
+
+The interface also lets you display the common ancestor of both models through the [[Image:./../images/EMF_Compare_Ancestor.gif]] icon. For example, if we select the '''Book''' class, we can see how it looks like on all three versions :
+
+[[Image:./../images/EMF_Compare_Merge_Book_Ancestor.png|center]]
+
+You can navigate through the differences using the appropriate actions, either the previous ([[Image:./../images/EMF_Compare_Prev_Diff.gif]]) or the next ([[Image:./../images/EMF_Compare_Next_Diff.gif]]) difference.
+
+The remaining two actions are those that actually interest us here we can either accept all non-conflicting differences to the local copy through [[Image:./../images/accept_all_changes.gif]] or accept them one after the other through [[Image:./../images/accept_change.gif]].
+
+Accept '''all''' differences is not what we seek : we want to keep the changes we made locally, not revert them to the state they had before the branching point (which is their current state on ''master'', the right side). We will then select all ''incoming'' differences (under the ''Right side'' node) one after the other and merge them one by one. This gives us our merged model :
+
+[[Image:./../images/EMF_Compare_Merged.png|center]]
+
+
+== Customization ==
+
+=== Engines ===
+
+During each comparison EMF Compare uses several engines (see [[./../developer/developer-guide.html#Comparison_Process|Comparison process]])
+* Match engine 
+* Difference engine
+* Equivalence engine
+* Requirement engine
+* Conflict detector
+
+EMF Compare offers a way to configure those engines.
+
+==== Match Engine ====
+
+To customize matching phase go to the "Engines" preference page.
+
+* Open preferences: Window > Preferences > EMF Compare
+* Select "Engines" page
+* Open Match tab
+
+[[File:../images/EMF_Compare_Match_Engine_Preference_Page.png]]
+
+===== Configure registered matching engine =====
+
+Some of the registered Matching engines could be configured. If so, an extra panel will be displayed on the left part of the preference page when the Match engine is selected.
+
+====== Matching strategy for default match engine ======
+
+The matching strategy of the default match engine can be configured.
+ 
+[[File:../images/EMF_Compare_Match_Engine_Preference_Page_Configuration.png]]
+ 
+Basically, you can choose to use either a strategy based on object identifiers or a strategy based on object content or both.
+* Only: Matching strategy based on id only. The match engine will only match two objects together if they have the same identifier. (see [[./../developer/developer-guide.html#Match_2 | Identifiers in Default Match Engine]]).
+* Never: Matching strategy based on object content. Only the structure of the object will define if two objects can match.
+* When available: This strategy will use both of the above strategies. If an identifier is found on an object then it will use the "Identifier Strategy" if not it will use the "Content strategy".
+
+ 
+===== Enable/Disable Match Engines =====
+
+Additional Match Engines can be contributed through EMF Compare's extension point (see [[./../developer/developer-guide.html#Overriding_the_Match_engine |Override Match Engine]]). They can be enabled or disabled from the preference page.
+
+[[File:../images/EMF_Compare_Match_Engine_Preference_Page_List.png]]
+
+* On this page you will find all registered match engines. They are ordered by priority (highest priority on top of the list). To enable an engine, check it. Uncheck the engine to disabled it. The first enabled Match engine that handles the comparison will be used.
+
+==== For other engines ====
+To customize one of the other phase, go to the "Engines" preference page.
+
+* Open preferences: Window > Preferences > EMF Compare
+* Select "Engines" page
+* Open the tab corresponding to the phase to customize.
+
+[[File:../images/EMF_Compare_Engines_Preference_Page.png]]
+
+===== Choose the default engine =====
+
+On this tab you can select which engine will be used by the comparison process. To do so, check the engine you want to define as default.
+
+=== Post processors customization ===
+
+Result of each phase of the comparison process (see [[./../developer/developer-guide.html#Comparison_Process|Comparison process]]) can be refined thanks to post processors.
+
+More information:
+* [[./../developer/developer-guide.html#Refine_the_default_Match_result|Refine Match Result]],
+* [[./../developer/developer-guide.html#Refine_the_default_Diff_result|Refine Diff Result]],
+* [[./../developer/developer-guide.html#Refine_the_default_equivalences|Refine Equivalence Result]]
+* etc ...
+
+To customize those post-processors go to the related preference page. 
+* Open preference page: Open Window > Preferences 
+* Select post-processors preference page: Select  EMF Compare > Post Processors
+
+[[File:../images/EMF_Compare_Post_Processor_Preference_Page.png]]
+
+On this page you will find all registered post processors. They have been sorted by ordinal (top element of the list will be executed first). To enable or disable any post processor simply check or uncheck each of them. Unchecked post processors will not be triggered during later comparisons.
+
+==== Model Resolvers ====
+For each comparison, EMF Compare needs to define which resources are about to be compared. This scope is called the logical model (see [[./../developer/logical-model.html#What_is_a_logical_model_.3F | Logical Model]]). Model resolvers are used to define strategies to build this logical model.
+
+To customize the model resolution behavior go to the "Resolution strategy" preference page.
+# Open preferences: Window -> Preferences
+# Open "Resolution strategy" preference page: EMF Compare > Resolution strategy
+
+[[File:../images/EMF_Compare_Model_Resolver_Preference_Page.png]]
+
+===== Disable model resolution =====
+
+EMF Compare can prevent building the logical model. In that case, it will only compare the selected resources. To disable model resolution, uncheck the button called "Enable model resolution".
+
+===== Choose a strategy =====
+
+By default, EMF Compare proposes 3 different strategies:
+* Default: This strategy will use the highest ranking model resolver contributed to the platform. With the basic EMF compare installation, this strategy will be "Resolve in project". 
+* Resolve in project: This strategy will resolve resources referenced by the current resource and all resources referencing the current resource within its containing project.
+* Resolve descendants: This strategy will resolve all resources referenced by the current resource.
+
+In order to ask EMF Compare to use a specific strategy, first enable the model resolution (if it's not already done) and select it in the combobox.
+
+Other external strategies might be contributed to EMF Compare. In that case it may happen that the selected strategy can not handle a comparison. If it is so, EMF Compare will use the default strategy.
+
+=== User Interface customization ===
+
+==== Colors Customization ====
+
+You can customize the colors used by EMF Compare to highlight differences in the user interface.
+ 
+# Open preferences: Window -> Preferences
+# Go to Colors and Fonts preferences: Select -> General -> Colors and Fonts
+# Open the EMF Compare Category.
+# Select the color you want to customize and click and edit to pick a new color. Your editor will now use your new colors.
+[[Image:./../images/EMFCompare_ColorPreferences.png]]
+
+
+
+==== Filters ====
+You have already been explained how to use filters to hide or display differences in EMF Compare UI (see [[#Toolbar]]). This chapter teaches you how to customize filter default activation.
+
+First open the filters preference page:
+* Open preferences: Window > Preferences > EMF Compare
+* Select "Filters" page.
+
+[[File:../images/EMF_Compare_Filters_Preference_Page.png]]
+
+The first panel (1) is used to define which filters should be activated by default. Checked elements will be activated for later comparisons. Of course, only filters that can handle the comparison will be activated (for futher explanations see [[./../developer/developer-guide.html#Add_your_own_filter|Add you own filter]]).
+
+The second panel (2) is used to define the synchronization behavior between the filters selection in UI and the preferences. The combobox in the preference page has 3 distinct values:
+* Always: Each time you will modify the filters selection in UI, the selected set of filters will be synchronized with the preferences. This way the filters that you have selected will be kept between comparisons.
+* Never: The selection of filters in UI will never be synchronized with the preferences.
+* Prompt: You will be asked each time that filters selection is modified if you want to synchronize the new set of filters with the preferences. If this option is set, a popup will appear just after each filter activation or deactivation. This popup proposes several ways to handle the newly selected set of filters: [[File:../images/EMF_Compare_Filters_Synchronization_Dialog.png]]
+** If your answer is "Yes", the current set of selected filters will be synchronized with the preferences. In other word, it will become your default actived set of filters.
+** If your answer is "No", nothing will be synchronized. Next time you will launch a comparison, the activated filters will be defined by the preferences.
+** If you check "Do not ask me again", the above behaviors will be executed and the synchronization behavior will change. It will be set to "Always" if you have selected "Yes". It will be set to "Never" if you have selected "No".
+
+==== Groups ====
+
+You have already been explained how to use groups to gather differences in EMF Compare UI (see [[#Toolbar]]). This chapter teaches you how to customize the default activated group in EMF Compare.
+
+First open the Groups preference page:
+* Open preferences: Window > Preferences > EMF Compare
+* Select "Groups" page.
+
+[[File:../images/EMF_Compare_Groups_Preference_Page.png]]
+
+This page is divided in two tabs. The first tab handles 2-way comparisons and the second tab handles 3-way comparisons.
+Each tab contains two panels:
+
+The top panel (1) is used to define the default group. EMF Compare uses an ordered list of groups to determine which group should be the default one. The first group in this list that can handle the comparison is chosen as default group. To change it, simply put the desired group in top of the list. To do so, use the up and down buttons located on the right side of the panel.
+
+The bottom panel (2) is used to define a synchronization behavior between selected group in UI and the preferences. The combo box lets you choose between 3 different behaviors: 
+* Always: Each time you will select a group in UI, it will become the default group.
+* Never: The selection of a group in UI will never modify the default group.
+* Prompt: You will be asked each time you change the active group if you want to synchronize it with the preferences. A popup will appear. It will propose several ways to handle the newly selected group: [[File:../images/EMF_Compare_Groups_Synchronization_Dialog.png]]
+** If your answer is "Yes", the current group will be synchronized with the preferences. In other word, it will become the default group.
+** If your answer is "No", nothing will be synchronized. Next time you will start a comparison, the default group will be defined by the preferences.
+** If you check "Do not ask me again", the above behaviors will be executed and the synchronization behavior will change. It will be set to "Always" if you have selected "Yes". It will be set to "Never" if you have selected "No".
+
+== Features ==
+
+=== Grouping Differences  ===
+
+This feature allows you to group differences together in the structural view according to a set predicate. By default, EMF Compare provides four distinct grouping strategies :
+
+[[Image:./../images/EMF_Compare_Groups_Choice.png]]
+
+; Default : Do not try and group differences together, display them as they were detected.
+
+[[Image:./../images/EMF_Compare_Groups_Default.png]]
+
+; By Kind : Group differences by their kind (''additions'', ''deletions'', ''moves'', ''changes'').
+
+[[Image:./../images/EMF_Compare_Groups_Kind.png]]
+
+; By Side : Group differences according to their side: left or right and a special group regrouping differences in conflicts with other differences together. This grouping strategy is display by default in case of a 3-way comparison.
+
+[[Image:./../images/EMF_Compare_Groups_Side.png]]
+
+; By Resource : Group differences according to their resource: useful when more than two resources involved in comparison and/or resources are split into fragments. 
+
+[[Image:./../images/EMF_Compare_Groups_Resource.png]]
+
+
+PENDING UPDATE, this is a demo displaying EMF Compare 1.3 [http://www.eclipse.org/emf/compare/doc/features/videos/Groups/groups.htm Demo]
+
+New grouping strategies can be provided to EMF Compare through extension points. See [[./../developer/developer-guide.html#Add your own group|Add your own group]] section in developer guide for further details. 
+
+=== Filtering Differences  ===
+
+This features allows you to filter differences out of the structural view according to a set predicate. By default, EMF Compare provides four distinct filters :
+
+[[Image:./../images/EMF_Compare_Filters_Choice.png]]
+
+; Pseudo conflicts differences : Filter out all pseudo conflicts differences (only in case of a 3-way comparison). Enabled by default.
+; Identical elements : Filter out all identical elements (elements with no differences). Enabled by default.
+; Empty Resource Mappings : Filter out all resource mappings with no differences from the view. Enabled by default.
+; Cascading differences : Filter out all differences that are contained under differences (except when in conflict). Enabled by default.
+
+PENDING UPDATE, this is a demo displaying EMF Compare 1.3 [http://www.eclipse.org/emf/compare/doc/features/videos/Filters/filters.htm Demo]
+
+New filters can be provided to EMF Compare through extension points. See [[./../developer/developer-guide.html#Add your own filter|Add your own filter]] section in developer guide for further details.
+
+=== Handling Conflicts  ===
+
+When a 3-way comparison has conflicts, all differences involved in the same conflict are grouped under a Confict node.
+
+In the following case, the Employee Green has his manager reference in conflict. The left side of the comparison shows that the manager of the Employee Green is the employee Smith while the right side side shows that the manager is the Employee Johnson.
+The consequences of a merge from right to left of the selected difference are displayed.
+
+When the left side difference ''Employee Smith [ manager changed ]'' is selected in the top panel, the right side difference ''Employee Johnson [ manager changed ]'' is highlighted in red, that means if the the left side difference ''Employee Smith [ manager changed ]'' is merged from right to left, then it will be impossible to merge the right side difference ''Employee Johnson [ manager changed ]'' from left to right.
+
+[[Image:./../images/EMF_Compare_Handling_Conflict_1.png]]
+
+After the merge of the left side difference from right to left ''Employee Smith [ manager changed ]'', the right side difference ''Employee Johnson [ manager changed ]'' is not "mergeable" from left to right anymore, it has been merged from right to left automatically.
+
+[[Image:./../images/EMF_Compare_Handling_Conflict_2.png]]
+
+=== Text Attribute Comparison  ===
+
+In case of differences made on ''String''-typed attributes, specifics actions are available in the top-right of the content viewer panel.
+
+[[Image:./../images/EMF_Compare_Text_Compare.png]]
+
+# Allows to merge all changes of the current difference.
+# Allows to merge the current change.
+# Allows to move to the next/previous textual difference (in case of multi-valuated ''String''-typed attributes).
+# Allows to move to next/previous change in the current textual difference.
+
+PENDING UPDATE, this demo displays EMF Compare 1.3
+[http://www.eclipse.org/emf/compare/doc/features/videos/Text%20compare/textCompare.htm Demo]
+
+=== Graphical Comparison  ===
+
+EMF compare provides the ability to compare models with Papyrus graphical modeler (GMF Diagrams). To get the graphical comparison, the ''EMF Compare Papyrus integration'' feature and Papyrus have to be installed.
+The graphical comparison will be launched if you compare diagrams files (.di), or if you compare models that have diagrams associated in the same folder.
+In the same way as the semantic model comparison, the graphical model comparison uses the same color coding, to distinguish <span style="color:blue">incoming</span> and <span style="color:gray">outgoing</span> changes, and <span style="color:red">conflicts</span>. To put in relief the graphical differences, some decorators are used:
+*On one hand, to focus on the impacted objects, identifying them with markers. These markers are simple transparent rectangles which are set down above the concerned objects and are lightly larger.
+*On the other hand, through phantoms (place-holders), to locate either the place where objects were deleted or the target location where objects should be added after merging.
+The color of the concerned decorators are highlighted on selection of the difference.
+
+In the following example, a 3-way comparison is run with UML class diagrams. We can see that a Shape associated to a semantic uml class named A has been added on the left side of the comparison. After selected the difference in top panel, we can see the concerned elements in down panels. In the left part, the Shape A is highlighted in gray because it is an incoming change. In the right part, a phantom is drawn at the place the Shape should be after merging from right to left.
+
+[[Image:./../images/EMF_Compare_Graphical_AddClassA.png]]
+
+About phantoms (place-holders):
+
+To ease their readability, in some cases, their context have to be displayed:
+*If they are nested in an other phantom (e.g. due to a delete of the parent object), this last contextual one is displayed at the same time as the main phantom concerned by the current selected change.
+*If they are edges connected to deleted nodes or edges, these last contextual ones are displayed at the same time as the main edge phantom.
+*The color of the contextual phantoms (dependencies) is not highlighted.
+They are drawn as:
+*A simple rectangle for nodes, at the same origin location (and size).
+*A simple line (with the same bend points) for edges, at the same location.
+*A simple line for nodes as element of containment list. For this case, the same LCS computation will be used to locate in the list, at the good index.
+*Particular cases: If the location of the contextual phantoms was changed, the new location of the main phantom is computed.
+**A node place-holder, related to a delete of a node, embedded in a node where the location changed.
+**An edge place-holder between nodes where the location changed. In this case, the display of the line is drawn again.
+
+
+Here is an example of nested phantom:
+* the first capture represent an addition of a lifeline in sequence diagram.
+
+[[Image:./../images/EMF_Compare_Graphical_Phantom.gif]]
+
+* the second capture represent an addition of an execution inside the lifeline. We can see the phantom of the execution element, which is highlighted and the phantom of the lifeline parent, which is not highlighted. 
+
+[[Image:./../images/EMF_Compare_Graphical_Nested_Phantom.gif]]
+
+Have a look on the following demos :
+
+PENDING update videos
+
+[[http://www.eclipse.org/emf/compare/doc/features/videos/EcoreTools-v2/EMFCompareEcoreTools.html | Demo : Comparing Ecore files with diagrams]] 
+
+[[http://www.eclipse.org/emf/compare/doc/features/videos/Papyrus/EMFComparePapyrus.html | Demo : Comparing UML files with diagrams]] 
+
+=== Logical Model  ===
+
+EMF Compare does not act simply on the selected files, but on their whole logical model (a given model can be split through multiple files through EMF ''control'' action). Thanks to that, if you try and compare a model file that reference other model files, the comparison will still be able to take these "other" files into account. For example, if you try and compare a ''genmodel'' file (that depends on its underlying ''ecore'' file) :
+
+[[Image:./../images/EMF_Compare_Logical_Compare_Action.png]]
+
+EMF Compare will actually consider both files when comparing :
+
+[[Image:./../images/EMF_Compare_Logical_Compare_Result.png]]
+
+PENDING UPDATE
+[http://www.eclipse.org/emf/compare/doc/features/videos/LogicalModels/LogicalModels.html Demo]
+
+=== UML Specialization  ===
+
+A specific work has been done with EMF Compare for UML. It consists in an additionnal filter named '''UML refined elements'''. This filter is active by default when a comparison involves UML resources.
+
+[[Image:./../images/EMF_Compare_UML_Filter.png]]
+
+The filter groups UML consistant differences together in one difference. For example, a UML association is modeled by an association element and several sub-elements:
+
+[[Image:./../images/EMF_Compare_UML_Association.png]]
+
+If EMF Compare detects a change on an element of type association, it will group all changes on the sub-elements of the assocation to the association difference.
+The goal of this filter is to ease the merge of differences. Indeed, all you have to do is to merge the association difference and it will merge all the sub-differences with it.
+
+Here is the comparison of two UML model, one with an association (the left side), another whithout (the right side). The '''UML refined elements''' filter has been deactivated:
+
+[[Image:./../images/EMF_Compare_UML_Association_2.png]]
+
+We can see a lot of differences. 
+The same comparison with the '''UML refined elements''' filter activated:
+
+[[Image:./../images/EMF_Compare_UML_Association_3.png]]
+
+PENDING
+
+[[http://www.eclipse.org/emf/compare/doc/features/videos/UML%20comparison/compareUml.htm | Demo : Specific support to encapsulate profiles and stereotypes diffs]]
+
+== Known Bugs and Limitations ==
+
+=== Project names and location ===
+
+'''Project names should match their location'''
+
+==== Cause ====
+
+If you need to compare models that:
+* reference another model in the same project (or another project which also meets the following point), and
+* are located in a project which name (as seen in their '.project' file) does not match their containing folder's name (case sensitive).
+
+Due to [https://bugs.eclipse.org/bugs/show_bug.cgi?id=354801 Bug 354801], we cannot properly support models that are located in Eclipse projects which identifier is distinct from their containing folder, case included. For example, if you have a project named ''EcoreModels'', it '''must''' be contained in a folder named ''EcoreModels''. Any other name, even if changing only the case, such as ''ecoreModels'', will cause issues when comparing fragmented models (or any model which references another).
+
+Note that this only applies to comparisons launched from within Eclipse, which would trigger the opening of the EMF Compare user interface.
+
+==== Observed Symptoms ====
+
+Symptoms vary, but they often include a NullPointerException somewhere in EMFSynchronizationModel such as :
+
+ Caused by: java.lang.NullPointerException
+ at org.eclipse.emf.compare.ide.ui.logical.RevisionedURIConverter.<init>(RevisionedURIConverter.java:108)
+ at org.eclipse.emf.compare.ide.ui.logical.EMFSynchronizationModel.resolveTraversal(EMFSynchronizationModel.java:464)
+ at org.eclipse.emf.compare.ide.ui.logical.EMFSynchronizationModel.createSynchronizationModel(EMFSynchronizationModel.java:165)
+ at org.eclipse.emf.compare.ide.ui.internal.structuremergeviewer.EMFCompareStructureMergeViewer.compareInputChanged(EMFCompareStructureMergeViewer.java:258)
+
+=== Models out of the workspace ===
+
+'''The models should be imported within the workspace'''
+
+==== Cause ====
+
+Trying to compare models that are not present in the current Eclipse workspace from either the ''Git repositories'' perspective, or from the ''Git Staging'' view.
+
+Note that this only applies to comparisons launched from within Eclipse, which would trigger the opening of the EMF Compare user interface.
+
+==== Observed Symptoms ====
+
+Symptoms are mostly the same here as they would be with the limitation mentionned above regarding project names, and they usually include the same NullPointerException:
+
+ Caused by: java.lang.NullPointerException
+ at org.eclipse.emf.compare.ide.ui.logical.RevisionedURIConverter.<init>(RevisionedURIConverter.java:108)
+ at org.eclipse.emf.compare.ide.ui.logical.EMFSynchronizationModel.resolveTraversal(EMFSynchronizationModel.java:464)
+ at org.eclipse.emf.compare.ide.ui.logical.EMFSynchronizationModel.createSynchronizationModel(EMFSynchronizationModel.java:165)
+ at org.eclipse.emf.compare.ide.ui.internal.structuremergeviewer.EMFCompareStructureMergeViewer.compareInputChanged(EMFCompareStructureMergeViewer.java:258)
+
+== Other Materials ==
+
+*[http://www.eclipse.org/emf/compare/doc/features/videos/index.html Videos of 2011 new features]
+ 
diff --git a/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/contentmergeviewer/WaitViewerCreator.java b/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/contentmergeviewer/WaitViewerCreator.java
index 65cf9dc..04d7a6d 100644
--- a/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/contentmergeviewer/WaitViewerCreator.java
+++ b/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/contentmergeviewer/WaitViewerCreator.java
@@ -1,132 +1,132 @@
-/*******************************************************************************

- * Copyright (c) 2014 Obeo.

- * All rights reserved. This program and the accompanying materials

- * are made available under the terms of the Eclipse Public License v1.0

- * which accompanies this distribution, and is available at

- * http://www.eclipse.org/legal/epl-v10.html

- * 

- * Contributors:

- *     Obeo - initial API and implementation

- *******************************************************************************/

-package org.eclipse.emf.compare.ide.ui.internal.contentmergeviewer;

-

-import org.eclipse.compare.CompareConfiguration;

-import org.eclipse.compare.CompareUI;

-import org.eclipse.compare.IViewerCreator;

-import org.eclipse.emf.compare.ide.ui.internal.EMFCompareIDEUIMessages;

-import org.eclipse.jface.resource.JFaceResources;

-import org.eclipse.jface.viewers.ISelection;

-import org.eclipse.jface.viewers.StructuredSelection;

-import org.eclipse.jface.viewers.Viewer;

-import org.eclipse.swt.SWT;

-import org.eclipse.swt.layout.GridData;

-import org.eclipse.swt.layout.GridLayout;

-import org.eclipse.swt.widgets.Composite;

-import org.eclipse.swt.widgets.Control;

-import org.eclipse.swt.widgets.Label;

-

-/**

- * Creates an empty viewer with a single centered label which say to wait for the comparison to finish.

- * 

- * @author <a href="mailto:mikael.barbero@obeo.fr">Mikael Barbero</a>

- */

-public class WaitViewerCreator implements IViewerCreator {

-

-	/**

-	 * {@inheritDoc}

-	 * 

-	 * @see org.eclipse.compare.IViewerCreator#createViewer(org.eclipse.swt.widgets.Composite,

-	 *      org.eclipse.compare.CompareConfiguration)

-	 */

-	public Viewer createViewer(final Composite parent, CompareConfiguration config) {

-		return new WaitViewer(parent);

-	}

-

-	/**

-	 * A dummy viewer that display a single label.

-	 * 

-	 * @author <a href="mailto:mikael.barbero@obeo.fr">Mikael Barbero</a>

-	 */

-	private final class WaitViewer extends Viewer {

-	

-		/** The Control as returned by {@link #getControl()}. */

-		private final Composite control;

-	

-		/**

-		 * Creates a new viewer and its controls.

-		 * 

-		 * @param parent

-		 *            the parent of the {@link #getControl() control} of this viewer.

-		 */

-		private WaitViewer(Composite parent) {

-			control = new Composite(parent, SWT.NONE);

-			GridLayout layout = new GridLayout(1, true);

-			control.setLayout(layout);

-			Label label = new Label(control, SWT.NONE);

-			label.setText(EMFCompareIDEUIMessages.getString("wait.viewer.desc")); //$NON-NLS-1$

-			label.setFont(JFaceResources.getBannerFont());

-			label.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, true, true));

-			control.setData(CompareUI.COMPARE_VIEWER_TITLE, EMFCompareIDEUIMessages

-					.getString("wait.viewer.title")); //$NON-NLS-1$

-	

-		}

-	

-		/**

-		 * {@inheritDoc}

-		 * 

-		 * @see org.eclipse.jface.viewers.Viewer#setSelection(org.eclipse.jface.viewers.ISelection, boolean)

-		 */

-		@Override

-		public void setSelection(ISelection selection, boolean reveal) {

-		}

-	

-		/**

-		 * {@inheritDoc}

-		 * 

-		 * @see org.eclipse.jface.viewers.Viewer#setInput(java.lang.Object)

-		 */

-		@Override

-		public void setInput(Object input) {

-		}

-	

-		/**

-		 * {@inheritDoc}

-		 * 

-		 * @see org.eclipse.jface.viewers.Viewer#refresh()

-		 */

-		@Override

-		public void refresh() {

-		}

-	

-		/**

-		 * {@inheritDoc}

-		 * 

-		 * @see org.eclipse.jface.viewers.Viewer#getSelection()

-		 */

-		@Override

-		public ISelection getSelection() {

-			return StructuredSelection.EMPTY;

-		}

-	

-		/**

-		 * {@inheritDoc}

-		 * 

-		 * @see org.eclipse.jface.viewers.Viewer#getInput()

-		 */

-		@Override

-		public Object getInput() {

-			return null;

-		}

-	

-		/**

-		 * {@inheritDoc}

-		 * 

-		 * @see org.eclipse.jface.viewers.Viewer#getControl()

-		 */

-		@Override

-		public Control getControl() {

-			return control;

-		}

-	}

-

-}

+/*******************************************************************************
+ * Copyright (c) 2014 Obeo.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     Obeo - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.compare.ide.ui.internal.contentmergeviewer;
+
+import org.eclipse.compare.CompareConfiguration;
+import org.eclipse.compare.CompareUI;
+import org.eclipse.compare.IViewerCreator;
+import org.eclipse.emf.compare.ide.ui.internal.EMFCompareIDEUIMessages;
+import org.eclipse.jface.resource.JFaceResources;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+
+/**
+ * Creates an empty viewer with a single centered label which say to wait for the comparison to finish.
+ * 
+ * @author <a href="mailto:mikael.barbero@obeo.fr">Mikael Barbero</a>
+ */
+public class WaitViewerCreator implements IViewerCreator {
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see org.eclipse.compare.IViewerCreator#createViewer(org.eclipse.swt.widgets.Composite,
+	 *      org.eclipse.compare.CompareConfiguration)
+	 */
+	public Viewer createViewer(final Composite parent, CompareConfiguration config) {
+		return new WaitViewer(parent);
+	}
+
+	/**
+	 * A dummy viewer that display a single label.
+	 * 
+	 * @author <a href="mailto:mikael.barbero@obeo.fr">Mikael Barbero</a>
+	 */
+	private final class WaitViewer extends Viewer {
+	
+		/** The Control as returned by {@link #getControl()}. */
+		private final Composite control;
+	
+		/**
+		 * Creates a new viewer and its controls.
+		 * 
+		 * @param parent
+		 *            the parent of the {@link #getControl() control} of this viewer.
+		 */
+		private WaitViewer(Composite parent) {
+			control = new Composite(parent, SWT.NONE);
+			GridLayout layout = new GridLayout(1, true);
+			control.setLayout(layout);
+			Label label = new Label(control, SWT.NONE);
+			label.setText(EMFCompareIDEUIMessages.getString("wait.viewer.desc")); //$NON-NLS-1$
+			label.setFont(JFaceResources.getBannerFont());
+			label.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, true, true));
+			control.setData(CompareUI.COMPARE_VIEWER_TITLE, EMFCompareIDEUIMessages
+					.getString("wait.viewer.title")); //$NON-NLS-1$
+	
+		}
+	
+		/**
+		 * {@inheritDoc}
+		 * 
+		 * @see org.eclipse.jface.viewers.Viewer#setSelection(org.eclipse.jface.viewers.ISelection, boolean)
+		 */
+		@Override
+		public void setSelection(ISelection selection, boolean reveal) {
+		}
+	
+		/**
+		 * {@inheritDoc}
+		 * 
+		 * @see org.eclipse.jface.viewers.Viewer#setInput(java.lang.Object)
+		 */
+		@Override
+		public void setInput(Object input) {
+		}
+	
+		/**
+		 * {@inheritDoc}
+		 * 
+		 * @see org.eclipse.jface.viewers.Viewer#refresh()
+		 */
+		@Override
+		public void refresh() {
+		}
+	
+		/**
+		 * {@inheritDoc}
+		 * 
+		 * @see org.eclipse.jface.viewers.Viewer#getSelection()
+		 */
+		@Override
+		public ISelection getSelection() {
+			return StructuredSelection.EMPTY;
+		}
+	
+		/**
+		 * {@inheritDoc}
+		 * 
+		 * @see org.eclipse.jface.viewers.Viewer#getInput()
+		 */
+		@Override
+		public Object getInput() {
+			return null;
+		}
+	
+		/**
+		 * {@inheritDoc}
+		 * 
+		 * @see org.eclipse.jface.viewers.Viewer#getControl()
+		 */
+		@Override
+		public Control getControl() {
+			return control;
+		}
+	}
+
+}
diff --git a/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/logical/DependencyResourceSet.java b/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/logical/DependencyResourceSet.java
index bbd5993..d4b81ec 100644
--- a/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/logical/DependencyResourceSet.java
+++ b/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/logical/DependencyResourceSet.java
@@ -1,82 +1,82 @@
-/*******************************************************************************

- * Copyright (c) 2013 Obeo.

- * All rights reserved. This program and the accompanying materials

- * are made available under the terms of the Eclipse Public License v1.0

- * which accompanies this distribution, and is available at

- * http://www.eclipse.org/legal/epl-v10.html

- * 

- * Contributors:

- *     Obeo - initial API and implementation

- *******************************************************************************/

-package org.eclipse.emf.compare.ide.ui.internal.logical;

-

-import java.util.Collections;

-

-import org.eclipse.emf.common.util.URI;

-import org.eclipse.emf.compare.ide.internal.utils.SyncResourceSet;

-import org.eclipse.emf.ecore.EObject;

-import org.eclipse.emf.ecore.InternalEObject;

-import org.eclipse.emf.ecore.resource.Resource;

-

-/**

- * This particular resource set will construct a dependency graph between the resources it loads, without

- * actually keeping them in memory. The graph can be later queried in order to determine the subgraph

- * corresponding to the dependencies of one given resource.

- * 

- * @author <a href="mailto:laurent.goubet@obeo.fr">Laurent Goubet</a>

- */

-public class DependencyResourceSet extends SyncResourceSet {

-	/** Keeps track of the dependency tree discovered through this resource set. */

-	private final Graph<URI> graph;

-

-	/**

-	 * Constructs a resource set given the dependency graph it will populate.

-	 * 

-	 * @param graph

-	 *            The dependency graph we'll populate as we resolve new references.

-	 */

-	public DependencyResourceSet(Graph<URI> graph) {

-		this.graph = graph;

-	}

-

-	/**

-	 * {@inheritDoc}

-	 * 

-	 * @see org.eclipse.emf.compare.ide.internal.utils.SyncResourceSet#createResource(org.eclipse.emf.common.util.URI)

-	 */

-	@Override

-	public synchronized Resource createResource(URI uri) {

-		final Resource resource = super.createResource(uri);

-		graph.add(uri);

-		return resource;

-	}

-

-	/**

-	 * {@inheritDoc}

-	 * 

-	 * @see org.eclipse.emf.compare.ide.internal.utils.SyncResourceSet#createResource(org.eclipse.emf.common.util.URI,

-	 *      java.lang.String)

-	 */

-	@Override

-	public synchronized Resource createResource(URI uri, String contentType) {

-		final Resource resource = super.createResource(uri, contentType);

-		graph.add(uri);

-		return resource;

-	}

-

-	/**

-	 * {@inheritDoc}

-	 * 

-	 * @see org.eclipse.emf.compare.ide.internal.utils.SyncResourceSet#resolveCrossReference(org.eclipse.emf.ecore.resource.Resource,

-	 *      org.eclipse.emf.ecore.EObject)

-	 */

-	@Override

-	protected void resolveCrossReference(Resource resource, EObject proxy) {

-		super.resolveCrossReference(resource, proxy);

-		URI parent = resource.getURI();

-		URI child = ((InternalEObject)proxy).eProxyURI().trimFragment();

-		if (parent.isPlatformResource() && child.isPlatformResource()) {

-			graph.addChildren(parent, Collections.singleton(child));

-		}

-	}

-}

+/*******************************************************************************
+ * Copyright (c) 2013 Obeo.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     Obeo - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.compare.ide.ui.internal.logical;
+
+import java.util.Collections;
+
+import org.eclipse.emf.common.util.URI;
+import org.eclipse.emf.compare.ide.internal.utils.SyncResourceSet;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.InternalEObject;
+import org.eclipse.emf.ecore.resource.Resource;
+
+/**
+ * This particular resource set will construct a dependency graph between the resources it loads, without
+ * actually keeping them in memory. The graph can be later queried in order to determine the subgraph
+ * corresponding to the dependencies of one given resource.
+ * 
+ * @author <a href="mailto:laurent.goubet@obeo.fr">Laurent Goubet</a>
+ */
+public class DependencyResourceSet extends SyncResourceSet {
+	/** Keeps track of the dependency tree discovered through this resource set. */
+	private final Graph<URI> graph;
+
+	/**
+	 * Constructs a resource set given the dependency graph it will populate.
+	 * 
+	 * @param graph
+	 *            The dependency graph we'll populate as we resolve new references.
+	 */
+	public DependencyResourceSet(Graph<URI> graph) {
+		this.graph = graph;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see org.eclipse.emf.compare.ide.internal.utils.SyncResourceSet#createResource(org.eclipse.emf.common.util.URI)
+	 */
+	@Override
+	public synchronized Resource createResource(URI uri) {
+		final Resource resource = super.createResource(uri);
+		graph.add(uri);
+		return resource;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see org.eclipse.emf.compare.ide.internal.utils.SyncResourceSet#createResource(org.eclipse.emf.common.util.URI,
+	 *      java.lang.String)
+	 */
+	@Override
+	public synchronized Resource createResource(URI uri, String contentType) {
+		final Resource resource = super.createResource(uri, contentType);
+		graph.add(uri);
+		return resource;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see org.eclipse.emf.compare.ide.internal.utils.SyncResourceSet#resolveCrossReference(org.eclipse.emf.ecore.resource.Resource,
+	 *      org.eclipse.emf.ecore.EObject)
+	 */
+	@Override
+	protected void resolveCrossReference(Resource resource, EObject proxy) {
+		super.resolveCrossReference(resource, proxy);
+		URI parent = resource.getURI();
+		URI child = ((InternalEObject)proxy).eProxyURI().trimFragment();
+		if (parent.isPlatformResource() && child.isPlatformResource()) {
+			graph.addChildren(parent, Collections.singleton(child));
+		}
+	}
+}
diff --git a/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/logical/ProjectModelResolver.java b/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/logical/ProjectModelResolver.java
index b3c2b80..185c44a 100644
--- a/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/logical/ProjectModelResolver.java
+++ b/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/logical/ProjectModelResolver.java
@@ -1,688 +1,688 @@
-/*******************************************************************************

- * Copyright (c) 2011, 2013 Obeo.

- * All rights reserved. This program and the accompanying materials

- * are made available under the terms of the Eclipse Public License v1.0

- * which accompanies this distribution, and is available at

- * http://www.eclipse.org/legal/epl-v10.html

- * 

- * Contributors:

- *     Obeo - initial API and implementation

- *******************************************************************************/

-package org.eclipse.emf.compare.ide.ui.internal.logical;

-

-import static com.google.common.collect.Sets.difference;

-import static com.google.common.collect.Sets.intersection;

-import static com.google.common.collect.Sets.newLinkedHashSet;

-import static org.eclipse.emf.compare.ide.ui.internal.util.PlatformElementUtil.adaptAs;

-import static org.eclipse.emf.compare.ide.utils.ResourceUtil.createURIFor;

-import static org.eclipse.emf.compare.ide.utils.ResourceUtil.hasContentType;

-

-import com.google.common.base.Throwables;

-import com.google.common.collect.ImmutableSet;

-import com.google.common.collect.Iterables;

-import com.google.common.collect.Sets;

-

-import java.util.Collections;

-import java.util.LinkedHashSet;

-import java.util.List;

-import java.util.Set;

-

-import org.eclipse.core.resources.IFile;

-import org.eclipse.core.resources.IProject;

-import org.eclipse.core.resources.IResource;

-import org.eclipse.core.resources.IResourceChangeEvent;

-import org.eclipse.core.resources.IResourceChangeListener;

-import org.eclipse.core.resources.IResourceDelta;

-import org.eclipse.core.resources.IResourceDeltaVisitor;

-import org.eclipse.core.resources.IResourceVisitor;

-import org.eclipse.core.resources.IStorage;

-import org.eclipse.core.resources.ResourcesPlugin;

-import org.eclipse.core.runtime.CoreException;

-import org.eclipse.core.runtime.IProgressMonitor;

-import org.eclipse.core.runtime.IStatus;

-import org.eclipse.core.runtime.Path;

-import org.eclipse.core.runtime.Status;

-import org.eclipse.core.runtime.content.IContentType;

-import org.eclipse.emf.common.util.URI;

-import org.eclipse.emf.compare.ide.ui.internal.EMFCompareIDEUIMessages;

-import org.eclipse.emf.compare.ide.ui.internal.EMFCompareIDEUIPlugin;

-import org.eclipse.emf.compare.ide.ui.logical.IModelResolver;

-import org.eclipse.emf.compare.ide.ui.logical.IStorageProvider;

-import org.eclipse.emf.compare.ide.ui.logical.IStorageProviderAccessor;

-import org.eclipse.emf.compare.ide.ui.logical.IStorageProviderAccessor.DiffSide;

-import org.eclipse.emf.compare.ide.ui.logical.SynchronizationModel;

-import org.eclipse.emf.compare.ide.utils.ResourceUtil;

-import org.eclipse.emf.compare.ide.utils.StorageTraversal;

-import org.eclipse.emf.compare.ide.utils.StorageURIConverter;

-

-/**

- * This implementation of an {@link IModelResolver} will look up in the whole project contained by the

- * "starting points" of the models to resolve in order to check for referencing parents. Once this is done,

- * we'll know the whole logical model for the "local" resource. The right and origin (if any) resources will

- * be provided with the same traversal of resources, expanded with a "top-down" approach : load all models of

- * the traversal from the remote side, then resolve their containment tree to check whether there are new

- * remote resources in the logical model.

- * 

- * @author <a href="mailto:laurent.goubet@obeo.fr">Laurent Goubet</a>

- */

-public class ProjectModelResolver extends LogicalModelResolver {

-	/** Content types of the files to consider as potential models. */

-	private static final String[] MODEL_CONTENT_TYPES = new String[] {

-			"org.eclipse.emf.compare.content.type", "org.eclipse.emf.ecore", //$NON-NLS-1$ //$NON-NLS-2$

-			"org.eclipse.emf.ecore.xmi", }; //$NON-NLS-1$

-

-	/**

-	 * Keeps track of the discovered dependency graph. Model resolvers are created from the extension point

-	 * registry, we can thus keep this graph around to avoid multiple crawlings of the same IProject. Team,

-	 * and the EMFResourceMapping, tend to be over-enthusiast with the resolution of model traversals. For

-	 * example, a single "right-click -> compare with -> commit..." with EGit ends up calling 8 distinct times

-	 * for the resource traversal of the selected resource.

-	 */

-	private Graph<URI> dependencyGraph;

-

-	/**

-	 * This resolver will keep a resource listener over the workspace in order to keep its dependencies graph

-	 * in sync.

-	 */

-	private ModelResourceListener resourceListener;

-

-	/**

-	 * {@inheritDoc}

-	 * 

-	 * @see org.eclipse.emf.compare.ide.ui.logical.AbstractModelResolver#initialize()

-	 */

-	@Override

-	public void initialize() {

-		super.initialize();

-		this.dependencyGraph = new Graph<URI>();

-		this.resourceListener = new ModelResourceListener();

-		ResourcesPlugin.getWorkspace().addResourceChangeListener(this.resourceListener);

-	}

-

-	/**

-	 * {@inheritDoc}

-	 * 

-	 * @see org.eclipse.emf.compare.ide.ui.logical.AbstractModelResolver#dispose()

-	 */

-	@Override

-	public void dispose() {

-		ResourcesPlugin.getWorkspace().removeResourceChangeListener(this.resourceListener);

-		this.resourceListener = null;

-		this.dependencyGraph = null;

-	}

-

-	/**

-	 * {@inheritDoc}

-	 * 

-	 * @see org.eclipse.emf.compare.ide.ui.internal.logical.LogicalModelResolver#resolveLocalModels(org.eclipse.core.resources.IResource,

-	 *      org.eclipse.core.resources.IResource, org.eclipse.core.resources.IResource,

-	 *      org.eclipse.core.runtime.IProgressMonitor)

-	 */

-	@Override

-	public SynchronizationModel resolveLocalModels(IResource left, IResource right, IResource origin,

-			IProgressMonitor monitor) {

-		if (!(left instanceof IFile) || !(right instanceof IFile)) {

-			return super.resolveLocalModels(left, right, origin, monitor);

-		}

-

-		updateChangedDependencies(monitor);

-		updateDependencies((IFile)left, monitor);

-		updateDependencies((IFile)right, monitor);

-		if (origin instanceof IFile) {

-			updateDependencies((IFile)origin, monitor);

-		}

-

-		final Set<IFile> startingPoints;

-		if (origin != null) {

-			startingPoints = ImmutableSet.of((IFile)left, (IFile)right, (IFile)origin);

-		} else {

-			startingPoints = ImmutableSet.of((IFile)left, (IFile)right);

-		}

-

-		final Set<IStorage> leftTraversal = resolveTraversal((IFile)left, difference(startingPoints,

-				Collections.singleton(left)), monitor);

-		final Set<IStorage> rightTraversal = resolveTraversal((IFile)right, difference(startingPoints,

-				Collections.singleton(right)), monitor);

-		final Set<IStorage> originTraversal;

-		if (origin instanceof IFile) {

-			originTraversal = resolveTraversal((IFile)origin, difference(startingPoints, Collections

-					.singleton(origin)), monitor);

-		} else {

-			originTraversal = Collections.emptySet();

-		}

-

-		/*

-		 * If one resource of the logical model was pointing to both (or "all three") of our starting

-		 * elements, we'll have way too many things in our traversal. We need to remove the intersection

-		 * before going any further.

-		 */

-		Set<IStorage> intersection = intersection(leftTraversal, rightTraversal);

-		if (!originTraversal.isEmpty()) {

-			intersection = intersection(intersection, originTraversal);

-		}

-		logCoherenceThreats(startingPoints, intersection);

-

-		final Set<IStorage> actualLeft = newLinkedHashSet(difference(leftTraversal, intersection));

-		final Set<IStorage> actualRight = newLinkedHashSet(difference(rightTraversal, intersection));

-		final Set<IStorage> actualOrigin = newLinkedHashSet(difference(originTraversal, intersection));

-		return new SynchronizationModel(new StorageTraversal(actualLeft), new StorageTraversal(actualRight),

-				new StorageTraversal(actualOrigin));

-	}

-

-	/**

-	 * When executing local comparisons, we resolve the full logical model of both (or "all three of") the

-	 * compared files.

-	 * <p>

-	 * If there is one resource in the scope that references all of these starting points, then we'll have

-	 * perfectly identical logical models for all comparison sides. Because of that, we need to constrain the

-	 * logical model of each starting point to only parts that are not accessible from other starting points.

-	 * This might cause coherence issues as merging could thus "break" references from other files to our

-	 * compared ones.

-	 * </p>

-	 * <p>

-	 * This method will be used to browse the files that are removed from the logical model, and log a warning

-	 * for the files that are removed even though they are "parents" of one of the starting points.

-	 * </p>

-	 * 

-	 * @param startingPoints

-	 *            Starting points of the comparison.

-	 * @param removedFromModel

-	 *            All files that have been removed from the comparison scope.

-	 */

-	private void logCoherenceThreats(Set<IFile> startingPoints, Set<IStorage> removedFromModel) {

-		final Set<URI> coherenceThreats = new LinkedHashSet<URI>();

-		for (IStorage start : startingPoints) {

-			final URI startURI = createURIFor(start);

-			for (IStorage removed : removedFromModel) {

-				final URI removedURI = createURIFor(removed);

-				if (dependencyGraph.hasChild(removedURI, startURI)) {

-					coherenceThreats.add(removedURI);

-				}

-			}

-		}

-

-		if (!coherenceThreats.isEmpty()) {

-			final String message = EMFCompareIDEUIMessages.getString("ModelResolver.coherenceWarning"); //$NON-NLS-1$

-			final String details = Iterables.toString(coherenceThreats);

-			EMFCompareIDEUIPlugin.getDefault().getLog().log(

-					new Status(IStatus.WARNING, EMFCompareIDEUIPlugin.PLUGIN_ID, message + '\n' + details));

-		}

-	}

-

-	/**

-	 * {@inheritDoc}

-	 * 

-	 * @see org.eclipse.emf.compare.ide.ui.internal.logical.LogicalModelResolver#resolveModels(org.eclipse.emf.compare.ide.ui.logical.IStorageProviderAccessor,

-	 *      org.eclipse.core.resources.IStorage, org.eclipse.core.resources.IStorage,

-	 *      org.eclipse.core.resources.IStorage, org.eclipse.core.runtime.IProgressMonitor)

-	 */

-	@Override

-	public SynchronizationModel resolveModels(IStorageProviderAccessor storageAccessor, IStorage left,

-			IStorage right, IStorage origin, IProgressMonitor monitor) {

-		final IFile leftFile = adaptAs(left, IFile.class);

-		if (leftFile == null) {

-			return super.resolveModels(storageAccessor, leftFile, right, origin, monitor);

-		}

-

-		updateChangedDependencies(monitor);

-		updateDependencies(leftFile, storageAccessor, monitor);

-

-		final Set<IStorage> leftTraversal = resolveLocalTraversal(storageAccessor, leftFile, monitor);

-		final Set<IStorage> rightTraversal = resolveTraversal(storageAccessor, DiffSide.REMOTE,

-				leftTraversal, monitor);

-		final Set<IStorage> originTraversal;

-		if (origin != null) {

-			originTraversal = resolveTraversal(storageAccessor, DiffSide.ORIGIN, leftTraversal, monitor);

-		} else {

-			originTraversal = Collections.emptySet();

-		}

-

-		return new SynchronizationModel(new StorageTraversal(leftTraversal), new StorageTraversal(

-				rightTraversal), new StorageTraversal(originTraversal));

-	}

-

-	/**

-	 * {@inheritDoc}

-	 * 

-	 * @see org.eclipse.emf.compare.ide.ui.internal.logical.LogicalModelResolver#resolveLocalModel(org.eclipse.core.resources.IResource,

-	 *      org.eclipse.core.runtime.IProgressMonitor)

-	 */

-	@Override

-	public StorageTraversal resolveLocalModel(IResource start, IProgressMonitor monitor) {

-		if (!(start instanceof IFile)) {

-			return super.resolveLocalModel(start, monitor);

-		}

-

-		updateChangedDependencies(monitor);

-		updateDependencies((IFile)start, monitor);

-

-		return new StorageTraversal(resolveTraversal((IFile)start, monitor));

-	}

-

-	/**

-	 * {@inheritDoc}

-	 * 

-	 * @see org.eclipse.emf.compare.ide.ui.internal.logical.LogicalModelResolver#canResolve(org.eclipse.core.resources.IStorage)

-	 */

-	@Override

-	public boolean canResolve(IStorage sourceStorage) {

-		if (sourceStorage instanceof IFile) {

-			IFile file = (IFile)sourceStorage;

-			return file.getProject().isAccessible() && ((IFile)sourceStorage).exists();

-		}

-		return false;

-	}

-

-	/**

-	 * Updates the dependency graph for the given file.

-	 * 

-	 * @param file

-	 *            File which dependencies we are to update.

-	 * @param monitor

-	 *            Monitor to report progress on.

-	 */

-	private void updateDependencies(IFile file, IProgressMonitor monitor) {

-		final URI startURI = createURIFor(file);

-		if (!dependencyGraph.contains(startURI)) {

-			final IProject project = file.getProject();

-			final ModelResourceVisitor modelVisitor = new ModelResourceVisitor(dependencyGraph, monitor);

-			try {

-				project.accept(modelVisitor);

-			} catch (CoreException e) {

-				Throwables.propagate(e);

-			}

-		}

-	}

-

-	/**

-	 * Updates the dependency graph for the given file.

-	 * 

-	 * @param file

-	 *            File which dependencies we are to update.

-	 * @param storageAccessor

-	 *            The accessor that can be used to retrieve synchronization information between our resources.

-	 * @param monitor

-	 *            Monitor to report progress on.

-	 */

-	private void updateDependencies(IFile file, IStorageProviderAccessor storageAccessor,

-			IProgressMonitor monitor) {

-		final URI leftURI = createURIFor(file);

-		if (!dependencyGraph.contains(leftURI)) {

-			final IProject project = file.getProject();

-			final ModelResourceVisitor modelVisitor = new ModelResourceVisitor(storageAccessor,

-					DiffSide.SOURCE, dependencyGraph, monitor);

-			try {

-				project.accept(modelVisitor);

-			} catch (CoreException e) {

-				// TODO log

-			}

-		}

-	}

-

-	/**

-	 * Checks all dependencies that have changed since we last checked (as returned by the

-	 * {@link #resourceListener}).

-	 * 

-	 * @param monitor

-	 *            Monitor to report progress on.

-	 */

-	private void updateChangedDependencies(IProgressMonitor monitor) {

-		final Set<URI> removedURIs = resourceListener.popRemovedURIs();

-		final Set<URI> changedURIs = Sets.difference(resourceListener.popChangedURIs(), removedURIs);

-

-		dependencyGraph.removeAll(removedURIs);

-		dependencyGraph.removeAll(changedURIs);

-

-		for (URI changed : changedURIs) {

-			if (!dependencyGraph.contains(changed)) {

-				final IFile file = getFileAt(changed);

-				updateDependencies(file, monitor);

-			}

-		}

-	}

-

-	/**

-	 * Checks whether the given file has one of the content types described in {@link #MODEL_CONTENT_TYPES}.

-	 * 

-	 * @param file

-	 *            The file which contents are to be checked.

-	 * @return <code>true</code> if this file has one of the "model" content types.

-	 */

-	protected static final boolean hasModelType(IFile file) {

-		boolean isModel = false;

-		final IContentType[] contentTypes = ResourceUtil.getContentTypes(file);

-		for (int i = 0; i < MODEL_CONTENT_TYPES.length && !isModel; i++) {

-			isModel = hasContentType(MODEL_CONTENT_TYPES[i], contentTypes);

-		}

-		return isModel;

-	}

-

-	/**

-	 * This will be used to resolve the traversal of a file's logical model, according to

-	 * {@link #dependencyGraph}.

-	 * 

-	 * @param resource

-	 *            The resource for which we need the full logical model.

-	 * @param monitor

-	 *            Monitor on which to report progress to the user.

-	 * @return The set of all storages that compose the logical model of <code>resource</code>.

-	 */

-	private Set<IStorage> resolveTraversal(IFile resource, IProgressMonitor monitor) {

-		final Set<IStorage> traversal = new LinkedHashSet<IStorage>();

-		final URI startURI = createURIFor(resource);

-

-		final Iterable<URI> uris = dependencyGraph.getSubgraphOf(startURI);

-		for (URI uri : uris) {

-			traversal.add(getFileAt(uri));

-		}

-		return traversal;

-	}

-

-	/**

-	 * This will be used in case of remote comparisons to resolve the local side's traversal (if there is a

-	 * local side).

-	 * 

-	 * @param storageAccessor

-	 *            The accessor that can be used to retrieve synchronization information between our resources.

-	 * @param resource

-	 *            The resource for which we need the full logical model.

-	 * @param monitor

-	 *            Monitor on which to report progress to the user.

-	 * @return The set of all storages that compose the logical model of <code>resource</code>.

-	 */

-	private Set<IStorage> resolveLocalTraversal(IStorageProviderAccessor storageAccessor, IFile resource,

-			IProgressMonitor monitor) {

-		final Set<IStorage> traversal = new LinkedHashSet<IStorage>();

-		final URI startURI = createURIFor(resource);

-

-		final Iterable<URI> uris = dependencyGraph.getSubgraphOf(startURI);

-		for (URI uri : uris) {

-			final IFile file = getFileAt(uri);

-			try {

-				if (!storageAccessor.isInSync(file)) {

-					traversal.add(file);

-				}

-			} catch (CoreException e) {

-				// swallow

-			}

-		}

-		return traversal;

-	}

-

-	/**

-	 * This will be used to resolve the traversal of a file's logical model, according to

-	 * {@link #dependencyGraph}.

-	 * 

-	 * @param resource

-	 *            The resource for which we need the full logical model.

-	 * @param bounds

-	 *            The resources constituting starting points of "other" logical models. This will be used to

-	 *            constrain the dependency sub-graph.

-	 * @param monitor

-	 *            Monitor on which to report progress to the user.

-	 * @return The set of all storages that compose the logical model of <code>resource</code>.

-	 */

-	private Set<IStorage> resolveTraversal(IFile resource, Set<IFile> bounds, IProgressMonitor monitor) {

-		final Set<IStorage> traversal = new LinkedHashSet<IStorage>();

-		final URI startURI = createURIFor(resource);

-

-		final Set<URI> uriBounds = new LinkedHashSet<URI>(bounds.size());

-		for (IFile bound : bounds) {

-			uriBounds.add(createURIFor(bound));

-		}

-

-		final Iterable<URI> uris = dependencyGraph.getBoundedSubgraphOf(startURI, uriBounds);

-		for (URI uri : uris) {

-			traversal.add(getFileAt(uri));

-		}

-		return traversal;

-	}

-

-	/**

-	 * Returns the IFile located at the given URI.

-	 * 

-	 * @param uri

-	 *            URI we need the file for.

-	 * @return The IFile located at the given URI.

-	 */

-	private IFile getFileAt(URI uri) {

-		final StringBuilder path = new StringBuilder();

-		List<String> segments = uri.segmentsList();

-		if (uri.isPlatformResource()) {

-			segments = segments.subList(1, segments.size());

-		}

-		for (String segment : segments) {

-			path.append(URI.decode(segment)).append('/');

-		}

-		return ResourcesPlugin.getWorkspace().getRoot().getFile(new Path(path.toString()));

-	}

-

-	/**

-	 * This will be used to resolve the logical model of a remote resource variant. Since we have no direct

-	 * access to the resources themselves, we cannot simply browse one of their container for the traversal.

-	 * Instead of that, we'll use the local traversal as a "reference", load remote variants of all of these

-	 * local files, and re-resolve them in a "top-down" approach in case there are new resources on the remote

-	 * side.

-	 * 

-	 * @param storageAccessor

-	 *            The accessor that can be used to retrieve synchronization information between our resources.

-	 * @param side

-	 *            Side of the logical model to resolve. Used in conjunction with the storage accessor to

-	 *            retrieve appropriate contents for the remote variants.

-	 * @param localTraversal

-	 *            Traversal resolved for the logical model of the local file.

-	 * @param monitor

-	 *            Monitor on which to report progress to the user.

-	 * @return The set of all remote storages composing the same logical model as the given local traversal.

-	 */

-	private Set<IStorage> resolveTraversal(IStorageProviderAccessor storageAccessor, DiffSide side,

-			Set<IStorage> localTraversal, IProgressMonitor monitor) {

-		final DependencyResourceSet resourceSet = new DependencyResourceSet(dependencyGraph);

-		final StorageURIConverter converter = new RevisionedURIConverter(resourceSet.getURIConverter(),

-				storageAccessor, side);

-		resourceSet.setURIConverter(converter);

-

-		final Set<IStorage> storages = Sets.newLinkedHashSet();

-		for (IStorage local : localTraversal) {

-			final IFile localFile = adaptAs(local, IFile.class);

-

-			try {

-				final IStorageProvider remoteStorageProvider = storageAccessor.getStorageProvider(localFile,

-						side);

-				if (remoteStorageProvider != null) {

-					final IStorage start = remoteStorageProvider.getStorage(monitor);

-

-					if (resourceSet.resolveAll(start, monitor)) {

-						if (!contains(storages, start)) {

-							storages.add(start);

-						}

-						for (IStorage loaded : converter.getLoadedRevisions()) {

-							if (!contains(storages, loaded)) {

-								storages.add(loaded);

-							}

-						}

-					} else {

-						// failed to load a remote version of this resource

-					}

-				} else {

-					// file only exist locally

-				}

-			} catch (CoreException e) {

-				// failed to load a remote version of this resource

-			}

-		}

-		return storages;

-	}

-

-	/**

-	 * This implementation of a resource visitor will allow us to browse all models in a given hierarchy.

-	 * 

-	 * @author <a href="mailto:laurent.goubet@obeo.fr">laurent Goubet</a>

-	 */

-	private static class ModelResourceVisitor implements IResourceVisitor {

-		/** Resource Set in which we should load the temporary resources. */

-		private final DependencyResourceSet resourceSet;

-

-		/** Monitor to report progress on. */

-		// FIXME logarithmic progress

-		private final IProgressMonitor monitor;

-

-		/**

-		 * Instantiates a resource visitor.

-		 * 

-		 * @param graph

-		 *            The dependency graph that is to be populated/completed.

-		 * @param monitor

-		 *            The monitor to report progress on.

-		 */

-		public ModelResourceVisitor(Graph<URI> graph, IProgressMonitor monitor) {

-			this.resourceSet = new DependencyResourceSet(graph);

-			this.monitor = monitor;

-			final StorageURIConverter converter = new StorageURIConverter(resourceSet.getURIConverter());

-			this.resourceSet.setURIConverter(converter);

-		}

-

-		/**

-		 * Instantiates a resource visitor given the storage accessor to use for I/O operations.

-		 * 

-		 * @param storageAccessor

-		 *            The accessor to use for all I/O operations to fetch resource content.

-		 * @param side

-		 *            Side of the resources. Used in conjunction with the storage accessor to fetch proper

-		 *            content.

-		 * @param graph

-		 *            The dependency graph that is to be populated/completed.

-		 * @param monitor

-		 *            The monitor to report progress on.

-		 */

-		public ModelResourceVisitor(IStorageProviderAccessor storageAccessor, DiffSide side,

-				Graph<URI> graph, IProgressMonitor monitor) {

-			this.resourceSet = new DependencyResourceSet(graph);

-			this.monitor = monitor;

-			final StorageURIConverter converter = new RevisionedURIConverter(resourceSet.getURIConverter(),

-					storageAccessor, side);

-			this.resourceSet.setURIConverter(converter);

-		}

-

-		/**

-		 * {@inheritDoc}

-		 * 

-		 * @see org.eclipse.core.resources.IResourceVisitor#visit(org.eclipse.core.resources.IResource)

-		 */

-		public boolean visit(IResource resource) throws CoreException {

-			if (resource instanceof IFile) {

-				IFile file = (IFile)resource;

-				if (hasModelType(file)) {

-					resourceSet.resolveAll(file, monitor);

-					return true;

-				}

-				return false;

-			}

-			return true;

-		}

-	}

-

-	/**

-	 * This will listen to workspace changes and react to all changes on "model" resources as determined by

-	 * {@link ProjectModelResolver#MODEL_CONTENT_TYPES}.

-	 * 

-	 * @author <a href="mailto:laurent.goubet@obeo.fr">laurent Goubet</a>

-	 */

-	private static class ModelResourceListener implements IResourceChangeListener {

-		/** Keeps track of the URIs that need to be reparsed when next we need the dependencies graph . */

-		protected Set<URI> changedURIs;

-

-		/** Tracks the files that have been removed. */

-		protected Set<URI> removedURIs;

-

-		/** Initializes this listener. */

-		public ModelResourceListener() {

-			this.changedURIs = new LinkedHashSet<URI>();

-			this.removedURIs = new LinkedHashSet<URI>();

-		}

-

-		/**

-		 * {@inheritDoc}

-		 * 

-		 * @see org.eclipse.core.resources.IResourceChangeListener#resourceChanged(org.eclipse.core.resources.IResourceChangeEvent)

-		 */

-		public void resourceChanged(IResourceChangeEvent event) {

-			final IResourceDelta delta = event.getDelta();

-			if (delta == null) {

-				return;

-			}

-

-			try {

-				delta.accept(new ModelResourceDeltaVisitor());

-			} catch (CoreException e) {

-				EMFCompareIDEUIPlugin.getDefault().log(e);

-			}

-		}

-

-		/**

-		 * Retrieves the set of all changed URIs since we last updated the dependencies graph, and clears it

-		 * for subsequent calls.

-		 * 

-		 * @return The set of all changed URIs since we last updated the dependencies graph.

-		 */

-		public Set<URI> popChangedURIs() {

-			final Set<URI> changed;

-			synchronized(changedURIs) {

-				changed = ImmutableSet.copyOf(changedURIs);

-				changedURIs.clear();

-			}

-			return changed;

-		}

-

-		/**

-		 * Retrieves the set of all removed URIs since we last updated the dependencies graph, and clears it

-		 * for subsequent calls.

-		 * 

-		 * @return The set of all removed URIs since we last updated the dependencies graph.

-		 */

-		public Set<URI> popRemovedURIs() {

-			final Set<URI> removed;

-			synchronized(removedURIs) {

-				removed = ImmutableSet.copyOf(removedURIs);

-				removedURIs.clear();

-			}

-			return removed;

-		}

-

-		/**

-		 * Visits a resource delta to collect the changed and removed files' URIs.

-		 * 

-		 * @author <a href="mailto:laurent.goubet@obeo.fr">laurent Goubet</a>

-		 */

-		private class ModelResourceDeltaVisitor implements IResourceDeltaVisitor {

-			/**

-			 * {@inheritDoc}

-			 * 

-			 * @see org.eclipse.core.resources.IResourceDeltaVisitor#visit(org.eclipse.core.resources.IResourceDelta)

-			 */

-			public boolean visit(IResourceDelta delta) throws CoreException {

-				if (delta.getFlags() == IResourceDelta.MARKERS

-						|| delta.getResource().getType() != IResource.FILE) {

-					return true;

-				}

-

-				final IFile file = (IFile)delta.getResource();

-				final URI fileURI = createURIFor(file);

-				// We can't check the content type of a removed resource

-				if (delta.getKind() == IResourceDelta.REMOVED) {

-					synchronized(removedURIs) {

-						removedURIs.add(fileURI);

-					}

-				} else if (hasModelType(file)) {

-					if ((delta.getKind() & (IResourceDelta.CHANGED | IResourceDelta.ADDED)) != 0) {

-						synchronized(changedURIs) {

-							changedURIs.add(fileURI);

-						}

-					}

-				}

-

-				return true;

-			}

-		}

-	}

-}

+/*******************************************************************************
+ * Copyright (c) 2011, 2013 Obeo.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     Obeo - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.compare.ide.ui.internal.logical;
+
+import static com.google.common.collect.Sets.difference;
+import static com.google.common.collect.Sets.intersection;
+import static com.google.common.collect.Sets.newLinkedHashSet;
+import static org.eclipse.emf.compare.ide.ui.internal.util.PlatformElementUtil.adaptAs;
+import static org.eclipse.emf.compare.ide.utils.ResourceUtil.createURIFor;
+import static org.eclipse.emf.compare.ide.utils.ResourceUtil.hasContentType;
+
+import com.google.common.base.Throwables;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Sets;
+
+import java.util.Collections;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IResourceChangeEvent;
+import org.eclipse.core.resources.IResourceChangeListener;
+import org.eclipse.core.resources.IResourceDelta;
+import org.eclipse.core.resources.IResourceDeltaVisitor;
+import org.eclipse.core.resources.IResourceVisitor;
+import org.eclipse.core.resources.IStorage;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.content.IContentType;
+import org.eclipse.emf.common.util.URI;
+import org.eclipse.emf.compare.ide.ui.internal.EMFCompareIDEUIMessages;
+import org.eclipse.emf.compare.ide.ui.internal.EMFCompareIDEUIPlugin;
+import org.eclipse.emf.compare.ide.ui.logical.IModelResolver;
+import org.eclipse.emf.compare.ide.ui.logical.IStorageProvider;
+import org.eclipse.emf.compare.ide.ui.logical.IStorageProviderAccessor;
+import org.eclipse.emf.compare.ide.ui.logical.IStorageProviderAccessor.DiffSide;
+import org.eclipse.emf.compare.ide.ui.logical.SynchronizationModel;
+import org.eclipse.emf.compare.ide.utils.ResourceUtil;
+import org.eclipse.emf.compare.ide.utils.StorageTraversal;
+import org.eclipse.emf.compare.ide.utils.StorageURIConverter;
+
+/**
+ * This implementation of an {@link IModelResolver} will look up in the whole project contained by the
+ * "starting points" of the models to resolve in order to check for referencing parents. Once this is done,
+ * we'll know the whole logical model for the "local" resource. The right and origin (if any) resources will
+ * be provided with the same traversal of resources, expanded with a "top-down" approach : load all models of
+ * the traversal from the remote side, then resolve their containment tree to check whether there are new
+ * remote resources in the logical model.
+ * 
+ * @author <a href="mailto:laurent.goubet@obeo.fr">Laurent Goubet</a>
+ */
+public class ProjectModelResolver extends LogicalModelResolver {
+	/** Content types of the files to consider as potential models. */
+	private static final String[] MODEL_CONTENT_TYPES = new String[] {
+			"org.eclipse.emf.compare.content.type", "org.eclipse.emf.ecore", //$NON-NLS-1$ //$NON-NLS-2$
+			"org.eclipse.emf.ecore.xmi", }; //$NON-NLS-1$
+
+	/**
+	 * Keeps track of the discovered dependency graph. Model resolvers are created from the extension point
+	 * registry, we can thus keep this graph around to avoid multiple crawlings of the same IProject. Team,
+	 * and the EMFResourceMapping, tend to be over-enthusiast with the resolution of model traversals. For
+	 * example, a single "right-click -> compare with -> commit..." with EGit ends up calling 8 distinct times
+	 * for the resource traversal of the selected resource.
+	 */
+	private Graph<URI> dependencyGraph;
+
+	/**
+	 * This resolver will keep a resource listener over the workspace in order to keep its dependencies graph
+	 * in sync.
+	 */
+	private ModelResourceListener resourceListener;
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see org.eclipse.emf.compare.ide.ui.logical.AbstractModelResolver#initialize()
+	 */
+	@Override
+	public void initialize() {
+		super.initialize();
+		this.dependencyGraph = new Graph<URI>();
+		this.resourceListener = new ModelResourceListener();
+		ResourcesPlugin.getWorkspace().addResourceChangeListener(this.resourceListener);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see org.eclipse.emf.compare.ide.ui.logical.AbstractModelResolver#dispose()
+	 */
+	@Override
+	public void dispose() {
+		ResourcesPlugin.getWorkspace().removeResourceChangeListener(this.resourceListener);
+		this.resourceListener = null;
+		this.dependencyGraph = null;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see org.eclipse.emf.compare.ide.ui.internal.logical.LogicalModelResolver#resolveLocalModels(org.eclipse.core.resources.IResource,
+	 *      org.eclipse.core.resources.IResource, org.eclipse.core.resources.IResource,
+	 *      org.eclipse.core.runtime.IProgressMonitor)
+	 */
+	@Override
+	public SynchronizationModel resolveLocalModels(IResource left, IResource right, IResource origin,
+			IProgressMonitor monitor) {
+		if (!(left instanceof IFile) || !(right instanceof IFile)) {
+			return super.resolveLocalModels(left, right, origin, monitor);
+		}
+
+		updateChangedDependencies(monitor);
+		updateDependencies((IFile)left, monitor);
+		updateDependencies((IFile)right, monitor);
+		if (origin instanceof IFile) {
+			updateDependencies((IFile)origin, monitor);
+		}
+
+		final Set<IFile> startingPoints;
+		if (origin != null) {
+			startingPoints = ImmutableSet.of((IFile)left, (IFile)right, (IFile)origin);
+		} else {
+			startingPoints = ImmutableSet.of((IFile)left, (IFile)right);
+		}
+
+		final Set<IStorage> leftTraversal = resolveTraversal((IFile)left, difference(startingPoints,
+				Collections.singleton(left)), monitor);
+		final Set<IStorage> rightTraversal = resolveTraversal((IFile)right, difference(startingPoints,
+				Collections.singleton(right)), monitor);
+		final Set<IStorage> originTraversal;
+		if (origin instanceof IFile) {
+			originTraversal = resolveTraversal((IFile)origin, difference(startingPoints, Collections
+					.singleton(origin)), monitor);
+		} else {
+			originTraversal = Collections.emptySet();
+		}
+
+		/*
+		 * If one resource of the logical model was pointing to both (or "all three") of our starting
+		 * elements, we'll have way too many things in our traversal. We need to remove the intersection
+		 * before going any further.
+		 */
+		Set<IStorage> intersection = intersection(leftTraversal, rightTraversal);
+		if (!originTraversal.isEmpty()) {
+			intersection = intersection(intersection, originTraversal);
+		}
+		logCoherenceThreats(startingPoints, intersection);
+
+		final Set<IStorage> actualLeft = newLinkedHashSet(difference(leftTraversal, intersection));
+		final Set<IStorage> actualRight = newLinkedHashSet(difference(rightTraversal, intersection));
+		final Set<IStorage> actualOrigin = newLinkedHashSet(difference(originTraversal, intersection));
+		return new SynchronizationModel(new StorageTraversal(actualLeft), new StorageTraversal(actualRight),
+				new StorageTraversal(actualOrigin));
+	}
+
+	/**
+	 * When executing local comparisons, we resolve the full logical model of both (or "all three of") the
+	 * compared files.
+	 * <p>
+	 * If there is one resource in the scope that references all of these starting points, then we'll have
+	 * perfectly identical logical models for all comparison sides. Because of that, we need to constrain the
+	 * logical model of each starting point to only parts that are not accessible from other starting points.
+	 * This might cause coherence issues as merging could thus "break" references from other files to our
+	 * compared ones.
+	 * </p>
+	 * <p>
+	 * This method will be used to browse the files that are removed from the logical model, and log a warning
+	 * for the files that are removed even though they are "parents" of one of the starting points.
+	 * </p>
+	 * 
+	 * @param startingPoints
+	 *            Starting points of the comparison.
+	 * @param removedFromModel
+	 *            All files that have been removed from the comparison scope.
+	 */
+	private void logCoherenceThreats(Set<IFile> startingPoints, Set<IStorage> removedFromModel) {
+		final Set<URI> coherenceThreats = new LinkedHashSet<URI>();
+		for (IStorage start : startingPoints) {
+			final URI startURI = createURIFor(start);
+			for (IStorage removed : removedFromModel) {
+				final URI removedURI = createURIFor(removed);
+				if (dependencyGraph.hasChild(removedURI, startURI)) {
+					coherenceThreats.add(removedURI);
+				}
+			}
+		}
+
+		if (!coherenceThreats.isEmpty()) {
+			final String message = EMFCompareIDEUIMessages.getString("ModelResolver.coherenceWarning"); //$NON-NLS-1$
+			final String details = Iterables.toString(coherenceThreats);
+			EMFCompareIDEUIPlugin.getDefault().getLog().log(
+					new Status(IStatus.WARNING, EMFCompareIDEUIPlugin.PLUGIN_ID, message + '\n' + details));
+		}
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see org.eclipse.emf.compare.ide.ui.internal.logical.LogicalModelResolver#resolveModels(org.eclipse.emf.compare.ide.ui.logical.IStorageProviderAccessor,
+	 *      org.eclipse.core.resources.IStorage, org.eclipse.core.resources.IStorage,
+	 *      org.eclipse.core.resources.IStorage, org.eclipse.core.runtime.IProgressMonitor)
+	 */
+	@Override
+	public SynchronizationModel resolveModels(IStorageProviderAccessor storageAccessor, IStorage left,
+			IStorage right, IStorage origin, IProgressMonitor monitor) {
+		final IFile leftFile = adaptAs(left, IFile.class);
+		if (leftFile == null) {
+			return super.resolveModels(storageAccessor, leftFile, right, origin, monitor);
+		}
+
+		updateChangedDependencies(monitor);
+		updateDependencies(leftFile, storageAccessor, monitor);
+
+		final Set<IStorage> leftTraversal = resolveLocalTraversal(storageAccessor, leftFile, monitor);
+		final Set<IStorage> rightTraversal = resolveTraversal(storageAccessor, DiffSide.REMOTE,
+				leftTraversal, monitor);
+		final Set<IStorage> originTraversal;
+		if (origin != null) {
+			originTraversal = resolveTraversal(storageAccessor, DiffSide.ORIGIN, leftTraversal, monitor);
+		} else {
+			originTraversal = Collections.emptySet();
+		}
+
+		return new SynchronizationModel(new StorageTraversal(leftTraversal), new StorageTraversal(
+				rightTraversal), new StorageTraversal(originTraversal));
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see org.eclipse.emf.compare.ide.ui.internal.logical.LogicalModelResolver#resolveLocalModel(org.eclipse.core.resources.IResource,
+	 *      org.eclipse.core.runtime.IProgressMonitor)
+	 */
+	@Override
+	public StorageTraversal resolveLocalModel(IResource start, IProgressMonitor monitor) {
+		if (!(start instanceof IFile)) {
+			return super.resolveLocalModel(start, monitor);
+		}
+
+		updateChangedDependencies(monitor);
+		updateDependencies((IFile)start, monitor);
+
+		return new StorageTraversal(resolveTraversal((IFile)start, monitor));
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see org.eclipse.emf.compare.ide.ui.internal.logical.LogicalModelResolver#canResolve(org.eclipse.core.resources.IStorage)
+	 */
+	@Override
+	public boolean canResolve(IStorage sourceStorage) {
+		if (sourceStorage instanceof IFile) {
+			IFile file = (IFile)sourceStorage;
+			return file.getProject().isAccessible() && ((IFile)sourceStorage).exists();
+		}
+		return false;
+	}
+
+	/**
+	 * Updates the dependency graph for the given file.
+	 * 
+	 * @param file
+	 *            File which dependencies we are to update.
+	 * @param monitor
+	 *            Monitor to report progress on.
+	 */
+	private void updateDependencies(IFile file, IProgressMonitor monitor) {
+		final URI startURI = createURIFor(file);
+		if (!dependencyGraph.contains(startURI)) {
+			final IProject project = file.getProject();
+			final ModelResourceVisitor modelVisitor = new ModelResourceVisitor(dependencyGraph, monitor);
+			try {
+				project.accept(modelVisitor);
+			} catch (CoreException e) {
+				Throwables.propagate(e);
+			}
+		}
+	}
+
+	/**
+	 * Updates the dependency graph for the given file.
+	 * 
+	 * @param file
+	 *            File which dependencies we are to update.
+	 * @param storageAccessor
+	 *            The accessor that can be used to retrieve synchronization information between our resources.
+	 * @param monitor
+	 *            Monitor to report progress on.
+	 */
+	private void updateDependencies(IFile file, IStorageProviderAccessor storageAccessor,
+			IProgressMonitor monitor) {
+		final URI leftURI = createURIFor(file);
+		if (!dependencyGraph.contains(leftURI)) {
+			final IProject project = file.getProject();
+			final ModelResourceVisitor modelVisitor = new ModelResourceVisitor(storageAccessor,
+					DiffSide.SOURCE, dependencyGraph, monitor);
+			try {
+				project.accept(modelVisitor);
+			} catch (CoreException e) {
+				// TODO log
+			}
+		}
+	}
+
+	/**
+	 * Checks all dependencies that have changed since we last checked (as returned by the
+	 * {@link #resourceListener}).
+	 * 
+	 * @param monitor
+	 *            Monitor to report progress on.
+	 */
+	private void updateChangedDependencies(IProgressMonitor monitor) {
+		final Set<URI> removedURIs = resourceListener.popRemovedURIs();
+		final Set<URI> changedURIs = Sets.difference(resourceListener.popChangedURIs(), removedURIs);
+
+		dependencyGraph.removeAll(removedURIs);
+		dependencyGraph.removeAll(changedURIs);
+
+		for (URI changed : changedURIs) {
+			if (!dependencyGraph.contains(changed)) {
+				final IFile file = getFileAt(changed);
+				updateDependencies(file, monitor);
+			}
+		}
+	}
+
+	/**
+	 * Checks whether the given file has one of the content types described in {@link #MODEL_CONTENT_TYPES}.
+	 * 
+	 * @param file
+	 *            The file which contents are to be checked.
+	 * @return <code>true</code> if this file has one of the "model" content types.
+	 */
+	protected static final boolean hasModelType(IFile file) {
+		boolean isModel = false;
+		final IContentType[] contentTypes = ResourceUtil.getContentTypes(file);
+		for (int i = 0; i < MODEL_CONTENT_TYPES.length && !isModel; i++) {
+			isModel = hasContentType(MODEL_CONTENT_TYPES[i], contentTypes);
+		}
+		return isModel;
+	}
+
+	/**
+	 * This will be used to resolve the traversal of a file's logical model, according to
+	 * {@link #dependencyGraph}.
+	 * 
+	 * @param resource
+	 *            The resource for which we need the full logical model.
+	 * @param monitor
+	 *            Monitor on which to report progress to the user.
+	 * @return The set of all storages that compose the logical model of <code>resource</code>.
+	 */
+	private Set<IStorage> resolveTraversal(IFile resource, IProgressMonitor monitor) {
+		final Set<IStorage> traversal = new LinkedHashSet<IStorage>();
+		final URI startURI = createURIFor(resource);
+
+		final Iterable<URI> uris = dependencyGraph.getSubgraphOf(startURI);
+		for (URI uri : uris) {
+			traversal.add(getFileAt(uri));
+		}
+		return traversal;
+	}
+
+	/**
+	 * This will be used in case of remote comparisons to resolve the local side's traversal (if there is a
+	 * local side).
+	 * 
+	 * @param storageAccessor
+	 *            The accessor that can be used to retrieve synchronization information between our resources.
+	 * @param resource
+	 *            The resource for which we need the full logical model.
+	 * @param monitor
+	 *            Monitor on which to report progress to the user.
+	 * @return The set of all storages that compose the logical model of <code>resource</code>.
+	 */
+	private Set<IStorage> resolveLocalTraversal(IStorageProviderAccessor storageAccessor, IFile resource,
+			IProgressMonitor monitor) {
+		final Set<IStorage> traversal = new LinkedHashSet<IStorage>();
+		final URI startURI = createURIFor(resource);
+
+		final Iterable<URI> uris = dependencyGraph.getSubgraphOf(startURI);
+		for (URI uri : uris) {
+			final IFile file = getFileAt(uri);
+			try {
+				if (!storageAccessor.isInSync(file)) {
+					traversal.add(file);
+				}
+			} catch (CoreException e) {
+				// swallow
+			}
+		}
+		return traversal;
+	}
+
+	/**
+	 * This will be used to resolve the traversal of a file's logical model, according to
+	 * {@link #dependencyGraph}.
+	 * 
+	 * @param resource
+	 *            The resource for which we need the full logical model.
+	 * @param bounds
+	 *            The resources constituting starting points of "other" logical models. This will be used to
+	 *            constrain the dependency sub-graph.
+	 * @param monitor
+	 *            Monitor on which to report progress to the user.
+	 * @return The set of all storages that compose the logical model of <code>resource</code>.
+	 */
+	private Set<IStorage> resolveTraversal(IFile resource, Set<IFile> bounds, IProgressMonitor monitor) {
+		final Set<IStorage> traversal = new LinkedHashSet<IStorage>();
+		final URI startURI = createURIFor(resource);
+
+		final Set<URI> uriBounds = new LinkedHashSet<URI>(bounds.size());
+		for (IFile bound : bounds) {
+			uriBounds.add(createURIFor(bound));
+		}
+
+		final Iterable<URI> uris = dependencyGraph.getBoundedSubgraphOf(startURI, uriBounds);
+		for (URI uri : uris) {
+			traversal.add(getFileAt(uri));
+		}
+		return traversal;
+	}
+
+	/**
+	 * Returns the IFile located at the given URI.
+	 * 
+	 * @param uri
+	 *            URI we need the file for.
+	 * @return The IFile located at the given URI.
+	 */
+	private IFile getFileAt(URI uri) {
+		final StringBuilder path = new StringBuilder();
+		List<String> segments = uri.segmentsList();
+		if (uri.isPlatformResource()) {
+			segments = segments.subList(1, segments.size());
+		}
+		for (String segment : segments) {
+			path.append(URI.decode(segment)).append('/');
+		}
+		return ResourcesPlugin.getWorkspace().getRoot().getFile(new Path(path.toString()));
+	}
+
+	/**
+	 * This will be used to resolve the logical model of a remote resource variant. Since we have no direct
+	 * access to the resources themselves, we cannot simply browse one of their container for the traversal.
+	 * Instead of that, we'll use the local traversal as a "reference", load remote variants of all of these
+	 * local files, and re-resolve them in a "top-down" approach in case there are new resources on the remote
+	 * side.
+	 * 
+	 * @param storageAccessor
+	 *            The accessor that can be used to retrieve synchronization information between our resources.
+	 * @param side
+	 *            Side of the logical model to resolve. Used in conjunction with the storage accessor to
+	 *            retrieve appropriate contents for the remote variants.
+	 * @param localTraversal
+	 *            Traversal resolved for the logical model of the local file.
+	 * @param monitor
+	 *            Monitor on which to report progress to the user.
+	 * @return The set of all remote storages composing the same logical model as the given local traversal.
+	 */
+	private Set<IStorage> resolveTraversal(IStorageProviderAccessor storageAccessor, DiffSide side,
+			Set<IStorage> localTraversal, IProgressMonitor monitor) {
+		final DependencyResourceSet resourceSet = new DependencyResourceSet(dependencyGraph);
+		final StorageURIConverter converter = new RevisionedURIConverter(resourceSet.getURIConverter(),
+				storageAccessor, side);
+		resourceSet.setURIConverter(converter);
+
+		final Set<IStorage> storages = Sets.newLinkedHashSet();
+		for (IStorage local : localTraversal) {
+			final IFile localFile = adaptAs(local, IFile.class);
+
+			try {
+				final IStorageProvider remoteStorageProvider = storageAccessor.getStorageProvider(localFile,
+						side);
+				if (remoteStorageProvider != null) {
+					final IStorage start = remoteStorageProvider.getStorage(monitor);
+
+					if (resourceSet.resolveAll(start, monitor)) {
+						if (!contains(storages, start)) {
+							storages.add(start);
+						}
+						for (IStorage loaded : converter.getLoadedRevisions()) {
+							if (!contains(storages, loaded)) {
+								storages.add(loaded);
+							}
+						}
+					} else {
+						// failed to load a remote version of this resource
+					}
+				} else {
+					// file only exist locally
+				}
+			} catch (CoreException e) {
+				// failed to load a remote version of this resource
+			}
+		}
+		return storages;
+	}
+
+	/**
+	 * This implementation of a resource visitor will allow us to browse all models in a given hierarchy.
+	 * 
+	 * @author <a href="mailto:laurent.goubet@obeo.fr">laurent Goubet</a>
+	 */
+	private static class ModelResourceVisitor implements IResourceVisitor {
+		/** Resource Set in which we should load the temporary resources. */
+		private final DependencyResourceSet resourceSet;
+
+		/** Monitor to report progress on. */
+		// FIXME logarithmic progress
+		private final IProgressMonitor monitor;
+
+		/**
+		 * Instantiates a resource visitor.
+		 * 
+		 * @param graph
+		 *            The dependency graph that is to be populated/completed.
+		 * @param monitor
+		 *            The monitor to report progress on.
+		 */
+		public ModelResourceVisitor(Graph<URI> graph, IProgressMonitor monitor) {
+			this.resourceSet = new DependencyResourceSet(graph);
+			this.monitor = monitor;
+			final StorageURIConverter converter = new StorageURIConverter(resourceSet.getURIConverter());
+			this.resourceSet.setURIConverter(converter);
+		}
+
+		/**
+		 * Instantiates a resource visitor given the storage accessor to use for I/O operations.
+		 * 
+		 * @param storageAccessor
+		 *            The accessor to use for all I/O operations to fetch resource content.
+		 * @param side
+		 *            Side of the resources. Used in conjunction with the storage accessor to fetch proper
+		 *            content.
+		 * @param graph
+		 *            The dependency graph that is to be populated/completed.
+		 * @param monitor
+		 *            The monitor to report progress on.
+		 */
+		public ModelResourceVisitor(IStorageProviderAccessor storageAccessor, DiffSide side,
+				Graph<URI> graph, IProgressMonitor monitor) {
+			this.resourceSet = new DependencyResourceSet(graph);
+			this.monitor = monitor;
+			final StorageURIConverter converter = new RevisionedURIConverter(resourceSet.getURIConverter(),
+					storageAccessor, side);
+			this.resourceSet.setURIConverter(converter);
+		}
+
+		/**
+		 * {@inheritDoc}
+		 * 
+		 * @see org.eclipse.core.resources.IResourceVisitor#visit(org.eclipse.core.resources.IResource)
+		 */
+		public boolean visit(IResource resource) throws CoreException {
+			if (resource instanceof IFile) {
+				IFile file = (IFile)resource;
+				if (hasModelType(file)) {
+					resourceSet.resolveAll(file, monitor);
+					return true;
+				}
+				return false;
+			}
+			return true;
+		}
+	}
+
+	/**
+	 * This will listen to workspace changes and react to all changes on "model" resources as determined by
+	 * {@link ProjectModelResolver#MODEL_CONTENT_TYPES}.
+	 * 
+	 * @author <a href="mailto:laurent.goubet@obeo.fr">laurent Goubet</a>
+	 */
+	private static class ModelResourceListener implements IResourceChangeListener {
+		/** Keeps track of the URIs that need to be reparsed when next we need the dependencies graph . */
+		protected Set<URI> changedURIs;
+
+		/** Tracks the files that have been removed. */
+		protected Set<URI> removedURIs;
+
+		/** Initializes this listener. */
+		public ModelResourceListener() {
+			this.changedURIs = new LinkedHashSet<URI>();
+			this.removedURIs = new LinkedHashSet<URI>();
+		}
+
+		/**
+		 * {@inheritDoc}
+		 * 
+		 * @see org.eclipse.core.resources.IResourceChangeListener#resourceChanged(org.eclipse.core.resources.IResourceChangeEvent)
+		 */
+		public void resourceChanged(IResourceChangeEvent event) {
+			final IResourceDelta delta = event.getDelta();
+			if (delta == null) {
+				return;
+			}
+
+			try {
+				delta.accept(new ModelResourceDeltaVisitor());
+			} catch (CoreException e) {
+				EMFCompareIDEUIPlugin.getDefault().log(e);
+			}
+		}
+
+		/**
+		 * Retrieves the set of all changed URIs since we last updated the dependencies graph, and clears it
+		 * for subsequent calls.
+		 * 
+		 * @return The set of all changed URIs since we last updated the dependencies graph.
+		 */
+		public Set<URI> popChangedURIs() {
+			final Set<URI> changed;
+			synchronized(changedURIs) {
+				changed = ImmutableSet.copyOf(changedURIs);
+				changedURIs.clear();
+			}
+			return changed;
+		}
+
+		/**
+		 * Retrieves the set of all removed URIs since we last updated the dependencies graph, and clears it
+		 * for subsequent calls.
+		 * 
+		 * @return The set of all removed URIs since we last updated the dependencies graph.
+		 */
+		public Set<URI> popRemovedURIs() {
+			final Set<URI> removed;
+			synchronized(removedURIs) {
+				removed = ImmutableSet.copyOf(removedURIs);
+				removedURIs.clear();
+			}
+			return removed;
+		}
+
+		/**
+		 * Visits a resource delta to collect the changed and removed files' URIs.
+		 * 
+		 * @author <a href="mailto:laurent.goubet@obeo.fr">laurent Goubet</a>
+		 */
+		private class ModelResourceDeltaVisitor implements IResourceDeltaVisitor {
+			/**
+			 * {@inheritDoc}
+			 * 
+			 * @see org.eclipse.core.resources.IResourceDeltaVisitor#visit(org.eclipse.core.resources.IResourceDelta)
+			 */
+			public boolean visit(IResourceDelta delta) throws CoreException {
+				if (delta.getFlags() == IResourceDelta.MARKERS
+						|| delta.getResource().getType() != IResource.FILE) {
+					return true;
+				}
+
+				final IFile file = (IFile)delta.getResource();
+				final URI fileURI = createURIFor(file);
+				// We can't check the content type of a removed resource
+				if (delta.getKind() == IResourceDelta.REMOVED) {
+					synchronized(removedURIs) {
+						removedURIs.add(fileURI);
+					}
+				} else if (hasModelType(file)) {
+					if ((delta.getKind() & (IResourceDelta.CHANGED | IResourceDelta.ADDED)) != 0) {
+						synchronized(changedURIs) {
+							changedURIs.add(fileURI);
+						}
+					}
+				}
+
+				return true;
+			}
+		}
+	}
+}
diff --git a/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/structuremergeviewer/AbstractStructuredViewerWrapper.java b/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/structuremergeviewer/AbstractStructuredViewerWrapper.java
index e577154..a403c26 100644
--- a/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/structuremergeviewer/AbstractStructuredViewerWrapper.java
+++ b/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/structuremergeviewer/AbstractStructuredViewerWrapper.java
@@ -58,11 +58,11 @@
 	/** The help listener of the wrapped viewer. */
 	private final HelpListener fWrappedViewerHelpListener;
 
-	private final IDoubleClickListener fWrappedViewerDoubleClickListener;

+	private final IDoubleClickListener fWrappedViewerDoubleClickListener;
 
-	private final ISelectionChangedListener fWrappedViewerPostSelectionChangedListener;

+	private final ISelectionChangedListener fWrappedViewerPostSelectionChangedListener;
 
-	private final IOpenListener fWrappedViewerOpenListener;

+	private final IOpenListener fWrappedViewerOpenListener;
 
 	/**
 	 * Constructor.
diff --git a/plugins/org.eclipse.emf.compare.ide/src/org/eclipse/emf/compare/ide/internal/utils/SyncResourceSet.java b/plugins/org.eclipse.emf.compare.ide/src/org/eclipse/emf/compare/ide/internal/utils/SyncResourceSet.java
index bc27bf5..28a9ce7 100644
--- a/plugins/org.eclipse.emf.compare.ide/src/org/eclipse/emf/compare/ide/internal/utils/SyncResourceSet.java
+++ b/plugins/org.eclipse.emf.compare.ide/src/org/eclipse/emf/compare/ide/internal/utils/SyncResourceSet.java
@@ -1,1734 +1,1734 @@
-/*******************************************************************************

- * Copyright (c) 2011, 2013 Obeo.

- * All rights reserved. This program and the accompanying materials

- * are made available under the terms of the Eclipse Public License v1.0

- * which accompanies this distribution, and is available at

- * http://www.eclipse.org/legal/epl-v10.html

- * 

- * Contributors:

- *     Obeo - initial API and implementation

- *******************************************************************************/

-package org.eclipse.emf.compare.ide.internal.utils;

-

-import com.google.common.annotations.Beta;

-import com.google.common.collect.Maps;

-import com.google.common.collect.Sets;

-

-import java.util.Collection;

-import java.util.Iterator;

-import java.util.LinkedHashSet;

-import java.util.List;

-import java.util.ListIterator;

-import java.util.Map;

-import java.util.Set;

-import java.util.concurrent.ExecutionException;

-import java.util.concurrent.Future;

-

-import org.eclipse.core.resources.IStorage;

-import org.eclipse.core.runtime.IProgressMonitor;

-import org.eclipse.core.runtime.IStatus;

-import org.eclipse.core.runtime.Status;

-import org.eclipse.core.runtime.SubMonitor;

-import org.eclipse.emf.common.notify.NotificationChain;

-import org.eclipse.emf.common.util.AbstractEList;

-import org.eclipse.emf.common.util.AbstractTreeIterator;

-import org.eclipse.emf.common.util.EList;

-import org.eclipse.emf.common.util.TreeIterator;

-import org.eclipse.emf.common.util.URI;

-import org.eclipse.emf.compare.ide.EMFCompareIDEPlugin;

-import org.eclipse.emf.compare.ide.internal.utils.PriorityExecutor.Priority;

-import org.eclipse.emf.compare.ide.utils.ResourceUtil;

-import org.eclipse.emf.ecore.EObject;

-import org.eclipse.emf.ecore.EPackage;

-import org.eclipse.emf.ecore.InternalEObject;

-import org.eclipse.emf.ecore.resource.Resource;

-import org.eclipse.emf.ecore.resource.URIConverter;

-import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;

-import org.eclipse.emf.ecore.util.InternalEList;

-import org.eclipse.emf.ecore.xmi.XMLResource;

-

-/**

- * This implementation of a ResourceSet will avoid loading of any resource from any other mean than

- * {@link #resolveAll()}. Furthermore, it will unload any resource it has loaded as soon as its finished with

- * the cross reference links resolving.

- * <p>

- * This is used from our EMFSynchronizationModel in order to resolve the traversals without keeping the whole

- * model in-memory (and striving to never have it in-memory as a whole).

- * </p>

- * <p>

- * Since this class only aims at resolving cross-resource dependencies, its main bottleneck is the parsing of

- * resources when loading (not even the I/O, but the time spent in the SAX parser). We're using a number of

- * tricks to make this bottleneck less problematic. The main improvement in loading performance when compared

- * with the usual resource sets is the threading of the load and unload operations. {@link ResourceLoader}

- * threads are used to load the files and parse them as EMF models. When they're done, they spawn their own

- * {@link #unload(Resource) sub-threads} to unload the models in separate threads.

- * </p>

- * <p>

- * The second improvement of loading performance comes from the specialization of {@link #getLoadOptions()}

- * that allows us to define a set of options that aims at speeding up the parsing process. Further profiling

- * might be needed to isolate other options that would have an impact, such as parser features or XML

- * options...

- * </p>

- * <p>

- * Finally, the humongous CacheAdapter of UML was causing serious issues. Not only did it hinder the

- * performance, but it also caused a random dead lock between our unloading and loading threads. We managed to

- * totally disable it through three means.

- * <ul>

- * <li>The use of the {@link XMLResource#OPTION_DISABLE_NOTIFY} load option.</li>

- * <li>The use of our own {@link NoNotificationParserPool parser pool} that does not re-enable notifications

- * at the end of loading.</li>

- * <li>The removal of all roots from their containing {@link Resource} during iteration when

- * {@link #resolve(Resource) resolving}.</li>

- * </ul>

- * </p>

- * 

- * @author <a href="mailto:laurent.goubet@obeo.fr">Laurent Goubet</a>

- * @noextend This class is not intended to be subclassed by clients.

- */

-@Beta

-public class SyncResourceSet extends ResourceSetImpl {

-	/**

-	 * Keeps track of the URIs that have been demanded by the resolving of a resource. This cache will be

-	 * invalidated when we start resolving this new set of resources.

-	 */

-	private final Set<URI> demandedURIs = Sets.newLinkedHashSet();

-

-	/** Keeps track of the URIs of all resources that have been loaded by this resource set. */

-	private final Set<URI> loadedURIs = Sets.newLinkedHashSet();

-

-	/** Associates URIs with their resources. */

-	private final Map<URI, Resource> uriCache = Maps.newConcurrentMap();

-

-	/**

-	 * This thread pool will be used to launch the loading and unloading of resources in separate threads.

-	 * <p>

-	 * Take note that the unloading threads will take precedence over the loading threads : we need to free

-	 * the memory as soon as possible, and we expect "unload" threads to complete faster that "load" ones.

-	 * </p>

-	 */

-	private final PriorityExecutor pool = new PriorityExecutor("ModelResolver"); //$NON-NLS-1$

-

-	/**

-	 * Default constructor.

-	 */

-	public SyncResourceSet() {

-		// initialize from here to avoid synchronization

-		resources = new SynchronizedResourcesEList<Resource>();

-		loadOptions = super.getLoadOptions();

-		/*

-		 * This resource set is specifically designed to resolve cross resources links, it thus spends a lot

-		 * of time loading resources. The following set of options is what seems to give the most significant

-		 * boost in loading performances, though I did not fine-tune what's really needed here. Take note that

-		 * the use of our own parser pool along with the disabling of notifications is what allows us to

-		 * bypass UML's CacheAdapter and the potential dead locks it causes.

-		 */

-		loadOptions.put(XMLResource.OPTION_USE_PARSER_POOL, new NoNotificationParserPool());

-		loadOptions.put(XMLResource.OPTION_USE_DEPRECATED_METHODS, Boolean.FALSE);

-		loadOptions.put(XMLResource.OPTION_DISABLE_NOTIFY, Boolean.TRUE);

-

-		final int bufferSize = 16384;

-		final Map<String, Object> parserProperties = Maps.newHashMap();

-		parserProperties.put("http://apache.org/xml/properties/input-buffer-size", Integer //$NON-NLS-1$

-				.valueOf(bufferSize));

-		loadOptions.put(XMLResource.OPTION_PARSER_PROPERTIES, parserProperties);

-

-		// These two might be superfluous

-		loadOptions.put(XMLResource.OPTION_DEFER_IDREF_RESOLUTION, Boolean.TRUE);

-

-		/*

-		 * We don't use XMLResource.OPTION_USE_XML_NAME_TO_FEATURE_MAP whereas it could bring performance

-		 * improvements because we are loading the resources concurrently and this map could be used (put and

-		 * get) by several threads. Passing a ConcurrentMap here is not an option either as EMF sometimes

-		 * needs to put "null" values in there. see https://bugs.eclipse.org/bugs/show_bug.cgi?id=403425 for

-		 * more details.

-		 */

-	}

-

-	/**

-	 * {@inheritDoc}

-	 * 

-	 * @see org.eclipse.emf.ecore.resource.impl.ResourceSetImpl#getResource(org.eclipse.emf.common.util.URI,

-	 *      boolean)

-	 */

-	@Override

-	public Resource getResource(URI uri, boolean loadOnDemand) {

-		// Never load resources from here... But we can't simply return "null" if the resource has already

-		// been loaded once, since the XMLHandler would recursively call this till the stack overflow

-		// otherwise.

-		Resource demanded = uriCache.get(uri);

-		if (!loadedURIs.contains(uri) && demanded == null) {

-			final EPackage ePackage = getPackageRegistry().getEPackage(uri.toString());

-			if (ePackage != null) {

-				demanded = ePackage.eResource();

-				uriCache.put(uri, demanded);

-			} else {

-				synchronized(demandedURIs) {

-					demandedURIs.add(uri);

-				}

-			}

-		}

-		return demanded;

-	}

-

-	/**

-	 * {@inheritDoc}

-	 * 

-	 * @see org.eclipse.emf.ecore.resource.impl.ResourceSetImpl#createResource(org.eclipse.emf.common.util.URI)

-	 */

-	@Override

-	public synchronized Resource createResource(URI uri) {

-		final Resource created = super.createResource(uri);

-		uriCache.put(uri, created);

-		return created;

-	}

-

-	/**

-	 * {@inheritDoc}

-	 * 

-	 * @see org.eclipse.emf.ecore.resource.impl.ResourceSetImpl#createResource(org.eclipse.emf.common.util.URI,

-	 *      java.lang.String)

-	 */

-	@Override

-	public synchronized Resource createResource(URI uri, String contentType) {

-		final Resource created = super.createResource(uri, contentType);

-		uriCache.put(uri, created);

-		return created;

-	}

-

-	/**

-	 * {@inheritDoc}

-	 * 

-	 * @see org.eclipse.emf.ecore.resource.impl.ResourceSetImpl#getResources()

-	 */

-	@Override

-	public EList<Resource> getResources() {

-		return resources;

-	}

-

-	/**

-	 * Loads the given URI as an EMF resource.

-	 * 

-	 * @param uri

-	 *            The URI to load as a resource.

-	 * @return The loaded Resource.

-	 */

-	protected Resource loadResource(URI uri) {

-		/*

-		 * Don't use super.getResource : we know the resource does not exist yet as there will only be one

-		 * "load" call for each given URI. The super implementation iterates over loaded resources before

-		 * doing any actual work. That causes some minimal overhead but, more importantly, it can generate

-		 * concurrent modification exceptions.

-		 */

-		final URIConverter theURIConverter = getURIConverter();

-		final URI normalizedURI = theURIConverter.normalize(uri);

-

-		Resource result = uriCache.get(normalizedURI);

-		if (result == null) {

-			result = delegatedGetResource(uri, true);

-			if (result != null) {

-				uriCache.put(uri, result);

-			}

-		}

-

-		if (result == null) {

-			result = demandCreateResource(uri);

-			if (result == null) {

-				// copy/pasted from super.getResource

-				throw new RuntimeException("Cannot create a resource for '" + uri //$NON-NLS-1$

-						+ "'; a registered resource factory is needed"); //$NON-NLS-1$

-			}

-			demandLoadHelper(result);

-		}

-		return result;

-	}

-

-	/**

-	 * {@inheritDoc}

-	 * 

-	 * @see org.eclipse.emf.ecore.resource.impl.ResourceSetImpl#getLoadOptions()

-	 */

-	@Override

-	public Map<Object, Object> getLoadOptions() {

-		return loadOptions;

-	}

-

-	/**

-	 * Resolve all cross resources links of the given starting point. Take note that this resource set is only

-	 * interested in the URIs of the resources, and that it will not keep the loaded content in memory. No

-	 * resource will be kept in the {@link #getResources() resources'} list of this set.

-	 * 

-	 * @param start

-	 *            The starting point from which we'll resolve cross resources references.

-	 * @param monitor

-	 *            the monitor to which progress will be reported

-	 * @return <code>true</code> if we could resolve the model, <code>false</code> if there was an error

-	 *         loading the starting point.

-	 */

-	public boolean resolveAll(IStorage start, IProgressMonitor monitor) {

-		final boolean result;

-		final URI expectedURI = ResourceUtil.createURIFor(start);

-		if (loadedURIs.contains(expectedURI)) {

-			result = true;

-		} else {

-			SubMonitor progress = SubMonitor.convert(monitor, 100);

-			final Resource resource = loadResource(expectedURI);

-			if (resource == null || !resource.getErrors().isEmpty()) {

-				result = false;

-			} else {

-				progress.worked(2);

-

-				// reset the demanded URI that was added by this first call

-				demandedURIs.clear();

-				// and make it "loaded" instead

-				loadedURIs.add(resource.getURI());

-

-				resolve(resource, progress.newChild(2));

-				unload(resource, progress.newChild(2));

-

-				final int remainingWork = 100 - 2 - 2 - 2;

-				resolveAll(progress.newChild(remainingWork));

-

-				result = true;

-			}

-		}

-		return result;

-	}

-

-	/**

-	 * Resolve all cross resources links of the resource located at the given URI. Take note that this

-	 * resource set is only interested in the URIs of the resource, and that it will not keep the loaded

-	 * content in memory. No resource will be kept in the {@link #getResources() resources'} list of this set.

-	 * 

-	 * @param resourceUri

-	 *            The URI of the "starting" resource from which we'll resolve all cross resources references.

-	 * @param monitor

-	 *            the monitor to which progress will be reported

-	 */

-	public void resolveAll(URI resourceUri, IProgressMonitor monitor) {

-		SubMonitor subMonitor = SubMonitor.convert(monitor, 100);

-		Resource resource = super.getResource(resourceUri, true);

-		// reset the demanded URI that was added by this first call

-		demandedURIs.clear();

-		// and make it "loaded" instead

-		loadedURIs.add(resourceUri);

-

-		resolve(resource, subMonitor.newChild(2));

-		unload(resource, subMonitor.newChild(2));

-

-		final int remainingWork = 100 - 2 - 2;

-		resolveAll(subMonitor.newChild(remainingWork));

-	}

-

-	/**

-	 * We've loaded a first resource (from one of the {@link #resolveAll(IStorage)} or

-	 * {@link #resolveAll(URI)} calls). We will now resolve all of this starting point's cross resources

-	 * references.

-	 * 

-	 * @param monitor

-	 *            the monitor to which progress will be reported

-	 */

-	private void resolveAll(IProgressMonitor monitor) {

-		// no need to size this monitor as it will just report logarithmic progress (see javadoc)

-		final SubMonitor progress = SubMonitor.convert(monitor);

-		Set<URI> newURIs;

-		synchronized(demandedURIs) {

-			newURIs = new LinkedHashSet<URI>(demandedURIs);

-			demandedURIs.clear();

-		}

-		while (!newURIs.isEmpty()) {

-			// report logarithmic progress (see SubMonitor javadoc)

-			progress.setWorkRemaining(10000);

-			loadedURIs.addAll(newURIs);

-			final Set<Future<Object>> resolveThreads = Sets.newLinkedHashSet();

-			for (URI uri : newURIs) {

-				resolveThreads.add(pool.submit(new ResourceLoader(uri, progress.newChild(1)), Priority.LOW));

-			}

-			for (Future<Object> future : resolveThreads) {

-				try {

-					future.get();

-				} catch (InterruptedException e) {

-					// Ignore

-				} catch (ExecutionException e) {

-					// TODO does this need to be logged when the underlying exception is IO?

-					final IStatus status = new Status(IStatus.WARNING, EMFCompareIDEPlugin.PLUGIN_ID, e

-							.getMessage(), e);

-					EMFCompareIDEPlugin.getDefault().getLog().log(status);

-				}

-			}

-			synchronized(demandedURIs) {

-				newURIs = new LinkedHashSet<URI>(demandedURIs);

-				demandedURIs.clear();

-			}

-		}

-	}

-

-	/**

-	 * This will resolve all cross references of the given resource, never actually loading other resources

-	 * (their URIs are collected within {@link #demandedURIs}.

-	 * 

-	 * @param resource

-	 *            The resource for which we are to resolve all cross references.

-	 * @param monitor

-	 *            The monitor to which progress will be reported.

-	 */

-	private void resolve(Resource resource, IProgressMonitor monitor) {

-		resource.eSetDeliver(false);

-		final List<EObject> roots = ((InternalEList<EObject>)resource.getContents()).basicList();

-		final Iterator<EObject> resourceContent = roots.iterator();

-		resource.getContents().clear();

-

-		SubMonitor subMonitor = SubMonitor.convert(monitor, roots.size());

-		while (resourceContent.hasNext()) {

-			final EObject eObject = resourceContent.next();

-			resolveCrossReferences(resource, eObject);

-			final TreeIterator<EObject> childContent = basicEAllContents(eObject);

-			// the process of one root is one tick

-			SubMonitor childMonitor = subMonitor.newChild(1);

-			while (childContent.hasNext()) {

-				// report logarithmic progress for each root processing (see javadoc)

-				childMonitor.setWorkRemaining(10000);

-				final EObject child = childContent.next();

-				if (child.eIsProxy()) {

-					resolveCrossReference(resource, child);

-				} else {

-					resolveCrossReferences(resource, child);

-				}

-				// report logarithmic progress (see javadoc)

-				childMonitor.worked(1);

-			}

-		}

-		resource.getContents().addAll(roots);

-	}

-

-	/**

-	 * Resolve a given proxy's reference. This will only be called on proxy EObjects (

-	 * <code>proxy.eIsProxy()</code> is true).

-	 * 

-	 * @param resource

-	 *            Resource containing this proxy.

-	 * @param proxy

-	 *            The proxy to resolve.

-	 */

-	protected void resolveCrossReference(Resource resource, EObject proxy) {

-		final URI proxyURI = ((InternalEObject)proxy).eProxyURI();

-		getResource(proxyURI.trimFragment(), false);

-	}

-

-	/**

-	 * An implementation of {@link EObject#eAllContents()} that will not resolve its proxies.

-	 * 

-	 * @param eObject

-	 *            The eobject for which contents we need an iterator.

-	 * @return The created {@link TreeIterator}.

-	 */

-	private TreeIterator<EObject> basicEAllContents(final EObject eObject) {

-		return new AbstractTreeIterator<EObject>(eObject, false) {

-			/** Generated SUID. */

-			private static final long serialVersionUID = 6874121606163401152L;

-

-			/**

-			 * {@inheritDoc}

-			 * 

-			 * @see org.eclipse.emf.common.util.AbstractTreeIterator#getChildren(java.lang.Object)

-			 */

-			@Override

-			public Iterator<EObject> getChildren(Object obj) {

-				return ((InternalEList<EObject>)((EObject)obj).eContents()).basicIterator();

-			}

-		};

-	}

-

-	/**

-	 * Unload the given resource.

-	 * 

-	 * @param resource

-	 *            The resource we are to unload.

-	 * @param monitor

-	 *            The monitor to which progress will be reported.

-	 */

-	private void unload(final Resource resource, IProgressMonitor monitor) {

-		final SubMonitor subMonitor = SubMonitor.convert(monitor, 1);

-		// only unload those resources that are located in the workspace

-		final URI uri = resource.getURI();

-		if (uri.isPlatformResource() || uri.isRelative() || uri.isFile()) {

-			uriCache.remove(uri);

-			getResources().remove(resource);

-

-			// Only "unload()" when needed... The one we know of is UML

-			if (resource.getClass().getSimpleName().startsWith("UMLResource")) { //$NON-NLS-1$

-				// We still need to unload what we loaded since some (like UML) cross reference everything...

-				final Runnable unloader = new Runnable() {

-					public void run() {

-						resource.unload();

-						subMonitor.worked(1);

-					}

-				};

-				pool.submit(unloader, Priority.NORMAL);

-			}

-		}

-	}

-

-	/**

-	 * Resolves the cross references of the given EObject.

-	 * 

-	 * @param resource

-	 *            Resource containing this EObject.

-	 * @param eObject

-	 *            The EObject for which we are to resolve the cross references.

-	 */

-	private void resolveCrossReferences(Resource resource, EObject eObject) {

-		final Iterator<EObject> objectChildren = ((InternalEList<EObject>)eObject.eCrossReferences())

-				.basicIterator();

-		while (objectChildren.hasNext()) {

-			final EObject eObj = objectChildren.next();

-			if (eObj.eIsProxy()) {

-				resolveCrossReference(resource, eObj);

-			}

-		}

-	}

-

-	/**

-	 * This implementation of a {@link Runnable} will be used to load a given uri from the disk as an EMF

-	 * {@link Resource} and resolve all of its cross-resource links (these will be stored in

-	 * {@link #demandedURIs} as we go). Once done, it will spawn another thread in order to unload that

-	 * resource out of the memory.

-	 * 

-	 * @author <a href="mailto:laurent.goubet@obeo.fr">Laurent Goubet</a>

-	 */

-	private class ResourceLoader implements Runnable {

-		/** The uri of the EMF Resource we are to load from the disk. */

-		private final URI uri;

-

-		/** The monitor to which progress will be reported. */

-		private final SubMonitor subMonitor;

-

-		/**

-		 * Constructs our loader thread given its target URI.

-		 * 

-		 * @param uri

-		 *            The uri of the EMF Resource this thread is to load from the disk.

-		 * @param monitor

-		 *            The monitor to which progress will be reported.

-		 */

-		public ResourceLoader(URI uri, IProgressMonitor monitor) {

-			this.uri = uri;

-			this.subMonitor = SubMonitor.convert(monitor, 2);

-		}

-

-		/**

-		 * {@inheritDoc}

-		 * 

-		 * @see java.lang.Runnable#run()

-		 */

-		public void run() {

-			final Resource newResource = loadResource(uri);

-			resolve(newResource, subMonitor.newChild(1));

-			unload(newResource, subMonitor.newChild(1));

-		}

-	}

-

-	/**

-	 * A synchronized implementation of {@link ResourcesEList}.

-	 * <p>

-	 * Note that this cannot be extracted out of the {@link SyncResourceSet} since the {@link ResourcesEList}

-	 * type is not visible.

-	 * </p>

-	 * 

-	 * @param <E>

-	 *            Type of this list's contents.

-	 * @author <a href="mailto:laurent.goubet@obeo.fr">Laurent Goubet</a>

-	 */

-	private class SynchronizedResourcesEList<E extends Object & Resource> extends ResourcesEList<E> {

-		/** Generated SUID. */

-		private static final long serialVersionUID = 7371376112881960414L;

-

-		/** The lock we'll use for synchronization of the resources list. */

-		private final Object lock = new Object();

-

-		/**

-		 * {@inheritDoc}

-		 * 

-		 * @see java.util.AbstractCollection#containsAll(java.util.Collection)

-		 */

-		@Override

-		public boolean containsAll(Collection<?> c) {

-			synchronized(lock) {

-				return super.containsAll(c);

-			}

-		}

-

-		/**

-		 * {@inheritDoc}

-		 * 

-		 * @see org.eclipse.emf.common.util.AbstractEList#set(int, java.lang.Object)

-		 */

-		@Override

-		public E set(int index, E object) {

-			synchronized(lock) {

-				return super.set(index, object);

-			}

-		}

-

-		/**

-		 * {@inheritDoc}

-		 * 

-		 * @see org.eclipse.emf.common.util.AbstractEList#add(java.lang.Object)

-		 */

-		@Override

-		public boolean add(E object) {

-			synchronized(lock) {

-				return super.add(object);

-			}

-		}

-

-		/**

-		 * {@inheritDoc}

-		 * 

-		 * @see org.eclipse.emf.common.util.AbstractEList#add(int, java.lang.Object)

-		 */

-		@Override

-		public void add(int index, E object) {

-			synchronized(lock) {

-				super.add(index, object);

-			}

-		}

-

-		/**

-		 * {@inheritDoc}

-		 * 

-		 * @see org.eclipse.emf.common.util.AbstractEList#addAll(java.util.Collection)

-		 */

-		@Override

-		public boolean addAll(Collection<? extends E> collection) {

-			synchronized(lock) {

-				return super.addAll(collection);

-			}

-		}

-

-		/**

-		 * {@inheritDoc}

-		 * 

-		 * @see org.eclipse.emf.common.util.AbstractEList#addAll(int, java.util.Collection)

-		 */

-		@Override

-		public boolean addAll(int index, Collection<? extends E> collection) {

-			synchronized(lock) {

-				return super.addAll(index, collection);

-			}

-		}

-

-		/**

-		 * {@inheritDoc}

-		 * 

-		 * @see org.eclipse.emf.common.util.AbstractEList#remove(java.lang.Object)

-		 */

-		@Override

-		public boolean remove(Object object) {

-			synchronized(lock) {

-				return super.remove(object);

-			}

-		}

-

-		/**

-		 * {@inheritDoc}

-		 * 

-		 * @see org.eclipse.emf.common.util.AbstractEList#retainAll(java.util.Collection)

-		 */

-		@Override

-		public boolean retainAll(Collection<?> collection) {

-			synchronized(lock) {

-				return super.retainAll(collection);

-			}

-		}

-

-		/**

-		 * {@inheritDoc}

-		 * 

-		 * @see org.eclipse.emf.common.util.AbstractEList#move(int, java.lang.Object)

-		 */

-		@Override

-		public void move(int index, E object) {

-			synchronized(lock) {

-				super.move(index, object);

-			}

-		}

-

-		/**

-		 * {@inheritDoc}

-		 * 

-		 * @see org.eclipse.emf.common.util.AbstractEList#equals(java.lang.Object)

-		 */

-		@Override

-		public boolean equals(Object object) {

-			synchronized(lock) {

-				return super.equals(object);

-			}

-		}

-

-		/**

-		 * {@inheritDoc}

-		 * 

-		 * @see org.eclipse.emf.common.util.AbstractEList#hashCode()

-		 */

-		@Override

-		public int hashCode() {

-			synchronized(lock) {

-				return super.hashCode();

-			}

-		}

-

-		/**

-		 * {@inheritDoc}

-		 * 

-		 * @see org.eclipse.emf.common.util.AbstractEList#toString()

-		 */

-		@Override

-		public String toString() {

-			synchronized(lock) {

-				return super.toString();

-			}

-		}

-

-		/**

-		 * {@inheritDoc}

-		 * 

-		 * @see org.eclipse.emf.common.util.AbstractEList#iterator()

-		 */

-		@Override

-		public Iterator<E> iterator() {

-			return new SynchronizedEIterator();

-		}

-

-		/**

-		 * {@inheritDoc}

-		 * 

-		 * @see org.eclipse.emf.common.util.AbstractEList#listIterator()

-		 */

-		@Override

-		public ListIterator<E> listIterator() {

-			return new SynchronizedEListIterator();

-		}

-

-		/**

-		 * {@inheritDoc}

-		 * 

-		 * @see org.eclipse.emf.common.util.AbstractEList#listIterator(int)

-		 */

-		@Override

-		public ListIterator<E> listIterator(int index) {

-			synchronized(lock) {

-				int curSize = size();

-				if (index < 0 || index > curSize) {

-					throw new BasicIndexOutOfBoundsException(index, curSize);

-				}

-				return new SynchronizedEListIterator(index);

-			}

-		}

-

-		/**

-		 * {@inheritDoc}

-		 * 

-		 * @see org.eclipse.emf.common.util.BasicEList#indexOf(java.lang.Object)

-		 */

-		@Override

-		public int indexOf(Object object) {

-			synchronized(lock) {

-				return super.indexOf(object);

-			}

-		}

-

-		/**

-		 * {@inheritDoc}

-		 * 

-		 * @see org.eclipse.emf.common.util.BasicEList#lastIndexOf(java.lang.Object)

-		 */

-		@Override

-		public int lastIndexOf(Object object) {

-			synchronized(lock) {

-				return super.lastIndexOf(object);

-			}

-		}

-

-		/**

-		 * {@inheritDoc}

-		 * 

-		 * @see org.eclipse.emf.common.util.BasicEList#toArray()

-		 */

-		@Override

-		public Object[] toArray() {

-			synchronized(lock) {

-				return super.toArray();

-			}

-		}

-

-		/**

-		 * {@inheritDoc}

-		 * 

-		 * @see org.eclipse.emf.common.util.BasicEList#toArray(T[])

-		 */

-		@Override

-		public <T> T[] toArray(T[] array) {

-			synchronized(lock) {

-				return super.toArray(array);

-			}

-		}

-

-		/**

-		 * {@inheritDoc}

-		 * 

-		 * @see org.eclipse.emf.common.util.BasicEList#setData(int, java.lang.Object[])

-		 */

-		@Override

-		public void setData(int size, Object[] data) {

-			synchronized(lock) {

-				super.setData(size, data);

-			}

-		}

-

-		/**

-		 * {@inheritDoc}

-		 * 

-		 * @see org.eclipse.emf.common.util.BasicEList#get(int)

-		 */

-		@Override

-		public E get(int index) {

-			synchronized(lock) {

-				return super.get(index);

-			}

-		}

-

-		/**

-		 * {@inheritDoc}

-		 * 

-		 * @see org.eclipse.emf.common.util.BasicEList#basicGet(int)

-		 */

-		@Override

-		public E basicGet(int index) {

-			synchronized(lock) {

-				return super.basicGet(index);

-			}

-		}

-

-		/**

-		 * {@inheritDoc}

-		 * 

-		 * @see org.eclipse.emf.common.util.BasicEList#shrink()

-		 */

-		@Override

-		public void shrink() {

-			synchronized(lock) {

-				super.shrink();

-			}

-		}

-

-		/**

-		 * {@inheritDoc}

-		 * 

-		 * @see org.eclipse.emf.common.util.BasicEList#grow(int)

-		 */

-		@Override

-		public void grow(int minimumCapacity) {

-			synchronized(lock) {

-				super.grow(minimumCapacity);

-			}

-		}

-

-		/**

-		 * {@inheritDoc}

-		 * 

-		 * @see org.eclipse.emf.common.util.BasicEList#clone()

-		 */

-		// CHECKSTYLE:OFF we're overriding...

-		@Override

-		public Object clone() {

-			// CHECKSTYLE:ON

-			synchronized(lock) {

-				return super.clone();

-			}

-		}

-

-		/**

-		 * {@inheritDoc}

-		 * 

-		 * @see org.eclipse.emf.common.notify.impl.NotifyingListImpl#addUnique(java.lang.Object)

-		 */

-		@Override

-		public void addUnique(E object) {

-			synchronized(lock) {

-				super.addUnique(object);

-			}

-		}

-

-		/**

-		 * {@inheritDoc}

-		 * 

-		 * @see org.eclipse.emf.common.notify.impl.NotifyingListImpl#addUnique(int, java.lang.Object)

-		 */

-		@Override

-		public void addUnique(int index, E object) {

-			synchronized(lock) {

-				super.addUnique(index, object);

-			}

-		}

-

-		/**

-		 * {@inheritDoc}

-		 * 

-		 * @see org.eclipse.emf.common.notify.impl.NotifyingListImpl#addAllUnique(java.util.Collection)

-		 */

-		@Override

-		public boolean addAllUnique(Collection<? extends E> collection) {

-			synchronized(lock) {

-				return super.addAllUnique(collection);

-			}

-		}

-

-		/**

-		 * {@inheritDoc}

-		 * 

-		 * @see org.eclipse.emf.common.notify.impl.NotifyingListImpl#addAllUnique(int, java.util.Collection)

-		 */

-		@Override

-		public boolean addAllUnique(int index, Collection<? extends E> collection) {

-			synchronized(lock) {

-				return super.addAllUnique(index, collection);

-			}

-		}

-

-		/**

-		 * {@inheritDoc}

-		 * 

-		 * @see org.eclipse.emf.common.notify.impl.NotifyingListImpl#addAllUnique(java.lang.Object[], int,

-		 *      int)

-		 */

-		@Override

-		public boolean addAllUnique(Object[] objects, int start, int end) {

-			synchronized(lock) {

-				return super.addAllUnique(objects, start, end);

-			}

-		}

-

-		/**

-		 * {@inheritDoc}

-		 * 

-		 * @see org.eclipse.emf.common.notify.impl.NotifyingListImpl#addAllUnique(int, java.lang.Object[],

-		 *      int, int)

-		 */

-		@Override

-		public boolean addAllUnique(int index, Object[] objects, int start, int end) {

-			synchronized(lock) {

-				return super.addAllUnique(index, objects, start, end);

-			}

-		}

-

-		/**

-		 * {@inheritDoc}

-		 * 

-		 * @see org.eclipse.emf.common.notify.impl.NotifyingListImpl#basicAdd(java.lang.Object,

-		 *      org.eclipse.emf.common.notify.NotificationChain)

-		 */

-		@Override

-		public NotificationChain basicAdd(E object, NotificationChain notifications) {

-			synchronized(lock) {

-				return super.basicAdd(object, notifications);

-			}

-		}

-

-		/**

-		 * {@inheritDoc}

-		 * 

-		 * @see org.eclipse.emf.common.notify.impl.NotifyingListImpl#remove(int)

-		 */

-		@Override

-		public E remove(int index) {

-			synchronized(lock) {

-				return super.remove(index);

-			}

-		}

-

-		/**

-		 * {@inheritDoc}

-		 * 

-		 * @see org.eclipse.emf.common.notify.impl.NotifyingListImpl#removeAll(java.util.Collection)

-		 */

-		@Override

-		public boolean removeAll(Collection<?> collection) {

-			synchronized(lock) {

-				return super.removeAll(collection);

-			}

-		}

-

-		/**

-		 * {@inheritDoc}

-		 * 

-		 * @see org.eclipse.emf.common.notify.impl.NotifyingListImpl#basicRemove(java.lang.Object,

-		 *      org.eclipse.emf.common.notify.NotificationChain)

-		 */

-		@Override

-		public NotificationChain basicRemove(Object object, NotificationChain notifications) {

-			synchronized(lock) {

-				return super.basicRemove(object, notifications);

-			}

-		}

-

-		/**

-		 * {@inheritDoc}

-		 * 

-		 * @see org.eclipse.emf.common.notify.impl.NotifyingListImpl#clear()

-		 */

-		@Override

-		public void clear() {

-			synchronized(lock) {

-				super.clear();

-			}

-		}

-

-		/**

-		 * {@inheritDoc}

-		 * 

-		 * @see org.eclipse.emf.common.notify.impl.NotifyingListImpl#setUnique(int, java.lang.Object)

-		 */

-		@Override

-		public E setUnique(int index, E object) {

-			synchronized(lock) {

-				return super.setUnique(index, object);

-			}

-		}

-

-		/**

-		 * {@inheritDoc}

-		 * 

-		 * @see org.eclipse.emf.common.notify.impl.NotifyingListImpl#basicSet(int, java.lang.Object,

-		 *      org.eclipse.emf.common.notify.NotificationChain)

-		 */

-		@Override

-		public NotificationChain basicSet(int index, E object, NotificationChain notifications) {

-			synchronized(lock) {

-				return super.basicSet(index, object, notifications);

-			}

-		}

-

-		/**

-		 * {@inheritDoc}

-		 * 

-		 * @see org.eclipse.emf.common.notify.impl.NotifyingListImpl#move(int, int)

-		 */

-		@Override

-		public E move(int targetIndex, int sourceIndex) {

-			synchronized(lock) {

-				return super.move(targetIndex, sourceIndex);

-			}

-		}

-

-		/**

-		 * {@inheritDoc}

-		 * 

-		 * @see org.eclipse.emf.ecore.util.NotifyingInternalEListImpl#basicList()

-		 */

-		@Override

-		public List<E> basicList() {

-			synchronized(lock) {

-				return super.basicList();

-			}

-		}

-

-		/**

-		 * {@inheritDoc}

-		 * 

-		 * @see org.eclipse.emf.ecore.util.NotifyingInternalEListImpl#basicIterator()

-		 */

-		@Override

-		public Iterator<E> basicIterator() {

-			return new SynchronizedNonResolvingEIterator();

-		}

-

-		/**

-		 * {@inheritDoc}

-		 * 

-		 * @see org.eclipse.emf.ecore.util.NotifyingInternalEListImpl#basicListIterator()

-		 */

-		@Override

-		public ListIterator<E> basicListIterator() {

-			return new SynchronizedNonResolvingEListIterator();

-		}

-

-		/**

-		 * {@inheritDoc}

-		 * 

-		 * @see org.eclipse.emf.ecore.util.NotifyingInternalEListImpl#basicListIterator(int)

-		 */

-		@Override

-		public ListIterator<E> basicListIterator(int index) {

-			synchronized(lock) {

-				int curSize = size();

-				if (index < 0 || index > curSize) {

-					throw new BasicIndexOutOfBoundsException(index, curSize);

-				}

-				return new SynchronizedNonResolvingEListIterator(index);

-			}

-		}

-

-		/**

-		 * {@inheritDoc}

-		 * 

-		 * @see org.eclipse.emf.ecore.resource.impl.ResourceSetImpl.ResourcesEList#contains(java.lang.Object)

-		 */

-		@Override

-		public boolean contains(Object object) {

-			synchronized(lock) {

-				return super.contains(object);

-			}

-		}

-

-		/**

-		 * {@inheritDoc}

-		 * 

-		 * @see org.eclipse.emf.ecore.util.NotifyingInternalEListImpl#basicContains(java.lang.Object)

-		 */

-		@Override

-		public boolean basicContains(Object object) {

-			synchronized(lock) {

-				return super.basicContains(object);

-			}

-		}

-

-		/**

-		 * {@inheritDoc}

-		 * 

-		 * @see org.eclipse.emf.ecore.util.NotifyingInternalEListImpl#basicContainsAll(java.util.Collection)

-		 */

-		@Override

-		public boolean basicContainsAll(Collection<?> collection) {

-			synchronized(lock) {

-				return super.basicContainsAll(collection);

-			}

-		}

-

-		/**

-		 * {@inheritDoc}

-		 * 

-		 * @see org.eclipse.emf.ecore.util.NotifyingInternalEListImpl#basicIndexOf(java.lang.Object)

-		 */

-

-		@Override

-		public int basicIndexOf(Object object) {

-			synchronized(lock) {

-				return super.basicIndexOf(object);

-			}

-		}

-

-		/**

-		 * {@inheritDoc}

-		 * 

-		 * @see org.eclipse.emf.ecore.util.NotifyingInternalEListImpl#basicLastIndexOf(java.lang.Object)

-		 */

-		@Override

-		public int basicLastIndexOf(Object object) {

-			synchronized(lock) {

-				return super.basicLastIndexOf(object);

-			}

-		}

-

-		/**

-		 * {@inheritDoc}

-		 * 

-		 * @see org.eclipse.emf.ecore.util.NotifyingInternalEListImpl#basicToArray()

-		 */

-		@Override

-		public Object[] basicToArray() {

-			synchronized(lock) {

-				return super.basicToArray();

-			}

-		}

-

-		/**

-		 * {@inheritDoc}

-		 * 

-		 * @see org.eclipse.emf.ecore.util.NotifyingInternalEListImpl#basicToArray(T[])

-		 */

-		@Override

-		public <T> T[] basicToArray(T[] array) {

-			synchronized(lock) {

-				return super.basicToArray(array);

-			}

-		}

-

-		/**

-		 * {@inheritDoc}

-		 * 

-		 * @see org.eclipse.emf.common.util.BasicEList#data()

-		 */

-		@Override

-		public Object[] data() {

-			synchronized(lock) {

-				return super.data();

-			}

-		}

-

-		/**

-		 * {@inheritDoc}

-		 * 

-		 * @see org.eclipse.emf.common.notify.impl.NotifyingListImpl#getFeature()

-		 */

-		@Override

-		public Object getFeature() {

-			synchronized(lock) {

-				return super.getFeature();

-			}

-		}

-

-		/**

-		 * {@inheritDoc}

-		 * 

-		 * @see org.eclipse.emf.ecore.resource.impl.ResourceSetImpl.ResourcesEList#getFeatureID()

-		 */

-		@Override

-		public int getFeatureID() {

-			synchronized(lock) {

-				return super.getFeatureID();

-			}

-		}

-

-		/**

-		 * {@inheritDoc}

-		 * 

-		 * @see org.eclipse.emf.ecore.resource.impl.ResourceSetImpl.ResourcesEList#getNotifier()

-		 */

-		@Override

-		public Object getNotifier() {

-			synchronized(lock) {

-				return super.getNotifier();

-			}

-		}

-

-		/**

-		 * {@inheritDoc}

-		 * 

-		 * @see org.eclipse.emf.common.util.BasicEList#isEmpty()

-		 */

-		@Override

-		public boolean isEmpty() {

-			synchronized(lock) {

-				return super.isEmpty();

-			}

-		}

-

-		/**

-		 * {@inheritDoc}

-		 * 

-		 * @see org.eclipse.emf.common.util.BasicEList#size()

-		 */

-		@Override

-		public int size() {

-			synchronized(lock) {

-				return super.size();

-			}

-		}

-

-		/**

-		 * {@inheritDoc}

-		 * 

-		 * @see java.util.AbstractList#subList(int, int)

-		 */

-		@Override

-		public List<E> subList(int fromIndex, int toIndex) {

-			synchronized(lock) {

-				return super.subList(fromIndex, toIndex);

-			}

-		}

-

-		/**

-		 * A synchronized implementation of the {@link AbstractEList.EIterator}.

-		 * 

-		 * @author <a href="mailto:laurent.goubet@obeo.fr">Laurent Goubet</a>

-		 */

-		private class SynchronizedEIterator extends AbstractEList<E>.EIterator<E> {

-			/**

-			 * {@inheritDoc}

-			 * 

-			 * @see org.eclipse.emf.common.util.AbstractEList.EIterator#hasNext()

-			 */

-			@Override

-			public boolean hasNext() {

-				synchronized(lock) {

-					return super.hasNext();

-				}

-			}

-

-			/**

-			 * {@inheritDoc}

-			 * 

-			 * @see org.eclipse.emf.common.util.AbstractEList.EIterator#next()

-			 */

-			@Override

-			public E next() {

-				synchronized(lock) {

-					return super.next();

-				}

-			}

-

-			/**

-			 * {@inheritDoc}

-			 * 

-			 * @see org.eclipse.emf.common.util.AbstractEList.EIterator#remove()

-			 */

-			@Override

-			public void remove() {

-				synchronized(lock) {

-					super.remove();

-				}

-			}

-

-			/**

-			 * {@inheritDoc}

-			 * 

-			 * @see java.lang.Object#equals(java.lang.Object)

-			 */

-			@Override

-			public boolean equals(Object obj) {

-				synchronized(lock) {

-					return super.equals(obj);

-				}

-			}

-

-			/**

-			 * {@inheritDoc}

-			 * 

-			 * @see java.lang.Object#hashCode()

-			 */

-			@Override

-			public int hashCode() {

-				synchronized(lock) {

-					return super.hashCode();

-				}

-			}

-

-			/**

-			 * {@inheritDoc}

-			 * 

-			 * @see java.lang.Object#toString()

-			 */

-			@Override

-			public String toString() {

-				synchronized(lock) {

-					return super.toString();

-				}

-			}

-		}

-

-		/**

-		 * A synchronized implementation of the {@link AbstractEList.EListIterator}.

-		 * 

-		 * @author <a href="mailto:laurent.goubet@obeo.fr">Laurent Goubet</a>

-		 */

-		private class SynchronizedEListIterator extends AbstractEList<E>.EListIterator<E> {

-			/**

-			 * Delegates to the super constructor.

-			 */

-			public SynchronizedEListIterator() {

-				super();

-			}

-

-			/**

-			 * Delegates to the super constructor.

-			 * 

-			 * @param index

-			 *            Index at which this list iterator should start.

-			 */

-			public SynchronizedEListIterator(int index) {

-				super(index);

-			}

-

-			/**

-			 * {@inheritDoc}

-			 * 

-			 * @see org.eclipse.emf.common.util.AbstractEList.EListIterator#add(java.lang.Object)

-			 */

-			@Override

-			public void add(E object) {

-				synchronized(lock) {

-					super.add(object);

-				}

-			}

-

-			/**

-			 * {@inheritDoc}

-			 * 

-			 * @see org.eclipse.emf.common.util.AbstractEList.EIterator#hasNext()

-			 */

-			@Override

-			public boolean hasNext() {

-				synchronized(lock) {

-					return super.hasNext();

-				}

-			}

-

-			/**

-			 * {@inheritDoc}

-			 * 

-			 * @see org.eclipse.emf.common.util.AbstractEList.EListIterator#hasPrevious()

-			 */

-			@Override

-			public boolean hasPrevious() {

-				synchronized(lock) {

-					return super.hasPrevious();

-				}

-			}

-

-			/**

-			 * {@inheritDoc}

-			 * 

-			 * @see org.eclipse.emf.common.util.AbstractEList.EIterator#next()

-			 */

-			@Override

-			public E next() {

-				synchronized(lock) {

-					return super.next();

-				}

-			}

-

-			/**

-			 * {@inheritDoc}

-			 * 

-			 * @see org.eclipse.emf.common.util.AbstractEList.EListIterator#previous()

-			 */

-			@Override

-			public E previous() {

-				synchronized(lock) {

-					return super.previous();

-				}

-			}

-

-			/**

-			 * {@inheritDoc}

-			 * 

-			 * @see org.eclipse.emf.common.util.AbstractEList.EListIterator#previousIndex()

-			 */

-			@Override

-			public int previousIndex() {

-				synchronized(lock) {

-					return super.previousIndex();

-				}

-			}

-

-			/**

-			 * {@inheritDoc}

-			 * 

-			 * @see org.eclipse.emf.common.util.AbstractEList.EIterator#remove()

-			 */

-			@Override

-			public void remove() {

-				synchronized(lock) {

-					super.remove();

-				}

-			}

-

-			/**

-			 * {@inheritDoc}

-			 * 

-			 * @see org.eclipse.emf.common.util.AbstractEList.EListIterator#set(java.lang.Object)

-			 */

-			@Override

-			public void set(E object) {

-				synchronized(lock) {

-					super.set(object);

-				}

-			}

-

-			/**

-			 * {@inheritDoc}

-			 * 

-			 * @see java.lang.Object#equals(java.lang.Object)

-			 */

-			@Override

-			public boolean equals(Object obj) {

-				synchronized(lock) {

-					return super.equals(obj);

-				}

-			}

-

-			/**

-			 * {@inheritDoc}

-			 * 

-			 * @see java.lang.Object#hashCode()

-			 */

-			@Override

-			public int hashCode() {

-				synchronized(lock) {

-					return super.hashCode();

-				}

-			}

-

-			/**

-			 * {@inheritDoc}

-			 * 

-			 * @see java.lang.Object#toString()

-			 */

-			@Override

-			public String toString() {

-				synchronized(lock) {

-					return super.toString();

-				}

-			}

-

-			/**

-			 * {@inheritDoc}

-			 * 

-			 * @see org.eclipse.emf.common.util.AbstractEList.EListIterator#nextIndex()

-			 */

-			@Override

-			public int nextIndex() {

-				synchronized(lock) {

-					return super.nextIndex();

-				}

-			}

-		}

-

-		/**

-		 * A synchronized implementation of the {@link AbstractEList.NonResolvingEIterator}.

-		 * 

-		 * @author <a href="mailto:laurent.goubet@obeo.fr">Laurent Goubet</a>

-		 */

-		private class SynchronizedNonResolvingEIterator extends AbstractEList<E>.NonResolvingEIterator<E> {

-			/**

-			 * {@inheritDoc}

-			 * 

-			 * @see org.eclipse.emf.common.util.AbstractEList.EIterator#hasNext()

-			 */

-			@Override

-			public boolean hasNext() {

-				synchronized(lock) {

-					return super.hasNext();

-				}

-			}

-

-			/**

-			 * {@inheritDoc}

-			 * 

-			 * @see org.eclipse.emf.common.util.AbstractEList.EIterator#next()

-			 */

-			@Override

-			public E next() {

-				synchronized(lock) {

-					return super.next();

-				}

-			}

-

-			/**

-			 * {@inheritDoc}

-			 * 

-			 * @see org.eclipse.emf.common.util.AbstractEList.NonResolvingEIterator#remove()

-			 */

-			@Override

-			public void remove() {

-				synchronized(lock) {

-					super.remove();

-				}

-			}

-

-			/**

-			 * {@inheritDoc}

-			 * 

-			 * @see java.lang.Object#equals(java.lang.Object)

-			 */

-			@Override

-			public boolean equals(Object obj) {

-				synchronized(lock) {

-					return super.equals(obj);

-				}

-			}

-

-			/**

-			 * {@inheritDoc}

-			 * 

-			 * @see java.lang.Object#hashCode()

-			 */

-			@Override

-			public int hashCode() {

-				synchronized(lock) {

-					return super.hashCode();

-				}

-			}

-

-			/**

-			 * {@inheritDoc}

-			 * 

-			 * @see java.lang.Object#toString()

-			 */

-			@Override

-			public String toString() {

-				synchronized(lock) {

-					return super.toString();

-				}

-			}

-		}

-

-		/**

-		 * A synchronized implementation of the {@link AbstractEList.NonResolvingEListIterator}.

-		 * 

-		 * @author <a href="mailto:laurent.goubet@obeo.fr">Laurent Goubet</a>

-		 */

-		private class SynchronizedNonResolvingEListIterator extends AbstractEList<E>.NonResolvingEListIterator<E> {

-			/**

-			 * Delegates to the super constructor.

-			 */

-			public SynchronizedNonResolvingEListIterator() {

-				super();

-			}

-

-			/**

-			 * Delegates to the super constructor.

-			 * 

-			 * @param index

-			 *            Index at which the iteration should start.

-			 */

-			public SynchronizedNonResolvingEListIterator(int index) {

-				super(index);

-			}

-

-			/**

-			 * {@inheritDoc}

-			 * 

-			 * @see org.eclipse.emf.common.util.AbstractEList.NonResolvingEListIterator#add(java.lang.Object)

-			 */

-			@Override

-			public void add(E object) {

-				synchronized(lock) {

-					super.add(object);

-				}

-			}

-

-			/**

-			 * {@inheritDoc}

-			 * 

-			 * @see org.eclipse.emf.common.util.AbstractEList.EIterator#hasNext()

-			 */

-			@Override

-			public boolean hasNext() {

-				synchronized(lock) {

-					return super.hasNext();

-				}

-			}

-

-			/**

-			 * {@inheritDoc}

-			 * 

-			 * @see org.eclipse.emf.common.util.AbstractEList.EListIterator#hasPrevious()

-			 */

-			@Override

-			public boolean hasPrevious() {

-				synchronized(lock) {

-					return super.hasPrevious();

-				}

-			}

-

-			/**

-			 * {@inheritDoc}

-			 * 

-			 * @see org.eclipse.emf.common.util.AbstractEList.EIterator#next()

-			 */

-			@Override

-			public E next() {

-				synchronized(lock) {

-					return super.next();

-				}

-			}

-

-			/**

-			 * {@inheritDoc}

-			 * 

-			 * @see org.eclipse.emf.common.util.AbstractEList.EListIterator#previous()

-			 */

-			@Override

-			public E previous() {

-				synchronized(lock) {

-					return super.previous();

-				}

-			}

-

-			/**

-			 * {@inheritDoc}

-			 * 

-			 * @see org.eclipse.emf.common.util.AbstractEList.EListIterator#previousIndex()

-			 */

-			@Override

-			public int previousIndex() {

-				synchronized(lock) {

-					return super.previousIndex();

-				}

-			}

-

-			/**

-			 * {@inheritDoc}

-			 * 

-			 * @see org.eclipse.emf.common.util.AbstractEList.NonResolvingEListIterator#remove()

-			 */

-			@Override

-			public void remove() {

-				synchronized(lock) {

-					super.remove();

-				}

-			}

-

-			/**

-			 * {@inheritDoc}

-			 * 

-			 * @see org.eclipse.emf.common.util.AbstractEList.NonResolvingEListIterator#set(java.lang.Object)

-			 */

-			@Override

-			public void set(E object) {

-				synchronized(lock) {

-					super.set(object);

-				}

-			}

-

-			/**

-			 * {@inheritDoc}

-			 * 

-			 * @see java.lang.Object#equals(java.lang.Object)

-			 */

-			@Override

-			public boolean equals(Object obj) {

-				synchronized(lock) {

-					return super.equals(obj);

-				}

-			}

-

-			/**

-			 * {@inheritDoc}

-			 * 

-			 * @see java.lang.Object#hashCode()

-			 */

-			@Override

-			public int hashCode() {

-				synchronized(lock) {

-					return super.hashCode();

-				}

-			}

-

-			/**

-			 * {@inheritDoc}

-			 * 

-			 * @see java.lang.Object#toString()

-			 */

-			@Override

-			public String toString() {

-				synchronized(lock) {

-					return super.toString();

-				}

-			}

-

-			/**

-			 * {@inheritDoc}

-			 * 

-			 * @see org.eclipse.emf.common.util.AbstractEList.EListIterator#nextIndex()

-			 */

-			@Override

-			public int nextIndex() {

-				synchronized(lock) {

-					return super.nextIndex();

-				}

-			}

-		}

-	}

-}

+/*******************************************************************************
+ * Copyright (c) 2011, 2013 Obeo.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     Obeo - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.compare.ide.internal.utils;
+
+import com.google.common.annotations.Beta;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+
+import org.eclipse.core.resources.IStorage;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.SubMonitor;
+import org.eclipse.emf.common.notify.NotificationChain;
+import org.eclipse.emf.common.util.AbstractEList;
+import org.eclipse.emf.common.util.AbstractTreeIterator;
+import org.eclipse.emf.common.util.EList;
+import org.eclipse.emf.common.util.TreeIterator;
+import org.eclipse.emf.common.util.URI;
+import org.eclipse.emf.compare.ide.EMFCompareIDEPlugin;
+import org.eclipse.emf.compare.ide.internal.utils.PriorityExecutor.Priority;
+import org.eclipse.emf.compare.ide.utils.ResourceUtil;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EPackage;
+import org.eclipse.emf.ecore.InternalEObject;
+import org.eclipse.emf.ecore.resource.Resource;
+import org.eclipse.emf.ecore.resource.URIConverter;
+import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
+import org.eclipse.emf.ecore.util.InternalEList;
+import org.eclipse.emf.ecore.xmi.XMLResource;
+
+/**
+ * This implementation of a ResourceSet will avoid loading of any resource from any other mean than
+ * {@link #resolveAll()}. Furthermore, it will unload any resource it has loaded as soon as its finished with
+ * the cross reference links resolving.
+ * <p>
+ * This is used from our EMFSynchronizationModel in order to resolve the traversals without keeping the whole
+ * model in-memory (and striving to never have it in-memory as a whole).
+ * </p>
+ * <p>
+ * Since this class only aims at resolving cross-resource dependencies, its main bottleneck is the parsing of
+ * resources when loading (not even the I/O, but the time spent in the SAX parser). We're using a number of
+ * tricks to make this bottleneck less problematic. The main improvement in loading performance when compared
+ * with the usual resource sets is the threading of the load and unload operations. {@link ResourceLoader}
+ * threads are used to load the files and parse them as EMF models. When they're done, they spawn their own
+ * {@link #unload(Resource) sub-threads} to unload the models in separate threads.
+ * </p>
+ * <p>
+ * The second improvement of loading performance comes from the specialization of {@link #getLoadOptions()}
+ * that allows us to define a set of options that aims at speeding up the parsing process. Further profiling
+ * might be needed to isolate other options that would have an impact, such as parser features or XML
+ * options...
+ * </p>
+ * <p>
+ * Finally, the humongous CacheAdapter of UML was causing serious issues. Not only did it hinder the
+ * performance, but it also caused a random dead lock between our unloading and loading threads. We managed to
+ * totally disable it through three means.
+ * <ul>
+ * <li>The use of the {@link XMLResource#OPTION_DISABLE_NOTIFY} load option.</li>
+ * <li>The use of our own {@link NoNotificationParserPool parser pool} that does not re-enable notifications
+ * at the end of loading.</li>
+ * <li>The removal of all roots from their containing {@link Resource} during iteration when
+ * {@link #resolve(Resource) resolving}.</li>
+ * </ul>
+ * </p>
+ * 
+ * @author <a href="mailto:laurent.goubet@obeo.fr">Laurent Goubet</a>
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+@Beta
+public class SyncResourceSet extends ResourceSetImpl {
+	/**
+	 * Keeps track of the URIs that have been demanded by the resolving of a resource. This cache will be
+	 * invalidated when we start resolving this new set of resources.
+	 */
+	private final Set<URI> demandedURIs = Sets.newLinkedHashSet();
+
+	/** Keeps track of the URIs of all resources that have been loaded by this resource set. */
+	private final Set<URI> loadedURIs = Sets.newLinkedHashSet();
+
+	/** Associates URIs with their resources. */
+	private final Map<URI, Resource> uriCache = Maps.newConcurrentMap();
+
+	/**
+	 * This thread pool will be used to launch the loading and unloading of resources in separate threads.
+	 * <p>
+	 * Take note that the unloading threads will take precedence over the loading threads : we need to free
+	 * the memory as soon as possible, and we expect "unload" threads to complete faster that "load" ones.
+	 * </p>
+	 */
+	private final PriorityExecutor pool = new PriorityExecutor("ModelResolver"); //$NON-NLS-1$
+
+	/**
+	 * Default constructor.
+	 */
+	public SyncResourceSet() {
+		// initialize from here to avoid synchronization
+		resources = new SynchronizedResourcesEList<Resource>();
+		loadOptions = super.getLoadOptions();
+		/*
+		 * This resource set is specifically designed to resolve cross resources links, it thus spends a lot
+		 * of time loading resources. The following set of options is what seems to give the most significant
+		 * boost in loading performances, though I did not fine-tune what's really needed here. Take note that
+		 * the use of our own parser pool along with the disabling of notifications is what allows us to
+		 * bypass UML's CacheAdapter and the potential dead locks it causes.
+		 */
+		loadOptions.put(XMLResource.OPTION_USE_PARSER_POOL, new NoNotificationParserPool());
+		loadOptions.put(XMLResource.OPTION_USE_DEPRECATED_METHODS, Boolean.FALSE);
+		loadOptions.put(XMLResource.OPTION_DISABLE_NOTIFY, Boolean.TRUE);
+
+		final int bufferSize = 16384;
+		final Map<String, Object> parserProperties = Maps.newHashMap();
+		parserProperties.put("http://apache.org/xml/properties/input-buffer-size", Integer //$NON-NLS-1$
+				.valueOf(bufferSize));
+		loadOptions.put(XMLResource.OPTION_PARSER_PROPERTIES, parserProperties);
+
+		// These two might be superfluous
+		loadOptions.put(XMLResource.OPTION_DEFER_IDREF_RESOLUTION, Boolean.TRUE);
+
+		/*
+		 * We don't use XMLResource.OPTION_USE_XML_NAME_TO_FEATURE_MAP whereas it could bring performance
+		 * improvements because we are loading the resources concurrently and this map could be used (put and
+		 * get) by several threads. Passing a ConcurrentMap here is not an option either as EMF sometimes
+		 * needs to put "null" values in there. see https://bugs.eclipse.org/bugs/show_bug.cgi?id=403425 for
+		 * more details.
+		 */
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see org.eclipse.emf.ecore.resource.impl.ResourceSetImpl#getResource(org.eclipse.emf.common.util.URI,
+	 *      boolean)
+	 */
+	@Override
+	public Resource getResource(URI uri, boolean loadOnDemand) {
+		// Never load resources from here... But we can't simply return "null" if the resource has already
+		// been loaded once, since the XMLHandler would recursively call this till the stack overflow
+		// otherwise.
+		Resource demanded = uriCache.get(uri);
+		if (!loadedURIs.contains(uri) && demanded == null) {
+			final EPackage ePackage = getPackageRegistry().getEPackage(uri.toString());
+			if (ePackage != null) {
+				demanded = ePackage.eResource();
+				uriCache.put(uri, demanded);
+			} else {
+				synchronized(demandedURIs) {
+					demandedURIs.add(uri);
+				}
+			}
+		}
+		return demanded;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see org.eclipse.emf.ecore.resource.impl.ResourceSetImpl#createResource(org.eclipse.emf.common.util.URI)
+	 */
+	@Override
+	public synchronized Resource createResource(URI uri) {
+		final Resource created = super.createResource(uri);
+		uriCache.put(uri, created);
+		return created;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see org.eclipse.emf.ecore.resource.impl.ResourceSetImpl#createResource(org.eclipse.emf.common.util.URI,
+	 *      java.lang.String)
+	 */
+	@Override
+	public synchronized Resource createResource(URI uri, String contentType) {
+		final Resource created = super.createResource(uri, contentType);
+		uriCache.put(uri, created);
+		return created;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see org.eclipse.emf.ecore.resource.impl.ResourceSetImpl#getResources()
+	 */
+	@Override
+	public EList<Resource> getResources() {
+		return resources;
+	}
+
+	/**
+	 * Loads the given URI as an EMF resource.
+	 * 
+	 * @param uri
+	 *            The URI to load as a resource.
+	 * @return The loaded Resource.
+	 */
+	protected Resource loadResource(URI uri) {
+		/*
+		 * Don't use super.getResource : we know the resource does not exist yet as there will only be one
+		 * "load" call for each given URI. The super implementation iterates over loaded resources before
+		 * doing any actual work. That causes some minimal overhead but, more importantly, it can generate
+		 * concurrent modification exceptions.
+		 */
+		final URIConverter theURIConverter = getURIConverter();
+		final URI normalizedURI = theURIConverter.normalize(uri);
+
+		Resource result = uriCache.get(normalizedURI);
+		if (result == null) {
+			result = delegatedGetResource(uri, true);
+			if (result != null) {
+				uriCache.put(uri, result);
+			}
+		}
+
+		if (result == null) {
+			result = demandCreateResource(uri);
+			if (result == null) {
+				// copy/pasted from super.getResource
+				throw new RuntimeException("Cannot create a resource for '" + uri //$NON-NLS-1$
+						+ "'; a registered resource factory is needed"); //$NON-NLS-1$
+			}
+			demandLoadHelper(result);
+		}
+		return result;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see org.eclipse.emf.ecore.resource.impl.ResourceSetImpl#getLoadOptions()
+	 */
+	@Override
+	public Map<Object, Object> getLoadOptions() {
+		return loadOptions;
+	}
+
+	/**
+	 * Resolve all cross resources links of the given starting point. Take note that this resource set is only
+	 * interested in the URIs of the resources, and that it will not keep the loaded content in memory. No
+	 * resource will be kept in the {@link #getResources() resources'} list of this set.
+	 * 
+	 * @param start
+	 *            The starting point from which we'll resolve cross resources references.
+	 * @param monitor
+	 *            the monitor to which progress will be reported
+	 * @return <code>true</code> if we could resolve the model, <code>false</code> if there was an error
+	 *         loading the starting point.
+	 */
+	public boolean resolveAll(IStorage start, IProgressMonitor monitor) {
+		final boolean result;
+		final URI expectedURI = ResourceUtil.createURIFor(start);
+		if (loadedURIs.contains(expectedURI)) {
+			result = true;
+		} else {
+			SubMonitor progress = SubMonitor.convert(monitor, 100);
+			final Resource resource = loadResource(expectedURI);
+			if (resource == null || !resource.getErrors().isEmpty()) {
+				result = false;
+			} else {
+				progress.worked(2);
+
+				// reset the demanded URI that was added by this first call
+				demandedURIs.clear();
+				// and make it "loaded" instead
+				loadedURIs.add(resource.getURI());
+
+				resolve(resource, progress.newChild(2));
+				unload(resource, progress.newChild(2));
+
+				final int remainingWork = 100 - 2 - 2 - 2;
+				resolveAll(progress.newChild(remainingWork));
+
+				result = true;
+			}
+		}
+		return result;
+	}
+
+	/**
+	 * Resolve all cross resources links of the resource located at the given URI. Take note that this
+	 * resource set is only interested in the URIs of the resource, and that it will not keep the loaded
+	 * content in memory. No resource will be kept in the {@link #getResources() resources'} list of this set.
+	 * 
+	 * @param resourceUri
+	 *            The URI of the "starting" resource from which we'll resolve all cross resources references.
+	 * @param monitor
+	 *            the monitor to which progress will be reported
+	 */
+	public void resolveAll(URI resourceUri, IProgressMonitor monitor) {
+		SubMonitor subMonitor = SubMonitor.convert(monitor, 100);
+		Resource resource = super.getResource(resourceUri, true);
+		// reset the demanded URI that was added by this first call
+		demandedURIs.clear();
+		// and make it "loaded" instead
+		loadedURIs.add(resourceUri);
+
+		resolve(resource, subMonitor.newChild(2));
+		unload(resource, subMonitor.newChild(2));
+
+		final int remainingWork = 100 - 2 - 2;
+		resolveAll(subMonitor.newChild(remainingWork));
+	}
+
+	/**
+	 * We've loaded a first resource (from one of the {@link #resolveAll(IStorage)} or
+	 * {@link #resolveAll(URI)} calls). We will now resolve all of this starting point's cross resources
+	 * references.
+	 * 
+	 * @param monitor
+	 *            the monitor to which progress will be reported
+	 */
+	private void resolveAll(IProgressMonitor monitor) {
+		// no need to size this monitor as it will just report logarithmic progress (see javadoc)
+		final SubMonitor progress = SubMonitor.convert(monitor);
+		Set<URI> newURIs;
+		synchronized(demandedURIs) {
+			newURIs = new LinkedHashSet<URI>(demandedURIs);
+			demandedURIs.clear();
+		}
+		while (!newURIs.isEmpty()) {
+			// report logarithmic progress (see SubMonitor javadoc)
+			progress.setWorkRemaining(10000);
+			loadedURIs.addAll(newURIs);
+			final Set<Future<Object>> resolveThreads = Sets.newLinkedHashSet();
+			for (URI uri : newURIs) {
+				resolveThreads.add(pool.submit(new ResourceLoader(uri, progress.newChild(1)), Priority.LOW));
+			}
+			for (Future<Object> future : resolveThreads) {
+				try {
+					future.get();
+				} catch (InterruptedException e) {
+					// Ignore
+				} catch (ExecutionException e) {
+					// TODO does this need to be logged when the underlying exception is IO?
+					final IStatus status = new Status(IStatus.WARNING, EMFCompareIDEPlugin.PLUGIN_ID, e
+							.getMessage(), e);
+					EMFCompareIDEPlugin.getDefault().getLog().log(status);
+				}
+			}
+			synchronized(demandedURIs) {
+				newURIs = new LinkedHashSet<URI>(demandedURIs);
+				demandedURIs.clear();
+			}
+		}
+	}
+
+	/**
+	 * This will resolve all cross references of the given resource, never actually loading other resources
+	 * (their URIs are collected within {@link #demandedURIs}.
+	 * 
+	 * @param resource
+	 *            The resource for which we are to resolve all cross references.
+	 * @param monitor
+	 *            The monitor to which progress will be reported.
+	 */
+	private void resolve(Resource resource, IProgressMonitor monitor) {
+		resource.eSetDeliver(false);
+		final List<EObject> roots = ((InternalEList<EObject>)resource.getContents()).basicList();
+		final Iterator<EObject> resourceContent = roots.iterator();
+		resource.getContents().clear();
+
+		SubMonitor subMonitor = SubMonitor.convert(monitor, roots.size());
+		while (resourceContent.hasNext()) {
+			final EObject eObject = resourceContent.next();
+			resolveCrossReferences(resource, eObject);
+			final TreeIterator<EObject> childContent = basicEAllContents(eObject);
+			// the process of one root is one tick
+			SubMonitor childMonitor = subMonitor.newChild(1);
+			while (childContent.hasNext()) {
+				// report logarithmic progress for each root processing (see javadoc)
+				childMonitor.setWorkRemaining(10000);
+				final EObject child = childContent.next();
+				if (child.eIsProxy()) {
+					resolveCrossReference(resource, child);
+				} else {
+					resolveCrossReferences(resource, child);
+				}
+				// report logarithmic progress (see javadoc)
+				childMonitor.worked(1);
+			}
+		}
+		resource.getContents().addAll(roots);
+	}
+
+	/**
+	 * Resolve a given proxy's reference. This will only be called on proxy EObjects (
+	 * <code>proxy.eIsProxy()</code> is true).
+	 * 
+	 * @param resource
+	 *            Resource containing this proxy.
+	 * @param proxy
+	 *            The proxy to resolve.
+	 */
+	protected void resolveCrossReference(Resource resource, EObject proxy) {
+		final URI proxyURI = ((InternalEObject)proxy).eProxyURI();
+		getResource(proxyURI.trimFragment(), false);
+	}
+
+	/**
+	 * An implementation of {@link EObject#eAllContents()} that will not resolve its proxies.
+	 * 
+	 * @param eObject
+	 *            The eobject for which contents we need an iterator.
+	 * @return The created {@link TreeIterator}.
+	 */
+	private TreeIterator<EObject> basicEAllContents(final EObject eObject) {
+		return new AbstractTreeIterator<EObject>(eObject, false) {
+			/** Generated SUID. */
+			private static final long serialVersionUID = 6874121606163401152L;
+
+			/**
+			 * {@inheritDoc}
+			 * 
+			 * @see org.eclipse.emf.common.util.AbstractTreeIterator#getChildren(java.lang.Object)
+			 */
+			@Override
+			public Iterator<EObject> getChildren(Object obj) {
+				return ((InternalEList<EObject>)((EObject)obj).eContents()).basicIterator();
+			}
+		};
+	}
+
+	/**
+	 * Unload the given resource.
+	 * 
+	 * @param resource
+	 *            The resource we are to unload.
+	 * @param monitor
+	 *            The monitor to which progress will be reported.
+	 */
+	private void unload(final Resource resource, IProgressMonitor monitor) {
+		final SubMonitor subMonitor = SubMonitor.convert(monitor, 1);
+		// only unload those resources that are located in the workspace
+		final URI uri = resource.getURI();
+		if (uri.isPlatformResource() || uri.isRelative() || uri.isFile()) {
+			uriCache.remove(uri);
+			getResources().remove(resource);
+
+			// Only "unload()" when needed... The one we know of is UML
+			if (resource.getClass().getSimpleName().startsWith("UMLResource")) { //$NON-NLS-1$
+				// We still need to unload what we loaded since some (like UML) cross reference everything...
+				final Runnable unloader = new Runnable() {
+					public void run() {
+						resource.unload();
+						subMonitor.worked(1);
+					}
+				};
+				pool.submit(unloader, Priority.NORMAL);
+			}
+		}
+	}
+
+	/**
+	 * Resolves the cross references of the given EObject.
+	 * 
+	 * @param resource
+	 *            Resource containing this EObject.
+	 * @param eObject
+	 *            The EObject for which we are to resolve the cross references.
+	 */
+	private void resolveCrossReferences(Resource resource, EObject eObject) {
+		final Iterator<EObject> objectChildren = ((InternalEList<EObject>)eObject.eCrossReferences())
+				.basicIterator();
+		while (objectChildren.hasNext()) {
+			final EObject eObj = objectChildren.next();
+			if (eObj.eIsProxy()) {
+				resolveCrossReference(resource, eObj);
+			}
+		}
+	}
+
+	/**
+	 * This implementation of a {@link Runnable} will be used to load a given uri from the disk as an EMF
+	 * {@link Resource} and resolve all of its cross-resource links (these will be stored in
+	 * {@link #demandedURIs} as we go). Once done, it will spawn another thread in order to unload that
+	 * resource out of the memory.
+	 * 
+	 * @author <a href="mailto:laurent.goubet@obeo.fr">Laurent Goubet</a>
+	 */
+	private class ResourceLoader implements Runnable {
+		/** The uri of the EMF Resource we are to load from the disk. */
+		private final URI uri;
+
+		/** The monitor to which progress will be reported. */
+		private final SubMonitor subMonitor;
+
+		/**
+		 * Constructs our loader thread given its target URI.
+		 * 
+		 * @param uri
+		 *            The uri of the EMF Resource this thread is to load from the disk.
+		 * @param monitor
+		 *            The monitor to which progress will be reported.
+		 */
+		public ResourceLoader(URI uri, IProgressMonitor monitor) {
+			this.uri = uri;
+			this.subMonitor = SubMonitor.convert(monitor, 2);
+		}
+
+		/**
+		 * {@inheritDoc}
+		 * 
+		 * @see java.lang.Runnable#run()
+		 */
+		public void run() {
+			final Resource newResource = loadResource(uri);
+			resolve(newResource, subMonitor.newChild(1));
+			unload(newResource, subMonitor.newChild(1));
+		}
+	}
+
+	/**
+	 * A synchronized implementation of {@link ResourcesEList}.
+	 * <p>
+	 * Note that this cannot be extracted out of the {@link SyncResourceSet} since the {@link ResourcesEList}
+	 * type is not visible.
+	 * </p>
+	 * 
+	 * @param <E>
+	 *            Type of this list's contents.
+	 * @author <a href="mailto:laurent.goubet@obeo.fr">Laurent Goubet</a>
+	 */
+	private class SynchronizedResourcesEList<E extends Object & Resource> extends ResourcesEList<E> {
+		/** Generated SUID. */
+		private static final long serialVersionUID = 7371376112881960414L;
+
+		/** The lock we'll use for synchronization of the resources list. */
+		private final Object lock = new Object();
+
+		/**
+		 * {@inheritDoc}
+		 * 
+		 * @see java.util.AbstractCollection#containsAll(java.util.Collection)
+		 */
+		@Override
+		public boolean containsAll(Collection<?> c) {
+			synchronized(lock) {
+				return super.containsAll(c);
+			}
+		}
+
+		/**
+		 * {@inheritDoc}
+		 * 
+		 * @see org.eclipse.emf.common.util.AbstractEList#set(int, java.lang.Object)
+		 */
+		@Override
+		public E set(int index, E object) {
+			synchronized(lock) {
+				return super.set(index, object);
+			}
+		}
+
+		/**
+		 * {@inheritDoc}
+		 * 
+		 * @see org.eclipse.emf.common.util.AbstractEList#add(java.lang.Object)
+		 */
+		@Override
+		public boolean add(E object) {
+			synchronized(lock) {
+				return super.add(object);
+			}
+		}
+
+		/**
+		 * {@inheritDoc}
+		 * 
+		 * @see org.eclipse.emf.common.util.AbstractEList#add(int, java.lang.Object)
+		 */
+		@Override
+		public void add(int index, E object) {
+			synchronized(lock) {
+				super.add(index, object);
+			}
+		}
+
+		/**
+		 * {@inheritDoc}
+		 * 
+		 * @see org.eclipse.emf.common.util.AbstractEList#addAll(java.util.Collection)
+		 */
+		@Override
+		public boolean addAll(Collection<? extends E> collection) {
+			synchronized(lock) {
+				return super.addAll(collection);
+			}
+		}
+
+		/**
+		 * {@inheritDoc}
+		 * 
+		 * @see org.eclipse.emf.common.util.AbstractEList#addAll(int, java.util.Collection)
+		 */
+		@Override
+		public boolean addAll(int index, Collection<? extends E> collection) {
+			synchronized(lock) {
+				return super.addAll(index, collection);
+			}
+		}
+
+		/**
+		 * {@inheritDoc}
+		 * 
+		 * @see org.eclipse.emf.common.util.AbstractEList#remove(java.lang.Object)
+		 */
+		@Override
+		public boolean remove(Object object) {
+			synchronized(lock) {
+				return super.remove(object);
+			}
+		}
+
+		/**
+		 * {@inheritDoc}
+		 * 
+		 * @see org.eclipse.emf.common.util.AbstractEList#retainAll(java.util.Collection)
+		 */
+		@Override
+		public boolean retainAll(Collection<?> collection) {
+			synchronized(lock) {
+				return super.retainAll(collection);
+			}
+		}
+
+		/**
+		 * {@inheritDoc}
+		 * 
+		 * @see org.eclipse.emf.common.util.AbstractEList#move(int, java.lang.Object)
+		 */
+		@Override
+		public void move(int index, E object) {
+			synchronized(lock) {
+				super.move(index, object);
+			}
+		}
+
+		/**
+		 * {@inheritDoc}
+		 * 
+		 * @see org.eclipse.emf.common.util.AbstractEList#equals(java.lang.Object)
+		 */
+		@Override
+		public boolean equals(Object object) {
+			synchronized(lock) {
+				return super.equals(object);
+			}
+		}
+
+		/**
+		 * {@inheritDoc}
+		 * 
+		 * @see org.eclipse.emf.common.util.AbstractEList#hashCode()
+		 */
+		@Override
+		public int hashCode() {
+			synchronized(lock) {
+				return super.hashCode();
+			}
+		}
+
+		/**
+		 * {@inheritDoc}
+		 * 
+		 * @see org.eclipse.emf.common.util.AbstractEList#toString()
+		 */
+		@Override
+		public String toString() {
+			synchronized(lock) {
+				return super.toString();
+			}
+		}
+
+		/**
+		 * {@inheritDoc}
+		 * 
+		 * @see org.eclipse.emf.common.util.AbstractEList#iterator()
+		 */
+		@Override
+		public Iterator<E> iterator() {
+			return new SynchronizedEIterator();
+		}
+
+		/**
+		 * {@inheritDoc}
+		 * 
+		 * @see org.eclipse.emf.common.util.AbstractEList#listIterator()
+		 */
+		@Override
+		public ListIterator<E> listIterator() {
+			return new SynchronizedEListIterator();
+		}
+
+		/**
+		 * {@inheritDoc}
+		 * 
+		 * @see org.eclipse.emf.common.util.AbstractEList#listIterator(int)
+		 */
+		@Override
+		public ListIterator<E> listIterator(int index) {
+			synchronized(lock) {
+				int curSize = size();
+				if (index < 0 || index > curSize) {
+					throw new BasicIndexOutOfBoundsException(index, curSize);
+				}
+				return new SynchronizedEListIterator(index);
+			}
+		}
+
+		/**
+		 * {@inheritDoc}
+		 * 
+		 * @see org.eclipse.emf.common.util.BasicEList#indexOf(java.lang.Object)
+		 */
+		@Override
+		public int indexOf(Object object) {
+			synchronized(lock) {
+				return super.indexOf(object);
+			}
+		}
+
+		/**
+		 * {@inheritDoc}
+		 * 
+		 * @see org.eclipse.emf.common.util.BasicEList#lastIndexOf(java.lang.Object)
+		 */
+		@Override
+		public int lastIndexOf(Object object) {
+			synchronized(lock) {
+				return super.lastIndexOf(object);
+			}
+		}
+
+		/**
+		 * {@inheritDoc}
+		 * 
+		 * @see org.eclipse.emf.common.util.BasicEList#toArray()
+		 */
+		@Override
+		public Object[] toArray() {
+			synchronized(lock) {
+				return super.toArray();
+			}
+		}
+
+		/**
+		 * {@inheritDoc}
+		 * 
+		 * @see org.eclipse.emf.common.util.BasicEList#toArray(T[])
+		 */
+		@Override
+		public <T> T[] toArray(T[] array) {
+			synchronized(lock) {
+				return super.toArray(array);
+			}
+		}
+
+		/**
+		 * {@inheritDoc}
+		 * 
+		 * @see org.eclipse.emf.common.util.BasicEList#setData(int, java.lang.Object[])
+		 */
+		@Override
+		public void setData(int size, Object[] data) {
+			synchronized(lock) {
+				super.setData(size, data);
+			}
+		}
+
+		/**
+		 * {@inheritDoc}
+		 * 
+		 * @see org.eclipse.emf.common.util.BasicEList#get(int)
+		 */
+		@Override
+		public E get(int index) {
+			synchronized(lock) {
+				return super.get(index);
+			}
+		}
+
+		/**
+		 * {@inheritDoc}
+		 * 
+		 * @see org.eclipse.emf.common.util.BasicEList#basicGet(int)
+		 */
+		@Override
+		public E basicGet(int index) {
+			synchronized(lock) {
+				return super.basicGet(index);
+			}
+		}
+
+		/**
+		 * {@inheritDoc}
+		 * 
+		 * @see org.eclipse.emf.common.util.BasicEList#shrink()
+		 */
+		@Override
+		public void shrink() {
+			synchronized(lock) {
+				super.shrink();
+			}
+		}
+
+		/**
+		 * {@inheritDoc}
+		 * 
+		 * @see org.eclipse.emf.common.util.BasicEList#grow(int)
+		 */
+		@Override
+		public void grow(int minimumCapacity) {
+			synchronized(lock) {
+				super.grow(minimumCapacity);
+			}
+		}
+
+		/**
+		 * {@inheritDoc}
+		 * 
+		 * @see org.eclipse.emf.common.util.BasicEList#clone()
+		 */
+		// CHECKSTYLE:OFF we're overriding...
+		@Override
+		public Object clone() {
+			// CHECKSTYLE:ON
+			synchronized(lock) {
+				return super.clone();
+			}
+		}
+
+		/**
+		 * {@inheritDoc}
+		 * 
+		 * @see org.eclipse.emf.common.notify.impl.NotifyingListImpl#addUnique(java.lang.Object)
+		 */
+		@Override
+		public void addUnique(E object) {
+			synchronized(lock) {
+				super.addUnique(object);
+			}
+		}
+
+		/**
+		 * {@inheritDoc}
+		 * 
+		 * @see org.eclipse.emf.common.notify.impl.NotifyingListImpl#addUnique(int, java.lang.Object)
+		 */
+		@Override
+		public void addUnique(int index, E object) {
+			synchronized(lock) {
+				super.addUnique(index, object);
+			}
+		}
+
+		/**
+		 * {@inheritDoc}
+		 * 
+		 * @see org.eclipse.emf.common.notify.impl.NotifyingListImpl#addAllUnique(java.util.Collection)
+		 */
+		@Override
+		public boolean addAllUnique(Collection<? extends E> collection) {
+			synchronized(lock) {
+				return super.addAllUnique(collection);
+			}
+		}
+
+		/**
+		 * {@inheritDoc}
+		 * 
+		 * @see org.eclipse.emf.common.notify.impl.NotifyingListImpl#addAllUnique(int, java.util.Collection)
+		 */
+		@Override
+		public boolean addAllUnique(int index, Collection<? extends E> collection) {
+			synchronized(lock) {
+				return super.addAllUnique(index, collection);
+			}
+		}
+
+		/**
+		 * {@inheritDoc}
+		 * 
+		 * @see org.eclipse.emf.common.notify.impl.NotifyingListImpl#addAllUnique(java.lang.Object[], int,
+		 *      int)
+		 */
+		@Override
+		public boolean addAllUnique(Object[] objects, int start, int end) {
+			synchronized(lock) {
+				return super.addAllUnique(objects, start, end);
+			}
+		}
+
+		/**
+		 * {@inheritDoc}
+		 * 
+		 * @see org.eclipse.emf.common.notify.impl.NotifyingListImpl#addAllUnique(int, java.lang.Object[],
+		 *      int, int)
+		 */
+		@Override
+		public boolean addAllUnique(int index, Object[] objects, int start, int end) {
+			synchronized(lock) {
+				return super.addAllUnique(index, objects, start, end);
+			}
+		}
+
+		/**
+		 * {@inheritDoc}
+		 * 
+		 * @see org.eclipse.emf.common.notify.impl.NotifyingListImpl#basicAdd(java.lang.Object,
+		 *      org.eclipse.emf.common.notify.NotificationChain)
+		 */
+		@Override
+		public NotificationChain basicAdd(E object, NotificationChain notifications) {
+			synchronized(lock) {
+				return super.basicAdd(object, notifications);
+			}
+		}
+
+		/**
+		 * {@inheritDoc}
+		 * 
+		 * @see org.eclipse.emf.common.notify.impl.NotifyingListImpl#remove(int)
+		 */
+		@Override
+		public E remove(int index) {
+			synchronized(lock) {
+				return super.remove(index);
+			}
+		}
+
+		/**
+		 * {@inheritDoc}
+		 * 
+		 * @see org.eclipse.emf.common.notify.impl.NotifyingListImpl#removeAll(java.util.Collection)
+		 */
+		@Override
+		public boolean removeAll(Collection<?> collection) {
+			synchronized(lock) {
+				return super.removeAll(collection);
+			}
+		}
+
+		/**
+		 * {@inheritDoc}
+		 * 
+		 * @see org.eclipse.emf.common.notify.impl.NotifyingListImpl#basicRemove(java.lang.Object,
+		 *      org.eclipse.emf.common.notify.NotificationChain)
+		 */
+		@Override
+		public NotificationChain basicRemove(Object object, NotificationChain notifications) {
+			synchronized(lock) {
+				return super.basicRemove(object, notifications);
+			}
+		}
+
+		/**
+		 * {@inheritDoc}
+		 * 
+		 * @see org.eclipse.emf.common.notify.impl.NotifyingListImpl#clear()
+		 */
+		@Override
+		public void clear() {
+			synchronized(lock) {
+				super.clear();
+			}
+		}
+
+		/**
+		 * {@inheritDoc}
+		 * 
+		 * @see org.eclipse.emf.common.notify.impl.NotifyingListImpl#setUnique(int, java.lang.Object)
+		 */
+		@Override
+		public E setUnique(int index, E object) {
+			synchronized(lock) {
+				return super.setUnique(index, object);
+			}
+		}
+
+		/**
+		 * {@inheritDoc}
+		 * 
+		 * @see org.eclipse.emf.common.notify.impl.NotifyingListImpl#basicSet(int, java.lang.Object,
+		 *      org.eclipse.emf.common.notify.NotificationChain)
+		 */
+		@Override
+		public NotificationChain basicSet(int index, E object, NotificationChain notifications) {
+			synchronized(lock) {
+				return super.basicSet(index, object, notifications);
+			}
+		}
+
+		/**
+		 * {@inheritDoc}
+		 * 
+		 * @see org.eclipse.emf.common.notify.impl.NotifyingListImpl#move(int, int)
+		 */
+		@Override
+		public E move(int targetIndex, int sourceIndex) {
+			synchronized(lock) {
+				return super.move(targetIndex, sourceIndex);
+			}
+		}
+
+		/**
+		 * {@inheritDoc}
+		 * 
+		 * @see org.eclipse.emf.ecore.util.NotifyingInternalEListImpl#basicList()
+		 */
+		@Override
+		public List<E> basicList() {
+			synchronized(lock) {
+				return super.basicList();
+			}
+		}
+
+		/**
+		 * {@inheritDoc}
+		 * 
+		 * @see org.eclipse.emf.ecore.util.NotifyingInternalEListImpl#basicIterator()
+		 */
+		@Override
+		public Iterator<E> basicIterator() {
+			return new SynchronizedNonResolvingEIterator();
+		}
+
+		/**
+		 * {@inheritDoc}
+		 * 
+		 * @see org.eclipse.emf.ecore.util.NotifyingInternalEListImpl#basicListIterator()
+		 */
+		@Override
+		public ListIterator<E> basicListIterator() {
+			return new SynchronizedNonResolvingEListIterator();
+		}
+
+		/**
+		 * {@inheritDoc}
+		 * 
+		 * @see org.eclipse.emf.ecore.util.NotifyingInternalEListImpl#basicListIterator(int)
+		 */
+		@Override
+		public ListIterator<E> basicListIterator(int index) {
+			synchronized(lock) {
+				int curSize = size();
+				if (index < 0 || index > curSize) {
+					throw new BasicIndexOutOfBoundsException(index, curSize);
+				}
+				return new SynchronizedNonResolvingEListIterator(index);
+			}
+		}
+
+		/**
+		 * {@inheritDoc}
+		 * 
+		 * @see org.eclipse.emf.ecore.resource.impl.ResourceSetImpl.ResourcesEList#contains(java.lang.Object)
+		 */
+		@Override
+		public boolean contains(Object object) {
+			synchronized(lock) {
+				return super.contains(object);
+			}
+		}
+
+		/**
+		 * {@inheritDoc}
+		 * 
+		 * @see org.eclipse.emf.ecore.util.NotifyingInternalEListImpl#basicContains(java.lang.Object)
+		 */
+		@Override
+		public boolean basicContains(Object object) {
+			synchronized(lock) {
+				return super.basicContains(object);
+			}
+		}
+
+		/**
+		 * {@inheritDoc}
+		 * 
+		 * @see org.eclipse.emf.ecore.util.NotifyingInternalEListImpl#basicContainsAll(java.util.Collection)
+		 */
+		@Override
+		public boolean basicContainsAll(Collection<?> collection) {
+			synchronized(lock) {
+				return super.basicContainsAll(collection);
+			}
+		}
+
+		/**
+		 * {@inheritDoc}
+		 * 
+		 * @see org.eclipse.emf.ecore.util.NotifyingInternalEListImpl#basicIndexOf(java.lang.Object)
+		 */
+
+		@Override
+		public int basicIndexOf(Object object) {
+			synchronized(lock) {
+				return super.basicIndexOf(object);
+			}
+		}
+
+		/**
+		 * {@inheritDoc}
+		 * 
+		 * @see org.eclipse.emf.ecore.util.NotifyingInternalEListImpl#basicLastIndexOf(java.lang.Object)
+		 */
+		@Override
+		public int basicLastIndexOf(Object object) {
+			synchronized(lock) {
+				return super.basicLastIndexOf(object);
+			}
+		}
+
+		/**
+		 * {@inheritDoc}
+		 * 
+		 * @see org.eclipse.emf.ecore.util.NotifyingInternalEListImpl#basicToArray()
+		 */
+		@Override
+		public Object[] basicToArray() {
+			synchronized(lock) {
+				return super.basicToArray();
+			}
+		}
+
+		/**
+		 * {@inheritDoc}
+		 * 
+		 * @see org.eclipse.emf.ecore.util.NotifyingInternalEListImpl#basicToArray(T[])
+		 */
+		@Override
+		public <T> T[] basicToArray(T[] array) {
+			synchronized(lock) {
+				return super.basicToArray(array);
+			}
+		}
+
+		/**
+		 * {@inheritDoc}
+		 * 
+		 * @see org.eclipse.emf.common.util.BasicEList#data()
+		 */
+		@Override
+		public Object[] data() {
+			synchronized(lock) {
+				return super.data();
+			}
+		}
+
+		/**
+		 * {@inheritDoc}
+		 * 
+		 * @see org.eclipse.emf.common.notify.impl.NotifyingListImpl#getFeature()
+		 */
+		@Override
+		public Object getFeature() {
+			synchronized(lock) {
+				return super.getFeature();
+			}
+		}
+
+		/**
+		 * {@inheritDoc}
+		 * 
+		 * @see org.eclipse.emf.ecore.resource.impl.ResourceSetImpl.ResourcesEList#getFeatureID()
+		 */
+		@Override
+		public int getFeatureID() {
+			synchronized(lock) {
+				return super.getFeatureID();
+			}
+		}
+
+		/**
+		 * {@inheritDoc}
+		 * 
+		 * @see org.eclipse.emf.ecore.resource.impl.ResourceSetImpl.ResourcesEList#getNotifier()
+		 */
+		@Override
+		public Object getNotifier() {
+			synchronized(lock) {
+				return super.getNotifier();
+			}
+		}
+
+		/**
+		 * {@inheritDoc}
+		 * 
+		 * @see org.eclipse.emf.common.util.BasicEList#isEmpty()
+		 */
+		@Override
+		public boolean isEmpty() {
+			synchronized(lock) {
+				return super.isEmpty();
+			}
+		}
+
+		/**
+		 * {@inheritDoc}
+		 * 
+		 * @see org.eclipse.emf.common.util.BasicEList#size()
+		 */
+		@Override
+		public int size() {
+			synchronized(lock) {
+				return super.size();
+			}
+		}
+
+		/**
+		 * {@inheritDoc}
+		 * 
+		 * @see java.util.AbstractList#subList(int, int)
+		 */
+		@Override
+		public List<E> subList(int fromIndex, int toIndex) {
+			synchronized(lock) {
+				return super.subList(fromIndex, toIndex);
+			}
+		}
+
+		/**
+		 * A synchronized implementation of the {@link AbstractEList.EIterator}.
+		 * 
+		 * @author <a href="mailto:laurent.goubet@obeo.fr">Laurent Goubet</a>
+		 */
+		private class SynchronizedEIterator extends AbstractEList<E>.EIterator<E> {
+			/**
+			 * {@inheritDoc}
+			 * 
+			 * @see org.eclipse.emf.common.util.AbstractEList.EIterator#hasNext()
+			 */
+			@Override
+			public boolean hasNext() {
+				synchronized(lock) {
+					return super.hasNext();
+				}
+			}
+
+			/**
+			 * {@inheritDoc}
+			 * 
+			 * @see org.eclipse.emf.common.util.AbstractEList.EIterator#next()
+			 */
+			@Override
+			public E next() {
+				synchronized(lock) {
+					return super.next();
+				}
+			}
+
+			/**
+			 * {@inheritDoc}
+			 * 
+			 * @see org.eclipse.emf.common.util.AbstractEList.EIterator#remove()
+			 */
+			@Override
+			public void remove() {
+				synchronized(lock) {
+					super.remove();
+				}
+			}
+
+			/**
+			 * {@inheritDoc}
+			 * 
+			 * @see java.lang.Object#equals(java.lang.Object)
+			 */
+			@Override
+			public boolean equals(Object obj) {
+				synchronized(lock) {
+					return super.equals(obj);
+				}
+			}
+
+			/**
+			 * {@inheritDoc}
+			 * 
+			 * @see java.lang.Object#hashCode()
+			 */
+			@Override
+			public int hashCode() {
+				synchronized(lock) {
+					return super.hashCode();
+				}
+			}
+
+			/**
+			 * {@inheritDoc}
+			 * 
+			 * @see java.lang.Object#toString()
+			 */
+			@Override
+			public String toString() {
+				synchronized(lock) {
+					return super.toString();
+				}
+			}
+		}
+
+		/**
+		 * A synchronized implementation of the {@link AbstractEList.EListIterator}.
+		 * 
+		 * @author <a href="mailto:laurent.goubet@obeo.fr">Laurent Goubet</a>
+		 */
+		private class SynchronizedEListIterator extends AbstractEList<E>.EListIterator<E> {
+			/**
+			 * Delegates to the super constructor.
+			 */
+			public SynchronizedEListIterator() {
+				super();
+			}
+
+			/**
+			 * Delegates to the super constructor.
+			 * 
+			 * @param index
+			 *            Index at which this list iterator should start.
+			 */
+			public SynchronizedEListIterator(int index) {
+				super(index);
+			}
+
+			/**
+			 * {@inheritDoc}
+			 * 
+			 * @see org.eclipse.emf.common.util.AbstractEList.EListIterator#add(java.lang.Object)
+			 */
+			@Override
+			public void add(E object) {
+				synchronized(lock) {
+					super.add(object);
+				}
+			}
+
+			/**
+			 * {@inheritDoc}
+			 * 
+			 * @see org.eclipse.emf.common.util.AbstractEList.EIterator#hasNext()
+			 */
+			@Override
+			public boolean hasNext() {
+				synchronized(lock) {
+					return super.hasNext();
+				}
+			}
+
+			/**
+			 * {@inheritDoc}
+			 * 
+			 * @see org.eclipse.emf.common.util.AbstractEList.EListIterator#hasPrevious()
+			 */
+			@Override
+			public boolean hasPrevious() {
+				synchronized(lock) {
+					return super.hasPrevious();
+				}
+			}
+
+			/**
+			 * {@inheritDoc}
+			 * 
+			 * @see org.eclipse.emf.common.util.AbstractEList.EIterator#next()
+			 */
+			@Override
+			public E next() {
+				synchronized(lock) {
+					return super.next();
+				}
+			}
+
+			/**
+			 * {@inheritDoc}
+			 * 
+			 * @see org.eclipse.emf.common.util.AbstractEList.EListIterator#previous()
+			 */
+			@Override
+			public E previous() {
+				synchronized(lock) {
+					return super.previous();
+				}
+			}
+
+			/**
+			 * {@inheritDoc}
+			 * 
+			 * @see org.eclipse.emf.common.util.AbstractEList.EListIterator#previousIndex()
+			 */
+			@Override
+			public int previousIndex() {
+				synchronized(lock) {
+					return super.previousIndex();
+				}
+			}
+
+			/**
+			 * {@inheritDoc}
+			 * 
+			 * @see org.eclipse.emf.common.util.AbstractEList.EIterator#remove()
+			 */
+			@Override
+			public void remove() {
+				synchronized(lock) {
+					super.remove();
+				}
+			}
+
+			/**
+			 * {@inheritDoc}
+			 * 
+			 * @see org.eclipse.emf.common.util.AbstractEList.EListIterator#set(java.lang.Object)
+			 */
+			@Override
+			public void set(E object) {
+				synchronized(lock) {
+					super.set(object);
+				}
+			}
+
+			/**
+			 * {@inheritDoc}
+			 * 
+			 * @see java.lang.Object#equals(java.lang.Object)
+			 */
+			@Override
+			public boolean equals(Object obj) {
+				synchronized(lock) {
+					return super.equals(obj);
+				}
+			}
+
+			/**
+			 * {@inheritDoc}
+			 * 
+			 * @see java.lang.Object#hashCode()
+			 */
+			@Override
+			public int hashCode() {
+				synchronized(lock) {
+					return super.hashCode();
+				}
+			}
+
+			/**
+			 * {@inheritDoc}
+			 * 
+			 * @see java.lang.Object#toString()
+			 */
+			@Override
+			public String toString() {
+				synchronized(lock) {
+					return super.toString();
+				}
+			}
+
+			/**
+			 * {@inheritDoc}
+			 * 
+			 * @see org.eclipse.emf.common.util.AbstractEList.EListIterator#nextIndex()
+			 */
+			@Override
+			public int nextIndex() {
+				synchronized(lock) {
+					return super.nextIndex();
+				}
+			}
+		}
+
+		/**
+		 * A synchronized implementation of the {@link AbstractEList.NonResolvingEIterator}.
+		 * 
+		 * @author <a href="mailto:laurent.goubet@obeo.fr">Laurent Goubet</a>
+		 */
+		private class SynchronizedNonResolvingEIterator extends AbstractEList<E>.NonResolvingEIterator<E> {
+			/**
+			 * {@inheritDoc}
+			 * 
+			 * @see org.eclipse.emf.common.util.AbstractEList.EIterator#hasNext()
+			 */
+			@Override
+			public boolean hasNext() {
+				synchronized(lock) {
+					return super.hasNext();
+				}
+			}
+
+			/**
+			 * {@inheritDoc}
+			 * 
+			 * @see org.eclipse.emf.common.util.AbstractEList.EIterator#next()
+			 */
+			@Override
+			public E next() {
+				synchronized(lock) {
+					return super.next();
+				}
+			}
+
+			/**
+			 * {@inheritDoc}
+			 * 
+			 * @see org.eclipse.emf.common.util.AbstractEList.NonResolvingEIterator#remove()
+			 */
+			@Override
+			public void remove() {
+				synchronized(lock) {
+					super.remove();
+				}
+			}
+
+			/**
+			 * {@inheritDoc}
+			 * 
+			 * @see java.lang.Object#equals(java.lang.Object)
+			 */
+			@Override
+			public boolean equals(Object obj) {
+				synchronized(lock) {
+					return super.equals(obj);
+				}
+			}
+
+			/**
+			 * {@inheritDoc}
+			 * 
+			 * @see java.lang.Object#hashCode()
+			 */
+			@Override
+			public int hashCode() {
+				synchronized(lock) {
+					return super.hashCode();
+				}
+			}
+
+			/**
+			 * {@inheritDoc}
+			 * 
+			 * @see java.lang.Object#toString()
+			 */
+			@Override
+			public String toString() {
+				synchronized(lock) {
+					return super.toString();
+				}
+			}
+		}
+
+		/**
+		 * A synchronized implementation of the {@link AbstractEList.NonResolvingEListIterator}.
+		 * 
+		 * @author <a href="mailto:laurent.goubet@obeo.fr">Laurent Goubet</a>
+		 */
+		private class SynchronizedNonResolvingEListIterator extends AbstractEList<E>.NonResolvingEListIterator<E> {
+			/**
+			 * Delegates to the super constructor.
+			 */
+			public SynchronizedNonResolvingEListIterator() {
+				super();
+			}
+
+			/**
+			 * Delegates to the super constructor.
+			 * 
+			 * @param index
+			 *            Index at which the iteration should start.
+			 */
+			public SynchronizedNonResolvingEListIterator(int index) {
+				super(index);
+			}
+
+			/**
+			 * {@inheritDoc}
+			 * 
+			 * @see org.eclipse.emf.common.util.AbstractEList.NonResolvingEListIterator#add(java.lang.Object)
+			 */
+			@Override
+			public void add(E object) {
+				synchronized(lock) {
+					super.add(object);
+				}
+			}
+
+			/**
+			 * {@inheritDoc}
+			 * 
+			 * @see org.eclipse.emf.common.util.AbstractEList.EIterator#hasNext()
+			 */
+			@Override
+			public boolean hasNext() {
+				synchronized(lock) {
+					return super.hasNext();
+				}
+			}
+
+			/**
+			 * {@inheritDoc}
+			 * 
+			 * @see org.eclipse.emf.common.util.AbstractEList.EListIterator#hasPrevious()
+			 */
+			@Override
+			public boolean hasPrevious() {
+				synchronized(lock) {
+					return super.hasPrevious();
+				}
+			}
+
+			/**
+			 * {@inheritDoc}
+			 * 
+			 * @see org.eclipse.emf.common.util.AbstractEList.EIterator#next()
+			 */
+			@Override
+			public E next() {
+				synchronized(lock) {
+					return super.next();
+				}
+			}
+
+			/**
+			 * {@inheritDoc}
+			 * 
+			 * @see org.eclipse.emf.common.util.AbstractEList.EListIterator#previous()
+			 */
+			@Override
+			public E previous() {
+				synchronized(lock) {
+					return super.previous();
+				}
+			}
+
+			/**
+			 * {@inheritDoc}
+			 * 
+			 * @see org.eclipse.emf.common.util.AbstractEList.EListIterator#previousIndex()
+			 */
+			@Override
+			public int previousIndex() {
+				synchronized(lock) {
+					return super.previousIndex();
+				}
+			}
+
+			/**
+			 * {@inheritDoc}
+			 * 
+			 * @see org.eclipse.emf.common.util.AbstractEList.NonResolvingEListIterator#remove()
+			 */
+			@Override
+			public void remove() {
+				synchronized(lock) {
+					super.remove();
+				}
+			}
+
+			/**
+			 * {@inheritDoc}
+			 * 
+			 * @see org.eclipse.emf.common.util.AbstractEList.NonResolvingEListIterator#set(java.lang.Object)
+			 */
+			@Override
+			public void set(E object) {
+				synchronized(lock) {
+					super.set(object);
+				}
+			}
+
+			/**
+			 * {@inheritDoc}
+			 * 
+			 * @see java.lang.Object#equals(java.lang.Object)
+			 */
+			@Override
+			public boolean equals(Object obj) {
+				synchronized(lock) {
+					return super.equals(obj);
+				}
+			}
+
+			/**
+			 * {@inheritDoc}
+			 * 
+			 * @see java.lang.Object#hashCode()
+			 */
+			@Override
+			public int hashCode() {
+				synchronized(lock) {
+					return super.hashCode();
+				}
+			}
+
+			/**
+			 * {@inheritDoc}
+			 * 
+			 * @see java.lang.Object#toString()
+			 */
+			@Override
+			public String toString() {
+				synchronized(lock) {
+					return super.toString();
+				}
+			}
+
+			/**
+			 * {@inheritDoc}
+			 * 
+			 * @see org.eclipse.emf.common.util.AbstractEList.EListIterator#nextIndex()
+			 */
+			@Override
+			public int nextIndex() {
+				synchronized(lock) {
+					return super.nextIndex();
+				}
+			}
+		}
+	}
+}
diff --git a/plugins/org.eclipse.emf.compare.rcp.ui/src/org/eclipse/emf/compare/rcp/ui/internal/structuremergeviewer/groups/impl/DifferenceGroupManager.java b/plugins/org.eclipse.emf.compare.rcp.ui/src/org/eclipse/emf/compare/rcp/ui/internal/structuremergeviewer/groups/impl/DifferenceGroupManager.java
index 4d2e8fb..45d936a 100644
--- a/plugins/org.eclipse.emf.compare.rcp.ui/src/org/eclipse/emf/compare/rcp/ui/internal/structuremergeviewer/groups/impl/DifferenceGroupManager.java
+++ b/plugins/org.eclipse.emf.compare.rcp.ui/src/org/eclipse/emf/compare/rcp/ui/internal/structuremergeviewer/groups/impl/DifferenceGroupManager.java
@@ -1,259 +1,259 @@
-/******************************************************************************

- * Copyright (c) 2014 Obeo.

- * All rights reserved. This program and the accompanying materials

- * are made available under the terms of the Eclipse Public License v1.0

- * which accompanies this distribution, and is available at

- * http://www.eclipse.org/legal/epl-v10.html

- * 

- * Contributors:

- *     Obeo - initial API and implementation

- *******************************************************************************/

-package org.eclipse.emf.compare.rcp.ui.internal.structuremergeviewer.groups.impl;

-

-import com.google.common.base.Function;

-import com.google.common.base.Joiner;

-import com.google.common.base.Predicate;

-import com.google.common.collect.Iterables;

-import com.google.common.collect.Lists;

-import com.google.common.collect.Sets;

-import com.google.common.collect.Sets.SetView;

-

-import java.util.Collections;

-import java.util.HashSet;

-import java.util.List;

-

-import org.eclipse.core.runtime.IStatus;

-import org.eclipse.emf.compare.rcp.internal.extension.IItemDescriptor;

-import org.eclipse.emf.compare.rcp.internal.extension.IItemRegistry;

-import org.eclipse.emf.compare.rcp.internal.extension.impl.ItemUtil;

-import org.eclipse.emf.compare.rcp.internal.tracer.TracingConstant;

-import org.eclipse.emf.compare.rcp.ui.EMFCompareRCPUIPlugin;

-import org.eclipse.emf.compare.rcp.ui.structuremergeviewer.groups.IDifferenceGroupProvider;

-import org.eclipse.emf.compare.rcp.ui.structuremergeviewer.groups.IDifferenceGroupProvider.ComparisonType;

-import org.eclipse.emf.compare.rcp.ui.structuremergeviewer.groups.IDifferenceGroupProvider.Descriptor;

-import org.osgi.service.prefs.Preferences;

-

-/**

- * This manager can be used to modify EMF Compare UI behavior regarding groups.

- * <p>

- * This manager can override the rank of groups. For example, it can be used to define a default group that

- * will be used by EMF Compare UI.

- * </p>

- * <p>

- * This manager can define a synchronization behavior between a user selection of group in EMF Compare UI and

- * the default group that is used by EMF Compare UI.

- * </p>

- * 

- * @author <a href="mailto:arthur.daussy@obeo.fr">Arthur Daussy</a>

- */

-public class DifferenceGroupManager {

-

-	/** Predicate for 2-way {@link IDifferenceGroupProvider.Descriptor}. */

-	private static final Predicate<IItemDescriptor<Descriptor>> TWO_WAY_FILTER = new Predicate<IItemDescriptor<Descriptor>>() {

-

-		public boolean apply(IItemDescriptor<Descriptor> descriptor) {

-			if (descriptor == null) {

-				return false;

-			}

-			ComparisonType type = descriptor.getItem().getType();

-			return type == ComparisonType.BOTH || type == ComparisonType.TWO_WAY;

-		}

-	};

-

-	/** Predicate for 3-way {@link IDifferenceGroupProvider.Descriptor}. */

-	private static final Predicate<IItemDescriptor<Descriptor>> THREE_WAY_FILTER = new Predicate<IItemDescriptor<Descriptor>>() {

-

-		public boolean apply(IItemDescriptor<Descriptor> descriptor) {

-			if (descriptor == null) {

-				return false;

-			}

-			ComparisonType type = descriptor.getItem().getType();

-			return type == ComparisonType.BOTH || type == ComparisonType.THREE_WAY;

-		}

-	};

-

-	/** Ordered list of groups for two way comparison. */

-	private static final String TWO_WAY_GROUP_RANKING = "org.eclipse.emf.compare.rcp.ui.groups.2way.ranking"; //$NON-NLS-1$

-

-	/** Ordered list of groups for three way comparison. */

-	private static final String THREE_WAY_GROUP_RANKING = "org.eclipse.emf.compare.rcp.ui.groups.3way.ranking"; //$NON-NLS-1$

-

-	/** Preferences holding preference values. */

-	private final Preferences preferences;

-

-	/** Registry of {@link IDifferenceGroupProvider.Descriptor}. */

-	private final IItemRegistry<IDifferenceGroupProvider.Descriptor> registry;

-

-	/**

-	 * Constructor.

-	 * 

-	 * @param preferences

-	 *            Preferences holding preference values.

-	 * @param registry

-	 *            Registry of {@link IDifferenceGroupProvider.Descriptor}.

-	 */

-	public DifferenceGroupManager(Preferences preferences,

-			IItemRegistry<IDifferenceGroupProvider.Descriptor> registry) {

-		super();

-		this.preferences = preferences;

-		this.registry = registry;

-	}

-

-	/**

-	 * Gets the current value of the group ranking.

-	 * 

-	 * @param preferenceKey

-	 *            Preference key use to retrieve the value in preferences.

-	 * @param defaultOrder

-	 *            The default ranking.

-	 * @return A ordered {@link List} of {@link IItemDescriptor}.

-	 */

-	private List<IItemDescriptor<IDifferenceGroupProvider.Descriptor>> getCurrent(String preferenceKey,

-			List<IItemDescriptor<Descriptor>> defaultOrder) {

-		return getOrderedItems(defaultOrder, registry, preferenceKey);

-	}

-

-	/**

-	 * Gets the current group order.

-	 * 

-	 * @param isThreeWay

-	 *            True if three way comparison, false otherwise.

-	 * @return Ordered {@link List} of {@link IDifferenceGroupProvider.Descriptor}.

-	 */

-	public List<IItemDescriptor<Descriptor>> getCurrentGroupRanking(boolean isThreeWay) {

-		return getCurrent(getGroupPreferenceKey(isThreeWay), getDefaultRankingConfiguration(isThreeWay));

-	}

-

-	/**

-	 * Gets the default groups order.

-	 * 

-	 * @param isThreeWay

-	 *            True if three way comparison, false otherwise.

-	 * @return Ordered {@link List} of {@link IDifferenceGroupProvider.Descriptor}.

-	 */

-	public List<IItemDescriptor<IDifferenceGroupProvider.Descriptor>> getDefaultRankingConfiguration(

-			boolean isThreeWay) {

-		final Iterable<IItemDescriptor<Descriptor>> groups;

-		if (isThreeWay) {

-			groups = Iterables.filter(registry.getItemDescriptors(), THREE_WAY_FILTER);

-		} else {

-

-			groups = Iterables.filter(registry.getItemDescriptors(), TWO_WAY_FILTER);

-		}

-		List<IItemDescriptor<Descriptor>> result = Lists.newArrayList(groups);

-		Collections.sort(result);

-		return result;

-	}

-

-	/**

-	 * Gets the preference key for group ranking.

-	 * 

-	 * @param isThreeWay

-	 *            True if three way comparison.

-	 * @return They key of the group ranking preference for this type of comparison.

-	 */

-	private String getGroupPreferenceKey(boolean isThreeWay) {

-		if (isThreeWay) {

-			return THREE_WAY_GROUP_RANKING;

-		} else {

-			return TWO_WAY_GROUP_RANKING;

-		}

-	}

-

-	/**

-	 * Returns an ordered list of {@link IItemDescriptor}. The order of the list is either defined by the rank

-	 * in the registry or from preference if the rank has been overloaded. If any descriptor has been added or

-	 * removed since last modification of the preference, this method will merge the modification.

-	 * 

-	 * @param orderedDefaultDescriptor

-	 *            List of ordered default {@link IItemDescriptor}.

-	 * @param descriptorRegistry

-	 *            Registry of descriptor.

-	 * @param orderedItemPreferenceKey

-	 *            Key in preferences where are stored the new order of descriptor

-	 * @return Ordered list of descriptor.

-	 * @param <T>

-	 *            Descriptor type.

-	 */

-	private <T> List<IItemDescriptor<T>> getOrderedItems(List<IItemDescriptor<T>> orderedDefaultDescriptor,

-			IItemRegistry<T> descriptorRegistry, String orderedItemPreferenceKey) {

-		List<IItemDescriptor<T>> itemsDescriptor = ItemUtil.getItemsDescriptor(descriptorRegistry,

-				orderedItemPreferenceKey, preferences);

-

-		if (itemsDescriptor == null) {

-			itemsDescriptor = orderedDefaultDescriptor;

-		} else {

-			HashSet<IItemDescriptor<T>> descriptorFromPrefSet = Sets.newLinkedHashSet(itemsDescriptor);

-			HashSet<IItemDescriptor<T>> defaultDescriptorSet = Sets

-					.newLinkedHashSet(orderedDefaultDescriptor);

-

-			// Remove descriptor

-			SetView<IItemDescriptor<T>> descriptorToRemove = Sets.difference(descriptorFromPrefSet,

-					defaultDescriptorSet);

-			Iterables.removeAll(itemsDescriptor, descriptorToRemove);

-

-			// Add new descriptor

-			SetView<IItemDescriptor<T>> descriptorToAdd = Sets.difference(defaultDescriptorSet,

-					descriptorFromPrefSet);

-			Iterables.addAll(itemsDescriptor, descriptorToAdd);

-

-		}

-		return itemsDescriptor;

-	}

-

-	/**

-	 * Sets the ranking of Difference group provider.

-	 * 

-	 * @param descriptors

-	 *            An ordered list of {@link IItemDescriptor}.

-	 * @param isThreeWay

-	 *            True if three way comparison.

-	 */

-	public void setCurrentGroupRanking(List<IItemDescriptor<Descriptor>> descriptors, boolean isThreeWay) {

-		storeInPreferences(getGroupPreferenceKey(isThreeWay), descriptors,

-				getDefaultRankingConfiguration(isThreeWay));

-

-		// Trace preferences values

-		if (TracingConstant.CONFIGURATION_TRACING_ACTIVATED) {

-			StringBuilder builder = new StringBuilder();

-			// Print each preferences

-			builder.append("Preference ").append(getGroupPreferenceKey(isThreeWay)).append(":\n"); //$NON-NLS-1$ //$NON-NLS-2$

-			String preferenceValue = preferences.get(getGroupPreferenceKey(isThreeWay), ""); //$NON-NLS-1$

-			String[] groups = preferenceValue.split(ItemUtil.PREFERENCE_DELIMITER);

-			for (int rank = 0; rank < groups.length; rank++) {

-				builder.append(rank).append(". ").append(groups[rank]).append("\n"); //$NON-NLS-1$ //$NON-NLS-2$

-			}

-			builder.append("\n\n"); //$NON-NLS-1$

-			EMFCompareRCPUIPlugin.getDefault().log(IStatus.INFO, builder.toString());

-		}

-	}

-

-	/**

-	 * Stores the value into preferences.

-	 * 

-	 * @param preferenceKey

-	 *            Key of the preference

-	 * @param currentValue

-	 *            Current value to store

-	 * @param defaultConf

-	 *            Default value

-	 */

-	private void storeInPreferences(String preferenceKey,

-			List<IItemDescriptor<IDifferenceGroupProvider.Descriptor>> currentValue,

-			List<IItemDescriptor<IDifferenceGroupProvider.Descriptor>> defaultConf) {

-		if (currentValue != null && !currentValue.equals(defaultConf)) {

-			Iterable<String> currentIDs = Iterables.transform(currentValue,

-					new Function<IItemDescriptor<IDifferenceGroupProvider.Descriptor>, String>() {

-

-						public String apply(IItemDescriptor<IDifferenceGroupProvider.Descriptor> arg0) {

-							return arg0.getID();

-						}

-					});

-			String preferenceValue = Joiner.on(ItemUtil.PREFERENCE_DELIMITER).join(currentIDs);

-			preferences.put(preferenceKey, preferenceValue);

-		} else {

-			preferences.remove(preferenceKey);

-		}

-	}

-

-}

+/******************************************************************************
+ * Copyright (c) 2014 Obeo.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     Obeo - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.compare.rcp.ui.internal.structuremergeviewer.groups.impl;
+
+import com.google.common.base.Function;
+import com.google.common.base.Joiner;
+import com.google.common.base.Predicate;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+import com.google.common.collect.Sets.SetView;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.emf.compare.rcp.internal.extension.IItemDescriptor;
+import org.eclipse.emf.compare.rcp.internal.extension.IItemRegistry;
+import org.eclipse.emf.compare.rcp.internal.extension.impl.ItemUtil;
+import org.eclipse.emf.compare.rcp.internal.tracer.TracingConstant;
+import org.eclipse.emf.compare.rcp.ui.EMFCompareRCPUIPlugin;
+import org.eclipse.emf.compare.rcp.ui.structuremergeviewer.groups.IDifferenceGroupProvider;
+import org.eclipse.emf.compare.rcp.ui.structuremergeviewer.groups.IDifferenceGroupProvider.ComparisonType;
+import org.eclipse.emf.compare.rcp.ui.structuremergeviewer.groups.IDifferenceGroupProvider.Descriptor;
+import org.osgi.service.prefs.Preferences;
+
+/**
+ * This manager can be used to modify EMF Compare UI behavior regarding groups.
+ * <p>
+ * This manager can override the rank of groups. For example, it can be used to define a default group that
+ * will be used by EMF Compare UI.
+ * </p>
+ * <p>
+ * This manager can define a synchronization behavior between a user selection of group in EMF Compare UI and
+ * the default group that is used by EMF Compare UI.
+ * </p>
+ * 
+ * @author <a href="mailto:arthur.daussy@obeo.fr">Arthur Daussy</a>
+ */
+public class DifferenceGroupManager {
+
+	/** Predicate for 2-way {@link IDifferenceGroupProvider.Descriptor}. */
+	private static final Predicate<IItemDescriptor<Descriptor>> TWO_WAY_FILTER = new Predicate<IItemDescriptor<Descriptor>>() {
+
+		public boolean apply(IItemDescriptor<Descriptor> descriptor) {
+			if (descriptor == null) {
+				return false;
+			}
+			ComparisonType type = descriptor.getItem().getType();
+			return type == ComparisonType.BOTH || type == ComparisonType.TWO_WAY;
+		}
+	};
+
+	/** Predicate for 3-way {@link IDifferenceGroupProvider.Descriptor}. */
+	private static final Predicate<IItemDescriptor<Descriptor>> THREE_WAY_FILTER = new Predicate<IItemDescriptor<Descriptor>>() {
+
+		public boolean apply(IItemDescriptor<Descriptor> descriptor) {
+			if (descriptor == null) {
+				return false;
+			}
+			ComparisonType type = descriptor.getItem().getType();
+			return type == ComparisonType.BOTH || type == ComparisonType.THREE_WAY;
+		}
+	};
+
+	/** Ordered list of groups for two way comparison. */
+	private static final String TWO_WAY_GROUP_RANKING = "org.eclipse.emf.compare.rcp.ui.groups.2way.ranking"; //$NON-NLS-1$
+
+	/** Ordered list of groups for three way comparison. */
+	private static final String THREE_WAY_GROUP_RANKING = "org.eclipse.emf.compare.rcp.ui.groups.3way.ranking"; //$NON-NLS-1$
+
+	/** Preferences holding preference values. */
+	private final Preferences preferences;
+
+	/** Registry of {@link IDifferenceGroupProvider.Descriptor}. */
+	private final IItemRegistry<IDifferenceGroupProvider.Descriptor> registry;
+
+	/**
+	 * Constructor.
+	 * 
+	 * @param preferences
+	 *            Preferences holding preference values.
+	 * @param registry
+	 *            Registry of {@link IDifferenceGroupProvider.Descriptor}.
+	 */
+	public DifferenceGroupManager(Preferences preferences,
+			IItemRegistry<IDifferenceGroupProvider.Descriptor> registry) {
+		super();
+		this.preferences = preferences;
+		this.registry = registry;
+	}
+
+	/**
+	 * Gets the current value of the group ranking.
+	 * 
+	 * @param preferenceKey
+	 *            Preference key use to retrieve the value in preferences.
+	 * @param defaultOrder
+	 *            The default ranking.
+	 * @return A ordered {@link List} of {@link IItemDescriptor}.
+	 */
+	private List<IItemDescriptor<IDifferenceGroupProvider.Descriptor>> getCurrent(String preferenceKey,
+			List<IItemDescriptor<Descriptor>> defaultOrder) {
+		return getOrderedItems(defaultOrder, registry, preferenceKey);
+	}
+
+	/**
+	 * Gets the current group order.
+	 * 
+	 * @param isThreeWay
+	 *            True if three way comparison, false otherwise.
+	 * @return Ordered {@link List} of {@link IDifferenceGroupProvider.Descriptor}.
+	 */
+	public List<IItemDescriptor<Descriptor>> getCurrentGroupRanking(boolean isThreeWay) {
+		return getCurrent(getGroupPreferenceKey(isThreeWay), getDefaultRankingConfiguration(isThreeWay));
+	}
+
+	/**
+	 * Gets the default groups order.
+	 * 
+	 * @param isThreeWay
+	 *            True if three way comparison, false otherwise.
+	 * @return Ordered {@link List} of {@link IDifferenceGroupProvider.Descriptor}.
+	 */
+	public List<IItemDescriptor<IDifferenceGroupProvider.Descriptor>> getDefaultRankingConfiguration(
+			boolean isThreeWay) {
+		final Iterable<IItemDescriptor<Descriptor>> groups;
+		if (isThreeWay) {
+			groups = Iterables.filter(registry.getItemDescriptors(), THREE_WAY_FILTER);
+		} else {
+
+			groups = Iterables.filter(registry.getItemDescriptors(), TWO_WAY_FILTER);
+		}
+		List<IItemDescriptor<Descriptor>> result = Lists.newArrayList(groups);
+		Collections.sort(result);
+		return result;
+	}
+
+	/**
+	 * Gets the preference key for group ranking.
+	 * 
+	 * @param isThreeWay
+	 *            True if three way comparison.
+	 * @return They key of the group ranking preference for this type of comparison.
+	 */
+	private String getGroupPreferenceKey(boolean isThreeWay) {
+		if (isThreeWay) {
+			return THREE_WAY_GROUP_RANKING;
+		} else {
+			return TWO_WAY_GROUP_RANKING;
+		}
+	}
+
+	/**
+	 * Returns an ordered list of {@link IItemDescriptor}. The order of the list is either defined by the rank
+	 * in the registry or from preference if the rank has been overloaded. If any descriptor has been added or
+	 * removed since last modification of the preference, this method will merge the modification.
+	 * 
+	 * @param orderedDefaultDescriptor
+	 *            List of ordered default {@link IItemDescriptor}.
+	 * @param descriptorRegistry
+	 *            Registry of descriptor.
+	 * @param orderedItemPreferenceKey
+	 *            Key in preferences where are stored the new order of descriptor
+	 * @return Ordered list of descriptor.
+	 * @param <T>
+	 *            Descriptor type.
+	 */
+	private <T> List<IItemDescriptor<T>> getOrderedItems(List<IItemDescriptor<T>> orderedDefaultDescriptor,
+			IItemRegistry<T> descriptorRegistry, String orderedItemPreferenceKey) {
+		List<IItemDescriptor<T>> itemsDescriptor = ItemUtil.getItemsDescriptor(descriptorRegistry,
+				orderedItemPreferenceKey, preferences);
+
+		if (itemsDescriptor == null) {
+			itemsDescriptor = orderedDefaultDescriptor;
+		} else {
+			HashSet<IItemDescriptor<T>> descriptorFromPrefSet = Sets.newLinkedHashSet(itemsDescriptor);
+			HashSet<IItemDescriptor<T>> defaultDescriptorSet = Sets
+					.newLinkedHashSet(orderedDefaultDescriptor);
+
+			// Remove descriptor
+			SetView<IItemDescriptor<T>> descriptorToRemove = Sets.difference(descriptorFromPrefSet,
+					defaultDescriptorSet);
+			Iterables.removeAll(itemsDescriptor, descriptorToRemove);
+
+			// Add new descriptor
+			SetView<IItemDescriptor<T>> descriptorToAdd = Sets.difference(defaultDescriptorSet,
+					descriptorFromPrefSet);
+			Iterables.addAll(itemsDescriptor, descriptorToAdd);
+
+		}
+		return itemsDescriptor;
+	}
+
+	/**
+	 * Sets the ranking of Difference group provider.
+	 * 
+	 * @param descriptors
+	 *            An ordered list of {@link IItemDescriptor}.
+	 * @param isThreeWay
+	 *            True if three way comparison.
+	 */
+	public void setCurrentGroupRanking(List<IItemDescriptor<Descriptor>> descriptors, boolean isThreeWay) {
+		storeInPreferences(getGroupPreferenceKey(isThreeWay), descriptors,
+				getDefaultRankingConfiguration(isThreeWay));
+
+		// Trace preferences values
+		if (TracingConstant.CONFIGURATION_TRACING_ACTIVATED) {
+			StringBuilder builder = new StringBuilder();
+			// Print each preferences
+			builder.append("Preference ").append(getGroupPreferenceKey(isThreeWay)).append(":\n"); //$NON-NLS-1$ //$NON-NLS-2$
+			String preferenceValue = preferences.get(getGroupPreferenceKey(isThreeWay), ""); //$NON-NLS-1$
+			String[] groups = preferenceValue.split(ItemUtil.PREFERENCE_DELIMITER);
+			for (int rank = 0; rank < groups.length; rank++) {
+				builder.append(rank).append(". ").append(groups[rank]).append("\n"); //$NON-NLS-1$ //$NON-NLS-2$
+			}
+			builder.append("\n\n"); //$NON-NLS-1$
+			EMFCompareRCPUIPlugin.getDefault().log(IStatus.INFO, builder.toString());
+		}
+	}
+
+	/**
+	 * Stores the value into preferences.
+	 * 
+	 * @param preferenceKey
+	 *            Key of the preference
+	 * @param currentValue
+	 *            Current value to store
+	 * @param defaultConf
+	 *            Default value
+	 */
+	private void storeInPreferences(String preferenceKey,
+			List<IItemDescriptor<IDifferenceGroupProvider.Descriptor>> currentValue,
+			List<IItemDescriptor<IDifferenceGroupProvider.Descriptor>> defaultConf) {
+		if (currentValue != null && !currentValue.equals(defaultConf)) {
+			Iterable<String> currentIDs = Iterables.transform(currentValue,
+					new Function<IItemDescriptor<IDifferenceGroupProvider.Descriptor>, String>() {
+
+						public String apply(IItemDescriptor<IDifferenceGroupProvider.Descriptor> arg0) {
+							return arg0.getID();
+						}
+					});
+			String preferenceValue = Joiner.on(ItemUtil.PREFERENCE_DELIMITER).join(currentIDs);
+			preferences.put(preferenceKey, preferenceValue);
+		} else {
+			preferences.remove(preferenceKey);
+		}
+	}
+
+}
diff --git a/plugins/org.eclipse.emf.compare.rcp.ui/src/org/eclipse/emf/compare/rcp/ui/internal/structuremergeviewer/groups/impl/DifferenceGroupRegistryImpl.java b/plugins/org.eclipse.emf.compare.rcp.ui/src/org/eclipse/emf/compare/rcp/ui/internal/structuremergeviewer/groups/impl/DifferenceGroupRegistryImpl.java
index e5f263b..20e8f8c 100644
--- a/plugins/org.eclipse.emf.compare.rcp.ui/src/org/eclipse/emf/compare/rcp/ui/internal/structuremergeviewer/groups/impl/DifferenceGroupRegistryImpl.java
+++ b/plugins/org.eclipse.emf.compare.rcp.ui/src/org/eclipse/emf/compare/rcp/ui/internal/structuremergeviewer/groups/impl/DifferenceGroupRegistryImpl.java
@@ -1,158 +1,158 @@
-/*******************************************************************************

- * Copyright (c) 2012, 2014 Obeo.

- * All rights reserved. This program and the accompanying materials

- * are made available under the terms of the Eclipse Public License v1.0

- * which accompanies this distribution, and is available at

- * http://www.eclipse.org/legal/epl-v10.html

- * 

- * Contributors:

- *     Obeo - initial API and implementation

- *******************************************************************************/

-package org.eclipse.emf.compare.rcp.ui.internal.structuremergeviewer.groups.impl;

-

-import static com.google.common.collect.Lists.newArrayList;

-

-import com.google.common.base.Preconditions;

-import com.google.common.collect.ImmutableList;

-

-import java.util.Collections;

-import java.util.List;

-import java.util.ListIterator;

-

-import org.eclipse.emf.compare.Comparison;

-import org.eclipse.emf.compare.rcp.internal.extension.IItemDescriptor;

-import org.eclipse.emf.compare.rcp.internal.extension.IItemRegistry;

-import org.eclipse.emf.compare.rcp.internal.extension.impl.WrapperItemDescriptor;

-import org.eclipse.emf.compare.rcp.ui.structuremergeviewer.groups.IDifferenceGroupProvider;

-import org.eclipse.emf.compare.rcp.ui.structuremergeviewer.groups.IDifferenceGroupProvider.Descriptor;

-import org.eclipse.emf.compare.scope.IComparisonScope;

-

-/**

- * Implementation of the {@link IDifferenceGroupProvider.Descriptor.Registry}. This implementation allow user

- * to override ranking of each group using preferences.

- * 

- * @author <a href="mailto:axel.richard@obeo.fr">Axel Richard</a>

- * @since 4.0

- */

-public class DifferenceGroupRegistryImpl implements IDifferenceGroupProvider.Descriptor.Registry {

-

-	/** A map that associates the class name to theirs {@link IDifferenceGroupProvider.Descriptor}s. */

-	private final IItemRegistry<IDifferenceGroupProvider.Descriptor> registry;

-

-	/** Group manager. */

-	private DifferenceGroupManager groupManager;

-

-	/**

-	 * Constructs the registry.

-	 * 

-	 * @param groupManager

-	 *            {@link DifferenceGroupManager} use to handle groups.

-	 * @param registry

-	 *            Item registry where are stored all registered group.

-	 */

-	public DifferenceGroupRegistryImpl(DifferenceGroupManager groupManager,

-			IItemRegistry<IDifferenceGroupProvider.Descriptor> registry) {

-		this.groupManager = groupManager;

-		this.registry = registry;

-	}

-

-	/**

-	 * {@inheritDoc}

-	 * 

-	 * @see org.eclipse.emf.compare.rcp.ui.structuremergeviewer.groups.IDifferenceGroupProvider.Descriptor.Registry#getGroupProviders(IComparisonScope,

-	 *      Comparison)

-	 */

-	public List<IDifferenceGroupProvider.Descriptor> getGroupProviders(IComparisonScope scope,

-			Comparison comparison) {

-		if (comparison != null) {

-			List<IDifferenceGroupProvider.Descriptor> providers = newArrayList();

-			List<IItemDescriptor<Descriptor>> groupProviderDescriptors = groupManager

-					.getCurrentGroupRanking(comparison.isThreeWay());

-			ListIterator<IItemDescriptor<Descriptor>> groupIterator = groupProviderDescriptors.listIterator();

-			while (groupIterator.hasNext()) {

-				IItemDescriptor<Descriptor> desc = groupIterator.next();

-				IDifferenceGroupProvider.Descriptor groupProviderDescriptor = desc.getItem();

-				IDifferenceGroupProvider gp = groupProviderDescriptor.createGroupProvider();

-				if (gp != null && isGroupProviderActivable(gp, scope, comparison)) {

-					providers.add(groupProviderDescriptor);

-				}

-			}

-			return ImmutableList.copyOf(providers);

-		}

-		return Collections.emptyList();

-	}

-

-	/**

-	 * {@inheritDoc}

-	 * 

-	 * @see org.eclipse.emf.compare.rcp.ui.structuremergeviewer.groups.IDifferenceGroupProvider.Descriptor.Registry#getDefaultGroupProvider(org.eclipse.emf.compare.scope.IComparisonScope,

-	 *      org.eclipse.emf.compare.Comparison)

-	 */

-	public IDifferenceGroupProvider.Descriptor getDefaultGroupProvider(IComparisonScope scope,

-			Comparison comparison) {

-		List<IDifferenceGroupProvider.Descriptor> descriptors = getGroupProviders(scope, comparison);

-		if (!descriptors.isEmpty()) {

-			return descriptors.get(0);

-		}

-		return null;

-	}

-

-	/**

-	 * Checks if the given IDifferenceGroupProvider is activable based on the scope and comparison objects.

-	 * 

-	 * @param dgp

-	 *            the given IDifferenceGroupProvider.

-	 * @param scope

-	 *            The scope on which the group provider will be applied.

-	 * @param comparison

-	 *            The comparison which is to be displayed in the structural view.

-	 * @return true, if it is activable, false otherwise.

-	 */

-	static final boolean isGroupProviderActivable(final IDifferenceGroupProvider dgp,

-			final IComparisonScope scope, final Comparison comparison) {

-		return dgp.isEnabled(scope, comparison);

-	}

-

-	/**

-	 * {@inheritDoc}

-	 * 

-	 * @see org.eclipse.emf.compare.rcp.ui.structuremergeviewer.groups.IDifferenceGroupProvider.Descriptor.Registry#add

-	 *      (org.eclipse.emf.compare.rcp.ui.structuremergeviewer.groups.IDifferenceGroupProvider.Descriptor)

-	 */

-	public IDifferenceGroupProvider.Descriptor add(IDifferenceGroupProvider.Descriptor providerDescriptor,

-			String className) {

-		Preconditions.checkNotNull(providerDescriptor);

-		IDifferenceGroupProvider groupProvider = providerDescriptor.createGroupProvider();

-		WrapperItemDescriptor<IDifferenceGroupProvider.Descriptor> descriptor = new WrapperItemDescriptor<IDifferenceGroupProvider.Descriptor>(

-				providerDescriptor.getLabel(), providerDescriptor.getDescription(), providerDescriptor

-						.getRank(), groupProvider.getClass().getName(), providerDescriptor);

-

-		IItemDescriptor<Descriptor> oldValue = registry.add(descriptor);

-		if (oldValue != null) {

-			return oldValue.getItem();

-		}

-		return null;

-	}

-

-	/**

-	 * {@inheritDoc}

-	 * 

-	 * @see org.eclipse.emf.compare.rcp.ui.structuremergeviewer.groups.IDifferenceGroupProvider.Descriptor.Registry#remove(java.lang.String)

-	 */

-	public IDifferenceGroupProvider.Descriptor remove(String className) {

-		IItemDescriptor<IDifferenceGroupProvider.Descriptor> oldValue = registry.remove(className);

-		if (oldValue != null) {

-			return oldValue.getItem();

-		}

-		return null;

-	}

-

-	/**

-	 * {@inheritDoc}

-	 * 

-	 * @see org.eclipse.emf.compare.rcp.ui.structuremergeviewer.groups.IDifferenceGroupProvider.Descriptor.Registry#clear()

-	 */

-	public void clear() {

-		registry.clear();

-	}

-}

+/*******************************************************************************
+ * Copyright (c) 2012, 2014 Obeo.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     Obeo - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.compare.rcp.ui.internal.structuremergeviewer.groups.impl;
+
+import static com.google.common.collect.Lists.newArrayList;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableList;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.ListIterator;
+
+import org.eclipse.emf.compare.Comparison;
+import org.eclipse.emf.compare.rcp.internal.extension.IItemDescriptor;
+import org.eclipse.emf.compare.rcp.internal.extension.IItemRegistry;
+import org.eclipse.emf.compare.rcp.internal.extension.impl.WrapperItemDescriptor;
+import org.eclipse.emf.compare.rcp.ui.structuremergeviewer.groups.IDifferenceGroupProvider;
+import org.eclipse.emf.compare.rcp.ui.structuremergeviewer.groups.IDifferenceGroupProvider.Descriptor;
+import org.eclipse.emf.compare.scope.IComparisonScope;
+
+/**
+ * Implementation of the {@link IDifferenceGroupProvider.Descriptor.Registry}. This implementation allow user
+ * to override ranking of each group using preferences.
+ * 
+ * @author <a href="mailto:axel.richard@obeo.fr">Axel Richard</a>
+ * @since 4.0
+ */
+public class DifferenceGroupRegistryImpl implements IDifferenceGroupProvider.Descriptor.Registry {
+
+	/** A map that associates the class name to theirs {@link IDifferenceGroupProvider.Descriptor}s. */
+	private final IItemRegistry<IDifferenceGroupProvider.Descriptor> registry;
+
+	/** Group manager. */
+	private DifferenceGroupManager groupManager;
+
+	/**
+	 * Constructs the registry.
+	 * 
+	 * @param groupManager
+	 *            {@link DifferenceGroupManager} use to handle groups.
+	 * @param registry
+	 *            Item registry where are stored all registered group.
+	 */
+	public DifferenceGroupRegistryImpl(DifferenceGroupManager groupManager,
+			IItemRegistry<IDifferenceGroupProvider.Descriptor> registry) {
+		this.groupManager = groupManager;
+		this.registry = registry;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see org.eclipse.emf.compare.rcp.ui.structuremergeviewer.groups.IDifferenceGroupProvider.Descriptor.Registry#getGroupProviders(IComparisonScope,
+	 *      Comparison)
+	 */
+	public List<IDifferenceGroupProvider.Descriptor> getGroupProviders(IComparisonScope scope,
+			Comparison comparison) {
+		if (comparison != null) {
+			List<IDifferenceGroupProvider.Descriptor> providers = newArrayList();
+			List<IItemDescriptor<Descriptor>> groupProviderDescriptors = groupManager
+					.getCurrentGroupRanking(comparison.isThreeWay());
+			ListIterator<IItemDescriptor<Descriptor>> groupIterator = groupProviderDescriptors.listIterator();
+			while (groupIterator.hasNext()) {
+				IItemDescriptor<Descriptor> desc = groupIterator.next();
+				IDifferenceGroupProvider.Descriptor groupProviderDescriptor = desc.getItem();
+				IDifferenceGroupProvider gp = groupProviderDescriptor.createGroupProvider();
+				if (gp != null && isGroupProviderActivable(gp, scope, comparison)) {
+					providers.add(groupProviderDescriptor);
+				}
+			}
+			return ImmutableList.copyOf(providers);
+		}
+		return Collections.emptyList();
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see org.eclipse.emf.compare.rcp.ui.structuremergeviewer.groups.IDifferenceGroupProvider.Descriptor.Registry#getDefaultGroupProvider(org.eclipse.emf.compare.scope.IComparisonScope,
+	 *      org.eclipse.emf.compare.Comparison)
+	 */
+	public IDifferenceGroupProvider.Descriptor getDefaultGroupProvider(IComparisonScope scope,
+			Comparison comparison) {
+		List<IDifferenceGroupProvider.Descriptor> descriptors = getGroupProviders(scope, comparison);
+		if (!descriptors.isEmpty()) {
+			return descriptors.get(0);
+		}
+		return null;
+	}
+
+	/**
+	 * Checks if the given IDifferenceGroupProvider is activable based on the scope and comparison objects.
+	 * 
+	 * @param dgp
+	 *            the given IDifferenceGroupProvider.
+	 * @param scope
+	 *            The scope on which the group provider will be applied.
+	 * @param comparison
+	 *            The comparison which is to be displayed in the structural view.
+	 * @return true, if it is activable, false otherwise.
+	 */
+	static final boolean isGroupProviderActivable(final IDifferenceGroupProvider dgp,
+			final IComparisonScope scope, final Comparison comparison) {
+		return dgp.isEnabled(scope, comparison);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see org.eclipse.emf.compare.rcp.ui.structuremergeviewer.groups.IDifferenceGroupProvider.Descriptor.Registry#add
+	 *      (org.eclipse.emf.compare.rcp.ui.structuremergeviewer.groups.IDifferenceGroupProvider.Descriptor)
+	 */
+	public IDifferenceGroupProvider.Descriptor add(IDifferenceGroupProvider.Descriptor providerDescriptor,
+			String className) {
+		Preconditions.checkNotNull(providerDescriptor);
+		IDifferenceGroupProvider groupProvider = providerDescriptor.createGroupProvider();
+		WrapperItemDescriptor<IDifferenceGroupProvider.Descriptor> descriptor = new WrapperItemDescriptor<IDifferenceGroupProvider.Descriptor>(
+				providerDescriptor.getLabel(), providerDescriptor.getDescription(), providerDescriptor
+						.getRank(), groupProvider.getClass().getName(), providerDescriptor);
+
+		IItemDescriptor<Descriptor> oldValue = registry.add(descriptor);
+		if (oldValue != null) {
+			return oldValue.getItem();
+		}
+		return null;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see org.eclipse.emf.compare.rcp.ui.structuremergeviewer.groups.IDifferenceGroupProvider.Descriptor.Registry#remove(java.lang.String)
+	 */
+	public IDifferenceGroupProvider.Descriptor remove(String className) {
+		IItemDescriptor<IDifferenceGroupProvider.Descriptor> oldValue = registry.remove(className);
+		if (oldValue != null) {
+			return oldValue.getItem();
+		}
+		return null;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see org.eclipse.emf.compare.rcp.ui.structuremergeviewer.groups.IDifferenceGroupProvider.Descriptor.Registry#clear()
+	 */
+	public void clear() {
+		registry.clear();
+	}
+}
diff --git a/plugins/org.eclipse.emf.compare.rcp/src/org/eclipse/emf/compare/rcp/internal/preferences/EMFComparePreferences.java b/plugins/org.eclipse.emf.compare.rcp/src/org/eclipse/emf/compare/rcp/internal/preferences/EMFComparePreferences.java
index b3a82e1..7b043f3 100644
--- a/plugins/org.eclipse.emf.compare.rcp/src/org/eclipse/emf/compare/rcp/internal/preferences/EMFComparePreferences.java
+++ b/plugins/org.eclipse.emf.compare.rcp/src/org/eclipse/emf/compare/rcp/internal/preferences/EMFComparePreferences.java
@@ -1,45 +1,45 @@
-/*******************************************************************************

- * Copyright (c) 2014 Obeo.

- * All rights reserved. This program and the accompanying materials

- * are made available under the terms of the Eclipse Public License v1.0

- * which accompanies this distribution, and is available at

- * http://www.eclipse.org/legal/epl-v10.html

- * 

- * Contributors:

- *     Obeo - initial API and implementation

- *******************************************************************************/

-package org.eclipse.emf.compare.rcp.internal.preferences;

-

-/**

- * All preferences constant for EMF Compare.

- * 

- * @author <a href="mailto:arthur.daussy@obeo.fr">Arthur Daussy</a>

- */

-public final class EMFComparePreferences {

-

-	/** Differences Engine preference. (Key to use in the registry to retrieve the engine descriptor). */

-	public static final String DIFF_ENGINES = "org.eclipse.emf.compare.preference.diff.engine"; //$NON-NLS-1$

-

-	/** Equivalences Engine preference. (Key to use in the registry to retrieve the engine descriptor). */

-	public static final String EQUI_ENGINES = "org.eclipse.emf.compare.preference.equi.engine"; //$NON-NLS-1$

-

-	/** Requirements Engine preference. (Key to use in the registry to retrieve the engine descriptor). */

-	public static final String REQ_ENGINES = "org.eclipse.emf.compare.preference.req.engine"; //$NON-NLS-1$

-

-	/** Conflicts detector preference. (Key to use in the registry to retrieve the engine descriptor). */

-	public static final String CONFLICTS_DETECTOR = "org.eclipse.emf.compare.preference.conflict.detector"; //$NON-NLS-1$

-

-	/** Disabled match engine preference. (Key to use in the registry to retrieve the engine descriptor). */

-	public static final String MATCH_ENGINE_DISABLE_ENGINES = "org.eclipse.emf.compare.preference.match.engine"; //$NON-NLS-1$

-

-	/** Disabled post processors preference. */

-	public static final String DISABLED_POST_PROCESSOR = "org.eclipse.emf.compare.preference.postprocessor.disabled"; //$NON-NLS-1$

-

-	/**

-	 * Private constructor. Not to be called.

-	 */

-	private EMFComparePreferences() {

-		// Hide default constructor.

-	}

-

-}

+/*******************************************************************************
+ * Copyright (c) 2014 Obeo.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     Obeo - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.compare.rcp.internal.preferences;
+
+/**
+ * All preferences constant for EMF Compare.
+ * 
+ * @author <a href="mailto:arthur.daussy@obeo.fr">Arthur Daussy</a>
+ */
+public final class EMFComparePreferences {
+
+	/** Differences Engine preference. (Key to use in the registry to retrieve the engine descriptor). */
+	public static final String DIFF_ENGINES = "org.eclipse.emf.compare.preference.diff.engine"; //$NON-NLS-1$
+
+	/** Equivalences Engine preference. (Key to use in the registry to retrieve the engine descriptor). */
+	public static final String EQUI_ENGINES = "org.eclipse.emf.compare.preference.equi.engine"; //$NON-NLS-1$
+
+	/** Requirements Engine preference. (Key to use in the registry to retrieve the engine descriptor). */
+	public static final String REQ_ENGINES = "org.eclipse.emf.compare.preference.req.engine"; //$NON-NLS-1$
+
+	/** Conflicts detector preference. (Key to use in the registry to retrieve the engine descriptor). */
+	public static final String CONFLICTS_DETECTOR = "org.eclipse.emf.compare.preference.conflict.detector"; //$NON-NLS-1$
+
+	/** Disabled match engine preference. (Key to use in the registry to retrieve the engine descriptor). */
+	public static final String MATCH_ENGINE_DISABLE_ENGINES = "org.eclipse.emf.compare.preference.match.engine"; //$NON-NLS-1$
+
+	/** Disabled post processors preference. */
+	public static final String DISABLED_POST_PROCESSOR = "org.eclipse.emf.compare.preference.postprocessor.disabled"; //$NON-NLS-1$
+
+	/**
+	 * Private constructor. Not to be called.
+	 */
+	private EMFComparePreferences() {
+		// Hide default constructor.
+	}
+
+}