Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » EMF » issue with EMF proxy, EOpposite, and Adapters(An EMF object with EOpposite relations is not updated when a Proxy is Replaced by a real EObject)
issue with EMF proxy, EOpposite, and Adapters [message #1802952] Tue, 19 February 2019 14:50 Go to next message
Patrik Suzzi is currently offline Patrik SuzziFriend
Messages: 91
Registered: June 2010
Location: Urdorf, Switzerland
Member

Hi All,

I have an issue with EMF proxy, EOpposite, and Adapters and I would like to get advice from the community.

In my model, I have a Mapping object referencing two classes: ClassA and ClassB. These mappings are EOpposites. (please, see the image below representing the model)

index.php/fa/34919/0/

When running, we could have Proxies, and because of this we hit a bug:

  • When we set a proxy in our Mapping Object, the framework sets the proxy as EOpposite.
  • When the framework replaces the proxy with a real EObject, the Opposite relation is gone. (BUG)


I took a look at the generated code, and I observed that:
Mapping.setFirst(.) correctly removes and adds again the inverses calling eInverseRemove() and eInverseAdd() (see snippet below)

    public void setFirst(ElementA newFirst) {
        if (newFirst != first) {
            NotificationChain msgs = null;
            if (first != null)
                msgs = ((InternalEObject)first).
                    eInverseRemove(this, ApplicationPackage.ELEMENT_A__MAPPINGS_A, ElementA.class, msgs);
            if (newFirst != null)
                msgs = ((InternalEObject)newFirst).
                    eInverseAdd(this, ApplicationPackage.ELEMENT_A__MAPPINGS_A, ElementA.class, msgs);
            msgs = basicSetFirst(newFirst, msgs);
            if (msgs != null) msgs.dispatch();
        }
        else if (eNotificationRequired())
            eNotify(new ENotificationImpl(this, Notification.SET, ApplicationPackage.MAPPING__FIRST, newFirst, newFirst));
    }


but in the Mapping.getFirst(), the proxy object is replaced by the actual EObject without unsetting/setting again the inverse.
(see first = (ElementA)eResolveProxy(oldFirst); in the snippet below)

    public ElementA getFirst() {
        if (first != null && first.eIsProxy()) {
            InternalEObject oldFirst = (InternalEObject)first;
            first = (ElementA)eResolveProxy(oldFirst);
            if (first != oldFirst) {
                if (eNotificationRequired())
                    eNotify(new ENotificationImpl(this, Notification.RESOLVE, ApplicationPackage.MAPPING__FIRST, oldFirst, first));
            }
        }
        return first;
    }


I found a way to solve our bug, by editing the generated code above:

  • replacing first = (ElementA)eResolveProxy(oldFirst);
  • with setFirst((ElementA)eResolveProxy(oldFirst));


This solution is not acceptable as we should not edit the EMF generated code, so I found two possible alternatives

(1) There must be a special flag in EMF genmodel, to tell EMF to eInverseRemove/eInverseAdd when a proxy is replaced by an EObject
(2) I should add an Adapter to reacto to Notification.RESOLVE, and call eInverseRemove/eInverseAdd when a proxy is replaced.

However, I am missing details to implement any of the two above solutions, hence I have two questions:

(1)
I don't know if there is a flag to tell EMF to call eInverseRemove() and eInverseAdd() when replacing a Proxy Object with an Actual EObject.
-> Does someone knows if such flag exists?

(2)
To add an Adapter to an EObject instance, I should modify a Generated Factory class. Again, I prefer not to modify generated code.
-> Is there a best practice way to attach an Adapter to all the instances of Generated classes, in order to avoid polluting generated code?

Thanks in advance for your time and consideration,

Best Regards,
Patrik
Re: issue with EMF proxy, EOpposite, and Adapters [message #1802977 is a reply to message #1802952] Wed, 20 February 2019 04:20 Go to previous messageGo to next message
Ed Merks is currently offline Ed MerksFriend
Messages: 30688
Registered: July 2009
Senior Member
One thing to note up front is that if you have a bidirectional, proxy-resolving, cross reference, both ends must be serialized and hence both ends will initially have a proxy as the opposite. When either proxy is resolved, there is no need to resolve the other end because that resolution will happen when the other end's other proxy is resolved. But it sounds like you are manually setting a proxy, but doing so only on one end; that's just not going to work as you've observed. I'm not sure why you are manually settings proxies in the first place. What's the motivation for this approach? I.e., why are you not directly setting the value but rather populating the value with a proxy?

Re: issue with EMF proxy, EOpposite, and Adapters [message #1802983 is a reply to message #1802977] Wed, 20 February 2019 07:53 Go to previous messageGo to next message
Patrik Suzzi is currently offline Patrik SuzziFriend
Messages: 91
Registered: June 2010
Location: Urdorf, Switzerland
Member

In our application we read input from multiple XML files, so we have a CustomXMIHandler building the Root EObject.
While CustomXMIHandler is reading xml resources, it can happen that a referenced Element (i.e. ElementA) is not in the current XML file, but in another file, yet to read.
So, when a referenced element is not on the current resource, we add a Proxy in its place.
Re: issue with EMF proxy, EOpposite, and Adapters [message #1803001 is a reply to message #1802983] Wed, 20 February 2019 14:23 Go to previous messageGo to next message
Ed Merks is currently offline Ed MerksFriend
Messages: 30688
Registered: July 2009
Senior Member
The point is that there must be a proxy at both ends. Is that the case? I imagine not, otherwise you'd not have a problem...
Re: issue with EMF proxy, EOpposite, and Adapters [message #1803036 is a reply to message #1803001] Thu, 21 February 2019 10:01 Go to previous message
Patrik Suzzi is currently offline Patrik SuzziFriend
Messages: 91
Registered: June 2010
Location: Urdorf, Switzerland
Member

Yes, correct: on one side I have a proxy and on the other side a value that I populated by reading the current XML file with my XMIHandler.

IIUC, for each bidirectional, proxy-resolving, cross reference, only two cases are valid:

  • both ends are proxies
  • both ends are concrete objects

Hence, I should solve the issue by changing how I build the Object tree in my XMIHandler:

  • for each "bidirectional, proxy-resolving, cross reference", If I cannot resolve both ends of the relation, I should put proxies on both ends.


Thanks and Best Regards,
Patrik

[Updated on: Thu, 21 February 2019 10:01]

Report message to a moderator

Previous Topic:Merging resources that share the same root node.
Next Topic:How to use an Adapter to get all the notifications in a EMF model?
Goto Forum:
  


Current Time: Wed Dec 11 01:36:29 GMT 2019

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

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

Back to the top