| <html> |
| <head> |
| <title>Extensions</title> |
| <link href="book.css" rel="stylesheet" type="text/css"/> |
| <meta content="DocBook XSL Stylesheets V1.75.1" name="generator"/> |
| <link rel="home" href="index.html" title="Xpand Documentation"/> |
| <link rel="up" href="emf_tutorial.html" title="Getting Started"/> |
| <link rel="prev" href="emf_tutorial_checking_contraints_with_check.html" title="Checking Constraints with the Check Language"/> |
| <link rel="next" href="Reference.html" title="Part I. Reference"/> |
| </head> |
| <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"> |
| <h1 xmlns:l="http://docbook.sourceforge.net/xmlns/l10n/1.0">Extensions</h1> |
| <div class="section" title="Extensions"> |
| <div class="titlepage"> |
| <div> |
| <div> |
| <h2 class="title" style="clear: both"> |
| <a name="emf_tutorial_extensions"/>Extensions</h2> |
| </div> |
| </div> |
| </div> |
| <p>It is often the case that you need additional properties in the |
| templates; these properties should not be added to the metaclasses |
| directly, since they are often specific to the specific code generation |
| target and thus should not "pollute" the metamodel.</p> |
| <p>It is possible to define such extensions<a name="N104BB" class="indexterm"/> external to the metaclasses. For details see the |
| <span class="emphasis"> |
| <em>Xtend Language Documentation</em> |
| </span>, we provide an simple |
| example here.</p> |
| <div class="section" title="Expression Extensions"> |
| <div class="titlepage"> |
| <div> |
| <div> |
| <h3 class="title"> |
| <a name="emf_tutorial_expression_extensions"/>Expression Extensions</h3> |
| </div> |
| </div> |
| </div> |
| <p>Assume we wanted to change the <span class="emphasis"> |
| <em>Attribute</em> |
| </span>s |
| part of the template as follows:</p> |
| <pre class="programlisting">«FOREACH attribute AS a» |
| private «a.type» «a.name»; |
| |
| public void «a.setterName()»( «a.type» value ) { |
| this.«a.name» = value; |
| } |
| |
| public «a.type» «a.getterName()»() { |
| return this.«a.name»; |
| } |
| «ENDFOREACH»</pre> |
| <p>To make this work, we need to define the |
| <code class="methodname">setterName()</code> and |
| <code class="methodname">getterName()</code> operations. We do this by writing |
| a so-called extension file; we call it <code class="filename">java.ext</code>. It |
| must have the <code class="filename">.ext</code> suffix to be recognized by |
| Xpand; the <span class="emphasis"> |
| <em>Java</em> |
| </span> name is because it contains |
| Java-generation specific properties. We put this file directly into the |
| <code class="filename">templates</code> directory under |
| <code class="filename">src</code>, i.e. directly next to the |
| <code class="filename">Root.xpt</code> file. The extension file looks as |
| follows:</p> |
| <p>First, we have to import the data metamodel; otherwise we would |
| not be able to use the <span class="emphasis"> |
| <em>Attribute</em> |
| </span> metaclass.</p> |
| <pre class="programlisting">import data;</pre> |
| <p>We can then define the two new operations |
| <code class="methodname">setterName</code> and |
| <code class="methodname">getterName</code>. Note that they take the type on |
| which they are called as their first parameter, a kind of "explicitly |
| this". After the colon we use an expression that returns the |
| to-be-defined value.</p> |
| <pre class="programlisting">String setterName(Attribute ele) : |
| 'set'+ele.name.toFirstUpper(); |
| |
| String getterName(Attribute ele) : |
| 'get'+ele.name.toFirstUpper();</pre> |
| <p>To make these extensions work, we have to add the following line |
| to the beginning of the <code class="filename">Root.xpt</code> template |
| file:</p> |
| <pre class="programlisting">«EXTENSION templates::java»</pre> |
| </div> |
| <div class="section" title="Java Extensions"> |
| <div class="titlepage"> |
| <div> |
| <div> |
| <h3 class="title"> |
| <a name="emf_tutorial_java_extensions"/>Java Extensions<a name="N10509" class="indexterm"/> |
| </h3> |
| </div> |
| </div> |
| </div> |
| <p>In case you cannot express the "business logic" for the expression |
| with the expression language, you can fall back to Java. Take a look at |
| the following extension definition file. It is called |
| <code class="filename">util.ext</code> and is located in <code class="filename">src/datamodel/generator/util</code>:</p> |
| <pre class="programlisting">String timestamp() : |
| JAVA datamodel.generator.util.TemplateUtils.timestamp();</pre> |
| <p>Here, we define an extension that is independent of a specific |
| model element, since it does not have a formal parameter! The |
| implementation of the extension is delegated to a static operation of a |
| Java class. Here is its implementation:</p> |
| <pre class="programlisting">public class TemplateUtils { |
| public static String timestamp() { |
| return String.valueOf( System.currentTimeMillis() ); |
| } |
| }</pre> |
| <p>This element can be used independent of any model element – it is |
| available globally.</p> |
| <p>Sometimes, it is necessary to access extensions not just from |
| templates and other Xtend files but also from Java code. The following |
| example is of this kind: We want to define properties that derive the |
| name of the implementation class from the entity name itself. The best |
| practice for this use case is to implement the derived property as a |
| Java method, as above. The following piece of code declares properties |
| for <code class="classname">Entity</code>:</p> |
| <pre class="programlisting">package datamodel; |
| |
| import data.Entity; |
| |
| public class EntityHelper { |
| |
| public static String className( Entity e ) { |
| return e.getName()+"Implementation"; |
| } |
| |
| public static String classFileName( Entity e ) { |
| return className(e)+".java"; |
| } |
| |
| }</pre> |
| <p>In addition, to access the properties from the template files, we |
| define an extension that uses the helper methods. The |
| <code class="filename">helper.ext</code> file is located right next to the helper |
| class shown above, i.e. in the <span class="package">datamodel</span> |
| package:</p> |
| <pre class="programlisting">import data; |
| |
| String className( Entity e ) : |
| JAVA datamodel.EntityHelper.className(data.Entity); |
| |
| String classFileName( Entity e ) : |
| JAVA datamodel.EntityHelper.classFileName(data.Entity);</pre> |
| <p>In addition to these new properties being accessible from Java |
| code by invoking <code class="code">EntityHelper.className(someEntity)</code>, we can |
| now write the following template:</p> |
| <pre class="programlisting">«EXTENSION templates::java» |
| «EXTENSION datamodel::generator::util::util» |
| «EXTENSION datamodel::helper» |
| |
| «DEFINE Root FOR data::DataModel» |
| «EXPAND Entity FOREACH entity» |
| «ENDDEFINE» |
| |
| «DEFINE Entity FOR data::Entity» |
| «FILE classFileName()» |
| // generated at «timestamp()» |
| public abstract class «className()» { |
| «FOREACH attribute AS a» |
| private «a.type» «a.name»; |
| public void «a.setterName()»( «a.type» value ) { |
| this.«a.name» = value; |
| } |
| |
| public «a.type» «a.getterName()»() { |
| return this.«a.name»; |
| } |
| «ENDFOREACH» |
| } |
| «ENDFILE» |
| «ENDDEFINE»</pre> |
| <p>For completeness, the following illustration shows the resulting |
| directory and file structure. </p> |
| <div class="figure"> |
| <a name="emf_tutorial_what_happened_so_far"/> |
| <p class="title"> |
| <b>Figure 17. What has happened so far</b> |
| </p> |
| <div class="figure-contents"> |
| <div class="mediaobject"> |
| <img src="images/emf_tutorial/generator_structure_so_far.png" alt="What has happened so far"/> |
| </div> |
| </div> |
| </div> |
| <p> |
| <br class="figure-break"/> |
| </p> |
| </div> |
| </div> |
| </body> |
| </html> |