Bug 234656 - EStructuralFeatureImpl.dynamicGet unsets resolved Objects when cross resource containment is used
Summary: EStructuralFeatureImpl.dynamicGet unsets resolved Objects when cross resource...
Status: VERIFIED FIXED
Alias: None
Product: EMF
Classification: Modeling
Component: Core (show other bugs)
Version: 2.3.0   Edit
Hardware: PC Windows XP
: P3 normal (vote)
Target Milestone: ---   Edit
Assignee: Marcelo Paternostro CLA
QA Contact:
URL:
Whiteboard:
Keywords: contributed
Depends on:
Blocks:
 
Reported: 2008-05-29 11:30 EDT by Florian Thienel CLA
Modified: 2008-06-03 00:13 EDT (History)
2 users (show)

See Also:


Attachments
Testcase to reproduce (2.46 KB, patch)
2008-05-29 11:30 EDT, Florian Thienel CLA
no flags Details | Diff
patch that seems to fix the problem (1.22 KB, patch)
2008-05-29 11:31 EDT, Florian Thienel CLA
no flags Details | Diff
A better fix and changes to incorporate the tests into our test suit. (5.35 KB, patch)
2008-05-29 12:49 EDT, Ed Merks CLA
no flags Details | Diff
Make sure the test is invoked from the suite (6.79 KB, patch)
2008-05-29 12:59 EDT, Ed Merks CLA
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Florian Thienel CLA 2008-05-29 11:30:15 EDT
Created attachment 102660 [details]
Testcase to reproduce

Build ID: M20080221-1800

Steps To Reproduce:
To reproduce the bug, execute the attached unit test.


More information:
The initial situation is the following:
Two objects reside in two different resources, connected with a dynamically created containment reference (e.g. "parent" and "child"), resolveProxies == true. 

When "parent" is loaded, a proxy is created for "child". On the first access to the reference, the proxy is resolved within EStructuralFeatureImpl.dynamicGet and "child" is correctly returned. 

But: dynamicGet invokes dynamicInverseRemove where the entry for child in the settings array is set to null, although it is set to the correct value ("child" instead of the proxy) before.

So, all following accesses to the reference return null instead of "child".

I attached a patch, that seems to fix the problem. The line where the proxy is replaced by the original "child" instance is moved after the invocation of dynamicInverseRemove.
Comment 1 Florian Thienel CLA 2008-05-29 11:31:50 EDT
Created attachment 102662 [details]
patch that seems to fix the problem
Comment 2 Ed Merks CLA 2008-05-29 12:49:29 EDT
Created attachment 102687 [details]
A better fix and changes to incorporate the tests into our test suit.
Comment 3 Ed Merks CLA 2008-05-29 12:52:35 EDT
I generated the model for it and looked carefully at the generated code:

  public TestClass getChild()
  {
    if (child != null && child.eIsProxy())
    {
      InternalEObject oldChild = (InternalEObject)child;
      child = (TestClass)eResolveProxy(oldChild);
      if (child != oldChild)
      {
        InternalEObject newChild = (InternalEObject)child;
        NotificationChain msgs = oldChild.eInverseRemove(this, EOPPOSITE_FEATURE_BASE - XPackage.TEST_CLASS__CHILD, null, null);
        if (newChild.eInternalContainer() == null)
        {
          msgs = newChild.eInverseAdd(this, EOPPOSITE_FEATURE_BASE - XPackage.TEST_CLASS__CHILD, null, msgs);
        }
        if (msgs != null) msgs.dispatch();
        if (eNotificationRequired())
          eNotify(new ENotificationImpl(this, Notification.RESOLVE, XPackage.TEST_CLASS__CHILD, oldChild, child));
      }
    }
    return child;
  }

It also sets the variable first, which made me wonder why the eInverseRemove didn't cause a problem.  But note how the inverse remove removes the parent from the old child, whereas in the dynamic setting implementation the old child was removed from the parent. So I changed the dynamic setting code to match this logic and that makes the test pass as well.

I totally appreciate that you provide a great JUnit test and that you tried to patch the problem as well.  THANKS!  It would be great if you could try this patch to confirm that it works before we commit it.  I'll mark this as a contribution when I commit it since we're going to use your JUnit test, which some changes.
Comment 4 Ed Merks CLA 2008-05-29 12:59:12 EDT
Created attachment 102690 [details]
Make sure the test is invoked from the suite

Marcelo, is there any other restructuring of the test that would be good?
Comment 5 Florian Thienel CLA 2008-05-30 02:48:21 EDT
(In reply to comment #3)
I tested your patch in my application and it works for me. Thank you for your fast reaction!
Comment 6 Ed Merks CLA 2008-06-02 10:44:00 EDT
The fix is committed to CVS for 2.4. A modified version of the test case was contributed.
Comment 7 Nick Boldt CLA 2008-06-03 00:13:42 EDT
Fix available in HEAD: 2.4.0RC3 (S200806021643).