Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » EMF » Remove dangling references
Remove dangling references [message #1766870] Wed, 28 June 2017 11:57 Go to next message
Jim 20100 is currently offline Jim 20100Friend
Messages: 58
Registered: June 2016
Member
Hello,

I have a bidirectional link between 2 classes.
The cardinality is (m,n).

Ex:
- root
- node A
- node B (contains a link to C)
- node C (levels: contains a link to B)


if I remove Node A or B, the Node C contains a dangling reference.
It prevents the user to save the document (but the modification star disapears, which is then dangerous).

If I read this document (https://eclipsesource.com/blogs/2015/05/26/emf-dos-and-donts-11/) I thought the bad link should be removed as well.

I read on other forum that I can easily find the dangling references and remove them by myself with EcoreUtil.UnresolvedProxyCrossReferencer.

I tried to find the dangling references but nothing with that code below.
For the argument of the find method, I tested on the root, on the node C, and even on the levels nodes.

Map<EObject,Collection<EStructuralFeature.Setting>> unresolvedProxies=EcoreUtil.UnresolvedProxyCrossReferencer.find(node);

if (unresolvedProxies.size() > 0) {


Please help.

Jim
Re: Remove dangling references [message #1766872 is a reply to message #1766870] Wed, 28 June 2017 12:19 Go to previous messageGo to next message
Ed Willink is currently offline Ed WillinkFriend
Messages: 5573
Registered: July 2009
Senior Member
Hi

If they really are bidirectional references, I think they should be removed too. So I suspect that they are not genuine bidirectional references but without any repro I can do no more than suspect.

Regards

Ed Willink
Re: Remove dangling references [message #1766873 is a reply to message #1766872] Wed, 28 June 2017 12:33 Go to previous messageGo to next message
Ed Merks is currently offline Ed MerksFriend
Messages: 29115
Registered: July 2009
Senior Member
An dangling references isn't going to be an unresolved proxy, it's just an object that's not contained by any resource. Perhaps the easiest would be to use org.eclipse.emf.ecore.xmi.XMLResource.OPTION_PROCESS_DANGLING_HREF as a save option, to discard dangling references rather than throw an exception. Is that okay?
Re: Remove dangling references [message #1766878 is a reply to message #1766873] Wed, 28 June 2017 13:26 Go to previous messageGo to next message
Jim 20100 is currently offline Jim 20100Friend
Messages: 58
Registered: June 2016
Member
Hi all,

In fact it is a bit more complex than that.

I have an Engineering object, which contains a Quantity attribute.
The Engineering object contains a link to several nodes containing a Weight attribute.
The Quantity field of the Engineering is equal to the sum of the Weight of all linked node.

So with the event management I can detect when the weight changes, and with the bidirectional link, I update the Engineering Quantity attribute.
But when you delete a linked node, I am not able to remove the link from the Engineering and then recalculate the Quantity field of this Engineering.
I need to remove the dangling link, and recalculate the Quantity.

I think I mix a bit the proxies resolution and the dangling links. Can you explain in a few words pls?

Can you explain more the org.eclipse.emf.ecore.xmi.XMLResource.OPTION_PROCESS_DANGLING_HREF parameter?
How it works? how to use it?


Re: Remove dangling references [message #1766933 is a reply to message #1766878] Wed, 28 June 2017 20:28 Go to previous messageGo to next message
Andreas Graf is currently offline Andreas GrafFriend
Messages: 203
Registered: July 2009
Senior Member
Why not make the quantity attribute a derived attribute? And calculate it only when its queried?
Re: Remove dangling references [message #1766962 is a reply to message #1766933] Thu, 29 June 2017 06:54 Go to previous messageGo to next message
Ed Merks is currently offline Ed MerksFriend
Messages: 29115
Registered: July 2009
Senior Member
In general, to find all dangling references you could write a class like this:
    class DanglingCrossReferencer extends EcoreUtil.CrossReferencer
    {
      public DanglingCrossReferencer(ResourceSet resourceSet)
      {
        super(resourceSet);
      }
      
      @Override
      protected boolean crossReference(EObject eObject, EReference eReference, EObject crossReferencedEObject)
      {
        return crossReferencedEObject.eResource() == null && !crossReferencedEObject.eIsProxy() && !eReference.isTransient();
      }
      
      public Map<EObject, Collection<EStructuralFeature.Setting>> findDanglingCrossReferences()
      {
        crossReference();
        done();
        return this;
      }
    }
In other words, the cross referencer base class is designed with hooks where you can define how the containment tree is navigated, and which cross references to include in the final map where here we essentially just specify the condition that a cross reference is dangling, i.e., it has no containing resource and it isn't a proxy (and perhaps we want to ignore this for transient features because they won't be serialized and so won't cause problems).
Re: Remove dangling references [message #1766993 is a reply to message #1766962] Thu, 29 June 2017 11:18 Go to previous message
Jim 20100 is currently offline Jim 20100Friend
Messages: 58
Registered: June 2016
Member
@Andreas: I cannot use a derived attribute, because it can be calculated (by using links) or entered manually.

@ed: it works perfectly Thx.

Here is the code for all:
private void checkDanglingReferences(Object object){

if (!(object instanceof PriceParent))
return;

// Go to the root node
Quote quote = ((PriceParentImpl)object).getQuote();

ResourceSet resourceSet = quote.eResource().getResourceSet();
DanglingCrossReferencer danglingReferencer = new DanglingCrossReferencer(resourceSet);

Map<EObject,Collection<EStructuralFeature.Setting>> danglingReferences=danglingReferencer.findDanglingCrossReferences();

if (danglingReferences.size() > 0) {
for (Map.Entry<EObject, Collection<EStructuralFeature.Setting>> danglingReferenceEntry : danglingReferences
.entrySet()) {
BasicEObjectImpl danglingReference = (BasicEObjectImpl) danglingReferenceEntry.getKey();
for (EStructuralFeature.Setting setting : danglingReferenceEntry.getValue()) {
EObject objectWithDanglingRefs = setting.getEObject();

// Engineering Item
if (isReferenceToCheck(objectWithDanglingRefs, setting.getEStructuralFeature())) {

EditingDomain domain = AdapterFactoryEditingDomain.getEditingDomainFor(objectWithDanglingRefs);
Command addThePart = RemoveCommand.create(domain, objectWithDanglingRefs,
setting.getEStructuralFeature(), Collections.singleton(danglingReference));
domain.getCommandStack().execute(addThePart);

}
}
}
}

}

}

Previous Topic:Remember/derive source location when loading model from xml
Next Topic:EMF resource save with relative Paths and a different format
Goto Forum:
  


Current Time: Wed Jan 17 07:42:19 GMT 2018

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

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