Jump to: navigation, search

Difference between revisions of "Acceleo/FAQ"

m (how to write '[' or ']' in the generated code)
(Trying to make sense of dynamic vs static overriding.)
 
(33 intermediate revisions by 4 users not shown)
Line 1: Line 1:
 +
=The Java launcher class is not generated=
 +
Acceleo generates and maintains the Java launcher for each Acceleo module with a main template. A main template is defined as a template with the following comment "[comment @main/]".
 +
You can create a main module by using the Acceleo Main Module wizard or by selecting "main template" in the regular Acceleo Module wizard. If you remove this comment, the Java launcher will not be synchronized anymore, if you change the metamodel used in your module, Acceleo will not register it in the Java launcher, etc.
 +
 +
=My metamodel is not found by Acceleo=
 +
If you encounter the following errors in the Java launcher.
 +
 +
  a.b.c.d cannot be resolved to a type
 +
  a.b.c.d.XXXXX cannot be resolved to a type
 +
  The method isInWorkspace(Class<? extends EPackage>) in the type AbstractAcceleoGenerator is not applicable for the arguments (Class<XXXX>)
 +
 +
You need a dependency with the plugin "a.b.c.d" to use the element of the metamodel it contains.
 +
Have a look a the MANIFEST.MF file and in its "dependencies" tab, you should add the dependency to "a.b.c.d"
 +
 
=My generation fails with a 'package not found' exception=
 
=My generation fails with a 'package not found' exception=
 
'''Q''' : Whenever I launch an Acceleo generation, it fails with the message ''package with URI '*' not found'.
 
'''Q''' : Whenever I launch an Acceleo generation, it fails with the message ''package with URI '*' not found'.
Line 65: Line 79:
 
         }
 
         }
 
    
 
    
         URIConverter.URI_MAP.put(URI.createURI("http://www.eclipse.org/acceleo/mtl/3.0/mtlstdlib.ecore"), URI.createURI(libraryLocation + "/model/mtlstdlib.ecore"));
+
         URIConverter.URI_MAP.put(URI.createURI("http://www.eclipse.org/acceleo/mtl/3.0/mtlstdlib.ecore"),
         URIConverter.URI_MAP.put(URI.createURI("http://www.eclipse.org/acceleo/mtl/3.0/mtlnonstdlib.ecore"), URI.createURI(libraryLocation + "/model/mtlnonstdlib.ecore"));
+
                                URI.createURI(libraryLocation + "/model/mtlstdlib.ecore"));
 +
         URIConverter.URI_MAP.put(URI.createURI("http://www.eclipse.org/acceleo/mtl/3.0/mtlnonstdlib.ecore"),
 +
                                URI.createURI(libraryLocation + "/model/mtlnonstdlib.ecore"));
 
       } else {
 
       } else {
 
         System.err.println("Coudln't retrieve location of plugin 'org.eclipse.acceleo.model'.");
 
         System.err.println("Coudln't retrieve location of plugin 'org.eclipse.acceleo.model'.");
Line 102: Line 118:
  
 
=How to write '[' or ']' in the generated code?=
 
=How to write '[' or ']' in the generated code?=
If you want to have the '[' or the ']' symbols, use ['['/] or [']'/].
+
'''Q''' : I need to generate open brackets ( '''[''' ) or close brackets ( ''']''' ) through Acceleo. How can I escape them?
 +
 
 +
'''A''' : The '''[''' and ''']''' symbols can be generated through respectively '''[ '[' /]''' and '''[ ']' /]'''.
 +
 
 +
=How do I compare data to an enumeration value?=
 +
'''Q''' : I want to know whether a given Class is of private, public or protected visibility, which are defined in the '''VisibilityKind''' Enumeration.
 +
 
 +
'''A''' : You need to qualify the access to the enumeration value. For example, ''if (operation.visibility = '''VisibilityKind::public''')''.
 +
 
 +
= Feature 'startHeaderPosition' not found =
 +
 
 +
  org.eclipse.emf.ecore.xmi.FeatureNotFoundException: Feature 'startHeaderPosition' not found
 +
 
 +
If the feature "startHeaderPosition" is not found it means that you are trying to launch an emtl file compiled by Acceleo 3.1.x in Acceleo 3.0.x. To resolve that problem, you can compile your emtl files with Acceleo 3.0.x or you can tell EMF to ignore the unknown features during the loading.
 +
 
 +
= How to use a Java service in Acceleo =
 +
Acceleo allow the user to call a method from a Java class thanks to the "invoke" operation.
 +
 
 +
[[Image:Acceleo-java-service.png|thumb|none|800px|Java service in Acceleo.]]
 +
 
 +
 
 +
= My query is only executed once =
 +
Queries in Acceleo have their result stored in a cache. If you call a query with the same parameter twice, we won't execute it twice. The second time we will only look for the already computed result in our cache. If you want to invoke a Java service with the same parameters several times in a generation with different results, you should call it from a template.
 +
 
 +
  [template public myJavaService(aString : String)][invoke(...)/][/template]
 +
 
 +
If you really want to use a query or if for performance reason you want to deactivate the cache (the result of all the queries is stored in memory, it can be big if you have a lot of queries on a big model), you can do it programmatically :
 +
 
 +
  AcceleoPreferences.switchQueryCache(false);
 +
 
 +
You can put this code before the launch of your Acceleo generator.
 +
 
 +
= How can I use multiple metamodels in an Acceleo module ? =
 +
 
 +
[[Image:Acceleo_Multiple_Metamodels.png|none|894px|Multiple metamodels]]
 +
 
 +
= How does the overriding system works in Acceleo ? =
 +
 
 +
Acceleo features two different systems in order to overrides the behavior of a template a static one and a dynamic one. Those two mechanism are addressing different kinds of problems:
 +
 
 +
== Static overriding ==
 +
 
 +
Static overriding should be used in order to create a generator. Let's consider the following modules:
 +
 
 +
  module A
 +
  public templateA
 +
  protected templateB
 +
  private templateC
 +
  public templateD
 +
  public queryA
 +
  protected queryB
 +
  private queryC
 +
 
 +
  module B extends A
 +
  public templateD extends templateD
 +
 
 +
With static overriding, the module B has access to:
 +
* moduleA.templateA
 +
* moduleA.templateB
 +
* moduleA.templateD (by calling super in moduleB.templateD)
 +
* moduleA.queryA
 +
* moduleA.queryB
 +
 
 +
It does not have access to private template/queries from the module A.
 +
 
 +
Static overriding feels like overriding in an object oriented language like Java but it is different because modules are not objects, they are more similar to namespaces. In order to see the difference, let's consider the following elements:
 +
 
 +
  --- Java ---
 +
  class A
 +
  methodA {}
 +
  method B {methodA()}
 +
 
 +
  class B extends A
 +
  methodA overrides methodA {}
 +
  methodB overrides methodB {super.methodB}
 +
 
 +
In Java, by calling the methodB on an object B, these are the methods that will be called:
 +
 
 +
* B.methodB (our starting point)
 +
* A.methodB (the call to super)
 +
* B.methodA (the call to methodA in A.methodB is dispatched to the implementation in B)
 +
 
 +
Even if the class A does not know the class B, the call the methodA in a.methodB is dispatched to the subclass B because it is our context. That's the way object oriented programming works.
 +
 
 +
Now let's consider those modules:
 +
 
 +
  --- Acceleo ---
 +
  module A
 +
  templateA
 +
  templateB [templateA/]
 +
 
 +
  module B extends A
 +
  templateA overrides templateA
 +
  templateB overrides templateB [super/]
 +
 
 +
  module C
 +
  import module B
 +
 
 +
 
 +
If you are calling templateB from the module C, these are the templates that will be called:
 +
 
 +
* B.templateB (the entry point)
 +
* A.templateB (the call to super)
 +
* A.templateA (not B.templateA, the call is not dispatched to the "subModule" contrary to Java)
 +
 
 +
The call to templateB will call the templateB in the module A but the keywords "extends" is just a modifier for the visibility of the module elements of the module A in relation to the module B it does not really create a relation between a "module A" and a "module B", those are not objects there are "just" namespaces. You could consider that the "extends" keyword should be used to give a namespace the content of public and protected elements from another namespace.
 +
 
 +
 
 +
== Dynamic overriding ==
 +
 
 +
Dynamic overriding is used thanks to the extension point "org.eclipse.acceleo.engine.dynamic.templates". It is not advisable to use it in order to create a generator, it should mainly be used in order to customize an existing generator. Let's consider that you have a great UML to Java generator but you have to customize the generator for a specific project (specific naming convention for example or maybe you want to generate a specific kind of Java for a J2EE framework). You have several options:
 +
 
 +
* you are generating some Java and JMerge tags (@generated) are enough for you to customize directly the generated code.
 +
* protected areas have been defined in the generator and you just have to change the generated code in the protected area in order to make your project work.
 +
* you need real changes in the generator and you have access to the source code of the generator and redeploying the generator is not a problem, you can create new modules that are extending the old ones and you can import them instead of the old ones, you can change a minimal amount of your generator and you can add the new behavior.
 +
* you don't have access to the code of the generator or you cannot redeploy it. The only solution left is the dynamic overriding.
 +
 
 +
With the dynamic overriding, you can add new modules to an existing generator but those modules and the templates that they contain will be used in priority. For example, let's consider those modules:
 +
 
 +
  --- Acceleo ---
 +
  module A
 +
  templateA
 +
  templateB
 +
 
 +
  module B
 +
  imports moduleA
 +
 
 +
 
 +
  -- The dynamic module in another plugin --
 +
  module C extends moduleA
 +
  templateA
 +
 
 +
If you are calling in your existing generator the templateA from the the moduleB, the dynamic template C.templateA will be used instead. The existing generator does not know about the new generator and it has no dependencies with this other generator but since we have installed the new generator as a plugin in the same Eclipse instance as the existing generator and since the new generator uses the dynamic module extension point, all its templates that are overriding a template from the original generator will be used instead of the original templates. In that way, it is closer to aspect oriented programming. You need to have deployed your existing generator and the new generator in the same Eclipse instance in order to use this mechanism as it is using Eclipse extension points.
 +
 
 +
In summary: While static overriding consists of overriding references to templates / queries, dynamic overriding overrides references to full modules in import statements. The two methods of overriding are not mutually exclusive; one could use static overriding in moduleC, replacing uses of moduleA to moduleC using dynamic overriding. One could refer to these two types of overriding as '''namespace overriding''' versus '''import overriding'''.
 +
 
 +
= Nothing is generated =
 +
Try to use the XMI based serialization: right click on your project -> properties -> acceleo -> check XMI
 +
Binary serialization produce smaller and faster ".emtl" files (Acceleo modules once compiled) but the XMI serialization produce "smarter" files that can handle resolve the URI of the element of the metamodel more easily.
 +
 
 +
= How to programmatically profile a generator =
 +
It is possible to programmatically attach a profiler to a generator.
 +
For example in you UI plugin add the following code around the call to the generator :
 +
 
 +
  --- Java ---
 +
  Profiler profiler = new Profiler();
 +
  AcceleoEngineUtils.setProfiler(profiler);
 +
  AcceleoPreferences.switchProfiler(true);
 +
  generator.doGenerate( ... )
 +
  AcceleoPreferences.switchProfiler(false);
 +
  String profileURI = ... + ".mtlp"; // URI of the profiling results file
 +
  profiler.save(profileURI);
 +
 
 +
 
 +
= Exception in thread "main" java.lang.NoClassDefFoundError: com/google/common/base/Predicate =
 +
Add com.google.collect as a dependency of your generator. (MANIFEST.MF -> Dependencies tab -> Add -> com.google.collect)
 +
 
 +
 
 +
= I can't find my metamodel in the new project/module wizard =
 +
If you have a metamodel in the workspace, and if you want to use it in an Acceleo project, starting with Acceleo 3.2, you can find it in the runtime section of the metamodel selection dialog. You can see an example in the following screenshot:
 +
 
 +
[[Image:Ecoreinworkspace.png|none|600px|]]
 +
 
 +
= Is it possible to change the "start of user code" / "end of user code" generated for a protected area? =
 +
No.
 +
 
 +
= Is it possible to generate in several directories during one generation? =
 +
A regular Acceleo generator has only one output folder. It is possible to use a common ancestor of two folders (for example "A") and to use a longer path for the file to generate (for example "B/C/D/E" and "B/F/G/H") to create a generation in to different folders (here "A/B/C/D/E" and "A/B/F/G/H").
 +
 
 +
= Can we copy files along the generation? =
 +
Acceleo can only generate text, it does not copy files.
 +
 
 +
= How can I access UML stereotype values from Acceleo? =
 +
 
 +
You can use a query such as this one :
 +
 
 +
  [query public getTaggedValue(stereotypedElement : Element, stereotypeName : String, propertyName : String) : OclAny =
 +
    let stereotype : Stereotype = stereotypedElement.getAppliedStereotype(stereotypeName) in
 +
      if not stereotype.oclIsUndefined() then
 +
        stereotypedElement.getValue(stereotype, propertyName)
 +
      else
 +
        null
 +
      endif/]
 +
 
 +
= How can I use Xcore with Acceleo? =
 +
If you want to use a Xcore based meta-model with Acceleo, you need to define a non-relative URI for your package.
 +
  package org.eclipse.xcore.test
 +
 
 +
  class MyClass {
 +
  String name
 +
  }
 +
 
 +
The URI of the package defined above would not work since it is considered by EMF as a relative one (org.eclipse.xcore.test). In order to fix this issue, please use a non relative URI for your Xcore meta-model like this:
 +
  @Ecore(nsURI="http://www.eclipse.org/xcore/test", nsPrefix="xcoretestprefix")
 +
  package org.eclipse.xcore.test
 +
 
 +
  class MyClass {
 +
  String name
 +
  }
 +
 
 +
Please be careful with the case of the properties (nsURI and nsPrefix) since the 1.0 version of Xcore does not validate those properties. Once the code of your meta-model is generated, you can deploy your meta-model in your Eclipse where Acceleo is installed and start working with it.
 +
 
 +
=How can I use UML profiles with my generator?=
 +
In the "registerPackages(...)" method of your Java launcher, you need to "register" the location of the profiles with the following piece of code:
 +
 
 +
  Map uriMap = resourceSet.getURIConverter().getURIMap(); 
 +
  URI uri = URI.createURI("platform:/plugin/org.eclipse.uml2.uml.resources/");
 +
  uriMap.put(URI.createURI(UMLResource.LIBRARIES_PATHMAP), uri.appendSegment("libraries").appendSegment(""));
 +
  uriMap.put(URI.createURI(UMLResource.METAMODELS_PATHMAP), uri.appendSegment("metamodels").appendSegment(""));
 +
  uriMap.put(URI.createURI(UMLResource.PROFILES_PATHMAP), uri.appendSegment("profiles").appendSegment("")); 
 +
 
 +
  // For RTSJ (real time Java)
 +
  uri = URI.createURI("platform:/plugin/org.topcased.uml2rtsj.thirdparty/");
 +
  uriMap.put(URI.createURI("pathmap://RTSJ_PROFILE/rtsj.uml"), uri.appendSegment("profile").appendSegment(""));
 +
 
 +
 
 +
{{Acceleo-index}}
 +
 
 +
[[Category:Modeling]]
 +
[[Category:M2T]]
 +
[[Category:Acceleo]]

Latest revision as of 09:29, 18 December 2012

The Java launcher class is not generated

Acceleo generates and maintains the Java launcher for each Acceleo module with a main template. A main template is defined as a template with the following comment "[comment @main/]". You can create a main module by using the Acceleo Main Module wizard or by selecting "main template" in the regular Acceleo Module wizard. If you remove this comment, the Java launcher will not be synchronized anymore, if you change the metamodel used in your module, Acceleo will not register it in the Java launcher, etc.

My metamodel is not found by Acceleo

If you encounter the following errors in the Java launcher.

 a.b.c.d cannot be resolved to a type
 a.b.c.d.XXXXX cannot be resolved to a type
 The method isInWorkspace(Class<? extends EPackage>) in the type AbstractAcceleoGenerator is not applicable for the arguments (Class<XXXX>)

You need a dependency with the plugin "a.b.c.d" to use the element of the metamodel it contains. Have a look a the MANIFEST.MF file and in its "dependencies" tab, you should add the dependency to "a.b.c.d"

My generation fails with a 'package not found' exception

Q : Whenever I launch an Acceleo generation, it fails with the message package with URI '*' not found'.

A : This error message indicates that the package which NsURI is '*' hasn't been registered in the Package registry. Most of the time, that means you either a) launched your program standalone and didn't register the package correctly or b) you haven't installed the plug-in that provides that metamodel.

Solving it is easy : it is a matter of registering the needed packages (and, optionally, resource factories). How is it done? Here is the most classic example with UML :

Package with uri 'http://www.eclipse.org/uml2/2.1.0/UML' not found.

What do I need to do for my UML model to be loadable :

EPackage.Registry.INSTANCE.put(UMLPackage.eNS_URI, UMLPackage.eINSTANCE); Resource.Factory.Registry.INSTANCE.getExtensionToFactoryMap().put(UMLResource.FILE_EXTENSION, UMLResource.Factory.INSTANCE);

The same goes for every metamodel you might need, simply change UMLPackage by XxxPackage according to your metamodel. The Resource Factory is mandatory for UML, but your metamodel might not need one; simply ignore this line if you don't have a custom factory.

You need these two lines to be before the point where your model is loaded. For Acceleo, this is done in the generated Java launcher : simply change the implementation of the registerPackages and registerResourceFactories method to add these needed lines.

How can I run a generation in a standalone environment?

Q : Can I run an Acceleo generation outside of Eclipse?

A : Yes, Acceleo has been developed with standalone execution in mind. All you have to do is to launch the main method of the generated Java launcher.

How can I compile my mtl files in a standalone environment?

Q : Can I use the Acceleo compiler to recompile mtl files outside of Eclipse?

A : Yes, though this requires a little more work than "simply" launching the generation. The easiest is to define your own ANT task for that job. It should extend the AcceleoCompiler ANT task that's provided along with Acceleo (the latest version of the jar containing this class can be retrieved here, or you could simply look at its source code and reproduce something similar).

The bare minimum your class would need in order to compile mtl files in a standalone environment would be :

 public class AcceleoStandaloneCompiler extends AcceleoCompiler {
   public void execute() throws BuildException {
     registerResourceFactories();
     registerPackages();
     registerLibraries();
 
     super.execute();
   }
 
   public void registerResourceFactories() {
     Resource.Factory.Registry.INSTANCE.getExtensionToFactoryMap().put("ecore", new EcoreResourceFactoryImpl());
     Resource.Factory.Registry.INSTANCE.getExtensionToFactoryMap().put(IAcceleoConstants.EMTL_FILE_EXTENSION, new EMtlResourceFactoryImpl());
 
     // Uncomment the following if you need to use UML models
     // Resource.Factory.Registry.INSTANCE.getExtensionToFactoryMap().put(UMLResource.FILE_EXTENSION, UMLResource.Factory.INSTANCE);
   }
 
   public void registerPackages() {
     // Uncomment if you need to use UML models
     // EPackage.Registry.INSTANCE.put(UMLPackage.eNS_URI, UMLPackage.eINSTANCE);
     // Uncomment if you need to use UML models saved with on old version of MDT/UML (you might need to change the URI's version number)
     // EPackage.Registry.INSTANCE.put("http://www.eclipse.org/uml2/2.1.0/UML", UMLPackage.eINSTANCE);
   }
 
   public void registerLibraries() {
     CodeSource acceleoModel = MtlPackage.class.getProtectionDomain().getCodeSource();
     if (acceleoModel != null) {
       String libraryLocation = acceleoModel.getLocation().toString();
       if (libraryLocation.endsWith(".jar")) {
         libraryLocation = "jar:" + libraryLocation + '!';
       }
 
       URIConverter.URI_MAP.put(URI.createURI("http://www.eclipse.org/acceleo/mtl/3.0/mtlstdlib.ecore"),
                                URI.createURI(libraryLocation + "/model/mtlstdlib.ecore"));
       URIConverter.URI_MAP.put(URI.createURI("http://www.eclipse.org/acceleo/mtl/3.0/mtlnonstdlib.ecore"),
                                URI.createURI(libraryLocation + "/model/mtlnonstdlib.ecore"));
     } else {
       System.err.println("Coudln't retrieve location of plugin 'org.eclipse.acceleo.model'.");
     }
   }
 }

Can Acceleo work with ClearCase?

Q : I have to (re)generate files in (a) project(s) that is versionned using ClearCase. Will Acceleo ask for check out when generating?

A : Yes, but you'll have to cope with two limitations : first, you have to change the generated Java launcher and second, you will no longer be able to launch your generations in a standalone mode. The modification that has to be done is to override the getGenerationStrategy() method of the generated launcher. Specifically, you want it to look like :

 public IAcceleoGenerationStrategy getGenerationStrategy() {
   return new WorkspaceAwareStrategy();
 }

Do not forget to remove the @generated tag from the Javadoc of this method (or change it to @generated NOT)!

How to migrate from Acceleo 2 to Acceleo 3?

Acceleo 3 has some differences with Acceleo 2, especially for the new syntax elements based on the Model-to-text OMG standard.

The question is : How to create the 3.x '.mtl' file from the 2.x '.mt' file?

AcceleoMigrateMigrated.png

The tooling will initialize the migration process... Just right click on the Acceleo 2.x project.

AcceleoMigrateMenu.png

We know that the migration can't be perfect, because the MTL standard is statically typed. Sometimes you need human understanding to provide the right context and get the right equivalence. You will probably have to change the way you organize your code generators. We are confident that Acceleo 2.x users will move easily to Acceleo 3.0.

Don't worry, the Acceleo Team will continue to maintain the 2.x syntax of Acceleo. However, the new major versions and the new features will take place on Eclipse.org.

There aren't a lot of differences between the old version of acceleo and the new one. It's not so long to migrate from a syntax to another. Acceleo 3.0 comes with an equivalence documentation.

How to write '[' or ']' in the generated code?

Q : I need to generate open brackets ( [ ) or close brackets ( ] ) through Acceleo. How can I escape them?

A : The [ and ] symbols can be generated through respectively [ '[' /] and [ ']' /].

How do I compare data to an enumeration value?

Q : I want to know whether a given Class is of private, public or protected visibility, which are defined in the VisibilityKind Enumeration.

A : You need to qualify the access to the enumeration value. For example, if (operation.visibility = VisibilityKind::public).

Feature 'startHeaderPosition' not found

  org.eclipse.emf.ecore.xmi.FeatureNotFoundException: Feature 'startHeaderPosition' not found

If the feature "startHeaderPosition" is not found it means that you are trying to launch an emtl file compiled by Acceleo 3.1.x in Acceleo 3.0.x. To resolve that problem, you can compile your emtl files with Acceleo 3.0.x or you can tell EMF to ignore the unknown features during the loading.

How to use a Java service in Acceleo

Acceleo allow the user to call a method from a Java class thanks to the "invoke" operation.

Java service in Acceleo.


My query is only executed once

Queries in Acceleo have their result stored in a cache. If you call a query with the same parameter twice, we won't execute it twice. The second time we will only look for the already computed result in our cache. If you want to invoke a Java service with the same parameters several times in a generation with different results, you should call it from a template.

 [template public myJavaService(aString : String)][invoke(...)/][/template]

If you really want to use a query or if for performance reason you want to deactivate the cache (the result of all the queries is stored in memory, it can be big if you have a lot of queries on a big model), you can do it programmatically :

  AcceleoPreferences.switchQueryCache(false);

You can put this code before the launch of your Acceleo generator.

How can I use multiple metamodels in an Acceleo module ?

Multiple metamodels

How does the overriding system works in Acceleo ?

Acceleo features two different systems in order to overrides the behavior of a template a static one and a dynamic one. Those two mechanism are addressing different kinds of problems:

Static overriding

Static overriding should be used in order to create a generator. Let's consider the following modules:

 module A
 public templateA
 protected templateB
 private templateC
 public templateD
 public queryA
 protected queryB
 private queryC
 
 module B extends A
 public templateD extends templateD

With static overriding, the module B has access to:

  • moduleA.templateA
  • moduleA.templateB
  • moduleA.templateD (by calling super in moduleB.templateD)
  • moduleA.queryA
  • moduleA.queryB

It does not have access to private template/queries from the module A.

Static overriding feels like overriding in an object oriented language like Java but it is different because modules are not objects, they are more similar to namespaces. In order to see the difference, let's consider the following elements:

 --- Java ---
 class A
 methodA {}
 method B {methodA()}
 
 class B extends A
 methodA overrides methodA {}
 methodB overrides methodB {super.methodB}

In Java, by calling the methodB on an object B, these are the methods that will be called:

  • B.methodB (our starting point)
  • A.methodB (the call to super)
  • B.methodA (the call to methodA in A.methodB is dispatched to the implementation in B)

Even if the class A does not know the class B, the call the methodA in a.methodB is dispatched to the subclass B because it is our context. That's the way object oriented programming works.

Now let's consider those modules:

 --- Acceleo ---
 module A
 templateA
 templateB [templateA/]
 
 module B extends A
 templateA overrides templateA
 templateB overrides templateB [super/]
 
 module C
 import module B


If you are calling templateB from the module C, these are the templates that will be called:

  • B.templateB (the entry point)
  • A.templateB (the call to super)
  • A.templateA (not B.templateA, the call is not dispatched to the "subModule" contrary to Java)

The call to templateB will call the templateB in the module A but the keywords "extends" is just a modifier for the visibility of the module elements of the module A in relation to the module B it does not really create a relation between a "module A" and a "module B", those are not objects there are "just" namespaces. You could consider that the "extends" keyword should be used to give a namespace the content of public and protected elements from another namespace.


Dynamic overriding

Dynamic overriding is used thanks to the extension point "org.eclipse.acceleo.engine.dynamic.templates". It is not advisable to use it in order to create a generator, it should mainly be used in order to customize an existing generator. Let's consider that you have a great UML to Java generator but you have to customize the generator for a specific project (specific naming convention for example or maybe you want to generate a specific kind of Java for a J2EE framework). You have several options:

  • you are generating some Java and JMerge tags (@generated) are enough for you to customize directly the generated code.
  • protected areas have been defined in the generator and you just have to change the generated code in the protected area in order to make your project work.
  • you need real changes in the generator and you have access to the source code of the generator and redeploying the generator is not a problem, you can create new modules that are extending the old ones and you can import them instead of the old ones, you can change a minimal amount of your generator and you can add the new behavior.
  • you don't have access to the code of the generator or you cannot redeploy it. The only solution left is the dynamic overriding.

With the dynamic overriding, you can add new modules to an existing generator but those modules and the templates that they contain will be used in priority. For example, let's consider those modules:

 --- Acceleo ---
 module A
 templateA
 templateB
 
 module B
 imports moduleA
 
 
 -- The dynamic module in another plugin --
 module C extends moduleA
 templateA

If you are calling in your existing generator the templateA from the the moduleB, the dynamic template C.templateA will be used instead. The existing generator does not know about the new generator and it has no dependencies with this other generator but since we have installed the new generator as a plugin in the same Eclipse instance as the existing generator and since the new generator uses the dynamic module extension point, all its templates that are overriding a template from the original generator will be used instead of the original templates. In that way, it is closer to aspect oriented programming. You need to have deployed your existing generator and the new generator in the same Eclipse instance in order to use this mechanism as it is using Eclipse extension points.

In summary: While static overriding consists of overriding references to templates / queries, dynamic overriding overrides references to full modules in import statements. The two methods of overriding are not mutually exclusive; one could use static overriding in moduleC, replacing uses of moduleA to moduleC using dynamic overriding. One could refer to these two types of overriding as namespace overriding versus import overriding.

Nothing is generated

Try to use the XMI based serialization: right click on your project -> properties -> acceleo -> check XMI Binary serialization produce smaller and faster ".emtl" files (Acceleo modules once compiled) but the XMI serialization produce "smarter" files that can handle resolve the URI of the element of the metamodel more easily.

How to programmatically profile a generator

It is possible to programmatically attach a profiler to a generator. For example in you UI plugin add the following code around the call to the generator :

 --- Java ---
 Profiler profiler = new Profiler();
 AcceleoEngineUtils.setProfiler(profiler);
 AcceleoPreferences.switchProfiler(true);
 generator.doGenerate( ... )
 AcceleoPreferences.switchProfiler(false);
 String profileURI = ... + ".mtlp"; // URI of the profiling results file
 profiler.save(profileURI);


Exception in thread "main" java.lang.NoClassDefFoundError: com/google/common/base/Predicate

Add com.google.collect as a dependency of your generator. (MANIFEST.MF -> Dependencies tab -> Add -> com.google.collect)


I can't find my metamodel in the new project/module wizard

If you have a metamodel in the workspace, and if you want to use it in an Acceleo project, starting with Acceleo 3.2, you can find it in the runtime section of the metamodel selection dialog. You can see an example in the following screenshot:

Ecoreinworkspace.png

Is it possible to change the "start of user code" / "end of user code" generated for a protected area?

No.

Is it possible to generate in several directories during one generation?

A regular Acceleo generator has only one output folder. It is possible to use a common ancestor of two folders (for example "A") and to use a longer path for the file to generate (for example "B/C/D/E" and "B/F/G/H") to create a generation in to different folders (here "A/B/C/D/E" and "A/B/F/G/H").

Can we copy files along the generation?

Acceleo can only generate text, it does not copy files.

How can I access UML stereotype values from Acceleo?

You can use a query such as this one :

 [query public getTaggedValue(stereotypedElement : Element, stereotypeName : String, propertyName : String) : OclAny = 
   let stereotype : Stereotype = stereotypedElement.getAppliedStereotype(stereotypeName) in
     if not stereotype.oclIsUndefined() then
       stereotypedElement.getValue(stereotype, propertyName)
     else 
       null
     endif/]

How can I use Xcore with Acceleo?

If you want to use a Xcore based meta-model with Acceleo, you need to define a non-relative URI for your package.

 package org.eclipse.xcore.test
 
 class MyClass {
 	String name
 }

The URI of the package defined above would not work since it is considered by EMF as a relative one (org.eclipse.xcore.test). In order to fix this issue, please use a non relative URI for your Xcore meta-model like this:

 @Ecore(nsURI="http://www.eclipse.org/xcore/test", nsPrefix="xcoretestprefix")
 package org.eclipse.xcore.test
 
 class MyClass {
 	String name
 }

Please be careful with the case of the properties (nsURI and nsPrefix) since the 1.0 version of Xcore does not validate those properties. Once the code of your meta-model is generated, you can deploy your meta-model in your Eclipse where Acceleo is installed and start working with it.

How can I use UML profiles with my generator?

In the "registerPackages(...)" method of your Java launcher, you need to "register" the location of the profiles with the following piece of code:

 Map uriMap = resourceSet.getURIConverter().getURIMap();  
 URI uri = URI.createURI("platform:/plugin/org.eclipse.uml2.uml.resources/");
 uriMap.put(URI.createURI(UMLResource.LIBRARIES_PATHMAP), uri.appendSegment("libraries").appendSegment(""));
 uriMap.put(URI.createURI(UMLResource.METAMODELS_PATHMAP), uri.appendSegment("metamodels").appendSegment(""));
 uriMap.put(URI.createURI(UMLResource.PROFILES_PATHMAP), uri.appendSegment("profiles").appendSegment(""));  
 
 // For RTSJ (real time Java)
 uri = URI.createURI("platform:/plugin/org.topcased.uml2rtsj.thirdparty/");
 uriMap.put(URI.createURI("pathmap://RTSJ_PROFILE/rtsj.uml"), uri.appendSegment("profile").appendSegment(""));



Acceleo Portal
Project Project · Installation · New & noteworthy · Release review · API policy · Retention policy · Next · Checklist
Features Acceleo Features · Runtime · Acceleo editor · Views & Perspective · Debugger · Profiler · Traceability · Wishlist · Interpreter · Maven
User documentation Getting Started · Acceleo operations reference · OCL operations reference · Text Production Rules · Migration From Acceleo 2.x · Best Practices · Videos · FAQ
Developer documentation Source code · How to contribute · Compatibility · MOFM2T specification · OCL specification
Community Conferences · Twitter & Blogs · Professional Support · Report a bug