How to get correct Diffs when using EMF compare on structurally equal objects which are different as per ==?

222 Views Asked by At

Followups below

Let's say I have this simple model (Xcore syntax):

class A {
  contains B[] bs opposite a
}

class B {
  String foo
  container A a opposite bs
}

I now have three A's, created like the following:

A a1 = ModelFactory.eINSTANCE.createA();
B b1 = ModelFactory.eINSTANCE.createB();
b1.setFoo("foo");
b1.setA(a1);

A a2 = ModelFactory.eINSTANCE.createA();
B b2 = ModelFactory.eINSTANCE.createB();
b2.setFoo("bar");
b2.setA(a2);

A a3 = ModelFactory.eINSTANCE.createA();
B b3 = ModelFactory.eINSTANCE.createB();
b3.setFoo("bar");
b3.setA(a3);

When I try to compare them like this:

DefaultComparisonScope scope = new DefaultComparisonScope(a1, a2, a3);
Comparison comp = EMFCompare.builder().build().compare(scope);
EList<Diff> diffs = comp.getDifferences();

I am expecting to get one attribute change on the B__FOO EAttribute, but I get two pseudo conflicts for the ADD kind for A__BS. I think this is because of how EMF handles equality, and the A's and B's are, technically, different.

How do I achieve that I get the "correct" differences?

Followup 1

I recreated this example in a fresh workspace, but I added an UUID to the A and B type (as my "real" model has, too), and this works as expected. Now on to finding out why my "real" model doesn't...

1

There are 1 best solutions below

0
On

The problem here is that EMF Compare cannot properly match the elements, as you have realized by adding an UUID.

As I see it, EMF Compare should be able to match your B elements since they have something inside them to differentiate and match, but the A, on the contrary, don't hold any information by themselves. Adding an UUID to your elements forces their identity and allows EMF Compare to know who's who.

You can circumvent the issue by adding your own logic to match your elements. I assume this is not how your actual model (and metamodel) will look like so you might have ways to differentiate your elements better (or better yet, to make sure your models have identifiers). The matching logic can be redefined in multiple ways. One is to change the ID function (in charge of computing element ids) if your case includes a way to uniquely identify your elements that is not through an id attribute or change the equality helper so that you can tell EMF Compare exactly how to match your objects (there is no sample code in the documentation for that, but you can see on the ID function snippet how to change the "equality helper factory").