* Move of a node within the diagram (with a configurable translation threshold for the move its location x/y).

* Move of a node within the diagram (with a configurable translation threshold for the move its location x/y).

* Move of an edge within the diagram (total number of bendpoints, change of bendpoints - sourceX, sourceY, targetX, targetY - and positions of the anchors).

* Move of an edge within the diagram (total number of bendpoints, change of bendpoints - sourceX, sourceY, targetX, targetY - and positions of the anchors).

Line 21:

Line 21:

For many cases, we need the semantic comparison to be done before the graphical one. The work on logical model integration should give us this facility by computing the differences of a whole resource set instead of just the current resource containing the notation model.

For many cases, we need the semantic comparison to be done before the graphical one. The work on logical model integration should give us this facility by computing the differences of a whole resource set instead of just the current resource containing the notation model.

−

The link with the semantic comparison had to be provided for the labels. For each element of type.startsWith("40"), we have to get the text of the label et compare them. They are not stored directly into the notation model.

+

The link with the semantic comparison had to be provided for the labels. For each element , we have to get the text of the label and compare them. They are not stored directly into the notation model.

Move operations of Edge and Node never correspond to semantic change.

Move operations of Edge and Node never correspond to semantic change.

Line 29:

Line 29:

=== Merge ===

=== Merge ===

−

As a we don't know from the notation model how labels are build and from which feature(s) of the semantic model, the merge operation of labels modification must be applied on the notation model to trigger the appropriate underlying commands on the semantic model. This merger operation can be triggerred only if the label is editable (=> ask to the editpart of the view '''isEditModeEnabled()''')

+

As a we don't know from the notation model how labels are build and from which feature(s) of the semantic model, the merge operation of labels modification must be applied on the notation model to trigger the appropriate underlying commands on the semantic model. This merger operation can be triggered only if the label is editable (=> ask to the editpart of the view '''isEditModeEnabled()''')

The merge of a move a node or an edge never triggers a merge on the semantic model, only on the graphical notation. The merge is a simple copy of values of bendpoints/layout constraints.

The merge of a move a node or an edge never triggers a merge on the semantic model, only on the graphical notation. The merge is a simple copy of values of bendpoints/layout constraints.

Addition/Removal of node or edge trigger the merge of the semantic difference if it is associated to one, and the merge operation of the graphical difference otherwise. This merge operation consist of re-create the element if it has been deleted from the diagram, or to restor the hidden status of this view (View.isVisible())

Addition/Removal of node or edge trigger the merge of the semantic difference if it is associated to one, and the merge operation of the graphical difference otherwise. This merge operation consist of re-create the element if it has been deleted from the diagram, or to restor the hidden status of this view (View.isVisible())

+

+

== Use of Difference Extensions and Hiding mechanism ==

+

+

To detect the differences related to functional cases of diagram comparison, new kinds of differences (extensions) are created to complete the DiffModel.

+

+

These extensions lean on the generic differences to be build and they are able to hide them.

+

+

Here is the list of the generic differences which are managed and, for each of them, what are the extensions which are created and the differences which are hidden:

+

+

* A '''ModelElementChangeLeftTarget''' difference, related to a ''View'', will involve the creation of a '''''DiagramModelElementChangeLeftTarget''''' difference extension. This extension will hide the '''ModelElementChangeLeftTarget''' input difference which was used to build it.

+

+

* In the same way, a '''ModelElementChangeRightTarget''' difference, related to a ''View'', will involve the creation of a '''''DiagramModelElementChangeRightTarget''''' difference extension. This extension will hide the '''ModelElementChangeRightTarget''' input difference which was used to build it.

+

+

* An '''UpdateAttribute''' on the ''EAttribute'' "''View_visible''", where the right view is not visible and it is not a remotely change OR the right view is visible but it is a remotely change, will involve the creation of a '''''DiagramShowElement''''' difference extension. This one will hide the '''UpdateAttribute''' input difference which was used to build it.

+

+

* In the same way, an '''UpdateAttribute''' on the ''EAttribute'' "''View_visible''", where the left view is not visible and it is not a remotely change or the left view is visible but it is a remotely change, will involve the creation of a '''''DiagramHideElement''''' difference extension. This one will hide the '''UpdateAttribute''' input difference which was used to build it.

+

+

* An '''UpdateAttribute''', where the container of its ''EAttribute'' is a ''Location'' and the related compared elements are not edges and the move is over the threshold specified in the page preferences, will involve the creation of a '''''DiagramMoveNode''''' difference extension. This extension will hide the '''UpdateAttribute''' input difference which was used to build it.

+

+

* On each matched object, it is checked (in the same time as the attributes checking) if the GMF labels are different to create a '''''DiagramLabelChange''''' difference extension. This one hides no existing difference. To check the labels, the ''ITextAwareEditPart'' edit parts are retrieved and their GMF parser to get the print string and to compare them.

+

+

* An '''UpdateAttribute''', where the container of its ''EAttribute'' is a ''RelativeBendpoints'' OR the ''EAttribute'' is ''IdentityAnchor_Id'', will involve the creation of a '''''DiagramEdgeChange''''' difference extension. Besides, an '''ModelElementChange''', where the related element is an ''IdentityAnchor'', will involve the creation of a '''''DiagramEdgeChange''''' difference extension too. For a same ''Edge'', it is possible to have several combined generic differences (several '''UpdateAttribute''' and '''ModelElementChange'''). To create only one extension for these ones, it is checked if there already exists a '''''DiagramEdgeChange''''' for this ''Edge'' in the building ''DiffModel''. This extension will hide the '''UpdateAttribute''' and/or '''ModelElementChange''' input differences which were used to build it.

+

+

=== Mergers ===

+

+

* For every difference extensions which lean on diagram changes only (no semantic changes), a single merger is used to merge these ones: ''DiagramDiffExtensionMerger''.

+

It is the case of ''DiagramShowElement'', ''DiagramHideElement'', ''DiagramMoveNode'' and ''DiagramEdgeChange'' difference extensions. The merger retrieves all the hidden differences of the extension and call the related merger for each of them.

+

+

* For ''DiagramLabelChange'', a ''DiagramlabelChangeMerger'' is used to set the new label from the GMF Command. This command allows to deploy changes on the semantic model.

+

+

* For ''DiagramModelElementChangeLeftTarget'' and ''DiagramModelElementChangeRightTarget'', a respectively ''DiagramModelElementChangeLeftTargetMerger'' and ''DiagramModelElementChangeRightTargetMerger'' are used. They have the same behavior as ''DiagramDiffExtensionMerger'' unless for the merge of the delete of a ''View''. Indeed, for the add of a View, the generic merger is able to merge the ''View'' and the semantic object together. But, for the delete, it does not manage to merge the semantic difference. These 2 mergers retrieve the semantic difference to merge it before the merge of the delete of the View.

== GMF editor integration within Comparison editor ==

== GMF editor integration within Comparison editor ==

Line 41:

Line 72:

The content merge viewer has to instantiate DiagramGraphicalViewer inside its '''createControls()''' method:

The content merge viewer has to instantiate DiagramGraphicalViewer inside its '''createControls()''' method:

viewer_left.setContents(diag_left); // the diagram from the notation model

+

viewer.setContents(diag); // the diagram from the notation model

It is also possible to make the viewer uneditable by browsing all children of the rootEditPart of each viewer, but then, we will not be able to ask for the '''editability''' of views. It should be better to add a top layer that forbid the editing.

It is also possible to make the viewer uneditable by browsing all children of the rootEditPart of each viewer, but then, we will not be able to ask for the '''editability''' of views. It should be better to add a top layer that forbid the editing.

Line 67:

Line 98:

== Markers for GMF diagrams ==

== Markers for GMF diagrams ==

−

Difference marker on notation model are provided by extending the '''org.eclipse.gmf.examples.runtime.diagram.decorator.provider.ReviewDecoratorProvider''' extension point.

+

Difference marker on notation model are provided by using the '''org.eclipse.gmf.runtime.diagram.ui.decoratorProviders''' extension point.

−

The provided IDecoratorProvider will create a decorator based on the proposed IDecoratorTarget. This IDecoratorTarget can be adapted to Notation View

+

The provided IDecoratorProvider will create a decorator based on the proposed IDecoratorTarget. This IDecoratorTarget can be adapted to a Notation View like this :

View view = (View) decoratorTarget.getAdapter(View.class);

View view = (View) decoratorTarget.getAdapter(View.class);

Line 79:

Line 110:

The issue with specific decorator is to define the locator. Each Figure has its own bounds and we will start from the assumption that:

The issue with specific decorator is to define the locator. Each Figure has its own bounds and we will start from the assumption that:

−

* Marker of decorated figure will be rectangle following their bounds (smallest rectangle completely enclosing the IFigure)

+

* Marker of decorated figure will be rectangle following their bounds (smallest rectangle completely enclosing the IFigure)

−

* Marker of decorated edges will be handled for polylines only and bounds of the decoration will be the bounds of the decorated

+

* Marker of decorated edges will be handled for polylines only and bounds of the decoration will be the bounds of the decorated

−

* Marker of move will be an icon (picture not yet defined) located:

+

* Marker of move will be an icon (picture not yet defined) located:

−

* in the middle of the edge if the edge has moved

+

** in the middle of the edge if the edge has moved

−

* in the top right of the bounds of the figure if it is a node.

+

** in the top right of the bounds of the figure if it is a node.

See samples of first annotation prototypes (on Ecore diagram):

See samples of first annotation prototypes (on Ecore diagram):

Line 101:

Line 132:

Edge marked (moved)

Edge marked (moved)

[[Image:markedMovedEdge.png]]

[[Image:markedMovedEdge.png]]

+

+

=== Implementation ===

+

+

Here are some screenshots of the current development under the ericsson_integration branch of the following repository https://github.com/mbarbero/emfcompare

+

+

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

+

|-

+

! align="center" colspan="4" | EcoreTools Tests Cases

+

|-

+

! align="center"| Description

+

! align="center"| State

+

! align="center" colspan="2"| Screenshot

+

|-

+

| Added nodes

+

! style="color:green" | ok

+

| [[Image:TC1.png|thumb]]

+

|-

+

| Deleted nodes

+

! style="color:green" | ok

+

| [[Image:TC2.png|thumb]]

+

|-

+

| Mix of added and deleted nodes

+

! style="color:green" | ok

+

| [[Image:TC3.png|thumb]]

+

|-

+

| Added node inside a node

+

! style="color:green" | ok

+

| [[Image:TC04.png|thumb]]

+

|-

+

| Removed node inside a node

+

! style="color:green" | ok

+

| [[Image:TC05.png|thumb]]

+

|-

+

| Moved node

+

! style="color:green" | ok

+

| [[Image:TC6.png|thumb]]

+

| [[Image:preference.png|thumb|A move threshold can be set in the preference page to detect this change]]

Revision as of 02:46, 18 October 2012

The GMF diagram comparison task can be splitted into four parts. First, we must be able to compare GMF Notation models, then we have to know how we handle the link with the comparison of the semantic model (i.e. the elements represented by the diagram). Third, we have to know how to integrate existing GMF editor within the EMF Compare editor. Finally, we have to know how to create generic markers on the diagram to give a feedback of the computed differences to the user.

Notation model comparison

Notation model comparison need its own MatchEngine and DiffEngine. The whole notation metamodel will not be taken into account. The difference computation will only occur on a subpart as depicted below:

The nodes and edges will be matched by their XMI IDs. Containment between nodes will be handled in a generic way (i.e. by the super class GenericMatchEngine).

Only following differences will be computed:

Addition / Removal of a node

Addition / Removal of an edge

Change of a Label on an edge or on a node

Move of a node within the diagram (with a configurable translation threshold for the move its location x/y).

Move of an edge within the diagram (total number of bendpoints, change of bendpoints - sourceX, sourceY, targetX, targetY - and positions of the anchors).

Link with the semantic comparison

For many cases, we need the semantic comparison to be done before the graphical one. The work on logical model integration should give us this facility by computing the differences of a whole resource set instead of just the current resource containing the notation model.

The link with the semantic comparison had to be provided for the labels. For each element , we have to get the text of the label and compare them. They are not stored directly into the notation model.

Move operations of Edge and Node never correspond to semantic change.

For addition and removal of nodes and edges, graphical differences may or may not corresponds to a semantic change. For instance, a graphical element may be removed because it has been hidden or deleted from the diagram. It does not correspond to a change in the semantic model. This graphical change does not have to be linked to a semantic change. In the other case, the addition or the removal of a node or an edge must match an addition or a deletion in the semantic model.

Merge

As a we don't know from the notation model how labels are build and from which feature(s) of the semantic model, the merge operation of labels modification must be applied on the notation model to trigger the appropriate underlying commands on the semantic model. This merger operation can be triggered only if the label is editable (=> ask to the editpart of the view isEditModeEnabled())

The merge of a move a node or an edge never triggers a merge on the semantic model, only on the graphical notation. The merge is a simple copy of values of bendpoints/layout constraints.

Addition/Removal of node or edge trigger the merge of the semantic difference if it is associated to one, and the merge operation of the graphical difference otherwise. This merge operation consist of re-create the element if it has been deleted from the diagram, or to restor the hidden status of this view (View.isVisible())

Use of Difference Extensions and Hiding mechanism

To detect the differences related to functional cases of diagram comparison, new kinds of differences (extensions) are created to complete the DiffModel.

These extensions lean on the generic differences to be build and they are able to hide them.

Here is the list of the generic differences which are managed and, for each of them, what are the extensions which are created and the differences which are hidden:

A ModelElementChangeLeftTarget difference, related to a View, will involve the creation of a DiagramModelElementChangeLeftTarget difference extension. This extension will hide the ModelElementChangeLeftTarget input difference which was used to build it.

In the same way, a ModelElementChangeRightTarget difference, related to a View, will involve the creation of a DiagramModelElementChangeRightTarget difference extension. This extension will hide the ModelElementChangeRightTarget input difference which was used to build it.

An UpdateAttribute on the EAttribute "View_visible", where the right view is not visible and it is not a remotely change OR the right view is visible but it is a remotely change, will involve the creation of a DiagramShowElement difference extension. This one will hide the UpdateAttribute input difference which was used to build it.

In the same way, an UpdateAttribute on the EAttribute "View_visible", where the left view is not visible and it is not a remotely change or the left view is visible but it is a remotely change, will involve the creation of a DiagramHideElement difference extension. This one will hide the UpdateAttribute input difference which was used to build it.

An UpdateAttribute, where the container of its EAttribute is a Location and the related compared elements are not edges and the move is over the threshold specified in the page preferences, will involve the creation of a DiagramMoveNode difference extension. This extension will hide the UpdateAttribute input difference which was used to build it.

On each matched object, it is checked (in the same time as the attributes checking) if the GMF labels are different to create a DiagramLabelChange difference extension. This one hides no existing difference. To check the labels, the ITextAwareEditPart edit parts are retrieved and their GMF parser to get the print string and to compare them.

An UpdateAttribute, where the container of its EAttribute is a RelativeBendpoints OR the EAttribute is IdentityAnchor_Id, will involve the creation of a DiagramEdgeChange difference extension. Besides, an ModelElementChange, where the related element is an IdentityAnchor, will involve the creation of a DiagramEdgeChange difference extension too. For a same Edge, it is possible to have several combined generic differences (several UpdateAttribute and ModelElementChange). To create only one extension for these ones, it is checked if there already exists a DiagramEdgeChange for this Edge in the building DiffModel. This extension will hide the UpdateAttribute and/or ModelElementChange input differences which were used to build it.

Mergers

For every difference extensions which lean on diagram changes only (no semantic changes), a single merger is used to merge these ones: DiagramDiffExtensionMerger.

It is the case of DiagramShowElement, DiagramHideElement, DiagramMoveNode and DiagramEdgeChange difference extensions. The merger retrieves all the hidden differences of the extension and call the related merger for each of them.

For DiagramLabelChange, a DiagramlabelChangeMerger is used to set the new label from the GMF Command. This command allows to deploy changes on the semantic model.

For DiagramModelElementChangeLeftTarget and DiagramModelElementChangeRightTarget, a respectively DiagramModelElementChangeLeftTargetMerger and DiagramModelElementChangeRightTargetMerger are used. They have the same behavior as DiagramDiffExtensionMerger unless for the merge of the delete of a View. Indeed, for the add of a View, the generic merger is able to merge the View and the semantic object together. But, for the delete, it does not manage to merge the semantic difference. These 2 mergers retrieve the semantic difference to merge it before the merge of the delete of the View.

GMF editor integration within Comparison editor

The integration of GMF editor within the comparison editor has to be done through specific contentMergeViewer (org.eclipse.compare.contentMergeViewers extension point) and maybe a specific structureMergerViewer (org.eclipse.compare.structureMergeViewers extension point) to provide the separation between graphical differences and semantic differences.

The content merge viewer has to instantiate DiagramGraphicalViewer inside its createControls() method:

It is also possible to make the viewer uneditable by browsing all children of the rootEditPart of each viewer, but then, we will not be able to ask for the editability of views. It should be better to add a top layer that forbid the editing.

Markers for GMF diagrams

Difference marker on notation model are provided by using the org.eclipse.gmf.runtime.diagram.ui.decoratorProviders extension point.

The provided IDecoratorProvider will create a decorator based on the proposed IDecoratorTarget. This IDecoratorTarget can be adapted to a Notation View like this :

View view = (View) decoratorTarget.getAdapter(View.class);

The decorator should be created if, and only if, there is a graphical difference associated with the given View. The graphical difference model will be retrieved from the owning EditPart.

Provided decorators has to implement IDecorator interface.

The issue with specific decorator is to define the locator. Each Figure has its own bounds and we will start from the assumption that:

Marker of decorated figure will be rectangle following their bounds (smallest rectangle completely enclosing the IFigure)

Marker of decorated edges will be handled for polylines only and bounds of the decoration will be the bounds of the decorated