Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » EMF "Technology" (Ecore Tools, EMFatic, etc)  » [EMF Compare] Compare n models and display results in one DiffGroup
[EMF Compare] Compare n models and display results in one DiffGroup [message #658495] Tue, 08 March 2011 18:02 Go to next message
leonard.krpan is currently offline leonard.krpanFriend
Messages: 20
Registered: March 2011
Junior Member
Hi,

this is going to be a lengthy post so here's some background:

I am working with (meta)models that are evolutionary versions of each other. They are identical for the most part, but a new version might feature some extra classes, attributes that were renamed from the previous version and stuff, classes moved to a different package etc.

We would like to compare n models pairwise (1 and 2, 2 and 3 ...) and display the results in one model. The results are displayed
in DiffMapGroups, which are an extension of DiffGroup with some extra information specific to our project. A DiffMapGroup contains a list of so-called History Elements, which contains information which two versions were compared and if there were changes to the element wrapped in the DiffMapGroup. One DiffMapGroup should contain one HistoryElement per pairwise comparison.

However, when comparing more than 2 models, I don't get the results as one subtree (under the initial DiffGroup element under the DiffModel element), but one subtree per comparison. I am supposed to the results as input for my contribution to the project, but this situation makes it barely usable for me.

There's a custom DiffEngine which is basically the GenericDiffEngine with a couple of adjustments. The calls to findExisitingGroup in addInContainer have not been changed.

It's findExisitingGroup that I located as the source of my issue: after the first comparison, there is already an existing DiffModel with one subtree (containing results from comparing Model 1 with Model 2). When the DiffEngine is run to compare Model 2 and Model 3, the groupParent in findExistingGroup refers to the root package of Model 1. targetParent refers to that same root package but in Model 2. Now this is the use case where there is already an existing group, but the groupParent == targetParent fails because it's referencing elements in two distinct models. getMatchedEObject(groupParent) returns null, because the matchCrossReferencer in this run of the DiffEngine has been initialized with the match model for Model 2 and Model 3, so Model 1 is not even found by the matchCrossReferencer. In the end, a new subtree under the DiffGroup root is created and the rest of the comparsion goes in there.

I tried passing an aggregated match model (adding up matching results to the existing match model after every matching) to the matchCrossReferencer. It gave me the expected results when comparing Model 1 with Model 2 with Model 3, but when I added Model 4, I saw that the temporary diff after differencing the first three models was different than when differencing only the three models. So apparently the extra matching information from matching Models 3 and 4 screws up the differencing of the other models!

I also tried creating a list of matchCrossReferencers with respective match models and then putting the body of getMatchedEObject in a for loop, feeding it one matchCrossReferencer at a time, but this totally wreaks havoc.

Is there any other way I can put everything in the same subtree and get deterministic results too? Smile

[Updated on: Wed, 09 March 2011 09:12]

Report message to a moderator

Re: [EMF Compare] Compare n models and display results in one DiffGroup [message #658711 is a reply to message #658495] Wed, 09 March 2011 15:14 Go to previous message
leonard.krpan is currently offline leonard.krpanFriend
Messages: 20
Registered: March 2011
Junior Member
Turns out I had the right idea but it was just too late in the day to implement it correctly and at the right location.

Here's what I did to make it work:

1. Created a getMatchedEObject method that can be passed a CrossReferencer as an argument:

protected final EObject getMatchedEObject(EcoreUtil.CrossReferencer matchCrossReferencer, EObject from) {
		EObject matchedEObject = null;

		final Collection<EStructuralFeature.Setting> settings = matchCrossReferencer.get(from);
...


2. Created crossFindExisitingGroup method: it utilizes a list of matchCrossReferencers, where each matchCrossReferencer has been initialized with the appropriate match model. With this and the new getMatchedEObject, I am able to create a chain of comparisons and so establish a link between the original model element that created the group initially and the element of a model that wasn't directly compared with the initial model:

private DiffGroup crossFindExistingGroup(DiffGroup root, EObject targetParent) {
		final TreeIterator<EObject> it = root.eAllContents();
		while (it.hasNext()) {
			final EObject obj = it.next();
			if (obj instanceof DiffGroup) {
				
				EObject groupParent = ((DiffGroup)obj).getRightParent();				
				EObject crossGroupParent = groupParent;
				EObject crossGroupParentMatchedObject = null;
				
				/*
				 *  Each matchCrossReferencer is initialized with a match model
				 *  of two model versions in ascending order (i.e. 1 and 2, 2 and 3, 3 and 4...)
				 */
				for( EcoreUtil.CrossReferencer matchCrossReferencer : matchCrossReferencers ) {
					
					// look for a match element in the match model contained in this matchCrossReferencer
					crossGroupParentMatchedObject = getMatchedEObject(matchCrossReferencer, crossGroupParent);
					
					if (crossGroupParentMatchedObject != null) {
						
						// groupParent is always from the origin model	
						if (groupParent == targetParent || crossGroupParentMatchedObject == targetParent) {
							
							return (DiffGroup)obj;
							
						} else {
							/*
							 * If the references don't match, use the matched object as the origin object
							 * for cross-referencing in the next iteration.
							 * (this creates a chain of references between all compared models)
							 */
							crossGroupParent = crossGroupParentMatchedObject;
						}
					}
				} 
			}
		} 
		return null;
	}


3. I'm using the crossFindExistingGroup in addInContainerPackage here:

...
DiffGroup targetGroup = crossFindExistingGroup(root, targetParent);

		if (targetGroup == null) {
			// Searches for a DiffGroup with the matched parent
			
			// use crossFindExisitingGroup instead of findExisitingGroup
			targetGroup = crossFindExistingGroup(root, getMatchedEObject(targetParent));
			if (targetGroup == null) {
				// we have to create the group
				targetGroup = buildHierarchyGroup(targetParent, root, noChanges);
...


buildHierarchyGroup is still using the regular findExisitingGroup for it's actions.
Previous Topic:[Henshin] Release 0.7
Next Topic:Remove Title from generated EMF editor
Goto Forum:
  


Current Time: Wed Oct 21 02:00:26 GMT 2020

Powered by FUDForum. Page generated in 0.01415 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software

Back to the top