eclipseeclipse-emf-ecoremetamodelacceleo

Acceleo transformation using a custom ecore metamodel


First of all , i am new to the modeling features of eclipse, so the question may be trivial, but i am searching for days and haven't found an answer.

I have created an ecore metamodel file with an ecore modeling project. The URI is this : /com.auth.dotnetPSM.PSMmodel/model/PSMMetamodel.ecore

I have also generated (via an ATL transformation) an xmi model file. the first element is like this:

<?xml version="1.0" encoding="ISO-8859-1"?>
<RESTfulServicePSM
    xmi:version="2.0" 
    xmlns:xmi="http://www.omg.org/XMI" 
    xmlns="/com.auth.dotnetPSM.PSMmodel/model/PSMMetamodel.ecore" 
    name="WSAT">

In the ATL project everything is working as expected.

Now i need to create an M2T transformation using Acceleo. So for starters, i created two modules, a main :

[comment encoding = UTF-8 /]

[module PsmToCode('/com.auth.dotnetPSM.PSMmodel/model/PSMMetamodel.ecore')]
[import org::eclipse::acceleo::psm2code::files::ResourceModelClasses/]

[template public PsmToCode(aRESTfulServicePSM : RESTfulServicePSM)]
[comment @main/]
[for ( aCSharpResourceModel : CSharpResourceModel | aRESTfulServicePSM.hasCSharpRModel)]
        [aCSharpResourceModel.generateResourceModelClasses()/]
 [/for]
[/template]

and another one:

[comment encoding = UTF-8 /]
[module ResourceModelClasses('/com.auth.dotnetPSM.PSMmodel/model/PSMMetamodel.ecore')]

[template public generateResourceModelClasses(aCSharpResourceModel : CSharpResourceModel)]

[file (aCSharpResourceModel.parentName.toUpperFirst().concat('.cs'), false, 'UTF-8')]

[/file]
[/template]

When i run this, i get a Package with uri '/com.auth.dotnetPSM.PSMmodel/model/PSMMetamodel.ecore' not found. (file:/H:/Users/doumas/workspace/PIM2PSM/WSATPSM.xmi, 6, 15) exception. What am i doing wrong?

Thanks in advance.


Solution

  • You probably have the .ecore for your metamodel and you didn't generate the metamodel code (using .genmodel). The error you have occurs when you try to open your .xmi file using an EMF tool (Acceleo/QVT...etc). So, many points here ;).

    You can deal with static or dynamic instances of your metamodel.

    Static instances

    Static instances are produced when you generate the code of your metamodel (using a .genmodel), you register your project as plugin and you create model that conforms to your deployed metamodel. In this case, your metamodel is deployed as an Eclipse plugin and your metamodel is registered in a global registry when the plugin is loaded by Eclipse. In your dev mode routine, the simpliest way of defining your metamodel and developing stuffs around it is to handle two eclipse instances. The first one (I will call it the "original" instance) is the one where your metamodel project is. The second one is launched through the run new eclipse configuration menu from the original instance (I will call it the "new" instance). So, here is the routine:

    1. You create your metamodel
    2. You generate the .genmodel linked to your metamodel
    3. You generate the metamodel code
    4. You launch your "new" eclipse instance from the original one
    5. You go through the file->new->other->Example Model EMF Creation Wizard->your_stuff wizard to create your model

    Now, your model is created and your metamodel is registered in the global registry, so Acceleo file will compile well and your model will be openeable/readeable by any EMF compliant application without extra work. This method is long but it's also the easiest.

    If you only want to deal with one Eclipse instance and if you have your metamodel code generated, you can also perform this:

    1. Link your acceleo project to your metamodel project
    2. Modify the java file generated by Acceleo and add this in the registerPackages method: resourceSet.getPackageRegistry().put(SomethingPackage.eINSTANCE.getNsURI(), SomethingPackage.eINSTANCE);

    This will register your metamodel and the Acceleo transformation should run without any issue. However, I'm not sure this manual step is required if you link your Acceleo project to your metamodel project. I think Acceleo can deal with the metamodel by itself if the metamodel project is in the same workspace (but in case, you can do it manually).

    Dynamic instances

    In the case you described, you are dealing with dynamic instances. It means that the metamodel code is not generated. ATL can handle dynamic instances so, that's why you were able to generate an .xmi. By the way, you can create an .xmi by opening your metamodel, select your root EClass and click on right_click->Create dynamic instance....

    If you want to deal with this type of instances, you have to register your metamodel manually for Acceleo. To do this, you have to modify the java file generated by Acceleo and add this in the registerPackages method:

    File file = new File("path/to/your/metamodel.ecore"); 
    EObject obj = ModelUtils.load(file, resourceSet); 
    resourceSet.getPackageRegistry().put("metamodel_ns_uri", obj); 
    

    (ModelUtils comes from org.eclipse.acceleo.common.utils) Using this, you could be able to generate code from Acceleo with dynamic instance.

    Also, just a quick word on Acceleo, if your RESTfulServicePSM instances will not generate code, you can directly put your @main annotation on your generateResourceModelClasses template directly. The Acceleo engine will iterate on each CSharpResourceModel instances by itself. Oh, and you can put many @main annotations on many templates, they will be evaluated ;).

    EDIT> I've just seen your problem is fixed, I should have look. Sorry for the long post.