Skip to main content

Notice: this Wiki will be going read only early in 2024 and edits will no longer be possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.

Jump to: navigation, search

Difference between revisions of "EMF Compare/Specifications/MergeExtension"

 
(10 intermediate revisions by 3 users not shown)
Line 1: Line 1:
 +
{{Template:EMF Compare Archive Notice}}
 +
 
= Evolution Specification: Provide a merge extension mechanism  =
 
= Evolution Specification: Provide a merge extension mechanism  =
  
Current status is '''DRAFT'''
+
Current status is '''ARCHIVED'''
  
 
== Preamble  ==
 
== Preamble  ==
Line 25: Line 27:
 
Standard merge operations will be rewritten with the lowest ranking in order to be overrideable.
 
Standard merge operations will be rewritten with the lowest ranking in order to be overrideable.
  
 +
[[Image:MergeExtensionClassDiagram.png]]
 +
 +
[[Image:MergeExtensionSeq.png]]
  
 
== Backward Compatibility and Migration Paths ==
 
== Backward Compatibility and Migration Paths ==
Line 30: Line 35:
 
=== Metamodel Changes ===
 
=== Metamodel Changes ===
  
This evolution does not change any metamodel.
+
Diff.copyLeftToRight() and Diff.copyRightToLeft() are now deprecated.
 +
 
 +
Merging a single diff sometimes requires EMF Compare to merge other differences. Requirements and equivalences come to mind, but there are also refining and extension that will trigger the merge of multiple differences at once. We need to be able to ask the merger registry for the correct merger for every single diff, which cannot be done from the differences themselves.
 +
 
 +
These two methods have been deprecated, though we expect no breakage as they delegate to a "standalone" implementation of the merger registry. However, all uses of these APIs should be migrated to the new one, namely :
 +
 
 +
<source lang="java">
 +
diff.copyRightToLeft();
 +
</source>
 +
 
 +
becomes
 +
 
 +
* '''In standalone mode''' :
 +
<source lang="java">
 +
IMerger.Registry registry = IMerger.RegistryImpl.createStandaloneInstance();
 +
registry.getHighestRankingMerger(diff).copyRightToLeft(diff, new BasicMonitor());
 +
</source>
 +
 
 +
* '''From a plug-in''' :
 +
 
 +
<source lang="java">
 +
IMerger.Registry registry = EMFCompareIdePugin.getDefault().getMergerRegistry();
 +
registry.getHighestRankingMerger(diff).copyRightToLeft(diff, new BasicMonitor());
 +
</source>
 +
 
 +
Likewise, merging differences in a batch operation previously required a for loop such as
 +
 
 +
<source lang="java">
 +
for (Diff diff : comparison.getDifferences()) {
 +
  diff.copyRightToLeft();
 +
}
 +
</source>
 +
 
 +
This should now be changed to (the same as above applies for standalone/plug-in use) :
 +
 
 +
<source lang="java">
 +
IMerger.Registry registry = IMerger.RegistryImpl.createStandaloneInstance();
 +
IBatchMerger merger = new BatchMerger(registry);
 +
merger.copyAllRightToLeft(comparison.getDifferences(), new BasicMonitor());
 +
</source>
  
 
=== API Changes ===
 
=== API Changes ===
  
 
* Add interfaces:
 
* Add interfaces:
 +
 +
This change will mainly add two public interfaces : IMerger represents the merge for individual differences and will hold the merging code currently implemented within the Diffs themselved, while IBatchMerger represents a batch operation and will allow the customization of how multiple differences are merged concurrently.
 +
 
<source lang="java">
 
<source lang="java">
 
public interface IMerger {
 
public interface IMerger {
Line 65: Line 112:
 
}
 
}
  
 +
}
 +
</source>
 +
 +
<source lang="java">
 +
public interface IBatchMerger {
 +
void copyAllLeftToRight(Iterable<? extends Diff> differences, Monitor monitor);
 +
 +
void copyAllRightToLeft(Iterable<? extends Diff> differences, Monitor monitor);
 
}
 
}
 
</source>
 
</source>
Line 74: Line 129:
 
Example of use:
 
Example of use:
 
<source lang="xml">
 
<source lang="xml">
<extension
+
<extension point="org.eclipse.emf.compare.ide.mergerExtension">
    point="org.eclipse.emf.compare.mergerExtension">
+
  <merger
  <merger
+
      class="org.eclipse.emf.compare.merge.ResourceAttachmentChangeMerger"
        class="org.eclipse.emf.compare.extension.merge.DefaultMerger"
+
      ranking="10">
        ranking="0">
+
  </merger>
  </merger>
+
  <merger
 +
      class="org.eclipse.emf.compare.merge.ReferenceChangeMerger"
 +
      ranking="10">
 +
  </merger>
 +
  <merger
 +
      class="org.eclipse.emf.compare.merge.AttributeChangeMerger"
 +
      ranking="10">
 +
  </merger>
 
</extension>
 
</extension>
 
</source>
 
</source>

Latest revision as of 12:24, 5 March 2014

THIS PAGE IS ARCHIVED. IT IS PROBABLY OUTDATED AND WILL NOT BE UPDATED

Evolution Specification: Provide a merge extension mechanism

Current status is ARCHIVED

Preamble

It enables to provide his own merger implementation for a set of differences concerned by a given predicate.


Introduction

The merge operation is implemented on a per difference type. It has three implementations in the core engine (ReferenceChange, AttributeChange and ResourceAttachmentChange). Each extension (UML, GMF Notation) has to provide its own type of difference to override the merge semantic. This is not very flexible and the required number of difference types it requires to implement does not add any value.


Detailed Specification

We propose to provide a merge extension mechanism.

Any extension will be able to contribute a merger on a subclass of Diff. The mergers registry will be queried each time a merge about to be performed. A merger contribution will provide its own predicate that will need to be verified before it is considered to be a valid candidate for a difference. It will also have a ranking in order to choose over multiple possible merger for a given difference.

Standard merge operations will be rewritten with the lowest ranking in order to be overrideable.

MergeExtensionClassDiagram.png

MergeExtensionSeq.png

Backward Compatibility and Migration Paths

Metamodel Changes

Diff.copyLeftToRight() and Diff.copyRightToLeft() are now deprecated.

Merging a single diff sometimes requires EMF Compare to merge other differences. Requirements and equivalences come to mind, but there are also refining and extension that will trigger the merge of multiple differences at once. We need to be able to ask the merger registry for the correct merger for every single diff, which cannot be done from the differences themselves.

These two methods have been deprecated, though we expect no breakage as they delegate to a "standalone" implementation of the merger registry. However, all uses of these APIs should be migrated to the new one, namely :

diff.copyRightToLeft();

becomes

  • In standalone mode :
IMerger.Registry registry = IMerger.RegistryImpl.createStandaloneInstance();
registry.getHighestRankingMerger(diff).copyRightToLeft(diff, new BasicMonitor());
  • From a plug-in :
IMerger.Registry registry = EMFCompareIdePugin.getDefault().getMergerRegistry();
registry.getHighestRankingMerger(diff).copyRightToLeft(diff, new BasicMonitor());

Likewise, merging differences in a batch operation previously required a for loop such as

for (Diff diff : comparison.getDifferences()) {
  diff.copyRightToLeft();
}

This should now be changed to (the same as above applies for standalone/plug-in use) :

IMerger.Registry registry = IMerger.RegistryImpl.createStandaloneInstance();
IBatchMerger merger = new BatchMerger(registry);
merger.copyAllRightToLeft(comparison.getDifferences(), new BasicMonitor());

API Changes

  • Add interfaces:

This change will mainly add two public interfaces : IMerger represents the merge for individual differences and will hold the merging code currently implemented within the Diffs themselved, while IBatchMerger represents a batch operation and will allow the customization of how multiple differences are merged concurrently.

public interface IMerger {
 
	boolean isMergerFor(Diff target);
 
	int getRanking();
 
	void setRanking(int parseInt);
 
	void copyRightToLeft(Diff target, Monitor monitor);
 
	void copyLeftToRight(Diff target, Monitor monitor);
 
	void setRegistry(Registry registry);
 
	Registry getRegistry();
 
	interface Registry {
 
		IMerger getHighestRankingMerger(Diff target);
 
		Collection<IMerger> getMergers(Diff target);
 
		IMerger add(IMerger merger);
 
		IMerger remove(String className);
 
		void clear();
	}
 
}
public interface IBatchMerger {
	void copyAllLeftToRight(Iterable<? extends Diff> differences, Monitor monitor);
 
	void copyAllRightToLeft(Iterable<? extends Diff> differences, Monitor monitor);
}
  • Add extension point:
<extension-point id="mergerExtension" name="Merger Extension" schema="schema/MergerExtension.exsd"/>

Example of use:

<extension point="org.eclipse.emf.compare.ide.mergerExtension">
  <merger
      class="org.eclipse.emf.compare.merge.ResourceAttachmentChangeMerger"
      ranking="10">
  </merger>
  <merger
      class="org.eclipse.emf.compare.merge.ReferenceChangeMerger"
      ranking="10">
  </merger>
  <merger
      class="org.eclipse.emf.compare.merge.AttributeChangeMerger"
      ranking="10">
  </merger>
</extension>
  • Change of createCopyCommand() and createCopyAllNonConflictingCommand() methods in ICompareEditingDomain:
Command createCopyCommand(Diff diff, boolean leftToRight, IMerger.Registry mergerRegistry);	
Command createCopyAllNonConflictingCommand(List<? extends Diff> differences, boolean leftToRight, IMerger.Registry mergerRegistry);

User Interface Changes

This evolution does not change any user interface.

Documentation Changes

This documentation will have to be updated:

  • New and Noteworthy
  • Developer Guide


Tests and Non-regression strategy

JUnit tests: ExtensionMergeTest.java in o.e.e.c.tests, o.e.e.c.diagram.ecoretools.tests, o.e.e.c.uml2.tests.

Manual tests: Detection of the extension launching a merge action.


Implementation choices and tradeoffs

N/A

Back to the top