Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » EMF » ChangeDescription#copyAndReverse()
ChangeDescription#copyAndReverse() [message #805280] Thu, 23 February 2012 15:26 Go to next message
Jason Roberts is currently offline Jason RobertsFriend
Messages: 5
Registered: February 2012
Junior Member
For ChangeDescription I am evaluating switching from using applyAndReverse() to create a forward delta to the new copyAndReverse(). I am hopeful that it will solve the problem with applyAndReverse when the UI is bound to the model.

In our case we are not interested in serializing the change description and sending it to another process like I commonly see in the examples. Instead we want to look at objectsToDetach to determine what has been added, then applyAndReverse() and look at objectsToDetach again to determine what has been removed and use the information to invoke a service that is EMF independent.

After uplifting to copyAndReverse I am seeing some unexpected results although it is very possible that I do not fully understand the new API.


Here is my test case:

public void testCopyAndReverse()
{
EPackage ePackage = EcoreFactory.eINSTANCE.createEPackage();
EAnnotation eAnnotation1 = EcoreFactory.eINSTANCE.createEAnnotation();
ePackage.getEAnnotations().add(eAnnotation1);

Map<EObject, URI> eObjectToProxyURIMap = new HashMap<EObject, URI>();

ChangeRecorder changeRecorder = new ChangeRecorder();
changeRecorder.setEObjectToProxyURIMap(eObjectToProxyURIMap);
changeRecorder.beginRecording(Collections.singleton(ePackage));

// A removal
ePackage.getEAnnotations().remove(eAnnotation1);

// An addition
EAnnotation eAnnotation2 = EcoreFactory.eINSTANCE.createEAnnotation();
ePackage.getEAnnotations().add(eAnnotation2);

ChangeDescription changeDescription = changeRecorder.endRecording();
assertEquals(1, changeDescription.getObjectsToDetach().size());
assertSame(eAnnotation2, changeDescription.getObjectsToDetach().get(0));

// Test undo and redo. This all works as expected.
changeDescription.applyAndReverse();
assertEquals(1, changeDescription.getObjectsToDetach().size());
assertSame(eAnnotation1, changeDescription.getObjectsToDetach().get(0));
changeDescription.applyAndReverse();
assertEquals(1, changeDescription.getObjectsToDetach().size());
assertSame(eAnnotation2, changeDescription.getObjectsToDetach().get(0));

// Test copyAndReverse()
changeDescription.copyAndReverse(eObjectToProxyURIMap);

// This assertion fails because objectsToDetach is empty.
// I would expect it to contain only eAnnotation1.
assertEquals(1, changeDescription.getObjectsToDetach().size());
}
Re: ChangeDescription#copyAndReverse() [message #805796 is a reply to message #805280] Fri, 24 February 2012 06:26 Go to previous messageGo to next message
Ed Merks is currently offline Ed MerksFriend
Messages: 33142
Registered: July 2009
Senior Member
Jason,

Comments below.

On 23/02/2012 4:26 PM, Jason Roberts wrote:
> For ChangeDescription I am evaluating switching from using
> applyAndReverse() to create a forward delta to the new
> copyAndReverse(). I am hopeful that it will solve the problem with
> applyAndReverse when the UI is bound to the model.
Yes, the intent was to allow you to create a forward delta without
modifying the model...
>
> In our case we are not interested in serializing the change
> description and sending it to another process like I commonly see in
> the examples. Instead we want to look at objectsToDetach to determine
> what has been added, then applyAndReverse() and look at
> objectsToDetach again to determine what has been removed and use the
> information to invoke a service that is EMF independent.
Given the symmetry of these things, would it make sense to look at the
final unreversed change description and conclude that objectsToDetatch
being the objects that you'd need to remove to get back to previous
state are in fact the objects that were attached and that
objectsToAttach being the objects that need to be put back are actually
the objects that were detached?
>
> After uplifting to copyAndReverse I am seeing some unexpected results
> although it is very possible that I do not fully understand the new API.
>
> Here is my test case:
>
> public void testCopyAndReverse()
> {
> EPackage ePackage = EcoreFactory.eINSTANCE.createEPackage();
> EAnnotation eAnnotation1 =
> EcoreFactory.eINSTANCE.createEAnnotation();
> ePackage.getEAnnotations().add(eAnnotation1);
>
> Map<EObject, URI> eObjectToProxyURIMap = new HashMap<EObject,
> URI>();
>
> ChangeRecorder changeRecorder = new ChangeRecorder();
> changeRecorder.setEObjectToProxyURIMap(eObjectToProxyURIMap);
> changeRecorder.beginRecording(Collections.singleton(ePackage));
Your objects aren't in resources so any proxies that are created won't
be resolvable...
>
> // A removal
> ePackage.getEAnnotations().remove(eAnnotation1);
>
> // An addition
> EAnnotation eAnnotation2 =
> EcoreFactory.eINSTANCE.createEAnnotation();
> ePackage.getEAnnotations().add(eAnnotation2);
>
> ChangeDescription changeDescription =
> changeRecorder.endRecording();
> assertEquals(1, changeDescription.getObjectsToDetach().size());
> assertSame(eAnnotation2,
> changeDescription.getObjectsToDetach().get(0));
>
> // Test undo and redo. This all works as expected.
> changeDescription.applyAndReverse();
> assertEquals(1, changeDescription.getObjectsToDetach().size());
> assertSame(eAnnotation1,
> changeDescription.getObjectsToDetach().get(0));
> changeDescription.applyAndReverse();
> assertEquals(1, changeDescription.getObjectsToDetach().size());
> assertSame(eAnnotation2,
> changeDescription.getObjectsToDetach().get(0));
>
> // Test copyAndReverse()
> changeDescription.copyAndReverse(eObjectToProxyURIMap);
So keep in mind what this method is doing. No original objects are
affected and anything that describes changes to original objects refers
to proxies to those objects.
>
> // This assertion fails because objectsToDetach is empty.
> // I would expect it to contain only eAnnotation1.
> assertEquals(1, changeDescription.getObjectsToDetach().size());
The change description isn't in a resource in a resource set, so any
proxies won't be resolvable. So you'll noticed if you look in the
object changes map, that the EPackage is a proxy and that while
getObjectsToDetatch is being computed, it fails to resolve, so it
appears to have no annotations. As such, the computation concludes that
nothing needs to be removed from it.
> }


Ed Merks
Professional Support: https://www.macromodeling.com/
Re: ChangeDescription#copyAndReverse() [message #809439 is a reply to message #805796] Tue, 28 February 2012 22:03 Go to previous messageGo to next message
Jason Roberts is currently offline Jason RobertsFriend
Messages: 5
Registered: February 2012
Junior Member
Ed,

Comments below.

> Given the symmetry of these things, would it make sense to look at the
> final unreversed change description and conclude that objectsToDetatch
> being the objects that you'd need to remove to get back to previous
> state are in fact the objects that were attached and that
> objectsToAttach being the objects that need to be put back are actually
> the objects that were detached?
I would actually like to use objectsToAttach to get the detached objects without having to reverse the change description, however I need the original eContainer of each object all the way up to the root eContainer. Right now prior to reversing the eContainer of each object is the change description itself. Unless there is another way to get that context without reversing the change description...

> Your objects aren't in resources so any proxies that are created won't
> be resolvable...
Updated my test case below.

> The change description isn't in a resource in a resource set, so any
> proxies won't be resolvable. So you'll noticed if you look in the
> object changes map, that the EPackage is a proxy and that while
> getObjectsToDetatch is being computed, it fails to resolve, so it
> appears to have no annotations. As such, the computation concludes that
> nothing needs to be removed from it.
Updated my test case below. I have little experience with proxies in EMF so check my logic, but I think I have added what you described.
I created a resource set with two resources, one for my object I am recording and one for the change description.


public void testCopyAndReverse2()
{
ResourceSet resourceSet = new ResourceSetImpl();
Resource resource1 = new ResourceImpl(URI.createURI("resource1"));
Resource resource2 = new ResourceImpl(URI.createURI("resource2"));
resourceSet.getResources().add(resource1);
resourceSet.getResources().add(resource2);

EPackage ePackage = EcoreFactory.eINSTANCE.createEPackage();
EAnnotation eAnnotation1 = EcoreFactory.eINSTANCE.createEAnnotation();
ePackage.getEAnnotations().add(eAnnotation1);
resource1.getContents().add(ePackage);

Map<EObject, URI> eObjectToProxyURIMap = new HashMap<EObject, URI>();

ChangeRecorder changeRecorder = new ChangeRecorder();
changeRecorder.setEObjectToProxyURIMap(eObjectToProxyURIMap);
changeRecorder.beginRecording(Collections.singleton(ePackage));

// A removal
ePackage.getEAnnotations().remove(eAnnotation1);

// An addition
EAnnotation eAnnotation2 = EcoreFactory.eINSTANCE.createEAnnotation();
ePackage.getEAnnotations().add(eAnnotation2);

ChangeDescription changeDescription = changeRecorder.endRecording();
resource2.getContents().add(changeDescription);
assertEquals(1, changeDescription.getObjectsToDetach().size());
assertSame(eAnnotation2, changeDescription.getObjectsToDetach().get(0));

// Test copyAndReverse()
changeDescription.copyAndReverse(eObjectToProxyURIMap);

// This assertion fails because objectsToDetach is empty.
// I would expect it to contain only eAnnotation1.
assertEquals(1, changeDescription.getObjectsToDetach().size());
}
Re: ChangeDescription#copyAndReverse() [message #809740 is a reply to message #809439] Wed, 29 February 2012 07:43 Go to previous message
Ed Merks is currently offline Ed MerksFriend
Messages: 33142
Registered: July 2009
Senior Member
Jason,

Comments below.

On 28/02/2012 11:03 PM, Jason Roberts wrote:
> Ed,
>
> Comments below.
>
>> Given the symmetry of these things, would it make sense to look at
>> the final unreversed change description and conclude that
>> objectsToDetatch being the objects that you'd need to remove to get
>> back to previous state are in fact the objects that were attached and
>> that objectsToAttach being the objects that need to be put back are
>> actually the objects that were detached?
> I would actually like to use objectsToAttach to get the detached
> objects without having to reverse the change description, however I
> need the original eContainer of each object all the way up to the root
> eContainer.
The change description knows where they need to be attached.
> Right now prior to reversing the eContainer of each object is the
> change description itself.
Yes, but the change description does have information about where the
object needs to be attached.
> Unless there is another way to get that context without reversing the
> change description...
As you can imagine, the change description has every detail necessary to
reverse all the changes so it does know where the object needs to be
reattached.
>
>> Your objects aren't in resources so any proxies that are created
>> won't be resolvable...
> Updated my test case below.
>
>> The change description isn't in a resource in a resource set, so any
>> proxies won't be resolvable. So you'll noticed if you look in the
>> object changes map, that the EPackage is a proxy and that while
>> getObjectsToDetatch is being computed, it fails to resolve, so it
>> appears to have no annotations. As such, the computation concludes
>> that nothing needs to be removed from it.
> Updated my test case below. I have little experience with proxies in
> EMF so check my logic, but I think I have added what you described.
> I created a resource set with two resources, one for my object I am
> recording and one for the change description.
>
>
> public void testCopyAndReverse2()
> {
> ResourceSet resourceSet = new ResourceSetImpl();
> Resource resource1 = new ResourceImpl(URI.createURI("resource1"));
> Resource resource2 = new ResourceImpl(URI.createURI("resource2"));
> resourceSet.getResources().add(resource1);
> resourceSet.getResources().add(resource2);
> EPackage ePackage =
> EcoreFactory.eINSTANCE.createEPackage();
> EAnnotation eAnnotation1 =
> EcoreFactory.eINSTANCE.createEAnnotation();
> ePackage.getEAnnotations().add(eAnnotation1);
> resource1.getContents().add(ePackage);
>
> Map<EObject, URI> eObjectToProxyURIMap = new HashMap<EObject,
> URI>();
>
> ChangeRecorder changeRecorder = new ChangeRecorder();
> changeRecorder.setEObjectToProxyURIMap(eObjectToProxyURIMap);
> changeRecorder.beginRecording(Collections.singleton(ePackage));
>
> // A removal
> ePackage.getEAnnotations().remove(eAnnotation1);
>
> // An addition
> EAnnotation eAnnotation2 =
> EcoreFactory.eINSTANCE.createEAnnotation();
> ePackage.getEAnnotations().add(eAnnotation2);
>
> ChangeDescription changeDescription =
> changeRecorder.endRecording();
> resource2.getContents().add(changeDescription);
> assertEquals(1, changeDescription.getObjectsToDetach().size());
> assertSame(eAnnotation2,
> changeDescription.getObjectsToDetach().get(0));
>
> // Test copyAndReverse()
> changeDescription.copyAndReverse(eObjectToProxyURIMap);
The problem here is that when the proxies are resolved, they don't
resolve to objects in the original state, they resolve to objects in the
final state.
>
> // This assertion fails because objectsToDetach is empty.
> // I would expect it to contain only eAnnotation1.
> assertEquals(1, changeDescription.getObjectsToDetach().size());
> }
Here's something that works, but is just as brute force as before.

public static void testCopyAndReverse2()
{
ResourceSet resourceSet = new ResourceSetImpl();
Resource resource1 = new ResourceImpl(URI.createURI("resource1"));
Resource resource1Copy = new
ResourceImpl(URI.createURI("resource1.copy"));
Resource resource2 = new ResourceImpl(URI.createURI("resource2"));
resourceSet.getResources().add(resource1);
resourceSet.getResources().add(resource1Copy);
resourceSet.getResources().add(resource2);
EPackage ePackage = EcoreFactory.eINSTANCE.createEPackage();
EAnnotation eAnnotation1 =
EcoreFactory.eINSTANCE.createEAnnotation();
ePackage.getEAnnotations().add(eAnnotation1);
resource1.getContents().add(ePackage);

resource1Copy.getContents().addAll(EcoreUtil.copyAll(resource1.getContents()));

Map<EObject, URI> eObjectToProxyURIMap = new HashMap<EObject,
URI>();

ChangeRecorder changeRecorder = new ChangeRecorder();
changeRecorder.setEObjectToProxyURIMap(eObjectToProxyURIMap);
changeRecorder.beginRecording(Collections.singleton(ePackage));

// A removal
ePackage.getEAnnotations().remove(eAnnotation1);

// An addition
EAnnotation eAnnotation2 =
EcoreFactory.eINSTANCE.createEAnnotation();
ePackage.getEAnnotations().add(eAnnotation2);

ChangeDescription changeDescription = changeRecorder.endRecording();

resource2.getContents().add(changeDescription);
assertEquals(1, changeDescription.getObjectsToDetach().size());
assertSame(eAnnotation2,
changeDescription.getObjectsToDetach().get(0));

// Test copyAndReverse()
changeDescription.copyAndReverse(eObjectToProxyURIMap);

resource1.setURI(URI.createURI("resource1.old"));
resource1Copy.setURI(URI.createURI("resource1"));


// This assertion fails because objectsToDetach is empty.
// I would expect it to contain only eAnnotation1.
assertEquals(1, changeDescription.getObjectsToDetach().size());
}


Ed Merks
Professional Support: https://www.macromodeling.com/
Previous Topic:create empty EList of org.eclipse.uml2.uml.Element
Next Topic:bundle "xx" cannot be resolved
Goto Forum:
  


Current Time: Sat Apr 27 00:00:18 GMT 2024

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

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

Back to the top