Problem with merge: duplicate objects are created [message #1695969] |
Wed, 20 May 2015 16:17 |
Erwan Bousse Messages: 7 Registered: May 2015 |
Junior Member |
|
|
Hi!
I am trying to use EMFCompare programmatically to find the differences between two models A and B, and to resolve all the differences so that in the end A is exactly the same as B.
However I have the following issue : in some situations, objects in B that are copied in A are copied twice. This seems to happen when an object is referenced twice, therefore when the two diffs are taken into account, the object is copied twice.
I have written this custom merger :
class Merger extends AbstractMerger {
public Merger() {
setRegistry(EMFCompareRCPPlugin.getDefault().getMergerRegistry());
}
@Override
public boolean isMergerFor(Diff target) {
// TODO Auto-generated method stub
return false;
}
@Override
public void copyRightToLeft(Diff target, Monitor monitor) {
this.mergeDiff(target, true, monitor);
}
@Override
public void copyLeftToRight(Diff target, Monitor monitor) {
this.mergeDiff(target, false, monitor);
}
}
And the following code to resolve the differences :
EObject left = ....;
EObject right = ....;
IComparisonScope scope = new DefaultComparisonScope(left, right, null);
EMFCompare build = EMFCompare.builder().build();
Comparison comparison = build.compare(scope);
List<Diff> differences = comparison.getDifferences();
Merger merger = new Merger();
BasicMonitor monitor = new BasicMonitor();
for (Diff diff : differences)
{
// if reference, use the merger.
merger.copyLeftToRight(diff, monitor);
diff.setState(DifferenceState.UNRESOLVED);
}
}
Maybe I am doing the whole thing wrong?
Thanks in advance,
|
|
|
Re: Problem with merge: duplicate objects are created [message #1696167 is a reply to message #1695969] |
Fri, 22 May 2015 13:51 |
Erwan Bousse Messages: 7 Registered: May 2015 |
Junior Member |
|
|
So I finally solved my problem by writing this very ugly merger :
class Merger extends AbstractMerger {
/**
* We want to bypass the reference merger that is eventually called by the
* abstract merger, so we create this merger with a very high ranking.
*
* The goal of the bypass is th replace the operation createCopy, so that
* objects are not created multiple times.
*
*/
public static class CustomReferenceMerger extends ReferenceChangeMerger {
final EcoreUtil.Copier copier = new EMFCompareCopier();
protected EObject createCopy(EObject referenceObject) {
if (copier.containsKey(referenceObject))
return copier.get(referenceObject);
return copier.copy(referenceObject);
}
@Override
public int getRanking() {
return Integer.MAX_VALUE;
}
}
public Merger() {
setRegistry(EMFCompareRCPPlugin.getDefault().getMergerRegistry());
getRegistry().add(new CustomReferenceMerger());
}
@Override
public boolean isMergerFor(Diff target) {
// TODO Auto-generated method stub
return false;
}
@Override
public void copyRightToLeft(Diff target, Monitor monitor) {
this.mergeDiff(target, true, monitor);
}
@Override
public void copyLeftToRight(Diff target, Monitor monitor) {
this.mergeDiff(target, false, monitor);
}
}
This workaround aims at bypassing the "createCopy" operation that is used by a merger to create new objects. The original version creates a copier, makes a copy, then throw the copier away, hence making it impossible to avoid duplicating objects by checking if the copy hadn't already been done.
However, the "mergeDiff" operation uses a registry to find the correct merger for references, which means that our Merger is not used for "createCopy". Hence this "CustomReferenceMerger" with the highest ranking in the registry, with a new working createCopy operation.
With this hack, I can now transform successfully a model A into a model B by merging the found differences into A. But I guess that there is a better way to do so .
|
|
|
Re: Problem with merge: duplicate objects are created [message #1696369 is a reply to message #1696167] |
Tue, 26 May 2015 07:14 |
|
Erwan,
There are differences for every single diff in the model, including equivalent differences (for example differences on the two ends of an eOpposite relationship). Therefore, merging "all" diferences in the Comparison model from one side to the other without regards for the requirements, implcations, equivalences and conflicts will most likely corrupt the target model (for example, by creating multiple copies of the same object).
Please look at the entry in the FAQ on how to use EMF Compare programmatically, especially on the last lines using the BatchMerger.
Laurent Goubet
Obeo
|
|
|
Powered by
FUDForum. Page generated in 0.02836 seconds