Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » EMF » Examples of EMF reflective API
Examples of EMF reflective API [message #419905] Thu, 12 June 2008 10:34 Go to next message
Eclipse UserFriend
Originally posted by: darpan.cmu.edu

Hi,

I have two identical UML models and when I change one model I want to
apply the same change to the other model.

After trying various approaches, the way I do is this is capture the
Notification from the original model and apply the changes on my target
model.

I want to do this using the EMF reflective API, but so far I have only had
limited success because of some of the subtleties involved.
For example, some of my code looks like this:

EStructuralFeature strucFeature =
affectedObject.eClass().getEStructuralFeature(featureID);
if (!strucFeature.isDerived()) {
EObject eObjectCopy = EcoreUtil.copy(newValueObject);
if (affectedObject.eIsSet(strucFeature)) {
if (strucFeature.isMany()) {
((EList) affectedObject.eGet(strucFeature))
.add(eObjectCopy);
} else {
affectedObject.eSet(strucFeature,
Collections.singletonList(eObjectCopy));
}
} else {
affectedObject.eSet(strucFeature, eObjectCopy);
}
}

I basically first create a copy of the newValue of the Notification and
then try to apply the same kind of Notification change on the new model
(ADD, SET, REMOVE etc., the above code is for ADD).

I am unsure of the various possibilities of EMF element properties that I
have to take care of here, e.g. things like derived, transient or isMany
of the structural feature.

I'd appreciate any help or pointers to locations of examples of EMF
reflective API.

Thanks,
-darpan
Re: Examples of EMF reflective API [message #419907 is a reply to message #419905] Thu, 12 June 2008 11:52 Go to previous messageGo to next message
Eclipse UserFriend
Originally posted by: cdamus.zeligsoft.com

--=-peTft9HGT7nvWP/oJ0Ya
Content-Type: text/plain
Content-Transfer-Encoding: 7bit

Hi, Darpan,

The EcoreUtil.Copier utility class is a good example of the reflective
API, and probably rather relevant to your task.

HTH,

Christian


On Thu, 2008-06-12 at 10:34 +0000, Darpan Saini wrote:

> Hi,
>
> I have two identical UML models and when I change one model I want to
> apply the same change to the other model.
>
> After trying various approaches, the way I do is this is capture the
> Notification from the original model and apply the changes on my target
> model.
>
> I want to do this using the EMF reflective API, but so far I have only had
> limited success because of some of the subtleties involved.
> For example, some of my code looks like this:
>
> EStructuralFeature strucFeature =
> affectedObject.eClass().getEStructuralFeature(featureID);
> if (!strucFeature.isDerived()) {
> EObject eObjectCopy = EcoreUtil.copy(newValueObject);
> if (affectedObject.eIsSet(strucFeature)) {
> if (strucFeature.isMany()) {
> ((EList) affectedObject.eGet(strucFeature))
> .add(eObjectCopy);
> } else {
> affectedObject.eSet(strucFeature,
> Collections.singletonList(eObjectCopy));
> }
> } else {
> affectedObject.eSet(strucFeature, eObjectCopy);
> }
> }
>
> I basically first create a copy of the newValue of the Notification and
> then try to apply the same kind of Notification change on the new model
> (ADD, SET, REMOVE etc., the above code is for ADD).
>
> I am unsure of the various possibilities of EMF element properties that I
> have to take care of here, e.g. things like derived, transient or isMany
> of the structural feature.
>
> I'd appreciate any help or pointers to locations of examples of EMF
> reflective API.
>
> Thanks,
> -darpan
>
>

--=-peTft9HGT7nvWP/oJ0Ya
Content-Type: text/html; charset=utf-8

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 TRANSITIONAL//EN">
<HTML>
<HEAD>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; CHARSET=UTF-8">
<META NAME="GENERATOR" CONTENT="GtkHTML/3.16.0">
</HEAD>
<BODY>
Hi, Darpan,<BR>
<BR>
The EcoreUtil.Copier utility class is a good example of the reflective API, and probably rather relevant to your task.<BR>
<BR>
HTH,<BR>
<BR>
Christian<BR>
<BR>
<BR>
On Thu, 2008-06-12 at 10:34 +0000, Darpan Saini wrote:
<BLOCKQUOTE TYPE=CITE>
<PRE>
<FONT COLOR="#000000">Hi,</FONT>

<FONT COLOR="#000000">I have two identical UML models and when I change one model I want to </FONT>
<FONT COLOR="#000000">apply the same change to the other model.</FONT>

<FONT COLOR="#000000">After trying various approaches, the way I do is this is capture the </FONT>
<FONT COLOR="#000000">Notification from the original model and apply the changes on my target </FONT>
<FONT COLOR="#000000">model. </FONT>

<FONT COLOR="#000000">I want to do this using the EMF reflective API, but so far I have only had </FONT>
<FONT COLOR="#000000">limited success because of some of the subtleties involved.</FONT>
<FONT COLOR="#000000">For example, some of my code looks like this:</FONT>

<FONT COLOR="#000000">EStructuralFeature strucFeature = </FONT>
<FONT COLOR="#000000"> affectedObject.eClass().getEStructuralFeature(featureID);</FONT >
<FONT COLOR="#000000">if (!strucFeature.isDerived()) {</FONT>
<FONT COLOR="#000000"> EObject eObjectCopy = EcoreUtil.copy(newValueObject);</FONT>
<FONT COLOR="#000000"> if (affectedObject.eIsSet(strucFeature)) {</FONT>
<FONT COLOR="#000000"> if (strucFeature.isMany()) {</FONT>
<FONT COLOR="#000000"> ((EList) affectedObject.eGet(strucFeature))</FONT>
<FONT COLOR="#000000"> .add(eObjectCopy);</FONT>
<FONT COLOR="#000000"> } else {</FONT>
<FONT COLOR="#000000"> affectedObject.eSet(strucFeature, </FONT>
<FONT COLOR="#000000">Collections.singletonList(eObjectCopy));</FONT >
<FONT COLOR="#000000"> }</FONT>
<FONT COLOR="#000000"> } else {</FONT>
<FONT COLOR="#000000"> affectedObject.eSet(strucFeature, eObjectCopy);</FONT>
<FONT COLOR="#000000"> }</FONT>
<FONT COLOR="#000000">}</FONT>

<FONT COLOR="#000000">I basically first create a copy of the newValue of the Notification and </FONT>
<FONT COLOR="#000000">then try to apply the same kind of Notification change on the new model </FONT>
<FONT COLOR="#000000">(ADD, SET, REMOVE etc., the above code is for ADD).</FONT>

<FONT COLOR="#000000">I am unsure of the various possibilities of EMF element properties that I </FONT>
<FONT COLOR="#000000">have to take care of here, e.g. things like derived, transient or isMany </FONT>
<FONT COLOR="#000000">of the structural feature.</FONT>

<FONT COLOR="#000000">I'd appreciate any help or pointers to locations of examples of EMF </FONT>
<FONT COLOR="#000000">reflective API.</FONT>

<FONT COLOR="#000000">Thanks,</FONT>
<FONT COLOR="#000000">-darpan</FONT>


</PRE>
</BLOCKQUOTE>
</BODY>
</HTML>

--=-peTft9HGT7nvWP/oJ0Ya--
Re: Examples of EMF reflective API [message #419908 is a reply to message #419905] Thu, 12 June 2008 11:56 Go to previous messageGo to next message
Ed Merks is currently offline Ed MerksFriend
Messages: 33140
Registered: July 2009
Senior Member
Darpan,

Comments below.

Darpan Saini wrote:
> Hi,
>
> I have two identical UML models and when I change one model I want to
> apply the same change to the other model.
>
> After trying various approaches, the way I do is this is capture the
> Notification from the original model and apply the changes on my
> target model.
A ChangeRecorder does much the same thing.
> I want to do this using the EMF reflective API, but so far I have only
> had limited success because of some of the subtleties involved.
> For example, some of my code looks like this:
>
> EStructuralFeature strucFeature =
> affectedObject.eClass().getEStructuralFeature(featureID);
> if (!strucFeature.isDerived()) {
> EObject eObjectCopy = EcoreUtil.copy(newValueObject);
This already seems a bit tricky. This does a deep copy and what if the
same object is used again...
> if (affectedObject.eIsSet(strucFeature)) {
> if (strucFeature.isMany()) {
> ((EList) affectedObject.eGet(strucFeature))
> .add(eObjectCopy);
How do you know it's supposed to be at the end of the list and not added
say at the beginning?
> } else {
> affectedObject.eSet(strucFeature,
> Collections.singletonList(eObjectCopy));
If it's not a multi-valued, I imagine you'd want to use just the single
value without wrapping it in a list.
> }
> } else {
> affectedObject.eSet(strucFeature, eObjectCopy);
It might be multi-valued...
> }
> }
>
> I basically first create a copy of the newValue of the Notification
> and then try to apply the same kind of Notification change on the new
> model (ADD, SET, REMOVE etc., the above code is for ADD).
>
> I am unsure of the various possibilities of EMF element properties
> that I have to take care of here, e.g. things like derived, transient
> or isMany of the structural feature.
>
> I'd appreciate any help or pointers to locations of examples of EMF
> reflective API.
Things like EcoreUtil.Copier and EcoreUtil.EqualityHelper are good
examples that show all the gory details of what it takes to copy an
object reflective or compare if two objects are equal reflectively.

I'd also suggesting looking into the ChangeRecorder as a way to solve
your problem. It records notifications and create a description of the
set of changes that are needed to revert the model instance back to it's
original state. So you should be able to record changes, fetch the
ChangeDescription, invoke applyAndReverse to get a forward description,
transmit that somewhere else (it's just another model that can be
serialized) and then can be applied by the receiver. For the
applyAndReverse part, some folks have made a copy of the changed model
and the change description itself (they must be copied as a unit with
copyAll, not one by one) and then did the applyAndReverse to the copy so
the original itself is not changed back. There are JUnit tests that
show the ChangeRecorder in action, so those might help.
>
> Thanks,
> -darpan
>
>


Ed Merks
Professional Support: https://www.macromodeling.com/
Re: Examples of EMF reflective API [message #419916 is a reply to message #419908] Fri, 13 June 2008 09:12 Go to previous messageGo to next message
Eclipse UserFriend
Originally posted by: darpan.cmu.edu

Thanks for your detailed response Ed.

I tried doing exactly what you mentioned. Create a ChangeRecorder and then
transmit the serialized ChangeDescription to the other end. However, on
the other end I do get the ChangeDescription but it does not apply the
change on the model.

The line
protected void apply(EObject originalObject, boolean reverse)
{
EStructuralFeature.Internal internalFeature =
(EStructuralFeature.Internal)getFeature();


in FeatureChangeImpl always returns null. I have taken care to have
exactly the same resource paths on both my workspaces. Also, when
serializing the ChangeDescription I serialize the absolute path of the
referenced objects

<?xml version="1.0" encoding="ASCII"?>
<change:ChangeDescription xmi:version="2.0"
xmlns:xmi="http://www.omg.org/XMI"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:change="http://www.eclipse.org/emf/2003/Change"
xmlns:uml="http://www.eclipse.org/uml2/2.1.0/UML">
<objectChanges>
<key
href=" platform:/resource/P1/umlExample1.uml#_r5L5sDkeEd2Xg8WeD-sSI A "/>
<value featureName="packagedElement">
<listChanges index="3" referenceValues="//@objectsToAttach.0"/>
</value>
</objectChanges>
<objectsToAttach xsi:type="uml:Class"/>
</change:ChangeDescription>

Since my project name and uml file name on both the ends is exactly the
same (actually the file is also same - so in theory it should be able to
match the uuid of the uml element).

Unfortunately the call to changeDescription.apply() does not yield any
results.

Any help appreciated.

Thanks,
-darpan
Re: Examples of EMF reflective API [message #419921 is a reply to message #419916] Fri, 13 June 2008 11:21 Go to previous messageGo to next message
Ed Merks is currently offline Ed MerksFriend
Messages: 33140
Registered: July 2009
Senior Member
Darpan,

Comments below.


Darpan Saini wrote:
> Thanks for your detailed response Ed.
>
> I tried doing exactly what you mentioned.
It sure didn't sound that way, or did you change it now?
> Create a ChangeRecorder and then transmit the serialized
> ChangeDescription to the other end.
Did you miss the step to reverse it so that it's a forward description
rather than a reverse one?
> However, on the other end I do get the ChangeDescription but it does
> not apply the change on the model.
Perhaps you did miss it.
>
> The line
> protected void apply(EObject originalObject, boolean reverse)
> {
> EStructuralFeature.Internal internalFeature =
> (EStructuralFeature.Internal)getFeature();
>
> in FeatureChangeImpl always returns null. I have taken care to have
> exactly the same resource paths on both my workspaces. Also, when
> serializing the ChangeDescription I serialize the absolute path of the
> referenced objects
>
> <?xml version="1.0" encoding="ASCII"?>
> <change:ChangeDescription xmi:version="2.0"
> xmlns:xmi="http://www.omg.org/XMI"
> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
> xmlns:change="http://www.eclipse.org/emf/2003/Change"
> xmlns:uml="http://www.eclipse.org/uml2/2.1.0/UML">
> <objectChanges>
> <key
> href=" platform:/resource/P1/umlExample1.uml#_r5L5sDkeEd2Xg8WeD-sSI A "/>
> <value featureName="packagedElement">
> <listChanges index="3" referenceValues="//@objectsToAttach.0"/>
> </value>
> </objectChanges>
> <objectsToAttach xsi:type="uml:Class"/>
> </change:ChangeDescription>
>
> Since my project name and uml file name on both the ends is exactly
> the same (actually the file is also same - so in theory it should be
> able to match the uuid of the uml element).
You can use a URI mapping in the resource set to redirect URIs if necessary.
>
>
> Unfortunately the call to changeDescription.apply() does not yield any
> results.
>
> Any help appreciated.
Did you check the deserialized change description to see if the
references to the uml resource are all resolved properly? I wold expect
the above to attach a new class to the referenced thing (probably a
package).
>
> Thanks,
> -darpan
>
>


Ed Merks
Professional Support: https://www.macromodeling.com/
Re: Examples of EMF reflective API [message #419938 is a reply to message #419921] Fri, 13 June 2008 16:11 Go to previous messageGo to next message
Eclipse UserFriend
Originally posted by: darpan.cmu.edu

Hi Ed,

I am not sure what I missed, because isn't the changeDescription that I
have provided a forward description?

The code that does this is:

public void notifyChanged(Notification notification) {
super.notifyChanged(notification);
try {
Resource res = new XMIResourceImpl(null);
ChangeDescription c = this.endRecording();
if (c != null) {
List<EObject> toBeCopied = new ArrayList<EObject>();
toBeCopied.add(c);
Iterator t = EcoreUtil.copyAll(toBeCopied).iterator();
ChangeDescription toApply =
(ChangeDescription) t.next();
toApply.applyAndReverse();
res.getContents().add(toApply);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
res.save(baos, null);
ModelUpdateEvent2 me2 = new ModelUpdateEvent2();
me2.setByteArray(baos.toByteArray());
EventManager.getInstance().dispatchEventAsynchronous(event);
toApply.applyAndReverse();
}
} catch (IOException e) {
e.printStackTrace();
}

This is in MyChangeRecorder (it extends ChangeRecorder). Note that I just
want to check if I can transmit one change first.

On the other side when I debug I can see that the objectToChange has an
eProperty - proxyURI and that is
platform:/resource/P1/umlExample1.uml#_r5L5sDkeEd2Xg8WeD-sSI A

The code responsible for applying the change on the other end is:
ModelUpdateEvent2 me2 = (ModelUpdateEvent2) e;
ByteArrayInputStream bais = new ByteArrayInputStream(me2.getByteArray());
try {
Resource res = new XMIResourceImpl(null);
res.load(bais, null);
ChangeDescription cd = (ChangeDescription) res.getContents().get(0);
cd.apply();
} catch (IOException e1) {
e1.printStackTrace();
}


Thanks,
-darpan
Re: Examples of EMF reflective API [message #419941 is a reply to message #419938] Fri, 13 June 2008 16:24 Go to previous messageGo to next message
Eclipse UserFriend
Originally posted by: darpan.cmu.edu

I think I am missing something here, on the other end how can I force the
call to resource.load() to force resolving the hrefs instead of creating
proxies?

-darpan
Re: Examples of EMF reflective API [message #419945 is a reply to message #419941] Fri, 13 June 2008 16:46 Go to previous messageGo to next message
Eclipse UserFriend
Originally posted by: darpan.cmu.edu

I tried to call EcoreUtil.resolveAll() on the resource that contains the
changeDescription. This call seems to have no affect on the
changeDescription and I guess thats where the problem lies. Because it
cannot find the package on the other side it cannot apply the change.

However, I am still unsure how I can help the changeDescription resolve
all its proxies after transmitting it to the other side.

Thanks,
-darpan
Re: Examples of EMF reflective API [message #419946 is a reply to message #419938] Fri, 13 June 2008 17:24 Go to previous messageGo to next message
Ed Merks is currently offline Ed MerksFriend
Messages: 33140
Registered: July 2009
Senior Member
Darpan,

Comments below.


Darpan Saini wrote:
> Hi Ed,
>
> I am not sure what I missed, because isn't the changeDescription that
> I have provided a forward description?
I can't tell looking at it which direction it is. A change description
just describes changes. When you record changes, the resulting change
description describes how to change the final (current) state of the
model back to the original (previous) state of the model. So in that
sense, it's a reverse description and that often surprises people. But
just looking at it, you can't say it goes in a particular direction,
e.g., you could have been deleting a contained class...
>
> The code that does this is:
>
> public void notifyChanged(Notification notification) {
> super.notifyChanged(notification);
> try {
> Resource res = new XMIResourceImpl(null);
This kind of thing concerns me. You should be using a resource set and
creating a resource with a URI. using a factory.
ResourceSet.createResource is the typical way to create a new resource.
> ChangeDescription c = this.endRecording();
> if (c != null) {
> List<EObject> toBeCopied = new ArrayList<EObject>();
> toBeCopied.add(c);
> Iterator t = EcoreUtil.copyAll(toBeCopied).iterator();
> ChangeDescription toApply = (ChangeDescription) t.next();
> toApply.applyAndReverse();
> res.getContents().add(toApply);
> ByteArrayOutputStream baos = new ByteArrayOutputStream();
> res.save(baos, null);
> ModelUpdateEvent2 me2 = new ModelUpdateEvent2();
> me2.setByteArray(baos.toByteArray());
> EventManager.getInstance().dispatchEventAsynchronous(event);
> toApply.applyAndReverse();
The whole copying thing is kind of pointless if you don't copy the model
to which it applies as well. It's okay to do it like this, just don't
bother copying it.
> }
> } catch (IOException e) {
> e.printStackTrace();
> }
>
> This is in MyChangeRecorder (it extends ChangeRecorder). Note that I
> just want to check if I can transmit one change first.
> On the other side when I debug I can see that the objectToChange has
> an eProperty - proxyURI and that is
> platform:/resource/P1/umlExample1.uml#_r5L5sDkeEd2Xg8WeD-sSI A
>
> The code responsible for applying the change on the other end is:
> ModelUpdateEvent2 me2 = (ModelUpdateEvent2) e;
> ByteArrayInputStream bais = new ByteArrayInputStream(me2.getByteArray());
> try {
> Resource res = new XMIResourceImpl(null);
The resource set isn't just a good idea here, it's crucial because you
won't be able to resolve proxies unless there's a containing resource
set in which which ResourceSet.getEObject can be called to resolve proxies.
> res.load(bais, null);
> ChangeDescription cd = (ChangeDescription) res.getContents().get(0);
> cd.apply();
> } catch (IOException e1) {
> e1.printStackTrace();
> }
>
>
> Thanks,
> -darpan
>


Ed Merks
Professional Support: https://www.macromodeling.com/
Re: Examples of EMF reflective API [message #419949 is a reply to message #419946] Fri, 13 June 2008 18:03 Go to previous message
Eclipse UserFriend
Originally posted by: darpan.cmu.edu

Ed,

You are the man!!

It works when I create the resource using my model's resource set and do
the same thing on the other side.

The only thing I have to figure out now is when to stop and resume
recording, to avoid making copies of the model. I do a
changeDescrition.applyAndReverse twice to bring the original model into
the changed state but between the two applications I serialize and send
out the changeDescription itself.

I really appreciate your fast responses.

Thanks,
-darpan
Previous Topic:[CDO] Dynamic models
Next Topic:Validation of Meta- and Instance Models
Goto Forum:
  


Current Time: Thu Apr 25 12:58:04 GMT 2024

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

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

Back to the top