Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » EMF » Copy EObject with eOpposite refs
Copy EObject with eOpposite refs [message #1007128] Mon, 04 February 2013 14:56 Go to next message
Erdal Karaca is currently offline Erdal KaracaFriend
Messages: 756
Registered: July 2009
Senior Member
Do you know of a ('simple') way to copy EObjects with eOpposite refs?
I am aware of eOpposite refs that would change the container. That is ok for my use case.

The javadocs of org.eclipse.emf.ecore.util.EcoreUtil.Copier.copyReference(EReference, EObject, EObject) say:

"""
Called to handle the copying of a cross reference; this adds values or sets a single value as appropriate for the multiplicity while omitting any bidirectional reference that isn't in the copy map.
"""

Is it sufficient to manually 'extend' the copy map?

I just ended up with this copy function:

  private Collection<EObject> copyAll(Collection<EObject> objectsToCopy,
      final boolean includeEopposites) {
    EcoreUtil.Copier copier = new Copier() {
      private static final long serialVersionUID = 1L;

      @Override
      public EObject get(Object key) {
        EObject eObject = super.get(key);

        if (eObject == null && includeEopposites) {
          if (key instanceof EObject) {
            eObject = (EObject) key;
          }
        }

        return eObject;
      }
    };
    Collection<EObject> copyAll = copier.copyAll(objectsToCopy);
    copier.copyReferences();
    return copyAll;
  }


It seems to work for some EObjects with eOpposite refs but with others I get:

java.util.ConcurrentModificationException
	at org.eclipse.emf.common.util.AbstractEList$EIterator.checkModCount(AbstractEList.java:756)
	at org.eclipse.emf.common.util.AbstractEList$EIterator.doNext(AbstractEList.java:710)
	at org.eclipse.emf.common.util.AbstractEList$EIterator.next(AbstractEList.java:690)
	at org.eclipse.emf.ecore.util.EcoreUtil$Copier.copyReference(EcoreUtil.java:717)
	at org.eclipse.emf.ecore.util.EcoreUtil$Copier.copyReferences(EcoreUtil.java:641)
Re: Copy EObject with eOpposite refs [message #1007132 is a reply to message #1007128] Mon, 04 February 2013 15:06 Go to previous messageGo to next message
Ed Merks is currently offline Ed MerksFriend
Messages: 26215
Registered: July 2009
Senior Member
Erdal,

Comments below.

On 04/02/2013 3:56 PM, Erdal Karaca wrote:
> Do you know of a ('simple') way to copy EObjects with eOpposite refs?
> I am aware of eOpposite refs that would change the container. That is
> ok for my use case.
I doubt it's okay. How can it possibly be okay?
>
> The javadocs of
> org.eclipse.emf.ecore.util.EcoreUtil.Copier.copyReference(EReference,
> EObject, EObject) say:
>
> """
> Called to handle the copying of a cross reference; this adds values or
> sets a single value as appropriate for the multiplicity while omitting
> any bidirectional reference that isn't in the copy map.
> """
>
> Is it sufficient to manually 'extend' the copy map?
>
> I just ended up with this copy function:
>
>
> private Collection<EObject> copyAll(Collection<EObject> objectsToCopy,
> final boolean includeEopposites) {
> EcoreUtil.Copier copier = new Copier() {
> private static final long serialVersionUID = 1L;
>
> @Override
> public EObject get(Object key) {
> EObject eObject = super.get(key);
>
> if (eObject == null && includeEopposites) {
> if (key instanceof EObject) {
> eObject = (EObject) key;
> }
> }
>
> return eObject;
> }
> };
> Collection<EObject> copyAll = copier.copyAll(objectsToCopy);
> copier.copyReferences();
> return copyAll;
> }
>
>
> It seems to work for some EObjects with eOpposite refs but with others
> I get:
>
>
> java.util.ConcurrentModificationException
> at
> org.eclipse.emf.common.util.AbstractEList$EIterator.checkModCount(AbstractEList.java:756)
> at
> org.eclipse.emf.common.util.AbstractEList$EIterator.doNext(AbstractEList.java:710)
> at
> org.eclipse.emf.common.util.AbstractEList$EIterator.next(AbstractEList.java:690)
> at
> org.eclipse.emf.ecore.util.EcoreUtil$Copier.copyReference(EcoreUtil.java:717)
> at
> org.eclipse.emf.ecore.util.EcoreUtil$Copier.copyReferences(EcoreUtil.java:641)
That's not surprising given that you're adding references to the
original list while iterating over it. Before I explain what you'd need
to do, I'd prefer you explain why you think it's okay for the original
object to be modified...
Re: Copy EObject with eOpposite refs [message #1007135 is a reply to message #1007132] Mon, 04 February 2013 15:23 Go to previous messageGo to next message
Erdal Karaca is currently offline Erdal KaracaFriend
Messages: 756
Registered: July 2009
Senior Member
Imaginary model:

EClass Master
- details: Detail 0..* (eOpposite = true, containment = true)

EClass Detail
- master: Master (eOpposite = true, container = true)

Just imagine a master/detail UI where the details of the master are shown in a table.
If I select one of the details and copy it to the details list of the master, then, I think, it is ok to let the master know of its new detail.
Maybe, I missed something...

Ed Merks wrote on Mon, 04 February 2013 16:06
Erdal,

Comments below.

On 04/02/2013 3:56 PM, Erdal Karaca wrote:
> Do you know of a ('simple') way to copy EObjects with eOpposite refs?
> I am aware of eOpposite refs that would change the container. That is
> ok for my use case.
I doubt it's okay. How can it possibly be okay?
>
> The javadocs of
> org.eclipse.emf.ecore.util.EcoreUtil.Copier.copyReference(EReference,
> EObject, EObject) say:
>
> """
> Called to handle the copying of a cross reference; this adds values or
> sets a single value as appropriate for the multiplicity while omitting
> any bidirectional reference that isn't in the copy map.
> """
>
> Is it sufficient to manually 'extend' the copy map?
>
> I just ended up with this copy function:
>
>
> private Collection<EObject> copyAll(Collection<EObject> objectsToCopy,
> final boolean includeEopposites) {
> EcoreUtil.Copier copier = new Copier() {
> private static final long serialVersionUID = 1L;
>
> @Override
> public EObject get(Object key) {
> EObject eObject = super.get(key);
>
> if (eObject == null && includeEopposites) {
> if (key instanceof EObject) {
> eObject = (EObject) key;
> }
> }
>
> return eObject;
> }
> };
> Collection<EObject> copyAll = copier.copyAll(objectsToCopy);
> copier.copyReferences();
> return copyAll;
> }
>
>
> It seems to work for some EObjects with eOpposite refs but with others
> I get:
>
>
> java.util.ConcurrentModificationException
> at
> org.eclipse.emf.common.util.AbstractEList$EIterator.checkModCount(AbstractEList.java:756)
> at
> org.eclipse.emf.common.util.AbstractEList$EIterator.doNext(AbstractEList.java:710)
> at
> org.eclipse.emf.common.util.AbstractEList$EIterator.next(AbstractEList.java:690)
> at
> org.eclipse.emf.ecore.util.EcoreUtil$Copier.copyReference(EcoreUtil.java:717)
> at
> org.eclipse.emf.ecore.util.EcoreUtil$Copier.copyReferences(EcoreUtil.java:641)
That's not surprising given that you're adding references to the
original list while iterating over it. Before I explain what you'd need
to do, I'd prefer you explain why you think it's okay for the original
object to be modified...

Re: Copy EObject with eOpposite refs [message #1007151 is a reply to message #1007135] Mon, 04 February 2013 15:49 Go to previous messageGo to next message
Ed Merks is currently offline Ed MerksFriend
Messages: 26215
Registered: July 2009
Senior Member
Erdal,

Comments below.

On 04/02/2013 4:23 PM, Erdal Karaca wrote:
> Imaginary model:
>
> EClass Master
> - details: Detail 0..* (eOpposite = true, containment = true)
>
> EClass Detail
> - master: Master (eOpposite = true, container = true)
>
> Just imagine a master/detail UI where the details of the master are
> shown in a table.
It's not a good example because it's a containment reference...
> If I select one of the details and copy it to the details list of the
> master, then, I think, it is ok to let the master know of its new detail.
If you're doing this in the IDE you need a command to modify the state
of the original model otherwise undo will be broken... That would be
true even for a non-containment reference example. Think about how
badly behaved your scenario (it it weren't a containment) would be if
you copied the Master object. All Details would be removed from the
original and added to the copy; that can't possibly be a good thing, right?
> Maybe, I missed something...
>
> Ed Merks wrote on Mon, 04 February 2013 16:06
>> Erdal,
>>
>> Comments below.
>>
>> On 04/02/2013 3:56 PM, Erdal Karaca wrote:
>> > Do you know of a ('simple') way to copy EObjects with eOpposite refs?
>> > I am aware of eOpposite refs that would change the container. That
>> is > ok for my use case.
>> I doubt it's okay. How can it possibly be okay?
>> >
>> > The javadocs of >
>> org.eclipse.emf.ecore.util.EcoreUtil.Copier.copyReference(EReference,
>> > EObject, EObject) say:
>> >
>> > """
>> > Called to handle the copying of a cross reference; this adds values
>> or > sets a single value as appropriate for the multiplicity while
>> omitting > any bidirectional reference that isn't in the copy map.
>> > """
>> >
>> > Is it sufficient to manually 'extend' the copy map?
>> >
>> > I just ended up with this copy function:
>> >
>> >
>> > private Collection<EObject> copyAll(Collection<EObject>
>> objectsToCopy,
>> > final boolean includeEopposites) {
>> > EcoreUtil.Copier copier = new Copier() {
>> > private static final long serialVersionUID = 1L;
>> >
>> > @Override
>> > public EObject get(Object key) {
>> > EObject eObject = super.get(key);
>> >
>> > if (eObject == null && includeEopposites) {
>> > if (key instanceof EObject) {
>> > eObject = (EObject) key;
>> > }
>> > }
>> >
>> > return eObject;
>> > }
>> > };
>> > Collection<EObject> copyAll = copier.copyAll(objectsToCopy);
>> > copier.copyReferences();
>> > return copyAll;
>> > }
>> >
>> >
>> > It seems to work for some EObjects with eOpposite refs but with
>> others > I get:
>> >
>> >
>> > java.util.ConcurrentModificationException
>> > at >
>> org.eclipse.emf.common.util.AbstractEList$EIterator.checkModCount(AbstractEList.java:756)
>> > at >
>> org.eclipse.emf.common.util.AbstractEList$EIterator.doNext(AbstractEList.java:710)
>> > at >
>> org.eclipse.emf.common.util.AbstractEList$EIterator.next(AbstractEList.java:690)
>> > at >
>> org.eclipse.emf.ecore.util.EcoreUtil$Copier.copyReference(EcoreUtil.java:717)
>> > at >
>> org.eclipse.emf.ecore.util.EcoreUtil$Copier.copyReferences(EcoreUtil.java:641)
>> That's not surprising given that you're adding references to the
>> original list while iterating over it. Before I explain what you'd
>> need to do, I'd prefer you explain why you think it's okay for the
>> original object to be modified...
>
>
Re: Copy EObject with eOpposite refs [message #1007154 is a reply to message #1007151] Mon, 04 February 2013 16:00 Go to previous messageGo to next message
Erdal Karaca is currently offline Erdal KaracaFriend
Messages: 756
Registered: July 2009
Senior Member
Yes, you are right... Anyways, what would be the solution? It (the code) is for educational purposes (dont do this) Smile

Ed Merks wrote on Mon, 04 February 2013 16:49

It's not a good example because it's a containment reference...
> If I select one of the details and copy it to the details list of the
> master, then, I think, it is ok to let the master know of its new detail.
If you're doing this in the IDE you need a command to modify the state
of the original model otherwise undo will be broken... That would be
true even for a non-containment reference example. Think about how
badly behaved your scenario (it it weren't a containment) would be if
you copied the Master object. All Details would be removed from the
original and added to the copy; that can't possibly be a good thing, right?

Re: Copy EObject with eOpposite refs [message #1007160 is a reply to message #1007154] Mon, 04 February 2013 16:10 Go to previous messageGo to next message
Ed Merks is currently offline Ed MerksFriend
Messages: 26215
Registered: July 2009
Senior Member
Erdal,

You'd need to specialize copyReference. Essentially copying the whole
method and changing the parts the filter out the things you want copied
anyway. You'll need to make a copy of the bidirectional list you're
iterator over that's changing during the iteration and iterate over that
copy.


On 04/02/2013 5:00 PM, Erdal Karaca wrote:
> Yes, you are right... Anyways, what would be the solution? It (the
> code) is for educational purposes (dont do this) :)
>
> Ed Merks wrote on Mon, 04 February 2013 16:49
>> It's not a good example because it's a containment reference...
>> > If I select one of the details and copy it to the details list of
>> the > master, then, I think, it is ok to let the master know of its
>> new detail.
>> If you're doing this in the IDE you need a command to modify the
>> state of the original model otherwise undo will be broken... That
>> would be true even for a non-containment reference example. Think
>> about how badly behaved your scenario (it it weren't a containment)
>> would be if you copied the Master object. All Details would be
>> removed from the original and added to the copy; that can't possibly
>> be a good thing, right?
>
>
Re: Copy EObject with eOpposite refs [message #1007166 is a reply to message #1007160] Mon, 04 February 2013 16:27 Go to previous message
Erdal Karaca is currently offline Erdal KaracaFriend
Messages: 756
Registered: July 2009
Senior Member
Thanks, Ed! It works... but it is really ugly, so dont do this at home!

Ed Merks wrote on Mon, 04 February 2013 17:10
You'd need to specialize copyReference. Essentially copying the whole
method and changing the parts the filter out the things you want copied
anyway. You'll need to make a copy of the bidirectional list you're
iterator over that's changing during the iteration and iterate over that
copy.

Previous Topic:How to implement an interface in Ecore Model Editor
Next Topic:[CDO][Teneo] How to write / read LOB data stream based?
Goto Forum:
  


Current Time: Sat Nov 22 18:04:43 GMT 2014

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

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