blob: b3a51be78c9d35c9ab0eafd6d96297f463fc7e40 [file] [log] [blame]
= Specifications of the EMF Compare 3.2.0 release (Eclipse Neon) =
== US_320_001 - UML Dangling stereotypes ==
=== Description ===
Support UML dangling stereotypes in comparisons and merges.
==== Categories ====
[[./index.html#Core-related Specifications|Core]], [[./index.html#UI-related Specifications|UI]], [[./index.html#UML-related Specifications|UML]]
=== Related Bugs & Reviews ===
This user story is linked with these bugs & reviews:
* https://bugs.eclipse.org/bugs/show_bug.cgi?id=467866
=== Related Tests ===
This user story is linked with these tests:
* http://git.eclipse.org/c/emfcompare/org.eclipse.emf.compare.git/tree/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/stereotypes/DanglingStereotypeApplicationTest.java
=== Content ===
The problem comes from UML dangling stereotypes in UML models. UML dangling stereotypes happen when a stereotype linked to a model element is still in a model while the model element has been removed.
Papyrus offers the possibility to fix dangling stereotypes by removing them.
In 3.1.0 and before, such changes are wrongly detected and displayed as ResourceAttachmentChanges in the comparison models, and displayed to users as "uncontrolled from xxx.uml".
==== Proposal ====
===== Core =====
A new type of ResourceAttachmentChange will be created in the org.eclipse.emf.compare.uml2/model/uml2compare.ecore metamodel. It will be a DanglingStereotypeApplication.
No specific merge work will be done on DanglingStereotypeApplication. That means DanglingStereotypeApplications will be mergeable from left to right or right to left (and accept/reject) without specific control. Thus, the dangling references could be merged into a "clean" model and make it "dirty".
===== UI =====
The DanglingStereotypeApplications will be displayed in red to warn users that there is problem(s) in their models. As a ResourceAttachmentChanges, DanglingStereotypeApplications will be displayed under MatchResources.
'''Current'''
[[Image:./images/US_320_001_2.png]]
'''Proposal'''
[[Image:./images/US_320_001_3.png]]
===== Cases =====
For all cases, consider the following base model.
[[Image:./images/US_320_001_1.png]]
'''Case 1: Dangling stereotype with nothing on the other side'''
[[Image:./images/US_320_001_3.png]]
A merge from left to right of the DanglingStereotypeApplication will lead to delete the dangling stereotype on the right model.
A merge from right to left of the DanglingStereotypeApplication will lead to have the dangling stereotype also on the left model.
'''Case 2: Dangling stereotype with class (without stereotype) on the other side'''
[[Image:./images/US_320_001_4.png]]
A merge from left to right of the DanglingStereotypeApplication will lead to delete the dangling stereotype on the right model.
A merge from right to left of the DanglingStereotypeApplication will lead to have the dangling stereotype also on the left model.
===== Possible Evolution =====
As a possible evolution, specific work could be done on merge to handle case where classes exist on one side and dangling references on the other side (see case 2 above), in order to "re-connect" class and their stereotype application if it is possible (if the id of the targeted element of the stereotype is still there).
== US_320_002 - Toolbar actions: contextual tooltips ==
=== Description ===
Add contextual tooltips for action buttons in EMF Compare UI.
==== Categories ====
[[./index.html#UI-related Specifications|UI]]
=== Content ===
The tooltips are not contextualized. Each button has the same tooltip for all possible cases. It is confusing for the user. Tooltips for actions and right click menu labels must be context specific.
==== Proposal ====
===== UI =====
The tooltip must display the best information depending of the context.
'''Proposal'''
The following list suggests tooltips for each possible case.
====== With only one editable model ======
Accept All Non-Conflicting Changes → Accept All Non-Conflicting Changes. The left changes will be accepted and the right changes will be merged into the left-hand side.
Reject All Non-Conflicting Changes → Reject All Non-Conflicting Changes. The left changes will be rejected and the right changes will not be used.
<u>Accept Change</u>
# single selection:
#* set:
#** in left/local model &rarr; Accept the change. Keep '''{left value}''' in '''{feature name}''' of this '''{left element type}''' on the left-hand side. The left-hand side will remain unchanged.
#** in right/remote model (left value not empty) &rarr; Accept the change. Set the '''{feature name}''' of this '''{left element type}''' to '''{right value}''' (instead of '''{left value}'''). The left-hand side will be modified.
#** in right/remote model (left value empty) &rarr; Accept the change. Set the '''{feature name}''' of this '''{left element type}''' to '''{right value}'''. The left-hand side will be modified.
#* unset:
#** in left/local model &rarr; Accept the change. Keep the '''{feature name}''' of this '''{left element type}''' unset on the left-hand side. The left-hand side will remain unchanged.
#** in right/remote model &rarr; Accept the change. Unset the '''{feature name}''' of this '''{left element type}''' (currently '''{left value}''') on the left-hand side. The left-hand side will be modified.
#* move:
#** in left/local model:
#*** move of container &rarr; Accept the change. Keep '''{left element}''' in '''{left element container}''' on the left-hand side. The left-hand side will remain unchanged.
#*** move of position (containment reference) &rarr; Accept the change. Keep '''{left element}''' at its current position in '''{left element container}''' on the left-hand side. The left-hand side will remain unchanged.
#*** move of position (non containment reference) &rarr; Accept the change. Keep '''{left element}''' at its current position on the left-hand side. The left-hand side will remain unchanged.
#** in right/remote model:
#*** move of container &rarr; Accept the change. Move '''{left element}''' in '''{right element container}''' (currently in '''{left element container}''') on the left-hand side. The left-hand side will be modified.
#*** move of position (containment reference) &rarr; Accept the change. Move the position of '''{left element}''' in '''{left element container}''' on the left-hand side. The left-hand side will be modified.
#*** move of position (non containment reference) &rarr; Accept the change. Move the position of '''{left element}''' on the left-hand side. The left-hand side will be modified.
#* add:
#** in left/local model:
#*** in containment feature &rarr; Accept the change. Keep '''{left element}''' in '''{left element container}''' on the left-hand side. The left-hand side will remain unchanged.
#*** in a reference &rarr; Accept the change. Keep '''{left element}''' on the left-hand side. The left-hand side will remain unchanged.
#*** in an attribute &rarr; Accept the change. Keep '''{left element}''' in '''{left element container}''' on the left-hand side. The left-hand side will remain unchanged.
#** in right/remote model:
#*** in containment feature &rarr; Accept the change. Add '''{right element}''' in '''{right element container}''' on the left-hand side. The left-hand side will be modified.
#*** in a reference &rarr; Accept the change. Add '''{right element}''' on the left-hand side. The left-hand side will be modified.
#*** in an attribute &rarr; Accept the change. Add '''{right element}''' in '''{right element container}''' on the left-hand side. The left-hand side will be modified.
#* delete:
#** in left/local model:
#*** from a containment change &rarr; Accept the change. Keep the deletion of '''{right element}''' from '''{right element container}''' on the left-hand side. The left-hand side will remain unchanged.
#*** from other features &rarr; Accept the change. Keep the deletion of '''{right element}''' on the left-hand side. The left-hand side will remain unchanged.
#** in right/remote model:
#*** from a containment change &rarr; Accept the change. Delete '''{left element}''' in '''{left element container}''' on the left-hand side. The left-hand side will be modified.
#*** from other features &rarr; Accept the change. Delete '''{left element}''' on the left-hand side. The left-hand side will be modified.
# multiple selection &rarr; Accept all non-conflicting changes from the current selection.
<u>Reject Change</u>
# single selection:
#* set:
#** in left/local model (right not empty) &rarr; Reject the change. Restore the '''{feature name}''' of this '''{left element type}''' to '''{right value}''' (instead of '''{left value}''') on the left-hand side. The left-hand side will be modified.
#** in left/local model (right empty) &rarr; Reject the change. Clear the '''{feature name}''' of this '''{left element type}''' (currently '''{left value}''') on the left-hand side. The left-hand side will be modified.
#** in right/remote model (left not empty) &rarr; Reject the change. Keep the '''{feature name}''' of this '''{right element type}''' set to '''{left value}''' on the left-hand side. The left-hand side will remain unchanged.
#** in right/remote model (left empty) &rarr; Reject the change. Keep the '''{feature name}''' of this '''{right element type}''' empty on the left-hand side. The left-hand side will remain unchanged.
#* unset:
#** in left/local model &rarr; Reject the change. Restore the '''{feature name}''' of this '''{left element type}''' to '''{right value}''' on the left-hand side. The left-hand side will be modified.
#** in right/remote model &rarr; Reject the change. Keep the '''{feature name}''' of this '''{right element type}''' set to '''{left value}''' on the left-hand side. The left-hand side will remain unchanged.
#* move:
#** in left/local model:
#*** move of container &rarr; Reject the change. Restore '''{left element}''' in '''{right element container}''' (currently in '''{left element container}''') on the left-hand side. The left-hand side will be modified.
#*** move of position &rarr; Reject the change. Restore the original position of '''{left element}''' on the left-hand side. The left-hand side will be modified.
#** in right/remote model:
#*** move of container &rarr; Reject the change. Keep '''{right element}''' in '''{left element container}''' on the left-hand side. The left-hand side will remain unchanged.
#*** move of position (containment reference) &rarr; Reject the change. Keep '''{right element}''' at its current position in '''{right element container}''' on the left-hand side. The left-hand side will remain unchanged.
#*** move of position (containment reference) &rarr; Reject the change. Keep '''{right element}''' at its current position on the left-hand side. The left-hand side will remain unchanged.
#* add:
#** in left/local model:
#*** in containment feature &rarr; Reject the change. Delete '''{left element}''' in '''{left element container}''' on the left-hand side. The left-hand side will be modified.
#*** in a reference &rarr; Reject the change. Delete '''{left element}''' on the left-hand side. The left-hand side will be modified.
#*** in an attribute &rarr; Reject the change. Delete '''{left element}''' from '''{left element container}''' on the left-hand side. The left-hand side will be modified.
#** in right/remote model:
#*** in containment feature &rarr; Reject the change. Do not add '''{right element}''' in '''{right element container}''' on the left-hand side. The left-hand side will remain unchanged.
#*** in a reference &rarr; Reject the change. Do not add '''{right element}''' on the left-hand side. The left-hand side will remain unchanged.
#*** in an attribute &rarr; Reject the change. Do not add '''{right element}''' under '''{right element container}''' on the left-hand side. The left-hand side will remain unchanged.
#* delete:
#** in left/local model:
#*** from a containment change &rarr; Reject the change. Restore '''{right element}''' in '''{right element container}''' on the left-hand side. The left-hand side will be modified.
#*** from other features &rarr; Reject the change. Restore '''{right element}''' on the left-hand side. The left-hand side will be modified.
#** in right/remote model:
#*** from a containment change &rarr; Reject the change. Keep '''{left element}''' in '''{left element container}''' on the left-hand side. The left-hand side will remain unchanged.
#*** from other features &rarr; Reject the change. Keep '''{left element}''' on the left-hand side. The left-hand side will remain unchanged.
# multiple selection &rarr; Reject all non-conflicting changes from the current selection.
====== With both models editable ======
Copy All Non-Conflicting Changes from Left to Right &rarr; Apply all left changes on the right-hand side. The left-hand side will remain unchanged.
Copy All Non-Conflicting Changes from Right to Left &rarr; Apply all right changes on the left-hand side. The right-hand side will remain unchanged.
<u>Copy Current Change from Left to Right</u>
# single selection:
#* set:
#** in left model (right value not empty) &rarr; Set the '''{feature name}''' of this '''{right element type}''' to '''{left value}''' on the right-hand side (currently '''{right value}'''). The left-hand side will remain unchanged. The right-hand side will be modified.
#** in left model (right value empty) &rarr; Set the '''{feature name}''' of this '''{right element type}''' to '''{left value}''' on the right-hand side. The left-hand side will remain unchanged. The right-hand side will be modified.
#** in right model (right value not empty) &rarr; Set the '''{feature name}''' of this '''{right element type}''' to '''{left value}''' on the right-hand side (instead of '''{right value}'''). The left-hand side will remain unchanged. The right-hand side will be modified.
#** in right model (right value empty) &rarr; Clear the '''{feature name}''' of this '''{right element type}''' (currently '''{right value}''') on the right-hand side. The left-hand side will remain unchanged. The right-hand side will be modified.
#* unset:
#** in left model &rarr; Unset the '''{feature name}''' of this '''{right element type}''' on the right-hand side (currently '''{right value}'''). The left-hand side will remain unchanged. The right-hand side will be modified.
#** in right model &rarr; Restore the '''{feature name}''' of this '''{right element type}''' to '''{left value}''' on the right-hand side. The left-hand side will remain unchanged. The right-hand side will be modified.
#* move:
#** in left model:
#*** move of container &rarr; Move '''{right element}''' in '''{left element container}''' (currently in '''{right element container}''') on the right-hand side. The left-hand side will remain unchanged. The right-hand side will be modified.
#*** move of position &rarr; Move '''{right element}''' on the right-hand side to match its left-hand side position. The left-hand side will remain unchanged. The right-hand side will be modified. The right-hand side will be modified.
#** in right model:
#*** move of container &rarr; Move '''{right element}''' in '''{left element container}''' (currently in '''{right element container}''') on the right-hand side. The left-hand side will remain unchanged. The right-hand side will be modified.
#*** move of position &rarr; Move '''{right element}''' on the right-hand side to match its left-hand side position. The left-hand side will remain unchanged. The right-hand side will be modified.
#* add:
#** in left model:
#*** in containment feature &rarr; Add '''{left element}''' in '''{left element container}''' on the right-hand side. The left-hand side will remain unchanged. The right-hand side will be modified.
#*** in a reference &rarr; Add '''{left element}''' on the right-hand side. The left-hand side will remain unchanged. The right-hand side will be modified.
#*** in an attribute &rarr; Add '''{left element}''' in '''{left element container}''' on the right-hand side. The left-hand side will remain unchanged. The right-hand side will be modified.
#** in right model:
#*** in containment feature &rarr; Delete '''{right element}''' in '''{right element container}''' on the right-hand side. The left-hand side will remain unchanged. The right-hand side will be modified.
#*** in a reference &rarr; Remove '''{right element}''' on the right-hand side. The left-hand side will remain unchanged. The right-hand side will be modified.
#*** in an attribute &rarr; Delete '''{right element}''' in '''{right element container}''' on the right-hand side. The left-hand side will remain unchanged. The right-hand side will be modified.
#* delete:
#** in left model:
#*** from a containment change &rarr; Delete '''{right element}''' from '''{right element container}''' on the right-hand side. The left-hand side will remain unchanged. The right-hand side will be modified.
#*** from other features &rarr; Delete '''{left element}''' on the right-hand side. The left-hand side will remain unchanged. The right-hand side will be modified.
#** in right model:
#*** from a containment change &rarr; Undo the deletion of '''{left element}''' from '''{left element container}''' on the right-hand side. The left-hand side will remain unchanged. The right-hand side will be modified.
#*** from other features &rarr; Undo the deletion of '''{right element}''' on the right-hand side. The left-hand side will remain unchanged. The right-hand side will be modified.
# multiple selection &rarr; Apply all non-conflicting changes from the current selection on the left-hand side.
<u>Copy Current Change from Right to Left</u>
# single selection:
#* set:
#** in right model (left value not empty) &rarr; Set the '''{feature name}''' of this '''{left element type}''' to '''{right value}''' on the left-hand side (instead of '''{left value}'''). The left-hand side will be modified. The right-hand side will remain unchanged.
#** in right model (left value empty) &rarr; Set the '''{feature name}''' of this '''{left element type}''' to '''{right value}''' on the left-hand side. The left-hand side will be modified. The right-hand side will remain unchanged.
#** in left model (right value not empty) &rarr; Set the '''{feature name}''' of this '''{left element type}''' to '''{right value}''' on the left-hand side (instead of '''{left value}'''). The left-hand side will be modified. The right-hand side will remain unchanged.
#** in left model (right value empty) &rarr; Clear the '''{feature name}''' of this '''{left element type}''' on the left-hand side (currently '''{left value}'''). The left-hand side will be modified. The right-hand side will remain unchanged.
#* unset:
#** in right model &rarr; Unset the '''{feature name}''' of this '''{left element type}''' on the left-hand side (currently '''{left value}'''). The left-hand side will be modified. The right-hand side will remain unchanged.
#** in left model &rarr; Restore the '''{feature name}''' of this '''{left element type}''' to '''{right value}''' on the left-hand side. The left-hand side will be modified. The right-hand side will remain unchanged.
#* move:
#** in right model:
#*** move of container &rarr; Move '''{left element}''' in '''{right element container}''' (currently in '''{left element container}''') on the left-hand side. The left-hand side will be modified. The right-hand side will remain unchanged.
#*** move of position &rarr; Move '''{left element}''' on the left-hand side to match its right-hand side position. The left-hand side will be modified. The right-hand side will remain unchanged.
#** in left model:
#*** move of container &rarr; Move '''{left element}''' in '''{right element container}''' (currently in '''{left element container}''') on the left-hand side. The left-hand side will be modified. The right-hand side will remain unchanged.
#*** move of position &rarr; Move the '''{left element}''' on the left-hand side to match its right-hand side position. The left-hand side will be modified. The right-hand side will remain unchanged.
#* add:
#** in right model:
#*** in containment feature &rarr; Add '''{right element}''' in '''{right element container}''' on the left-hand side. The left-hand side will be modified. The right-hand side will remain unchanged.
#*** in a reference &rarr; Add '''{right element}''' on the left-hand side. The left-hand side will be modified. The right-hand side will remain unchanged.
#*** in an attribute &rarr; Add '''{right element}''' in '''{right element container}''' on the left-hand side. The left-hand side will be modified. The right-hand side will remain unchanged.
#** in left model:
#*** in containment feature &rarr; Delete '''{left element}''' in '''{left element container}''' on the left-hand side. The left-hand side will be modified. The right-hand side will remain unchanged.
#*** in a reference &rarr; Remove '''{left element}''' on the left-hand side. The left-hand side will be modified. The right-hand side will remain unchanged.
#*** in an attribute &rarr; Delete '''{left element}''' in '''{left element container}''' on the left-hand side. The left-hand side will be modified. The right-hand side will remain unchanged.
#* delete:
#** in right model:
#*** from a containment change &rarr; Delete '''{left element}''' from '''{left element container}''' on the left-hand side. The left-hand side will be modified. The right-hand side will remain unchanged.
#*** from other features &rarr; Delete '''{right element}''' on the left-hand side. The left-hand side will be modified. The right-hand side will remain unchanged.
#** in left model:
#*** from a containment change &rarr; Undo the deletion of '''{right element}''' in '''{right element position}''' on the left-hand side. The left-hand side will be modified. The right-hand side will remain unchanged.
#*** from other features &rarr; Undo the deletion of '''{left element}''' on the left-hand side. The left-hand side will be modified. The right-hand side will remain unchanged.
# multiple selection &rarr; Apply all non-conflicting changes from the current selection on the left-hand side.
== US_320_003 - Synchronize view integration ==
=== Description ===
Integration of EMF resource mappings with the Synchronize view.
==== Categories ====
[[./index.html#Team-related Specifications|Team]], [[./index.html#UI-related Specifications|UI]]
=== Content ===
As a user, I want to easily keep track of the EMF resource mappings (''logical models'' and its containing resources) that I'm currently merging using the Team Synchronizing perspective.
Currently, the Synchronize view shows all resources that have been changed, added, or deleted in the scope of the synchronization. If I double-click a model resource, EMF Compare's merge viewer shows all differences that relate to the double-clicked model resource or the model resources that are part of the same EMF resource mapping as the double-clicked model resource. Consequently, if I double-click ''another'' model resource in the Synchronize view that is part ''of the same EMF resource mapping'', the merge viewer will show the very same changes, but in a different order. If I however double-click ''another'' model resource that is part of ''another EMF resource mapping'', the differences of another (not obviously visible) set of model resources are shown. As a result, users easily get lost during the comparison or merge in the Team Synchronizing perspective.
In general, it is a problem that EMF Compare's merge viewer operates on the level of EMF resource mappings that potentially span multiple resources while the Synchronize view displays the single resources only that may or may not be part of EMF resource mappings. Especially when multiple EMF resource mappings are in the scope of a synchronization, it is hard to keep track, causing the following issues:
# Users don't see the EMF resource mappings in the Synchronize view
# Users don't see which model resources they are currently working on in EMF Compare's merge viewer (except if they switch to the ''By Resource'' group)
# Users don't easily see which model resources relate to which resource in the Synchronize view even when using the ''By Resource'' group (as it only shows the file names but not the project and path, doesn't use the same hierarchy and icons, etc.)
# Users don't see how many EMF resource mappings are in the scope of the change that need to be merged or resolved
==== Proposal ====
The goal of this proposal is three-fold and should be addressed in three iterations:
# ''Extend the Synchronize view'' to be aware of and display EMF resource mappings
# ''Extend the structure merge viewer'' content so that users can directly relate its content to the structure in the Synchronize view
# ''Link the Synchronize view and the structure merge viewer'' so that it shows which model resource we have currently selected
===== 1. Extend the Synchronize view =====
To realize the first goal, we propose to use the extension points ''org.eclipse.team.ui.teamContentProviders'' and ''org.eclipse.ui.navigator.navigatorContent'' as done for Git commits. Once those extension points are implemented, we obtain a new ''model'' (in the sense of the Team API) that we suggest to name ''EMF Logical Models''.
[[Image:./images/US_320_003_1_1.png]]
Once ''EMF Logical Models'' is selected, the Synchronize view shows only model resources and groups them according to the logical models.
[[Image:./images/US_320_003_1_2.png]]
===== 2. Extend the structure merge viewer =====
To make it easier for users to relate the content of the structure merge viewer to the content of the Synchronize view, we propose to add an ''EMF resource mapping'' group for the structure merge viewer that shows the exact same content as in the Synchronize view for the respective EMF resource mapping currently compared, but ''in addition'' the differences of the involved model resources.
[[Image:./images/US_320_003_2.png]]
===== 3. Link the Synchronize view and the structure merge viewer =====
Without having a concrete technical solution in mind, we think users would benefit from linking the selections between the structure merge viewer and the Synchronize view: if a match or difference is selected in the content merge viewer, EMF Compare should select the respective resource that contains the selected match or the match that contains the selected difference in the Synchronize view. Vice versa, if a model resource is selected or double-clicked (and the content merge viewer shows the same EMF resource mapping already), EMF Compare should leave the content of the content merge viewer unchanged and select the respective resource in the content merge viewer tree. Users should however be able to activate or deactivate linking among views, as usual in Eclipse.
Note that it seems that we unfortunately cannot directly use ''Link with Editor'' of the Synchronize view as it requires the comparison editor to have an editor input that adapts to the respective resource to be linked. However, in the content merge viewer, we would have to change the respective resource according to the selection.
== US_320_004 - Comparisons and merges involving resource changes ==
=== Description ===
Management of resource moves and renames with ResourceAttachmentChanges.
Management of the move of a root node of a model resource that contains one or several root nodes (which is necessary for Papyrus notation resources for instance).
==== Categories ====
[[./index.html#Core-related Specifications|Core]], [[./index.html#Team-related Specifications|Team]], [[./index.html#UI-related Specifications|UI]]
=== Content ===
The notion of <code>ResourceLocationChange</code> introduced in a previous version of EMFCompare has limits as soon as resources with several roots are involved in comparisons.
Actually, <code>ResourceLocationChange</code> is only relevant for resources with one root, which is limited and wrong.
Consequently, we introduce the notion of <code>ResourceAttachmentChange</code> with kind <code>MOVE</code>. <code>ResourceLocationChange</code> is consequently deprecated.
This change also implies to modify the way we handle the matching of resources.
Before, when using <code>ResourceLocationChange</code>s to manage the renaming or move or resources, we had to be able to match 2 resources that did not have the same name or path.
Now, with the use of <code>ResourceAttachmentChange/MOVE</code>, we don't have to artificially match 2 resources located in different places.
This is especially more robust when working with git repositories, since in this case comparisons can be handled by matching resources accroding only to their path.
When dealing with EGit, 2 resources with different paths will never be matched.
This does not prevent a <code>ResourceAttachmentChange</code> of kind <code>MOVE</code> to be created, since such a change is attached to the moved root element.
'''''IMPORTANT RESTRICTION'''''<br/>
''Please note that this specification only supports moves of root nodes for EGit comparisons.''<br/>
''Such moves will not be properly detected for local comparisons, since the paths of resources will then always be different.''
However, this solution is more robust, more powerful since it allows to manage resource with several roots (which is the case of GMF notaionf resources for instance), and also more elegant since it does not break the general contract of diffs like <code>ResourceLocationChange</code> did.
This change is accompanied by EGit-specific and papyrus-specific classes registered through extension points:
* <code>EGitPostProcessor</code> in project <code>org.eclipse.emf.compare.egit</code>
** is used to actually create the <code>ResourceAttachmentChange</code> with kind <code>MOVE</code>
* <code>PapyrusResourceAttachmentChangeMerger</code> in project <code>org.eclipse.emf.compare.diagram.ide.ui.papyrus</code>
** is used to merge papyrus-specific empty resources, which contain no model element to which any diff can be attached. This is necessary to properly create or delete empty resources such as *.di files, or sometimes empty *.notation files also.
== US_320_007 - Remove EMFCompareConfiguration from EMFCompareRCPUIPlugin and extract Graph in a separate plug-in ==
=== Description ===
Depreciate the access to <code>EMFCompareConfiguration</code> in the <code>EMFCompareRCPUIPlugin</code>.<br/>
Depreciate the access to <code>Graph</code> in <code>EMFCompareConfiguration</code>.<br/>
Extract the management of the dependency graph from EMFCompare to its own plugin.
==== Categories ====
[[./index.html#Core-related Specifications|Core]]
=== Content ===
==== specification ====
The graphs used by EMFCompare are currently computed and managed by an internal class in <code>org.eclipse.emf.compare</code> bundle. The URI resources graph is shared by all comparisons, its instance being held by the <code>ThreadedModelResolver</code>. Since the bundle <code>org.eclipse.emf.compare.ide.ui</code> needs to access this graph, it is passed throught the <code>EMFCompareConfiguration</code> which is accessible in the <code>EMFCompareRCPUIPlugin</code>.
The <code>EMFCompareRCPUIPlugin</code> and the URI resources Graph are singletons and used for all comparisons. On the other hand, the <code>EMFCompareConfiguration</code> is specific to each comparison and recreated each time.
It seems that the <code>EMFCompareConfiguration</code> has been put in the <code>EMFCompareRCPUIPlugin</code> only to allow the transfert of the URI resources graph and the <code>StructureMergeViewerFilter</code> between plugins. A solution to give access to the URI resources graph is to create a new plugin with the creation and managment of graphs as responsibility. The <code>StructureMergeViewerFilter</code> which is given by the <code>EMFCompareConfiguration</code> through the <code>EMFCompareRCPUIPlugin</code> must be give in another way. A solution is to give it through the <code>TreeItemAdapterFactorySpec</code>.
This work done, the field <code>compareConfiguration</code> and the methods <code>getEMFCompareConfiguration</code> and <code>setEMFCompareConfiguration</code> will be deprecated, and will not have any effects anymore.
==== design ====
Several different graphs are used during a comparison. The URI resources graph is the only one to be unique for all comparisons. The other graphs are comparison specific.
To handle the previously expressed needs, several actions must be performed:
* Extract the classes <code>Graph</code> and <code>ReadOnlyGraph</code> in a new plugin <code>org.eclipse.emf.compare.graph</code>
* The plugin must be a singleton
* The resource graph must be accessible from the plugin added
* The class <code>Graph</code> must remain accessible for comparison needs.
==== test cases ====
The work will be tested by non-regression tests
== Improve performance of conflict detection on large model ==
=== Description ===
As a '''user''',<br/>
I want to '''be able to compare large model (50'000 model elements) with many differences (~30'000 differences) in a reasonable time (less than 1 minute)'''<br/>
so that '''I can compare large models without disrupting my work flow'''
==== Categories ====
[[./index.html#Core-related Specifications|Core]]
=== Content ===
==== Analysis ====
Users who deal with large models complain about the duration of comparisons, especially when a large number of differences is involved.
This is mostly due to:
* The logical model computation (which has however been deeply optimized and for which we lack ideas for improvements)
* The computation of conflicts, because the algorithm implement in class <code>DefaultConflictDetector</code> is ''O(n²)''
An analysis of this algorithm showed that it could be improved to scale much better
==== Design ====
We introduce a new implementation of <code>IConflictDetector</code> called <code>FastConflictDetector</code>.
Instead of iterating over each diff and, for each of them, going over every other diff to check whether it conflicts with it,
the fast conflict detector iterates over each diff and, for each of them, looks for conflict candidates in specific relevant places.
These places are:
* The current diff's <code>Match</code>
* The (indexed) <code>ReferenceChange</code>s that point to the "same" value as the current diff, only if diff is a '''containment''' <code>ReferenceChange</code>.
Consequently, the number of candidates to check for conflict is much smaller than in the default algorithm.
[[Image:./images/FastConflictDetection.png]]
Technically, the implementation delegates the search for candidates to an instance of a specific class, which is instantiated by a factory which takes into account the type and the kind of the diff. This allows the code to be more readable and thus maintainable than previously, because each method acts in a more specific context, which reduces the number of <code>fi</code> statements, for instance. Each of these classes shares behavior by extending a common abstract class.
==== Test Cases ====
The testing strategy is the following:
* to run all the existing tests with both the DefaultConflictDetector and the FastConflictDetector, and to check the results are identical.
* to run manual tests on large models to make sure the user time is reasonable (less than 1 minute for a model as described above)
* to verify the positive impact on the nightly EMFCompare performance measurements
== US_320_008 - Ignore changes in Papyrus di-files ==
=== Description ===
As a '''Papyrus user''',<br/>
I want to '''see only model and diagram changes that I applied and not usage-caused changes of meta-information in di-files'''<br/>
so that '''the list of changes is more concise and I can more easily understand the changes applied between two versions'''
==== Categories ====
[[./index.html#UML-related Specifications|UML]]
=== Related Bugs & Reviews ===
This user story is linked with these bugs & reviews:
* https://bugs.eclipse.org/bugs/show_bug.cgi?id=485494
=== Related Tests ===
This user story is linked with these tests:
* https://git.eclipse.org/c/emfcompare/org.eclipse.emf.compare.git/tree/plugins/org.eclipse.emf.compare.diagram.papyrus.tests/src/org/eclipse/emf/compare/diagram/papyrus/tests/difile/IgnoreDiFilePostProcessorTest.java
* https://git.eclipse.org/c/emfcompare/org.eclipse.emf.compare.git/tree/plugins/org.eclipse.emf.compare.diagram.papyrus.tests.git/src/org/eclipse/emf/compare/diagram/papyrus/tests/egit/IgnoreDiFileChangesInGitMergeTest.java
=== Content ===
In older versions of Papyrus, additional information, such as the open diagram tabs, are stored in the di-files of the Papyrus model. Also with new versions, this information is updated while the user, for instance, changes the open tabs, if the respective content storing this information already exists in the di-file. Users consequently manipulate the di-file "unconsciously" by opening or closing diagrams and may be faced with unclear and rather unimportant merge conflicts during a git merge of Papyrus models.
This is aggravated by the fact that the contents of the di-file is serialized as a model without XMI:IDs or attribute values that allow EMF Compare to match the elements in the di-file accordingly.
Therefore, we introduce a post processor that removes conflicts among changes that affect model elements located in the di-file. If the user opts to include those changes in the comparison anyway, he/she still can deactivate the "Ignore Papyrus Di-files Post-Processor".
== US_320_009 - Multiplicity Element Change ==
=== Description ===
As a '''Papyrus user''',<br/>
I want to '''see conflicts of multiplicity changes only if they are different'''<br/>
so that '''the list of changes is more concise and the list of conflicts is minimal'''
==== Categories ====
[[./index.html#UML-related Specifications|UML]]
=== Related Bugs & Reviews ===
This user story is linked with these bugs & reviews:
* https://bugs.eclipse.org/bugs/show_bug.cgi?id=479449
=== Content ===
==== Analysis ====
Users would expect that setting the multiplicity to the ''same'' values on both sides wouldn't result in a real conflict -- only a pseudo conflict. EMF Compare does already raise a conflict only if the same feature value is changed on both sides to ''different'' values. For simple-type values, such as integers, it compares the values directly and for EObject values, it uses the match model to determine whether the values are actually different.
In a UML multiplicity element, its lower and upper value are represented as UML instance specifications, which are EObjects, rather than simple integer values. When now a multiplicity element is set to the same value on both sides, the Papyrus editor will create new UML instance specification objects, which represent the same value, but which have different XMI:IDs. As they have different XMI:IDs, they have not been matched by the ID-based match engine and thus are considered as different. Consequently, EMF Compare always raises a conflict on a concurrent multiplicity change, even if the changes set the multiplicity to the same value.
==== Design ====
There are two different ways of addressing this issue:
# Register a specific EqualityHelper that, if asked for equality of UML instance specifications, determines the equality based on the actual simple-typed value they carry rather than relying on the match model.
# Introduce a specific UML diff type ''MultiplicityChange'' and specific conflict handling in the UML post-processor.
Whereas the first option is simpler, it may have unwanted side-effects, because all instance specifications that carry the same value would then be considered as equal by the EqualityHelper, whether they are inside a multiplicity element or not. As instance specifications are used all over the place in UML, this seems to be risky without analyzing the consequences in detail.
The second option has not only the advantage that it has no unforeseen side-effects, it also allows represent multiplicity changes in a more user-friendly way. That is, EMF Compare would not only show "lowerValue changed", but could elaborate that the lower value ''of the multiplicity'' has changed. In the user interface of Papyrus, the UI control to change the lower and upper value is also called ''multiplicity''. Thus, mentioning ''multiplicity'' will be more in line with what the user expects.
In summary, we advocate for the second option: the UML diff type.