| UnmatchElement List vs total [message #1058054] |
Fri, 10 May 2013 12:22  |
Andrew Whelan Messages: 62 Registered: October 2012 Location: Syracuse NY |
Member |
|
|
When I do the following using EMFCompare
MatchModel match = MatchService.doMatch(eObject1,
eObject2, Collections.<String, Object> emptyMap());
The MatchModel returned has a method that will show me all of the elements of eObject2 that don't exist in eObject1 and elements of eObject1 that don't exist in eObject2. In this scenario eObject1 and eObject2 are of the same class or model.
EList<UnmatchElement> uList = match.getUnmachedElements();
Each UnmatchElement of uList has, among its contents, the EObject for the subelement of eObject1 or eObject2 that didn't appear in one. It also has a value Side for LEFT <eObject1> or RIGHT <eObject2>.
I want to get the total number of matchable elements from eObject1 so that I can calculate (total UnmatchElement from eObject2)/(total matchable elements of eObject1, which is the total number of subelements in eObject1). This way I could claim eObject2 has a certain percentage of matching elements from eObject1.
Can anyone tell me how to get the total number of matchable elements from eObject1 using the EMFCompare APIs so that I can make the above computation? (or if there is a way to get this outside of the EMFCompare APIs, I am interested in that too).
Thanks
-Andrew
|
|
|
| Re: UnmatchElement List vs total [message #1058283 is a reply to message #1058054] |
Mon, 13 May 2013 09:04   |
Laurent Goubet Messages: 1548 Registered: July 2009 |
Senior Member |
|
|
Andrew,
This value would not be interesting with EMF Compare 1.*, which you are using, let's see "how to do it" first, I'll expand the "why won't it work" later.
"match.getUnmatchedElement()" will return all elements that we could not match, as you found out. In your case, you would use "eObject1.eAllContents().size()" to get the total number of elements that could have been matched (i.e. all elements that are contained by "eObject1". So a naive approach would be to say that "unmatchedElements / eAllContent().size()" is some kind of similarity percentage, However...
EMF Compare 1 did not look "under" unmatched elements to check for other matches (elements that have been moved from one container to the other for example). That is to say that with such models:
Model
|-Package1
|-Class1
|-Class2
and
Model
|-Package1
| |-Class1
|-Package2
|-Class2
(For a textual description : we created a new package, "package2" and moved the class "Class2" to that new container.)
You will have a MatchModel that contains two unmatched elements : "Package2" in right, and "Class2" in left. Whereas "Class2" really is not "unmatched", it has just moved "into" an unmatched element.
You would not have such a limitation with EMF Compare 2 : there is exactly one "Match" element for all elements of the input models, unmatched ones being represented by a "Match" which has only one of its sides filled in. If that is more clear, your Comparison model would look like so :
Comparison
|-Match "Package1 <-> Package1"
| |-Match "Class1 <-> Class1"
| |-Match "Class2 <-> Class2"
|-Match " <-> Package2"
Notice how there is only one match with only one side : "package2" really is the only unmatched element here. The match for "Class2" is located under the Match for Package1, but that hierarchy is only there to help visualize the comparison model in the UI, the "Class2" EObject it references for the "right" side really is the one that's located under Package2.
I'd advise using EMF Compare 2 instead of EMF Compare 1, this problem was the main limitation we created a second version in the first place .
Laurent Goubet
Obeo
|
|
|
|
|
| Re: UnmatchElement List vs total [message #1059688 is a reply to message #1059609] |
Tue, 21 May 2013 04:40  |
Laurent Goubet Messages: 1548 Registered: July 2009 |
Senior Member |
|
|
Andrew,
You probably tried to clone at a moment git.eclipse.org was down... but I do not recall any down time for this server lately. Are you still seeing these issues now? Are you behind a proxy that would prevent you from accessing the server (you can try with the web UI at http://git.eclipse.org/c/emfcompare/org.eclipse.emf.compare.git/ )?
We use this repository daily, and I just cloned it with the exact same URL you did, successfuly :
$ git clone git://git.eclipse.org/gitroot/emfcompare/org.eclipse.emf.compare.git test.compare.clone
Cloning into test.compare.clone...
remote: Counting objects: 64600, done.
remote: Compressing objects: 100% (11172/11172), done.
remote: Total 64600 (delta 37662), reused 63388 (delta 36494)
Receiving objects: 100% (64600/64600), 14.42 MiB | 704 KiB/s, done.
Resolving deltas: 100% (37662/37662), done.
The documentation of EMF Compare 2 may still be incomplete, but the developer guide already describes some of the core concepts.
The "UnmatchElement" concept has disappeared from the metamodel since one of our goals was to simplify it and make for a more robust merge. An "unmatch" is an element for which only one side (or two, in the case of three-way comparisons) has been filled. There isn't an easy way to retrieve all unmatched elements... since this value evolves with the merge operations that are taken.
In the example above, I gave an example with one unmatched element :
Comparison
|-Match "Package1 <-> Package1"
| |-Match "Class1 <-> Class1"
| |-Match "Class2 <-> Class2"
|-Match " <-> Package2"
"Package2" is unmatched. If a user merges this change, the Comparison model evolves to look like this :
Comparison
|-Match "Package1 <-> Package1"
| |-Match "Class1 <-> Class1"
| |-Match "Class2 <-> Class2"
|-Match "Package2 <-> Package2"
i.e. there is no more "unmatched" elements here, and subsequent merge operations (moving "Class2" into "Package2") can use this information to move the element in the proper container.
You could emulate the behavior of EMF Compare 1 to get a "snapshot" of all unmatched elements at a given moment though something like this :
public List<Match> getUnmatched(Comparison comparison) {
final List<Match> unmatched = new ArrayList<Match>();
for (Match root : comparison.getMatches()) {
if (isUnmatched(root)) {
unmatched.add(root);
}
unmatched.addAll(getUnmatched(root));
}
return unmatched;
}
private List<Match> getUnmatched(Match match) {
final List<Match> unmatched = new ArrayList<Match>();
for (Match subMatch : match.getSubmatches()) {
if (isUnmatched(subMatch)) {
unmatched.add(subMatch);
}
unmatched.addAll(getUnmatched(subMatch));
}
return unmatched;
}
private boolean isUnmatched(Match match) {
if (match.getLeft() == null || match.getRight() == null) {
return true;
}
return match.getComparison().isThreeWay() && match.getOrigin() == null;
}
As you can see for yourself, this is kind of a "brute force" lookup : we never need this information, be it for the UI or for the merge, so it remains buried in the model. Do note that this is only the state at a given moment : merging any difference can make that information evolve. Once you have a "Match" corresponding to an unmatched element, finding out which side contains it is a matter of looking at the side which is not "null". (You might have more luck looking at the "Diff" elements themselves...)
Laurent Goubet
Obeo
|
|
|
Powered by
FUDForum. Page generated in 0.05735 seconds