Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.

Bug 385043

Summary: Problem with eSetResource(null, null) in EMF from GMF in Eclipse Juno
Product: [Modeling] GMF-Runtime Reporter: Tiziano Leidi <tleidi>
Component: GeneralAssignee: Project Inbox <gmf-runtime-inbox>
Status: CLOSED DUPLICATE QA Contact:
Severity: blocker    
Priority: P3 CC: ahunter.eclipse, apupier, tleidi
Version: 2.4   
Target Milestone: ---   
Hardware: All   
OS: All   
Whiteboard:

Description Tiziano Leidi CLA 2012-07-13 08:13:43 EDT
Hi People,
we installed the new Eclipse 4.2 and we are currently facing the following problem in GMF code.

In the class [code]ClipboardSupportUtil[/code] (GMF) there is the following method.

[code]	public static EObject appendEObjectAt(EObject eObject,
			EReference reference, EObject referencedObject) {
		if (isOkToAppendEObjectAt(eObject, reference, referencedObject) == false) {
			return null;
		}
		if (reference.isContainment()) {
            ((InternalEObject)referencedObject).eSetResource(null,null);
			sendCreateEvent(referencedObject);
		}
		((Collection) eObject.eGet(reference)).add(referencedObject);
		return referencedObject;
	}[/code]

which calls [code]eSetResource(null,null)[/code]

The implementation of [code]eSetResource [/code]has changed in EMF from the previous version, ... in BasicEObjectImpl now there is the following new implementation

[code]  public NotificationChain eSetResource(Resource.Internal resource, NotificationChain notifications)
  {
    Resource.Internal oldResource = eDirectResource();
    // When setting the resource to null we assume that detach has already been called in the resource implementation
    //
    if (oldResource != null && resource != null)
    {
      notifications = ((InternalEList<?>)oldResource.getContents()).basicRemove(this, notifications);
      oldResource.detached(this);
    }[/code]

which previously was(Eclipse Indigo)

[code]  public NotificationChain eSetResource(Resource.Internal resource, NotificationChain notifications)
  {
    Resource.Internal oldResource = eDirectResource();
    if (oldResource != null)
    {
      notifications = ((InternalEList<?>)oldResource.getContents()).basicRemove(this, notifications);

      // When setting the resource to null we assume that detach has already been called in the resource implementation
      //
      if (resource != null)
      {
        oldResource.detached(this);
      }
    }[/code]

As a consequence, the behavior is different for a call [code]eSetResource(null,null)[/code] and the object is not removed from the resource with [code]basicRemove[/code] as it previously was.

I had the following answer from Ed Merks:

This change was made to fix <a
href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=346805">https://bugs.eclipse.org/bugs/show_bug.cgi?id=346805</a>.

This API was never intended to be called directly by clients:
/**
* Sets this object to be directly contained by the resource
* and returns accumulated notifications.
* This is only done as the inverse of {@link
Resource#getContents()}&lt;code&gt;.add(this)&lt;/code&gt;.
* @return accumulated notifications.
*/
NotificationChain eSetResource(Resource.Internal
resource, NotificationChain notifications);

The GMF code should be using resource.getContents().remove(...).
  
I.e., perhaps it should be
referencedObject.eResource().getContents().remove(referencedObject)
though I'm not sure if the referenced object is necessarily
contained directly in a resource so maybe it should check that
eResource() isn't null.

You should open a bugzilla for the GMF runtime to fix this.

...

Many thanks
Tiziano
Comment 1 Anthony Hunter CLA 2012-07-13 11:54:53 EDT
Can you confirm what functional area is broken? How do you reproduce this issue in an editor based on the GMF Runtime?
Comment 2 Tiziano Leidi CLA 2012-07-16 03:04:34 EDT
(In reply to comment #1)
> Can you confirm what functional area is broken? How do you reproduce this issue
> in an editor based on the GMF Runtime?

Yes, at the functional level, the problem is related with paste operations (class PasteChildOperation and its sub classes). When trying to use paste actions in editors (e.g. paste of an EObject into another one - many references with containment) everything seems to work correctly, but at the end objects are not added.

This is caused by the fact that the EObject is not correctly removed from the LoadingEMFResource (class PasteIntoPartentOperation) and when the resource is unloaded the EObject is removed from the target EObject ant its eContainer is set to null).

Please let me know if you need some more information ...
Comment 3 Aurelien Pupier CLA 2012-09-22 12:02:48 EDT

*** This bug has been marked as a duplicate of bug 390022 ***