Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » EMF » Programatically refactoring ecore models
Programatically refactoring ecore models [message #423283] Fri, 26 September 2008 08:00 Go to next message
Andrew H is currently offline Andrew HFriend
Messages: 117
Registered: July 2009
Senior Member
I am in the process of splitting a large ecore model into several ecore
models. I am doing this in a number of steps and hit something odd.

For one step I am basically moving packages into subpackages and also
moving some classes into different packages.
I am using the ecore to ecore mappings mainly cause I could use the UI to
do the mapping but am reading and processing the mappings myself.
On the target ecore side is a skeleton package hierarchy. The mappings map
either a package or a set of classes from the source model into a pacakge
on the target model.
The main processing code looks somewhat like this

private void process(Mapping mapping) {
EList<EObject> inputs = mapping.getInputs();
for (EObject i : inputs) {
if (i instanceof EPackage) {
EPackage inputPackage = (EPackage)i;
outPackage.getESubpackages().add(inputPackage);
}
else if (i instanceof EClassifier) {
EClassifier inputClassifier = (EClassifier)i;
outPackage.getEClassifiers().add(inputClassifier);
}
}
}

After this has finished I then split the target model up so that every
package is in its own ecore file as follows

public void createResources(EPackage pkg, String baseNSURI, String
ecoreFileDirPath) throws IOException {
String packagePath = ecoreFileDirPath + "/" + pkg.getName();
String packageNSURI = baseNSURI + "/" + pkg.getName();
pkg.setNsURI(packageNSURI);
pkg.setNsPrefix(pkg.getName());
createFileResourceFor(packagePath + ".ecore", pkg);
EList<EPackage> subpackages = pkg.getESubpackages();
for (EPackage child : subpackages) {
createResources(child, packageNSURI, packagePath);
}
}

And then I save it. It works but many of the serialised references are
pointing to the old ecore files.

e.g.
<eClassifiers xsi:type="ecore:EClass" name="Foo"
eSuperTypes="../../oldecorefile.ecore#//Bar">

However, when I tried to debug this by doing the following from inside
process method, the problem went away for many of the cases. So it seems
there must be a cached reference somewhere that gets reevaluated when I
access the classes.

private void touch(EClassifier classifier) {
System.err.println("touching classifier " + classifier);
if (classifier instanceof EClass) {
EClass c = (EClass)classifier;
EList<EClass> superTypes = c.getESuperTypes();
for (EClass parent : superTypes) {
System.out.println("supertype " + parent);
}

EList<EStructuralFeature> features = c.getEStructuralFeatures();
for (EStructuralFeature sf : features) {
System.out.println("feature " + sf);
sf.getEType();
}

}
}

So what am I doing wrong and what should I be doing to get this to work?
Re: Programatically refactoring ecore models [message #423292 is a reply to message #423283] Fri, 26 September 2008 11:42 Go to previous messageGo to next message
Ed Merks is currently offline Ed MerksFriend
Messages: 31557
Registered: July 2009
Senior Member
This is a multi-part message in MIME format.
--------------070709020409040504060807
Content-Type: text/plain; charset=ISO-8859-15; format=flowed
Content-Transfer-Encoding: 7bit

Andrew,

Comments below.

Andrew H wrote:
> I am in the process of splitting a large ecore model into several
> ecore models. I am doing this in a number of steps and hit something odd.
I imagine this is fairly painful!
>
> For one step I am basically moving packages into subpackages and also
> moving some classes into different packages. I am using the ecore to
> ecore mappings mainly cause I could use the UI to do the mapping but
> am reading and processing the mappings myself.
I see. (It didn't help that there was a bug in the recipe, which is now
fixed.)
> On the target ecore side is a skeleton package hierarchy. The mappings
> map either a package or a set of classes from the source model into a
> pacakge on the target model.
> The main processing code looks somewhat like this
>
> private void process(Mapping mapping) {
> EList<EObject> inputs = mapping.getInputs();
> for (EObject i : inputs) {
> if (i instanceof EPackage) {
> EPackage inputPackage = (EPackage)i;
> outPackage.getESubpackages().add(inputPackage);
Keep in mind that adding the inputPackage as child of the outPackage
will remove it from any container it currently has. So if
inputPackage.eContainer() != null before, this might well be a bad approach.
> }
> else if (i instanceof EClassifier) {
> EClassifier inputClassifier = (EClassifier)i;
> outPackage.getEClassifiers().add(inputClassifier);
> }
> }
> }
>
> After this has finished I then split the target model up so that every
> package is in its own ecore file as follows
>
> public void createResources(EPackage pkg, String baseNSURI, String
> ecoreFileDirPath) throws IOException {
> String packagePath = ecoreFileDirPath + "/" + pkg.getName();
> String packageNSURI = baseNSURI + "/" + pkg.getName();
> pkg.setNsURI(packageNSURI);
> pkg.setNsPrefix(pkg.getName());
> createFileResourceFor(packagePath + ".ecore", pkg);
> EList<EPackage> subpackages = pkg.getESubpackages();
> for (EPackage child : subpackages) {
> createResources(child, packageNSURI, packagePath);
> }
> }
Note that EPackage.eSubpackages supports cross resource containment
(resolveProxies is true) and hence adding the subpackage to a different
resource doesn't remove it from its container...
>
> And then I save it. It works but many of the serialised references are
> pointing to the old ecore files.
Are you saving after having put *everything *in a new resource?
>
> e.g. <eClassifiers xsi:type="ecore:EClass" name="Foo"
> eSuperTypes="../../oldecorefile.ecore#//Bar">
>
> However, when I tried to debug this by doing the following from inside
> process method, the problem went away for many of the cases. So it
> seems there must be a cached reference somewhere that gets reevaluated
> when I access the classes.
Keep in mind too that proxies are resolve on demand. So if you don't do
something to resolve them, they'll indeed cache exactly the URI
(although resolved against the URI of the containing document to make it
absolute) as it had in the file.
>
> private void touch(EClassifier classifier) {
> System.err.println("touching classifier " + classifier);
> if (classifier instanceof EClass) {
> EClass c = (EClass)classifier;
> EList<EClass> superTypes = c.getESuperTypes();
> for (EClass parent : superTypes) {
> System.out.println("supertype " + parent);
> }
>
> EList<EStructuralFeature> features = c.getEStructuralFeatures();
> for (EStructuralFeature sf : features) {
> System.out.println("feature " + sf);
> sf.getEType();
> }
>
> }
> }
>
> So what am I doing wrong and what should I be doing to get this to work?
Calling EcoreUtil.resolveAll on the resource set or resource before you
being tearing it apart will ensure that all proxies are resolve and that
no objects will be holding references to proxies with cached old URIs.
>
>

--------------070709020409040504060807
Content-Type: text/html; charset=ISO-8859-15
Content-Transfer-Encoding: 8bit

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta content="text/html;charset=ISO-8859-15"
http-equiv="Content-Type">
</head>
<body bgcolor="#ffffff" text="#000000">
Andrew,<br>
<br>
Comments below.<br>
<br>
Andrew H wrote:
<blockquote
cite="mid:b9830b772b7fae8fb1ed26dbb33537c5$1@www.eclipse.org"
type="cite">I am in the process of splitting a large ecore model into
several ecore models. I am doing this in a number of steps and hit
something odd.
<br>
</blockquote>
I imagine this is fairly painful!<br>
<blockquote
cite="mid:b9830b772b7fae8fb1ed26dbb33537c5$1@www.eclipse.org"
type="cite"><br>
For one step I am basically moving packages into subpackages and also
moving some classes into different packages. I am using the ecore to
ecore mappings mainly cause I could use the UI to do the mapping but am
reading and processing the mappings myself.
<br>
</blockquote>
I see.


Ed Merks
Professional Support: https://www.macromodeling.com/
Re: Programatically refactoring ecore models [message #423335 is a reply to message #423292] Mon, 29 September 2008 01:48 Go to previous messageGo to next message
Andrew H is currently offline Andrew HFriend
Messages: 117
Registered: July 2009
Senior Member
Thanks Ed

The EcoreUtil.resolveAll seemed to fix the problem.

BTW I haven't been able to find any doco on how to execute an ecore2ecore
mapping. i.e. once I have created an ecore2ecore mapping then how do I run
that on a source model?

Further comments inline

Ed Merks wrote:

> Andrew,

> Comments below.

> Andrew H wrote:
>> I am in the process of splitting a large ecore model into several
>> ecore models. I am doing this in a number of steps and hit something odd.
> I imagine this is fairly painful!

Somewhat. Would have been much easier if the original schemas were broken
down well into a hierarchy of packages.

>>
>> For one step I am basically moving packages into subpackages and also
>> moving some classes into different packages. I am using the ecore to
>> ecore mappings mainly cause I could use the UI to do the mapping but
>> am reading and processing the mappings myself.
> I see. (It didn't help that there was a bug in tEcoreUtil.resolveAllhe
recipe, which is now
> fixed.)

Wasn't aware of that. I don't think I ran into a bug??

>> On the target ecore side is a skeleton package hierarchy. The mappings
>> map either a package or a set of classes from the source model into a
>> pacakge on the target model.
>> The main processing code looks somewhat like this
>>
>> private void process(Mapping mapping) {
>> EList<EObject> inputs = mapping.getInputs();
>> for (EObject i : inputs) {
>> if (i instanceof EPackage) {
>> EPackage inputPackage = (EPackage)i;
>> outPackage.getESubpackages().add(inputPackage);
> Keep in mind that adding the inputPackage as child of the outPackage
> will remove it from any container it currently has. So if
> inputPackage.eContainer() != null before, this might well be a bad approach.

Yeah I'm aware of that and in fact relying on it. Its really a trick for
minimising the amount of work I need to do to do the refactoring.
Basically I load the ecore files in one resource set, then manipulate them
and save them in a different resource set. The first resource set is then
tossed.

The intent is actually to treat them as copies but it cuts down on a fair
bit of code this way I believe. i.e. I can just pick up a package with all
its children and stick it in a new ecore file and make it the child of
another package.

I do concede though that it would be cleaner to actually make copies.

>> }
>> else if (i instanceof EClassifier) {
>> EClassifier inputClassifier = (EClassifier)i;
>> outPackage.getEClassifiers().add(inputClassifier);
>> }
>> }
>> }
>>
>> After this has finished I then split the target model up so that every
>> package is in its own ecore file as follows
>>
>> public void createResources(EPackage pkg, String baseNSURI, String
>> ecoreFileDirPath) throws IOException {
>> String packagePath = ecoreFileDirPath + "/" + pkg.getName();
>> String packageNSURI = baseNSURI + "/" + pkg.getName();
>> pkg.setNsURI(packageNSURI);
>> pkg.setNsPrefix(pkg.getName());
>> createFileResourceFor(packagePath + ".ecore", pkg);
>> EList<EPackage> subpackages = pkg.getESubpackages();
>> for (EPackage child : subpackages) {
>> createResources(child, packageNSURI, packagePath);
>> }
>> }
> Note that EPackage.eSubpackages supports cross resource containment
> (resolveProxies is true) and hence adding the subpackage to a different
> resource doesn't remove it from its container...

I put every package in a new ecore file (one package per file). I am
assuming that when I do resource.getContents().add(pkg), that it will be
unplugged from the old resource and plugged into the new.

>>
>> And then I save it. It works but many of the serialised references are
>> pointing to the old ecore files.
> Are you saving after having put *everything *in a new resource?

Yes. Every package is now in a separate resource in the one resource set.
Then I save the whole resource set.

>>
>> e.g. <eClassifiers xsi:type="ecore:EClass" name="Foo"
>> eSuperTypes="../../oldecorefile.ecore#//Bar">
>>
>> However, when I tried to debug this by doing the following from inside
>> process method, the problem went away for many of the cases. So it
>> seems there must be a cached reference somewhere that gets reevaluated
>> when I access the classes.
> Keep in mind too that proxies are resolve on demand. So if you don't do
> something to resolve them, they'll indeed cache exactly the URI
> (although resolved against the URI of the containing document to make it
> absolute) as it had in the file.

This must have been what bit me.

>>
>> private void touch(EClassifier classifier) {
>> System.err.println("touching classifier " + classifier);
>> if (classifier instanceof EClass) {
>> EClass c = (EClass)classifier;
>> EList<EClass> superTypes = c.getESuperTypes();
>> for (EClass parent : superTypes) {
>> System.out.println("supertype " + parent);
>> }
>>
>> EList<EStructuralFeature> features = c.getEStructuralFeatures();
>> for (EStructuralFeature sf : features) {
>> System.out.println("feature " + sf);
>> sf.getEType();
>> }
>>
>> }
>> }
>>
>> So what am I doing wrong and what should I be doing to get this to work?
> Calling EcoreUtil.resolveAll on the resource set or resource before you
> being tearing it apart will ensure that all proxies are resolve and that
> no objects will be holding references to proxies with cached old URIs.


This did the trick. thanks
Re: Programatically refactoring ecore models [message #423347 is a reply to message #423335] Mon, 29 September 2008 11:30 Go to previous message
Ed Merks is currently offline Ed MerksFriend
Messages: 31557
Registered: July 2009
Senior Member
This is a multi-part message in MIME format.
--------------070803030904050004000809
Content-Type: text/plain; charset=ISO-8859-15; format=flowed
Content-Transfer-Encoding: 7bit

Andrew,

This recipe show one use of ecore2ecore mapping.
<http://wiki.eclipse.org/EMF/Recipes#Recipe:_Data_Migration>

http://wiki.eclipse.org/EMF/Recipes#Recipe:_Data_Migration

By themselves, mappings are purely declarative. They don't do or mean
anything, but can act as input to something else that gives them
specific meaning...


Andrew H wrote:
> Thanks Ed
>
> The EcoreUtil.resolveAll seemed to fix the problem.
>
> BTW I haven't been able to find any doco on how to execute an
> ecore2ecore mapping. i.e. once I have created an ecore2ecore mapping
> then how do I run that on a source model?
>
> Further comments inline
>
> Ed Merks wrote:
>
>> Andrew,
>
>> Comments below.
>
>> Andrew H wrote:
>>> I am in the process of splitting a large ecore model into several
>>> ecore models. I am doing this in a number of steps and hit something
>>> odd.
>> I imagine this is fairly painful!
>
> Somewhat. Would have been much easier if the original schemas were
> broken down well into a hierarchy of packages.
>
>>>
>>> For one step I am basically moving packages into subpackages and
>>> also moving some classes into different packages. I am using the
>>> ecore to ecore mappings mainly cause I could use the UI to do the
>>> mapping but am reading and processing the mappings myself.
>> I see. (It didn't help that there was a bug in tEcoreUtil.resolveAllhe
> recipe, which is now
>> fixed.)
>
> Wasn't aware of that. I don't think I ran into a bug??
>
>>> On the target ecore side is a skeleton package hierarchy. The
>>> mappings map either a package or a set of classes from the source
>>> model into a pacakge on the target model.
>>> The main processing code looks somewhat like this
>>>
>>> private void process(Mapping mapping) {
>>> EList<EObject> inputs = mapping.getInputs();
>>> for (EObject i : inputs) {
>>> if (i instanceof EPackage) {
>>> EPackage inputPackage = (EPackage)i;
>>> outPackage.getESubpackages().add(inputPackage);
>> Keep in mind that adding the inputPackage as child of the outPackage
>> will remove it from any container it currently has. So if
>> inputPackage.eContainer() != null before, this might well be a bad
>> approach.
>
> Yeah I'm aware of that and in fact relying on it. Its really a trick
> for minimising the amount of work I need to do to do the refactoring.
> Basically I load the ecore files in one resource set, then manipulate
> them and save them in a different resource set. The first resource set
> is then tossed.
>
> The intent is actually to treat them as copies but it cuts down on a
> fair bit of code this way I believe. i.e. I can just pick up a package
> with all its children and stick it in a new ecore file and make it the
> child of another package.
>
> I do concede though that it would be cleaner to actually make copies.
>
>>> }
>>> else if (i instanceof EClassifier) {
>>> EClassifier inputClassifier = (EClassifier)i;
>>> outPackage.getEClassifiers().add(inputClassifier);
>>> }
>>> }
>>> }
>>>
>>> After this has finished I then split the target model up so that
>>> every package is in its own ecore file as follows
>>>
>>> public void createResources(EPackage pkg, String baseNSURI, String
>>> ecoreFileDirPath) throws IOException {
>>> String packagePath = ecoreFileDirPath + "/" + pkg.getName();
>>> String packageNSURI = baseNSURI + "/" + pkg.getName();
>>> pkg.setNsURI(packageNSURI);
>>> pkg.setNsPrefix(pkg.getName());
>>> createFileResourceFor(packagePath + ".ecore", pkg);
>>> EList<EPackage> subpackages = pkg.getESubpackages();
>>> for (EPackage child : subpackages) {
>>> createResources(child, packageNSURI, packagePath);
>>> }
>>> }
>> Note that EPackage.eSubpackages supports cross resource containment
>> (resolveProxies is true) and hence adding the subpackage to a
>> different resource doesn't remove it from its container...
>
> I put every package in a new ecore file (one package per file). I am
> assuming that when I do resource.getContents().add(pkg), that it will
> be unplugged from the old resource and plugged into the new.
>
>>>
>>> And then I save it. It works but many of the serialised references
>>> are pointing to the old ecore files.
>> Are you saving after having put *everything *in a new resource?
>
> Yes. Every package is now in a separate resource in the one resource
> set. Then I save the whole resource set.
>
>>>
>>> e.g. <eClassifiers xsi:type="ecore:EClass" name="Foo"
>>> eSuperTypes="../../oldecorefile.ecore#//Bar">
>>>
>>> However, when I tried to debug this by doing the following from inside
>>> process method, the problem went away for many of the cases. So it
>>> seems there must be a cached reference somewhere that gets
>>> reevaluated when I access the classes.
>> Keep in mind too that proxies are resolve on demand. So if you don't
>> do something to resolve them, they'll indeed cache exactly the URI
>> (although resolved against the URI of the containing document to make
>> it absolute) as it had in the file.
>
> This must have been what bit me.
>
>>>
>>> private void touch(EClassifier classifier) {
>>> System.err.println("touching classifier " + classifier);
>>> if (classifier instanceof EClass) {
>>> EClass c = (EClass)classifier;
>>> EList<EClass> superTypes = c.getESuperTypes();
>>> for (EClass parent : superTypes) {
>>> System.out.println("supertype " + parent);
>>> }
>>> EList<EStructuralFeature> features =
>>> c.getEStructuralFeatures();
>>> for (EStructuralFeature sf : features) {
>>> System.out.println("feature " + sf);
>>> sf.getEType();
>>> }
>>> } }
>>>
>>> So what am I doing wrong and what should I be doing to get this to
>>> work?
>> Calling EcoreUtil.resolveAll on the resource set or resource before
>> you being tearing it apart will ensure that all proxies are resolve
>> and that no objects will be holding references to proxies with cached
>> old URIs.
>
>
> This did the trick. thanks
>

--------------070803030904050004000809
Content-Type: text/html; charset=ISO-8859-15
Content-Transfer-Encoding: 8bit

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta content="text/html;charset=ISO-8859-15"
http-equiv="Content-Type">
</head>
<body bgcolor="#ffffff" text="#000000">
Andrew,<br>
<br>
This recipe show one use of ecore2ecore mapping.<a
href="http://wiki.eclipse.org/EMF/Recipes#Recipe:_Data_Migration"><br>
</a>
<blockquote><a
href="http://wiki.eclipse.org/EMF/Recipes#Recipe:_Data_Migration">http://wiki.eclipse.org/EMF/Recipes#Recipe:_Data_Migration</a><br>
</blockquote>
By themselves, mappings are purely declarative.


Ed Merks
Professional Support: https://www.macromodeling.com/
Previous Topic:modify generated code or subclass?
Next Topic:Wrapping character values using SimleAnyType
Goto Forum:
  


Current Time: Wed Oct 28 06:44:37 GMT 2020

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

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

Back to the top