Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » EMF » [Compare] How to resolve proxies
[Compare] How to resolve proxies [message #1837934] Thu, 11 February 2021 03:51 Go to next message
Denis Nikiforov is currently offline Denis NikiforovFriend
Messages: 343
Registered: August 2013
Senior Member
Hi

I'm trying to compare two diagrams (located in aird-files). The logic is as follows. Two visual elements (diagrams, nodes, edges) are equal if their target (semantic) EObjects are equal. Target EObjects are equal if their names (or ids) are equal.

The problem is that semantic EObjects are located in a separate xmi-files. EMF Compare doesn't resolve proxies to these objects. So I can't get their names.

How could I fix it?

Also what is a right way to implement such a comparision? For now I defined a custom MatchEngineFactoryImpl. It creates a DefaultMatchEngine with IdentifierEObjectMatcher with custom id-getter:

import org.eclipse.emf.compare.match.DefaultComparisonFactory;
import org.eclipse.emf.compare.match.DefaultEqualityHelperFactory;
import org.eclipse.emf.compare.match.DefaultMatchEngine;
import org.eclipse.emf.compare.match.IComparisonFactory;
import org.eclipse.emf.compare.match.IMatchEngine;
import org.eclipse.emf.compare.match.eobject.IEObjectMatcher;
import org.eclipse.emf.compare.match.eobject.IdentifierEObjectMatcher;
import org.eclipse.emf.compare.match.impl.MatchEngineFactoryImpl;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.gmf.runtime.notation.Anchor;
import org.eclipse.gmf.runtime.notation.Bendpoints;
import org.eclipse.gmf.runtime.notation.Edge;
import org.eclipse.gmf.runtime.notation.LayoutConstraint;
import org.eclipse.gmf.runtime.notation.Style;
import org.eclipse.gmf.runtime.notation.View;
import org.eclipse.sirius.diagram.DSemanticDiagram;
import org.eclipse.sirius.viewpoint.DAnalysis;
import org.eclipse.sirius.viewpoint.DRepresentationDescriptor;
import org.eclipse.sirius.viewpoint.DSemanticDecorator;
import org.eclipse.sirius.viewpoint.DView;
import org.eclipse.sirius.viewpoint.IdentifiedElement;
import org.eclipse.sirius.viewpoint.UIState;

import com.google.common.base.Function;

public class MatchEngineFactory extends MatchEngineFactoryImpl {

    public MatchEngineFactory() {
    }

    @Override
    public IMatchEngine getMatchEngine() {
        Function<EObject, String> idFunction = new Function<EObject, String>() {
            public String apply(EObject obj) {
                String id = getId(obj);
                if (id == null) {
                	return null;
                }
            	System.out.println(id + " " + obj);
                return obj.eClass().getName() + id;
            }
        };
        IEObjectMatcher matcher = new IdentifierEObjectMatcher(
        		new IdentifierEObjectMatcher(), idFunction);
        IComparisonFactory comparisonFactory = new DefaultComparisonFactory(
                new DefaultEqualityHelperFactory());
        return new DefaultMatchEngine(matcher, comparisonFactory);
    }

    private static String getId(EObject obj) {
    	// GMF objects
        if (obj instanceof Edge) {
        	return getId(((View) obj).getElement());
        }
        if (obj instanceof View) {
        	return getId(((View) obj).getElement());
        }
        if (obj instanceof LayoutConstraint) {
        	return null;
        }
        if (obj instanceof Style) {
        	return null;
        }
        if (obj instanceof Bendpoints) {
        	return null;
        }
        if (obj instanceof Anchor) {
        	return null;
        }

        // Sirius objects
    	if (obj instanceof DAnalysis) {
    		return "5387ba35-1f2d-4614-b29f-874ef97b27f6-DAnalysis";
    	}
    	if (obj instanceof DView) {
    		return "5387ba35-1f2d-4614-b29f-874ef97b27f6-DView";
    	}
    	if (obj instanceof DRepresentationDescriptor) {
    		EObject target = ((DRepresentationDescriptor) obj).getTarget();
    		EcoreUtil.resolve(target, (EObject) null);
    		return getId(target);
    	}
    	if (obj instanceof DSemanticDiagram) {
    		System.out.println(((DSemanticDiagram) obj).getTarget());
    		System.out.println(getId(((DSemanticDiagram) obj).getTarget()));
    		return getId(((DSemanticDiagram) obj).getTarget());
    	}
    	if (obj instanceof DSemanticDecorator) {
    		return getId(((DSemanticDecorator) obj).getTarget());
    	}
        if (obj instanceof IdentifiedElement) {
            return ((IdentifiedElement) obj).getUid();
        }
        if (obj instanceof UIState) {
            return null;
        }

        // Other Ecore objects
        EStructuralFeature idFeature = obj.eClass().getEStructuralFeature("id"); //$NON-NLS-1$
        if (idFeature == null) {
            return null;
        }
        Object id = obj.eGet(idFeature);
        if (!(id instanceof String)) {
            return null;
        }
        String result = (String) id;
        if (result.isEmpty()) {
            return null;
        }
        return result;
    }

}


The following code returns null, because the target object is unresolved proxy and it's attributes aren't loaded:
    	if (obj instanceof DSemanticDecorator) {
    		return getId(((DSemanticDecorator) obj).getTarget());
    	}


Actually there are a lot of ugly hacks. The method returns the same id for any DAnalysis or DView. So they are always equal.

Maybe it's better to implement a custom IEqualityHelper?
Re: [Compare] How to resolve proxies [message #1837957 is a reply to message #1837934] Thu, 11 February 2021 10:06 Go to previous messageGo to next message
Denis Nikiforov is currently offline Denis NikiforovFriend
Messages: 343
Registered: August 2013
Senior Member
According to the documentation https://www.eclipse.org/emf/compare/documentation/latest/developer/developer-guide.html#Proxy_Resolution it seems that it is impossible to compare objects from one resource using information from another resource:

Quote:
EMF Compare will never resolve proxies except for those strictly necessary. Whatever the phase of comparison, we strive to never hold the whole model in memory.

For example, I can't compare diagram nodes (located in aird-file) using target objects of these nodes (located in a separate xmi-file)? Because both aird and xmi files will not be holded in memory at the same time?

What means "strictly necessary to resolve proxies" in the quote? Is it possible to force EMF Compare to resolve proxies from aird to xmi-files? And to force it to keep the whole logical model (including diagrams and underlying semantic objects) in memory?
Re: [Compare] How to resolve proxies [message #1837973 is a reply to message #1837957] Thu, 11 February 2021 14:42 Go to previous message
Denis Nikiforov is currently offline Denis NikiforovFriend
Messages: 343
Registered: August 2013
Senior Member
There is a one more scenario. I'm trying to compare two EObjects in a model. Some of the contents of the EObjects is moved into separate files using (Sirius Control or EMF Control Command):
            <entities name="some object">
              <details xsi:type="some:type" href="link to external entity"/>
            </entities>

The problem is that EObjects contained in the separate files are ignored during comparision.

Using debug I've found the following method in the FilterComparisonScope class:
	public Iterator<? extends EObject> getChildren(EObject eObject) {
		if (eObject == null) {
			return emptyIterator();
		}

		final Iterator<EObject> properContent = EcoreUtil.getAllProperContents(eObject, false);
		final Iterator<EObject> filter = Iterators.filter(properContent, eObjectContentFilter);

		final Iterator<EObject> uriInitializingIt = new URIInitializingIterator<EObject>(eObject, filter);

		return Iterators.unmodifiableIterator(uriInitializingIt);
	}

The 2nd parameter for EcoreUtil.getAllProperContents() is false. So it never resolve proxies.

I can't find any way to define custom IComparisonScope or to force EMF Compare to resolve proxies.
Previous Topic:[xcore] Reference types from UML2 meta-model in xcore
Next Topic:[CDO] Basic use of CDO programmatically
Goto Forum:
  


Current Time: Thu Apr 18 23:21:41 GMT 2024

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

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

Back to the top