Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » EMF "Technology" (Ecore Tools, EMFatic, etc)  » EMF Compare
EMF Compare [message #531797] Thu, 06 May 2010 08:52 Go to next message
Hanane is currently offline HananeFriend
Messages: 6
Registered: May 2010
Junior Member
Hi,
I'm new user to EMF Compare and I tried to compare two instance of models (from the same metamodel),and i want display the list of differences in Console,
but problem is that even if i load the two models to compare which with no difference i always get the same message in console:

//////////////////////////////////////////////////////////// /////////////////////////////////////////////////////

*** Loading resources ***

C:\Documents and Settings\yatimih\runtime-New_configuration\MyAlgorithm1\diag ram\old-default.impala_diagram : rootCompositeBox1

C:\Documents and Settings\yatimih\runtime-New_configuration\MyAlgorithm2\diag ram\old-default.impala_diagram : rootCompositeBox2

*** Matching and Differencing models ***

1
24
1
org.eclipse.emf.compare.diff.metamodel.impl.DiffGroupImpl@1ae93c5 (conflicting: false, kind: Addition)
org.eclipse.emf.compare.diff.metamodel.impl.DiffGroupImpl@1ae93c5 (conflicting: false, kind: Addition)
Change:2
3 change(s) in RootCompositeBox MyAlgorithm1

2
57 change(s) in Diagram default.impala_diagram

2
//////////////////////////////////////////////////////////// //////////////////////////////////////////////////

i need some examples and tutorials about this subject,

can anyone help me,

Thanks in advance
Re: EMF Compare [message #532790 is a reply to message #531797] Tue, 11 May 2010 09:03 Go to previous messageGo to next message
Laurent Goubet is currently offline Laurent GoubetFriend
Messages: 1902
Registered: July 2009
Senior Member
This is a multi-part message in MIME format.
--------------010506020303050700070907
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 7bit

Hi,

I guess you're using the "standalone example" as a base for launching
your comparison. You told you were loading the two models yourself, so I
guess you took care of registering all needed packages and resource
factories (such as what is given as example for UML on
http://wiki.eclipse.org/MDT/UML2/FAQ#What.27s_required_to_lo ad_a_UML_.28.uml.29_resource_from_a_standalone_application.3 F
).

I don't know what all the "integer" messages printed in the console are,
But the rest seems to tell EMF Compare indeed detected a number of
differences in your models ; you can iterate on the diff model's
eAllContent to check what all the differences are.

Seeing as what you're comparing are diagrams, I'd say you have IDs in
these models (xmi ids or functional ids). If the two diagrams have been
created in a graphical modeler at a distinct time (i.e they are not
"copy paste" of one another), then chances are the IDs of your elements
are different even if the elements themselves are identical. You'll have
to set the option MatchOptions.IGNORE_XMI_ID (or
MatchOptions.IGNORE_FUNCTIONAL_ID if yours are functional IDs) to true
for your comparison in order to avoid having EMF Compare detect
differences based on IDs alone. (This is done via the Map MatchService
takes as a parameter of all "doXxxMatch" operations.)

If this is not your issue, you can try comparing your models from the
Eclipse UI to see if EMF Compare behaves as expected when called from
the "standard" code. You only need to select your two impala_diagram
files in the workspace, right-click them and select "compare with =>
each other" to try this.

If none of this helps, I'll need more info as to what you get as
differences in order to try and understand what EMF Compare falsely
detect as different.

Laurent Goubet
Obeo

Hanane wrote:
> Hi,
> I'm new user to EMF Compare and I tried to compare two instance of
> models (from the same metamodel),and i want display the list of
> differences in Console,
> but problem is that even if i load the two models to compare which with
> no difference i always get the same message in console:
>
> ////////////////////////////////////////////////////////////
> /////////////////////////////////////////////////////
>
> *** Loading resources ***
> C:\Documents and
> Settings\yatimih\runtime-New_configuration\MyAlgorithm1\diag
> ram\old-default.impala_diagram : rootCompositeBox1
> C:\Documents and
> Settings\yatimih\runtime-New_configuration\MyAlgorithm2\diag
> ram\old-default.impala_diagram : rootCompositeBox2
> *** Matching and Differencing models ***
> 1
> 24
> 1
> mailto:org.eclipse.emf.compare.diff.metamodel.impl.DiffGroupImpl@1ae93c5
> (conflicting: false, kind: Addition)
> mailto:org.eclipse.emf.compare.diff.metamodel.impl.DiffGroupImpl@1ae93c5
> (conflicting: false, kind: Addition)
> Change:2
> 3 change(s) in RootCompositeBox MyAlgorithm1
>
> 2
> 57 change(s) in Diagram default.impala_diagram
>
> 2
> ////////////////////////////////////////////////////////////
> //////////////////////////////////////////////////
>
> i need some examples and tutorials about this subject,
>
> can anyone help me,
>
> Thanks in advance


--------------010506020303050700070907
Content-Type: text/x-vcard; charset=utf-8;
name="laurent_goubet.vcf"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
filename="laurent_goubet.vcf"

YmVnaW46dmNhcmQNCmZuOkxhdXJlbnQgR291YmV0DQpuOkdvdWJldDtMYXVy ZW50DQpvcmc6
PGEgaHJlZj0iaHR0cDovL3d3dy5vYmVvLmZyIj5PYmVvPC9hPg0KZW1haWw7 aW50ZXJuZXQ6
bGF1cmVudC5nb3ViZXRAb2Jlby5mcg0KdXJsOmh0dHA6Ly93d3cub2Jlby5m cg0KdmVyc2lv
bjoyLjENCmVuZDp2Y2FyZA0KDQo=
--------------010506020303050700070907--
Re: EMF Compare __urgent [message #534766 is a reply to message #532790] Thu, 20 May 2010 09:41 Go to previous messageGo to next message
Hanane is currently offline HananeFriend
Messages: 6
Registered: May 2010
Junior Member
Hi Laurent,
Thank you for your reply.
I already add : MatchOptions.IGNORE_XMI_ID and
MatchOptions.IGNORE_FUNCTIONAL_ID to my code;

In fact,until now i can see the differences (of type DiffElement , DiffGroup) in console,But i still have a problem to see a MatchElement and UnMatchElement

i started by create a Button in menubar 1 (CompareAction.java)
and the principale code 2 (compareDiagram.java)

the code is:
code1 :
package com.st.hed.iqi.impala.emfcompareimpala;

import java.io.IOException;

import org.eclipse.core.resources.IFile;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;

import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.IWorkbenchWindowActionDelegate;

public class CompareAction implements IWorkbenchWindowActionDelegate {

Object firstElement = null;
Object secondElement = null;
/**
* The constructor.
*/
public CompareAction() {
super();
}
public void selectionChanged(IAction action, ISelection selection) {
String fileExtension = "impala_diagram";

action.setEnabled(false);

if (selection instanceof IStructuredSelection) {

IStructuredSelection structuredSelection = (IStructuredSelection) selection;
firstElement = structuredSelection.getFirstElement();

if (structuredSelection.size() == 2){
secondElement = structuredSelection.toArray()[1];

action.setEnabled((structuredSelection.size() == 2)
&& (firstElement.toString().endsWith(fileExtension))
&& (secondElement.toString().endsWith(fileExtension))
);
}

}
}

public void run(IAction action) {

IFile file1 = null;
IFile file2 = null;

if (firstElement instanceof IFile){
file1 = (IFile) firstElement;
file2 = (IFile) secondElement;
}
CompareDiagram compareDiagram = new CompareDiagram();
try {
compareDiagram.getDiff(file1, file2);
} catch (Exception e){
e.printStackTrace();
}

}
public void dispose() {
}
public void init(IWorkbenchWindow window) {
}
}
code2 :
package com.st.hed.iqi.impala.emfcompareimpala;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import org.eclipse.emf.common.util.EList;

import org.eclipse.emf.compare.diff.metamodel.DiffElement;
import org.eclipse.emf.compare.diff.metamodel.DiffGroup;
import org.eclipse.emf.compare.diff.metamodel.DiffModel;
import org.eclipse.emf.compare.diff.metamodel.DiffPackage;
import org.eclipse.emf.compare.diff.service.DiffService;

import org.eclipse.emf.compare.match.api.MatchOptions;
import org.eclipse.emf.compare.match.metamodel.Match2Elements;
import org.eclipse.emf.compare.match.metamodel.MatchElement;
import org.eclipse.emf.compare.match.metamodel.MatchModel;
import org.eclipse.emf.compare.match.metamodel.MatchPackage;
import org.eclipse.emf.compare.match.metamodel.UnMatchElement;
import org.eclipse.emf.compare.match.service.MatchService;
import org.eclipse.emf.compare.match.*;

import org.eclipse.emf.compare.util.ModelUtils;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.IPath;

import com.st.hed.iqi.impala.srcgen.model.RootCompositeBox;

public class CompareDiagram {
private static final double SIMILARITY = 1.0;
CompareDiagram() {
// prevents instantiation
}

public void getDiff(IFile iFile1, IFile iFile2) throws Exception {
IPath location1 = iFile1.getLocation();
IPath location2 = iFile2.getLocation();

File file1 = location1.toFile();
File file2 = location2.toFile();

if (file1.canRead() && file2.canRead()) {

EPackage.Registry.INSTANCE.put(DiffPackage.eNS_URI, DiffPackage.eINSTANCE);
EPackage.Registry.INSTANCE.put(MatchPackage.eNS_URI, MatchPackage.eINSTANCE);

// Creates the resourceSet where we'll load the models
final ResourceSet resourceSet = new ResourceSetImpl();

try {
System.out.println(" *** Loading resources *** \n");

// Loads the two models from the tabModel
final EObject model1 = ModelUtils.load(file1, resourceSet);
final EObject model2 = ModelUtils.load(file2, resourceSet);

RootCompositeBox rootCompositeBox1 = (RootCompositeBox) model1;
RootCompositeBox rootCompositeBox2 = (RootCompositeBox) model2;

System.out.println(file1 + " : rootCompositeBox1 \n");
System.out.println(file2 + " : rootCompositeBox2 \n");

// get the Match model which we can browse like any other EMF

Map<String, Object> options = new HashMap<String, Object>();

options.put(MatchOptions.OPTION_IGNORE_XMI_ID, true);
options.put(MatchOptions.OPTION_IGNORE_ID, true);

// Select the differences to ignore
final Set<EObject> diffToIgnore = new HashSet<EObject>();

// build the list of differences to look
final Set<EObject> diffLookup = new HashSet<EObject>();

// Select the matched Element to ignore
final Set<EObject> matchedElemToIgnore = new HashSet<EObject>();

// build the list of matched Element to look
final Set<EObject> matchedElemLookup = new HashSet<EObject>();

// Select the unmatched Element to ignore
final Set<EObject> unmatchedElemToIgnore = new HashSet<EObject>();

// build the list of unmatched Element to look
final Set<EObject> unmatchedElemLookup = new HashSet<EObject>();


final MatchModel matchModel = MatchService.doMatch(rootCompositeBox1, rootCompositeBox2, options);

System.out.println(" *** matched Elements *** \n");
EList<MatchElement> matchedElements = matchModel.getMatchedElements();
System.out.println("Matched Elements(size) = " + matchedElements.size() + "\n");
for (int iMatch = 0; iMatch < matchedElements.size(); iMatch++) {
MatchElement matchElement = matchedElements.get(iMatch);
System.out.println("MatchElem[" + iMatch + "] : " + matchElement.toString() + " has similarity : " + matchElement.getSimilarity() + "\n");
//final List<EObject> list = matchElement.eContents();
//final EObject eObject = list.get(0);
//Iteratot<EObject> iterator = ;

if (matchElement.getSimilarity() != SIMILARITY) {
final Match2Elements elements = (Match2Elements) matchElement;
getMatchedElement(elements, matchedElemLookup);
}
/**
EList<MatchElement> subMatchedElements = matchElement.getSubMatchElements();
System.out.println("Sub-Matched Elements(size) = " + subMatchedElements.size() + "\n");
for (int isubMatch = 0; isubMatch < subMatchedElements.size(); isubMatch++){
MatchElement submatchElem = subMatchedElements.get(isubMatch);
System.out.println("SubmatchElem[" + isubMatch + "] : " + submatchElem.toString() + " has similarity : " + submatchElem.getSimilarity() + "\n");

if (submatchElem.getSimilarity() != SIMILARITY) {
final Match2Elements subElements = (Match2Elements) submatchElem;
getMatchedElement(subElements, matchedElemLookup);
}
}
*/
}

System.out.println(" *** unmatched Elements *** \n");
EList<UnMatchElement> unmatchElements = matchModel.getUnMatchedElements();
System.out.println("Unmatched Elements(size)= " + unmatchElements.size() + "\n");
for (int iUnMatch = 0; iUnMatch < unmatchElements.size(); iUnMatch++) {
UnMatchElement unMatchElement = unmatchElements.get(iUnMatch);
EObject eObject = unMatchElement.getElement();
System.out.println(" UnMatchElem[" + iUnMatch + "] is : " + eObject);
if (eObject != null){
getUnMatchedElement(eObject, unmatchedElemLookup);

}
}


System.out.println(" *** Differencing models *** \n");
DiffModel myDiff = DiffService.doDiff(matchModel, false);

EList<DiffElement> diffElements = myDiff.getOwnedElements();

if (diffElements.size() == 0) {
System.out.println("There is no difference between the two RootCompositeBox \n");
} else {
System.out.println("Diff Elements(size) = " + diffElements.size() + " \n ");

for (int iDiff = 0; iDiff < diffElements.size(); iDiff++) {
final DiffElement diffElem = diffElements.get(iDiff);
System.out.println("DiffElement[" + iDiff + "] is : " + diffElem.toString() + " \n ");
String kind = diffElem.getKind().getName();
System.out.println("KIND = " + kind + "\n");

if (diffElem instanceof DiffGroup){
final DiffGroup group = (DiffGroup) diffElem;
System.out.println(group + " \n ") ;
addDiffFromGroup(group, diffLookup);
}else {
diffLookup.add(diffElem);
System.out.println(diffLookup.add(diffElem) + " \n ");
}
}
}
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
private void getMatchedElement(Match2Elements elements, Set<EObject> matchedElemLookup){
EObject left = elements.getLeftElement();
EObject right = elements.getRightElement();

if (left instanceof MatchElement){
final MatchElement leftMatchElement = (MatchElement) left;
for (MatchElement subLeftMatchElement : leftMatchElement.getSubMatchElements()){

if (subLeftMatchElement.getSimilarity() != SIMILARITY){
final Match2Elements subLeftMatch2Element = (Match2Elements) subLeftMatchElement;
System.out.println(subLeftMatch2Element + " \n ");
getMatchedElement( subLeftMatch2Element, matchedElemLookup);
}
}
}else {
matchedElemLookup.add(left);
System.out.println(matchedElemLookup.add(left) + " \n ");
}

if (right instanceof MatchElement){
final MatchElement rightMatchElement = (MatchElement) right;
if (rightMatchElement.getSimilarity() != SIMILARITY){
final Match2Elements rightMatch2Element = (Match2Elements) rightMatchElement;
System.out.println(rightMatch2Element + " \n ");
getMatchedElement( rightMatch2Element, matchedElemLookup);

}
} else {
matchedElemLookup.add(right);
System.out.println(matchedElemLookup.add(right) + " \n ");
}
}

private void getUnMatchedElement(EObject eObject, Set<EObject> unmatchedElemLookup){

}

private void addDiffFromGroup(DiffGroup group, Set<EObject> diffLookup) {
EList<DiffElement> diffGroups = group.getSubDiffElements();
System.out.println(diffGroups + " \n ");
for (final DiffElement diffElem : diffGroups) {
if (diffElem instanceof DiffGroup) {
final DiffGroup subGroup = (DiffGroup) diffElem;
System.out.println(" * " + subGroup + " \n ");
addDiffFromGroup(subGroup, diffLookup);
} else {
diffLookup.add(diffElem);
System.out.println(diffLookup.add(diffElem) + " \n ");
}
}
}
}

Regards,
Hanane YATIMI

[Updated on: Thu, 20 May 2010 09:42]

Report message to a moderator

Re: EMF Compare __urgent [message #535070 is a reply to message #534766] Fri, 21 May 2010 08:26 Go to previous messageGo to next message
Laurent Goubet is currently offline Laurent GoubetFriend
Messages: 1902
Registered: July 2009
Senior Member
This is a multi-part message in MIME format.
--------------070802000706050605010802
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 7bit

Hanane,

First of all, please refrain from using "urgent" in your post subjects,
this will not get the post read faster, and it might in fact have the
opposite effect. We read the newsgroup questions when we can, and answer
at the same rate.

Other than that, if you don't explain your issue, we can in now way help
you : I can't create an Eclipse workspace, take you three classes, put
them into a project, build ecore/uml/... models to compare them through
this code, launch and try to understand what's failing and what's
accurate, then try and see if the code is erroneous or if it is my
models that don't correspond to yours ...

If there is something that doesn't work with your code, you might be
interested in searching for "floating point operation" in google ; for
example, "0.3 == 0.1 + 0.1 + 0.1" returns false. Your "getSimilarity()
== SIMILARITY" scare me as equality testing on doubles through == is
risky at best. If it the problem isn't that, then please explain what
you're trying to do, and how EMF Compare doesn't help or fails.

Laurent Goubet
Obeo

Hanane wrote:
> Hi Laurent,
> Thank you for your reply.
> I already add : MatchOptions.IGNORE_XMI_ID and
> MatchOptions.IGNORE_FUNCTIONAL_ID to my code;
>
> In fact,until now i can see the differences (of type DiffElement ,
> DiffGroup) in console,But i still have a problem to see a MatchElement
> and UnMatchElement
> i started by create a Button in menubar 1 (CompareAction.java) and the
> principale code 2 (compareDiagram.java)
>
> the code is:
> code1 :
> package com.st.hed.iqi.impala.emfcompareimpala;
>
> import java.io.IOException;
>
> import org.eclipse.core.resources.IFile;
> import org.eclipse.jface.action.IAction;
> import org.eclipse.jface.viewers.ISelection;
> import org.eclipse.jface.viewers.IStructuredSelection;
>
> import org.eclipse.ui.IWorkbenchWindow;
> import org.eclipse.ui.IWorkbenchWindowActionDelegate;
>
> public class CompareAction implements IWorkbenchWindowActionDelegate {
>
> Object firstElement = null;
> Object secondElement = null;
> /**
> * The constructor.
> */
> public CompareAction() {
> super();
> }
> public void selectionChanged(IAction action, ISelection selection) {
> String fileExtension = "impala_diagram";
>
> action.setEnabled(false);
> if (selection instanceof IStructuredSelection) {
>
> IStructuredSelection structuredSelection =
> (IStructuredSelection) selection;
> firstElement =
> structuredSelection.getFirstElement();
>
> if (structuredSelection.size() == 2){
> secondElement = structuredSelection.toArray()[1];
>
> action.setEnabled((structuredSelection.size() == 2)
> &&
> (firstElement.toString().endsWith(fileExtension))
> &&
> (secondElement.toString().endsWith(fileExtension))
> );
> }
>
> }
> }
>
> public void run(IAction action) {
>
> IFile file1 = null;
> IFile file2 = null;
> if (firstElement instanceof IFile){
> file1 = (IFile) firstElement;
> file2 = (IFile) secondElement;
> }
> CompareDiagram compareDiagram = new CompareDiagram();
> try {
> compareDiagram.getDiff(file1, file2);
> } catch (Exception e){
> e.printStackTrace();
> }
>
> }
> public void dispose() {
> }
> public void init(IWorkbenchWindow window) {
> }
> }
> code2 :
> package com.st.hed.iqi.impala.emfcompareimpala;
>
> import java.io.File;
> import java.io.IOException;
> import java.util.HashMap;
> import java.util.HashSet;
> import java.util.Map;
> import java.util.Set;
>
> import org.eclipse.emf.common.util.EList;
>
> import org.eclipse.emf.compare.diff.metamodel.DiffElement;
> import org.eclipse.emf.compare.diff.metamodel.DiffGroup;
> import org.eclipse.emf.compare.diff.metamodel.DiffModel;
> import org.eclipse.emf.compare.diff.metamodel.DiffPackage;
> import org.eclipse.emf.compare.diff.service.DiffService;
>
> import org.eclipse.emf.compare.match.api.MatchOptions;
> import org.eclipse.emf.compare.match.metamodel.Match2Elements;
> import org.eclipse.emf.compare.match.metamodel.MatchElement;
> import org.eclipse.emf.compare.match.metamodel.MatchModel;
> import org.eclipse.emf.compare.match.metamodel.MatchPackage;
> import org.eclipse.emf.compare.match.metamodel.UnMatchElement;
> import org.eclipse.emf.compare.match.service.MatchService;
> import org.eclipse.emf.compare.match.*;
>
> import org.eclipse.emf.compare.util.ModelUtils;
> import org.eclipse.emf.ecore.EObject;
> import org.eclipse.emf.ecore.EPackage;
> import org.eclipse.emf.ecore.resource.ResourceSet;
> import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
>
> import org.eclipse.core.resources.IFile;
> import org.eclipse.core.runtime.IPath;
>
> import com.st.hed.iqi.impala.srcgen.model.RootCompositeBox;
>
> public class CompareDiagram {
> private static final double SIMILARITY = 1.0;
> CompareDiagram() {
> // prevents instantiation
> }
>
> public void getDiff(IFile iFile1, IFile iFile2) throws Exception {
> IPath location1 = iFile1.getLocation();
> IPath location2 = iFile2.getLocation();
>
> File file1 = location1.toFile();
> File file2 = location2.toFile();
>
> if (file1.canRead() && file2.canRead()) {
>
> EPackage.Registry.INSTANCE.put(DiffPackage.eNS_URI,
> DiffPackage.eINSTANCE);
> EPackage.Registry.INSTANCE.put(MatchPackage.eNS_URI,
> MatchPackage.eINSTANCE);
>
> // Creates the resourceSet where we'll load the models
> final ResourceSet resourceSet = new ResourceSetImpl();
>
> try {
> System.out.println(" *** Loading resources *** \n");
>
> // Loads the two models from the tabModel
> final EObject model1 = ModelUtils.load(file1, resourceSet);
> final EObject model2 = ModelUtils.load(file2, resourceSet);
>
> RootCompositeBox rootCompositeBox1 = (RootCompositeBox)
> model1;
> RootCompositeBox rootCompositeBox2 = (RootCompositeBox)
> model2;
>
> System.out.println(file1 + " : rootCompositeBox1 \n");
> System.out.println(file2 + " : rootCompositeBox2 \n");
>
> // get the Match model which we can browse like any
> other EMF
>
> Map<String, Object> options = new HashMap<String,
> Object>();
>
> options.put(MatchOptions.OPTION_IGNORE_XMI_ID, true);
> options.put(MatchOptions.OPTION_IGNORE_ID, true);
>
> // Select the differences to ignore
> final Set<EObject> diffToIgnore = new HashSet<EObject>();
>
> // build the list of differences to look
> final Set<EObject> diffLookup = new HashSet<EObject>();
>
> // Select the matched Element to ignore
> final Set<EObject> matchedElemToIgnore = new
> HashSet<EObject>();
>
> // build the list of matched Element to look
> final Set<EObject> matchedElemLookup = new
> HashSet<EObject>();
>
> // Select the unmatched Element to ignore
> final Set<EObject> unmatchedElemToIgnore = new
> HashSet<EObject>();
>
> // build the list of unmatched Element to look
> final Set<EObject> unmatchedElemLookup = new
> HashSet<EObject>();
>
>
> final MatchModel matchModel =
> MatchService.doMatch(rootCompositeBox1, rootCompositeBox2, options);
>
> System.out.println(" *** matched Elements *** \n");
> EList<MatchElement> matchedElements =
> matchModel.getMatchedElements();
> System.out.println("Matched Elements(size) = " +
> matchedElements.size() + "\n");
> for (int iMatch = 0; iMatch < matchedElements.size();
> iMatch++) {
> MatchElement matchElement =
> matchedElements.get(iMatch);
> System.out.println("MatchElem[" + iMatch + "] : " +
> matchElement.toString() + " has similarity : " +
> matchElement.getSimilarity() + "\n");
> //final List<EObject> list = matchElement.eContents();
> //final EObject eObject = list.get(0);
> //Iteratot<EObject> iterator = ;
>
> if (matchElement.getSimilarity() != SIMILARITY) {
> final Match2Elements elements = (Match2Elements)
> matchElement;
> getMatchedElement(elements, matchedElemLookup);
> }
> /**
> EList<MatchElement> subMatchedElements =
> matchElement.getSubMatchElements();
> System.out.println("Sub-Matched Elements(size) = " +
> subMatchedElements.size() + "\n");
> for (int isubMatch = 0; isubMatch <
> subMatchedElements.size(); isubMatch++){
> MatchElement submatchElem =
> subMatchedElements.get(isubMatch);
> System.out.println("SubmatchElem[" + isubMatch +
> "] : " + submatchElem.toString() + " has similarity : " +
> submatchElem.getSimilarity() + "\n");
>
> if (submatchElem.getSimilarity() != SIMILARITY) {
> final Match2Elements subElements =
> (Match2Elements) submatchElem;
> getMatchedElement(subElements,
> matchedElemLookup);
> }
> }
> */
> }
>
> System.out.println(" *** unmatched Elements *** \n");
> EList<UnMatchElement> unmatchElements =
> matchModel.getUnMatchedElements();
> System.out.println("Unmatched Elements(size)= " +
> unmatchElements.size() + "\n");
> for (int iUnMatch = 0; iUnMatch <
> unmatchElements.size(); iUnMatch++) {
> UnMatchElement unMatchElement =
> unmatchElements.get(iUnMatch);
> EObject eObject = unMatchElement.getElement();
> System.out.println(" UnMatchElem[" + iUnMatch + "]
> is : " + eObject);
> if (eObject != null){
> getUnMatchedElement(eObject, unmatchedElemLookup);
>
> }
> }
>
>
> System.out.println(" *** Differencing models *** \n");
> DiffModel myDiff = DiffService.doDiff(matchModel, false);
> EList<DiffElement> diffElements =
> myDiff.getOwnedElements();
>
> if (diffElements.size() == 0) {
> System.out.println("There is no difference between
> the two RootCompositeBox \n");
> } else {
> System.out.println("Diff Elements(size) = " +
> diffElements.size() + " \n ");
>
> for (int iDiff = 0; iDiff < diffElements.size();
> iDiff++) {
> final DiffElement diffElem =
> diffElements.get(iDiff);
> System.out.println("DiffElement[" + iDiff + "]
> is : " + diffElem.toString() + " \n ");
> String kind = diffElem.getKind().getName();
> System.out.println("KIND = " + kind + "\n");
>
> if (diffElem instanceof DiffGroup){
> final DiffGroup group = (DiffGroup) diffElem;
> System.out.println(group + " \n ") ;
> addDiffFromGroup(group, diffLookup);
> }else {
> diffLookup.add(diffElem);
> System.out.println(diffLookup.add(diffElem)
> + " \n ");
> }
> }
> }
> } catch (IOException e) {
> e.printStackTrace();
> } catch (InterruptedException e) {
> e.printStackTrace();
> }
> }
> }
> private void getMatchedElement(Match2Elements elements, Set<EObject>
> matchedElemLookup){
> EObject left = elements.getLeftElement();
> EObject right = elements.getRightElement();
>
> if (left instanceof MatchElement){
> final MatchElement leftMatchElement = (MatchElement) left;
> for (MatchElement subLeftMatchElement :
> leftMatchElement.getSubMatchElements()){
>
> if (subLeftMatchElement.getSimilarity() != SIMILARITY){
> final Match2Elements subLeftMatch2Element =
> (Match2Elements) subLeftMatchElement;
> System.out.println(subLeftMatch2Element + " \n ");
> getMatchedElement( subLeftMatch2Element,
> matchedElemLookup);
> }
> }
> }else {
> matchedElemLookup.add(left);
> System.out.println(matchedElemLookup.add(left) + " \n ");
> }
>
> if (right instanceof MatchElement){
> final MatchElement rightMatchElement = (MatchElement) right;
> if (rightMatchElement.getSimilarity() != SIMILARITY){
> final Match2Elements rightMatch2Element =
> (Match2Elements) rightMatchElement;
> System.out.println(rightMatch2Element + " \n ");
> getMatchedElement( rightMatch2Element, matchedElemLookup);
>
> }
> } else {
> matchedElemLookup.add(right);
> System.out.println(matchedElemLookup.add(right) + " \n ");
> }
> }
>
> private void getUnMatchedElement(EObject eObject, Set<EObject>
> unmatchedElemLookup){
> }
>
> private void addDiffFromGroup(DiffGroup group, Set<EObject>
> diffLookup) {
> EList<DiffElement> diffGroups = group.getSubDiffElements();
> System.out.println(diffGroups + " \n ");
> for (final DiffElement diffElem : diffGroups) {
> if (diffElem instanceof DiffGroup) {
> final DiffGroup subGroup = (DiffGroup) diffElem;
> System.out.println(" * " + subGroup + " \n ");
> addDiffFromGroup(subGroup, diffLookup);
> } else {
> diffLookup.add(diffElem);
> System.out.println(diffLookup.add(diffElem) + " \n ");
> }
> }
> }
> }
>
> Regards,
> Hanane YATIMI


--------------070802000706050605010802
Content-Type: text/x-vcard; charset=utf-8;
name="laurent_goubet.vcf"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
filename="laurent_goubet.vcf"

YmVnaW46dmNhcmQNCmZuOkxhdXJlbnQgR291YmV0DQpuOkdvdWJldDtMYXVy ZW50DQpvcmc6
PGEgaHJlZj0iaHR0cDovL3d3dy5vYmVvLmZyIj5PYmVvPC9hPg0KZW1haWw7 aW50ZXJuZXQ6
bGF1cmVudC5nb3ViZXRAb2Jlby5mcg0KdXJsOmh0dHA6Ly93d3cub2Jlby5m cg0KdmVyc2lv
bjoyLjENCmVuZDp2Y2FyZA0KDQo=
--------------070802000706050605010802--
Re: EMF Compare [message #536508 is a reply to message #535070] Fri, 28 May 2010 14:21 Go to previous messageGo to next message
Hanane is currently offline HananeFriend
Messages: 6
Registered: May 2010
Junior Member

Hi Laurent,
Thank you for your reply.

In fact,until now,with EMFCompare i can see matched element ,unmatched element and diff element in my console,
but the problem is that i don't want to see all things concerning the diagram ( means ,position of elements in models like (x, y) gmf,... )but only models (means if the elements of type EObjects exist in models or no,and also if their attribute has changed or no...) ,

For that raison,i create my own (MatchEngine and DiffEngine) ; which extend (GenericMatchEngine and GenericDiffEngine);
and also,i add my" Extension Point " like that :

- fileExtension (impala_diagram )
-engineClass (ImpalaMatchEngine)

and i did the same for DifEngine


And i want know which methods,class...are responsible for the display of the diagram (position of the elements in models ) that i have to override;otherwise , i want to keep in my own MatchEngine only methods which allow me to do the comparison between the two medels concerning existance (so deletion,addition,change) of elements,

this is the code of my own MatchEngine :

//////////////////////////////////////////////////////////// ////////////////////////////////////////////

package com.st.hed.iqi.impala.emfcompareimpala;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.eclipse.emf.common.EMFPlugin;
import org.eclipse.emf.compare.EMFComparePlugin;
import org.eclipse.emf.compare.FactoryException;
import org.eclipse.emf.compare.internal.runtime.CompareProgressMoni tor;
import org.eclipse.emf.compare.match.EMFCompareMatchMessages;
import org.eclipse.emf.compare.match.api.MatchOptions;
import org.eclipse.emf.compare.match.engine.GenericMatchEngine;
import org.eclipse.emf.compare.match.metamodel.Match2Elements;
import org.eclipse.emf.compare.match.metamodel.MatchFactory;
import org.eclipse.emf.compare.match.metamodel.MatchModel;
import org.eclipse.emf.compare.match.metamodel.UnMatchElement;
import org.eclipse.emf.compare.match.statistic.MetamodelFilter;
import org.eclipse.emf.compare.match.statistic.similarity.NameSimil arity;
import org.eclipse.emf.compare.match.statistic.similarity.Structure Similarity;
import org.eclipse.emf.compare.util.EFactory;
import org.eclipse.emf.compare.util.EMFCompareMap;
import org.eclipse.emf.compare.util.EMFComparePreferenceKeys;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.emf.ecore.xmi.XMIResource;

public class ImpalaMatchEngine extends GenericMatchEngine{

/** Containmnent reference for the matched elements root. */
private static final String MATCH_ELEMENT_NAME = "matchedElements"; //$NON-NLS-1$

/**
* Minimal number of attributes an element must have for content comparison.
*/
private static final int MIN_ATTRIBUTES_COUNT = 5;

/** This constant is used as key for the buffering of relations similarity. */
private static final char RELATION_SIMILARITY = 'r';

/** Containmnent reference for {@link MatchElement}s' submatches. */
private static final String SUBMATCH_ELEMENT_NAME = "subMatchElements"; //$NON-NLS-1$

/** Containmnent reference for the {@link MatchModel}'s unmatched elements. */
private static final String UNMATCH_ELEMENT_NAME = "unMatchedElements"; //$NON-NLS-1$

/** This constant is used as key for the buffering of name similarity. */
private static final char NAME_SIMILARITY = 'n';

/** This constant is used as key for the buffering of type similarity. */
private static final char TYPE_SIMILARITY = 't';

/** This constant is used as key for the buffering of value similarity. */
private static final char VALUE_SIMILARITY = 'v';

/**
* {@link MetamodelFilter} used for filtering unused features of the objects we're computing the
* similarity for.
*/
protected final MetamodelFilter filter = new MetamodelFilter();

/** Contains the options given to the match procedure. */
protected final Map<String, Object> options = new EMFCompareMap<String, Object>();

/**
* This map allows us memorize the {@link EObject} we've been able to match thanks to their functional ID.
*/
private final Map<String, EObject> matchedByID = new EMFCompareMap<String, EObject>();

/**
* This map allows us memorize the {@link EObject} we've been able to match thanks to their XMI ID.
*/
private final Map<String, EObject> matchedByXMIID = new EMFCompareMap<String, EObject>();

/**
* This map is used to cache the comparison results Pair(Element1, Element2) => [nameSimilarity,
* valueSimilarity, relationSimilarity, TypeSimilarity].
*/
private final Map<String, Double> metricsCache = new EMFCompareMap<String, Double>();


/**
* This list will be intensively used while matching elements to keep track of the unmatched ones from the
* left model.
*/
private final List<EObject> stillToFindFromModel1 = new ArrayList<EObject>();

/**
* This list will be intensively used while matching elements to keep track of the unmatched ones from the
* right model.
*/
private final List<EObject> stillToFindFromModel2 = new ArrayList<EObject>();

/**
* {@inheritDoc}
*
* @see org.eclipse.emf.compare.match.api.IMatchEngine#modelMatch(or g.eclipse.emf.ecore.EObject,
* org.eclipse.emf.ecore.EObject, java.util.Map)
*/
public MatchModel modelMatch(EObject leftRoot, EObject rightRoot, Map<String, Object> optionMap)
throws InterruptedException {
if (optionMap != null && optionMap.size() > 0)
loadOptionMap(optionMap);

MatchModel result = null;
// Creates and sizes progress monitor
final CompareProgressMonitor monitor = new CompareProgressMonitor(getOption(MatchOptions.OPTION_PROGRES S_MONITOR));
int size = 1;
for (EObject root : leftRoot.eResource().getContents()) {
final Iterator<EObject> rootContent = root.eAllContents();
while (rootContent.hasNext()) {
rootContent.next();
size++;
}
}
startMonitor(monitor, size);

result = doMatch(leftRoot.eResource(), rightRoot.eResource(), monitor);
return result;
}

/**
* This replaces the contents of the defaults options map with the options overridden by the given map.
*
* @param map
* Map containing the option given to the match procedure. cannot be <code>null</code>.
*/
private void loadOptionMap(Map<String, Object> map) {
options.putAll(map);
Integer option = getOption(MatchOptions.OPTION_SEARCH_WINDOW);
if (option< 0)
options.put(MatchOptions.OPTION_SEARCH_WINDOW, getPreferenceSearchWindow());
}
/**
* This will return the value associated to the given key in the options map.
* <p>
* NOTE : Misuses of this method will easily throw {@link ClassCastException}s.
* </p>
*
* @param <T>
* Expected type of the value associated to <code>key</code>.
* @param key
* Key of the value to retrieve.
* @return Value associated to the given key in the options map.
* @throws ClassCastException
* If the value isn't assignment compatible with the expected type.
*/
@SuppressWarnings("unchecked")
protected <T> T getOption(String key) throws ClassCastException {
return (T)options.get(key);
}

/**
* Returns the search window corresponding to the number of siblings to consider while matching. Reducing
* this number (on the preferences page) considerably improve performances while reducing precision.
*
* @return An <code>int</code> representing the number of siblings to consider for matching.
*/
private int getPreferenceSearchWindow() {
int searchWindow = MatchOptions.DEFAULT_SEARCH_WINDOW;
if (EMFPlugin.IS_ECLIPSE_RUNNING
&& EMFComparePlugin.getDefault() != null
&& EMFComparePlugin.getDefault().getInt(
EMFComparePreferenceKeys.PREFERENCES_KEY_SEARCH_WINDOW) > 0)
searchWindow = EMFComparePlugin.getDefault().getInt(
EMFComparePreferenceKeys.PREFERENCES_KEY_SEARCH_WINDOW);
if (searchWindow < 0)
searchWindow = 0;
return searchWindow;
}

/**
* Starts the monitor for comparison progress. Externalized here to avoid multiple usage of the Strings.
*
* @param monitor
* The monitor that need be started
* @param size
* Size of the monitor
*/
private void startMonitor(CompareProgressMonitor monitor, int size) {
monitor.beginTask(EMFCompareMatchMessages.getString("DifferencesServices.monitor.task "), size); //$NON-NLS-1$
monitor.subTask(EMFCompareMatchMessages.getString("DifferencesServices.monitor.browsing ")); //$NON-NLS-1$
}

/**
* This method handles the creation and returning of a two way model match.
*
* @param leftResource
* Left model for the comparison.
* @param rightResource
* Right model for the comparison.
* @param monitor
* Progress monitor to display while the comparison lasts.
* @return The corresponding {@link MatchModel}.
* @throws InterruptedException
* Thrown if the comparison is interrupted somehow.
*/
private MatchModel doMatch(Resource leftResource, Resource rightResource, CompareProgressMonitor monitor)
throws InterruptedException {
final MatchModel root = MatchFactory.eINSTANCE.createMatchModel();
setModelURIs(root, leftResource, rightResource);

// filters unused features
filterUnused(leftResource);
filterUnused(rightResource);

// navigate through both models at the same time and realize mappings..
try {
if (!this.<Boolean> getOption(MatchOptions.OPTION_IGNORE_XMI_ID))
if (leftResource instanceof XMIResource && rightResource instanceof XMIResource)
matchByXMIID((XMIResource)leftResource, (XMIResource)rightResource);
if (!this.<Boolean> getOption(MatchOptions.OPTION_IGNORE_ID))
matchByID(leftResource, rightResource);

monitor.subTask(EMFCompareMatchMessages.getString("DifferencesServices.monitor.roots ")); //$NON-NLS-1$
final List<Match2Elements> matchedRoots = mapLists(leftResource.getContents(), rightResource
.getContents(), this.<Integer> getOption(MatchOptions.OPTION_SEARCH_WINDOW), monitor);
stillToFindFromModel1.clear();
stillToFindFromModel2.clear();
final List<EObject> unMatchedLeftRoots = new ArrayList<EObject>(leftResource.getContents());
final List<EObject> unMatchedRightRoots = new ArrayList<EObject>(rightResource.getContents());
// These sets will help us in keeping track of the yet to be found
// elements
final Set<EObject> still1 = new HashSet<EObject>();
final Set<EObject> still2 = new HashSet<EObject>();

// If one of the resources has no roots, considers it as deleted
if (leftResource.getContents().size() > 0 && rightResource.getContents().size() > 0) {
Match2Elements matchModelRoot = MatchFactory.eINSTANCE.createMatch2Elements();
// We haven't found any similar roots, we then consider the
// firsts to be similar.
if (matchedRoots.size() == 0) {
final Match2Elements rootMapping = MatchFactory.eINSTANCE.createMatch2Elements();
rootMapping.setLeftElement(leftResource.getContents().get(0) );
EObject rightElement = findMostSimilar(leftResource.getContents().get(0),
unMatchedRightRoots);
if (rightElement == null)
rightElement = unMatchedRightRoots.get(0);
rootMapping.setRightElement(rightElement);
matchedRoots.add(rootMapping);
}
monitor.subTask(EMFCompareMatchMessages
.getString("DifferencesServices.monitor.rootsContents")); //$NON-NLS-1$
for (Match2Elements matchedRoot : matchedRoots) {
final Match2Elements rootMapping = recursiveMappings(matchedRoot.getLeftElement(),
matchedRoot.getRightElement(), monitor);
// this is the first passage
if (matchModelRoot.getLeftElement() == null) {
matchModelRoot = rootMapping;
redirectedAdd(root, MATCH_ELEMENT_NAME, matchModelRoot);
} else {
redirectedAdd(matchModelRoot, SUBMATCH_ELEMENT_NAME, rootMapping);
}

// Synchronizes the two lists to avoid multiple elements
still1.removeAll(stillToFindFromModel1);
still2.removeAll(stillToFindFromModel2);
// checks for matches within the yet to found elements lists
createSubMatchElements(rootMapping, new ArrayList<EObject>(stillToFindFromModel1),
new ArrayList<EObject>(stillToFindFromModel2), monitor);
// Adds all unfound elements to the sets
still1.addAll(stillToFindFromModel1);
still2.addAll(stillToFindFromModel2);

unMatchedLeftRoots.remove(matchedRoot.getLeftElement());
unMatchedRightRoots.remove(matchedRoot.getRightElement());
}
// We'll iterate through the unMatchedRoots all contents
monitor.subTask(EMFCompareMatchMessages
.getString("DifferencesServices.monitor.unmatchedRoots")); //$NON-NLS-1$
createSubMatchElements(matchModelRoot, unMatchedLeftRoots, unMatchedRightRoots, monitor);
} else {
// Roots are unmatched, this is either a file addition or
// deletion
still1.addAll(unMatchedLeftRoots);
still2.addAll(unMatchedRightRoots);
}

// Now takes care of remaining unfound elements
still1.addAll(stillToFindFromModel1);
still2.addAll(stillToFindFromModel2);
createUnMatchElements(root, still1);
createUnMatchElements(root, still2);
} catch (FactoryException e) {
EMFComparePlugin.log(e, false);
}
return root;
}

/**
* Sets the values of the {@link MatchModel}'s left and right models.
*
* @param modelRoot
* Root of the {@link MatchModel}.
* @param left
* Element from which to resolve the left model URI.
* @param right
* Element from which to resolve the right model URI.
*/
private void setModelURIs(MatchModel modelRoot, Resource left, Resource right) {
setModelURIs(modelRoot, left, right, null);
}

/**
* Sets the values of the {@link MatchModel}'s left, right and ancestor models.
*
* @param modelRoot
* Root of the {@link MatchModel}.
* @param left
* Element from which to resolve the left model URI.
* @param right
* Element from which to resolve the right model URI.
* @param ancestor
* Element from which to resolve the ancestor model URI. Can be <code>null</code>.
*/
private void setModelURIs(MatchModel modelRoot, Resource left, Resource right, Resource ancestor) {
// Sets values of left, right and ancestor model URIs
if (left != null && left.getURI() != null)
modelRoot.setLeftModel(left.getURI().toString());
if (right != null && right.getURI() != null)
modelRoot.setRightModel(right.getURI().toString());
if (ancestor != null && ancestor.getURI() != null)
modelRoot.setOriginModel(ancestor.getURI().toString());
}

/**
* Filters unused features of the resource.
*
* @param resource
* Resource to be apply filter on.
*/
private void filterUnused(Resource resource) {
for (EObject root : resource.getContents())
filter.analyseModel(root);
}

/**
* Iterates through both of the given {@link XMIResource resources} to find all the elements that can be
* matched by their XMI ID, then populates {@link #matchedByXMIID} with those mappings.
*
* @param left
* First of the two {@link XMIResource resources} to visit.
* @param right
* Second of the {@link XMIResource resources} to visit.
* @throws FactoryException
* Thrown if we couldn't compute a key to store the items in cache.
*/
private void matchByXMIID(XMIResource left, XMIResource right) throws FactoryException {
matchedByXMIID.clear();
final Iterator<EObject> leftIterator = left.getAllContents();

while (leftIterator.hasNext()) {
final EObject item1 = leftIterator.next();
final String item1ID = left.getID(item1);
if (item1ID != null) {
final EObject item2 = right.getEObject(item1ID);
if (item2 != null) {
final StringBuilder item1Key = new StringBuilder();
item1Key.append(NameSimilarity.findName(item1));
item1Key.append(item1.hashCode());
matchedByXMIID.put(item1Key.toString(), item2);
}
}
}
}

/**
* Iterates through both of the given {@link XMIResource resources} to find all the elements that can be
* matched by their XMI ID, then populates {@link #matchedByID} with those mappings.
*
* @param left
* First of the two {@link XMIResource resources} to visit.
* @param right
* Second of the {@link XMIResource resources} to visit.
* @throws FactoryException
* Thrown if we couldn't compute a key to store the items in cache.
*/
private void matchByID(Resource left, Resource right) throws FactoryException {
matchedByID.clear();
final Iterator<EObject> leftIterator = left.getAllContents();
while (leftIterator.hasNext()) {
final EObject item1 = leftIterator.next();
final String item1ID = EcoreUtil.getID(item1);
if (item1ID != null) {
final Iterator<EObject> rightIterator = right.getAllContents();
while (rightIterator.hasNext()) {
final EObject item2 = rightIterator.next();
final String item2ID = EcoreUtil.getID(item2);
if (item2 != null && item1ID.equals(item2ID)) {
final StringBuilder item1Key = new StringBuilder();
item1Key.append(NameSimilarity.findName(item1));
item1Key.append(item1.hashCode());
matchedByID.put(item1Key.toString(), item2);
break;
}
}
}
}
}

/**
* Returns a list containing mappings of the nodes of both given {@link List}s.
*
* @param list1
* First of the lists from which we need to map the elements
* @param list2
* Second list to map the elements from.
* @param window
* Number of siblings to consider for the matching.
* @param monitor
* {@link CompareProgressMonitor Progress monitor} to display while the comparison lasts. Might
* be <code>null</code>, in which case we won't monitor progress.
* @return A {@link List} containing mappings of the nodes of both given {@link List}s.
* @throws FactoryException
* Thrown if the metrics cannot be computed.
* @throws InterruptedException
* Thrown if the matching process is interrupted somehow.
*/
private List<Match2Elements> mapLists(List<EObject> list1, List<EObject> list2, int window,
CompareProgressMonitor monitor) throws FactoryException, InterruptedException {
final List<Match2Elements> result = new ArrayList<Match2Elements>();
int curIndex = 0 - window / 2;
final List<EObject> notFoundList1 = new ArrayList<EObject>(list1);
final List<EObject> notFoundList2 = new ArrayList<EObject>(list2);

final Iterator<EObject> it1 = list1.iterator();
// then iterate over the 2 lists and compare the elements
while (it1.hasNext() && notFoundList2.size() > 0) {
final EObject obj1 = it1.next();

final StringBuilder obj1Key = new StringBuilder();
obj1Key.append(NameSimilarity.findName(obj1));
obj1Key.append(obj1.hashCode());
EObject obj2 = matchedByID.get(obj1Key.toString());

if (obj2 == null) {
// subtracts the difference between the notfound and the
// original list to avoid ArrayOutOfBounds
final int end = Math.min(curIndex + window - (list2.size() - notFoundList2.size()),
notFoundList2.size());
final int index = Math
.min(Math.max(curIndex - (list2.size() - notFoundList2.size()), 0), end);

obj2 = findMostSimilar(obj1, notFoundList2.subList(index, end));
if (obj2 != null) {
// checks if the most similar to obj2 is obj1
final EObject obj1Check = findMostSimilar(obj2, notFoundList1);
if (obj1Check != obj1 && obj1Check != null && isSimilar(obj1Check, obj2)) {
continue;
}
}
}

if (notFoundList1.contains(obj1) && notFoundList2.contains(obj2) && isSimilar(obj1, obj2)) {
final Match2Elements mapping = MatchFactory.eINSTANCE.createMatch2Elements();
final double metric = absoluteMetric(obj1, obj2);

mapping.setLeftElement(obj1);
mapping.setRightElement(obj2);
mapping.setSimilarity(metric);
result.add(mapping);
notFoundList2.remove(obj2);
notFoundList1.remove(obj1);
}
curIndex += 1;
monitor.worked(1);
if (monitor.isCanceled())
throw new InterruptedException();
}

// now putting the not found elements aside for later
stillToFindFromModel2.addAll(notFoundList2);
stillToFindFromModel1.addAll(notFoundList1);
return result;
}

/**
* Returns an absolute comparison metric between the two given {@link EObject}s.
*
* @param obj1
* The first {@link EObject} to compare.
* @param obj2
* Second of the {@link EObject}s to compare.
* @return An absolute comparison metric. 0 &lt; value &lt; 1.
* @throws FactoryException
* Thrown if we cannot compute the content similarity.
*/
private double absoluteMetric(EObject obj1, EObject obj2) throws FactoryException {
final double nameSimilarity = nameSimilarity(obj1, obj2);
final double relationsSimilarity = relationsSimilarity(obj1, obj2);
double sameUri = 0d;
if (hasSameUri(obj1, obj2))
sameUri = 1;
final double positionSimilarity = relationsSimilarity / 2d + sameUri / 2d;

final double contentWeight = 0.5d;

if (nonNullFeaturesCount(obj1) > MIN_ATTRIBUTES_COUNT
&& nonNullFeaturesCount(obj2) > MIN_ATTRIBUTES_COUNT) {
final double nameWeight = 0.4d;
final double positionWeight = 0.4d;
final double contentSimilarity = contentSimilarity(obj1, obj2);
// Computing type similarity really is time expensive
// double typeSimilarity = typeSimilarity(obj1, obj2);
return (contentSimilarity * contentWeight + nameSimilarity * nameWeight + positionSimilarity
* positionWeight)
/ (contentWeight + nameWeight + positionWeight);
}
// we didn't have enough features to compute an accurate metric
final double nameWeight = 0.8d;
final double positionWeight = 0.2d;
return (nameSimilarity * nameWeight + positionSimilarity * positionWeight)
/ (nameWeight + positionWeight);
}

/**
* This will compute the similarity between two {@link EObject}s' relations.
*
* @param obj1
* First of the two {@link EObject}s.
* @param obj2
* Second of the two {@link EObject}s.
* @return <code>double</code> representing the similarity between the two {@link EObject}s' relations.
* 0 &lt; value &lt; 1.
* @throws FactoryException
* Thrown if we cannot compute the relations' similarity metrics.
* @see StructureSimilarity#relationsSimilarityMetric(EObject, EObject, MetamodelFilter)
*/
private double relationsSimilarity(EObject obj1, EObject obj2) throws FactoryException {
double similarity = 0d;
final Double value = getSimilarityFromCache(obj1, obj2, RELATION_SIMILARITY);
if (value != null) {
similarity = value;
} else {
similarity = StructureSimilarity.relationsSimilarityMetric(obj1, obj2, filter);
setSimilarityInCache(obj1, obj2, RELATION_SIMILARITY, similarity);
}
return similarity;
}

/**
* Checks wether the two given {@link EObject} have the same URI.
*
* @param obj1
* First of the two {@link EObject} we're comparing.
* @param obj2
* Second {@link EObject} we're comparing.
* @return <code>True</code> if the {@link EObject}s have the same URI, <code>False</code> otherwise.
*/
private boolean hasSameUri(EObject obj1, EObject obj2) {
if (obj1.eResource() != null && obj2.eResource() != null)
return obj1.eResource().getURIFragment(obj1).equals(obj2.eResource( ).getURIFragment(obj2));
return false;
}

/**
* Counts all the {@link EStructuralFeature features} of the given {@link EObject} that are
* <code>null</code> or initialized to the empty {@link String} &quot;&quot;.
*
* @param eobj
* {@link EObject} we need to count the empty features of.
* @return The number of features initialized to <code>null</code> or the empty String.
*/
private int nonNullFeaturesCount(EObject eobj) {
// TODO should probably cache result here
int nonNullFeatures = 0;
final Iterator<EStructuralFeature> features = eobj.eClass().getEAllStructuralFeatures().iterator();
while (features.hasNext()) {
final EStructuralFeature feature = features.next();
if (eobj.eGet(feature) != null && !"".equals(eobj.eGet(feature).toString())) //$NON-NLS-1$
nonNullFeatures++;
}
return nonNullFeatures;
}
/**
* We consider here <code>current1</code> and <code>current2</code> are similar. This method creates
* the mapping for the objects <code>current1</code> and <code>current2</code>, Then submappings for
* these two elements' contents.
*
* @param current1
* First element of the two elements mapping.
* @param current2
* Second of the two elements mapping.
* @param monitor
* {@link CompareProgressMonitor Progress monitor} to display while the comparison lasts. Might
* be <code>null</code>, in which case we won't monitor progress.
* @return The mapping for <code>current1</code> and <code>current2</code> and their content.
* @throws FactoryException
* Thrown when the metrics cannot be computed for <code>current1</code> and
* <code>current2</code>.
* @throws InterruptedException
* Thrown if the matching process is interrupted somehow.
*/
private Match2Elements recursiveMappings(EObject current1, EObject current2,
CompareProgressMonitor monitor) throws FactoryException, InterruptedException {
Match2Elements mapping = null;
mapping = MatchFactory.eINSTANCE.createMatch2Elements();
mapping.setLeftElement(current1);
mapping.setRightElement(current2);
mapping.setSimilarity(absoluteMetric(current1, current2));
final List<Match2Elements> mapList = mapLists(getContents(current1), getContents(current2), this
.<Integer> getOption(MatchOptions.OPTION_SEARCH_WINDOW), monitor);
// We can map other elements with mapLists; we iterate through them.
final Iterator<Match2Elements> it = mapList.iterator();
while (it.hasNext()) {
final Match2Elements subMapping = it.next();
// As we know source and target are similars, we call recursive
// mappings onto these objects
EFactory.eAdd(mapping, SUBMATCH_ELEMENT_NAME, recursiveMappings(subMapping.getLeftElement(),
subMapping.getRightElement(), monitor));
}
return mapping;
}

/**
* Workaround for bug #235606 : elements held by a reference with containment=true and derived=true are
* not matched since not returned by {@link EObject#eContents()}. This allows us to return the list of all
* contents from an EObject <u>including</u> those references.
*
* @param eObject
* The EObject we seek the content of.
* @return The list of all the content of a given EObject, derived containmnent references included.
*/
@SuppressWarnings("unchecked")
private List<EObject> getContents(EObject eObject) {
// TODO can this be cached (Map<EClass, List<EReference>>)?
final List<EObject> result = new ArrayList(eObject.eContents());
for (EReference reference : eObject.eClass().getEAllReferences()) {
if (reference.isContainment() && reference.isDerived()) {
final Object value = eObject.eGet(reference);
if (value instanceof Collection)
result.addAll((Collection)value);
else if (value instanceof EObject)
result.add((EObject)value);
}
}
return result;
}

/**
* Creates the {@link Match2Elements submatch elements} corresponding to the mapping of objects from the
* two given {@link List}s.
*
* @param root
* Root of the {@link MatchModel} where to insert all these mappings.
* @param list1
* First of the lists used to compute mapping.
* @param list2
* Second of the lists used to compute mapping.
* @param monitor
* {@link CompareProgressMonitor progress monitor} to display while the comparison lasts. Might
* be <code>null</code>, in which case we won't monitor progress.
* @throws FactoryException
* Thrown if we cannot match the elements of the two lists or add submatch elements to
* <code>root</code>.
* @throws InterruptedException
* Thrown if the operation is cancelled or fails somehow.
*/
private void createSubMatchElements(EObject root, List<EObject> list1, List<EObject> list2,
CompareProgressMonitor monitor) throws FactoryException, InterruptedException {
stillToFindFromModel1.clear();
stillToFindFromModel2.clear();
final List<Match2Elements> mappings = mapLists(list1, list2, this
.<Integer> getOption(MatchOptions.OPTION_SEARCH_WINDOW), monitor);

final Iterator<Match2Elements> it = mappings.iterator();
while (it.hasNext()) {
final Match2Elements map = it.next();
final Match2Elements match = recursiveMappings(map.getLeftElement(), map.getRightElement(),
monitor);
redirectedAdd(root, SUBMATCH_ELEMENT_NAME, match);
}
}

/**
* Creates {@link UnMatchElement}s wrapped around all the elements of the given {@link List}.
*
* @param root
* Root of the {@link MatchModel} under which to insert all these {@link UnMatchElement}s.
* @param unMatchedElements
* {@link Set} containing all the elements we haven't been able to match.
* @throws FactoryException
* Thrown if we cannot add elements under the given {@link MatchModel root}.
*/
private void createUnMatchElements(MatchModel root, Set<EObject> unMatchedElements)
throws FactoryException {
for (EObject element : unMatchedElements) {
final UnMatchElement unMap = MatchFactory.eINSTANCE.createUnMatchElement();
unMap.setElement(element);
redirectedAdd(root, UNMATCH_ELEMENT_NAME, unMap);
}
unMatchedElements.clear();
}

/**
* This method is an indirection for adding Mappings in the current MappingGroup.
*
* @param object
* {@link EObject} to add a feature value to.
* @param name
* Name of the feature to consider.
* @param value
* Value to add to the feature <code>name</code> of <code>object</code>.
* @throws FactoryException
* Thrown if the value's affectation fails.
*/
private void redirectedAdd(EObject object, String name, Object value) throws FactoryException {
EFactory.eAdd(object, name, value);
}

/**
* Returns the given similarity between the two given {@link EObject}s as it is stored in cache.<br/>
* <p>
* <code>similarityKind</code> must be one of
* <ul>
* <li>{@link #NAME_SIMILARITY}</li>
* <li>{@link #TYPE_SIMILARITY}</li>
* <li>{@link #VALUE_SIMILARITY}</li>
* <li>{@link #RELATION_SIMILARITY}</li>
* </ul>
* </p>
*
* @param obj1
* First of the two {@link EObject}s we seek the similarity for.
* @param obj2
* Second of the two {@link EObject}s we seek the similarity for.
* @param similarityKind
* Kind of similarity to get.
* @return The similarity as described by <code>similarityKind</code> as it is stored in cache for the
* two given {@link EObject}s.
*/
private Double getSimilarityFromCache(EObject obj1, EObject obj2, char similarityKind) {
return metricsCache.get(pairHashCode(obj1, obj2, similarityKind));
}

/**
* Computes an unique key between to {@link EObject}s to store their similarity in cache.
* <p>
* <code>similarityKind</code> must be one of
* <ul>
* <li>{@link #NAME_SIMILARITY}</li>
* <li>{@link #TYPE_SIMILARITY}</li>
* <li>{@link #VALUE_SIMILARITY}</li>
* <li>{@link #RELATION_SIMILARITY}</li>
* </ul>
* </p>
*
* @param obj1
* First of the two {@link EObject}s.
* @param obj2
* Second of the two {@link EObject}s.
* @param similarityKind
* Kind of similarity this key will represent in cache.
* @return Unique key for the similarity cache.
*/
private String pairHashCode(EObject obj1, EObject obj2, char similarityKind) {
if (similarityKind == NAME_SIMILARITY || similarityKind == TYPE_SIMILARITY
|| similarityKind == VALUE_SIMILARITY || similarityKind == RELATION_SIMILARITY) {
final StringBuilder hash = new StringBuilder();
hash.append(similarityKind).append(obj1.hashCode()).append(o bj2.hashCode());
return hash.toString();
}
throw new IllegalArgumentException(EMFCompareMatchMessages.getString(
"DifferencesServices.illegalSimilarityKind", similarityKind)); //$NON-NLS-1$
}

/**
* Stores in cache the given similarity between the two given {@link EObject}s.<br/>
* <p>
* <code>similarityKind</code> must be one of
* <ul>
* <li>{@link #NAME_SIMILARITY}</li>
* <li>{@link #TYPE_SIMILARITY}</li>
* <li>{@link #VALUE_SIMILARITY}</li>
* <li>{@link #RELATION_SIMILARITY}</li>
* </ul>
* </p>
*
* @param obj1
* First of the two {@link EObject}s we're setting the similarity for.
* @param obj2
* Second of the two {@link EObject}s we're setting the similarity for.
* @param similarityKind
* Kind of similarity to set.
* @param similarity
* Value of the similarity between the two {@link EObject}s.
*/
private void setSimilarityInCache(EObject obj1, EObject obj2, char similarityKind, double similarity) {
metricsCache.put(pairHashCode(obj1, obj2, similarityKind), new Double(similarity));
}


}

//////////////////////////////////////////////////////////// ////////////////////////////////////////////
and the content of my console (when i used the GenericMatchEngine and GenericDiffEngine):

//////////////////////////////////////////////////////////// ////////////////////////////////////////////
*** Loading resources ***

C:\Documents and Settings\yatimih\runtime-New_configuration\MyAlgorithm1\diag ram\Copy of old-default.impala_diagram : rootCompositeBox1

C:\Documents and Settings\yatimih\runtime-New_configuration\MyAlgorithm1\diag ram\old-default.impala_diagram : rootCompositeBox2

*** matched Elements ***

Matched Elements(size) = 1

MatchElem[0] : org.eclipse.emf.compare.match.metamodel.impl.Match2ElementsI mpl @1eb0d79 (similarity: 0.9580419580419581) has similarity : 0.9580419580419581

the left element is : com.st.hed.iqi.impala.srcgen.model.impl.RootCompositeBoxImpl @120d1c0 (name: MyAlgorithm1, version: 1.0.0, description: Description is not filled, isReadOnly: false, isChangedFromLib: false)

the right element is : com.st.hed.iqi.impala.srcgen.model.impl.RootCompositeBoxImpl @f82888 (name: MyAlgorithm1, version: 1.0.0, description: Description is not filled, isReadOnly: false, isChangedFromLib: false)

this is a list of the content objects of the left element :

* com.st.hed.iqi.impala.srcgen.model.impl.NCodeGenPropertyImpl @1a9ab54 (language: iqi-c, name: GEN_UNIQUE_NAME, value: )

this is a list of the content objects of the left element :

* com.st.hed.iqi.impala.srcgen.model.impl.NCodeGenPropertyImpl @1f7e4cf (language: iqi-c, name: GENERATION_DATE, value: )

this is a list of the content objects of the left element :

* com.st.hed.iqi.impala.srcgen.model.impl.NCodeGenPropertyImpl @1cee582 (language: iqi-c, name: USER, value: )

this is a list of the content objects of the left element :

* com.st.hed.iqi.impala.srcgen.model.impl.NCodeGenPropertyImpl @3dd567 (language: iqi-c, name: GENERATOR_VERSION, value: )

this is a list of the content objects of the left element :

* com.st.hed.iqi.impala.srcgen.model.impl.NCodeGenPropertyImpl @1856ec1 (language: iqi-c, name: TYPE_QUALIFIED_NAME, value: )

this is a list of the content objects of the left element :

* com.st.hed.impala.src.model.impl.ImpalaInputParameterBoxImpl @ec28c0 (name: Sequence_input, version: 1.0.0, description: Description is not filled, isReadOnly: false, isChangedFromLib: false) (debugMode: NoDebug, debugTextFormat: null, debugHeader: null, debugTrailer: null, debugDumpDestination: null)

this is a list of the content objects of the left element :

* com.st.hed.iqi.impala.srcgen.model.impl.CompositeBoxImpl@1c200d0 (name: CB, version: 1.0.0, description: Description is not filled, isReadOnly: false, isChangedFromLib: false)

this is a list of the content objects of the left element :

* com.st.hed.impala.src.model.impl.ImpalaFrameGathererImpl@5db277 (increment: 1, channel: Y, offsetInSequence: 0) (name: FG, version: 1.0.0, description: Description is not filled, isReadOnly: false, isChangedFromLib: false, debugMode: NoDebug, debugTextFormat: null, debugHeader: null, debugTrailer: null, debugDumpDestination: null, newRootDirectory: null, newRadix: null)

this is a list of the content objects of the left element :

* com.st.hed.impala.src.model.impl.ImpalaFrameSelectorImpl@6cd712 (increment: 1, channel: Y, offsetInSequence: 0) (name: FS, version: 1.0.0, description: Description is not filled, isReadOnly: false, isChangedFromLib: false, debugMode: NoDebug, debugTextFormat: null, debugHeader: null, debugTrailer: null, debugDumpDestination: null)

this is a list of the content objects of the left element :

* com.st.hed.iqi.impala.srcgen.model.impl.NSequenceImpl@f61e2 (name: input, version: 1.0.0, description: Description is not filled, isReadOnly: false, isChangedFromLib: false) (width: 1, height: 1, sampling: YUV444, startFrameNb: 0, NbOfFrames: 1, SequenceRoot: , SequenceRadix: , storageType: SGP, isProgressive: true, isTopFirst: true, dynamic: Cool



this is a list of the content objects of the right element :

* com.st.hed.iqi.impala.srcgen.model.impl.NCodeGenPropertyImpl @2d1d1e (language: iqi-c, name: GEN_UNIQUE_NAME, value: )

this is a list of the content objects of the right element :

* com.st.hed.iqi.impala.srcgen.model.impl.NCodeGenPropertyImpl @1d2c4aa (language: iqi-c, name: GENERATION_DATE, value: )

this is a list of the content objects of the right element :

* com.st.hed.iqi.impala.srcgen.model.impl.NCodeGenPropertyImpl @6db04e (language: iqi-c, name: USER, value: )

this is a list of the content objects of the right element :

* com.st.hed.iqi.impala.srcgen.model.impl.NCodeGenPropertyImpl @151da55 (language: iqi-c, name: GENERATOR_VERSION, value: )

this is a list of the content objects of the right element :

* com.st.hed.impala.src.model.impl.ImpalaInputParameterBoxImpl @d53356 (name: Sequence_input, version: 1.0.0, description: Description is not filled, isReadOnly: false, isChangedFromLib: false) (debugMode: NoDebug, debugTextFormat: null, debugHeader: null, debugTrailer: null, debugDumpDestination: null)

this is a list of the content objects of the right element :

* com.st.hed.iqi.impala.srcgen.model.impl.CompositeBoxImpl@877294 (name: CB, version: 1.0.0, description: Description is not filled, isReadOnly: false, isChangedFromLib: false)

this is a list of the content objects of the right element :

* com.st.hed.impala.src.model.impl.ImpalaFrameGathererImpl@1fa522d (increment: 1, channel: Y, offsetInSequence: 0) (name: FG, version: 1.0.0, description: Description is not filled, isReadOnly: false, isChangedFromLib: false, debugMode: NoDebug, debugTextFormat: null, debugHeader: null, debugTrailer: null, debugDumpDestination: null, newRootDirectory: null, newRadix: null)

this is a list of the content objects of the right element :

* com.st.hed.impala.src.model.impl.ImpalaFrameGathererImpl@129271e (increment: 1, channel: Y, offsetInSequence: 0) (name: FG1, version: 1.0.0, description: Description is not filled, isReadOnly: false, isChangedFromLib: false, debugMode: NoDebug, debugTextFormat: null, debugHeader: null, debugTrailer: null, debugDumpDestination: null, newRootDirectory: null, newRadix: null)

this is a list of the content objects of the right element :

* com.st.hed.impala.src.model.impl.ImpalaFrameSelectorImpl@c73ac2 (increment: 1, channel: Y, offsetInSequence: 0) (name: FS, version: 1.0.0, description: Description is not filled, isReadOnly: false, isChangedFromLib: false, debugMode: NoDebug, debugTextFormat: null, debugHeader: null, debugTrailer: null, debugDumpDestination: null)

this is a list of the content objects of the right element :

* com.st.hed.iqi.impala.srcgen.model.impl.NSequenceImpl@1e2b2a6 (name: input, version: 1.0.0, description: Description is not filled, isReadOnly: false, isChangedFromLib: false) (width: 1, height: 1, sampling: YUV444, startFrameNb: 0, NbOfFrames: 1, SequenceRoot: , SequenceRadix: , storageType: SGP, isProgressive: true, isTopFirst: true, dynamic: Cool

this is a list of the content objects of the right element :

* com.st.hed.iqi.impala.srcgen.model.impl.CompositeBoxImpl@6d2d52 (name: lib, version: 1.0.0, description: This is the container for the library types, isReadOnly: false, isChangedFromLib: false)

Unmatched Elements(size) = 8

UnMatchElem[0] is : org.eclipse.emf.compare.match.metamodel.impl.UnMatchElementI mpl @c183ea

* org.eclipse.gmf.runtime.notation.impl.DiagramImpl@1ea08e7 (visible: true, type: impala-metamodel, mutable: false) (name: , measurementUnit: Pixel)

UnMatchElem[1] is : org.eclipse.emf.compare.match.metamodel.impl.UnMatchElementI mpl @bbb074

* com.st.hed.iqi.impala.srcgen.model.impl.NCodeGenPropertyImpl @1c3599d (language: iqi-c, name: GEN_UNIQUE_NAME, value: )

UnMatchElem[2] is : org.eclipse.emf.compare.match.metamodel.impl.UnMatchElementI mpl @3dc250

* com.st.hed.iqi.impala.srcgen.model.impl.NCodeGenPropertyImpl @f933f1 (language: iqi-c, name: TYPE_QUALIFIED_NAME, value: MyAlgorithm1::lib::pixel)

UnMatchElem[3] is : org.eclipse.emf.compare.match.metamodel.impl.UnMatchElementI mpl @a01a84

* com.st.hed.iqi.impala.srcgen.model.impl.NCodeGenPropertyImpl @559e4f (language: iqi-c, name: TYPE_QUALIFIED_NAME, value: MyAlgorithm1::lib::pixel)

UnMatchElem[4] is : org.eclipse.emf.compare.match.metamodel.impl.UnMatchElementI mpl @12cf455

* com.st.hed.iqi.impala.srcgen.model.impl.CompositeBoxImpl@6d2d52 (name: lib, version: 1.0.0, description: This is the container for the library types, isReadOnly: false, isChangedFromLib: false)

lib

* com.st.hed.iqi.impala.srcgen.model.impl.NCodeGenPropertyImpl @7da288 (language: iqi-c, name: LIB_CONTAINER, value: true)

* com.st.hed.iqi.impala.srcgen.model.impl.NCodeGenPropertyImpl @399f62 (language: iqi-c, name: GEN_UNIQUE_NAME, value: MyAlgorithm1::lib)

* com.st.hed.impala.src.model.impl.ImpalaInputWindowImpl@176feac (name: pixel, version: 1.0.0, description: Description is not filled, isReadOnly: false, isChangedFromLib: false) (height: 1, width: 1) (debugMode: NoDebug, debugTextFormat: null, debugHeader: null, debugTrailer: null, debugDumpDestination: null)

UnMatchElem[5] is : org.eclipse.emf.compare.match.metamodel.impl.UnMatchElementI mpl @5d15c6

* org.eclipse.gmf.runtime.notation.impl.EdgeImpl@1282220 (visible: true, type: 3009, mutable: false)

UnMatchElem[6] is : org.eclipse.emf.compare.match.metamodel.impl.UnMatchElementI mpl @140960c

* com.st.hed.impala.src.model.impl.ImpalaFrameGathererImpl@129271e (increment: 1, channel: Y, offsetInSequence: 0) (name: FG1, version: 1.0.0, description: Description is not filled, isReadOnly: false, isChangedFromLib: false, debugMode: NoDebug, debugTextFormat: null, debugHeader: null, debugTrailer: null, debugDumpDestination: null, newRootDirectory: null, newRadix: null)

FG1

UnMatchElem[7] is : org.eclipse.emf.compare.match.metamodel.impl.UnMatchElementI mpl @13afac7

* org.eclipse.gmf.runtime.notation.impl.NodeImpl@9283b0 (visible: true, type: 1007, mutable: false)

*** Differencing models ***

Diff Elements(size) = 1

DiffElement[0] is : org.eclipse.emf.compare.diff.metamodel.impl.DiffGroupImpl@4000e7 (conflicting: false, kind: Addition)

KIND = Change

org.eclipse.emf.compare.diff.metamodel.impl.DiffGroupImpl@4000e7 (conflicting: false, kind: Change)

[10 change(s) in RootCompositeBox MyAlgorithm1, 11 change(s) in Diagram default.impala_diagram, org.eclipse.gmf.runtime.notation.impl.DiagramImpl@1ea08e7 (visible: true, type: impala-metamodel, mutable: false) (name: , measurementUnit: Pixel) has been removed]

* 10 change(s) in RootCompositeBox MyAlgorithm1

[6 change(s) in CompositeBox CB, 2 change(s) in NCodeGenProperty TYPE_QUALIFIED_NAME, com.st.hed.iqi.impala.srcgen.model.impl.CompositeBoxImpl@6d2d52 (name: lib, version: 1.0.0, description: This is the container for the library types, isReadOnly: false, isChangedFromLib: false) has been added, com.st.hed.impala.src.model.impl.ImpalaFrameGathererImpl@129271e (increment: 1, channel: Y, offsetInSequence: 0) (name: FG1, version: 1.0.0, description: Description is not filled, isReadOnly: false, isChangedFromLib: false, debugMode: NoDebug, debugTextFormat: null, debugHeader: null, debugTrailer: null, debugDumpDestination: null, newRootDirectory: null, newRadix: null) has been added]

* 6 change(s) in CompositeBox CB

[3 change(s) in Shaper SHAP, 1 change(s) in FrameGatherer FGCB, com.st.hed.iqi.impala.srcgen.model.impl.NCodeGenPropertyImpl @1c3599d (language: iqi-c, name: GEN_UNIQUE_NAME, value: ) has been removed, 1 change(s) in Kernel k]

* 3 change(s) in Shaper SHAP

[3 change(s) in OutputWindow out]

* 3 change(s) in OutputWindow out

[Attribute debugTrailer in out has changed from to null, Attribute debugDumpDestination in out has changed from to null, com.st.hed.iqi.impala.srcgen.model.impl.NCodeGenPropertyImpl @559e4f (language: iqi-c, name: TYPE_QUALIFIED_NAME, value: MyAlgorithm1::lib::pixel) has been added]

false

false

false

* 1 change(s) in FrameGatherer FGCB

[FG1 has been added to reference toParentOutputFrames in FGCB]

false

false

* 1 change(s) in Kernel k

[1 change(s) in InputWindow IWK]

* 1 change(s) in InputWindow IWK

[ com.st.hed.iqi.impala.srcgen.model.impl.NCodeGenPropertyImpl @f933f1 (language: iqi-c, name: TYPE_QUALIFIED_NAME, value: MyAlgorithm1::lib::pixel) has been added]

false

* 2 change(s) in NCodeGenProperty TYPE_QUALIFIED_NAME

[Attribute value in TYPE_QUALIFIED_NAME has changed from to MyAlgorithm1::lib::pixel, TYPE_QUALIFIED_NAME has been moved from com.st.hed.iqi.impala.srcgen.model.impl.RootCompositeBoxImpl @120d1c0 (name: MyAlgorithm1, version: 1.0.0, description: Description is not filled, isReadOnly: false, isChangedFromLib: false) to com.st.hed.impala.src.model.impl.ImpalaOutputWindowImpl@1423658 (name: OWK, version: 1.0.0, description: Description is not filled, isReadOnly: false, isChangedFromLib: false) (height: 1, width: 1) (debugMode: NoDebug, debugTextFormat: null, debugHeader: null, debugTrailer: null, debugDumpDestination: null)]

false

false

false

false

* 11 change(s) in Diagram default.impala_diagram

[3 change(s) in Node true, 1 change(s) in Edge true, 1 change(s) in Edge true, 1 change(s) in Edge true, 1 change(s) in Edge true, 1 change(s) in Edge true, 1 change(s) in Edge true, org.eclipse.gmf.runtime.notation.impl.EdgeImpl@1282220 (visible: true, type: 3009, mutable: false) has been added, org.eclipse.gmf.runtime.notation.impl.NodeImpl@9283b0 (visible: true, type: 1007, mutable: false) has been added]

* 3 change(s) in Node true

[1 change(s) in Node true, 1 change(s) in HintedDiagramLinkStyle HintedDiagramLinkStyle, 1 change(s) in Bounds 96]

* 1 change(s) in Node true

[1 change(s) in Node true]

* 1 change(s) in Node true

[1 change(s) in Bounds 337]

* 1 change(s) in Bounds 337

[Attribute width in 337 has changed from 187 to -1]

false

* 1 change(s) in HintedDiagramLinkStyle HintedDiagramLinkStyle

[Reference diagramLink in HintedDiagramLinkStyle changed from org.eclipse.gmf.runtime.notation.impl.DiagramImpl@1ea08e7 (visible: true, type: impala-metamodel, mutable: false) (name: , measurementUnit: Pixel) to null]

false

* 1 change(s) in Bounds 96

[Attribute height in 96 has changed from 192 to 253]

false

* 1 change(s) in Edge true

[1 change(s) in RelativeBendpoints [org.eclipse.gmf.runtime.notation.datatype.RelativeBendpoint@beb8f0 (sourceX: 31, sourceY: -1, targetX: -58, targetY: -133), org.eclipse.gmf.runtime.notation.datatype.RelativeBendpoint@15faa7c (sourceX: 42, sourceY: -1, targetX: -47, targetY: -133), org.eclipse.gmf.runtime.notation.datatype.RelativeBendpoint@1b1db9a (sourceX: 42, sourceY: 131, targetX: -47, targetY: -1), org.eclipse.gmf.runtime.notation.datatype.RelativeBendpoint@1c86489 (sourceX: 60, sourceY: 131, targetX: -29, targetY: -1)]]

* 1 change(s) in RelativeBendpoints [org.eclipse.gmf.runtime.notation.datatype.RelativeBendpoint@beb8f0 (sourceX: 31, sourceY: -1, targetX: -58, targetY: -133), org.eclipse.gmf.runtime.notation.datatype.RelativeBendpoint@15faa7c (sourceX: 42, sourceY: -1, targetX: -47, targetY: -133), org.eclipse.gmf.runtime.notation.datatype.RelativeBendpoint@1b1db9a (sourceX: 42, sourceY: 131, targetX: -47, targetY: -1), org.eclipse.gmf.runtime.notation.datatype.RelativeBendpoint@1c86489 (sourceX: 60, sourceY: 131, targetX: -29, targetY: -1)]

[Att
Re: EMF Compare [message #536851 is a reply to message #536508] Mon, 31 May 2010 09:35 Go to previous message
Laurent Goubet is currently offline Laurent GoubetFriend
Messages: 1902
Registered: July 2009
Senior Member
This is a multi-part message in MIME format.
--------------040809070202060300050909
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 7bit

Hi,

As you fully copy/pasted the GenericMatchEngine in your own
implementation (thus shunning any improvement/fix we may have done since
then), I cannot say where you changed anything, and try and determine
what your code does.

Other than that, I must admit I don't really understand your issue. If
you don't wish to see any difference concerning the diagrams, why do
you compare the diagrams and not the underlying models?

Laurent Goubet
Obeo

Hanane wrote:
>
> Hi Laurent,
> Thank you for your reply.
>
> In fact,until now,with EMFCompare i can see matched element ,unmatched
> element and diff element in my console,
> but the problem is that i don't want to see all things concerning the
> diagram ( means ,position of elements in models like (x, y) gmf,... )but
> only models (means if the elements of type EObjects exist in models or
> no,and also if their attribute has changed or no...) ,
>
> For that raison,i create my own (MatchEngine and DiffEngine) ; which
> extend (GenericMatchEngine and GenericDiffEngine);
> and also,i add my" Extension Point " like that :
>
> - fileExtension (impala_diagram )
> -engineClass (ImpalaMatchEngine)
>
> and i did the same for DifEngine
>
>
> And i want know which methods,class...are responsible for the display of
> the diagram (position of the elements in models ) that i have to
> override;otherwise , i want to keep in my own MatchEngine only methods
> which allow me to do the comparison between the two medels concerning
> existance (so deletion,addition,change) of elements,
>
> this is the code of my own MatchEngine :
>
> ////////////////////////////////////////////////////////////
> ////////////////////////////////////////////
>
> package com.st.hed.iqi.impala.emfcompareimpala;
>
> import java.util.ArrayList;
> import java.util.Collection;
> import java.util.HashSet;
> import java.util.Iterator;
> import java.util.List;
> import java.util.Map;
> import java.util.Set;
>
> import org.eclipse.emf.common.EMFPlugin;
> import org.eclipse.emf.compare.EMFComparePlugin;
> import org.eclipse.emf.compare.FactoryException;
> import org.eclipse.emf.compare.internal.runtime.CompareProgressMoni tor;
> import org.eclipse.emf.compare.match.EMFCompareMatchMessages;
> import org.eclipse.emf.compare.match.api.MatchOptions;
> import org.eclipse.emf.compare.match.engine.GenericMatchEngine;
> import org.eclipse.emf.compare.match.metamodel.Match2Elements;
> import org.eclipse.emf.compare.match.metamodel.MatchFactory;
> import org.eclipse.emf.compare.match.metamodel.MatchModel;
> import org.eclipse.emf.compare.match.metamodel.UnMatchElement;
> import org.eclipse.emf.compare.match.statistic.MetamodelFilter;
> import org.eclipse.emf.compare.match.statistic.similarity.NameSimil arity;
> import org.eclipse.emf.compare.match.statistic.similarity.Structure
> Similarity;
> import org.eclipse.emf.compare.util.EFactory;
> import org.eclipse.emf.compare.util.EMFCompareMap;
> import org.eclipse.emf.compare.util.EMFComparePreferenceKeys;
> import org.eclipse.emf.ecore.EObject;
> import org.eclipse.emf.ecore.EReference;
> import org.eclipse.emf.ecore.EStructuralFeature;
> import org.eclipse.emf.ecore.resource.Resource;
> import org.eclipse.emf.ecore.util.EcoreUtil;
> import org.eclipse.emf.ecore.xmi.XMIResource;
>
> public class ImpalaMatchEngine extends GenericMatchEngine{
>
> /** Containmnent reference for the matched elements root. */
> private static final String MATCH_ELEMENT_NAME = "matchedElements";
> //$NON-NLS-1$
>
> /**
> * Minimal number of attributes an element must have for content
> comparison.
> */
> private static final int MIN_ATTRIBUTES_COUNT = 5;
>
> /** This constant is used as key for the buffering of relations
> similarity. */
> private static final char RELATION_SIMILARITY = 'r';
>
> /** Containmnent reference for {@link MatchElement}s' submatches. */
> private static final String SUBMATCH_ELEMENT_NAME =
> "subMatchElements"; //$NON-NLS-1$
>
> /** Containmnent reference for the {@link MatchModel}'s unmatched
> elements. */
> private static final String UNMATCH_ELEMENT_NAME =
> "unMatchedElements"; //$NON-NLS-1$
>
> /** This constant is used as key for the buffering of name
> similarity. */
> private static final char NAME_SIMILARITY = 'n';
>
> /** This constant is used as key for the buffering of type
> similarity. */
> private static final char TYPE_SIMILARITY = 't';
>
> /** This constant is used as key for the buffering of value
> similarity. */
> private static final char VALUE_SIMILARITY = 'v';
>
> /**
> * {@link MetamodelFilter} used for filtering unused features of the
> objects we're computing the
> * similarity for.
> */
> protected final MetamodelFilter filter = new MetamodelFilter();
>
> /** Contains the options given to the match procedure. */
> protected final Map<String, Object> options = new
> EMFCompareMap<String, Object>();
>
> /**
> * This map allows us memorize the {@link EObject} we've been able
> to match thanks to their functional ID.
> */
> private final Map<String, EObject> matchedByID = new
> EMFCompareMap<String, EObject>();
>
> /**
> * This map allows us memorize the {@link EObject} we've been able
> to match thanks to their XMI ID.
> */
> private final Map<String, EObject> matchedByXMIID = new
> EMFCompareMap<String, EObject>();
>
> /**
> * This map is used to cache the comparison results Pair(Element1,
> Element2) => .
> */
> private final Map<String, Double> metricsCache = new
> EMFCompareMap<String, Double>();
>
>
> /**
> * This list will be intensively used while matching elements to
> keep track of the unmatched ones from the
> * left model.
> */
> private final List<EObject> stillToFindFromModel1 = new
> ArrayList<EObject>();
>
> /**
> * This list will be intensively used while matching elements to
> keep track of the unmatched ones from the
> * right model.
> */
> private final List<EObject> stillToFindFromModel2 = new
> ArrayList<EObject>();
>
> /**
> * {@inheritDoc}
> * * @see
> org.eclipse.emf.compare.match.api.IMatchEngine#modelMatch(or
> g.eclipse.emf.ecore.EObject,
> * org.eclipse.emf.ecore.EObject, java.util.Map)
> */
> public MatchModel modelMatch(EObject leftRoot, EObject rightRoot,
> Map<String, Object> optionMap)
> throws InterruptedException {
> if (optionMap != null && optionMap.size() > 0)
> loadOptionMap(optionMap);
>
> MatchModel result = null;
> // Creates and sizes progress monitor
> final CompareProgressMonitor monitor = new
> CompareProgressMonitor(getOption(MatchOptions.OPTION_PROGRES S_MONITOR));
> int size = 1;
> for (EObject root : leftRoot.eResource().getContents()) {
> final Iterator<EObject> rootContent = root.eAllContents();
> while (rootContent.hasNext()) {
> rootContent.next();
> size++;
> }
> }
> startMonitor(monitor, size);
>
> result = doMatch(leftRoot.eResource(), rightRoot.eResource(),
> monitor);
> return result;
> }
>
> /**
> * This replaces the contents of the defaults options map with the
> options overridden by the given map.
> * * @param map
> * Map containing the option given to the match
> procedure. cannot be <code>null</code>.
> */
> private void loadOptionMap(Map<String, Object> map) {
> options.putAll(map);
> Integer option = getOption(MatchOptions.OPTION_SEARCH_WINDOW);
> if (option< 0)
> options.put(MatchOptions.OPTION_SEARCH_WINDOW,
> getPreferenceSearchWindow());
> }
> /**
> * This will return the value associated to the given key in the
> options map.
> * <p>
> * NOTE : Misuses of this method will easily throw {@link
> ClassCastException}s.
> * </p>
> * * @param <T>
> * Expected type of the value associated to
> <code>key</code>.
> * @param key
> * Key of the value to retrieve.
> * @return Value associated to the given key in the options map.
> * @throws ClassCastException
> * If the value isn't assignment compatible with the
> expected type.
> */
> @SuppressWarnings("unchecked")
> protected <T> T getOption(String key) throws ClassCastException {
> return (T)options.get(key);
> }
>
> /**
> * Returns the search window corresponding to the number of siblings
> to consider while matching. Reducing
> * this number (on the preferences page) considerably improve
> performances while reducing precision.
> * * @return An <code>int</code> representing the number of
> siblings to consider for matching.
> */
> private int getPreferenceSearchWindow() {
> int searchWindow = MatchOptions.DEFAULT_SEARCH_WINDOW;
> if (EMFPlugin.IS_ECLIPSE_RUNNING
> && EMFComparePlugin.getDefault() != null
> && EMFComparePlugin.getDefault().getInt(
>
> EMFComparePreferenceKeys.PREFERENCES_KEY_SEARCH_WINDOW) > 0)
> searchWindow = EMFComparePlugin.getDefault().getInt(
>
> EMFComparePreferenceKeys.PREFERENCES_KEY_SEARCH_WINDOW);
> if (searchWindow < 0)
> searchWindow = 0;
> return searchWindow;
> }
>
> /**
> * Starts the monitor for comparison progress. Externalized here to
> avoid multiple usage of the Strings.
> * * @param monitor
> * The monitor that need be started
> * @param size
> * Size of the monitor
> */
> private void startMonitor(CompareProgressMonitor monitor, int size) {
>
> monitor.beginTask(EMFCompareMatchMessages.getString("DifferencesServices.monitor.task
> "), size); //$NON-NLS-1$
>
> monitor.subTask(EMFCompareMatchMessages.getString("DifferencesServices.monitor.browsing
> ")); //$NON-NLS-1$
> }
>
> /**
> * This method handles the creation and returning of a two way model
> match.
> * * @param leftResource
> * Left model for the comparison.
> * @param rightResource
> * Right model for the comparison.
> * @param monitor
> * Progress monitor to display while the comparison lasts.
> * @return The corresponding {@link MatchModel}.
> * @throws InterruptedException
> * Thrown if the comparison is interrupted somehow.
> */
> private MatchModel doMatch(Resource leftResource, Resource
> rightResource, CompareProgressMonitor monitor)
> throws InterruptedException {
> final MatchModel root = MatchFactory.eINSTANCE.createMatchModel();
> setModelURIs(root, leftResource, rightResource);
>
> // filters unused features
> filterUnused(leftResource);
> filterUnused(rightResource);
>
> // navigate through both models at the same time and realize
> mappings..
> try {
> if (!this.<Boolean>
> getOption(MatchOptions.OPTION_IGNORE_XMI_ID))
> if (leftResource instanceof XMIResource && rightResource
> instanceof XMIResource)
> matchByXMIID((XMIResource)leftResource,
> (XMIResource)rightResource);
> if (!this.<Boolean> getOption(MatchOptions.OPTION_IGNORE_ID))
> matchByID(leftResource, rightResource);
>
>
> monitor.subTask(EMFCompareMatchMessages.getString("DifferencesServices.monitor.roots
> ")); //$NON-NLS-1$
> final List<Match2Elements> matchedRoots =
> mapLists(leftResource.getContents(), rightResource
> .getContents(), this.<Integer>
> getOption(MatchOptions.OPTION_SEARCH_WINDOW), monitor);
> stillToFindFromModel1.clear();
> stillToFindFromModel2.clear();
> final List<EObject> unMatchedLeftRoots = new
> ArrayList<EObject>(leftResource.getContents());
> final List<EObject> unMatchedRightRoots = new
> ArrayList<EObject>(rightResource.getContents());
> // These sets will help us in keeping track of the yet to be
> found
> // elements
> final Set<EObject> still1 = new HashSet<EObject>();
> final Set<EObject> still2 = new HashSet<EObject>();
>
> // If one of the resources has no roots, considers it as
> deleted
> if (leftResource.getContents().size() > 0 &&
> rightResource.getContents().size() > 0) {
> Match2Elements matchModelRoot =
> MatchFactory.eINSTANCE.createMatch2Elements();
> // We haven't found any similar roots, we then consider the
> // firsts to be similar.
> if (matchedRoots.size() == 0) {
> final Match2Elements rootMapping =
> MatchFactory.eINSTANCE.createMatch2Elements();
>
> rootMapping.setLeftElement(leftResource.getContents().get(0) );
> EObject rightElement =
> findMostSimilar(leftResource.getContents().get(0),
> unMatchedRightRoots);
> if (rightElement == null)
> rightElement = unMatchedRightRoots.get(0);
> rootMapping.setRightElement(rightElement);
> matchedRoots.add(rootMapping);
> }
> monitor.subTask(EMFCompareMatchMessages
>
> .getString("DifferencesServices.monitor.rootsContents")); //$NON-NLS-1$
> for (Match2Elements matchedRoot : matchedRoots) {
> final Match2Elements rootMapping =
> recursiveMappings(matchedRoot.getLeftElement(),
> matchedRoot.getRightElement(), monitor);
> // this is the first passage
> if (matchModelRoot.getLeftElement() == null) {
> matchModelRoot = rootMapping;
> redirectedAdd(root, MATCH_ELEMENT_NAME,
> matchModelRoot);
> } else {
> redirectedAdd(matchModelRoot,
> SUBMATCH_ELEMENT_NAME, rootMapping);
> }
>
> // Synchronizes the two lists to avoid multiple
> elements
> still1.removeAll(stillToFindFromModel1);
> still2.removeAll(stillToFindFromModel2);
> // checks for matches within the yet to found
> elements lists
> createSubMatchElements(rootMapping, new
> ArrayList<EObject>(stillToFindFromModel1),
> new
> ArrayList<EObject>(stillToFindFromModel2), monitor);
> // Adds all unfound elements to the sets
> still1.addAll(stillToFindFromModel1);
> still2.addAll(stillToFindFromModel2);
>
>
> unMatchedLeftRoots.remove(matchedRoot.getLeftElement());
>
> unMatchedRightRoots.remove(matchedRoot.getRightElement());
> }
> // We'll iterate through the unMatchedRoots all contents
> monitor.subTask(EMFCompareMatchMessages
>
> .getString("DifferencesServices.monitor.unmatchedRoots")); //$NON-NLS-1$
> createSubMatchElements(matchModelRoot,
> unMatchedLeftRoots, unMatchedRightRoots, monitor);
> } else {
> // Roots are unmatched, this is either a file addition or
> // deletion
> still1.addAll(unMatchedLeftRoots);
> still2.addAll(unMatchedRightRoots);
> }
>
> // Now takes care of remaining unfound elements
> still1.addAll(stillToFindFromModel1);
> still2.addAll(stillToFindFromModel2);
> createUnMatchElements(root, still1);
> createUnMatchElements(root, still2);
> } catch (FactoryException e) {
> EMFComparePlugin.log(e, false);
> }
> return root;
> }
>
> /**
> * Sets the values of the {@link MatchModel}'s left and right models.
> * * @param modelRoot
> * Root of the {@link MatchModel}.
> * @param left
> * Element from which to resolve the left model URI.
> * @param right
> * Element from which to resolve the right model URI.
> */
> private void setModelURIs(MatchModel modelRoot, Resource left,
> Resource right) {
> setModelURIs(modelRoot, left, right, null);
> }
>
> /**
> * Sets the values of the {@link MatchModel}'s left, right and
> ancestor models.
> * * @param modelRoot
> * Root of the {@link MatchModel}.
> * @param left
> * Element from which to resolve the left model URI.
> * @param right
> * Element from which to resolve the right model URI.
> * @param ancestor
> * Element from which to resolve the ancestor model URI.
> Can be <code>null</code>.
> */
> private void setModelURIs(MatchModel modelRoot, Resource left,
> Resource right, Resource ancestor) {
> // Sets values of left, right and ancestor model URIs
> if (left != null && left.getURI() != null)
> modelRoot.setLeftModel(left.getURI().toString());
> if (right != null && right.getURI() != null)
> modelRoot.setRightModel(right.getURI().toString());
> if (ancestor != null && ancestor.getURI() != null)
> modelRoot.setOriginModel(ancestor.getURI().toString());
> }
>
> /**
> * Filters unused features of the resource.
> * * @param resource
> * Resource to be apply filter on.
> */
> private void filterUnused(Resource resource) {
> for (EObject root : resource.getContents())
> filter.analyseModel(root);
> }
>
> /**
> * Iterates through both of the given {@link XMIResource resources}
> to find all the elements that can be
> * matched by their XMI ID, then populates {@link #matchedByXMIID}
> with those mappings.
> * * @param left
> * First of the two {@link XMIResource resources} to visit.
> * @param right
> * Second of the {@link XMIResource resources} to visit.
> * @throws FactoryException
> * Thrown if we couldn't compute a key to store the
> items in cache.
> */
> private void matchByXMIID(XMIResource left, XMIResource right)
> throws FactoryException {
> matchedByXMIID.clear();
> final Iterator<EObject> leftIterator = left.getAllContents();
>
> while (leftIterator.hasNext()) {
> final EObject item1 = leftIterator.next();
> final String item1ID = left.getID(item1);
> if (item1ID != null) {
> final EObject item2 = right.getEObject(item1ID);
> if (item2 != null) {
> final StringBuilder item1Key = new StringBuilder();
> item1Key.append(NameSimilarity.findName(item1));
> item1Key.append(item1.hashCode());
> matchedByXMIID.put(item1Key.toString(), item2);
> }
> }
> }
> }
>
> /**
> * Iterates through both of the given {@link XMIResource resources}
> to find all the elements that can be
> * matched by their XMI ID, then populates {@link #matchedByID} with
> those mappings.
> * * @param left
> * First of the two {@link XMIResource resources} to visit.
> * @param right
> * Second of the {@link XMIResource resources} to visit.
> * @throws FactoryException
> * Thrown if we couldn't compute a key to store the
> items in cache.
> */
> private void matchByID(Resource left, Resource right) throws
> FactoryException {
> matchedByID.clear();
> final Iterator<EObject> leftIterator = left.getAllContents();
> while (leftIterator.hasNext()) {
> final EObject item1 = leftIterator.next();
> final String item1ID = EcoreUtil.getID(item1);
> if (item1ID != null) {
> final Iterator<EObject> rightIterator =
> right.getAllContents();
> while (rightIterator.hasNext()) {
> final EObject item2 = rightIterator.next();
> final String item2ID = EcoreUtil.getID(item2);
> if (item2 != null && item1ID.equals(item2ID)) {
> final StringBuilder item1Key = new StringBuilder();
> item1Key.append(NameSimilarity.findName(item1));
> item1Key.append(item1.hashCode());
> matchedByID.put(item1Key.toString(), item2);
> break;
> }
> }
> }
> }
> }
>
> /**
> * Returns a list containing mappings of the nodes of both given
> {@link List}s.
> * * @param list1
> * First of the lists from which we need to map the elements
> * @param list2
> * Second list to map the elements from.
> * @param window
> * Number of siblings to consider for the matching.
> * @param monitor
> * {@link CompareProgressMonitor Progress monitor} to
> display while the comparison lasts. Might
> * be <code>null</code>, in which case we won't monitor
> progress.
> * @return A {@link List} containing mappings of the nodes of both
> given {@link List}s.
> * @throws FactoryException
> * Thrown if the metrics cannot be computed.
> * @throws InterruptedException
> * Thrown if the matching process is interrupted somehow.
> */
> private List<Match2Elements> mapLists(List<EObject> list1,
> List<EObject> list2, int window,
> CompareProgressMonitor monitor) throws FactoryException,
> InterruptedException {
> final List<Match2Elements> result = new
> ArrayList<Match2Elements>();
> int curIndex = 0 - window / 2;
> final List<EObject> notFoundList1 = new ArrayList<EObject>(list1);
> final List<EObject> notFoundList2 = new ArrayList<EObject>(list2);
>
> final Iterator<EObject> it1 = list1.iterator();
> // then iterate over the 2 lists and compare the elements
> while (it1.hasNext() && notFoundList2.size() > 0) {
> final EObject obj1 = it1.next();
>
> final StringBuilder obj1Key = new StringBuilder();
> obj1Key.append(NameSimilarity.findName(obj1));
> obj1Key.append(obj1.hashCode());
> EObject obj2 = matchedByID.get(obj1Key.toString());
>
> if (obj2 == null) {
> // subtracts the difference between the notfound and the
> // original list to avoid ArrayOutOfBounds
> final int end = Math.min(curIndex + window -
> (list2.size() - notFoundList2.size()),
> notFoundList2.size());
> final int index = Math
> .min(Math.max(curIndex - (list2.size() -
> notFoundList2.size()), 0), end);
>
> obj2 = findMostSimilar(obj1,
> notFoundList2.subList(index, end));
> if (obj2 != null) {
> // checks if the most similar to obj2 is obj1
> final EObject obj1Check = findMostSimilar(obj2,
> notFoundList1);
> if (obj1Check != obj1 && obj1Check != null &&
> isSimilar(obj1Check, obj2)) {
> continue;
> }
> }
> }
>
> if (notFoundList1.contains(obj1) &&
> notFoundList2.contains(obj2) && isSimilar(obj1, obj2)) {
> final Match2Elements mapping =
> MatchFactory.eINSTANCE.createMatch2Elements();
> final double metric = absoluteMetric(obj1, obj2);
>
> mapping.setLeftElement(obj1);
> mapping.setRightElement(obj2);
> mapping.setSimilarity(metric);
> result.add(mapping);
> notFoundList2.remove(obj2);
> notFoundList1.remove(obj1);
> }
> curIndex += 1;
> monitor.worked(1);
> if (monitor.isCanceled())
> throw new InterruptedException();
> }
>
> // now putting the not found elements aside for later
> stillToFindFromModel2.addAll(notFoundList2);
> stillToFindFromModel1.addAll(notFoundList1);
> return result;
> }
>
> /**
> * Returns an absolute comparison metric between the two given
> {@link EObject}s.
> * * @param obj1
> * The first {@link EObject} to compare.
> * @param obj2
> * Second of the {@link EObject}s to compare.
> * @return An absolute comparison metric. 0 < value < 1.
> * @throws FactoryException
> * Thrown if we cannot compute the content similarity.
> */
> private double absoluteMetric(EObject obj1, EObject obj2) throws
> FactoryException {
> final double nameSimilarity = nameSimilarity(obj1, obj2);
> final double relationsSimilarity = relationsSimilarity(obj1, obj2);
> double sameUri = 0d;
> if (hasSameUri(obj1, obj2))
> sameUri = 1;
> final double positionSimilarity = relationsSimilarity / 2d +
> sameUri / 2d;
>
> final double contentWeight = 0.5d;
>
> if (nonNullFeaturesCount(obj1) > MIN_ATTRIBUTES_COUNT
> && nonNullFeaturesCount(obj2) > MIN_ATTRIBUTES_COUNT) {
> final double nameWeight = 0.4d;
> final double positionWeight = 0.4d;
> final double contentSimilarity = contentSimilarity(obj1, obj2);
> // Computing type similarity really is time expensive
> // double typeSimilarity = typeSimilarity(obj1, obj2);
> return (contentSimilarity * contentWeight + nameSimilarity *
> nameWeight + positionSimilarity
> * positionWeight)
> / (contentWeight + nameWeight + positionWeight);
> }
> // we didn't have enough features to compute an accurate metric
> final double nameWeight = 0.8d;
> final double positionWeight = 0.2d;
> return (nameSimilarity * nameWeight + positionSimilarity *
> positionWeight)
> / (nameWeight + positionWeight);
> }
>
> /**
> * This will compute the similarity between two {@link EObject}s'
> relations.
> * * @param obj1
> * First of the two {@link EObject}s.
> * @param obj2
> * Second of the two {@link EObject}s.
> * @return <code>double</code> representing the similarity between
> the two {@link EObject}s' relations.
> * 0 < value < 1.
> * @throws FactoryException
> * Thrown if we cannot compute the relations' similarity
> metrics.
> * @see StructureSimilarity#relationsSimilarityMetric(EObject,
> EObject, MetamodelFilter)
> */
> private double relationsSimilarity(EObject obj1, EObject obj2)
> throws FactoryException {
> double similarity = 0d;
> final Double value = getSimilarityFromCache(obj1, obj2,
> RELATION_SIMILARITY);
> if (value != null) {
> similarity = value;
> } else {
> similarity =
> StructureSimilarity.relationsSimilarityMetric(obj1, obj2, filter);
> setSimilarityInCache(obj1, obj2, RELATION_SIMILARITY,
> similarity);
> }
> return similarity;
> }
>
> /**
> * Checks wether the two given {@link EObject} have the same URI.
> * * @param obj1
> * First of the two {@link EObject} we're comparing.
> * @param obj2
> * Second {@link EObject} we're comparing.
> * @return <code>True</code> if the {@link EObject}s have the same
> URI, <code>False</code> otherwise.
> */
> private boolean hasSameUri(EObject obj1, EObject obj2) {
> if (obj1.eResource() != null && obj2.eResource() != null)
> return
> obj1.eResource().getURIFragment(obj1).equals(obj2.eResource(
> ).getURIFragment(obj2));
> return false;
> }
>
> /**
> * Counts all the {@link EStructuralFeature features} of the given
> {@link EObject} that are
> * <code>null</code> or initialized to the empty {@link String} "".
> * * @param eobj
> * {@link EObject} we need to count the empty features of.
> * @return The number of features initialized to <code>null</code>
> or the empty String.
> */
> private int nonNullFeaturesCount(EObject eobj) {
> // TODO should probably cache result here
> int nonNullFeatures = 0;
> final Iterator<EStructuralFeature> features =
> eobj.eClass().getEAllStructuralFeatures().iterator();
> while (features.hasNext()) {
> final EStructuralFeature feature = features.next();
> if (eobj.eGet(feature) != null &&
> !"".equals(eobj.eGet(feature).toString())) //$NON-NLS-1$
> nonNullFeatures++;
> }
> return nonNullFeatures;
> }
> /**
> * We consider here <code>current1</code> and <code>current2</code>
> are similar. This method creates
> * the mapping for the objects <code>current1</code> and
> <code>current2</code>, Then submappings for
> * these two elements' contents.
> * * @param current1
> * First element of the two elements mapping.
> * @param current2
> * Second of the two elements mapping.
> * @param monitor
> * {@link CompareProgressMonitor Progress monitor} to
> display while the comparison lasts. Might
> * be <code>null</code>, in which case we won't monitor
> progress.
> * @return The mapping for <code>current1</code> and
> <code>current2</code> and their content.
> * @throws FactoryException
> * Thrown when the metrics cannot be computed for
> <code>current1</code> and
> * <code>current2</code>.
> * @throws InterruptedException
> * Thrown if the matching process is interrupted somehow.
> */
> private Match2Elements recursiveMappings(EObject current1, EObject
> current2,
> CompareProgressMonitor monitor) throws FactoryException,
> InterruptedException {
> Match2Elements mapping = null;
> mapping = MatchFactory.eINSTANCE.createMatch2Elements();
> mapping.setLeftElement(current1);
> mapping.setRightElement(current2);
> mapping.setSimilarity(absoluteMetric(current1, current2));
> final List<Match2Elements> mapList =
> mapLists(getContents(current1), getContents(current2), this
> .<Integer> getOption(MatchOptions.OPTION_SEARCH_WINDOW),
> monitor);
> // We can map other elements with mapLists; we iterate through
> them.
> final Iterator<Match2Elements> it = mapList.iterator();
> while (it.hasNext()) {
> final Match2Elements subMapping = it.next();
> // As we know source and target are similars, we call recursive
> // mappings onto these objects
> EFactory.eAdd(mapping, SUBMATCH_ELEMENT_NAME,
> recursiveMappings(subMapping.getLeftElement(),
> subMapping.getRightElement(), monitor));
> }
> return mapping;
> }
>
> /**
> * Workaround for bug #235606 : elements held by a reference with
> containment=true and derived=true are
> * not matched since not returned by {@link EObject#eContents()}.
> This allows us to return the list of all
> * contents from an EObject <u>including</u> those references.
> * * @param eObject
> * The EObject we seek the content of.
> * @return The list of all the content of a given EObject, derived
> containmnent references included.
> */
> @SuppressWarnings("unchecked")
> private List<EObject> getContents(EObject eObject) {
> // TODO can this be cached (Map<EClass, List<EReference>>)?
> final List<EObject> result = new ArrayList(eObject.eContents());
> for (EReference reference : eObject.eClass().getEAllReferences()) {
> if (reference.isContainment() && reference.isDerived()) {
> final Object value = eObject.eGet(reference);
> if (value instanceof Collection)
> result.addAll((Collection)value);
> else if (value instanceof EObject)
> result.add((EObject)value);
> }
> }
> return result;
> }
>
> /**
> * Creates the {@link Match2Elements submatch elements}
> corresponding to the mapping of objects from the
> * two given {@link List}s.
> * * @param root
> * Root of the {@link MatchModel} where to insert all
> these mappings.
> * @param list1
> * First of the lists used to compute mapping.
> * @param list2
> * Second of the lists used to compute mapping.
> * @param monitor
> * {@link CompareProgressMonitor progress monitor} to
> display while the comparison lasts. Might
> * be <code>null</code>, in which case we won't monitor
> progress.
> * @throws FactoryException
> * Thrown if we cannot match the elements of the two
> lists or add submatch elements to
> * <code>root</code>.
> * @throws InterruptedException
> * Thrown if the operation is cancelled or fails somehow.
> */
> private void createSubMatchElements(EObject root, List<EObject>
> list1, List<EObject> list2,
> CompareProgressMonitor monitor) throws FactoryException,
> InterruptedException {
> stillToFindFromModel1.clear();
> stillToFindFromModel2.clear();
> final List<Match2Elements> mappings = mapLists(list1, list2, this
> .<Integer> getOption(MatchOptions.OPTION_SEARCH_WINDOW),
> monitor);
>
> final Iterator<Match2Elements> it = mappings.iterator();
> while (it.hasNext()) {
> final Match2Elements map = it.next();
> final Match2Elements match =
> recursiveMappings(map.getLeftElement(), map.getRightElement(),
> monitor);
> redirectedAdd(root, SUBMATCH_ELEMENT_NAME, match);
> }
> }
>
> /**
> * Creates {@link UnMatchElement}s wrapped around all the elements
> of the given {@link List}.
> * * @param root
> * Root of the {@link MatchModel} under which to insert
> all these {@link UnMatchElement}s.
> * @param unMatchedElements
> * {@link Set} containing all the elements we haven't
> been able to match.
> * @throws FactoryException
> * Thrown if we cannot add elements under the given
> {@link MatchModel root}.
> */
> private void createUnMatchElements(MatchModel root, Set<EObject>
> unMatchedElements)
> throws FactoryException {
> for (EObject element : unMatchedElements) {
> final UnMatchElement unMap =
> MatchFactory.eINSTANCE.createUnMatchElement();
> unMap.setElement(element);
> redirectedAdd(root, UNMATCH_ELEMENT_NAME, unMap);
> }
> unMatchedElements.clear();
> }
>
> /**
> * This method is an indirection for adding Mappings in the current
> MappingGroup.
> * * @param object
> * {@link EObject} to add a feature value to.
> * @param name
> * Name of the feature to consider.
> * @param value
> * Value to add to the feature <code>name</code> of
> <code>object</code>.
> * @throws FactoryException
> * Thrown if the value's affectation fails.
> */
> private void redirectedAdd(EObject object, String name, Object
> value) throws FactoryException {
> EFactory.eAdd(object, name, value);
> }
>
> /**
> * Returns the given similarity between the two given {@link
> EObject}s as it is stored in cache.<br/>
> * <p>
> * <code>similarityKind</code> must be one of
> * <ul>
> * <li>{@link #NAME_SIMILARITY}</li>
> * <li>{@link #TYPE_SIMILARITY}</li>
> * <li>{@link #VALUE_SIMILARITY}</li>
> * <li>{@link #RELATION_SIMILARITY}</li>
> * </ul>
> * </p>
> * * @param obj1
> * First of the two {@link EObject}s we seek the
> similarity for.
> * @param obj2
> * Second of the two {@link EObject}s we seek the
> similarity for.
> * @param similarityKind
> * Kind of similarity to get.
> * @return The similarity as described by
> <code>similarityKind</code> as it is stored in cache for the
> * two given {@link EObject}s.
> */
> private Double getSimilarityFromCache(EObject obj1, EObject obj2,
> char similarityKind) {
> return metricsCache.get(pairHashCode(obj1, obj2, similarityKind));
> }
>
> /**
> * Computes an unique key between to {@link EObject}s to store their
> similarity in cache.
> * <p>
> * <code>similarityKind</code> must be one of
> * <ul>
> * <li>{@link #NAME_SIMILARITY}</li>
> * <li>{@link #TYPE_SIMILARITY}</li>
> * <li>{@link #VALUE_SIMILARITY}</li>
> * <li>{@link #RELATION_SIMILARITY}</li>
> * </ul>
> * </p>
> * * @param obj1
> * First of the two {@link EObject}s.
> * @param obj2
> * Second of the two {@link EObject}s.
> * @param similarityKind
> * Kind of similarity this key will represent in cache.
> * @return Unique key for the similarity cache.
> */
> private String pairHashCode(EObject obj1, EObject obj2, char
> similarityKind) {
> if (similarityKind == NAME_SIMILARITY || similarityKind ==
> TYPE_SIMILARITY
> || similarityKind == VALUE_SIMILARITY || similarityKind
> == RELATION_SIMILARITY) {
> final StringBuilder hash = new StringBuilder();
>
> hash.append(similarityKind).append(obj1.hashCode()).append(o
> bj2.hashCode());
> return hash.toString();
> }
> throw new
> IllegalArgumentException(EMFCompareMatchMessages.getString(
> "DifferencesServices.illegalSimilarityKind",
> similarityKind)); //$NON-NLS-1$
> }
>
> /**
> * Stores in cache the given similarity between the two given {@link
> EObject}s.<br/>
> * <p>
> * <code>similarityKind</code> must be one of
> * <ul>
> * <li>{@link #NAME_SIMILARITY}</li>
> * <li>{@link #TYPE_SIMILARITY}</li>
> * <li>{@link #VALUE_SIMILARITY}</li>
> * <li>{@link #RELATION_SIMILARITY}</li>
> * </ul>
> * </p>
> * * @param obj1
> * First of the two {@link EObject}s we're setting the
> similarity for.
> * @param obj2
> * Second of the two {@link EObject}s we're setting the
> similarity for.
> * @param similarityKind
> * Kind of similarity to set.
> * @param similarity
> * Value of the similarity between the two {@link EObject}s.
> */
> private void setSimilarityInCache(EObject obj1, EObject obj2, char
> similarityKind, double similarity) {
> metricsCache.put(pairHashCode(obj1, obj2, similarityKind), new
> Double(similarity));
> }
>
>
> }
>
> ////////////////////////////////////////////////////////////
> ////////////////////////////////////////////
> and the content of my console (when i used the GenericMatchEngine and
> GenericDiffEngine):
>
> ////////////////////////////////////////////////////////////
> ////////////////////////////////////////////
> *** Loading resources ***
> C:\Documents and
> Settings\yatimih\runtime-New_configuration\MyAlgorithm1\diag ram\Copy of
> old-default.impala_diagram : rootCompositeBox1
> C:\Documents and
> Settings\yatimih\runtime-New_configuration\MyAlgorithm1\diag
> ram\old-default.impala_diagram : rootCompositeBox2
> *** matched Elements ***
> Matched Elements(size) = 1
>
> MatchElem :
> mailto: org.eclipse.emf.compare.match.metamodel.impl.Match2ElementsI mpl @1eb0d79
> (similarity: 0.9580419580419581) has similarity : 0.9580419580419581
>
> the left element is :
> mailto: com.st.hed.iqi.impala.srcgen.model.impl.RootCompositeBoxImpl @120d1c0
> (name: MyAlgorithm1, version: 1.0.0, description: Description is not
> filled, isReadOnly: false, isChangedFromLib: false)
>
> the right element is :
> mailto: com.st.hed.iqi.impala.srcgen.model.impl.RootCompositeBoxImpl @f82888
> (name: MyAlgorithm1, version: 1.0.0, description: Description is not
> filled, isReadOnly: false, isChangedFromLib: false)
>
> this is a list of the content objects of the left element :
> *
> mailto: com.st.hed.iqi.impala.srcgen.model.impl.NCodeGenPropertyImpl @1a9ab54
> (language: iqi-c, name: GEN_UNIQUE_NAME, value: )
>
> this is a list of the content objects of the left element :
> *
> mailto: com.st.hed.iqi.impala.srcgen.model.impl.NCodeGenPropertyImpl @1f7e4cf
> (language: iqi-c, name: GENERATION_DATE, value: )
>
> this is a list of the content objects of the left element :
> *
> mailto: com.st.hed.iqi.impala.srcgen.model.impl.NCodeGenPropertyImpl @1cee582
> (language: iqi-c, name: USER, value: )
>
> this is a list of the content objects of the left element :
> *
> mailto: com.st.hed.iqi.impala.srcgen.model.impl.NCodeGenPropertyImpl @3dd567
> (language: iqi-c, name: GENERATOR_VERSION, value: )
>
> this is a list of the content objects of the left element :
> *
> mailto: com.st.hed.iqi.impala.srcgen.model.impl.NCodeGenPropertyImpl @1856ec1
> (language: iqi-c, name: TYPE_QUALIFIED_NAME, value: )
>
> this is a list of the content objects of the left element :
> *
> mailto: com.st.hed.impala.src.model.impl.ImpalaInputParameterBoxImpl @ec28c0
> (name: Sequence_input, version: 1.0.0, description: Description is not
> filled, isReadOnly: false, isChangedFromLib: false) (debugMode: NoDebug,
> debugTextFormat: null, debugHeader: null, debugTrailer: null,
> debugDumpDestination: null)
>
> this is a list of the content objects of the left element :
> *
> mailto:com.st.hed.iqi.impala.srcgen.model.impl.CompositeBoxImpl@1c200d0
> (name: CB, version: 1.0.0, description: Description is not filled,
> isReadOnly: false, isChangedFromLib: false)
>
> this is a list of the content objects of the left element :
> *
> mailto:com.st.hed.impala.src.model.impl.ImpalaFrameGathererImpl@5db277
> (increment: 1, channel: Y, offsetInSequence: 0) (name: FG, version:
> 1.0.0, description: Description is not filled, isReadOnly: false,
> isChangedFromLib: false, debugMode: NoDebug, debugTextFormat: null,
> debugHeader: null, debugTrailer: null, debugDumpDestination: null,
> newRootDirectory: null, newRadix: null)
>
> this is a list of the content objects of the left element :
> *
> mailto:com.st.hed.impala.src.model.impl.ImpalaFrameSelectorImpl@6cd712
> (increment: 1, channel: Y, offsetInSequence: 0) (name: FS, version:
> 1.0.0, description: Description is not filled, isReadOnly: false,
> isChangedFromLib: false, debugMode: NoDebug, debugTextFormat: null,
> debugHeader: null, debugTrailer: null, debugDumpDestination: null)
>
> this is a list of the content objects of the left element :
> *
> mailto:com.st.hed.iqi.impala.srcgen.model.impl.NSequenceImpl@f61e2
> (name: input, version: 1.0.0, description: Description is not filled,
> isReadOnly: false, isChangedFromLib: false) (width: 1, height: 1,
> sampling: YUV444, startFrameNb: 0, NbOfFrames: 1, SequenceRoot: ,
> SequenceRadix: , storageType: SGP, isProgressive: true, isTopFirst:
> true, dynamic: 8)
>
>
>
> this is a list of the content objects of the right element :
> *
> mailto: com.st.hed.iqi.impala.srcgen.model.impl.NCodeGenPropertyImpl @2d1d1e
> (language: iqi-c, name: GEN_UNIQUE_NAME, value: )
>
> this is a list of the content objects of the right element :
> *
> mailto: com.st.hed.iqi.impala.srcgen.model.impl.NCodeGenPropertyImpl @1d2c4aa
> (language: iqi-c, name: GENERATION_DATE, value: )
>
> this is a list of the content objects of the right element :
> *
> mailto: com.st.hed.iqi.impala.srcgen.model.impl.NCodeGenPropertyImpl @6db04e
> (language: iqi-c, name: USER, value: )
>
> this is a list of the content objects of the right element :
> *
> mailto: com.st.hed.iqi.impala.srcgen.model.impl.NCodeGenPropertyImpl @151da55
> (language: iqi-c, name: GENERATOR_VERSION, value: )
>
> this is a list of the content objects of the right element :
> *
> mailto: com.st.hed.impala.src.model.impl.ImpalaInputParameterBoxImpl @d53356
> (name: Sequence_input, version: 1.0.0, description: Description is not
> filled, isReadOnly: false, isChangedFromLib: false) (debugMode: NoDebug,
> debugTextFormat: null, debugHeader: null, debugTrailer: null,
> debugDumpDestination: null)
>
> this is a list of the content objects of the right element :
> *
> mailto:com.st.hed.iqi.impala.srcgen.model.impl.CompositeBoxImpl@877294
> (name: CB, version: 1.0.0, description: Description is not filled,
> isReadOnly: false, isChangedFromLib: false)
>
> this is a list of the content objects of the right element :
> *
> mailto:com.st.hed.impala.src.model.impl.ImpalaFrameGathererImpl@1fa522d
> (increment: 1, channel: Y, offsetInSequence: 0) (name: FG, version:
> 1.0.0, description: Description is not filled, isReadOnly: false,
> isChangedFromLib: false, debugMode: NoDebug, debugTextFormat: null,
> debugHeader: null, debugTrailer: null, debugDumpDestination: null,
> newRootDirectory: null, newRadix: null)
>
> this is a list of the content objects of the right element :
> *
> mailto:com.st.hed.impala.src.model.impl.ImpalaFrameGathererImpl@129271e
> (increment: 1, channel: Y, offsetInSequence: 0) (name: FG1, version:
> 1.0.0, description: Description is not filled, isReadOnly: false,
> isChangedFromLib: false, debugMode: NoDebug, debugTextFormat: null,
> debugHeader: null, debugTrailer: null, debugDumpDestination: null,
> newRootDirectory: null, newRadix: null)
>
> this is a list of the content objects of the right element :
> *
> mailto:com.st.hed.impala.src.model.impl.ImpalaFrameSelectorImpl@c73ac2
> (increment: 1, channel: Y, offsetInSequence: 0) (name: FS, version:
> 1.0.0, description: Description is not filled, isReadOnly: false,
> isChangedFromLib: false, debugMode: NoDebug, debugTextFormat: null,
> debugHeader: null, debugTrailer: null, debugDumpDestination: null)
>
> this is a list of the content objects of the right element :
> *
> mailto:com.st.hed.iqi.impala.srcgen.model.impl.NSequenceImpl@1e2b2a6
> (name: input, version: 1.0.0, description: Description is not filled,
> isReadOnly: false, isChangedFromLib: false) (width: 1, height: 1,
> sampling: YUV444, startFrameNb: 0, NbOfFrames: 1, SequenceRoot: ,
> SequenceRadix: , storageType: SGP, isProgressive: true, isTopFirst:
> true, dynamic: 8)
>
> this is a list of the content objects of the right element :
> *
> mailto:com.st.hed.iqi.impala.srcgen.model.impl.CompositeBoxImpl@6d2d52
> (name: lib, version: 1.0.0, description: This is the container for the
> library types, isReadOnly: false, isChangedFromLib: false)
>
> Unmatched Elements(size) = 8
>
> UnMatchElem is :
> mailto: org.eclipse.emf.compare.match.metamodel.impl.UnMatchElementI mpl @c183ea
>
>
> * mailto:org.eclipse.gmf.runtime.notation.impl.DiagramImpl@1ea08e7
> (visible: true, type: impala-metamodel, mutable: false) (name: ,
> measurementUnit: Pixel)
> UnMatchElem is :
> mailto: org.eclipse.emf.compare.match.metamodel.impl.UnMatchElementI mpl @bbb074
>
>
> *
> mailto: com.st.hed.iqi.impala.srcgen.model.impl.NCodeGenPropertyImpl @1c3599d
> (language: iqi-c, name: GEN_UNIQUE_NAME, value: )
> UnMatchElem is :
> mail
Re: EMF Compare __urgent [message #622916 is a reply to message #532790] Thu, 20 May 2010 09:41 Go to previous message
Hanane is currently offline HananeFriend
Messages: 6
Registered: May 2010
Junior Member
Hi Laurent,
Thank you for your reply.
I already add : MatchOptions.IGNORE_XMI_ID and
MatchOptions.IGNORE_FUNCTIONAL_ID to my code;

In fact,until now i can see the differences (of type DiffElement , DiffGroup) in console,But i still have a problem to see a MatchElement and UnMatchElement

i started by create a Button in menubar 1 (CompareAction.java)
and the principale code 2 (compareDiagram.java)

the code is:
code1 :
package com.st.hed.iqi.impala.emfcompareimpala;

import java.io.IOException;

import org.eclipse.core.resources.IFile;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;

import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.IWorkbenchWindowActionDelegate;

public class CompareAction implements IWorkbenchWindowActionDelegate {

Object firstElement = null;
Object secondElement = null;
/**
* The constructor.
*/
public CompareAction() {
super();
}
public void selectionChanged(IAction action, ISelection selection) {
String fileExtension = "impala_diagram";

action.setEnabled(false);

if (selection instanceof IStructuredSelection) {

IStructuredSelection structuredSelection = (IStructuredSelection) selection;
firstElement = structuredSelection.getFirstElement();

if (structuredSelection.size() == 2){
secondElement = structuredSelection.toArray()[1];

action.setEnabled((structuredSelection.size() == 2)
&& (firstElement.toString().endsWith(fileExtension))
&& (secondElement.toString().endsWith(fileExtension))
);
}

}
}

public void run(IAction action) {

IFile file1 = null;
IFile file2 = null;

if (firstElement instanceof IFile){
file1 = (IFile) firstElement;
file2 = (IFile) secondElement;
}
CompareDiagram compareDiagram = new CompareDiagram();
try {
compareDiagram.getDiff(file1, file2);
} catch (Exception e){
e.printStackTrace();
}

}
public void dispose() {
}
public void init(IWorkbenchWindow window) {
}
}
code2 :
package com.st.hed.iqi.impala.emfcompareimpala;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import org.eclipse.emf.common.util.EList;

import org.eclipse.emf.compare.diff.metamodel.DiffElement;
import org.eclipse.emf.compare.diff.metamodel.DiffGroup;
import org.eclipse.emf.compare.diff.metamodel.DiffModel;
import org.eclipse.emf.compare.diff.metamodel.DiffPackage;
import org.eclipse.emf.compare.diff.service.DiffService;

import org.eclipse.emf.compare.match.api.MatchOptions;
import org.eclipse.emf.compare.match.metamodel.Match2Elements;
import org.eclipse.emf.compare.match.metamodel.MatchElement;
import org.eclipse.emf.compare.match.metamodel.MatchModel;
import org.eclipse.emf.compare.match.metamodel.MatchPackage;
import org.eclipse.emf.compare.match.metamodel.UnMatchElement;
import org.eclipse.emf.compare.match.service.MatchService;
import org.eclipse.emf.compare.match.*;

import org.eclipse.emf.compare.util.ModelUtils;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.IPath;

import com.st.hed.iqi.impala.srcgen.model.RootCompositeBox;

public class CompareDiagram {
private static final double SIMILARITY = 1.0;
CompareDiagram() {
// prevents instantiation
}

public void getDiff(IFile iFile1, IFile iFile2) throws Exception {
IPath location1 = iFile1.getLocation();
IPath location2 = iFile2.getLocation();

File file1 = location1.toFile();
File file2 = location2.toFile();

if (file1.canRead() && file2.canRead()) {

EPackage.Registry.INSTANCE.put(DiffPackage.eNS_URI, DiffPackage.eINSTANCE);
EPackage.Registry.INSTANCE.put(MatchPackage.eNS_URI, MatchPackage.eINSTANCE);

// Creates the resourceSet where we'll load the models
final ResourceSet resourceSet = new ResourceSetImpl();

try {
System.out.println(" *** Loading resources *** \n");

// Loads the two models from the tabModel
final EObject model1 = ModelUtils.load(file1, resourceSet);
final EObject model2 = ModelUtils.load(file2, resourceSet);

RootCompositeBox rootCompositeBox1 = (RootCompositeBox) model1;
RootCompositeBox rootCompositeBox2 = (RootCompositeBox) model2;

System.out.println(file1 + " : rootCompositeBox1 \n");
System.out.println(file2 + " : rootCompositeBox2 \n");

// get the Match model which we can browse like any other EMF

Map<String, Object> options = new HashMap<String, Object>();

options.put(MatchOptions.OPTION_IGNORE_XMI_ID, true);
options.put(MatchOptions.OPTION_IGNORE_ID, true);

// Select the differences to ignore
final Set<EObject> diffToIgnore = new HashSet<EObject>();

// build the list of differences to look
final Set<EObject> diffLookup = new HashSet<EObject>();

// Select the matched Element to ignore
final Set<EObject> matchedElemToIgnore = new HashSet<EObject>();

// build the list of matched Element to look
final Set<EObject> matchedElemLookup = new HashSet<EObject>();

// Select the unmatched Element to ignore
final Set<EObject> unmatchedElemToIgnore = new HashSet<EObject>();

// build the list of unmatched Element to look
final Set<EObject> unmatchedElemLookup = new HashSet<EObject>();


final MatchModel matchModel = MatchService.doMatch(rootCompositeBox1, rootCompositeBox2, options);

System.out.println(" *** matched Elements *** \n");
EList<MatchElement> matchedElements = matchModel.getMatchedElements();
System.out.println("Matched Elements(size) = " + matchedElements.size() + "\n");
for (int iMatch = 0; iMatch < matchedElements.size(); iMatch++) {
MatchElement matchElement = matchedElements.get(iMatch);
System.out.println("MatchElem[" + iMatch + "] : " + matchElement.toString() + " has similarity : " + matchElement.getSimilarity() + "\n");
//final List<EObject> list = matchElement.eContents();
//final EObject eObject = list.get(0);
//Iteratot<EObject> iterator = ;

if (matchElement.getSimilarity() != SIMILARITY) {
final Match2Elements elements = (Match2Elements) matchElement;
getMatchedElement(elements, matchedElemLookup);
}
/**
EList<MatchElement> subMatchedElements = matchElement.getSubMatchElements();
System.out.println("Sub-Matched Elements(size) = " + subMatchedElements.size() + "\n");
for (int isubMatch = 0; isubMatch < subMatchedElements.size(); isubMatch++){
MatchElement submatchElem = subMatchedElements.get(isubMatch);
System.out.println("SubmatchElem[" + isubMatch + "] : " + submatchElem.toString() + " has similarity : " + submatchElem.getSimilarity() + "\n");

if (submatchElem.getSimilarity() != SIMILARITY) {
final Match2Elements subElements = (Match2Elements) submatchElem;
getMatchedElement(subElements, matchedElemLookup);
}
}
*/
}

System.out.println(" *** unmatched Elements *** \n");
EList<UnMatchElement> unmatchElements = matchModel.getUnMatchedElements();
System.out.println("Unmatched Elements(size)= " + unmatchElements.size() + "\n");
for (int iUnMatch = 0; iUnMatch < unmatchElements.size(); iUnMatch++) {
UnMatchElement unMatchElement = unmatchElements.get(iUnMatch);
EObject eObject = unMatchElement.getElement();
System.out.println(" UnMatchElem[" + iUnMatch + "] is : " + eObject);
if (eObject != null){
getUnMatchedElement(eObject, unmatchedElemLookup);

}
}


System.out.println(" *** Differencing models *** \n");
DiffModel myDiff = DiffService.doDiff(matchModel, false);

EList<DiffElement> diffElements = myDiff.getOwnedElements();

if (diffElements.size() == 0) {
System.out.println("There is no difference between the two RootCompositeBox \n");
} else {
System.out.println("Diff Elements(size) = " + diffElements.size() + " \n ");

for (int iDiff = 0; iDiff < diffElements.size(); iDiff++) {
final DiffElement diffElem = diffElements.get(iDiff);
System.out.println("DiffElement[" + iDiff + "] is : " + diffElem.toString() + " \n ");
String kind = diffElem.getKind().getName();
System.out.println("KIND = " + kind + "\n");

if (diffElem instanceof DiffGroup){
final DiffGroup group = (DiffGroup) diffElem;
System.out.println(group + " \n ") ;
addDiffFromGroup(group, diffLookup);
}else {
diffLookup.add(diffElem);
System.out.println(diffLookup.add(diffElem) + " \n ");
}
}
}
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
private void getMatchedElement(Match2Elements elements, Set<EObject> matchedElemLookup){
EObject left = elements.getLeftElement();
EObject right = elements.getRightElement();

if (left instanceof MatchElement){
final MatchElement leftMatchElement = (MatchElement) left;
for (MatchElement subLeftMatchElement : leftMatchElement.getSubMatchElements()){

if (subLeftMatchElement.getSimilarity() != SIMILARITY){
final Match2Elements subLeftMatch2Element = (Match2Elements) subLeftMatchElement;
System.out.println(subLeftMatch2Element + " \n ");
getMatchedElement( subLeftMatch2Element, matchedElemLookup);
}
}
}else {
matchedElemLookup.add(left);
System.out.println(matchedElemLookup.add(left) + " \n ");
}

if (right instanceof MatchElement){
final MatchElement rightMatchElement = (MatchElement) right;
if (rightMatchElement.getSimilarity() != SIMILARITY){
final Match2Elements rightMatch2Element = (Match2Elements) rightMatchElement;
System.out.println(rightMatch2Element + " \n ");
getMatchedElement( rightMatch2Element, matchedElemLookup);

}
} else {
matchedElemLookup.add(right);
System.out.println(matchedElemLookup.add(right) + " \n ");
}
}

private void getUnMatchedElement(EObject eObject, Set<EObject> unmatchedElemLookup){

}

private void addDiffFromGroup(DiffGroup group, Set<EObject> diffLookup) {
EList<DiffElement> diffGroups = group.getSubDiffElements();
System.out.println(diffGroups + " \n ");
for (final DiffElement diffElem : diffGroups) {
if (diffElem instanceof DiffGroup) {
final DiffGroup subGroup = (DiffGroup) diffElem;
System.out.println(" * " + subGroup + " \n ");
addDiffFromGroup(subGroup, diffLookup);
} else {
diffLookup.add(diffElem);
System.out.println(diffLookup.add(diffElem) + " \n ");
}
}
}
}

Regards,
Hanane YATIMI
Re: EMF Compare __urgent [message #622920 is a reply to message #622916] Fri, 21 May 2010 08:26 Go to previous message
Laurent Goubet is currently offline Laurent GoubetFriend
Messages: 1902
Registered: July 2009
Senior Member
This is a multi-part message in MIME format.
--------------070802000706050605010802
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 7bit

Hanane,

First of all, please refrain from using "urgent" in your post subjects,
this will not get the post read faster, and it might in fact have the
opposite effect. We read the newsgroup questions when we can, and answer
at the same rate.

Other than that, if you don't explain your issue, we can in now way help
you : I can't create an Eclipse workspace, take you three classes, put
them into a project, build ecore/uml/... models to compare them through
this code, launch and try to understand what's failing and what's
accurate, then try and see if the code is erroneous or if it is my
models that don't correspond to yours ...

If there is something that doesn't work with your code, you might be
interested in searching for "floating point operation" in google ; for
example, "0.3 == 0.1 + 0.1 + 0.1" returns false. Your "getSimilarity()
== SIMILARITY" scare me as equality testing on doubles through == is
risky at best. If it the problem isn't that, then please explain what
you're trying to do, and how EMF Compare doesn't help or fails.

Laurent Goubet
Obeo

Hanane wrote:
> Hi Laurent,
> Thank you for your reply.
> I already add : MatchOptions.IGNORE_XMI_ID and
> MatchOptions.IGNORE_FUNCTIONAL_ID to my code;
>
> In fact,until now i can see the differences (of type DiffElement ,
> DiffGroup) in console,But i still have a problem to see a MatchElement
> and UnMatchElement
> i started by create a Button in menubar 1 (CompareAction.java) and the
> principale code 2 (compareDiagram.java)
>
> the code is:
> code1 :
> package com.st.hed.iqi.impala.emfcompareimpala;
>
> import java.io.IOException;
>
> import org.eclipse.core.resources.IFile;
> import org.eclipse.jface.action.IAction;
> import org.eclipse.jface.viewers.ISelection;
> import org.eclipse.jface.viewers.IStructuredSelection;
>
> import org.eclipse.ui.IWorkbenchWindow;
> import org.eclipse.ui.IWorkbenchWindowActionDelegate;
>
> public class CompareAction implements IWorkbenchWindowActionDelegate {
>
> Object firstElement = null;
> Object secondElement = null;
> /**
> * The constructor.
> */
> public CompareAction() {
> super();
> }
> public void selectionChanged(IAction action, ISelection selection) {
> String fileExtension = "impala_diagram";
>
> action.setEnabled(false);
> if (selection instanceof IStructuredSelection) {
>
> IStructuredSelection structuredSelection =
> (IStructuredSelection) selection;
> firstElement =
> structuredSelection.getFirstElement();
>
> if (structuredSelection.size() == 2){
> secondElement = structuredSelection.toArray()[1];
>
> action.setEnabled((structuredSelection.size() == 2)
> &&
> (firstElement.toString().endsWith(fileExtension))
> &&
> (secondElement.toString().endsWith(fileExtension))
> );
> }
>
> }
> }
>
> public void run(IAction action) {
>
> IFile file1 = null;
> IFile file2 = null;
> if (firstElement instanceof IFile){
> file1 = (IFile) firstElement;
> file2 = (IFile) secondElement;
> }
> CompareDiagram compareDiagram = new CompareDiagram();
> try {
> compareDiagram.getDiff(file1, file2);
> } catch (Exception e){
> e.printStackTrace();
> }
>
> }
> public void dispose() {
> }
> public void init(IWorkbenchWindow window) {
> }
> }
> code2 :
> package com.st.hed.iqi.impala.emfcompareimpala;
>
> import java.io.File;
> import java.io.IOException;
> import java.util.HashMap;
> import java.util.HashSet;
> import java.util.Map;
> import java.util.Set;
>
> import org.eclipse.emf.common.util.EList;
>
> import org.eclipse.emf.compare.diff.metamodel.DiffElement;
> import org.eclipse.emf.compare.diff.metamodel.DiffGroup;
> import org.eclipse.emf.compare.diff.metamodel.DiffModel;
> import org.eclipse.emf.compare.diff.metamodel.DiffPackage;
> import org.eclipse.emf.compare.diff.service.DiffService;
>
> import org.eclipse.emf.compare.match.api.MatchOptions;
> import org.eclipse.emf.compare.match.metamodel.Match2Elements;
> import org.eclipse.emf.compare.match.metamodel.MatchElement;
> import org.eclipse.emf.compare.match.metamodel.MatchModel;
> import org.eclipse.emf.compare.match.metamodel.MatchPackage;
> import org.eclipse.emf.compare.match.metamodel.UnMatchElement;
> import org.eclipse.emf.compare.match.service.MatchService;
> import org.eclipse.emf.compare.match.*;
>
> import org.eclipse.emf.compare.util.ModelUtils;
> import org.eclipse.emf.ecore.EObject;
> import org.eclipse.emf.ecore.EPackage;
> import org.eclipse.emf.ecore.resource.ResourceSet;
> import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
>
> import org.eclipse.core.resources.IFile;
> import org.eclipse.core.runtime.IPath;
>
> import com.st.hed.iqi.impala.srcgen.model.RootCompositeBox;
>
> public class CompareDiagram {
> private static final double SIMILARITY = 1.0;
> CompareDiagram() {
> // prevents instantiation
> }
>
> public void getDiff(IFile iFile1, IFile iFile2) throws Exception {
> IPath location1 = iFile1.getLocation();
> IPath location2 = iFile2.getLocation();
>
> File file1 = location1.toFile();
> File file2 = location2.toFile();
>
> if (file1.canRead() && file2.canRead()) {
>
> EPackage.Registry.INSTANCE.put(DiffPackage.eNS_URI,
> DiffPackage.eINSTANCE);
> EPackage.Registry.INSTANCE.put(MatchPackage.eNS_URI,
> MatchPackage.eINSTANCE);
>
> // Creates the resourceSet where we'll load the models
> final ResourceSet resourceSet = new ResourceSetImpl();
>
> try {
> System.out.println(" *** Loading resources *** \n");
>
> // Loads the two models from the tabModel
> final EObject model1 = ModelUtils.load(file1, resourceSet);
> final EObject model2 = ModelUtils.load(file2, resourceSet);
>
> RootCompositeBox rootCompositeBox1 = (RootCompositeBox)
> model1;
> RootCompositeBox rootCompositeBox2 = (RootCompositeBox)
> model2;
>
> System.out.println(file1 + " : rootCompositeBox1 \n");
> System.out.println(file2 + " : rootCompositeBox2 \n");
>
> // get the Match model which we can browse like any
> other EMF
>
> Map<String, Object> options = new HashMap<String,
> Object>();
>
> options.put(MatchOptions.OPTION_IGNORE_XMI_ID, true);
> options.put(MatchOptions.OPTION_IGNORE_ID, true);
>
> // Select the differences to ignore
> final Set<EObject> diffToIgnore = new HashSet<EObject>();
>
> // build the list of differences to look
> final Set<EObject> diffLookup = new HashSet<EObject>();
>
> // Select the matched Element to ignore
> final Set<EObject> matchedElemToIgnore = new
> HashSet<EObject>();
>
> // build the list of matched Element to look
> final Set<EObject> matchedElemLookup = new
> HashSet<EObject>();
>
> // Select the unmatched Element to ignore
> final Set<EObject> unmatchedElemToIgnore = new
> HashSet<EObject>();
>
> // build the list of unmatched Element to look
> final Set<EObject> unmatchedElemLookup = new
> HashSet<EObject>();
>
>
> final MatchModel matchModel =
> MatchService.doMatch(rootCompositeBox1, rootCompositeBox2, options);
>
> System.out.println(" *** matched Elements *** \n");
> EList<MatchElement> matchedElements =
> matchModel.getMatchedElements();
> System.out.println("Matched Elements(size) = " +
> matchedElements.size() + "\n");
> for (int iMatch = 0; iMatch < matchedElements.size();
> iMatch++) {
> MatchElement matchElement =
> matchedElements.get(iMatch);
> System.out.println("MatchElem[" + iMatch + "] : " +
> matchElement.toString() + " has similarity : " +
> matchElement.getSimilarity() + "\n");
> //final List<EObject> list = matchElement.eContents();
> //final EObject eObject = list.get(0);
> //Iteratot<EObject> iterator = ;
>
> if (matchElement.getSimilarity() != SIMILARITY) {
> final Match2Elements elements = (Match2Elements)
> matchElement;
> getMatchedElement(elements, matchedElemLookup);
> }
> /**
> EList<MatchElement> subMatchedElements =
> matchElement.getSubMatchElements();
> System.out.println("Sub-Matched Elements(size) = " +
> subMatchedElements.size() + "\n");
> for (int isubMatch = 0; isubMatch <
> subMatchedElements.size(); isubMatch++){
> MatchElement submatchElem =
> subMatchedElements.get(isubMatch);
> System.out.println("SubmatchElem[" + isubMatch +
> "] : " + submatchElem.toString() + " has similarity : " +
> submatchElem.getSimilarity() + "\n");
>
> if (submatchElem.getSimilarity() != SIMILARITY) {
> final Match2Elements subElements =
> (Match2Elements) submatchElem;
> getMatchedElement(subElements,
> matchedElemLookup);
> }
> }
> */
> }
>
> System.out.println(" *** unmatched Elements *** \n");
> EList<UnMatchElement> unmatchElements =
> matchModel.getUnMatchedElements();
> System.out.println("Unmatched Elements(size)= " +
> unmatchElements.size() + "\n");
> for (int iUnMatch = 0; iUnMatch <
> unmatchElements.size(); iUnMatch++) {
> UnMatchElement unMatchElement =
> unmatchElements.get(iUnMatch);
> EObject eObject = unMatchElement.getElement();
> System.out.println(" UnMatchElem[" + iUnMatch + "]
> is : " + eObject);
> if (eObject != null){
> getUnMatchedElement(eObject, unmatchedElemLookup);
>
> }
> }
>
>
> System.out.println(" *** Differencing models *** \n");
> DiffModel myDiff = DiffService.doDiff(matchModel, false);
> EList<DiffElement> diffElements =
> myDiff.getOwnedElements();
>
> if (diffElements.size() == 0) {
> System.out.println("There is no difference between
> the two RootCompositeBox \n");
> } else {
> System.out.println("Diff Elements(size) = " +
> diffElements.size() + " \n ");
>
> for (int iDiff = 0; iDiff < diffElements.size();
> iDiff++) {
> final DiffElement diffElem =
> diffElements.get(iDiff);
> System.out.println("DiffElement[" + iDiff + "]
> is : " + diffElem.toString() + " \n ");
> String kind = diffElem.getKind().getName();
> System.out.println("KIND = " + kind + "\n");
>
> if (diffElem instanceof DiffGroup){
> final DiffGroup group = (DiffGroup) diffElem;
> System.out.println(group + " \n ") ;
> addDiffFromGroup(group, diffLookup);
> }else {
> diffLookup.add(diffElem);
> System.out.println(diffLookup.add(diffElem)
> + " \n ");
> }
> }
> }
> } catch (IOException e) {
> e.printStackTrace();
> } catch (InterruptedException e) {
> e.printStackTrace();
> }
> }
> }
> private void getMatchedElement(Match2Elements elements, Set<EObject>
> matchedElemLookup){
> EObject left = elements.getLeftElement();
> EObject right = elements.getRightElement();
>
> if (left instanceof MatchElement){
> final MatchElement leftMatchElement = (MatchElement) left;
> for (MatchElement subLeftMatchElement :
> leftMatchElement.getSubMatchElements()){
>
> if (subLeftMatchElement.getSimilarity() != SIMILARITY){
> final Match2Elements subLeftMatch2Element =
> (Match2Elements) subLeftMatchElement;
> System.out.println(subLeftMatch2Element + " \n ");
> getMatchedElement( subLeftMatch2Element,
> matchedElemLookup);
> }
> }
> }else {
> matchedElemLookup.add(left);
> System.out.println(matchedElemLookup.add(left) + " \n ");
> }
>
> if (right instanceof MatchElement){
> final MatchElement rightMatchElement = (MatchElement) right;
> if (rightMatchElement.getSimilarity() != SIMILARITY){
> final Match2Elements rightMatch2Element =
> (Match2Elements) rightMatchElement;
> System.out.println(rightMatch2Element + " \n ");
> getMatchedElement( rightMatch2Element, matchedElemLookup);
>
> }
> } else {
> matchedElemLookup.add(right);
> System.out.println(matchedElemLookup.add(right) + " \n ");
> }
> }
>
> private void getUnMatchedElement(EObject eObject, Set<EObject>
> unmatchedElemLookup){
> }
>
> private void addDiffFromGroup(DiffGroup group, Set<EObject>
> diffLookup) {
> EList<DiffElement> diffGroups = group.getSubDiffElements();
> System.out.println(diffGroups + " \n ");
> for (final DiffElement diffElem : diffGroups) {
> if (diffElem instanceof DiffGroup) {
> final DiffGroup subGroup = (DiffGroup) diffElem;
> System.out.println(" * " + subGroup + " \n ");
> addDiffFromGroup(subGroup, diffLookup);
> } else {
> diffLookup.add(diffElem);
> System.out.println(diffLookup.add(diffElem) + " \n ");
> }
> }
> }
> }
>
> Regards,
> Hanane YATIMI


--------------070802000706050605010802
Content-Type: text/x-vcard; charset=utf-8;
name="laurent_goubet.vcf"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
filename="laurent_goubet.vcf"

YmVnaW46dmNhcmQNCmZuOkxhdXJlbnQgR291YmV0DQpuOkdvdWJldDtMYXVy ZW50DQpvcmc6
PGEgaHJlZj0iaHR0cDovL3d3dy5vYmVvLmZyIj5PYmVvPC9hPg0KZW1haWw7 aW50ZXJuZXQ6
bGF1cmVudC5nb3ViZXRAb2Jlby5mcg0KdXJsOmh0dHA6Ly93d3cub2Jlby5m cg0KdmVyc2lv
bjoyLjENCmVuZDp2Y2FyZA0KDQo=
--------------070802000706050605010802--
Re: EMF Compare [message #622948 is a reply to message #535070] Fri, 28 May 2010 14:21 Go to previous message
Hanane is currently offline HananeFriend
Messages: 6
Registered: May 2010
Junior Member
Hi Laurent,
Thank you for your reply.

In fact,until now,with EMFCompare i can see matched element ,unmatched element and diff element in my console,
but the problem is that i don't want to see all things concerning the diagram ( means ,position of elements in models like (x, y) gmf,... )but only models (means if the elements of type EObjects exist in models or no,and also if their attribute has changed or no...) ,

For that raison,i create my own (MatchEngine and DiffEngine) ; which extend (GenericMatchEngine and GenericDiffEngine);
and also,i add my" Extension Point " like that :

- fileExtension (impala_diagram )
-engineClass (ImpalaMatchEngine)

and i did the same for DifEngine


And i want know which methods,class...are responsible for the display of the diagram (position of the elements in models ) that i have to override;otherwise , i want to keep in my own MatchEngine only methods which allow me to do the comparison between the two medels concerning existance (so deletion,addition,change) of elements,

this is the code of my own MatchEngine :

//////////////////////////////////////////////////////////// ////////////////////////////////////////////

package com.st.hed.iqi.impala.emfcompareimpala;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.eclipse.emf.common.EMFPlugin;
import org.eclipse.emf.compare.EMFComparePlugin;
import org.eclipse.emf.compare.FactoryException;
import org.eclipse.emf.compare.internal.runtime.CompareProgressMoni tor;
import org.eclipse.emf.compare.match.EMFCompareMatchMessages;
import org.eclipse.emf.compare.match.api.MatchOptions;
import org.eclipse.emf.compare.match.engine.GenericMatchEngine;
import org.eclipse.emf.compare.match.metamodel.Match2Elements;
import org.eclipse.emf.compare.match.metamodel.MatchFactory;
import org.eclipse.emf.compare.match.metamodel.MatchModel;
import org.eclipse.emf.compare.match.metamodel.UnMatchElement;
import org.eclipse.emf.compare.match.statistic.MetamodelFilter;
import org.eclipse.emf.compare.match.statistic.similarity.NameSimil arity;
import org.eclipse.emf.compare.match.statistic.similarity.Structure Similarity;
import org.eclipse.emf.compare.util.EFactory;
import org.eclipse.emf.compare.util.EMFCompareMap;
import org.eclipse.emf.compare.util.EMFComparePreferenceKeys;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.emf.ecore.xmi.XMIResource;

public class ImpalaMatchEngine extends GenericMatchEngine{

/** Containmnent reference for the matched elements root. */
private static final String MATCH_ELEMENT_NAME = "matchedElements"; //$NON-NLS-1$

/**
* Minimal number of attributes an element must have for content comparison.
*/
private static final int MIN_ATTRIBUTES_COUNT = 5;

/** This constant is used as key for the buffering of relations similarity. */
private static final char RELATION_SIMILARITY = 'r';

/** Containmnent reference for {@link MatchElement}s' submatches. */
private static final String SUBMATCH_ELEMENT_NAME = "subMatchElements"; //$NON-NLS-1$

/** Containmnent reference for the {@link MatchModel}'s unmatched elements. */
private static final String UNMATCH_ELEMENT_NAME = "unMatchedElements"; //$NON-NLS-1$

/** This constant is used as key for the buffering of name similarity. */
private static final char NAME_SIMILARITY = 'n';

/** This constant is used as key for the buffering of type similarity. */
private static final char TYPE_SIMILARITY = 't';

/** This constant is used as key for the buffering of value similarity. */
private static final char VALUE_SIMILARITY = 'v';

/**
* {@link MetamodelFilter} used for filtering unused features of the objects we're computing the
* similarity for.
*/
protected final MetamodelFilter filter = new MetamodelFilter();

/** Contains the options given to the match procedure. */
protected final Map<String, Object> options = new EMFCompareMap<String, Object>();

/**
* This map allows us memorize the {@link EObject} we've been able to match thanks to their functional ID.
*/
private final Map<String, EObject> matchedByID = new EMFCompareMap<String, EObject>();

/**
* This map allows us memorize the {@link EObject} we've been able to match thanks to their XMI ID.
*/
private final Map<String, EObject> matchedByXMIID = new EMFCompareMap<String, EObject>();

/**
* This map is used to cache the comparison results Pair(Element1, Element2) => .
*/
private final Map<String, Double> metricsCache = new EMFCompareMap<String, Double>();


/**
* This list will be intensively used while matching elements to keep track of the unmatched ones from the
* left model.
*/
private final List<EObject> stillToFindFromModel1 = new ArrayList<EObject>();

/**
* This list will be intensively used while matching elements to keep track of the unmatched ones from the
* right model.
*/
private final List<EObject> stillToFindFromModel2 = new ArrayList<EObject>();

/**
* {@inheritDoc}
*
* @see org.eclipse.emf.compare.match.api.IMatchEngine#modelMatch(or g.eclipse.emf.ecore.EObject,
* org.eclipse.emf.ecore.EObject, java.util.Map)
*/
public MatchModel modelMatch(EObject leftRoot, EObject rightRoot, Map<String, Object> optionMap)
throws InterruptedException {
if (optionMap != null && optionMap.size() > 0)
loadOptionMap(optionMap);

MatchModel result = null;
// Creates and sizes progress monitor
final CompareProgressMonitor monitor = new CompareProgressMonitor(getOption(MatchOptions.OPTION_PROGRES S_MONITOR));
int size = 1;
for (EObject root : leftRoot.eResource().getContents()) {
final Iterator<EObject> rootContent = root.eAllContents();
while (rootContent.hasNext()) {
rootContent.next();
size++;
}
}
startMonitor(monitor, size);

result = doMatch(leftRoot.eResource(), rightRoot.eResource(), monitor);
return result;
}

/**
* This replaces the contents of the defaults options map with the options overridden by the given map.
*
* @param map
* Map containing the option given to the match procedure. cannot be <code>null</code>.
*/
private void loadOptionMap(Map<String, Object> map) {
options.putAll(map);
Integer option = getOption(MatchOptions.OPTION_SEARCH_WINDOW);
if (option< 0)
options.put(MatchOptions.OPTION_SEARCH_WINDOW, getPreferenceSearchWindow());
}
/**
* This will return the value associated to the given key in the options map.
* <p>
* NOTE : Misuses of this method will easily throw {@link ClassCastException}s.
* </p>
*
* @param <T>
* Expected type of the value associated to <code>key</code>.
* @param key
* Key of the value to retrieve.
* @return Value associated to the given key in the options map.
* @throws ClassCastException
* If the value isn't assignment compatible with the expected type.
*/
@SuppressWarnings("unchecked")
protected <T> T getOption(String key) throws ClassCastException {
return (T)options.get(key);
}

/**
* Returns the search window corresponding to the number of siblings to consider while matching. Reducing
* this number (on the preferences page) considerably improve performances while reducing precision.
*
* @return An <code>int</code> representing the number of siblings to consider for matching.
*/
private int getPreferenceSearchWindow() {
int searchWindow = MatchOptions.DEFAULT_SEARCH_WINDOW;
if (EMFPlugin.IS_ECLIPSE_RUNNING
&& EMFComparePlugin.getDefault() != null
&& EMFComparePlugin.getDefault().getInt(
EMFComparePreferenceKeys.PREFERENCES_KEY_SEARCH_WINDOW) > 0)
searchWindow = EMFComparePlugin.getDefault().getInt(
EMFComparePreferenceKeys.PREFERENCES_KEY_SEARCH_WINDOW);
if (searchWindow < 0)
searchWindow = 0;
return searchWindow;
}

/**
* Starts the monitor for comparison progress. Externalized here to avoid multiple usage of the Strings.
*
* @param monitor
* The monitor that need be started
* @param size
* Size of the monitor
*/
private void startMonitor(CompareProgressMonitor monitor, int size) {
monitor.beginTask(EMFCompareMatchMessages.getString("DifferencesServices.monitor.task "), size); //$NON-NLS-1$
monitor.subTask(EMFCompareMatchMessages.getString("DifferencesServices.monitor.browsing ")); //$NON-NLS-1$
}

/**
* This method handles the creation and returning of a two way model match.
*
* @param leftResource
* Left model for the comparison.
* @param rightResource
* Right model for the comparison.
* @param monitor
* Progress monitor to display while the comparison lasts.
* @return The corresponding {@link MatchModel}.
* @throws InterruptedException
* Thrown if the comparison is interrupted somehow.
*/
private MatchModel doMatch(Resource leftResource, Resource rightResource, CompareProgressMonitor monitor)
throws InterruptedException {
final MatchModel root = MatchFactory.eINSTANCE.createMatchModel();
setModelURIs(root, leftResource, rightResource);

// filters unused features
filterUnused(leftResource);
filterUnused(rightResource);

// navigate through both models at the same time and realize mappings..
try {
if (!this.<Boolean> getOption(MatchOptions.OPTION_IGNORE_XMI_ID))
if (leftResource instanceof XMIResource && rightResource instanceof XMIResource)
matchByXMIID((XMIResource)leftResource, (XMIResource)rightResource);
if (!this.<Boolean> getOption(MatchOptions.OPTION_IGNORE_ID))
matchByID(leftResource, rightResource);

monitor.subTask(EMFCompareMatchMessages.getString("DifferencesServices.monitor.roots ")); //$NON-NLS-1$
final List<Match2Elements> matchedRoots = mapLists(leftResource.getContents(), rightResource
.getContents(), this.<Integer> getOption(MatchOptions.OPTION_SEARCH_WINDOW), monitor);
stillToFindFromModel1.clear();
stillToFindFromModel2.clear();
final List<EObject> unMatchedLeftRoots = new ArrayList<EObject>(leftResource.getContents());
final List<EObject> unMatchedRightRoots = new ArrayList<EObject>(rightResource.getContents());
// These sets will help us in keeping track of the yet to be found
// elements
final Set<EObject> still1 = new HashSet<EObject>();
final Set<EObject> still2 = new HashSet<EObject>();

// If one of the resources has no roots, considers it as deleted
if (leftResource.getContents().size() > 0 && rightResource.getContents().size() > 0) {
Match2Elements matchModelRoot = MatchFactory.eINSTANCE.createMatch2Elements();
// We haven't found any similar roots, we then consider the
// firsts to be similar.
if (matchedRoots.size() == 0) {
final Match2Elements rootMapping = MatchFactory.eINSTANCE.createMatch2Elements();
rootMapping.setLeftElement(leftResource.getContents().get(0) );
EObject rightElement = findMostSimilar(leftResource.getContents().get(0),
unMatchedRightRoots);
if (rightElement == null)
rightElement = unMatchedRightRoots.get(0);
rootMapping.setRightElement(rightElement);
matchedRoots.add(rootMapping);
}
monitor.subTask(EMFCompareMatchMessages
.getString("DifferencesServices.monitor.rootsContents")); //$NON-NLS-1$
for (Match2Elements matchedRoot : matchedRoots) {
final Match2Elements rootMapping = recursiveMappings(matchedRoot.getLeftElement(),
matchedRoot.getRightElement(), monitor);
// this is the first passage
if (matchModelRoot.getLeftElement() == null) {
matchModelRoot = rootMapping;
redirectedAdd(root, MATCH_ELEMENT_NAME, matchModelRoot);
} else {
redirectedAdd(matchModelRoot, SUBMATCH_ELEMENT_NAME, rootMapping);
}

// Synchronizes the two lists to avoid multiple elements
still1.removeAll(stillToFindFromModel1);
still2.removeAll(stillToFindFromModel2);
// checks for matches within the yet to found elements lists
createSubMatchElements(rootMapping, new ArrayList<EObject>(stillToFindFromModel1),
new ArrayList<EObject>(stillToFindFromModel2), monitor);
// Adds all unfound elements to the sets
still1.addAll(stillToFindFromModel1);
still2.addAll(stillToFindFromModel2);

unMatchedLeftRoots.remove(matchedRoot.getLeftElement());
unMatchedRightRoots.remove(matchedRoot.getRightElement());
}
// We'll iterate through the unMatchedRoots all contents
monitor.subTask(EMFCompareMatchMessages
.getString("DifferencesServices.monitor.unmatchedRoots")); //$NON-NLS-1$
createSubMatchElements(matchModelRoot, unMatchedLeftRoots, unMatchedRightRoots, monitor);
} else {
// Roots are unmatched, this is either a file addition or
// deletion
still1.addAll(unMatchedLeftRoots);
still2.addAll(unMatchedRightRoots);
}

// Now takes care of remaining unfound elements
still1.addAll(stillToFindFromModel1);
still2.addAll(stillToFindFromModel2);
createUnMatchElements(root, still1);
createUnMatchElements(root, still2);
} catch (FactoryException e) {
EMFComparePlugin.log(e, false);
}
return root;
}

/**
* Sets the values of the {@link MatchModel}'s left and right models.
*
* @param modelRoot
* Root of the {@link MatchModel}.
* @param left
* Element from which to resolve the left model URI.
* @param right
* Element from which to resolve the right model URI.
*/
private void setModelURIs(MatchModel modelRoot, Resource left, Resource right) {
setModelURIs(modelRoot, left, right, null);
}

/**
* Sets the values of the {@link MatchModel}'s left, right and ancestor models.
*
* @param modelRoot
* Root of the {@link MatchModel}.
* @param left
* Element from which to resolve the left model URI.
* @param right
* Element from which to resolve the right model URI.
* @param ancestor
* Element from which to resolve the ancestor model URI. Can be <code>null</code>.
*/
private void setModelURIs(MatchModel modelRoot, Resource left, Resource right, Resource ancestor) {
// Sets values of left, right and ancestor model URIs
if (left != null && left.getURI() != null)
modelRoot.setLeftModel(left.getURI().toString());
if (right != null && right.getURI() != null)
modelRoot.setRightModel(right.getURI().toString());
if (ancestor != null && ancestor.getURI() != null)
modelRoot.setOriginModel(ancestor.getURI().toString());
}

/**
* Filters unused features of the resource.
*
* @param resource
* Resource to be apply filter on.
*/
private void filterUnused(Resource resource) {
for (EObject root : resource.getContents())
filter.analyseModel(root);
}

/**
* Iterates through both of the given {@link XMIResource resources} to find all the elements that can be
* matched by their XMI ID, then populates {@link #matchedByXMIID} with those mappings.
*
* @param left
* First of the two {@link XMIResource resources} to visit.
* @param right
* Second of the {@link XMIResource resources} to visit.
* @throws FactoryException
* Thrown if we couldn't compute a key to store the items in cache.
*/
private void matchByXMIID(XMIResource left, XMIResource right) throws FactoryException {
matchedByXMIID.clear();
final Iterator<EObject> leftIterator = left.getAllContents();

while (leftIterator.hasNext()) {
final EObject item1 = leftIterator.next();
final String item1ID = left.getID(item1);
if (item1ID != null) {
final EObject item2 = right.getEObject(item1ID);
if (item2 != null) {
final StringBuilder item1Key = new StringBuilder();
item1Key.append(NameSimilarity.findName(item1));
item1Key.append(item1.hashCode());
matchedByXMIID.put(item1Key.toString(), item2);
}
}
}
}

/**
* Iterates through both of the given {@link XMIResource resources} to find all the elements that can be
* matched by their XMI ID, then populates {@link #matchedByID} with those mappings.
*
* @param left
* First of the two {@link XMIResource resources} to visit.
* @param right
* Second of the {@link XMIResource resources} to visit.
* @throws FactoryException
* Thrown if we couldn't compute a key to store the items in cache.
*/
private void matchByID(Resource left, Resource right) throws FactoryException {
matchedByID.clear();
final Iterator<EObject> leftIterator = left.getAllContents();
while (leftIterator.hasNext()) {
final EObject item1 = leftIterator.next();
final String item1ID = EcoreUtil.getID(item1);
if (item1ID != null) {
final Iterator<EObject> rightIterator = right.getAllContents();
while (rightIterator.hasNext()) {
final EObject item2 = rightIterator.next();
final String item2ID = EcoreUtil.getID(item2);
if (item2 != null && item1ID.equals(item2ID)) {
final StringBuilder item1Key = new StringBuilder();
item1Key.append(NameSimilarity.findName(item1));
item1Key.append(item1.hashCode());
matchedByID.put(item1Key.toString(), item2);
break;
}
}
}
}
}

/**
* Returns a list containing mappings of the nodes of both given {@link List}s.
*
* @param list1
* First of the lists from which we need to map the elements
* @param list2
* Second list to map the elements from.
* @param window
* Number of siblings to consider for the matching.
* @param monitor
* {@link CompareProgressMonitor Progress monitor} to display while the comparison lasts. Might
* be <code>null</code>, in which case we won't monitor progress.
* @return A {@link List} containing mappings of the nodes of both given {@link List}s.
* @throws FactoryException
* Thrown if the metrics cannot be computed.
* @throws InterruptedException
* Thrown if the matching process is interrupted somehow.
*/
private List<Match2Elements> mapLists(List<EObject> list1, List<EObject> list2, int window,
CompareProgressMonitor monitor) throws FactoryException, InterruptedException {
final List<Match2Elements> result = new ArrayList<Match2Elements>();
int curIndex = 0 - window / 2;
final List<EObject> notFoundList1 = new ArrayList<EObject>(list1);
final List<EObject> notFoundList2 = new ArrayList<EObject>(list2);

final Iterator<EObject> it1 = list1.iterator();
// then iterate over the 2 lists and compare the elements
while (it1.hasNext() && notFoundList2.size() > 0) {
final EObject obj1 = it1.next();

final StringBuilder obj1Key = new StringBuilder();
obj1Key.append(NameSimilarity.findName(obj1));
obj1Key.append(obj1.hashCode());
EObject obj2 = matchedByID.get(obj1Key.toString());

if (obj2 == null) {
// subtracts the difference between the notfound and the
// original list to avoid ArrayOutOfBounds
final int end = Math.min(curIndex + window - (list2.size() - notFoundList2.size()),
notFoundList2.size());
final int index = Math
.min(Math.max(curIndex - (list2.size() - notFoundList2.size()), 0), end);

obj2 = findMostSimilar(obj1, notFoundList2.subList(index, end));
if (obj2 != null) {
// checks if the most similar to obj2 is obj1
final EObject obj1Check = findMostSimilar(obj2, notFoundList1);
if (obj1Check != obj1 && obj1Check != null && isSimilar(obj1Check, obj2)) {
continue;
}
}
}

if (notFoundList1.contains(obj1) && notFoundList2.contains(obj2) && isSimilar(obj1, obj2)) {
final Match2Elements mapping = MatchFactory.eINSTANCE.createMatch2Elements();
final double metric = absoluteMetric(obj1, obj2);

mapping.setLeftElement(obj1);
mapping.setRightElement(obj2);
mapping.setSimilarity(metric);
result.add(mapping);
notFoundList2.remove(obj2);
notFoundList1.remove(obj1);
}
curIndex += 1;
monitor.worked(1);
if (monitor.isCanceled())
throw new InterruptedException();
}

// now putting the not found elements aside for later
stillToFindFromModel2.addAll(notFoundList2);
stillToFindFromModel1.addAll(notFoundList1);
return result;
}

/**
* Returns an absolute comparison metric between the two given {@link EObject}s.
*
* @param obj1
* The first {@link EObject} to compare.
* @param obj2
* Second of the {@link EObject}s to compare.
* @return An absolute comparison metric. 0 < value < 1.
* @throws FactoryException
* Thrown if we cannot compute the content similarity.
*/
private double absoluteMetric(EObject obj1, EObject obj2) throws FactoryException {
final double nameSimilarity = nameSimilarity(obj1, obj2);
final double relationsSimilarity = relationsSimilarity(obj1, obj2);
double sameUri = 0d;
if (hasSameUri(obj1, obj2))
sameUri = 1;
final double positionSimilarity = relationsSimilarity / 2d + sameUri / 2d;

final double contentWeight = 0.5d;

if (nonNullFeaturesCount(obj1) > MIN_ATTRIBUTES_COUNT
&& nonNullFeaturesCount(obj2) > MIN_ATTRIBUTES_COUNT) {
final double nameWeight = 0.4d;
final double positionWeight = 0.4d;
final double contentSimilarity = contentSimilarity(obj1, obj2);
// Computing type similarity really is time expensive
// double typeSimilarity = typeSimilarity(obj1, obj2);
return (contentSimilarity * contentWeight + nameSimilarity * nameWeight + positionSimilarity
* positionWeight)
/ (contentWeight + nameWeight + positionWeight);
}
// we didn't have enough features to compute an accurate metric
final double nameWeight = 0.8d;
final double positionWeight = 0.2d;
return (nameSimilarity * nameWeight + positionSimilarity * positionWeight)
/ (nameWeight + positionWeight);
}

/**
* This will compute the similarity between two {@link EObject}s' relations.
*
* @param obj1
* First of the two {@link EObject}s.
* @param obj2
* Second of the two {@link EObject}s.
* @return <code>double</code> representing the similarity between the two {@link EObject}s' relations.
* 0 < value < 1.
* @throws FactoryException
* Thrown if we cannot compute the relations' similarity metrics.
* @see StructureSimilarity#relationsSimilarityMetric(EObject, EObject, MetamodelFilter)
*/
private double relationsSimilarity(EObject obj1, EObject obj2) throws FactoryException {
double similarity = 0d;
final Double value = getSimilarityFromCache(obj1, obj2, RELATION_SIMILARITY);
if (value != null) {
similarity = value;
} else {
similarity = StructureSimilarity.relationsSimilarityMetric(obj1, obj2, filter);
setSimilarityInCache(obj1, obj2, RELATION_SIMILARITY, similarity);
}
return similarity;
}

/**
* Checks wether the two given {@link EObject} have the same URI.
*
* @param obj1
* First of the two {@link EObject} we're comparing.
* @param obj2
* Second {@link EObject} we're comparing.
* @return <code>True</code> if the {@link EObject}s have the same URI, <code>False</code> otherwise.
*/
private boolean hasSameUri(EObject obj1, EObject obj2) {
if (obj1.eResource() != null && obj2.eResource() != null)
return obj1.eResource().getURIFragment(obj1).equals(obj2.eResource( ).getURIFragment(obj2));
return false;
}

/**
* Counts all the {@link EStructuralFeature features} of the given {@link EObject} that are
* <code>null</code> or initialized to the empty {@link String} "".
*
* @param eobj
* {@link EObject} we need to count the empty features of.
* @return The number of features initialized to <code>null</code> or the empty String.
*/
private int nonNullFeaturesCount(EObject eobj) {
// TODO should probably cache result here
int nonNullFeatures = 0;
final Iterator<EStructuralFeature> features = eobj.eClass().getEAllStructuralFeatures().iterator();
while (features.hasNext()) {
final EStructuralFeature feature = features.next();
if (eobj.eGet(feature) != null && !"".equals(eobj.eGet(feature).toString())) //$NON-NLS-1$
nonNullFeatures++;
}
return nonNullFeatures;
}
/**
* We consider here <code>current1</code> and <code>current2</code> are similar. This method creates
* the mapping for the objects <code>current1</code> and <code>current2</code>, Then submappings for
* these two elements' contents.
*
* @param current1
* First element of the two elements mapping.
* @param current2
* Second of the two elements mapping.
* @param monitor
* {@link CompareProgressMonitor Progress monitor} to display while the comparison lasts. Might
* be <code>null</code>, in which case we won't monitor progress.
* @return The mapping for <code>current1</code> and <code>current2</code> and their content.
* @throws FactoryException
* Thrown when the metrics cannot be computed for <code>current1</code> and
* <code>current2</code>.
* @throws InterruptedException
* Thrown if the matching process is interrupted somehow.
*/
private Match2Elements recursiveMappings(EObject current1, EObject current2,
CompareProgressMonitor monitor) throws FactoryException, InterruptedException {
Match2Elements mapping = null;
mapping = MatchFactory.eINSTANCE.createMatch2Elements();
mapping.setLeftElement(current1);
mapping.setRightElement(current2);
mapping.setSimilarity(absoluteMetric(current1, current2));
final List<Match2Elements> mapList = mapLists(getContents(current1), getContents(current2), this
.<Integer> getOption(MatchOptions.OPTION_SEARCH_WINDOW), monitor);
// We can map other elements with mapLists; we iterate through them.
final Iterator<Match2Elements> it = mapList.iterator();
while (it.hasNext()) {
final Match2Elements subMapping = it.next();
// As we know source and target are similars, we call recursive
// mappings onto these objects
EFactory.eAdd(mapping, SUBMATCH_ELEMENT_NAME, recursiveMappings(subMapping.getLeftElement(),
subMapping.getRightElement(), monitor));
}
return mapping;
}

/**
* Workaround for bug #235606 : elements held by a reference with containment=true and derived=true are
* not matched since not returned by {@link EObject#eContents()}. This allows us to return the list of all
* contents from an EObject <u>including</u> those references.
*
* @param eObject
* The EObject we seek the content of.
* @return The list of all the content of a given EObject, derived containmnent references included.
*/
@SuppressWarnings("unchecked")
private List<EObject> getContents(EObject eObject) {
// TODO can this be cached (Map<EClass, List<EReference>>)?
final List<EObject> result = new ArrayList(eObject.eContents());
for (EReference reference : eObject.eClass().getEAllReferences()) {
if (reference.isContainment() && reference.isDerived()) {
final Object value = eObject.eGet(reference);
if (value instanceof Collection)
result.addAll((Collection)value);
else if (value instanceof EObject)
result.add((EObject)value);
}
}
return result;
}

/**
* Creates the {@link Match2Elements submatch elements} corresponding to the mapping of objects from the
* two given {@link List}s.
*
* @param root
* Root of the {@link MatchModel} where to insert all these mappings.
* @param list1
* First of the lists used to compute mapping.
* @param list2
* Second of the lists used to compute mapping.
* @param monitor
* {@link CompareProgressMonitor progress monitor} to display while the comparison lasts. Might
* be <code>null</code>, in which case we won't monitor progress.
* @throws FactoryException
* Thrown if we cannot match the elements of the two lists or add submatch elements to
* <code>root</code>.
* @throws InterruptedException
* Thrown if the operation is cancelled or fails somehow.
*/
private void createSubMatchElements(EObject root, List<EObject> list1, List<EObject> list2,
CompareProgressMonitor monitor) throws FactoryException, InterruptedException {
stillToFindFromModel1.clear();
stillToFindFromModel2.clear();
final List<Match2Elements> mappings = mapLists(list1, list2, this
.<Integer> getOption(MatchOptions.OPTION_SEARCH_WINDOW), monitor);

final Iterator<Match2Elements> it = mappings.iterator();
while (it.hasNext()) {
final Match2Elements map = it.next();
final Match2Elements match = recursiveMappings(map.getLeftElement(), map.getRightElement(),
monitor);
redirectedAdd(root, SUBMATCH_ELEMENT_NAME, match);
}
}

/**
* Creates {@link UnMatchElement}s wrapped around all the elements of the given {@link List}.
*
* @param root
* Root of the {@link MatchModel} under which to insert all these {@link UnMatchElement}s.
* @param unMatchedElements
* {@link Set} containing all the elements we haven't been able to match.
* @throws FactoryException
* Thrown if we cannot add elements under the given {@link MatchModel root}.
*/
private void createUnMatchElements(MatchModel root, Set<EObject> unMatchedElements)
throws FactoryException {
for (EObject element : unMatchedElements) {
final UnMatchElement unMap = MatchFactory.eINSTANCE.createUnMatchElement();
unMap.setElement(element);
redirectedAdd(root, UNMATCH_ELEMENT_NAME, unMap);
}
unMatchedElements.clear();
}

/**
* This method is an indirection for adding Mappings in the current MappingGroup.
*
* @param object
* {@link EObject} to add a feature value to.
* @param name
* Name of the feature to consider.
* @param value
* Value to add to the feature <code>name</code> of <code>object</code>.
* @throws FactoryException
* Thrown if the value's affectation fails.
*/
private void redirectedAdd(EObject object, String name, Object value) throws FactoryException {
EFactory.eAdd(object, name, value);
}

/**
* Returns the given similarity between the two given {@link EObject}s as it is stored in cache.<br/>
* <p>
* <code>similarityKind</code> must be one of
* <ul>
* <li>{@link #NAME_SIMILARITY}</li>
* <li>{@link #TYPE_SIMILARITY}</li>
* <li>{@link #VALUE_SIMILARITY}</li>
* <li>{@link #RELATION_SIMILARITY}</li>
* </ul>
* </p>
*
* @param obj1
* First of the two {@link EObject}s we seek the similarity for.
* @param obj2
* Second of the two {@link EObject}s we seek the similarity for.
* @param similarityKind
* Kind of similarity to get.
* @return The similarity as described by <code>similarityKind</code> as it is stored in cache for the
* two given {@link EObject}s.
*/
private Double getSimilarityFromCache(EObject obj1, EObject obj2, char similarityKind) {
return metricsCache.get(pairHashCode(obj1, obj2, similarityKind));
}

/**
* Computes an unique key between to {@link EObject}s to store their similarity in cache.
* <p>
* <code>similarityKind</code> must be one of
* <ul>
* <li>{@link #NAME_SIMILARITY}</li>
* <li>{@link #TYPE_SIMILARITY}</li>
* <li>{@link #VALUE_SIMILARITY}</li>
* <li>{@link #RELATION_SIMILARITY}</li>
* </ul>
* </p>
*
* @param obj1
* First of the two {@link EObject}s.
* @param obj2
* Second of the two {@link EObject}s.
* @param similarityKind
* Kind of similarity this key will represent in cache.
* @return Unique key for the similarity cache.
*/
private String pairHashCode(EObject obj1, EObject obj2, char similarityKind) {
if (similarityKind == NAME_SIMILARITY || similarityKind == TYPE_SIMILARITY
|| similarityKind == VALUE_SIMILARITY || similarityKind == RELATION_SIMILARITY) {
final StringBuilder hash = new StringBuilder();
hash.append(similarityKind).append(obj1.hashCode()).append(o bj2.hashCode());
return hash.toString();
}
throw new IllegalArgumentException(EMFCompareMatchMessages.getString(
"DifferencesServices.illegalSimilarityKind", similarityKind)); //$NON-NLS-1$
}

/**
* Stores in cache the given similarity between the two given {@link EObject}s.<br/>
* <p>
* <code>similarityKind</code> must be one of
* <ul>
* <li>{@link #NAME_SIMILARITY}</li>
* <li>{@link #TYPE_SIMILARITY}</li>
* <li>{@link #VALUE_SIMILARITY}</li>
* <li>{@link #RELATION_SIMILARITY}</li>
* </ul>
* </p>
*
* @param obj1
* First of the two {@link EObject}s we're setting the similarity for.
* @param obj2
* Second of the two {@link EObject}s we're setting the similarity for.
* @param similarityKind
* Kind of similarity to set.
* @param similarity
* Value of the similarity between the two {@link EObject}s.
*/
private void setSimilarityInCache(EObject obj1, EObject obj2, char similarityKind, double similarity) {
metricsCache.put(pairHashCode(obj1, obj2, similarityKind), new Double(similarity));
}


}

//////////////////////////////////////////////////////////// ////////////////////////////////////////////
and the content of my console (when i used the GenericMatchEngine and GenericDiffEngine):

//////////////////////////////////////////////////////////// ////////////////////////////////////////////
*** Loading resources ***

C:\Documents and Settings\yatimih\runtime-New_configuration\MyAlgorithm1\diag ram\Copy of old-default.impala_diagram : rootCompositeBox1

C:\Documents and Settings\yatimih\runtime-New_configuration\MyAlgorithm1\diag ram\old-default.impala_diagram : rootCompositeBox2

*** matched Elements ***

Matched Elements(size) = 1

MatchElem : mailto: org.eclipse.emf.compare.match.metamodel.impl.Match2ElementsI mpl @1eb0d79 (similarity: 0.9580419580419581) has similarity : 0.9580419580419581

the left element is : mailto: com.st.hed.iqi.impala.srcgen.model.impl.RootCompositeBoxImpl @120d1c0 (name: MyAlgorithm1, version: 1.0.0, description: Description is not filled, isReadOnly: false, isChangedFromLib: false)

the right element is : mailto: com.st.hed.iqi.impala.srcgen.model.impl.RootCompositeBoxImpl @f82888 (name: MyAlgorithm1, version: 1.0.0, description: Description is not filled, isReadOnly: false, isChangedFromLib: false)

this is a list of the content objects of the left element :

* mailto: com.st.hed.iqi.impala.srcgen.model.impl.NCodeGenPropertyImpl @1a9ab54 (language: iqi-c, name: GEN_UNIQUE_NAME, value: )

this is a list of the content objects of the left element :

* mailto: com.st.hed.iqi.impala.srcgen.model.impl.NCodeGenPropertyImpl @1f7e4cf (language: iqi-c, name: GENERATION_DATE, value: )

this is a list of the content objects of the left element :

* mailto: com.st.hed.iqi.impala.srcgen.model.impl.NCodeGenPropertyImpl @1cee582 (language: iqi-c, name: USER, value: )

this is a list of the content objects of the left element :

* mailto: com.st.hed.iqi.impala.srcgen.model.impl.NCodeGenPropertyImpl @3dd567 (language: iqi-c, name: GENERATOR_VERSION, value: )

this is a list of the content objects of the left element :

* mailto: com.st.hed.iqi.impala.srcgen.model.impl.NCodeGenPropertyImpl @1856ec1 (language: iqi-c, name: TYPE_QUALIFIED_NAME, value: )

this is a list of the content objects of the left element :

* mailto: com.st.hed.impala.src.model.impl.ImpalaInputParameterBoxImpl @ec28c0 (name: Sequence_input, version: 1.0.0, description: Description is not filled, isReadOnly: false, isChangedFromLib: false) (debugMode: NoDebug, debugTextFormat: null, debugHeader: null, debugTrailer: null, debugDumpDestination: null)

this is a list of the content objects of the left element :

* mailto:com.st.hed.iqi.impala.srcgen.model.impl.CompositeBoxImpl@1c200d0 (name: CB, version: 1.0.0, description: Description is not filled, isReadOnly: false, isChangedFromLib: false)

this is a list of the content objects of the left element :

* mailto:com.st.hed.impala.src.model.impl.ImpalaFrameGathererImpl@5db277 (increment: 1, channel: Y, offsetInSequence: 0) (name: FG, version: 1.0.0, description: Description is not filled, isReadOnly: false, isChangedFromLib: false, debugMode: NoDebug, debugTextFormat: null, debugHeader: null, debugTrailer: null, debugDumpDestination: null, newRootDirectory: null, newRadix: null)

this is a list of the content objects of the left element :

* mailto:com.st.hed.impala.src.model.impl.ImpalaFrameSelectorImpl@6cd712 (increment: 1, channel: Y, offsetInSequence: 0) (name: FS, version: 1.0.0, description: Description is not filled, isReadOnly: false, isChangedFromLib: false, debugMode: NoDebug, debugTextFormat: null, debugHeader: null, debugTrailer: null, debugDumpDestination: null)

this is a list of the content objects of the left element :

* mailto:com.st.hed.iqi.impala.srcgen.model.impl.NSequenceImpl@f61e2 (name: input, version: 1.0.0, description: Description is not filled, isReadOnly: false, isChangedFromLib: false) (width: 1, height: 1, sampling: YUV444, startFrameNb: 0, NbOfFrames: 1, SequenceRoot: , SequenceRadix: , storageType: SGP, isProgressive: true, isTopFirst: true, dynamic: 8)



this is a list of the content objects of the right element :

* mailto: com.st.hed.iqi.impala.srcgen.model.impl.NCodeGenPropertyImpl @2d1d1e (language: iqi-c, name: GEN_UNIQUE_NAME, value: )

this is a list of the content objects of the right element :

* mailto: com.st.hed.iqi.impala.srcgen.model.impl.NCodeGenPropertyImpl @1d2c4aa (language: iqi-c, name: GENERATION_DATE, value: )

this is a list of the content objects of the right element :

* mailto: com.st.hed.iqi.impala.srcgen.model.impl.NCodeGenPropertyImpl @6db04e (language: iqi-c, name: USER, value: )

this is a list of the content objects of the right element :

* mailto: com.st.hed.iqi.impala.srcgen.model.impl.NCodeGenPropertyImpl @151da55 (language: iqi-c, name: GENERATOR_VERSION, value: )

this is a list of the content objects of the right element :

* mailto: com.st.hed.impala.src.model.impl.ImpalaInputParameterBoxImpl @d53356 (name: Sequence_input, version: 1.0.0, description: Description is not filled, isReadOnly: false, isChangedFromLib: false) (debugMode: NoDebug, debugTextFormat: null, debugHeader: null, debugTrailer: null, debugDumpDestination: null)

this is a list of the content objects of the right element :

* mailto:com.st.hed.iqi.impala.srcgen.model.impl.CompositeBoxImpl@877294 (name: CB, version: 1.0.0, description: Description is not filled, isReadOnly: false, isChangedFromLib: false)

this is a list of the content objects of the right element :

* mailto:com.st.hed.impala.src.model.impl.ImpalaFrameGathererImpl@1fa522d (increment: 1, channel: Y, offsetInSequence: 0) (name: FG, version: 1.0.0, description: Description is not filled, isReadOnly: false, isChangedFromLib: false, debugMode: NoDebug, debugTextFormat: null, debugHeader: null, debugTrailer: null, debugDumpDestination: null, newRootDirectory: null, newRadix: null)

this is a list of the content objects of the right element :

* mailto:com.st.hed.impala.src.model.impl.ImpalaFrameGathererImpl@129271e (increment: 1, channel: Y, offsetInSequence: 0) (name: FG1, version: 1.0.0, description: Description is not filled, isReadOnly: false, isChangedFromLib: false, debugMode: NoDebug, debugTextFormat: null, debugHeader: null, debugTrailer: null, debugDumpDestination: null, newRootDirectory: null, newRadix: null)

this is a list of the content objects of the right element :

* mailto:com.st.hed.impala.src.model.impl.ImpalaFrameSelectorImpl@c73ac2 (increment: 1, channel: Y, offsetInSequence: 0) (name: FS, version: 1.0.0, description: Description is not filled, isReadOnly: false, isChangedFromLib: false, debugMode: NoDebug, debugTextFormat: null, debugHeader: null, debugTrailer: null, debugDumpDestination: null)

this is a list of the content objects of the right element :

* mailto:com.st.hed.iqi.impala.srcgen.model.impl.NSequenceImpl@1e2b2a6 (name: input, version: 1.0.0, description: Description is not filled, isReadOnly: false, isChangedFromLib: false) (width: 1, height: 1, sampling: YUV444, startFrameNb: 0, NbOfFrames: 1, SequenceRoot: , SequenceRadix: , storageType: SGP, isProgressive: true, isTopFirst: true, dynamic: 8)

this is a list of the content objects of the right element :

* mailto:com.st.hed.iqi.impala.srcgen.model.impl.CompositeBoxImpl@6d2d52 (name: lib, version: 1.0.0, description: This is the container for the library types, isReadOnly: false, isChangedFromLib: false)

Unmatched Elements(size) = 8

UnMatchElem is : mailto: org.eclipse.emf.compare.match.metamodel.impl.UnMatchElementI mpl @c183ea

* mailto:org.eclipse.gmf.runtime.notation.impl.DiagramImpl@1ea08e7 (visible: true, type: impala-metamodel, mutable: false) (name: , measurementUnit: Pixel)

UnMatchElem is : mailto: org.eclipse.emf.compare.match.metamodel.impl.UnMatchElementI mpl @bbb074

* mailto: com.st.hed.iqi.impala.srcgen.model.impl.NCodeGenPropertyImpl @1c3599d (language: iqi-c, name: GEN_UNIQUE_NAME, value: )

UnMatchElem is : mailto: org.eclipse.emf.compare.match.metamodel.impl.UnMatchElementI mpl @3dc250

* mailto: com.st.hed.iqi.impala.srcgen.model.impl.NCodeGenPropertyImpl @f933f1 (language: iqi-c, name: TYPE_QUALIFIED_NAME, value: MyAlgorithm1::lib::pixel)

UnMatchElem is : mailto: org.eclipse.emf.compare.match.metamodel.impl.UnMatchElementI mpl @a01a84

* mailto: com.st.hed.iqi.impala.srcgen.model.impl.NCodeGenPropertyImpl @559e4f (language: iqi-c, name: TYPE_QUALIFIED_NAME, value: MyAlgorithm1::lib::pixel)

UnMatchElem is : mailto: org.eclipse.emf.compare.match.metamodel.impl.UnMatchElementI mpl @12cf455

* mailto:com.st.hed.iqi.impala.srcgen.model.impl.CompositeBoxImpl@6d2d52 (name: lib, version: 1.0.0, description: This is the container for the library types, isReadOnly: false, isChangedFromLib: false)

lib

* mailto: com.st.hed.iqi.impala.srcgen.model.impl.NCodeGenPropertyImpl @7da288 (language: iqi-c, name: LIB_CONTAINER, value: true)

* mailto: com.st.hed.iqi.impala.srcgen.model.impl.NCodeGenPropertyImpl @399f62 (language: iqi-c, name: GEN_UNIQUE_NAME, value: MyAlgorithm1::lib)

* mailto:com.st.hed.impala.src.model.impl.ImpalaInputWindowImpl@176feac (name: pixel, version: 1.0.0, description: Description is not filled, isReadOnly: false, isChangedFromLib: false) (height: 1, width: 1) (debugMode: NoDebug, debugTextFormat: null, debugHeader: null, debugTrailer: null, debugDumpDestination: null)

UnMatchElem is : mailto: org.eclipse.emf.compare.match.metamodel.impl.UnMatchElementI mpl @5d15c6

* mailto:org.eclipse.gmf.runtime.notation.impl.EdgeImpl@1282220 (visible: true, type: 3009, mutable: false)

UnMatchElem is : mailto: org.eclipse.emf.compare.match.metamodel.impl.UnMatchElementI mpl @140960c

* mailto:com.st.hed.impala.src.model.impl.ImpalaFrameGathererImpl@129271e (increment: 1, channel: Y, offsetInSequence: 0) (name: FG1, version: 1.0.0, description: Description is not filled, isReadOnly: false, isChangedFromLib: false, debugMode: NoDebug, debugTextFormat: null, debugHeader: null, debugTrailer: null, debugDumpDestination: null, newRootDirectory: null, newRadix: null)

FG1

UnMatchElem is : mailto: org.eclipse.emf.compare.match.metamodel.impl.UnMatchElementI mpl @13afac7

* mailto:org.eclipse.gmf.runtime.notation.impl.NodeImpl@9283b0 (visible: true, type: 1007, mutable: false)

*** Differencing models ***

Diff Elements(size) = 1

DiffElement is : mailto:org.eclipse.emf.compare.diff.metamodel.impl.DiffGroupImpl@4000e7 (conflicting: false, kind: Addition)

KIND = Change

mailto:org.eclipse.emf.compare.diff.metamodel.impl.DiffGroupImpl@4000e7 (conflicting: false, kind: Change)



* 10 change(s) in RootCompositeBox MyAlgorithm1



* 6 change(s) in CompositeBox CB



* 3 change(s) in Shaper SHAP



* 3 change(s) in OutputWindow out



false

false

false

* 1 change(s) in FrameGatherer FGCB



false

false

* 1 change(s) in Kernel k



* 1 change(s) in InputWindow IWK



false

* 2 change(s) in NCodeGenProperty TYPE_QUALIFIED_NAME



false

false

false

false

* 11 change(s) in Diagram default.impala_diagram



* 3 change(s) in Node true



* 1 change(s) in Node true



* 1 change(s) in Node true



* 1 change(s) in Bounds 337



false

* 1 change(s) in HintedDiagramLinkStyle HintedDiagramLinkStyle



false

* 1 change(s) in Bounds 96



false

* 1 change(s) in Edge true

[1 change(s) in RelativeBendpoints [mailto:org.eclipse.gmf.runtime.notation.datatype.RelativeBendpoint@beb8f0 (sourceX: 31, sourceY: -1, targetX: -58, targetY: -133), mailto:org.eclipse.gmf.runtime.notation.datatype.RelativeBendpoint@15faa7c (sourceX: 42, sourceY: -1, targetX: -47, targetY: -133), mailto:org.eclipse.gmf.runtime.notation.datatype.RelativeBendpoint@1b1db9a (sourceX: 42, sourceY: 131, targetX: -47, targetY: -1), mailto:org.eclipse.gmf.runtime.notation.datatype.RelativeBendpoint@1c86489 (sourceX: 60, sourceY: 131, targetX: -29, targetY: -1)]]

* 1 change(s) in RelativeBendpoints [mailto:org.eclipse.gmf.runtime.notation.datatype.RelativeBendpoint@beb8f0 (sourceX: 31, sourceY: -1, targetX: -58, targetY: -133), mailto:org.eclipse.gmf.runtime.notation.datatype.RelativeBendpoint@15faa7c (sourceX: 42, sourceY: -1, targetX: -47, targetY: -133), mailto:org.eclipse.gmf.runtime.notation.datatype.RelativeBendpoint@1b1db9a (sourceX: 42, sourceY: 131, targetX: -47, targetY: -1), mailto:org.eclipse.gmf.runtime.notation.datatype.RelativeBendpoint@1c86489 (sourceX: 60, sourceY: 131, targetX: -29, targetY: -1)]

[Att
Re: EMF Compare [message #622957 is a reply to message #622948] Mon, 31 May 2010 09:35 Go to previous message
Laurent Goubet is currently offline Laurent GoubetFriend
Messages: 1902
Registered: July 2009
Senior Member
This is a multi-part message in MIME format.
--------------040809070202060300050909
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 7bit

Hi,

As you fully copy/pasted the GenericMatchEngine in your own
implementation (thus shunning any improvement/fix we may have done since
then), I cannot say where you changed anything, and try and determine
what your code does.

Other than that, I must admit I don't really understand your issue. If
you don't wish to see any difference concerning the diagrams, why do
you compare the diagrams and not the underlying models?

Laurent Goubet
Obeo

Hanane wrote:
>
> Hi Laurent,
> Thank you for your reply.
>
> In fact,until now,with EMFCompare i can see matched element ,unmatched
> element and diff element in my console,
> but the problem is that i don't want to see all things concerning the
> diagram ( means ,position of elements in models like (x, y) gmf,... )but
> only models (means if the elements of type EObjects exist in models or
> no,and also if their attribute has changed or no...) ,
>
> For that raison,i create my own (MatchEngine and DiffEngine) ; which
> extend (GenericMatchEngine and GenericDiffEngine);
> and also,i add my" Extension Point " like that :
>
> - fileExtension (impala_diagram )
> -engineClass (ImpalaMatchEngine)
>
> and i did the same for DifEngine
>
>
> And i want know which methods,class...are responsible for the display of
> the diagram (position of the elements in models ) that i have to
> override;otherwise , i want to keep in my own MatchEngine only methods
> which allow me to do the comparison between the two medels concerning
> existance (so deletion,addition,change) of elements,
>
> this is the code of my own MatchEngine :
>
> ////////////////////////////////////////////////////////////
> ////////////////////////////////////////////
>
> package com.st.hed.iqi.impala.emfcompareimpala;
>
> import java.util.ArrayList;
> import java.util.Collection;
> import java.util.HashSet;
> import java.util.Iterator;
> import java.util.List;
> import java.util.Map;
> import java.util.Set;
>
> import org.eclipse.emf.common.EMFPlugin;
> import org.eclipse.emf.compare.EMFComparePlugin;
> import org.eclipse.emf.compare.FactoryException;
> import org.eclipse.emf.compare.internal.runtime.CompareProgressMoni tor;
> import org.eclipse.emf.compare.match.EMFCompareMatchMessages;
> import org.eclipse.emf.compare.match.api.MatchOptions;
> import org.eclipse.emf.compare.match.engine.GenericMatchEngine;
> import org.eclipse.emf.compare.match.metamodel.Match2Elements;
> import org.eclipse.emf.compare.match.metamodel.MatchFactory;
> import org.eclipse.emf.compare.match.metamodel.MatchModel;
> import org.eclipse.emf.compare.match.metamodel.UnMatchElement;
> import org.eclipse.emf.compare.match.statistic.MetamodelFilter;
> import org.eclipse.emf.compare.match.statistic.similarity.NameSimil arity;
> import org.eclipse.emf.compare.match.statistic.similarity.Structure
> Similarity;
> import org.eclipse.emf.compare.util.EFactory;
> import org.eclipse.emf.compare.util.EMFCompareMap;
> import org.eclipse.emf.compare.util.EMFComparePreferenceKeys;
> import org.eclipse.emf.ecore.EObject;
> import org.eclipse.emf.ecore.EReference;
> import org.eclipse.emf.ecore.EStructuralFeature;
> import org.eclipse.emf.ecore.resource.Resource;
> import org.eclipse.emf.ecore.util.EcoreUtil;
> import org.eclipse.emf.ecore.xmi.XMIResource;
>
> public class ImpalaMatchEngine extends GenericMatchEngine{
>
> /** Containmnent reference for the matched elements root. */
> private static final String MATCH_ELEMENT_NAME = "matchedElements";
> //$NON-NLS-1$
>
> /**
> * Minimal number of attributes an element must have for content
> comparison.
> */
> private static final int MIN_ATTRIBUTES_COUNT = 5;
>
> /** This constant is used as key for the buffering of relations
> similarity. */
> private static final char RELATION_SIMILARITY = 'r';
>
> /** Containmnent reference for {@link MatchElement}s' submatches. */
> private static final String SUBMATCH_ELEMENT_NAME =
> "subMatchElements"; //$NON-NLS-1$
>
> /** Containmnent reference for the {@link MatchModel}'s unmatched
> elements. */
> private static final String UNMATCH_ELEMENT_NAME =
> "unMatchedElements"; //$NON-NLS-1$
>
> /** This constant is used as key for the buffering of name
> similarity. */
> private static final char NAME_SIMILARITY = 'n';
>
> /** This constant is used as key for the buffering of type
> similarity. */
> private static final char TYPE_SIMILARITY = 't';
>
> /** This constant is used as key for the buffering of value
> similarity. */
> private static final char VALUE_SIMILARITY = 'v';
>
> /**
> * {@link MetamodelFilter} used for filtering unused features of the
> objects we're computing the
> * similarity for.
> */
> protected final MetamodelFilter filter = new MetamodelFilter();
>
> /** Contains the options given to the match procedure. */
> protected final Map<String, Object> options = new
> EMFCompareMap<String, Object>();
>
> /**
> * This map allows us memorize the {@link EObject} we've been able
> to match thanks to their functional ID.
> */
> private final Map<String, EObject> matchedByID = new
> EMFCompareMap<String, EObject>();
>
> /**
> * This map allows us memorize the {@link EObject} we've been able
> to match thanks to their XMI ID.
> */
> private final Map<String, EObject> matchedByXMIID = new
> EMFCompareMap<String, EObject>();
>
> /**
> * This map is used to cache the comparison results Pair(Element1,
> Element2) => .
> */
> private final Map<String, Double> metricsCache = new
> EMFCompareMap<String, Double>();
>
>
> /**
> * This list will be intensively used while matching elements to
> keep track of the unmatched ones from the
> * left model.
> */
> private final List<EObject> stillToFindFromModel1 = new
> ArrayList<EObject>();
>
> /**
> * This list will be intensively used while matching elements to
> keep track of the unmatched ones from the
> * right model.
> */
> private final List<EObject> stillToFindFromModel2 = new
> ArrayList<EObject>();
>
> /**
> * {@inheritDoc}
> * * @see
> org.eclipse.emf.compare.match.api.IMatchEngine#modelMatch(or
> g.eclipse.emf.ecore.EObject,
> * org.eclipse.emf.ecore.EObject, java.util.Map)
> */
> public MatchModel modelMatch(EObject leftRoot, EObject rightRoot,
> Map<String, Object> optionMap)
> throws InterruptedException {
> if (optionMap != null && optionMap.size() > 0)
> loadOptionMap(optionMap);
>
> MatchModel result = null;
> // Creates and sizes progress monitor
> final CompareProgressMonitor monitor = new
> CompareProgressMonitor(getOption(MatchOptions.OPTION_PROGRES S_MONITOR));
> int size = 1;
> for (EObject root : leftRoot.eResource().getContents()) {
> final Iterator<EObject> rootContent = root.eAllContents();
> while (rootContent.hasNext()) {
> rootContent.next();
> size++;
> }
> }
> startMonitor(monitor, size);
>
> result = doMatch(leftRoot.eResource(), rightRoot.eResource(),
> monitor);
> return result;
> }
>
> /**
> * This replaces the contents of the defaults options map with the
> options overridden by the given map.
> * * @param map
> * Map containing the option given to the match
> procedure. cannot be <code>null</code>.
> */
> private void loadOptionMap(Map<String, Object> map) {
> options.putAll(map);
> Integer option = getOption(MatchOptions.OPTION_SEARCH_WINDOW);
> if (option< 0)
> options.put(MatchOptions.OPTION_SEARCH_WINDOW,
> getPreferenceSearchWindow());
> }
> /**
> * This will return the value associated to the given key in the
> options map.
> * <p>
> * NOTE : Misuses of this method will easily throw {@link
> ClassCastException}s.
> * </p>
> * * @param <T>
> * Expected type of the value associated to
> <code>key</code>.
> * @param key
> * Key of the value to retrieve.
> * @return Value associated to the given key in the options map.
> * @throws ClassCastException
> * If the value isn't assignment compatible with the
> expected type.
> */
> @SuppressWarnings("unchecked")
> protected <T> T getOption(String key) throws ClassCastException {
> return (T)options.get(key);
> }
>
> /**
> * Returns the search window corresponding to the number of siblings
> to consider while matching. Reducing
> * this number (on the preferences page) considerably improve
> performances while reducing precision.
> * * @return An <code>int</code> representing the number of
> siblings to consider for matching.
> */
> private int getPreferenceSearchWindow() {
> int searchWindow = MatchOptions.DEFAULT_SEARCH_WINDOW;
> if (EMFPlugin.IS_ECLIPSE_RUNNING
> && EMFComparePlugin.getDefault() != null
> && EMFComparePlugin.getDefault().getInt(
>
> EMFComparePreferenceKeys.PREFERENCES_KEY_SEARCH_WINDOW) > 0)
> searchWindow = EMFComparePlugin.getDefault().getInt(
>
> EMFComparePreferenceKeys.PREFERENCES_KEY_SEARCH_WINDOW);
> if (searchWindow < 0)
> searchWindow = 0;
> return searchWindow;
> }
>
> /**
> * Starts the monitor for comparison progress. Externalized here to
> avoid multiple usage of the Strings.
> * * @param monitor
> * The monitor that need be started
> * @param size
> * Size of the monitor
> */
> private void startMonitor(CompareProgressMonitor monitor, int size) {
>
> monitor.beginTask(EMFCompareMatchMessages.getString("DifferencesServices.monitor.task
> "), size); //$NON-NLS-1$
>
> monitor.subTask(EMFCompareMatchMessages.getString("DifferencesServices.monitor.browsing
> ")); //$NON-NLS-1$
> }
>
> /**
> * This method handles the creation and returning of a two way model
> match.
> * * @param leftResource
> * Left model for the comparison.
> * @param rightResource
> * Right model for the comparison.
> * @param monitor
> * Progress monitor to display while the comparison lasts.
> * @return The corresponding {@link MatchModel}.
> * @throws InterruptedException
> * Thrown if the comparison is interrupted somehow.
> */
> private MatchModel doMatch(Resource leftResource, Resource
> rightResource, CompareProgressMonitor monitor)
> throws InterruptedException {
> final MatchModel root = MatchFactory.eINSTANCE.createMatchModel();
> setModelURIs(root, leftResource, rightResource);
>
> // filters unused features
> filterUnused(leftResource);
> filterUnused(rightResource);
>
> // navigate through both models at the same time and realize
> mappings..
> try {
> if (!this.<Boolean>
> getOption(MatchOptions.OPTION_IGNORE_XMI_ID))
> if (leftResource instanceof XMIResource && rightResource
> instanceof XMIResource)
> matchByXMIID((XMIResource)leftResource,
> (XMIResource)rightResource);
> if (!this.<Boolean> getOption(MatchOptions.OPTION_IGNORE_ID))
> matchByID(leftResource, rightResource);
>
>
> monitor.subTask(EMFCompareMatchMessages.getString("DifferencesServices.monitor.roots
> ")); //$NON-NLS-1$
> final List<Match2Elements> matchedRoots =
> mapLists(leftResource.getContents(), rightResource
> .getContents(), this.<Integer>
> getOption(MatchOptions.OPTION_SEARCH_WINDOW), monitor);
> stillToFindFromModel1.clear();
> stillToFindFromModel2.clear();
> final List<EObject> unMatchedLeftRoots = new
> ArrayList<EObject>(leftResource.getContents());
> final List<EObject> unMatchedRightRoots = new
> ArrayList<EObject>(rightResource.getContents());
> // These sets will help us in keeping track of the yet to be
> found
> // elements
> final Set<EObject> still1 = new HashSet<EObject>();
> final Set<EObject> still2 = new HashSet<EObject>();
>
> // If one of the resources has no roots, considers it as
> deleted
> if (leftResource.getContents().size() > 0 &&
> rightResource.getContents().size() > 0) {
> Match2Elements matchModelRoot =
> MatchFactory.eINSTANCE.createMatch2Elements();
> // We haven't found any similar roots, we then consider the
> // firsts to be similar.
> if (matchedRoots.size() == 0) {
> final Match2Elements rootMapping =
> MatchFactory.eINSTANCE.createMatch2Elements();
>
> rootMapping.setLeftElement(leftResource.getContents().get(0) );
> EObject rightElement =
> findMostSimilar(leftResource.getContents().get(0),
> unMatchedRightRoots);
> if (rightElement == null)
> rightElement = unMatchedRightRoots.get(0);
> rootMapping.setRightElement(rightElement);
> matchedRoots.add(rootMapping);
> }
> monitor.subTask(EMFCompareMatchMessages
>
> .getString("DifferencesServices.monitor.rootsContents")); //$NON-NLS-1$
> for (Match2Elements matchedRoot : matchedRoots) {
> final Match2Elements rootMapping =
> recursiveMappings(matchedRoot.getLeftElement(),
> matchedRoot.getRightElement(), monitor);
> // this is the first passage
> if (matchModelRoot.getLeftElement() == null) {
> matchModelRoot = rootMapping;
> redirectedAdd(root, MATCH_ELEMENT_NAME,
> matchModelRoot);
> } else {
> redirectedAdd(matchModelRoot,
> SUBMATCH_ELEMENT_NAME, rootMapping);
> }
>
> // Synchronizes the two lists to avoid multiple
> elements
> still1.removeAll(stillToFindFromModel1);
> still2.removeAll(stillToFindFromModel2);
> // checks for matches within the yet to found
> elements lists
> createSubMatchElements(rootMapping, new
> ArrayList<EObject>(stillToFindFromModel1),
> new
> ArrayList<EObject>(stillToFindFromModel2), monitor);
> // Adds all unfound elements to the sets
> still1.addAll(stillToFindFromModel1);
> still2.addAll(stillToFindFromModel2);
>
>
> unMatchedLeftRoots.remove(matchedRoot.getLeftElement());
>
> unMatchedRightRoots.remove(matchedRoot.getRightElement());
> }
> // We'll iterate through the unMatchedRoots all contents
> monitor.subTask(EMFCompareMatchMessages
>
> .getString("DifferencesServices.monitor.unmatchedRoots")); //$NON-NLS-1$
> createSubMatchElements(matchModelRoot,
> unMatchedLeftRoots, unMatchedRightRoots, monitor);
> } else {
> // Roots are unmatched, this is either a file addition or
> // deletion
> still1.addAll(unMatchedLeftRoots);
> still2.addAll(unMatchedRightRoots);
> }
>
> // Now takes care of remaining unfound elements
> still1.addAll(stillToFindFromModel1);
> still2.addAll(stillToFindFromModel2);
> createUnMatchElements(root, still1);
> createUnMatchElements(root, still2);
> } catch (FactoryException e) {
> EMFComparePlugin.log(e, false);
> }
> return root;
> }
>
> /**
> * Sets the values of the {@link MatchModel}'s left and right models.
> * * @param modelRoot
> * Root of the {@link MatchModel}.
> * @param left
> * Element from which to resolve the left model URI.
> * @param right
> * Element from which to resolve the right model URI.
> */
> private void setModelURIs(MatchModel modelRoot, Resource left,
> Resource right) {
> setModelURIs(modelRoot, left, right, null);
> }
>
> /**
> * Sets the values of the {@link MatchModel}'s left, right and
> ancestor models.
> * * @param modelRoot
> * Root of the {@link MatchModel}.
> * @param left
> * Element from which to resolve the left model URI.
> * @param right
> * Element from which to resolve the right model URI.
> * @param ancestor
> * Element from which to resolve the ancestor model URI.
> Can be <code>null</code>.
> */
> private void setModelURIs(MatchModel modelRoot, Resource left,
> Resource right, Resource ancestor) {
> // Sets values of left, right and ancestor model URIs
> if (left != null && left.getURI() != null)
> modelRoot.setLeftModel(left.getURI().toString());
> if (right != null && right.getURI() != null)
> modelRoot.setRightModel(right.getURI().toString());
> if (ancestor != null && ancestor.getURI() != null)
> modelRoot.setOriginModel(ancestor.getURI().toString());
> }
>
> /**
> * Filters unused features of the resource.
> * * @param resource
> * Resource to be apply filter on.
> */
> private void filterUnused(Resource resource) {
> for (EObject root : resource.getContents())
> filter.analyseModel(root);
> }
>
> /**
> * Iterates through both of the given {@link XMIResource resources}
> to find all the elements that can be
> * matched by their XMI ID, then populates {@link #matchedByXMIID}
> with those mappings.
> * * @param left
> * First of the two {@link XMIResource resources} to visit.
> * @param right
> * Second of the {@link XMIResource resources} to visit.
> * @throws FactoryException
> * Thrown if we couldn't compute a key to store the
> items in cache.
> */
> private void matchByXMIID(XMIResource left, XMIResource right)
> throws FactoryException {
> matchedByXMIID.clear();
> final Iterator<EObject> leftIterator = left.getAllContents();
>
> while (leftIterator.hasNext()) {
> final EObject item1 = leftIterator.next();
> final String item1ID = left.getID(item1);
> if (item1ID != null) {
> final EObject item2 = right.getEObject(item1ID);
> if (item2 != null) {
> final StringBuilder item1Key = new StringBuilder();
> item1Key.append(NameSimilarity.findName(item1));
> item1Key.append(item1.hashCode());
> matchedByXMIID.put(item1Key.toString(), item2);
> }
> }
> }
> }
>
> /**
> * Iterates through both of the given {@link XMIResource resources}
> to find all the elements that can be
> * matched by their XMI ID, then populates {@link #matchedByID} with
> those mappings.
> * * @param left
> * First of the two {@link XMIResource resources} to visit.
> * @param right
> * Second of the {@link XMIResource resources} to visit.
> * @throws FactoryException
> * Thrown if we couldn't compute a key to store the
> items in cache.
> */
> private void matchByID(Resource left, Resource right) throws
> FactoryException {
> matchedByID.clear();
> final Iterator<EObject> leftIterator = left.getAllContents();
> while (leftIterator.hasNext()) {
> final EObject item1 = leftIterator.next();
> final String item1ID = EcoreUtil.getID(item1);
> if (item1ID != null) {
> final Iterator<EObject> rightIterator =
> right.getAllContents();
> while (rightIterator.hasNext()) {
> final EObject item2 = rightIterator.next();
> final String item2ID = EcoreUtil.getID(item2);
> if (item2 != null && item1ID.equals(item2ID)) {
> final StringBuilder item1Key = new StringBuilder();
> item1Key.append(NameSimilarity.findName(item1));
> item1Key.append(item1.hashCode());
> matchedByID.put(item1Key.toString(), item2);
> break;
> }
> }
> }
> }
> }
>
> /**
> * Returns a list containing mappings of the nodes of both given
> {@link List}s.
> * * @param list1
> * First of the lists from which we need to map the elements
> * @param list2
> * Second list to map the elements from.
> * @param window
> * Number of siblings to consider for the matching.
> * @param monitor
> * {@link CompareProgressMonitor Progress monitor} to
> display while the comparison lasts. Might
> * be <code>null</code>, in which case we won't monitor
> progress.
> * @return A {@link List} containing mappings of the nodes of both
> given {@link List}s.
> * @throws FactoryException
> * Thrown if the metrics cannot be computed.
> * @throws InterruptedException
> * Thrown if the matching process is interrupted somehow.
> */
> private List<Match2Elements> mapLists(List<EObject> list1,
> List<EObject> list2, int window,
> CompareProgressMonitor monitor) throws FactoryException,
> InterruptedException {
> final List<Match2Elements> result = new
> ArrayList<Match2Elements>();
> int curIndex = 0 - window / 2;
> final List<EObject> notFoundList1 = new ArrayList<EObject>(list1);
> final List<EObject> notFoundList2 = new ArrayList<EObject>(list2);
>
> final Iterator<EObject> it1 = list1.iterator();
> // then iterate over the 2 lists and compare the elements
> while (it1.hasNext() && notFoundList2.size() > 0) {
> final EObject obj1 = it1.next();
>
> final StringBuilder obj1Key = new StringBuilder();
> obj1Key.append(NameSimilarity.findName(obj1));
> obj1Key.append(obj1.hashCode());
> EObject obj2 = matchedByID.get(obj1Key.toString());
>
> if (obj2 == null) {
> // subtracts the difference between the notfound and the
> // original list to avoid ArrayOutOfBounds
> final int end = Math.min(curIndex + window -
> (list2.size() - notFoundList2.size()),
> notFoundList2.size());
> final int index = Math
> .min(Math.max(curIndex - (list2.size() -
> notFoundList2.size()), 0), end);
>
> obj2 = findMostSimilar(obj1,
> notFoundList2.subList(index, end));
> if (obj2 != null) {
> // checks if the most similar to obj2 is obj1
> final EObject obj1Check = findMostSimilar(obj2,
> notFoundList1);
> if (obj1Check != obj1 && obj1Check != null &&
> isSimilar(obj1Check, obj2)) {
> continue;
> }
> }
> }
>
> if (notFoundList1.contains(obj1) &&
> notFoundList2.contains(obj2) && isSimilar(obj1, obj2)) {
> final Match2Elements mapping =
> MatchFactory.eINSTANCE.createMatch2Elements();
> final double metric = absoluteMetric(obj1, obj2);
>
> mapping.setLeftElement(obj1);
> mapping.setRightElement(obj2);
> mapping.setSimilarity(metric);
> result.add(mapping);
> notFoundList2.remove(obj2);
> notFoundList1.remove(obj1);
> }
> curIndex += 1;
> monitor.worked(1);
> if (monitor.isCanceled())
> throw new InterruptedException();
> }
>
> // now putting the not found elements aside for later
> stillToFindFromModel2.addAll(notFoundList2);
> stillToFindFromModel1.addAll(notFoundList1);
> return result;
> }
>
> /**
> * Returns an absolute comparison metric between the two given
> {@link EObject}s.
> * * @param obj1
> * The first {@link EObject} to compare.
> * @param obj2
> * Second of the {@link EObject}s to compare.
> * @return An absolute comparison metric. 0 < value < 1.
> * @throws FactoryException
> * Thrown if we cannot compute the content similarity.
> */
> private double absoluteMetric(EObject obj1, EObject obj2) throws
> FactoryException {
> final double nameSimilarity = nameSimilarity(obj1, obj2);
> final double relationsSimilarity = relationsSimilarity(obj1, obj2);
> double sameUri = 0d;
> if (hasSameUri(obj1, obj2))
> sameUri = 1;
> final double positionSimilarity = relationsSimilarity / 2d +
> sameUri / 2d;
>
> final double contentWeight = 0.5d;
>
> if (nonNullFeaturesCount(obj1) > MIN_ATTRIBUTES_COUNT
> && nonNullFeaturesCount(obj2) > MIN_ATTRIBUTES_COUNT) {
> final double nameWeight = 0.4d;
> final double positionWeight = 0.4d;
> final double contentSimilarity = contentSimilarity(obj1, obj2);
> // Computing type similarity really is time expensive
> // double typeSimilarity = typeSimilarity(obj1, obj2);
> return (contentSimilarity * contentWeight + nameSimilarity *
> nameWeight + positionSimilarity
> * positionWeight)
> / (contentWeight + nameWeight + positionWeight);
> }
> // we didn't have enough features to compute an accurate metric
> final double nameWeight = 0.8d;
> final double positionWeight = 0.2d;
> return (nameSimilarity * nameWeight + positionSimilarity *
> positionWeight)
> / (nameWeight + positionWeight);
> }
>
> /**
> * This will compute the similarity between two {@link EObject}s'
> relations.
> * * @param obj1
> * First of the two {@link EObject}s.
> * @param obj2
> * Second of the two {@link EObject}s.
> * @return <code>double</code> representing the similarity between
> the two {@link EObject}s' relations.
> * 0 < value < 1.
> * @throws FactoryException
> * Thrown if we cannot compute the relations' similarity
> metrics.
> * @see StructureSimilarity#relationsSimilarityMetric(EObject,
> EObject, MetamodelFilter)
> */
> private double relationsSimilarity(EObject obj1, EObject obj2)
> throws FactoryException {
> double similarity = 0d;
> final Double value = getSimilarityFromCache(obj1, obj2,
> RELATION_SIMILARITY);
> if (value != null) {
> similarity = value;
> } else {
> similarity =
> StructureSimilarity.relationsSimilarityMetric(obj1, obj2, filter);
> setSimilarityInCache(obj1, obj2, RELATION_SIMILARITY,
> similarity);
> }
> return similarity;
> }
>
> /**
> * Checks wether the two given {@link EObject} have the same URI.
> * * @param obj1
> * First of the two {@link EObject} we're comparing.
> * @param obj2
> * Second {@link EObject} we're comparing.
> * @return <code>True</code> if the {@link EObject}s have the same
> URI, <code>False</code> otherwise.
> */
> private boolean hasSameUri(EObject obj1, EObject obj2) {
> if (obj1.eResource() != null && obj2.eResource() != null)
> return
> obj1.eResource().getURIFragment(obj1).equals(obj2.eResource(
> ).getURIFragment(obj2));
> return false;
> }
>
> /**
> * Counts all the {@link EStructuralFeature features} of the given
> {@link EObject} that are
> * <code>null</code> or initialized to the empty {@link String} "".
> * * @param eobj
> * {@link EObject} we need to count the empty features of.
> * @return The number of features initialized to <code>null</code>
> or the empty String.
> */
> private int nonNullFeaturesCount(EObject eobj) {
> // TODO should probably cache result here
> int nonNullFeatures = 0;
> final Iterator<EStructuralFeature> features =
> eobj.eClass().getEAllStructuralFeatures().iterator();
> while (features.hasNext()) {
> final EStructuralFeature feature = features.next();
> if (eobj.eGet(feature) != null &&
> !"".equals(eobj.eGet(feature).toString())) //$NON-NLS-1$
> nonNullFeatures++;
> }
> return nonNullFeatures;
> }
> /**
> * We consider here <code>current1</code> and <code>current2</code>
> are similar. This method creates
> * the mapping for the objects <code>current1</code> and
> <code>current2</code>, Then submappings for
> * these two elements' contents.
> * * @param current1
> * First element of the two elements mapping.
> * @param current2
> * Second of the two elements mapping.
> * @param monitor
> * {@link CompareProgressMonitor Progress monitor} to
> display while the comparison lasts. Might
> * be <code>null</code>, in which case we won't monitor
> progress.
> * @return The mapping for <code>current1</code> and
> <code>current2</code> and their content.
> * @throws FactoryException
> * Thrown when the metrics cannot be computed for
> <code>current1</code> and
> * <code>current2</code>.
> * @throws InterruptedException
> * Thrown if the matching process is interrupted somehow.
> */
> private Match2Elements recursiveMappings(EObject current1, EObject
> current2,
> CompareProgressMonitor monitor) throws FactoryException,
> InterruptedException {
> Match2Elements mapping = null;
> mapping = MatchFactory.eINSTANCE.createMatch2Elements();
> mapping.setLeftElement(current1);
> mapping.setRightElement(current2);
> mapping.setSimilarity(absoluteMetric(current1, current2));
> final List<Match2Elements> mapList =
> mapLists(getContents(current1), getContents(current2), this
> .<Integer> getOption(MatchOptions.OPTION_SEARCH_WINDOW),
> monitor);
> // We can map other elements with mapLists; we iterate through
> them.
> final Iterator<Match2Elements> it = mapList.iterator();
> while (it.hasNext()) {
> final Match2Elements subMapping = it.next();
> // As we know source and target are similars, we call recursive
> // mappings onto these objects
> EFactory.eAdd(mapping, SUBMATCH_ELEMENT_NAME,
> recursiveMappings(subMapping.getLeftElement(),
> subMapping.getRightElement(), monitor));
> }
> return mapping;
> }
>
> /**
> * Workaround for bug #235606 : elements held by a reference with
> containment=true and derived=true are
> * not matched since not returned by {@link EObject#eContents()}.
> This allows us to return the list of all
> * contents from an EObject <u>including</u> those references.
> * * @param eObject
> * The EObject we seek the content of.
> * @return The list of all the content of a given EObject, derived
> containmnent references included.
> */
> @SuppressWarnings("unchecked")
> private List<EObject> getContents(EObject eObject) {
> // TODO can this be cached (Map<EClass, List<EReference>>)?
> final List<EObject> result = new ArrayList(eObject.eContents());
> for (EReference reference : eObject.eClass().getEAllReferences()) {
> if (reference.isContainment() && reference.isDerived()) {
> final Object value = eObject.eGet(reference);
> if (value instanceof Collection)
> result.addAll((Collection)value);
> else if (value instanceof EObject)
> result.add((EObject)value);
> }
> }
> return result;
> }
>
> /**
> * Creates the {@link Match2Elements submatch elements}
> corresponding to the mapping of objects from the
> * two given {@link List}s.
> * * @param root
> * Root of the {@link MatchModel} where to insert all
> these mappings.
> * @param list1
> * First of the lists used to compute mapping.
> * @param list2
> * Second of the lists used to compute mapping.
> * @param monitor
> * {@link CompareProgressMonitor progress monitor} to
> display while the comparison lasts. Might
> * be <code>null</code>, in which case we won't monitor
> progress.
> * @throws FactoryException
> * Thrown if we cannot match the elements of the two
> lists or add submatch elements to
> * <code>root</code>.
> * @throws InterruptedException
> * Thrown if the operation is cancelled or fails somehow.
> */
> private void createSubMatchElements(EObject root, List<EObject>
> list1, List<EObject> list2,
> CompareProgressMonitor monitor) throws FactoryException,
> InterruptedException {
> stillToFindFromModel1.clear();
> stillToFindFromModel2.clear();
> final List<Match2Elements> mappings = mapLists(list1, list2, this
> .<Integer> getOption(MatchOptions.OPTION_SEARCH_WINDOW),
> monitor);
>
> final Iterator<Match2Elements> it = mappings.iterator();
> while (it.hasNext()) {
> final Match2Elements map = it.next();
> final Match2Elements match =
> recursiveMappings(map.getLeftElement(), map.getRightElement(),
> monitor);
> redirectedAdd(root, SUBMATCH_ELEMENT_NAME, match);
> }
> }
>
> /**
> * Creates {@link UnMatchElement}s wrapped around all the elements
> of the given {@link List}.
> * * @param root
> * Root of the {@link MatchModel} under which to insert
> all these {@link UnMatchElement}s.
> * @param unMatchedElements
> * {@link Set} containing all the elements we haven't
> been able to match.
> * @throws FactoryException
> * Thrown if we cannot add elements under the given
> {@link MatchModel root}.
> */
> private void createUnMatchElements(MatchModel root, Set<EObject>
> unMatchedElements)
> throws FactoryException {
> for (EObject element : unMatchedElements) {
> final UnMatchElement unMap =
> MatchFactory.eINSTANCE.createUnMatchElement();
> unMap.setElement(element);
> redirectedAdd(root, UNMATCH_ELEMENT_NAME, unMap);
> }
> unMatchedElements.clear();
> }
>
> /**
> * This method is an indirection for adding Mappings in the current
> MappingGroup.
> * * @param object
> * {@link EObject} to add a feature value to.
> * @param name
> * Name of the feature to consider.
> * @param value
> * Value to add to the feature <code>name</code> of
> <code>object</code>.
> * @throws FactoryException
> * Thrown if the value's affectation fails.
> */
> private void redirectedAdd(EObject object, String name, Object
> value) throws FactoryException {
> EFactory.eAdd(object, name, value);
> }
>
> /**
> * Returns the given similarity between the two given {@link
> EObject}s as it is stored in cache.<br/>
> * <p>
> * <code>similarityKind</code> must be one of
> * <ul>
> * <li>{@link #NAME_SIMILARITY}</li>
> * <li>{@link #TYPE_SIMILARITY}</li>
> * <li>{@link #VALUE_SIMILARITY}</li>
> * <li>{@link #RELATION_SIMILARITY}</li>
> * </ul>
> * </p>
> * * @param obj1
> * First of the two {@link EObject}s we seek the
> similarity for.
> * @param obj2
> * Second of the two {@link EObject}s we seek the
> similarity for.
> * @param similarityKind
> * Kind of similarity to get.
> * @return The similarity as described by
> <code>similarityKind</code> as it is stored in cache for the
> * two given {@link EObject}s.
> */
> private Double getSimilarityFromCache(EObject obj1, EObject obj2,
> char similarityKind) {
> return metricsCache.get(pairHashCode(obj1, obj2, similarityKind));
> }
>
> /**
> * Computes an unique key between to {@link EObject}s to store their
> similarity in cache.
> * <p>
> * <code>similarityKind</code> must be one of
> * <ul>
> * <li>{@link #NAME_SIMILARITY}</li>
> * <li>{@link #TYPE_SIMILARITY}</li>
> * <li>{@link #VALUE_SIMILARITY}</li>
> * <li>{@link #RELATION_SIMILARITY}</li>
> * </ul>
> * </p>
> * * @param obj1
> * First of the two {@link EObject}s.
> * @param obj2
> * Second of the two {@link EObject}s.
> * @param similarityKind
> * Kind of similarity this key will represent in cache.
> * @return Unique key for the similarity cache.
> */
> private String pairHashCode(EObject obj1, EObject obj2, char
> similarityKind) {
> if (similarityKind == NAME_SIMILARITY || similarityKind ==
> TYPE_SIMILARITY
> || similarityKind == VALUE_SIMILARITY || similarityKind
> == RELATION_SIMILARITY) {
> final StringBuilder hash = new StringBuilder();
>
> hash.append(similarityKind).append(obj1.hashCode()).append(o
> bj2.hashCode());
> return hash.toString();
> }
> throw new
> IllegalArgumentException(EMFCompareMatchMessages.getString(
> "DifferencesServices.illegalSimilarityKind",
> similarityKind)); //$NON-NLS-1$
> }
>
> /**
> * Stores in cache the given similarity between the two given {@link
> EObject}s.<br/>
> * <p>
> * <code>similarityKind</code> must be one of
> * <ul>
> * <li>{@link #NAME_SIMILARITY}</li>
> * <li>{@link #TYPE_SIMILARITY}</li>
> * <li>{@link #VALUE_SIMILARITY}</li>
> * <li>{@link #RELATION_SIMILARITY}</li>
> * </ul>
> * </p>
> * * @param obj1
> * First of the two {@link EObject}s we're setting the
> similarity for.
> * @param obj2
> * Second of the two {@link EObject}s we're setting the
> similarity for.
> * @param similarityKind
> * Kind of similarity to set.
> * @param similarity
> * Value of the similarity between the two {@link EObject}s.
> */
> private void setSimilarityInCache(EObject obj1, EObject obj2, char
> similarityKind, double similarity) {
> metricsCache.put(pairHashCode(obj1, obj2, similarityKind), new
> Double(similarity));
> }
>
>
> }
>
> ////////////////////////////////////////////////////////////
> ////////////////////////////////////////////
> and the content of my console (when i used the GenericMatchEngine and
> GenericDiffEngine):
>
> ////////////////////////////////////////////////////////////
> ////////////////////////////////////////////
> *** Loading resources ***
> C:\Documents and
> Settings\yatimih\runtime-New_configuration\MyAlgorithm1\diag ram\Copy of
> old-default.impala_diagram : rootCompositeBox1
> C:\Documents and
> Settings\yatimih\runtime-New_configuration\MyAlgorithm1\diag
> ram\old-default.impala_diagram : rootCompositeBox2
> *** matched Elements ***
> Matched Elements(size) = 1
>
> MatchElem :
> mailto: org.eclipse.emf.compare.match.metamodel.impl.Match2ElementsI mpl @1eb0d79
> (similarity: 0.9580419580419581) has similarity : 0.9580419580419581
>
> the left element is :
> mailto: com.st.hed.iqi.impala.srcgen.model.impl.RootCompositeBoxImpl @120d1c0
> (name: MyAlgorithm1, version: 1.0.0, description: Description is not
> filled, isReadOnly: false, isChangedFromLib: false)
>
> the right element is :
> mailto: com.st.hed.iqi.impala.srcgen.model.impl.RootCompositeBoxImpl @f82888
> (name: MyAlgorithm1, version: 1.0.0, description: Description is not
> filled, isReadOnly: false, isChangedFromLib: false)
>
> this is a list of the content objects of the left element :
> *
> mailto: com.st.hed.iqi.impala.srcgen.model.impl.NCodeGenPropertyImpl @1a9ab54
> (language: iqi-c, name: GEN_UNIQUE_NAME, value: )
>
> this is a list of the content objects of the left element :
> *
> mailto: com.st.hed.iqi.impala.srcgen.model.impl.NCodeGenPropertyImpl @1f7e4cf
> (language: iqi-c, name: GENERATION_DATE, value: )
>
> this is a list of the content objects of the left element :
> *
> mailto: com.st.hed.iqi.impala.srcgen.model.impl.NCodeGenPropertyImpl @1cee582
> (language: iqi-c, name: USER, value: )
>
> this is a list of the content objects of the left element :
> *
> mailto: com.st.hed.iqi.impala.srcgen.model.impl.NCodeGenPropertyImpl @3dd567
> (language: iqi-c, name: GENERATOR_VERSION, value: )
>
> this is a list of the content objects of the left element :
> *
> mailto: com.st.hed.iqi.impala.srcgen.model.impl.NCodeGenPropertyImpl @1856ec1
> (language: iqi-c, name: TYPE_QUALIFIED_NAME, value: )
>
> this is a list of the content objects of the left element :
> *
> mailto: com.st.hed.impala.src.model.impl.ImpalaInputParameterBoxImpl @ec28c0
> (name: Sequence_input, version: 1.0.0, description: Description is not
> filled, isReadOnly: false, isChangedFromLib: false) (debugMode: NoDebug,
> debugTextFormat: null, debugHeader: null, debugTrailer: null,
> debugDumpDestination: null)
>
> this is a list of the content objects of the left element :
> *
> mailto:com.st.hed.iqi.impala.srcgen.model.impl.CompositeBoxImpl@1c200d0
> (name: CB, version: 1.0.0, description: Description is not filled,
> isReadOnly: false, isChangedFromLib: false)
>
> this is a list of the content objects of the left element :
> *
> mailto:com.st.hed.impala.src.model.impl.ImpalaFrameGathererImpl@5db277
> (increment: 1, channel: Y, offsetInSequence: 0) (name: FG, version:
> 1.0.0, description: Description is not filled, isReadOnly: false,
> isChangedFromLib: false, debugMode: NoDebug, debugTextFormat: null,
> debugHeader: null, debugTrailer: null, debugDumpDestination: null,
> newRootDirectory: null, newRadix: null)
>
> this is a list of the content objects of the left element :
> *
> mailto:com.st.hed.impala.src.model.impl.ImpalaFrameSelectorImpl@6cd712
> (increment: 1, channel: Y, offsetInSequence: 0) (name: FS, version:
> 1.0.0, description: Description is not filled, isReadOnly: false,
> isChangedFromLib: false, debugMode: NoDebug, debugTextFormat: null,
> debugHeader: null, debugTrailer: null, debugDumpDestination: null)
>
> this is a list of the content objects of the left element :
> *
> mailto:com.st.hed.iqi.impala.srcgen.model.impl.NSequenceImpl@f61e2
> (name: input, version: 1.0.0, description: Description is not filled,
> isReadOnly: false, isChangedFromLib: false) (width: 1, height: 1,
> sampling: YUV444, startFrameNb: 0, NbOfFrames: 1, SequenceRoot: ,
> SequenceRadix: , storageType: SGP, isProgressive: true, isTopFirst:
> true, dynamic: 8)
>
>
>
> this is a list of the content objects of the right element :
> *
> mailto: com.st.hed.iqi.impala.srcgen.model.impl.NCodeGenPropertyImpl @2d1d1e
> (language: iqi-c, name: GEN_UNIQUE_NAME, value: )
>
> this is a list of the content objects of the right element :
> *
> mailto: com.st.hed.iqi.impala.srcgen.model.impl.NCodeGenPropertyImpl @1d2c4aa
> (language: iqi-c, name: GENERATION_DATE, value: )
>
> this is a list of the content objects of the right element :
> *
> mailto: com.st.hed.iqi.impala.srcgen.model.impl.NCodeGenPropertyImpl @6db04e
> (language: iqi-c, name: USER, value: )
>
> this is a list of the content objects of the right element :
> *
> mailto: com.st.hed.iqi.impala.srcgen.model.impl.NCodeGenPropertyImpl @151da55
> (language: iqi-c, name: GENERATOR_VERSION, value: )
>
> this is a list of the content objects of the right element :
> *
> mailto: com.st.hed.impala.src.model.impl.ImpalaInputParameterBoxImpl @d53356
> (name: Sequence_input, version: 1.0.0, description: Description is not
> filled, isReadOnly: false, isChangedFromLib: false) (debugMode: NoDebug,
> debugTextFormat: null, debugHeader: null, debugTrailer: null,
> debugDumpDestination: null)
>
> this is a list of the content objects of the right element :
> *
> mailto:com.st.hed.iqi.impala.srcgen.model.impl.CompositeBoxImpl@877294
> (name: CB, version: 1.0.0, description: Description is not filled,
> isReadOnly: false, isChangedFromLib: false)
>
> this is a list of the content objects of the right element :
> *
> mailto:com.st.hed.impala.src.model.impl.ImpalaFrameGathererImpl@1fa522d
> (increment: 1, channel: Y, offsetInSequence: 0) (name: FG, version:
> 1.0.0, description: Description is not filled, isReadOnly: false,
> isChangedFromLib: false, debugMode: NoDebug, debugTextFormat: null,
> debugHeader: null, debugTrailer: null, debugDumpDestination: null,
> newRootDirectory: null, newRadix: null)
>
> this is a list of the content objects of the right element :
> *
> mailto:com.st.hed.impala.src.model.impl.ImpalaFrameGathererImpl@129271e
> (increment: 1, channel: Y, offsetInSequence: 0) (name: FG1, version:
> 1.0.0, description: Description is not filled, isReadOnly: false,
> isChangedFromLib: false, debugMode: NoDebug, debugTextFormat: null,
> debugHeader: null, debugTrailer: null, debugDumpDestination: null,
> newRootDirectory: null, newRadix: null)
>
> this is a list of the content objects of the right element :
> *
> mailto:com.st.hed.impala.src.model.impl.ImpalaFrameSelectorImpl@c73ac2
> (increment: 1, channel: Y, offsetInSequence: 0) (name: FS, version:
> 1.0.0, description: Description is not filled, isReadOnly: false,
> isChangedFromLib: false, debugMode: NoDebug, debugTextFormat: null,
> debugHeader: null, debugTrailer: null, debugDumpDestination: null)
>
> this is a list of the content objects of the right element :
> *
> mailto:com.st.hed.iqi.impala.srcgen.model.impl.NSequenceImpl@1e2b2a6
> (name: input, version: 1.0.0, description: Description is not filled,
> isReadOnly: false, isChangedFromLib: false) (width: 1, height: 1,
> sampling: YUV444, startFrameNb: 0, NbOfFrames: 1, SequenceRoot: ,
> SequenceRadix: , storageType: SGP, isProgressive: true, isTopFirst:
> true, dynamic: 8)
>
> this is a list of the content objects of the right element :
> *
> mailto:com.st.hed.iqi.impala.srcgen.model.impl.CompositeBoxImpl@6d2d52
> (name: lib, version: 1.0.0, description: This is the container for the
> library types, isReadOnly: false, isChangedFromLib: false)
>
> Unmatched Elements(size) = 8
>
> UnMatchElem is :
> mailto: org.eclipse.emf.compare.match.metamodel.impl.UnMatchElementI mpl @c183ea
>
>
> * mailto:org.eclipse.gmf.runtime.notation.impl.DiagramImpl@1ea08e7
> (visible: true, type: impala-metamodel, mutable: false) (name: ,
> measurementUnit: Pixel)
> UnMatchElem is :
> mailto: org.eclipse.emf.compare.match.metamodel.impl.UnMatchElementI mpl @bbb074
>
>
> *
> mailto: com.st.hed.iqi.impala.srcgen.model.impl.NCodeGenPropertyImpl @1c3599d
> (language: iqi-c, name: GEN_UNIQUE_NAME, value: )
> UnMatchElem is :
> mail
Previous Topic:[Ecore Tools] Diagram editor: reflect model changes automatically
Next Topic:[xtext] "EPackage is used twice" or How to import several packages of the same ecore model
Goto Forum:
  


Current Time: Tue Apr 23 08:36:30 GMT 2024

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

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

Back to the top