Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » EMF » Extending EcoreUtil.Copier to include bidirectional references(EcreUtil.Copier)
Extending EcoreUtil.Copier to include bidirectional references [message #1802224] Mon, 04 February 2019 16:16 Go to next message
Pablo Gomez Abajo is currently offline Pablo Gomez AbajoFriend
Messages: 8
Registered: February 2019
Junior Member
Hi,

I'm trying to extend EcoreUtil.Copier class to include bidirectional references (references with an EOpposite value), but I'm not reaching the solution. I would appreciate any help.

This is my modified not working yet extension of EcoreUtil.Copier.

public class EMFCopier extends EcoreUtil.Copier {

	private static final long serialVersionUID = 1L;

	@Override
	protected void copyReference(EReference eReference, EObject eObject, EObject copyEObject)
	{
		if (eObject.eIsSet(eReference))
		{
			EStructuralFeature.Setting setting = getTarget(eReference, eObject, copyEObject);
			if (setting != null)
			{
				Object value = eObject.eGet(eReference, resolveProxies);
				if (eReference.isMany())
				{
					@SuppressWarnings("unchecked") InternalEList<EObject> source = (InternalEList<EObject>)value;
					@SuppressWarnings("unchecked") InternalEList<EObject> target = (InternalEList<EObject>)setting;
					if (source.isEmpty())
					{
						target.clear();
					}
					else
					{
						boolean isBidirectional = eReference.getEOpposite() != null && !eReference.getEOpposite().isMany();
						int index = 0;
						for (Iterator<EObject> k = resolveProxies ? source.iterator() : source.basicIterator(); k.hasNext();)
						{
							EObject referencedEObject = k.next();
							EObject copyReferencedEObject = get(referencedEObject);
							if (copyReferencedEObject == null)
							{
								if (useOriginalReferences && !isBidirectional)
								{
									target.addUnique(index, referencedEObject);
									++index;
								}
							}
							else
							{
								if (isBidirectional)
								{
									int position = target.indexOf(copyReferencedEObject);
									if (position == -1)
									{
										target.addUnique(index, copyReferencedEObject);
									}
									else if (index != position)
									{
										target.move(index, copyReferencedEObject);
									}
								}
								else
								{
									target.addUnique(index, copyReferencedEObject);
								}
								++index;
							}
						}
					}
				}
				else
				{
					if (value == null)
					{
						setting.set(null);
					}
					else
					{
						Object copyReferencedEObject = get(value);
						if (copyReferencedEObject == null)
						{
							if (useOriginalReferences && !(eReference.getEOpposite() != null && !eReference.getEOpposite().isMany()))
							{
								setting.set(value);
							}
						}
						else
						{
							setting.set(copyReferencedEObject);
						}
					}
				}
			}
		}
	}
}


Many thanks in advance.
Re: Extending EcoreUtil.Copier to include bidirectional references [message #1802280 is a reply to message #1802224] Tue, 05 February 2019 19:44 Go to previous messageGo to next message
Ed Willink is currently offline Ed WillinkFriend
Messages: 6388
Registered: July 2009
Senior Member
HI

EcoreUtil.Copier does a good job of deep copying which includes opposites.

I suggest you revisit your use case to understand why it isn't working. Perhaps you just didn't give the copier all the roots.

Regards

Ed Willink
Re: Extending EcoreUtil.Copier to include bidirectional references [message #1802292 is a reply to message #1802280] Wed, 06 February 2019 05:00 Go to previous messageGo to next message
Ed Merks is currently offline Ed MerksFriend
Messages: 30203
Registered: July 2009
Senior Member
Firstly, your attempt to modify this behavior is probably, in fact no doubt, misguided. There's a good reason that opposites are copied conditionally and you've not specified the "not working" aspect of your attempt to change the behavior. The reason that opposites are copied only if the reference is also part of the set of objects being copied is because otherwise, the original set of objects will be modified during the copying. I.e., the original set of objects will end up with references to the copy, and in the case of single-valued reference that means the original object will reference the copy, but will no longer reference the object it originally referenced. No doubt that will be perceived as "not working" so there's not much point in me trying to test your changes against some unspecified model and determine if the new behavior is "working" according to our unspecified definition of "working".

Most likely you should be focused on using EcoreUtil.copyAll to copy a larger set of object in a simple operation such that bidirectional references among the copies reflect exactly the bidirectional references among the originals. In any case, if you wish to augment the behavior in some way that truly does involve the original objects referencing the copied objects, you should clearly state what you intend for that behavior to be...
Re: Extending EcoreUtil.Copier to include bidirectional references [message #1802308 is a reply to message #1802292] Wed, 06 February 2019 07:49 Go to previous messageGo to next message
Pablo Gomez Abajo is currently offline Pablo Gomez AbajoFriend
Messages: 8
Registered: February 2019
Junior Member
Many thanks, Ed. I will try to fix this... But I'm not sure how to do it. I'm calling EcoreUtil.copyAll this way to deep clone a Resource:

EMFCopier copier = new EMFCopier();
resource.getContents().addAll(copier.copyAll(model.getContents()))
copier.copyReferences();


Also

EcoreUtil.Copier copier = new EcoreUtil.Copier();
resource.getContents().addAll(copier.copyAll(model.getContents()))
copier.copyReferences();


But not getting the expected result...

Best regards,

Pablo

Re: Extending EcoreUtil.Copier to include bidirectional references [message #1802310 is a reply to message #1802308] Wed, 06 February 2019 08:18 Go to previous messageGo to next message
Ed Merks is currently offline Ed MerksFriend
Messages: 30203
Registered: July 2009
Senior Member
Do any of the resource's contents (I assume "model" is a resource) have bidirectional references to objects in other resources? If so, those will of course not be in the copy, nor should they be. So what exactly is "the expect result" of this operation supposed to be? Keep in mind that your goal should remain that original objects are not touched by copying. You might want some original object to end up with a reference to the copy, but you should be explicit about exactly those cases and explain the underlying thinking and details to me so I can understand your goal and help figure out the best direction to take.
Re: Extending EcoreUtil.Copier to include bidirectional references [message #1802316 is a reply to message #1802310] Wed, 06 February 2019 09:48 Go to previous messageGo to next message
Pablo Gomez Abajo is currently offline Pablo Gomez AbajoFriend
Messages: 8
Registered: February 2019
Junior Member
Yes, Ed, many thanks for your fast support. Te expected result is a deep clone of the source resource (object model) in the target resource (object resource)... A clone which also includes the bidirectional references, which is not happening now. These bidirectional references must refer to the corresponding cloned objects of the new created resource.

I hope I explained it better now.

Best wishes,

Pablo

Re: Extending EcoreUtil.Copier to include bidirectional references [message #1802317 is a reply to message #1802316] Wed, 06 February 2019 09:57 Go to previous messageGo to next message
Pablo Gomez Abajo is currently offline Pablo Gomez AbajoFriend
Messages: 8
Registered: February 2019
Junior Member
And the objects in the source resource only have references to its own contents.

Re: Extending EcoreUtil.Copier to include bidirectional references [message #1802319 is a reply to message #1802317] Wed, 06 February 2019 10:28 Go to previous messageGo to next message
Ed Merks is currently offline Ed MerksFriend
Messages: 30203
Registered: July 2009
Senior Member
Sorry, but I don't believe you. I would suggest setting a breakpoint at these two lines:

https://git.eclipse.org/c/emf/org.eclipse.emf.git/tree/plugins/org.eclipse.emf.ecore/src/org/eclipse/emf/ecore/util/EcoreUtil.java#n786
                if (copyReferencedEObject == null)
                {
                  if (useOriginalReferences && !isBidirectional)


https://git.eclipse.org/c/emf/org.eclipse.emf.git/tree/plugins/org.eclipse.emf.ecore/src/org/eclipse/emf/ecore/util/EcoreUtil.java#n826
              if (copyReferencedEObject == null)
              {
                if (useOriginalReferences && eReference.getEOpposite() == null)
                {


If what you say is true, i.e., "objects in the source resource only have references to its own contents", then you will not hit those breakpoints. If what you say is false, then you will hit them, and you'll see that you have a reference to an object that has not been copied, and you'll know exactly which object that is.
Re: Extending EcoreUtil.Copier to include bidirectional references [message #1802546 is a reply to message #1802319] Mon, 11 February 2019 18:08 Go to previous message
Pablo Gomez Abajo is currently offline Pablo Gomez AbajoFriend
Messages: 8
Registered: February 2019
Junior Member
You were right, Ed, many thanks. I had a bug in my implementation and the way I was setting some references in objects.

Many thanks!!!!
Previous Topic:Resource /library.editor does not exist
Next Topic:[CDO]
Goto Forum:
  


Current Time: Sun Jun 16 12:55:00 GMT 2019

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

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

Back to the top