Home » Modeling » Compare » Determine if two Ecore xmi models are equal
Determine if two Ecore xmi models are equal [message #1748514] |
Wed, 23 November 2016 20:56 |
Nicolas Paetzold Messages: 3 Registered: November 2016 |
Junior Member |
|
|
Hi everyone,
I'm trying to use EMF Compare programmatically to determine if two Ecore xmi models are equal or not. The two models will be created completely separately from each other by two different ATL transformations.
I started by using the Families metamodel (from the ATL zoo) and comparing two simple models. The problem is that even if I compare the exact same model (I created one model and copied it into another file) the comparing result shows me differences. At first I was using the default match engine. Then I tried to ignore identifiers in the match engine and setting the ranking to 20 (as in the developer guide described) but the result does not change. I still get these two differences (I don't know what they mean):
UNRESOLVED LEFT ADD ReferenceChangeSpec{reference=Family.sons, value=Member@47d9a273, parentMatch=MatchSpec{left=Family@659499f1, right=Family@3cebbb30, origin=<null>, #differences=1, #submatches=5}, match of value=MatchSpec{left=Member@47d9a273, right=<null>, origin=<null>, #differences=0, #submatches=0}}
UNRESOLVED LEFT DELETE ReferenceChangeSpec{reference=Family.sons, value=Member@4b8ee4de, parentMatch=MatchSpec{left=Family@1e1a0406, right=Family@51e69659, origin=<null>, #differences=1, #submatches=5}, match of value=MatchSpec{left=<null>, right=Member@4b8ee4de, origin=<null>, #differences=0, #submatches=0}}
This is the code I'm using right now:
URI uri1 = URI.createFileURI("models/families1.xmi");
URI uri2 = URI.createFileURI("models/families2.xmi");
Resource.Factory.Registry.INSTANCE.getExtensionToFactoryMap().put("*", new XMIResourceFactoryImpl());
ResourceSet resourceSet = new ResourceSetImpl();
ResourceSet resourceSet1 = new ResourceSetImpl();
ResourceSet resourceSet2 = new ResourceSetImpl();
//load and register the Packages of the metamodel
Resource ecoreResource = resourceSet.getResource(URI.createURI("models/Families.ecore"), true);
EList<EObject> packages = ecoreResource.getContents();
for (EObject packageObject : packages) {
EPackage ePackage = (EPackage) packageObject;
String nsURI = ePackage.getNsURI();
EPackage.Registry.INSTANCE.put(nsURI,ePackage);
}
resourceSet1.getResource(uri1, true);
resourceSet2.getResource(uri2, true);
// Configure EMF Compare
IEObjectMatcher matcher = DefaultMatchEngine.createDefaultEObjectMatcher(UseIdentifiers.NEVER);
IComparisonFactory comparisonFactory = new DefaultComparisonFactory(new DefaultEqualityHelperFactory());
IMatchEngine.Factory matchEngineFactory = new MatchEngineFactoryImpl(matcher, comparisonFactory);
matchEngineFactory.setRanking(20);
IMatchEngine.Factory.Registry matchEngineRegistry = new MatchEngineFactoryRegistryImpl();
matchEngineRegistry.add(matchEngineFactory);
EMFCompare comparator = EMFCompare.builder().setMatchEngineFactoryRegistry(matchEngineRegistry).build();
// Compare the two models
IComparisonScope scope = new DefaultComparisonScope(resourceSet1, resourceSet2, null);
Comparison comparison = comparator.compare(scope);
EList<Diff> differences = comparison.getDifferences();
int differenceCount = differences.size();
The two (exact same) models I'm using are attached as well as the metamodel. Can anyone please tell me what I'm doing wrong? I expected that there would be no differences.
Hope someone can help me,
Nicolas
|
|
|
Re: Determine if two Ecore xmi models are equal [message #1748605 is a reply to message #1748514] |
Fri, 25 November 2016 08:35 |
|
Hi Nicolas,
the two differences you get mean that (1) a Member instance has been added to containment reference Family.sons and (2) a Member instance has been deleted from containment reference Family.sons.
This addition/deletion is detected because the Member instance (I guess either Brandon, David, or Dylan) could not be matched with its corresponding Member instance on the opposite side. Since it couldn't be matched, EMF Compare considers them as a addition and deletion. I'd have to step through the code to find out why exactly the two Member instances couldn't be matched. If you set UseIdentifiers.NEVER, you'll eventually use the ProximityEObjectMatcher for determining whether two EObjects are considered to be matching. I don't have a lot of experience with the ProximityEObjectMatcher, as we usually use the IdentifierEObjectMatcher and have some sort of ID function. So, I'd step through the code of the ProximityEObjectMatcher to find out why the two Member instances won't be matched and see what you could do about it. I guess, content-based matching (as done by the ProximityEObjectMatcher), will always be a fuzzy thing as it uses heuristics, etc. Thus, you'd have to see if it'll work well for your use case or customize the matching to your needs.
I hope this helps!
Best wishes,
Philip
--
Philip Langer
Get professional Eclipse developer support:
http://eclipsesource.com/en/services/developer-support/
--
Philip Langer
Get professional Eclipse developer support:
http://eclipsesource.com/en/services/developer-support/
|
|
| |
Re: Determine if two Ecore xmi models are equal [message #1748741 is a reply to message #1748612] |
Mon, 28 November 2016 08:24 |
|
Hi Nicolas,
the idea of the IdentifierEObjectMatcher is to apply a function to an EObject, which returns some sort of identity that is then used to determine whether two objects match; that is, whether their identity is equal. Typically that is either the XMI:ID, the value of a specific attribute, etc. I'm not sure if it makes sense to use the IdentifierEObjectMatcher, if you want to consider _all_ properties of the object. It would not be able to match as soon as a single property is different. Given that you could have references to other objects, it would also require the referenced object to be equal and so on, eventually leading to getting a match only if the entire model is exactly the same.
What exactly are your requirements? For the family model, it looks like it would make sense to use the IdentifierEObjectMatcher and take the firstName as identity.
To get good results in heuristic content-based matching, it usually requires some customization of model matching. So, I'd rather recommend to step through the ProximityEObjectMatcher and find out why the persons are not matched in order to check whether it could be easily customized, or write a custom matcher altogether.
Hope this helps,
Philip
--
Philip Langer
Get professional Eclipse developer support:
http://eclipsesource.com/en/services/developer-support/
--
Philip Langer
Get professional Eclipse developer support:
http://eclipsesource.com/en/services/developer-support/
|
|
| |
Re: Determine if two Ecore xmi models are equal [message #1749132 is a reply to message #1748948] |
Fri, 02 December 2016 08:39 |
|
Hi Nicolas,
hm, for your requirement I would suggest to use the IdentifierEObjectMatcher and set the firstName attribute to isId=true in the Ecore metamodel (or customize the identity function to use the firstName attribute).
This way, the IdentifierEObjectMatcher would use it as the only identifier for matching the model elements. When the values of the IdentifierEObjectMatcher are correct and all other values of each model element are equal, you'll get zero differences. If a value on a feature <> firstName are not equal, you'll get the correct difference for each of them. If a value on the feature firstName is not equal, you'll get an addition and a deletion of a person.
I guess with this approach, you have not a lot of customization effort (if at all) and will get good results for your use case (I assume and hope ).
Best wishes,
Philip
--
Philip Langer
Get professional Eclipse developer support:
http://eclipsesource.com/en/services/developer-support/
--
Philip Langer
Get professional Eclipse developer support:
http://eclipsesource.com/en/services/developer-support/
|
|
|
Goto Forum:
Current Time: Thu Mar 28 08:29:03 GMT 2024
Powered by FUDForum. Page generated in 0.03377 seconds
|