Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » EMF » [CDO] clarification on how to delete an object contained in a CDOResource.
[CDO] clarification on how to delete an object contained in a CDOResource. [message #758952] Fri, 25 November 2011 11:40 Go to next message
Christophe Bouhier is currently offline Christophe BouhierFriend
Messages: 937
Registered: July 2009
Senior Member
Hello,

I am deleting an object from it's resource like this:


Resource resource = eObject.eResource();
resource.getContents().remove(eObject);

When committing, I get a danlingRef Exception.

Caused by: org.eclipse.emf.cdo.util.DanglingReferenceException: The
object
"NetXResource?(com.netxforge.netxstudio.library.impl.NetXResourceImpl)"
is not contained in a resource

So how do I get rid of the object, as it still exists, and it's not in a
resource and it's in state TRANSIENT?


When I use the EMF.edit DeleteCommand, the commit gives no problem.
What is different, I have checked the execute() in RemoveCommand, and it
does, as I do. What am I overlooking?


thank you,
Christophe Bouhier
Re: [CDO] clarification on how to delete an object contained in a CDOResource. [message #758968 is a reply to message #758952] Fri, 25 November 2011 12:16 Go to previous messageGo to next message
Christophe Bouhier is currently offline Christophe BouhierFriend
Messages: 937
Registered: July 2009
Senior Member
Just noticed, that the state of the object after deletion with the
EMF.Edit RemoveCommand is CLEAN, not TRANSIENT. I think this could be
the reason I have this problem,

Question remains, how do I mimic the RemoveCommand, so my object endsup
in the correct state?

thank you,
Christophe


On 25-11-11 12:40, Christophe Bouhier wrote:
> Hello,
>
> I am deleting an object from it's resource like this:
>
>
> Resource resource = eObject.eResource();
> resource.getContents().remove(eObject);
>
> When committing, I get a danlingRef Exception.
>
> Caused by: org.eclipse.emf.cdo.util.DanglingReferenceException: The
> object
> "NetXResource?(com.netxforge.netxstudio.library.impl.NetXResourceImpl)"
> is not contained in a resource
>
> So how do I get rid of the object, as it still exists, and it's not in a
> resource and it's in state TRANSIENT?
>
>
> When I use the EMF.edit DeleteCommand, the commit gives no problem.
> What is different, I have checked the execute() in RemoveCommand, and it
> does, as I do. What am I overlooking?
>
>
> thank you,
> Christophe Bouhier
>
Re: [CDO] clarification on how to delete an object contained in a CDOResource. [message #759086 is a reply to message #758952] Sat, 26 November 2011 08:40 Go to previous messageGo to next message
Eike Stepper is currently offline Eike StepperFriend
Messages: 6682
Registered: July 2009
Senior Member
Am 25.11.2011 12:40, schrieb Christophe Bouhier:
> Hello,
>
> I am deleting an object from it's resource like this:
>
>
> Resource resource = eObject.eResource();
> resource.getContents().remove(eObject);
>
> When committing, I get a danlingRef Exception.
>
> Caused by: org.eclipse.emf.cdo.util.DanglingReferenceException: The object
> "NetXResource?(com.netxforge.netxstudio.library.impl.NetXResourceImpl)" is not contained in a resource
>
> So how do I get rid of the object, as it still exists, and it's not in a resource and it's in state TRANSIENT?
All that sounds like the expected *EMF* behavior when you detach (delete) an object from the persistent tree(s) but
still have some other persistent objects pointing to the detached one. Detached CDOObjects have the CDOState.TRANSIENT
when they're not attached.

You must either attach the referenced object somewhere or delete all references to it. Note that (just like in pure EMF)
objects could point to the detached object although they're not even loaded which can later lead to the situation
described in the recent newsgroup thread "DanglingReferenceException or
org.eclipse.emf.cdo.util.ObjectNotFoundException". CDO offers API to determine all these referers:

org.eclipse.emf.cdo.view.CDOView.queryXRefs(CDOObject, EReference...)
org.eclipse.emf.cdo.view.CDOView.queryXRefs(Set<CDOObject>, EReference...)
org.eclipse.emf.cdo.view.CDOView.queryXRefsAsync(Set<CDOObject>, EReference...)

>
>
> When I use the EMF.edit DeleteCommand, the commit gives no problem.
> What is different, I have checked the execute() in RemoveCommand, and it does, as I do. What am I overlooking?
Nothing I guess ;-)

I'm not an expert with EMF.Edit but AFAIK the delete command uses a normal EMF cross referencer to detect and remove
*local* cross references.

Cheers
/Eike

----
http://www.esc-net.de
http://thegordian.blogspot.com
http://twitter.com/eikestepper


Re: [CDO] clarification on how to delete an object contained in a CDOResource. [message #759112 is a reply to message #759086] Sat, 26 November 2011 13:48 Go to previous messageGo to next message
Christophe Bouhier is currently offline Christophe BouhierFriend
Messages: 937
Registered: July 2009
Senior Member
Hi Eike,

Thank you for your response. For this object I was absolutely sure
nothing referred to it, so I didn't apply the xreferencer, but with your
explanation I am not so sure any more.

I actually made a specialized command which uses the CDO xreferences, to
find objects. It however introduces some substantial delay, when
deleting large amounts of objects. I am hoping to somehow reduce the
search scope, by setting the target EReference, what I would need is
some util, to find out which EReferences exist towards this object.

For whom ever is interested, see attached specialized command.

rgds Christophe



On 26-11-11 09:40, Eike Stepper wrote:
> Am 25.11.2011 12:40, schrieb Christophe Bouhier:
>> Hello,
>>
>> I am deleting an object from it's resource like this:
>>
>>
>> Resource resource = eObject.eResource();
>> resource.getContents().remove(eObject);
>>
>> When committing, I get a danlingRef Exception.
>>
>> Caused by: org.eclipse.emf.cdo.util.DanglingReferenceException: The
>> object
>> "NetXResource?(com.netxforge.netxstudio.library.impl.NetXResourceImpl)" is
>> not contained in a resource
>>
>> So how do I get rid of the object, as it still exists, and it's not in
>> a resource and it's in state TRANSIENT?
> All that sounds like the expected *EMF* behavior when you detach
> (delete) an object from the persistent tree(s) but still have some other
> persistent objects pointing to the detached one. Detached CDOObjects
> have the CDOState.TRANSIENT when they're not attached.
>
> You must either attach the referenced object somewhere or delete all
> references to it. Note that (just like in pure EMF) objects could point
> to the detached object although they're not even loaded which can later
> lead to the situation described in the recent newsgroup thread
> "DanglingReferenceException or
> org.eclipse.emf.cdo.util.ObjectNotFoundException". CDO offers API to
> determine all these referers:
>
> org.eclipse.emf.cdo.view.CDOView.queryXRefs(CDOObject, EReference...)
> org.eclipse.emf.cdo.view.CDOView.queryXRefs(Set<CDOObject>, EReference...)
> org.eclipse.emf.cdo.view.CDOView.queryXRefsAsync(Set<CDOObject>,
> EReference...)
>
>>
>>
>> When I use the EMF.edit DeleteCommand, the commit gives no problem.
>> What is different, I have checked the execute() in RemoveCommand, and
>> it does, as I do. What am I overlooking?
> Nothing I guess ;-)
>
> I'm not an expert with EMF.Edit but AFAIK the delete command uses a
> normal EMF cross referencer to detect and remove *local* cross references.
>
> Cheers
> /Eike
>
> ----
> http://www.esc-net.de
> http://thegordian.blogspot.com
> http://twitter.com/eikestepper
>
>


/*******************************************************************************
* Copyright (c) Nov 26, 2011 NetXForge.
*
* This program is free software: you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details. You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
* Contributors: Christophe Bouhier - initial API and implementation and/or
* initial documentation
*******************************************************************************/
package com.netxforge.netxstudio.screens.editing.actions;

import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;

import org.eclipse.emf.cdo.CDOObject;
import org.eclipse.emf.cdo.CDOObjectReference;
import org.eclipse.emf.cdo.view.CDOView;
import org.eclipse.emf.common.command.Command;
import org.eclipse.emf.common.command.CompoundCommand;
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.edit.EMFEditPlugin;
import org.eclipse.emf.edit.command.CommandParameter;
import org.eclipse.emf.edit.command.RemoveCommand;
import org.eclipse.emf.edit.command.SetCommand;
import org.eclipse.emf.edit.domain.AdapterFactoryEditingDomain;
import org.eclipse.emf.edit.domain.EditingDomain;

import com.google.common.collect.Lists;

public class WarningDeleteCommand extends CompoundCommand {

/**
* This constructs a command that deletes the objects in the given
* collection.
*/
public WarningDeleteCommand(EditingDomain domain, Collection<?> collection) {
super(0, LABEL, DESCRIPTION);
this.domain = domain;
this.collection = collection;
}

/**
* This creates a command that deletes the given object.
*/
public static Command create(EditingDomain domain, Object object) {
return create(domain, Collections.singleton(object));
}

/**
* This creates a command that deletes the objects in the given collection.
*/
public static Command create(EditingDomain domain,
final Collection<?> collection) {
return domain.createCommand(WarningDeleteCommand.class,
new CommandParameter(null, null, collection));
}

/**
* This caches the label.
*/
protected static final String LABEL = EMFEditPlugin.INSTANCE
.getString("_UI_DeleteCommand_label");

/**
* This caches the description.
*/
protected static final String DESCRIPTION = EMFEditPlugin.INSTANCE
.getString("_UI_DeleteCommand_description");

/**
* This is the editing domain in which this command operates.
*/
protected EditingDomain domain;

/**
* This is the collection of objects to be deleted.
*/
protected Collection<?> collection;

/**
* This returns the collection of objects to be deleted.
*/
public Collection<?> getCollection() {
return collection;
}

@Override
protected boolean prepare() {
prepareCommand();
return super.prepare();
}

protected void prepareCommand() {
append(RemoveCommand.create(domain, collection));
}

@Override
public void execute() {
Collection<EObject> eObjects = getObjects();

List<CDOObjectReference> xRefs = this.findReferencesGlobally(eObjects);

super.execute();

if (xRefs != null) {
for (CDOObjectReference xref : xRefs) {

EObject referencingEObject = xref.getSourceObject();
EObject eObject = xref.getTargetObject();

// Do not delete referring objects which are scheduled for deletion themselves.
if (!eObjects.contains(referencingEObject)) {
EStructuralFeature eStructuralFeature = xref
.getSourceFeature();
if (eStructuralFeature.isMany()) {


// Hack, has remove command doesn't work sometimes....
Command cmd = RemoveCommand
.create(domain, referencingEObject,
eStructuralFeature, eObject);
if(cmd.canExecute()){
appendAndExecute(cmd);
}else{
Object eGet = referencingEObject.eGet(eStructuralFeature);
if(eGet instanceof List<?>){
((List<?>)eGet).remove(eObject);
}
}

} else {
appendAndExecute(SetCommand.create(domain,
referencingEObject, eStructuralFeature,
SetCommand.UNSET_VALUE));
}
}

}
}
}

/**
* Creates a collection of contained objects to be deleted.
*
* @return
*/
public Collection<EObject> getObjects() {

Collection<EObject> eObjects = new LinkedHashSet<EObject>();
for (Object wrappedObject : collection) {
Object object = AdapterFactoryEditingDomain.unwrap(wrappedObject);
if (object instanceof EObject) {
eObjects.add((EObject) object);
for (Iterator<EObject> j = ((EObject) object).eAllContents(); j
.hasNext();) {
eObjects.add(j.next());
}
} else if (object instanceof Resource) {
for (Iterator<EObject> j = ((Resource) object).getAllContents(); j
.hasNext();) {
eObjects.add(j.next());
}
}
}
return eObjects;
}

public List<CDOObjectReference> getUsage(Collection<EObject> eObjects) {
return findReferencesGlobally(eObjects);
}

private List<CDOObjectReference> findReferencesGlobally(
Collection<EObject> eObjects) {
List<CDOObjectReference> queryXRefs = Lists.newArrayList();
for (EObject o : eObjects) {
if (o instanceof CDOObject) {
CDOView cdoView = ((CDOObject) o).cdoView();
try {
List<CDOObjectReference> runRefs = cdoView.queryXRefs(
(CDOObject) o, new EReference[] {});

for (CDOObjectReference runRef : runRefs) {
// Iterate through the already found queryRefs, compare
// source to look for double entries.
// if(!exists(queryXRefs, runRef)){
// queryXRefs.add(runRef);
// }
queryXRefs.add(runRef);
}

} catch (Exception e) {
e.printStackTrace();
// The query sometimes throws exeception, if i.e an entity
// can't be found..
// EClass ExpressionResult does not have an entity name, has
// it been mapped to Hibernate?
}
}
}
return queryXRefs;
}

boolean exists(List<CDOObjectReference> refList, CDOObjectReference ref) {
boolean found = false;
// and target.
for (CDOObjectReference qRef : refList) {
if ((ref.getSourceObject() == qRef.getSourceObject())
&& (ref.getTargetObject() == qRef.getTargetObject())) {
found = true;
break;
}
}
return found;
}

}
Re: [CDO] clarification on how to delete an object contained in a CDOResource. [message #759159 is a reply to message #759112] Sun, 27 November 2011 07:48 Go to previous messageGo to next message
Eike Stepper is currently offline Eike StepperFriend
Messages: 6682
Registered: July 2009
Senior Member
Am 26.11.2011 14:48, schrieb Christophe Bouhier:
> Hi Eike,
>
> Thank you for your response. For this object I was absolutely sure nothing referred to it, so I didn't apply the
> xreferencer, but with your explanation I am not so sure any more.
>
> I actually made a specialized command which uses the CDO xreferences, to find objects. It however introduces some
> substantial delay, when deleting large amounts of objects. I am hoping to somehow reduce the search scope, by setting
> the target EReference, what I would need is some util, to find out which EReferences exist towards this object.
>
> For whom ever is interested, see attached specialized command.
I see that your command executes an xref query against the backend for each of the N objects individually. It may be N
times faster to execute a single query for all N target objects at the same time:

org.eclipse.emf.cdo.view.CDOView.queryXRefs(Set<CDOObject>, EReference...)
org.eclipse.emf.cdo.view.CDOView.queryXRefsAsync(Set<CDOObject>, EReference...)

Cheers
/Eike

----
http://www.esc-net.de
http://thegordian.blogspot.com
http://twitter.com/eikestepper


>
> rgds Christophe
>
>
>
> On 26-11-11 09:40, Eike Stepper wrote:
>> Am 25.11.2011 12:40, schrieb Christophe Bouhier:
>>> Hello,
>>>
>>> I am deleting an object from it's resource like this:
>>>
>>>
>>> Resource resource = eObject.eResource();
>>> resource.getContents().remove(eObject);
>>>
>>> When committing, I get a danlingRef Exception.
>>>
>>> Caused by: org.eclipse.emf.cdo.util.DanglingReferenceException: The
>>> object
>>> "NetXResource?(com.netxforge.netxstudio.library.impl.NetXResourceImpl)" is
>>> not contained in a resource
>>>
>>> So how do I get rid of the object, as it still exists, and it's not in
>>> a resource and it's in state TRANSIENT?
>> All that sounds like the expected *EMF* behavior when you detach
>> (delete) an object from the persistent tree(s) but still have some other
>> persistent objects pointing to the detached one. Detached CDOObjects
>> have the CDOState.TRANSIENT when they're not attached.
>>
>> You must either attach the referenced object somewhere or delete all
>> references to it. Note that (just like in pure EMF) objects could point
>> to the detached object although they're not even loaded which can later
>> lead to the situation described in the recent newsgroup thread
>> "DanglingReferenceException or
>> org.eclipse.emf.cdo.util.ObjectNotFoundException". CDO offers API to
>> determine all these referers:
>>
>> org.eclipse.emf.cdo.view.CDOView.queryXRefs(CDOObject, EReference...)
>> org.eclipse.emf.cdo.view.CDOView.queryXRefs(Set<CDOObject>, EReference...)
>> org.eclipse.emf.cdo.view.CDOView.queryXRefsAsync(Set<CDOObject>,
>> EReference...)
>>
>>>
>>>
>>> When I use the EMF.edit DeleteCommand, the commit gives no problem.
>>> What is different, I have checked the execute() in RemoveCommand, and
>>> it does, as I do. What am I overlooking?
>> Nothing I guess ;-)
>>
>> I'm not an expert with EMF.Edit but AFAIK the delete command uses a
>> normal EMF cross referencer to detect and remove *local* cross references.
>>
>> Cheers
>> /Eike
>>
>> ----
>> http://www.esc-net.de
>> http://thegordian.blogspot.com
>> http://twitter.com/eikestepper
>>
>>
>


Re: [CDO] clarification on how to delete an object contained in a CDOResource. [message #759160 is a reply to message #759159] Sun, 27 November 2011 07:50 Go to previous message
Eike Stepper is currently offline Eike StepperFriend
Messages: 6682
Registered: July 2009
Senior Member
BTW, these are equivalent:

cdoView.queryXRefs((CDOObject) o, new EReference[] {});
cdoView.queryXRefs((CDOObject) o);

Cheers
/Eike

----
http://www.esc-net.de
http://thegordian.blogspot.com
http://twitter.com/eikestepper



Am 27.11.2011 08:48, schrieb Eike Stepper:
> Am 26.11.2011 14:48, schrieb Christophe Bouhier:
>> Hi Eike,
>>
>> Thank you for your response. For this object I was absolutely sure nothing referred to it, so I didn't apply the
>> xreferencer, but with your explanation I am not so sure any more.
>>
>> I actually made a specialized command which uses the CDO xreferences, to find objects. It however introduces some
>> substantial delay, when deleting large amounts of objects. I am hoping to somehow reduce the search scope, by setting
>> the target EReference, what I would need is some util, to find out which EReferences exist towards this object.
>>
>> For whom ever is interested, see attached specialized command.
> I see that your command executes an xref query against the backend for each of the N objects individually. It may be N
> times faster to execute a single query for all N target objects at the same time:
>
> org.eclipse.emf.cdo.view.CDOView.queryXRefs(Set<CDOObject>, EReference...)
> org.eclipse.emf.cdo.view.CDOView.queryXRefsAsync(Set<CDOObject>, EReference...)
>
> Cheers
> /Eike
>
> ----
> http://www.esc-net.de
> http://thegordian.blogspot.com
> http://twitter.com/eikestepper
>
>
>>
>> rgds Christophe
>>
>>
>>
>> On 26-11-11 09:40, Eike Stepper wrote:
>>> Am 25.11.2011 12:40, schrieb Christophe Bouhier:
>>>> Hello,
>>>>
>>>> I am deleting an object from it's resource like this:
>>>>
>>>>
>>>> Resource resource = eObject.eResource();
>>>> resource.getContents().remove(eObject);
>>>>
>>>> When committing, I get a danlingRef Exception.
>>>>
>>>> Caused by: org.eclipse.emf.cdo.util.DanglingReferenceException: The
>>>> object
>>>> "NetXResource?(com.netxforge.netxstudio.library.impl.NetXResourceImpl)" is
>>>> not contained in a resource
>>>>
>>>> So how do I get rid of the object, as it still exists, and it's not in
>>>> a resource and it's in state TRANSIENT?
>>> All that sounds like the expected *EMF* behavior when you detach
>>> (delete) an object from the persistent tree(s) but still have some other
>>> persistent objects pointing to the detached one. Detached CDOObjects
>>> have the CDOState.TRANSIENT when they're not attached.
>>>
>>> You must either attach the referenced object somewhere or delete all
>>> references to it. Note that (just like in pure EMF) objects could point
>>> to the detached object although they're not even loaded which can later
>>> lead to the situation described in the recent newsgroup thread
>>> "DanglingReferenceException or
>>> org.eclipse.emf.cdo.util.ObjectNotFoundException". CDO offers API to
>>> determine all these referers:
>>>
>>> org.eclipse.emf.cdo.view.CDOView.queryXRefs(CDOObject, EReference...)
>>> org.eclipse.emf.cdo.view.CDOView.queryXRefs(Set<CDOObject>, EReference...)
>>> org.eclipse.emf.cdo.view.CDOView.queryXRefsAsync(Set<CDOObject>,
>>> EReference...)
>>>
>>>>
>>>>
>>>> When I use the EMF.edit DeleteCommand, the commit gives no problem.
>>>> What is different, I have checked the execute() in RemoveCommand, and
>>>> it does, as I do. What am I overlooking?
>>> Nothing I guess ;-)
>>>
>>> I'm not an expert with EMF.Edit but AFAIK the delete command uses a
>>> normal EMF cross referencer to detect and remove *local* cross references.
>>>
>>> Cheers
>>> /Eike
>>>
>>> ----
>>> http://www.esc-net.de
>>> http://thegordian.blogspot.com
>>> http://twitter.com/eikestepper
>>>
>>>
>>


Previous Topic:Extending an emf model & the generated editor?
Next Topic:Map.Entry, EMap & opposite reference
Goto Forum:
  


Current Time: Thu Apr 25 22:54:32 GMT 2024

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

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

Back to the top