blob: b8f86c899b4bf09f625f67138c39e483119f83d1 [file] [log] [blame]
<?xml version="1.0" encoding="UTF-8"?>
<chapter id="core_reference" xreflabel="Core reference">
<title><emphasis>Xpand</emphasis> / <emphasis>Xtend</emphasis> /
<emphasis>Check</emphasis> Reference</title>
<section id="r10_introduction">
<title>Introduction</title>
<para>The <emphasis>Xpand</emphasis> generator framework provides textual
languages, that are useful in different contexts in the MDSD process (e.g.
validation, metamodel extensions, code generation, model transformation).
Each language (<emphasis>Check</emphasis>, <emphasis>Xtend</emphasis>, and
<emphasis>Xpand</emphasis>) is built upon a common expression language and
type system. Therefore, they can operate on the same models, metamodels
and meta-metamodels and you do not need to learn the syntax again and
again, because it is always the same.</para>
<para>The expressions framework provides a uniform abstraction layer over
different meta-meta-models (e.g. EMF Ecore, Eclipse UML2, JavaBeans, XML
Schema etc.). Additionally, it offers a powerful, statically typed
expressions language, which is used in the various textual
languages.</para>
</section>
<section id="r10_typesystem">
<title>Type System <indexterm>
<primary>Type</primary>
<secondary>Data type</secondary>
</indexterm> <indexterm>
<primary>Type</primary>
<secondary>Parameterized type</secondary>
</indexterm></title>
<para>The abstraction layer on API basis is called a type system. It
provides access to built-in types and different registered metamodel
implementations. These registered metamodel implementations offer access
to the types they provide. The first part of this documentation describes
the type system. The expression sub-language is described afterwards in
the second part of this documentation. This differentiation is necessary
because the type system and the expression language are two different
things. The type system is a kind of reflection layer, that can be
extended with metamodel implementations. The expression language defines a
concrete syntax for executable expressions, using the type system.</para>
<para>The Java API described here is located in the
<package>org.eclipse.xpand.type</package> package and is a part of the
subproject <package>core.expressions</package>.</para>
<section id="r10_typesystem_types">
<title>Types</title>
<para>Every object (e.g. model elements, values, etc.) has a type. A
type contains properties and operations. In addition it might inherit
from other types (multiple inheritance is also possible, depending on
the underlying meta-meta-model).</para>
<section id="r10_typesystem_typenames">
<title>Type Names</title>
<para>Types have a simple name (e.g. <classname>String</classname>)
and an optional namespace used to distingish between two types with
the same name (e.g. <classname>my::metamodel</classname>). The
delimiter for name space fragments is a double colon
"<classname>::</classname>". A fully qualified name looks like this:
<programlisting language="xtend">my::fully::qualified::MetaType</programlisting></para>
<para>The namespace and name used by a specific type is defined by the
corresponding <classname>MetaModel</classname><indexterm>
<primary>MetaModel</primary>
</indexterm> implementation. The <classname>EmfMetaModel<indexterm>
<primary>EmfMetaModel</primary>
</indexterm></classname>, for instance, maps
<classname>EPackages</classname> to namespace and
<classname>EClassifiers</classname> to names.<indexterm>
<primary>EPackages</primary>
</indexterm> <indexterm>
<primary>EClassifiers</primary>
</indexterm> Therefore, the name of the Ecore element
<classname>EClassifier</classname> is called:</para>
<programlisting>ecore::EClassifier</programlisting>
<para>If you do not want to use namespaces (for whatever reason), you
can always implement your own metamodel and map the names
accordingly.</para>
</section>
<section id="r10_typesystem_collection_typenames">
<title>Collection Type Names</title>
<para>The built-in type system also contains the following collection
types<indexterm>
<primary>Collection type</primary>
</indexterm>: <classname>Collection</classname>,
<classname>List</classname> and <classname>Set</classname>. Because
the expressions language is statically type checked and we do not like
casts and <classname>ClassCastExceptions</classname>, we introduced
the concept of <emphasis>parameterized types</emphasis>. The type
system does not support full featured generics, because we do not need
them.</para>
<para>The syntax is:</para>
<programlisting>Collection[my::Type]
List[my::Type]
Set[my::Type]
</programlisting>
</section>
<section id="r10_typesystem_features">
<title>Features</title>
<para>Each type offers features. The type (resp. the metamodel) is
responsible for mapping the features. There are three different kinds
of features: <itemizedlist>
<listitem>
<para>Properties</para>
</listitem>
<listitem>
<para>Operations</para>
</listitem>
<listitem>
<para>Static properties</para>
</listitem>
</itemizedlist></para>
<para><emphasis>Properties</emphasis><indexterm>
<primary>Type</primary>
<secondary>Property</secondary>
</indexterm> are straight forward: They have a name and a type. They
can be invoked on instances of the corresponding type. The same is
true for <emphasis>Operations</emphasis><indexterm>
<primary>Type</primary>
<secondary>Operation</secondary>
</indexterm>. But in contrast to properties, they can have
parameters. <emphasis>Static properties</emphasis> <indexterm>
<primary>Type</primary>
<secondary>Static property</secondary>
</indexterm>are the equivalent to enums or constants. They must be
invoked statically and they do not have parameters.</para>
</section>
</section>
<section id="r10_builtintypes">
<title>Built-In Types<indexterm>
<primary>Built-in type</primary>
</indexterm></title>
<para>As mentioned before, the expressions framework has several
built-in types that define operations and properties. In the following,
we will give a rough overview of the types and their features. We will
not document all of the operations here, because the built-in types will
evolve over time and we want to derive the documentation from the
implementation (model-driven, of course). For a complete reference,
consult the generated <link linkend="???">API
documentation</link>.</para>
<section id="r10_builtintypes_object">
<title><classname>Object<indexterm>
<primary>Built-in type</primary>
<secondary>Object</secondary>
</indexterm></classname></title>
<para><classname>Object</classname> defines a couple of basic
operations, like <methodname>equals()</methodname>. The property
metaType provides access to Xpand's type for that Object. Every type
has to extend <classname>Object</classname>.</para>
</section>
<section id="r10_builtintypes_void">
<title><classname>Void</classname><indexterm>
<primary>Built-in type</primary>
<secondary>Void</secondary>
</indexterm></title>
<para>The <classname>Void</classname> type can be specified as the
return type for operations, although it is not recommended, because
whenever possible expressions should be free of side effects whenever
possible. The only possible value is <varname>null</varname>.
Sometimes it might be useful to use <classname>Void</classname> as an
parameter type, if you want to be able to call a function for
different argument types and also supply a valid implementation when
the function is invoked with <varname>null</varname>.</para>
</section>
<section id="r10_builtintypes_simple">
<title>Simple types (Data types)</title>
<indexterm>
<primary>Built-in type</primary>
<secondary>Simple type</secondary>
</indexterm>
<para>The type system doesn't have a concept data type. Data types are
just types. As in OCL, we support the following types:
<classname>String</classname>, <classname>Boolean</classname>,
<classname>Integer</classname>, <classname>Real</classname>.
<itemizedlist>
<listitem>
<para><classname>String</classname><indexterm>
<primary>String type</primary>
</indexterm>: A rich and convenient
<classname>String</classname> library is especially important
for code generation. The type system supports the '+' operator
for concatenation, the usual
<classname>java.lang.String</classname> operations
(<methodname>length()</methodname>, etc.) and some special
operations (like <methodname>toFirstUpper()</methodname>,
<methodname>toFirstLower()</methodname>, regular expressions,
etc. often needed in code generation templates).</para>
</listitem>
<listitem>
<para><classname>Boolean</classname><indexterm>
<primary>Boolean type</primary>
</indexterm>: <classname>Boolean</classname> offers the usual
operators (Java syntax): &amp;&amp;, ||, !, etc.</para>
</listitem>
<listitem>
<para><classname>Integer</classname><indexterm>
<primary>Integer type</primary>
</indexterm> and <classname>Real</classname><indexterm>
<primary>Real type</primary>
</indexterm>: <classname>Integer</classname> and
<classname>Real</classname> offer the usual compare operators
(&lt;,&gt;,&lt;=,&gt;=) and simple arithmetics (+,-,*,/). Note
that <emphasis><classname>Integer</classname> extends
<classname>Real</classname>!</emphasis></para>
</listitem>
</itemizedlist></para>
</section>
<section id="r10_builtintypes_collections">
<title>Collection types</title>
<indexterm>
<primary>Built-in type</primary>
<secondary>Collection types</secondary>
</indexterm>
<para>The type system has three different Collection types.
<classname>Collection</classname><indexterm>
<primary>Collection</primary>
</indexterm> is the base type, it provides several operations known
from <classname>java.util.Collection</classname>. The other two types
(<classname>List</classname><indexterm>
<primary>List</primary>
</indexterm>, <classname>Set<indexterm>
<primary>Set type</primary>
</indexterm></classname>) correspond to their
<package>java.util</package> equivalents, too.</para>
</section>
<section id="r10_builtintypes_typesystem_types">
<title>Type system types</title>
<para>The type system describes itself, hence, there are types for the
different concepts. These types are needed for reflective programming.
To avoid confusion with metatypes with the same name (it is not
unusual to have a metatype called <classname>Operation</classname>,
for instance) we have prefixed all of the types with the namespace
<classname>xpand2</classname>. We have:</para>
<itemizedlist>
<listitem>
<para><classname>xpand2::Type</classname></para>
</listitem>
<listitem>
<para><classname>xpand2::Feature</classname></para>
</listitem>
<listitem>
<para><classname>xpand2::Property</classname></para>
</listitem>
<listitem>
<para><classname>xpand2::StaticProperty</classname></para>
</listitem>
<listitem>
<para><classname>xpand2::Operation</classname></para>
</listitem>
</itemizedlist>
<para>You should be aware that if you name a type by name in an
expression the object you get is in fact an
<classname>xpand2::Type</classname>. A common use case is to prove
that an object is of some type or its subtype, using the
<methodname>instanceOf()</methodname> operation or exactly of one
type.</para>
<para><programlisting language="java">// results to true, if the result of someExpression is of type MyType or its subtypes
MyType.isInstance(someExpression)
// results to true, if the result of someExpression is exactly of type MyType
someExpression.metaType == MyType</programlisting>Note that this should be
only used when really required. The recommended way to handle
alternative implementations for a type hierarchy is using <link
linkend="???">Multiple Dispatch</link>.</para>
</section>
</section>
<section id="r10_metamodel_implementations">
<title>Metamodel Implementations (also known as
Meta-Metamodels)<indexterm>
<primary>Metamodel implementation</primary>
</indexterm></title>
<para>By default, the type system only knows the <link
linkend="???">built-in types</link>. In order to register your own
metatypes (e.g. <classname>Entity</classname> or
<classname>State</classname>), you need to register a respective
metamodel implementation with the type system. Within a metamodel
implementation the <emphasis>Xpand</emphasis> type system elements
(<classname>Type</classname>, <classname>Property</classname>,
<indexterm>
<primary>property</primary>
</indexterm><classname> Operation) </classname><indexterm>
<primary>Operation</primary>
</indexterm> are mapped to an arbitrary other type system (e.g. Java
reflections, Ecore or XML Schema).</para>
<section id="r10_metamodel_example_java">
<title>Example JavaMetaModel</title>
<para>For instance, if you want to have the following JavaBean act as
a metatype (i.e. your model contains instances of the type):</para>
<programlisting language="java">public class Attribute {
private String name;
private String type;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
}
</programlisting>
<para>You need to use the <classname>JavaMetaModel</classname>
<indexterm>
<primary>JavaMetaModel</primary>
</indexterm> implementation which uses the ordinary Java reflection
layer in order to map access to the model.</para>
<para>So, if you have the following expression in e.g.
<emphasis>Xpand</emphasis>:</para>
<programlisting>myattr.name.toFirstUpper()</programlisting>
<para>and <varname>myattr</varname> is the name of a local variable
pointing to an instance of <classname>Attribute</classname>. The
<emphasis>Xpand</emphasis> type system asks the metamodel
implementations, if they 'know' a type for the instance of Attribute.
If you have the <classname>JavaMetaModel</classname> registered it
will return an <classname>xpand2::Type</classname> which maps to the
underlying Java class. When the type is asked if it knows a property
'<varname>name</varname>', it will inspect the Java class using the
Java reflection API.</para>
<para>The JavaMetaModel implementation shipped with
<emphasis>Xpand</emphasis> can be configured with a strategy
[GOF95-Pattern] in order to control or change the mapping. For
instance, the <classname>JavaBeansStrategy</classname> maps getter and
setter methods to simple properties, so we would use this strategy for
the example above.</para>
</section>
<section id="r10_metamodel_contributors">
<title>Eclipse IDE MetaModelContributors</title>
<para>You should know that for each <classname>Metamodel</classname>
<indexterm>
<primary>Metamodel</primary>
</indexterm>implementation you use at runtime, you need to have a so
called <classname>MetamodelContributor</classname> extension for the
plugins to work with. If you just use one of the standard metamodel
implementations (EMF, UML2 or Java) you don't have to worry about it,
since <emphasis>Xpand</emphasis> is shipped with respective
MetamodelContributors (see the corresponding docs for details). If you
need to implement your own
<classname>MetamodelContributor</classname><indexterm>
<primary>MetamodelContributor</primary>
</indexterm> you should have a look at the Eclipse plug-in reference
doc.</para>
</section>
<section id="r10_metamodel_workflow">
<title>Configuring Metamodel implementations with the workflow</title>
<para>You need to configure your <emphasis>Xpand</emphasis> language
components with the respective metamodel implementations.</para>
<para>A possible configuration of the <classname>Xpand2</classname>
generator component looks like this:</para>
<programlisting language="xml">&lt;component class="org.eclipse.xpand2.Generator"&gt;
&lt;metaModel class="org.eclipse.type.emf.EmfMetaModel"&gt;
&lt;metaModelPackage value="my.generated.MetaModel1Package"/&gt;
&lt;/metaModel&gt;
&lt;metaModel class="org.eclipse.type.emf.EmfMetaModel"&gt;
&lt;metaModelFile value="my/java/package/metamodel2.ecore"/&gt;
&lt;/metaModel&gt;
...
&lt;/component&gt;
</programlisting>
<para>In this example the <classname>EmfMetaModel</classname>
implementation is configured two times. This means that we want to use
two metamodels at the same time, both based on EMF. The
<property>metaModelPackage</property> property is a property that is
specific to the <classname>EmfMetaModel</classname> (located in the
<filename>org.eclipse.xtend.typesystem.emf</filename> plugin). It
points to the generated <classname>EPackages</classname> interface.
The second meta model is configured using the Ecore file. You do no
need to have a generated Ecore model for <emphasis>Xpand</emphasis> in
order to work. The <classname>EmfMetaModel</classname> works with
dynamic EMF models just as it works with generated EMF models.</para>
<para>Note that is recommended to prefer the
<classname>EmfRegistryMetaModel</classname> instead of the
<classname>EmfMetaModel</classname>, although
<classname>EmfMetaModel</classname> is derived from the
<classname>EmfRegistryMetaModel</classname>. Further it is recommended
to use platform URIs (see <ulink
url="http://help.eclipse.org/galileo/topic/org.eclipse.emf.doc/references/javadoc/org/eclipse/emf/common/util/URI.html">API
Doc URI</ulink>) to refer to EMF resources.</para>
<para>The use of platform URIs in the workflow requires setting up EMF
for standalone execution with the
<classname>StandaloneSetup</classname> class from the
<classname>org.eclipse.emf.mwe.utils</classname> plugin. Further,
StandaloneSetup is used to register known EMF packages. An equivalent
workflow configuration for the sample above would look like
this:</para>
<para><programlisting language="xml">&lt;bean class="org.eclipse.emf.mwe.utils.StandaloneSetup"&gt;
&lt;platformUri value=".."/&gt;
&lt;registerGeneratedEPackage value="my.generated.MetaModel1Package"/&gt;
&lt;registerEcoreFile value="platform:/resource/my/java/package/metamodel2.ecore"/&gt;
&lt;/bean&gt;
...
&lt;component class="org.eclipse.xpand2.Generator"&gt;
&lt;metaModel class="org.eclipse.type.emf.EmfRegistryMetaModel"/&gt;
...
&lt;/component&gt;
</programlisting>The <classname>StandaloneSetup</classname> is given the path
to the platform. This is the path to which platform resource URIs are
resolved relative to. It usually points to the workspace or check out
location of the plugin project, which is usually one directory above
the working directory in which a workflow is executed.</para>
<para>Metamodel instances are often shared between different
components that make use of expressions (most notably the Xpand
<classname>Generator</classname>,
<classname>XtendComponent</classname> and
<classname>CheckComponent</classname>). Normally you don't want that a
Metamodel instance configured and instantiated for each workflow
component. MWE lets you instantiate a class using the
<methodname>&lt;bean&gt;</methodname> tag and by giving the bean an id
value, this same instance can be referred to using the idRef
attribute. This would lead to this workflow:</para>
<para><programlisting language="xml">&lt;bean class="org.eclipse.emf.mwe.utils.StandaloneSetup"&gt;
&lt;platformUri value=".."/&gt;
&lt;registerGeneratedEPackage value="my.generated.MetaModel1Package"/&gt;
&lt;registerEcoreFile value="platform:/resource/my/java/package/metamodel2.ecore"/&gt;
&lt;/bean&gt;
&lt;bean id="mm_emf" class="org.eclipse.type.emf.EmfRegistryMetaModel"/&gt;
...
&lt;component class="org.eclipse.xpand2.Generator"&gt;
&lt;metaModel idRef="mm_emf"/&gt;
...
&lt;/component&gt;
</programlisting></para>
</section>
</section>
<section id="r10_using_different_metamodels">
<title>Using different Metamodel implementations (also known as
Meta-Metamodels)</title>
<para>With Xpand you can work on different kinds of Model
representations at the same time in a transparent manner. One can work
with EMF models, XML DOM models, and simple JavaBeans in the same
<emphasis>Xpand</emphasis> template. You just need to configure the
respective MetaModel implementations.</para>
<para>If you want to do so you need to know how the type lookup works.
Let us assume that we have an EMF metamodel <indexterm>
<primary>EMF metamodel</primary>
</indexterm> and a model based on some Java classes. Then the
following would be a possible configuration:</para>
<programlisting language="xml">&lt;component class="org.eclipse.xpand2.Generator"&gt;
&lt;metaModel class="org.eclipse.internal.xtend.type.impl.java.JavaMetaModel"/&gt;
&lt;metaModel class="org.eclipse.xtend.typesystem.emf.EmfRegistryMetaModel"&gt;
&lt;metaModelFile value="my/java/package/metamodel.ecore"/&gt;
&lt;/metaModel&gt;
...
&lt;/component&gt;
</programlisting>
<para>When the runtime needs to access a property of a given object, it
asks the metamodels in the configured order. Let us assume that our
model element is an instance of the Java type
<classname>org.eclipse.emf.ecore.EObject</classname> and it is a dynamic
instance of an EMF EClass <classname>MyType</classname>.</para>
<para>We have <emphasis>three</emphasis> Metamodels: <orderedlist>
<indexterm>
<primary>Metamodel</primary>
</indexterm>
<listitem>
<para>Built-Ins (always the first one)</para>
</listitem>
<listitem>
<para>JavaMetaModel</para>
</listitem>
<listitem>
<para>EMFMetaModel - metamodel.ecore</para>
</listitem>
</orderedlist></para>
<para>The first one will return the type <classname>Object</classname>
(not <classname>java.lang.Object</classname> but
<classname>Object</classname> of <emphasis>Xpand</emphasis>!). At this
point the type <classname>Object</classname> best fits the request, so
it will act as the desired type.</para>
<para>The second metamodel returns a type called
<classname>org::eclipse::emf::ecore::EObject</classname> The type system
will check if the returned type is a specialization of the current
'best-fit' type (<classname>Object</classname>). It is, because it
extends <classname>Object</classname> (Every metatype has to extend
<classname>Object</classname>). At this time the type system assumes
<classname>org::eclipse::emf::ecore::EObject</classname> to be the
desired type.</para>
<para>The third metamodel will return
<classname>metamodel::MyType</classname> which is the desired type. But
unfortunately it doesn't extend
<classname>org::eclipse::emf::ecore::EObject</classname> as it has
nothing to do with those Java types. Instead it extends
<classname>emf::EObject</classname> which extends
<classname>Object</classname>.</para>
<para>We need to swap the configuration of the two metamodels to get the
desired type.</para>
<programlisting language="xml">&lt;component class="org.eclipse.xpand2.Generator"&gt;
&lt;metaModel class="org.eclipse.xtend.typesystem.emf.EmfMetaModel"&gt;
&lt;metaModelFile value="my/java/package/metamodel.ecore"/&gt;
&lt;/metaModel&gt;
&lt;metaModel class="org.eclipse.internal.xtend.type.impl.java.JavaMetaModel"/&gt;
...
&lt;/component&gt;</programlisting>
<para>The order of the metamodels is important for the work within the
Xpand-editors. The metamodels to work with can be configured inside the
<emphasis>Xtend/Xpand</emphasis> -properties dialog. The
<emphasis>Activated metamodel contributors</emphasis> table is a ordered
list. The more specific metamodels have to be placed at the top of the
list. <mediaobject>
<imageobject role="fo">
<imagedata fileref="images/eclipse_integration/projectProperties.png"
scale="80" />
</imageobject>
<imageobject role="html">
<imagedata fileref="images/eclipse_integration/projectProperties.png" />
</imageobject>
</mediaobject></para>
</section>
<section id="metamodel_reference" xreflabel="Metamodel reference">
<title>Metamodel Reference</title>
<indexterm>
<primary>Metamodel</primary>
</indexterm>
<para>In the following, each of the built-in metamodels that come with
<emphasis>Xpand</emphasis> will be documented. Furthermore, there will
be some guidelines on how to implement your own metamodel.</para>
<section id="emf_metamodels" xreflabel="EMF metamodels">
<title>EMF Metamodels</title>
<para>This section will describe the metamodels that can be used for
EMF models. <emphasis role="strong">Please note that you have to
execute one of the setup utility classes, <classname>Setup</classname>
or <classname>StandaloneSetup</classname>, in your workflow before you
can use one of the EMF metamodels.</emphasis></para>
<section id="emfregistry_metamodel" xreflabel="EMF registry metamodel">
<title>The EMF Registry Metamodel
(org.eclipse.xtend.typesystem.emf.EmfRegistryMetaModel)</title>
<indexterm>
<primary>Metamodel</primary>
<secondary>EMF Registry</secondary>
</indexterm>
<indexterm>
<primary>EmfRegistryMetaModel</primary>
</indexterm>
<para>This metamodel looks for the referenced metamodels in the
global EMF model registry. This means, when using this metamodel,
only models that are registered in this global EMF model registry
will be accessible from within the metamodel.</para>
<para>This metamodel provides the following configuration
property:</para>
<table frame="all" id="properties_emfregistrymetamodel">
<title>Properties of
<classname>EmfRegistryMetaModel</classname></title>
<tgroup align="left" cols="2" colsep="1" rowsep="1">
<colspec colname="emfregistrymetamodel_property_name" />
<colspec colname="emfregistrymetamodel_property_description" />
<thead>
<row>
<entry>Name of property</entry>
<entry>Description</entry>
</row>
</thead>
<tbody>
<row>
<entry><varname>useSingleGlobalResourceSet</varname></entry>
<entry>This boolean property determines the way resource
sets are used. If set to <emphasis>true</emphasis>, all
model resources will be stored in a single global resource
set. Otherwise, a separate resource set will be used for
each model resource.</entry>
</row>
</tbody>
</tgroup>
</table>
</section>
<section id="emf_metamodel" xreflabel="EMF metamodel">
<title>The EMF Metamodel
(org.eclipse.xtend.typesystem.emf.EmfMetaModel)</title>
<indexterm>
<primary>Metamodel</primary>
<secondary>EMF</secondary>
</indexterm>
<indexterm>
<primary>EmfMetaModel</primary>
</indexterm>
<para>This metamodel is a specialized version of the <xref
linkend="emfregistry_metamodel" />. In addition to the features of
the former, it allows to specify an unregistered model in different
ways that will be added to the metamodel.</para>
<para>This metamodel provides the following configuration
properties:</para>
<table frame="all" id="properties_emfmetamodel">
<title>Properties of <classname>EmfMetaModel</classname></title>
<tgroup align="left" cols="2" colsep="1" rowsep="1">
<colspec colname="emfmetamodel_property_name" />
<colspec colname="emfmetamodel_property_description" />
<thead>
<row>
<entry>Name of property</entry>
<entry>Description</entry>
</row>
</thead>
<tbody>
<row>
<entry><varname>useSingleGlobalResourceSet</varname></entry>
<entry>This boolean property determines the way resource
sets are used. If set to <emphasis>true</emphasis>, all
model resources will be stored in a single global resource
set. Otherwise, a separate resource set will be used for
each model resource.</entry>
</row>
<row>
<entry><varname>metaModelFile</varname></entry>
<entry>Sets the path to the Ecore file that will be added to
the metamodel.</entry>
</row>
<row>
<entry><varname>metaModelDescriptor</varname></entry>
<entry>Adds a model to the metamodel by specifying the name
of an EPackage descriptor class.</entry>
</row>
<row>
<entry><varname>metaModelPackage</varname></entry>
<entry>Adds a model to the metamodel by specifying the name
of an EPackage.</entry>
</row>
</tbody>
</tgroup>
</table>
</section>
</section>
<section id="uml_metamodels" xreflabel="UML metamodels">
<title>UML Metamodels</title>
<para><emphasis>Xpand</emphasis> also provides several metamodels that
allow to use UML models in conjunction with this model-to-text
generation framework. <emphasis role="strong">Please note that you
have to execute the setup utility class <classname>Setup</classname>
in your workflow before you can use one of the UML
metamodels</emphasis></para>
<section id="uml2_metamodel" xreflabel="UML2 metamodel">
<title>The UML2 Metamodel
(org.eclipse.xtend.typesystem.uml2.UML2MetaModel)</title>
<indexterm>
<primary>Metamodel</primary>
<secondary>UML2</secondary>
</indexterm>
<indexterm>
<primary>UML2MetaModel</primary>
</indexterm>
<para>This metamodel is a specialized version of the <emphasis><xref
linkend="emf_metamodel" /></emphasis>. It provides access to UML2
models, and it has the following configuration properties:</para>
<table frame="all" id="properties_uml2metamodel">
<title>Properties of <classname>UML2MetaModel</classname></title>
<tgroup align="left" cols="2" colsep="1" rowsep="1">
<colspec colname="uml2metamodel_property_name" />
<colspec colname="uml2metamodel_property_description" />
<thead>
<row>
<entry>Name of property</entry>
<entry>Description</entry>
</row>
</thead>
<tbody>
<row>
<entry><varname>useSingleGlobalResourceSet</varname></entry>
<entry>This boolean property determines the way resource
sets are used. If set to <emphasis>true</emphasis>, all
model resources will be stored in a single global resource
set. Otherwise, a separate resource set will be used for
each model resource.</entry>
</row>
<row>
<entry><varname>modelFile</varname></entry>
<entry>Sets the path to the UML2 model file that will be
added to the metamodel.</entry>
</row>
</tbody>
</tgroup>
</table>
<para>This implementation will be rarely used, since usually
profiled UML models will be used and therefore the Profile Metamodel
is.</para>
</section>
<section id="uml2profile_metamodel" xreflabel="UML2 profile metamodel">
<title>The UML2 Profile Metamodel
(org.eclipse.xtend.typesystem.uml2.profile.ProfileMetaModel)</title>
<indexterm>
<primary>Metamodel</primary>
<secondary>UML2</secondary>
</indexterm>
<indexterm>
<primary>ProfileMetaModel</primary>
</indexterm>
<para>This metamodel allows to apply UML profiles to UML2 models,
and extends the UML2 Metamodel. It has the following configuration
properties:</para>
<table frame="all" id="properties_profilemetamodel">
<title>Properties of
<classname>ProfileMetaModel</classname></title>
<tgroup align="left" cols="2" colsep="1" rowsep="1">
<colspec colname="profilemetamodel_property_name" />
<colspec colname="profilemetamodel_property_description" />
<thead>
<row>
<entry>Name of property</entry>
<entry>Description</entry>
</row>
</thead>
<tbody>
<row>
<entry><varname>useSingleGlobalResourceSet</varname></entry>
<entry>This boolean property determines the way resource
sets are used. If set to <emphasis>true</emphasis>, all
model resources will be stored in a single global resource
set. Otherwise, a separate resource set will be used for
each model resource.</entry>
</row>
<row>
<entry><varname>modelFile</varname></entry>
<entry>Sets the path to the UML2 model file that will be
added to the metamodel. Use resource URIs for the
values.</entry>
</row>
<row>
<entry><varname>profile</varname></entry>
<entry>Sets the path to the UML profile that will be applied
to the UML2 model. This property can be used multiple times
if more than one profile is used. Use resource URIs for the
values.</entry>
</row>
</tbody>
</tgroup>
</table>
</section>
<section id="xmi_reader" xreflabel="XMI reader">
<title>The XMI reader
(org.eclipse.xtend.typesystem.uml2.profile.ProfilingExtensions.XmiReader)</title>
<indexterm>
<primary>XMI reader</primary>
</indexterm>
<indexterm>
<primary>XMIReader</primary>
</indexterm>
<para>The XMI reader component is important when working with UML
models. It allows to read out a model stored in an XMI file and put
its contents into a model slot.</para>
<para>The <classname>XMIReader</classname> component provides the
following configurable properties:</para>
<table frame="all" id="properties_xmireader">
<title>Properties of <classname>XMIReader</classname></title>
<tgroup align="left" cols="2" colsep="1" rowsep="1">
<colspec colname="xmireader_property_name" />
<colspec colname="xmireader_property_description" />
<thead>
<row>
<entry>Name of property</entry>
<entry>Description</entry>
</row>
</thead>
<tbody>
<row>
<entry>metaModelFile</entry>
<entry>Sets the path to the Ecore file that will be added to
the metamodel.</entry>
</row>
<row>
<entry>metaModelDescriptor</entry>
<entry>Adds a model to the metamodel by specifying the name
of an EPackage descriptor class.</entry>
</row>
<row>
<entry>metaModelPackage</entry>
<entry>Adds a model to the metamodel by specifying the name
of an EPackage.</entry>
</row>
<row>
<entry>outputSlot</entry>
<entry>Sets the name of the model slot where the read model
will be stored in.</entry>
</row>
<row>
<entry>firstElementOnly</entry>
<entry>This boolean property determines if only the first
model element of the XMI file will be used. If set to
<emphasis>true</emphasis>, only the first model element will
be used, all other elements will be ignored. Otherwise, all
model elements in the XMI file will be used.</entry>
</row>
</tbody>
</tgroup>
</table>
</section>
</section>
<section id="java_metamodel" xreflabel="Java metamodel">
<title>The Java Metamodel
(org.eclipse.internal.xtend.type.impl.java.JavaMetaModel)</title>
<indexterm>
<primary>Metamodel</primary>
<secondary>Java</secondary>
</indexterm>
<indexterm>
<primary>JavaMetaModel</primary>
</indexterm>
<para>The Java metamodel allows normal Java classes as metatypes for
your metamodel. The <classname>JavaMetaClass</classname> uses the
strategy pattern to define how the elements are exactly mapped to the
metamodel elements. There is a class called
<classname>org.eclipse.internal.xtend.type.impl.java.JavaBeansMetaModel</classname>
that is preconfigured with a strategy that maps simple Java beans onto
the metamodel elements.</para>
<para>The Java metamodel has no configurable properties.</para>
</section>
<section id="xsd_metamodel" xreflabel="XSD metamodel">
<title>The XSD Metamodel
(org.eclipse.xtend.typesystem.xsd.XSDMetaModel)</title>
<indexterm>
<primary>Metamodel</primary>
<secondary>XSD</secondary>
</indexterm>
<indexterm>
<primary>XSDMetaModel</primary>
</indexterm>
<para>The XSD metamodel provides access to models implemented in the
XML Schema Definition language. It has the following configuration
properties:</para>
<table frame="all" id="properties_xsdmetamodel">
<title>Properties of <classname>XSDMetaModel</classname></title>
<tgroup align="left" cols="2" colsep="1" rowsep="1">
<colspec colname="xsdmetamodel_property_name" />
<colspec colname="xsdmetamodel_property_description" />
<thead>
<row>
<entry>Name of property</entry>
<entry>Description</entry>
</row>
</thead>
<tbody>
<row>
<entry><varname>id</varname></entry>
<entry>Sets the ID of the current model.</entry>
</row>
<row>
<entry><varname>registerPackagesGlobally</varname></entry>
<entry>This boolean property determines if the model packages
will be registered globally. If set to
<emphasis>true</emphasis>, the model packages will be
registered in the global registry. Otherwise, packages will
not be registered.</entry>
</row>
<row>
<entry><varname>savePackagesPath</varname></entry>
<entry>Sets the path where model packages will be saved (in
XMI format).</entry>
</row>
</tbody>
</tgroup>
</table>
</section>
<section id="implementing_metamodels"
xreflabel="Implementing your own metamodel">
<title>Implementing Your Own Metamodel</title>
<indexterm>
<primary>Metamodel</primary>
<secondary>Implementing metamodels</secondary>
</indexterm>
<para>The <emphasis>Xpand</emphasis> framework also allows you to
integrate new metamodel implementations. This section quickly outlines
the steps that have to be taken in order to implement a
metamodel:</para>
<orderedlist>
<listitem>
<para>Create a class that implements the
<classname>MetaModel</classname> interface.</para>
</listitem>
<listitem>
<para>In order to be able to integrate your metamodel into the
Eclipse UI, you also have to provide a metamodel contributor class
for your metamodel implementation that implements either the
<classname>MetaModelContributor</classname> or the
<classname>MetaModelContributor2</classname> interface.</para>
</listitem>
<listitem>
<para>Finally, you have to extend the
<classname>org.eclipse.xtend.shared.ui.metaModelContributors</classname>
extension point in order to register your metamodel contributor
with the Eclipse UI.</para>
</listitem>
</orderedlist>
</section>
</section>
</section>
<section id="r10_expressions_language" xreflabel="Expressions">
<title>Expressions<indexterm>
<primary>Expression</primary>
</indexterm></title>
<para>The expression sub-language<indexterm>
<primary>Expression language</primary>
</indexterm> is a syntactical mixture of Java and OCL<indexterm>
<primary>OCL</primary>
</indexterm>. This documentation provides a detailed description of each
available expression. Let us start with some simple examples.</para>
<para>Accessing a property:</para>
<programlisting>myModelElement.name</programlisting>
<para>Accessing an operation:</para>
<programlisting>myModelElement.doStuff()</programlisting>
<para>simple arithmetic:</para>
<programlisting>1 + 1 * 2</programlisting>
<para>boolean expressions (just an example:-)):</para>
<programlisting>!('text'.startsWith('t') &amp;&amp; ! false)</programlisting>
<section id="r10_expressions_builtin">
<title>Literals and special operators for built-in types</title>
<para>There are several literals<indexterm>
<primary>Literals</primary>
</indexterm> for built-in types:</para>
<section id="r10_expressions_builtin_object">
<title><classname>Object</classname> <indexterm>
<primary>Built-in type</primary>
<secondary><classname>Object</classname></secondary>
</indexterm> <indexterm>
<primary>Built-in type</primary>
<secondary><classname>Void</classname></secondary>
</indexterm></title>
<para>There are naturally no literals for object, but we have two
operators:</para>
<para>equals:</para>
<programlisting>obj1 == obj2</programlisting>
<para>not equals:</para>
<programlisting>obj1 != obj2</programlisting>
</section>
<section id="r10_expressions_builtin_void">
<title><classname>Void</classname></title>
<para>The only possible instance of <classname>Void</classname> is the
<varname>null</varname> reference. Therefore, we have one
literal:</para>
<programlisting>null</programlisting>
</section>
<section id="r10_expressions_builtin_typeliterals">
<title>Type literals</title>
<para>The literal for types is just the name of the type (no
'<filename>.class</filename>' suffix, etc.). Example:</para>
<programlisting>String // the type string
my::special::Type // evaluates to the type 'my::special::Type'</programlisting>
</section>
<section id="r10_expressions_builtin_staticproperties">
<title>StaticProperty literals</title>
<para>The literal for static properties<indexterm>
<primary>Type</primary>
<secondary>Static property</secondary>
</indexterm> (aka enum literals<indexterm>
<primary>Enumeration</primary>
<secondary>Literal</secondary>
</indexterm>) is correlative to type literals:</para>
<programlisting>my::Color::RED</programlisting>
</section>
<section id="r10_expressions_builtin_string">
<title><classname>String</classname></title>
<para>There are two different literal syntaxes (with the same
semantics):</para>
<programlisting>'a String literal'
"a String literal" // both are okay</programlisting>
<para>For Strings the expression sub-language supports the plus
operator that is overloaded with concatenation:</para>
<programlisting>'my element '+ ele.name +' is really cool!'</programlisting>
<para>Note, that multi-line Strings are supported.</para>
</section>
<section id="r10_expressions_builtin_boolean">
<title><classname>Boolean</classname></title>
<para>The boolean literals are:</para>
<programlisting>true
false</programlisting>
<para>Operators are:</para>
<programlisting>true &amp;&amp; false // AND
true || false // OR
! true // NOT</programlisting>
</section>
<section id="r10_expressions_builtin_numeric">
<title><classname>Integer</classname> and
<classname>Real</classname></title>
<para>The syntax for integer literals is as expected:</para>
<programlisting>// integer literals
3
57278
// real literals
3.0
0.75</programlisting>
<para>Additionally, we have the common arithmetic operators:</para>
<programlisting>3 + 4 // addition
4 - 5 // subtraction
2 * 6 // multiplication
3 / 64 // divide
// Unary minus operator
- 42
- 47.11
</programlisting>
<para>Furthermore, the well known compare operators are
defined:</para>
<programlisting>4 &gt; 5 // greater than
4 &lt; 5 // smaller than
4 &gt;= 23 // greater equals than
4 &lt;= 12 // smaller equals than</programlisting>
</section>
<section id="r10_expressions_builtin_collections">
<title>Collections</title>
<para>There is a literal for lists:</para>
<programlisting>{1,2,3,4} // a list with four integers</programlisting>
<para>There is no other special concrete syntax for collections. If
you need a set, you have to call the <methodname>toSet()</methodname>
operation on the list literal:</para>
<programlisting>{1,2,4,4}.toSet() // a set with 3(!) integers</programlisting>
</section>
</section>
<section id="r10_expressions_collection_operations">
<title>Special Collection operations</title>
<para>Like OCL, the <emphasis>Xpand</emphasis> expression sub-language
defines several special operations on collections. However, those
operations are not members of the type system, therefore you cannot use
them in a reflective manner.</para>
<section id="r10_expressions_collection_select">
<title><methodname>select<indexterm>
<primary>select</primary>
</indexterm></methodname></title>
<para>Sometimes, an expression yields a large collection, but one is
only interested in a special subset of the collection. The expression
sub-language has special constructs to specify a selection out of a
specific collection. These are the <methodname>select</methodname> and
<methodname>reject</methodname> operations. The select specifies a
subset of a collection. A <methodname>select</methodname> is an
operation on a collection and is specified as follows:</para>
<programlisting>collection.select(v | boolean-expression-with-v)</programlisting>
<para><methodname>select</methodname> returns a sublist of the
specified collection. The list contains all elements for which the
evaluation of <varname>boolean-expression-with-v</varname> results is
<varname>true</varname>. Example:</para>
<programlisting>{1,2,3,4}.select(i | i &gt;= 3) // returns {3,4}</programlisting>
</section>
<section id="r10_expressions_collection_typeselect">
<title><methodname>typeSelect</methodname> <indexterm>
<primary>typeSelect</primary>
</indexterm></title>
<para>A special version of a select expression is
<methodname>typeSelect</methodname>. Rather than providing a boolean
expression a class name is here provided.</para>
<programlisting>collection.typeSelect(SomeType) </programlisting>
<para><methodname>typeSelect</methodname> returns that sublist of the
specified collection, that contains only objects which are an instance
of the specified class (also inherited). It is equivalent to the
expression</para>
<para><programlisting>collection.select(e | SomeType.isInstance(e)) </programlisting></para>
</section>
<section id="r10_expressions_collection_reject">
<title><methodname>reject<indexterm>
<primary>reject</primary>
</indexterm></methodname></title>
<para>The <methodname>reject</methodname> operation is similar to the
<methodname>select</methodname> operation, but with
<methodname>reject</methodname> we get the subset of all the elements
of the collection for which the expression evaluates to
<varname>false</varname>. The <methodname>reject</methodname> syntax
is identical to the <methodname>select</methodname> syntax:</para>
<programlisting>collection.reject(v | boolean-expression-with-v)</programlisting>
<para>Example:</para>
<programlisting>{1,2,3,4}.reject(i | i &gt;= 3) // returns {1,2}</programlisting>
</section>
<section id="r10_expressions_collection_collect">
<title><methodname>collect<indexterm>
<primary>collect</primary>
</indexterm></methodname></title>
<para>As shown in the previous section, the
<methodname>select</methodname> and <methodname>reject</methodname>
operations always result in a sub-collection of the original
collection. Sometimes one wants to apply an operation on all elements
of the collection and collect the results of the evaluation in a list.
In such cases, we can use a <methodname>collect</methodname>
operation. The <methodname>collect</methodname> operation uses the
same syntax as the <methodname>select</methodname> and
<methodname>reject</methodname> and is written like this:</para>
<programlisting>collection.collect(v | expression-with-v)</programlisting>
<para><methodname>collect</methodname> again iterates over the target
collection and evaluates the given expression on each element. In
contrast to <methodname>select</methodname>, the evaluation result is
collected in a list. When an iteration is finished the list with all
results is returned. Example:</para>
<programlisting>namedElements.collect(ne | ne.name) // returns a list of strings
namedElements.collect(ne | ne.name.length &gt; 3) // returns a list of boolean
</programlisting>
</section>
<section id="r10_expressions_collection_collect_shorthand">
<title>Shorthand for <methodname>collect</methodname> (and more than
that)</title>
<para>As navigation through many objects is very common, there is a
shorthand notation for collect <indexterm>
<primary>collect</primary>
</indexterm>that makes the expressions more readable. Instead
of</para>
<programlisting>self.employee.collect(e | e.birthdate) </programlisting>
<para>one can also write:</para>
<programlisting>self.employee.birthdate</programlisting>
<para>In general, when a property is applied to a collection of
Objects, it will automatically be interpreted as a
<methodname>collect</methodname> over the members of the collection
with the specified property.</para>
<para>The syntax is a shorthand for <methodname>collect</methodname>,
if the feature does not return a collection itself. But sometimes we
have the following:</para>
<programlisting>self.buildings.rooms.windows // returns a list of windows</programlisting>
<para>This syntax works, but one cannot express it using the
<methodname>collect</methodname> operation in an easy way.</para>
</section>
<section id="r10_expressions_collection_forall">
<title><methodname>forAll</methodname></title>
<para>Often a boolean expression has to be evaluated for all elements
in a collection. The <methodname>forAll</methodname><indexterm>
<primary>forAll</primary>
</indexterm> operation allows specifying a Boolean expression, which
must be <varname>true</varname> for all objects in a collection in
order for the <methodname>forAll</methodname> operation to return
<varname>true</varname>:</para>
<programlisting>collection.forAll(v | boolean-expression-with-v)</programlisting>
<para>The result of <methodname>forAll</methodname> is
<varname>true</varname> if
<varname>boolean-expression-with-v</varname> is <varname>true
</varname>for all the elements contained in a collection. If
<varname>boolean-expression-with-v</varname> is
<varname>false</varname> for one or more of the elements in the
collection, then the <methodname>forAll</methodname> expression
evaluates to <varname>false</varname>.</para>
<bridgehead>Example:</bridgehead>
<programlisting>{3,4,500}.forAll(i | i &lt; 10) // evaluates to false (500 &lt; 10 is false)</programlisting>
</section>
<section id="r10_expressions_collection_exists">
<title><methodname>exists<indexterm>
<primary>exists</primary>
</indexterm></methodname></title>
<para>Often you will need to know whether there is at least one
element in a collection for which a boolean is
<varname>true</varname>. The exists operation allows you to specify a
Boolean expression which must be <varname>true</varname> for at least
one object in a collection:</para>
<programlisting>collection.exists(v | boolean-expression-with-v)</programlisting>
<para>The result of the exists operation is <varname>true</varname> if
<varname>boolean-expression-with-v</varname> is
<varname>true</varname> for at least one element of collection. If the
<varname>boolean-expression-with-v</varname> is
<varname>false</varname> for all elements in collection, then the
complete expression evaluates to <varname>false</varname>.</para>
<bridgehead>Example:</bridgehead>
<programlisting>{3,4,500}.exists(i | i &lt; 10) // evaluates to true (e.g. 3 &lt; 10 is true)</programlisting>
</section>
<section id="r10_expressions_collection_sortby">
<title><methodname>sortBy</methodname></title>
<para>If you want to sort a list of elements, you can use the higher
order function <methodname>sortBy</methodname> <indexterm>
<primary>sortBy</primary>
</indexterm>. The list you invoke the
<methodname>sortBy</methodname> operation on, is sorted by the results
of the given expression.</para>
<bridgehead>Example:</bridgehead>
<programlisting>myListOfEntity.sortBy(entity | entity.name)</programlisting>
<para>In the example the list of entities is sorted by the name of the
entities. Note that there is no such <classname>Comparable</classname>
type in <emphasis>Xpand</emphasis>. If the values returned from the
expression are instances of
<classname>java.util.Comparable</classname> the
<methodname>compareTo</methodname> method is used, otherwise
<methodname>toString()</methodname> is invoked and the the result is
used.</para>
<para>All the following expressions return
<varname>true</varname>:</para>
<programlisting>{'C','B','A'}.sortBy(e | e) == {'A','B','C'}
{'AAA','BB','C'}.sortBy(e | e.length) == {'C','BB','AAA'}
{5,3,1,2}.sortBy(e | e) == {1,2,3,5}
{5,3,1,2}.sortBy(e | e - 2 * e) == {5,3,2,1}
...</programlisting>
</section>
</section>
<section id="r10_expressions_if">
<title><methodname>if</methodname> expression</title>
<indexterm>
<primary>Expression</primary>
<secondary>if</secondary>
</indexterm>
<para>There are two different forms of conditional expressions. The
first one is the so-called <emphasis>if expression</emphasis>.
Syntax:</para>
<programlisting>condition ? thenExpression : elseExpression</programlisting>
<para><emphasis role="bold">Example:</emphasis></para>
<programlisting>name != null ? name : 'unknown'</programlisting>
<para>Alternatively, you also could write:</para>
<programlisting>if name != null then
name
else
'unknown'
</programlisting>
</section>
<section id="r10_expressions_switch">
<title><methodname>switch</methodname> expression</title>
<indexterm>
<primary>Expression</primary>
<secondary>switch</secondary>
</indexterm>
<para>The other one is called <emphasis>switch expression</emphasis>.
Syntax:</para>
<programlisting>switch (expression) {
(case expression : thenExpression)*
default : catchAllExpression
}</programlisting>
<para>The default part is mandatory, because
<methodname>switch</methodname> is an expression, therefore it needs to
evaluate to something in any case.</para>
<para><emphasis role="bold">Example:</emphasis></para>
<programlisting>switch (person.name) {
case 'Hansen' : 'Du kanns platt schnacken'
default : 'Du kanns mi nech verstohn!'
}</programlisting>
<para>There is an abbreviation for <emphasis>Boolean</emphasis>
expressions:</para>
<programlisting>switch {
case booleanExpression : thenExpression
default : catchAllExpression
} </programlisting>
</section>
<section id="r10_expressions_chain">
<title>Chain expression</title>
<indexterm>
<primary>Expression</primary>
<secondary>chain</secondary>
</indexterm>
<para>Expressions and functional languages should be free of side
effects as far as possible. But sometimes there you need invocations
that do have side effects. In some cases expressions even do not have a
return type (i.e. the return type is <classname>Void</classname>). If
you need to call such operations, you can use the chain
expression.</para>
<para><emphasis role="bold">Syntax:</emphasis></para>
<programlisting>anExpr -&gt;
anotherExpr -&gt;
lastExpr </programlisting>
<para>Each expression is evaluated in sequence, but only the result of
the last expression is returned.</para>
<para><emphasis role="bold">Example</emphasis>:</para>
<programlisting>person.setName('test') -&gt;
person</programlisting>
<para>This chain expression will set the <varname>name</varname> of the
person first, before it returns the person object itself.</para>
</section>
<section id="r10_expressions_create">
<title><methodname>new</methodname> expression</title>
<indexterm>
<primary>Expression</primary>
<secondary>new</secondary>
</indexterm>
<para>The <methodname>new</methodname> expression is used to instantiate
new objects of a given type:</para>
<programlisting>new TypeName</programlisting>
<para>Note that often <link linkend="???">create extensions</link> are
the better way to instantiate objects when used for model
transformations.</para>
</section>
<section id="r10_expressions_globalvar">
<title>'GLOBALVAR' expression</title>
<para>Sometimes you don't want to pass everything down the call stack by
parameter. Therefore, we have the <methodname>GLOBALVAR</methodname>
<indexterm>
<primary>GLOBALVAR</primary>
</indexterm> expression. There are two things you need to do, to use
global variables.</para>
<section id="r10_expressions_globalvar_workflow">
<title>Using GLOBALVARS to configure workflows</title>
<para>Each workflow component using the expression framework
(<emphasis>Xpand</emphasis>, <emphasis>Check</emphasis> and
<emphasis>Xtend</emphasis>) can be configured with global variables.
<indexterm>
<primary>Global variables</primary>
</indexterm> Here is an example:</para>
<programlisting language="xml">&lt;workflow&gt;
.... stuff
&lt;component class="org.eclipse.xpand2.Generator"&gt;
... usual stuff (see ref doc)
&lt;globalVarDef name="MyPSM" value="slotNameOfPSM"/&gt;
&lt;globalVarDef name="ImplClassSuffix" value="'Impl'"/&gt;
&lt;/component&gt;
&lt;/workflow&gt;</programlisting>
<para>Note that <varname>value</varname> contains an expression or
slot name. If you want to pass a string value you will have to quote
the value, like the value for <classname>ImplClassSuffix</classname>
in the example.</para>
<para>If you have injected global variables into the respective
component, you can call them using the following syntax:</para>
<programlisting>GLOBALVAR ImplClassSuffix</programlisting>
<para>Note, we don't have any static type information. Therefore
<classname>Object</classname> is assumed. So, you have to down cast
the global variable to the intended type:</para>
<programlisting>((String) GLOBALVAR ImplClassSuffix)</programlisting>
<para>It is good practice to type it once, using an Extension and then
always refer to that extension:</para>
<programlisting language="xtend">String implClassSuffix() : GLOBALVAR ImplClassSuffix;
// usage of the typed global var extension
ImplName(Class c) :
name+implClassSuffix();</programlisting>
</section>
</section>
<section id="r10_expressions_multidispatch">
<title>Multi methods (multiple dispatch)</title>
<para>The expressions language supports multiple dispatching <indexterm>
<primary>Multiple dispatching</primary>
</indexterm>. This means that when there is a bunch of overloaded
operations, the decision which operation has to be resolved is based on
the dynamic type of all parameters (the implicit
'<varname>this</varname>' included).</para>
<para>In Java only the dynamic type of the '<varname>this</varname>'
element is considered, for parameters the static type is used (this is
called single dispatch).</para>
<para>Here is a Java example:</para>
<programlisting language="xtend">class MyType {
boolean equals(Object o) {
if (o instanceof MyClass) {
return equals((MyClass)o);
}
return super.equals(o);
}
boolean equals(MyType mt) {
//implementation...
}
} </programlisting>
<para>The method <methodname>equals(Object o)</methodname> would not
have to be overwritten, if Java would support multiple dispatch.</para>
</section>
<section id="r10_expressions_casting">
<title>Casting<indexterm>
<primary>Casting</primary>
</indexterm></title>
<para>The expression language is statically type checked. Although there
are many concepts that help the programmer to have really good static
type information, sometimes. One knows more about the real type than the
system. To explicitly give the system such an information casts are
available. <emphasis>Casts are 100% static, so you do not need them, if
you never statically typecheck your expressions! </emphasis></para>
<para>The syntax for casts is very Java-like:</para>
<programlisting>((String)unTypedList.get(0)).toUpperCase()</programlisting>
</section>
<section>
<title>Xpand keywords and metamodel properties<indexterm>
<primary>Keyword</primary>
<secondary>Property</secondary>
</indexterm></title>
<para>When the name of a metamodel property conflicts with an
<emphasis>Xpand</emphasis> or <emphasis>Xtend</emphasis> keyword, the
conflict is resolved in favour of the keyword. To refer to the metamodel
property in these cases, its name must be preceded by a
'<varname>^</varname>' character.</para>
<para>Example:</para>
<programlisting>private String foo(Import ^import) : ^import.name;
</programlisting>
</section>
</section>
<section id="Check_language" xreflabel="Check language">
<title><emphasis>Check</emphasis></title>
<section id="Check_language_description"
xreflabel="Description of the Check language">
<title>Description of the <emphasis>Check</emphasis> language</title>
<para><emphasis>Xpand</emphasis> also provides a language to specify
constraints <indexterm>
<primary>Constraint</primary>
</indexterm> that the model has to fulfill in order to be correct.
This language is very easy to understand and use. Basically, it is built
around the expression syntax that has been discussed in detail in the
previous section. Constraints specified in the
<emphasis>Check</emphasis> <indexterm>
<primary>Check</primary>
<secondary>Language</secondary>
</indexterm> language have to be stored in files with the file
extension <filename>.chk</filename> <indexterm>
<primary>.chk</primary>
</indexterm><indexterm>
<primary>Check</primary>
<secondary>File extension</secondary>
</indexterm>. Furthermore, these files have to be on the Java
classpath, of course, in order to be found. Let us look at an example,
in order to understand what these constraints look like and what they
do:<programlisting language="check">import data;
context Attribute ERROR
"Names have to be more than one character long." :
name.length &gt; 1;</programlisting>Now, let us look at the example line by
line:<orderedlist>
<listitem>
<para>First, the metamodel has to be imported.</para>
</listitem>
<listitem>
<para>Then, the context is specified for which the constraint
applies. In other words, after the <code>context</code> keyword,
we put the name of the metaclass that is going to be checked by
the constraint. Then, there follows either <code>ERROR</code> or
<code>WARNING</code>, These keywords specify what kind of action
will be taken in case the constraint fails:<table frame="all">
<title>Types of action for <emphasis>Check</emphasis>
constraints</title>
<tgroup cols="2" colsep="1" rowsep="1">
<colspec colnum="2" colwidth="7*" />
<tbody>
<row>
<entry><code>WARNING</code></entry>
<entry>If the constraint fails, the specified message is
printed, but the workflow execution is not
stopped.</entry>
</row>
<row>
<entry><code>ERROR</code></entry>
<entry>If the constraint fails, the specified message is
printed and all further processing is stopped.</entry>
</row>
</tbody>
</tgroup>
</table></para>
</listitem>
<listitem>
<para>Now, the message that is put in case that the constraint
fails is specified as a string. It is possible to include the
value of attributes or the return value of functions into the
message in order to make the message more clear. For example, it
would be possible to improve the above example by rewriting it
like this:</para>
<programlisting language="check">import data;
context Attribute ERROR
"Name of '" + name + "too short. Names have to be more than one character long." :
name.length &gt; 1;</programlisting>
</listitem>
<listitem>
<para>Finally, there is the condition itself, which is specified
by an expression, which has been discussed in detail in the
previous section. If this expression is <varname>true</varname>,
the constraint is fulfilled.</para>
</listitem>
</orderedlist></para>
<para><important>
<para>Please always keep in mind that the message that is associated
with the constraint is printed, if the condition of the constraint
is <varname>false</varname>! Thus, if the specified constraint
condition is <varname>true</varname>, nothing will be printed out
and the constraint will be fulfilled.</para>
</important></para>
<section id="Guard_conditions" xreflabel="Guard Conditions">
<title>Guard Conditions</title>
<para>The <emphasis>Check</emphasis> language of
<emphasis>Xpand</emphasis> also provides so called <indexterm>
<primary>Guard conditions</primary>
</indexterm>. These conditions allow to apply a check constraint
only to model elements that meet certain criteria. Specifying such a
guard condition is done by adding an <emphasis>if</emphasis> clause to
the check constraint. The <emphasis>if</emphasis> clause has to be
added after the <emphasis>context</emphasis> clause as demonstrated by
the following example: <programlisting language="check">import data;
context Attribute if name.length &gt; 1 ERROR
"Attribute names have to start with an 'a'" :
name.startsWith("a");</programlisting></para>
</section>
</section>
<section id="check_checkcomponent"
xreflabel="The workflow component CheckComponent">
<title>The workflow component
<emphasis>CheckComponent</emphasis></title>
<para>The workflow component
<classname>org.eclipse.xtend.check.CheckComponent</classname> allows to
integrate model validation constraints using the
<emphasis>Check</emphasis> into a modeling workflow using MWE.</para>
<para>This component provides the following configuration
properties:</para>
<table frame="all" id="properties_checkcomponent">
<title>Properties</title>
<tgroup align="left" cols="2" colsep="1" rowsep="1">
<colspec colname="checkcomponent_property_name" />
<colspec colname="checkcomponent_property_description" />
<thead>
<row>
<entry>Name of property</entry>
<entry>Description</entry>
</row>
</thead>
<tbody>
<row>
<entry><varname>checkFile</varname></entry>
<entry>This property allows to add files containing constraints
written in the <emphasis>Check</emphasis> language to the
validation component.</entry>
</row>
<row>
<entry><varname>emfAllChildrenSlot</varname></entry>
<entry>Name of a workflow slot that contains an EMF object,
which has to be validated including all child elements that it
contains. <emphasis>This property only works in conjunction with
EMF based models.</emphasis></entry>
</row>
<row>
<entry><varname>expression</varname></entry>
<entry>This property allows to set a check expression for the
validation component. <emphasis role="strong">This property only
works in conjunction with non-EMF based
models.</emphasis></entry>
</row>
<row>
<entry><varname>abortOnError</varname></entry>
<entry>This boolean property determines if the workflow will be
aborted or not if one of the validation constraints
fails.</entry>
</row>
<row>
<entry><varname>warnIfNothingChecked</varname></entry>
<entry>If this boolean property will be set to
<emphasis>true</emphasis>, a warning will be generated if there
were no validation checks. Otherwise, no warning will be
issued.</entry>
</row>
</tbody>
</tgroup>
</table>
</section>
</section>
<section id="Xtend_language" xreflabel="Xtend">
<title><emphasis>Xtend</emphasis></title>
<indexterm>
<primary>Xtend</primary>
<secondary>Language</secondary>
</indexterm>
<para>Like the expressions sublanguage that summarizes the syntax of
expressions for all the other textual languages delivered with the
<emphasis>Xpand</emphasis> framework, there is another commonly used
language called <emphasis>Xtend</emphasis>.</para>
<para>This language provides the possibility to define rich libraries of
independent operations and non-invasive metamodel extensions<indexterm>
<primary>Metamodel</primary>
<secondary>(non-invasive) extension</secondary>
</indexterm> based on either Java methods or <emphasis>Xtend</emphasis>
expressions. Those libraries can be referenced from all other textual
languages that are based on the expressions framework.</para>
<section>
<title>Xtend files</title>
<indexterm>
<primary>*.ext</primary>
</indexterm>
<para><indexterm>
<primary>Xtend</primary>
<secondary>File extension</secondary>
</indexterm>An Xtend file must reside in the Java class path of the
used execution context. File extension must be
<filename>*.ext</filename>. Let us have a look at an Xend file.</para>
<programlisting>import my::metamodel;extension other::ExtensionFile;
/**
* Documentation
*/
anExpressionExtension(String stringParam) :
doingStuff(with(stringParam))
;
/**
* java extensions are just mappings
*/
String aJavaExtension(String param) : JAVA
my.JavaClass.staticMethod(java.lang.String)
;
</programlisting>
<para>The example shows the following statements:</para>
<orderedlist>
<listitem>
<para>import statements</para>
</listitem>
<listitem>
<para>extension import statements</para>
</listitem>
<listitem>
<para>expression or java extensions</para>
</listitem>
</orderedlist>
</section>
<section>
<title>Comments<indexterm>
<primary>Xtend</primary>
<secondary>Comments</secondary>
</indexterm></title>
<para>We have single- and multi-line comments. The syntax for single
line comments is:</para>
<programlisting>// my comment</programlisting>
<para>Multi line comments are written like this:</para>
<programlisting>/* My multi line comment */</programlisting>
</section>
<section>
<title>Import Statements</title>
<para>Using the import<indexterm>
<primary>import</primary>
</indexterm> statement one can import name spaces of different
types.(see expressions framework reference documentation).</para>
<para>Syntax is:</para>
<programlisting>import my::imported::namespace;</programlisting>
<para>Xtend does not support static imports or any similar concept.
Therefore, the following is incorrect syntax:</para>
<programlisting>import my::imported::namespace::*; // WRONG! import my::Type; // WRONG!</programlisting>
</section>
<section>
<title>Extension Import Statement</title>
<indexterm>
<primary>Extension</primary>
</indexterm>
<para>You can import another Xtend file using the extension statement.
The syntax is:</para>
<programlisting>extension fully::qualified::ExtensionFileName;</programlisting>
<para>Note, that no file extension (<filename>*.ext</filename>) is
specified.</para>
<section>
<title>Reexporting Extensions</title>
<para>If you want to export extensions from another extension file
together with your local extensions, you can add the keyword
<methodname>reexport</methodname> <indexterm>
<primary>Reexport</primary>
</indexterm> to the end of the respective extension import
statement.</para>
<programlisting>extension fully::qualified::ExtensionFileName reexport;</programlisting>
</section>
</section>
<section>
<title>Extensions</title>
<para>The syntax of a simple expression extension is as follows:</para>
<programlisting>ReturnType extensionName(ParamType1 paramName1, ParamType2...): expression-using-params;</programlisting>
<para><emphasis role="bold">Example:</emphasis></para>
<programlisting>String getterName(NamedElement ele) : 'get'+ele.name.firstUpper();</programlisting>
<section>
<title>Extension Invocation<indexterm>
<primary>Extension</primary>
<secondary>invocation</secondary>
</indexterm></title>
<para>There are two different ways of how to invoke an extension. It
can be invoked like a function:</para>
<programlisting>getterName(myNamedElement)</programlisting>
<para>The other way to invoke an extension is through the "member
syntax":</para>
<programlisting>myNamedElement.getterName()</programlisting>
<para>For any invocation in member syntax, the target expression (the
member) is mapped to the first parameter. Therefore, both syntactical
forms do the same thing.</para>
<para>It is important to understand that extensions are not members of
the type system, hence, they are not accessible through reflection and
you cannot specialize or overwrite operations using them.</para>
<para>The expression evaluation engine first looks for an appropriate
operation before looking for an extension, in other words operations
have higher precedence.</para>
</section>
<section>
<title>Type Inference<indexterm>
<primary>Type inference</primary>
</indexterm></title>
<para>For most extensions, you do not need to specify the return
type,<indexterm>
<primary>Return type</primary>
</indexterm> because it can be derived from the specified
expression. The special thing is, that the static return type of such
an extension depends on the context of use.</para>
<para>For instance, if you have the following extension</para>
<programlisting>asList(Object o): {o};</programlisting>
<para>the invocation of</para>
<programlisting>asList('text')</programlisting>
<para>has the static type <classname>List[String]</classname>. This
means you can call</para>
<programlisting>asList('text').get(0).toUpperCase()</programlisting>
<para>The expression is statically type safe, because its return type
is derived automatically.</para>
<para>There is <emphasis>always</emphasis> a return value, whether you
specify it or not, even if you specify explicitly
'<classname>Void</classname>'.</para>
<para>See the following example.</para>
<programlisting>modelTarget.ownedElements.addAllNotNull(modelSource.contents.duplicate())</programlisting>
<para>In this example <methodname>duplicate()</methodname> dispatches
polymorphically<indexterm>
<primary>Polymorphism</primary>
</indexterm>. Two of the extensions might look like:</para>
<programlisting>Void duplicate(Realization realization):
realization.Specifier().duplicate()-&gt;
realization.Realizer().duplicate()
;
create target::Class duplicate(source::Class):
...
;</programlisting>
<para>If a '<classname>Realization</classname>' is contained in the
'<methodname>contents</methodname>' list of
'<varname>modelSource</varname>', the
'<methodname>Realizer</methodname>' of the
'<classname>Realization</classname>' will be added to the
'<varname>ownedElements</varname>' list of the
'<varname>modelTarget</varname>'. If you do not want to add in the
case that the contained element is a 'Realization' you might change
the extension to:</para>
<programlisting>Void duplicate(Realization realization):
realization.Specifier().duplicate()-&gt;
realization.Realizer().duplicate() -&gt;
{}
;</programlisting>
</section>
<section>
<title>Recursion</title>
<para>There is only one exception: For recursive extensions <indexterm>
<primary>Recursive extensions</primary>
</indexterm><indexterm>
<primary>Extension</primary>
<secondary>recursion</secondary>
</indexterm> the return type cannot be inferred, therefore you need
to specify it explicitly:</para>
<programlisting>String fullyQualifiedName(NamedElement n) : n.parent == null ? n.name :
fullyQualifiedName(n.parent)+'::'+n.name
;</programlisting>
<para>Recursive extensions are non-deterministic in a static context,
therefore, it is necessary to specify a return type.</para>
</section>
<section>
<title>Cached Extensions<indexterm>
<primary>Extension</primary>
<secondary>caching</secondary>
</indexterm></title>
<para>If you call an extension without side effects very often, you
would like to cache the result for each set of parameters, in order
improve the performance. You can just add the keyword
'<code>cached</code>'<indexterm>
<primary>cached</primary>
</indexterm> to the extension in order to achieve this:</para>
<programlisting>cached String getterName(NamedElement ele) :
'get'+ele.name.firstUpper()
;</programlisting>
<para>The <methodname>getterName</methodname> will be computed only
once for each <classname>NamedElement</classname>.</para>
</section>
<section>
<title>Private Extensions<indexterm>
<primary>Extension</primary>
<secondary>private</secondary>
</indexterm></title>
<para>By default all extensions are public, i.e. they are visible from
outside the extension file. If you want to hide extensions you can add
the keyword '<methodname>private</methodname>'<indexterm>
<primary>private</primary>
</indexterm> in front of them:</para>
<programlisting>private internalHelper(NamedElement ele) :
// implementation....
;</programlisting>
</section>
</section>
<section>
<title>Java Extensions</title>
<para>In some cases one does want to call a Java method from inside an
expression. This can be done by providing a Java extension<indexterm>
<primary>Java extension</primary>
</indexterm><indexterm>
<primary>Extension</primary>
<secondary>Java</secondary>
</indexterm>:</para>
<programlisting>Void myJavaExtension(String param) :
JAVA my.Type.someMethod(java.lang.String)
;</programlisting>
<para>The signature is the same as for any other extension. Its syntax
is:</para>
<programlisting>JAVA fully.qualified.Type.someMethod(my.ParamType1,
my.ParamType2,
...)
;</programlisting>
<para>Note that you cannot use any imported namespaces. You have to
specify the type, its method and the parameter types in a fully
qualified way.</para>
<para><emphasis role="bold">Example:</emphasis></para>
<para>If you have defined the following Java extension:</para>
<programlisting>String concat (String a, String b):
JAVA my.Helper.concat(java.lang.String, java.lang.String);</programlisting>
<para>and you have the following Java class:</para>
<programlisting>package my;
public class Helper {
public String concat(String a, String b){
return a + b;
}
}</programlisting>
<para>the expressions</para>
<programlisting>concat('Hello ',"world!")
"Hello ".concat('world!')</programlisting>
<para>both result are invoking the Java method <methodname>void
concat(String a, String b).</methodname></para>
<section>
<title>static vs non-static invocation</title>
<para>The implementation of a Java extension is redirected to a public
method in a Java class. If the method is not declared static it is
required that the Java class has a default constructor. Xtend will
instantiate the class for each invocation.</para>
</section>
<section>
<title>IExecutionContextAware<indexterm>
<primary>IExecutionContextAware</primary>
</indexterm></title>
<para>It is possible with a Java Extension to gain access to the
ExecutionContext<indexterm>
<primary>ExecutionContext</primary>
</indexterm>, which enables to retrieve detailed runtime information
on invocation. To use the current ExecutionContext in a Java extension
the class must implement
<classname>org.eclipse.xtend.expression.IExecutionContextAware</classname></para>
<para><programlisting>public interface IExecutionContextAware {
void setExecutionContext (ExecutionContext ctx);
}
</programlisting></para>
<para>The invoked method must not be static.</para>
</section>
</section>
<section id="create_extension">
<title>Create Extensions (Model Transformation)</title>
<para>The <emphasis>Xtend</emphasis> language supports additional
support for model transformations<indexterm>
<primary>Model transformation</primary>
</indexterm>. The concept is called <emphasis>create
extension</emphasis> and <indexterm>
<primary>Extension</primary>
<secondary>create</secondary>
</indexterm><indexterm>
<primary>create</primary>
</indexterm> it is explained a bit more comprehensive as usual.</para>
<para>Elements contained in a model are usually referenced multiple
times. Consider the following model structure:</para>
<programlisting> P
/ \
C1 C2
\ /
R
</programlisting>
<para>A package <varname>P</varname> contains two classes
<varname>C1</varname> and <varname>C2</varname>. <varname>C1</varname>
contains a reference <varname>R</varname> of type <varname>C2</varname>
(<varname>P</varname> also references <varname>C2</varname>).</para>
<para>We could write the following extensions in order to transform an
Ecore (EMF) model to our metamodel (Package, Class, Reference).</para>
<programlisting>Package toPackage(EPackage x) :
let p = new Package :
p.ownedMember.addAll(x.eClassifiers.toClass()) -&gt;
p;
Class toClass(EClass x) :
let c = new Class :
c.attributes.addAll(x.eReferences.toReference()) -&gt;
c;
Reference toReference(EReference x) :
let r = new Reference :
r.setType(x.eType.toClass()) -&gt;
r;
</programlisting>
<para>For an Ecore model with the above structure, the result would
be:</para>
<programlisting> P
/ \
C1 C2
|
R - C2
</programlisting>
<para>What happened? The <varname>C2</varname> class has been created 2
times (one time for the package containment and another time for the
reference <varname>R</varname> that also refers to
<varname>C2</varname>). We can solve the problem by adding the
'<methodname>cached</methodname>' keyword <indexterm>
<primary>Expression</primary>
<secondary>cached</secondary>
</indexterm> to the second extension:</para>
<programlisting>cached toClass(EClass x) :
let c = new Class :
c.attributes.addAll(c.eAttributes.toAttribute()) -&gt;
c;
</programlisting>
<para>The process goes like this:</para>
<orderedlist>
<listitem>
<para>start create <varname>P</varname></para>
<orderedlist>
<listitem>
<para>start create <varname>C1</varname> (contained in
<varname>P</varname>)</para>
<orderedlist>
<listitem>
<para>start create <varname>R</varname> (contained in
<varname>C1</varname>)</para>
<orderedlist>
<listitem>
<para>start create <varname>C2</varname> (referenced
from <varname>R</varname>)</para>
</listitem>
<listitem>
<para>end (result <varname>C2</varname> is
cached)</para>
</listitem>
</orderedlist>
</listitem>
<listitem>
<para>end <varname>R</varname></para>
</listitem>
</orderedlist>
</listitem>
<listitem>
<para>end <varname>C1</varname></para>
</listitem>
<listitem>
<para>start get cached <varname>C2</varname> (contained in
<varname>P</varname>)</para>
</listitem>
</orderedlist>
</listitem>
<listitem>
<para>end P</para>
</listitem>
</orderedlist>
<para>So this works very well. We will get the intended structure. But
what about circular dependencies? For instance, <varname>C2</varname>
could contain a <classname>Reference</classname> <varname>R2</varname>
of type <varname>C1</varname> (bidirectional references):</para>
<para>The transformation would occur like this:</para>
<orderedlist>
<listitem>
<para>start create <varname>P</varname></para>
<orderedlist>
<listitem>
<para>start create <varname>C1</varname> (contained in
<varname>P</varname>)</para>
<orderedlist>
<listitem>
<para>start create <varname>R</varname> (contained in
<varname>C1</varname>)</para>
<orderedlist>
<listitem>
<para>start create <varname>C2</varname> (referenced
from <varname>R</varname>)</para>
<orderedlist>
<listitem>
<para>start create <varname>R2</varname> (contained
in <varname>C2</varname>)</para>
<orderedlist>
<listitem>
<para>start create <varname>C1</varname> (referenced
from <varname>R1</varname>)... OOPS!</para>
</listitem>
</orderedlist>
</listitem>
</orderedlist>
</listitem>
</orderedlist>
</listitem>
</orderedlist>
</listitem>
</orderedlist>
</listitem>
</orderedlist>
<para><varname>C1</varname> is already in creation and will not complete
until the stack is reduced. Deadlock! The problem is that the cache
caches the return value, but <varname>C1</varname> was not returned so
far, because it is still in construction.</para>
<para>The solution: create extensions!</para>
<para>The syntax is as follows:</para>
<programlisting>create Package toPackage(EPackage x) :
this.classifiers.addAll(x.eClassifiers.toClass());
create Class toClass(EClass x) :
this.attributes.addAll(x.eReferences.toReference());
create Reference toReference(EReference x) :
this.setType(x.eType.toClass());
</programlisting>
<para>This is not only a shorter syntax, but it also has the needed
semantics: The created model element will be added to the cache before
evaluating the body. The return value is always the reference to the
created and maybe not completely initialized element.</para>
</section>
<section>
<title>Calling Extensions From Java</title>
<para>The previous section showed how to implement Extensions in Java.
This section shows how to call Extensions from Java.<indexterm>
<primary>XtendFacade</primary>
</indexterm></para>
<programlisting>// setup
XtendFacade f = XtendFacade.create("my::path::MyExtensionFile");
// use
f.call("sayHello",new Object[]{"World"});
</programlisting>
<para>The called extension file looks like this: <indexterm>
<primary>Expression</primary>
<secondary>call</secondary>
</indexterm></para>
<programlisting>sayHello(String s) :
"Hello " + s;</programlisting>
<para>This example uses only features of the
<classname>BuiltinMetaModel</classname>, in this case the
"<methodname>+</methodname>" feature from the
<classname>StringTypeImpl</classname>.</para>
<para>Here is another example, that uses the
<classname>JavaBeansMetaModel</classname><indexterm>
<primary>JavaBeansMetaModel</primary>
</indexterm> strategy. This strategy provides as additional feature:
the access to properties using the getter and setter methods.</para>
<para>For more information about type systems, see the <emphasis><xref
linkend="r10_expressions_language" /></emphasis> reference
documentation.</para>
<para>We have one JavaBean-like metamodel class:</para>
<programlisting>package mypackage;
public class MyBeanMetaClass {
private String myProp;
public String getMyProp() { return myProp; }
public void setMyProp(String s) { myProp = s;}
}</programlisting>
<para>in addition to the built-in metamodel type system, we register the
<classname>JavaMetaModel</classname><indexterm>
<primary>JavaMetaModel</primary>
</indexterm> with the
<classname>JavaBeansStrategy</classname><indexterm>
<primary>JavaBeansStrategy</primary>
</indexterm> for our facade. Now, we can use also this strategy in our
extension:</para>
<programlisting>// setup facade
XtendFacade f = XtendFacade.create("myext::JavaBeanExtension");
// setup additional type system
JavaMetaModel jmm =
new JavaMetaModel("JavaMM", new JavaBeansStrategy());
f.registerMetaModel(jmm);
// use the facade
MyBeanMetaClass jb = MyBeanMetaClass();
jb.setMyProp("test");
f.call("readMyProp", new Object[]{jb}));</programlisting>
<para>The called extension file looks like this:</para>
<programlisting>import mypackage;
readMyProp(MyBeanMetaClass jb) :
jb.myProp
;
</programlisting>
</section>
<section>
<title>WorkflowComponent<indexterm>
<primary>WorkflowComponent</primary>
</indexterm></title>
<para>With the additional support for model transformation, it makes
sense to invoke <emphasis>Xtend</emphasis> within a workflow. A typical
workflow configuration of the <emphasis>Xtend</emphasis> component
<indexterm>
<primary>XtendComponent</primary>
</indexterm>looks like this:</para>
<programlisting language="xml">&lt;component class="org.eclipse.xtend.XtendComponent"&gt;
&lt;metaModel class="org.eclipse.xtend.typesystem.emf.EmfMetaModel"&gt;
&lt;metaModelFile value="metamodel1.ecore"/&gt;
&lt;/metamodel&gt;
&lt;metaModel class="org.eclipse.xtend.typesystem.type.emf.EmfMetaModel"&gt;
&lt;metaModelFile value="metamodel2.ecore"/&gt;
&lt;/metaModel&gt;
&lt;invoke value="my::example::Trafo::transform(inputSlot)"/&gt;
&lt;outputSlot value="transformedModel"/&gt;
&lt;/component&gt;
</programlisting>
<para>Note that you can mix and use any kinds of metamodels (not only
EMF metamodels).</para>
</section>
<section>
<title>Aspect-Oriented Programming in
<emphasis>Xtend</emphasis><indexterm>
<primary>Aspect-Oriented Programming</primary>
</indexterm><indexterm>
<primary>AOP</primary>
</indexterm></title>
<para>Using the workflow engine, it is now possible to package (e.g.
zip) a written generator and deliver it as a kind of black box. If you
want to use such a generator but need to change some things without
modifying any code, you can make use of around advices that are
supported by <emphasis>Xtend</emphasis>.</para>
<para>The following advice is weaved<indexterm>
<primary>Weaving advices</primary>
</indexterm> around every invocation of an extension whose name starts
with '<package>my::generator::</package>':</para>
<programlisting>around my::generator::*(*) :
log('Invoking ' + ctx.name) -&gt; ctx.proceed()
;
</programlisting>
<para>Around advices<indexterm>
<primary>Advice</primary>
</indexterm> let you change behaviour in an non-invasive way (you do
not need to touch the packaged extensions).</para>
<section>
<title>Join Point and Point Cut Syntax</title>
<para>Aspect orientaton is basically about weaving code into different
points inside the call graph of a software module. Such points are
called <emphasis>join points</emphasis>. In <emphasis>Xtend</emphasis>
the join points are the extension invocations (Note that
<emphasis>Xpand</emphasis> offers a similar feature, see the
<emphasis>Xpand</emphasis> documentation).</para>
<para>One specifies on which join points <indexterm>
<primary>Join point</primary>
</indexterm> the contributed code should be executed by specifying
something like a 'query' on all available join points. Such a query is
called a point cut.<indexterm>
<primary>Point cut</primary>
</indexterm></para>
<programlisting>around [pointcut] :
expression;</programlisting>
<para>A point cut consists of a fully qualified name and a list of
parameter declarations.</para>
<section>
<title>Extensions Name</title>
<para>The extension name part of a point cut must match the fully
qualified name of the definition of the join point. Such expressions
are case sensitive. The asterisk character is used to specify
wildcards.</para>
<para>Some examples:</para>
<programlisting>my::Extension::definition // extensions with the specified name
org::eclipse::xpand2::* //extensions prefixed with 'org::eclipse::xpand2::'
*Operation* // extensions containing the word 'Operation' in it.
* // all extensions</programlisting>
<warning>
<para>Be careful when using wildcards, because you will get an
endless recursion, in case you weave an extension, which is called
inside the advice.</para>
</warning>
</section>
<section>
<title>Parameter Types</title>
<para>The parameters of the extensions that we want to add our
advice to, can also be specified in the point cut. The rule is, that
the type of the specified parameter must be the same or a supertype
of the corresponding parameter type (the dynamic type at runtime) of
the definition to be called.</para>
<para>Additionally, one can set the wildcard at the end of the
parameter list, to specify that there might be none or more
parameters of any kind.<indexterm>
<primary>Type</primary>
<secondary>Parameter</secondary>
</indexterm></para>
<para>Some examples:</para>
<programlisting>my::Templ::extension() // extension without parameters
my::Templ::extension(String s) // extension with exactly one parameter of type String
my::Templ::extension(String s,*) // templ def with one or more parameters,
// where the first parameter is of type String
my::Templ::extension(*) // templ def with any number of parameters
</programlisting>
</section>
<section>
<title>Proceeding</title>
<para>Inside an advice, you might want to call the underlying
definition. This can be done using the implicit variable
<varname>ctx</varname>, which is of the type
<type>xtend::AdviceContext</type><indexterm>
<primary>AdviceContext</primary>
</indexterm> and provides an operation
<methodname>proceed()</methodname><indexterm>
<primary>proceed</primary>
</indexterm> which invokes the underlying definition with the
original parameters (Note that you might have changed any mutable
object in the advice before).</para>
<para>If you want to control what parameters are to be passed to the
definition, you can use the operation
<methodname>proceed(List[Object] params)</methodname>. You should be
aware, that in advices, no type checking is done.</para>
<para>Additionally, there are some inspection properties (like
<varname>name</varname>, <varname>paramTypes</varname>, etc.)
available.</para>
</section>
</section>
<section>
<title>Workflow configuration</title>
<para>To weave the defined advices into the different join
points<indexterm>
<primary>Join point</primary>
</indexterm>, you need to configure the
<classname>XtendComponent</classname><indexterm>
<primary>XtendComponent</primary>
<secondary>Advices</secondary>
</indexterm> with the qualified names of the Extension files
containing the advices.</para>
<para>Example:</para>
<programlisting language="xml">&lt;component class="org.eclipse.xtend.XtendComponent"&gt;
&lt;metaModel class="org.eclipse.xtend.typesystem.emf.EmfMetaModel"&gt;
&lt;metaModelFile value="metamodel1.ecore"/&gt;
&lt;/metamodel&gt;
&lt;metaModel class="org.eclipse.xtend.typesystem.emf.EmfMetaModel"&gt;
&lt;metaModelFile value="metamodel2.ecore"/&gt;
&lt;/metaModel&gt;
&lt;invoke value="my::example::Trafo::transform(inputSlot)"/&gt;
&lt;outputSlot value="transformedModel"/&gt;
&lt;advices value="my::Advices,my::Advices2"/&gt;
&lt;/component&gt;
</programlisting>
</section>
<section id="xtend_example_introduction">
<title>Model-to-Model transformation with
<emphasis>Xtend</emphasis></title>
<para>This example uses Eclipse EMF as the basis <indexterm>
<primary>Model-to-model transformation</primary>
</indexterm>for model-to-model transformations. It builds on the
<emphasis>emfExample</emphasis> documented elsewhere. Please read and
install the <emphasis>emfExample</emphasis> first.</para>
<para>The idea in this example is to transform the data model
introduced in the EMF example into itself. This might seem boring, but
the example is in fact quite illustrative.</para>
</section>
<section id="xtend_example_workflow">
<title>Workflow</title>
<para>By now, you should know the role and structure of workflow
files. Therefore, the interesting aspect of the workflow file below is
the <emphasis><classname>XtendComponent</classname></emphasis>.</para>
<programlisting language="xml">&lt;workflow&gt;
&lt;property file="workflow.properties"/&gt;
...
&lt;component class="org.eclipse.xtend.XtendComponent"&gt;
&lt;metaModel class="org.eclipse.xtend.typesystem.emf.EmfMetaModel"&gt;
&lt;metaModelPackage value="data.DataPackage"/&gt;
&lt;/metaModel&gt;
&lt;invoke value="test::Trafo::duplicate(rootElement)"/&gt;
&lt;outputSlot value="newModel"/&gt;
&lt;/component&gt;
...
&lt;/workflow&gt;</programlisting>
<para>As usual, we have to define the metamodel that should be used,
and since we want to transform a data model into a data model, we need
to specify only the <classname>data.DataPackage</classname> as the
metamodel.</para>
<para>We then specify which function to invoke for the transformation.
The statement
<classname>test::Trafo::duplicate(rootElement)</classname> means to
invoke: <itemizedlist>
<listitem>
<para>the <classname>duplicate</classname> function taking the
contents of the <classname>rootElement</classname> slot as a
parameter</para>
</listitem>
<listitem>
<para>the function can be found in the
<filename>Trafo.ext</filename> file</para>
</listitem>
<listitem>
<para>and that in turn is in the classpath, in the
<package>test</package>package.</para>
</listitem>
</itemizedlist></para>
</section>
<section id="xtend_example_the_transformation">
<title>The transformation</title>
<para>The transformation, as mentioned above, can be found in the
<filename>Trafo.ext</filename> file in the <classname>test</classname>
package in the <classname>src</classname> folder. Let us walk through
the file.</para>
<para>So, first we import the metamodel.</para>
<programlisting language="xtend">import data;</programlisting>
<para>The next function is a so-called create extension<indexterm>
<primary>Extension</primary>
<secondary>create</secondary>
</indexterm><indexterm>
<primary>Create extension</primary>
</indexterm>. Create extensions, as a side effect when called,
create an instance of the type given after the
<classname>create</classname> keyword. In our case, the
<classname>duplicate</classname> function creates an instance of
<classname>DataModel</classname>. This newly created object can be
referred to in the transformation <indexterm>
<primary>Transformation</primary>
</indexterm>by <classname>this</classname> (which is why
<classname>this</classname> is specified behind the type). Since
<classname>this</classname> can be omitted, we do not have to mention
it explicitly in the transformation.</para>
<para>The function also takes an instance of
<classname>DataModel</classname> as its only parameter. That object is
referred to in the transformation as <varname>s</varname>. So, this
function sets the name of the newly created
<classname>DataModel</classname> to be the name of the original one,
and then adds duplicates of all entities of the original one to the
new one. To create the duplicates of the entities, the
<classname>duplicate()</classname> operation is called for each
<classname>Entity</classname>. This is the next function in the
transformation.</para>
<programlisting language="xtend">create DataModel this duplicate(DataModel s):
entity.addAll(s.entity.duplicate()) -&gt;
setName(s.name);</programlisting>
<para>The duplication function for entities is also a create
extension. This time, it creates a new <classname>Entity</classname>
for each old <classname>Entity</classname> passed in. Again, it copies
the name and adds duplicates of the attributes and references to the
new one.</para>
<programlisting language="xtend">create Entity this duplicate(Entity old):
attribute.addAll(old.attribute.duplicate()) -&gt;
reference.addAll(old.reference.duplicate()) -&gt;
setName(old.name);</programlisting>
<para>The function that copies the attribute is rather straight
forward, but ...</para>
<programlisting language="xtend">create Attribute this duplicate(Attribute old):
setName(old.name) -&gt;
setType(old.type);</programlisting>
<indexterm>
<primary>Expression</primary>
<secondary>create</secondary>
</indexterm>
<para>... the one for the references is more interesting. Note that a
reference, while being owned by some <classname>Entity</classname>,
also references another Entity as its target. So, how do you make sure
you do not duplicate the target twice? <emphasis>Xtend</emphasis>
provides explicit support for this kind of situation. <emphasis>Create
extensions are only executed once per tuple of parameters!</emphasis>
So if, for example, the <emphasis>Entity</emphasis> behind the target
reference had already been duplicated by calling the
<methodname>duplicate</methodname> function with the respective
parameter, the next time it will be called <emphasis>the exact same
object will be returned</emphasis>. This is very useful for graph
transformations.</para>
<programlisting language="xtend">create EntityReference this duplicate(EntityReference old):
setName( old.name ) -&gt;
setTarget( old.target.duplicate() );</programlisting>
<para>For more information about the <emphasis>Xtend</emphasis>
language please see the <emphasis><xref
linkend="Xtend_language" /></emphasis> reference documentation.</para>
</section>
</section>
</section>
<section id="xpand_reference_introduction">
<title><emphasis>Xpand2</emphasis></title>
<para>The <emphasis>Xpand</emphasis><indexterm>
<primary>Xpand</primary>
<secondary>Language</secondary>
</indexterm> language is used in templates to control the output
generation. This documentation describes the general syntax and semantics
of the <emphasis>Xpand</emphasis> language.</para>
<para>Typing the <foreignphrase>guillemets</foreignphrase><indexterm>
<primary>Guillemet</primary>
</indexterm> (« and ») used in the templates is supported by the Eclipse
editor, which provides keyboard shortcuts with <keycombo action="simul">
<keycap>Ctrl</keycap>
<keycap>&lt;</keycap>
</keycombo> and <keycombo action="simul">
<keycap>Ctrl</keycap>
<keycap>&gt;</keycap>
</keycombo>.</para>
<section id="xpand_reference_template_files_and_ecoding">
<title>Template files and encoding</title>
<para>Templates are stored in files with the extension
<filename>.xpt</filename><indexterm>
<primary>File extension</primary>
<secondary>.xpt</secondary>
</indexterm>.<indexterm>
<primary>.xpt</primary>
</indexterm> Template files<indexterm>
<primary>Template</primary>
<secondary>File</secondary>
</indexterm> must reside on the Java classpath of the generator
process.</para>
<para>Almost all characters used in the standard syntax are part of
<emphasis>ASCII</emphasis> and should therefore be available in any
encoding<indexterm>
<primary>File encoding</primary>
<secondary>encoding</secondary>
</indexterm><indexterm>
<primary>Encoding</primary>
<see>File encoding</see>
</indexterm>. The only limitation are the tag brackets
(<emphasis>guillemets</emphasis>), for which the characters "«" (Unicode
<varname>00AB</varname>) and "»" (Unicode <varname>00BB</varname>) are
used. So for reading templates, an encoding should be used that supports
these characters (e.g. <varname>ISO-8859-1</varname> or
<varname>UTF-8</varname>).</para>
<para>Names of properties, templates, namespaces etc. must only contain
letters, numbers and underscores.</para>
</section>
<section id="xpand_reference_general_structure_of_template_files">
<title>General structure of template files</title>
<para>Here is a first example of a template:<programlisting>«IMPORT meta::model»
«EXTENSION my::ExtensionFile»
«DEFINE javaClass FOR Entity»
«FILE fileName()»
package «javaPackage()»;
public class «name» {
// implementation
}
«ENDFILE»
«ENDDEFINE»</programlisting>A template file consists of any number of IMPORT
statements, followed by any number of EXTENSION statements, followed by
one or more DEFINE blocks (called definitions).</para>
</section>
<section id="xpand_reference_statements_of_the_expand_language">
<title>Statements of the <emphasis>Xpand</emphasis> language</title>
<section id="xpand_reference_import">
<title>IMPORT<indexterm>
<primary>IMPORT</primary>
</indexterm></title>
<para>If you are tired of always typing the fully qualified names of
your types and definitions, you can import a namespace using the
IMPORT statement. <programlisting>«IMPORT meta::model»</programlisting>This
one imports the namespace <varname>meta::model</varname>. If your
template contains such a statement, you can use the unqualified names
of all types and template files contained in that namespace. This is
similar to a Java import statement <varname>import
meta.model.*</varname>.</para>
</section>
<section id="xpand_reference_extension">
<title>EXTENSION<indexterm>
<primary>EXTENSION</primary>
</indexterm></title>
<para>Metamodels are typically described in a structural way
(graphical, or hierarchical, etc.) . A shortcoming of this is that it
is difficult to specify additional behaviour (query operations,
derived properties, etc.). Also, it is a good idea not to pollute the
metamodel with target platform specific information (e.g. Java type
names, packages, getter and setter names, etc.).</para>
<para>Extensions provide a flexible and convenient way of defining
additional features of metaclasses. You do this by using the <link
linkend="???"><emphasis>Xtend</emphasis><indexterm>
<primary>Xtend</primary>
</indexterm> language</link>.</para>
<para>An <classname>EXTENSION</classname> import points to the
<emphasis>Xtend</emphasis> file containing the required extensions:
<programlisting>«EXTENSION my::ExtensionFile»</programlisting> Note
that extension files have to reside on the Java classpath<indexterm>
<primary>Classpath</primary>
</indexterm>, too. Therefore, they use the same namespace mechanism
(and syntax) as types and template files.</para>
</section>
<section id="xpand_reference_define">
<title>DEFINE<indexterm>
<primary>DEFINE</primary>
</indexterm></title>
<para>The central concept of <emphasis>Xpand</emphasis> is the
<code>DEFINE</code> block, also called a template. This is the
smallest identifiable unit in a template file<indexterm>
<primary>Template</primary>
<secondary>File</secondary>
</indexterm>. The tag consists of a name, an optional
comma-separated parameter list, as well as the name of the metamodel
class for which the template is defined. <programlisting>«DEFINE templateName(formalParameterList) FOR MetaClass»
a sequence of statements
«ENDDEFINE»</programlisting>To some extend, templates can be seen as special
methods of the metaclass. There is always an implicit
<varname>this</varname> parameter which can be used to address the
"underlying" model element; in our example above, this model element
is of type "<classname>MetaClass</classname>".</para>
<para>As in Java, a formal parameter list entry consists of the type
followed by the name of that parameter.</para>
<para>The body of a template can contain a sequence of other
statements including any text.</para>
<para>A full parametric polymorphism<indexterm>
<primary>Polymorphism</primary>
</indexterm> <indexterm>
<primary>Template</primary>
<secondary>Polymorphism</secondary>
</indexterm> is available for templates. If there are two templates
with the same name that are defined for two metaclasses which inherit
from the same superclass, <emphasis>Xpand</emphasis> will use the
corresponding subclass template, in case the template is called for
the superclass. Vice versa, the template of the superclass would be
used in case a subclass template is not available. Note that this not
only works for the target type, but for all parameters. Technically,
the target type is handled as the first parameter.</para>
<para>So, let us assume you have the following metamodel: <figure>
<title>Sample metamodel</title>
<mediaobject>
<imageobject role="fo">
<imagedata fileref="images/XPand/metamodelexample.gif"
scale="80" />
</imageobject>
<imageobject role="html">
<imagedata fileref="images/XPand/metamodelexample.gif" />
</imageobject>
</mediaobject>
</figure></para>
<para>Assume further, you would have a model which contains a
collection of <classname>A</classname>, <classname>B</classname> and
<classname>C</classname> instances in the property
<methodname>listOfAs</methodname>. Then, you can write the following
template: <programlisting>«DEFINE someOtherDefine FOR SomeMetaClass»
«EXPAND implClass FOREACH listOfAs»
«ENDDEFINE»
«DEFINE implClass FOR A»
// this is the code generated for the superclass A
«ENDDEFINE»
«DEFINE implClass FOR B»
// this is the code generated for the subclass B
«ENDDEFINE»
«DEFINE implClass FOR C»
// this is the code generated for the subclass C
«ENDDEFINE»</programlisting>So for each <classname>B</classname> in the list,
the template defined for <classname>B</classname> is executed, for
each <classname>C</classname> in the collection the template defined
for <emphasis><classname>C</classname></emphasis> is invoked, and for
all others (which are then instances of <classname>A</classname>) the
default template is executed.</para>
</section>
<section id="xpand_reference_file">
<title>FILE<indexterm>
<primary>FILE</primary>
</indexterm></title>
<para>The <varname>FILE</varname> statement redirects the output
generated from its body statements to the specified target.
<programlisting>«FILE expression [outletName]»
a sequence of statements
«ENDFILE»</programlisting>The target is a file in the file system whose name
is specified by the expression (relative to the specified target
directory for that generator run). The expression for the target
specification can be a concatenation (using the + operator).
Additionally, you can specify an identifier (a legal Java identifier)
for the name of the outlet<indexterm>
<primary>Outlet</primary>
</indexterm>. (See the configuration section for a description of
outlets). To produce the target file into subdirectories use "/" in
the expression result as separator for the directory structure.</para>
<para>The body of a <varname>FILE</varname> statement can contain any
other statements.</para>
<para><emphasis role="bold">Example: </emphasis><programlisting>«FILE InterfaceName + ".java"»
package «InterfacePackageName»;
/* generated class! Do not modify! */
public interface «InterfaceName» {
«EXPAND Operation::InterfaceImplementation FOREACH Operation»
}
«ENDFILE»
«FILE ImplName + ".java" MY_OUTLET»
package «ImplPackageName»;
public class «ImplName» extends «ImplBaseName»
implements «InterfaceName» {
//TODO: implement it
}
«ENDFILE»</programlisting></para>
</section>
<section id="xpand_reference_expand">
<title>EXPAND<indexterm>
<primary>EXPAND</primary>
</indexterm></title>
<para>The <varname>EXPAND</varname> statement "expands" another
<varname>DEFINE</varname> block (in a separate variable context),
inserts its output at the current location and continues with the next
statement. This is similar in concept to a subroutine call.
<programlisting>«EXPAND definitionName [(parameterList)]
[FOR expression | FOREACH expression [SEPARATOR expression] ] [ONFILECLOSE]»</programlisting>The
various alternative syntaxes are explained below.</para>
<section id="xpand_reference_names">
<title>Names</title>
<para>If the <emphasis>definitionName</emphasis> is a simple
unqualified name, the corresponding <varname>DEFINE</varname> block
must be in the same template file.</para>
<para>If the called definition is not contained in the same template
file, the name of the template file must be specified. As usual, the
double colon is used to delimit namespaces. <programlisting>«EXPAND TemplateFile::definitionName FOR myModelElement»</programlisting>Note
that you would need to import the namespace<indexterm>
<primary>Namespace</primary>
<secondary>Import</secondary>
</indexterm> of the template file (if there is one). For instance,
if the template file resides in the java package
<varname>my.templates</varname>, there are two alternatives. You
could either write <programlisting>«IMPORT my::templates»
...
«EXPAND TemplateFile::definitionName FOR myModelElement»</programlisting> or
<programlisting>«EXPAND my::templates::TemplateFile::definitionName
FOR myModelElement»</programlisting></para>
</section>
<section>
<title>Lazy evaluation</title>
<para>Appending the <indexterm>
<primary>ONFILECLOSE</primary>
</indexterm><classname>ONFILECLOSE</classname> statement defers
evaluation of the expanded definition until the current file is
closed with <classname>ENDFILE</classname>. This is of use when the
state required to create the text is collected during the evaluation
of the processed definition.<programlisting>«FILE ...»
...
«EXPAND LazyEvaluatedDefinition FOREACH myCollection ONFILECLOSE»
...
«ENDFILE» «REM»Now 'LazyEvaluatedDefinition' is called«ENDFILE»</programlisting></para>
<para>A typical example for usage of the
<classname>ONFILECLOSE</classname> statement is when you want to
create a list of imports in a Java class, but the types that are
used should be added when they are used in the templates
later.</para>
<para>The state, usually a collection, that is used for the lazy
expanded evaluation must be valid until the file is closed. This can
be achieved in two ways:</para>
<itemizedlist>
<listitem>
<para>Span a <classname>LET</classname> statement around the
<classname>FILE</classname> statement that bounds an empty
collection</para>
<para><programlisting>«LET (List[MyType]) {} AS importedTypes»
«FILE ...»
...
«EXPAND ImportStatement FOREACH importedTypes ONFILECLOSE»
...
«importedTypes.add(someType) -&gt; ""-»
...
«ENDFILE»
«ENDLET»</programlisting></para>
</listitem>
<listitem>
<para>Use a <link linkend="create_extension"><emphasis>create
extension</emphasis></link> which returns an empty collection
and append elements to it. Since it is a create extension the
empty collection will be returned on first call and for each
subsequent call a reference to this collection will be returned
and not a new collection created.</para>
<para><emphasis role="bold">Example:</emphasis></para>
<para><filename>some/path/InsertionPoints.ext</filename>:</para>
<para><programlisting>create List[Type] importedTypes (SomeType context) : (List[Type]) {}; </programlisting></para>
<para>In Xpand use this as follows:</para>
<para><programlisting>«EXTENSION some::path::InsertionPoints»
«FILE ...»
...
«EXPAND ImportStatement FOREACH importedTypes() ONFILECLOSE»
...
«importedTypes().add(someType) -&gt; ""-»
...
«ENDFILE»
«ENDLET»</programlisting></para>
</listitem>
</itemizedlist>
</section>
</section>
<section id="xpand_reference_for_vs_foreach">
<title>FOR vs. FOREACH<indexterm>
<primary>FOR</primary>
</indexterm><indexterm>
<primary>FOREACH</primary>
</indexterm></title>
<para>If <varname>FOR</varname> or <varname>FOREACH</varname> is
omitted the other template is called <varname>FOR this</varname>.
<programlisting>«EXPAND TemplateFile::definitionName»</programlisting>
equals <programlisting>«EXPAND TemplateFile::definitionName FOR this»</programlisting>
If <varname>FOR</varname> is specified, the definition is executed for
the result of the target expression. <programlisting>«EXPAND myDef FOR entity»</programlisting>If
<varname>FOREACH</varname> is specified, the target expression must
evaluate to a collection type<indexterm>
<primary>collection type</primary>
</indexterm>. In this case, the specified definition is executed for
each element of that collection. <programlisting>«EXPAND myDef FOREACH entity.allAttributes» </programlisting></para>
<para>An <varname>EvaluationException</varname> will be thrown if the
specified target expression cannot be evaluated to an existing element
of the instantiated model or no suitable <varname>DEFINE</varname>
block can be found.</para>
<section id="xpand_reference_specifying_a_separator">
<title>Specifying a Separator<indexterm>
<primary>SEPARATOR</primary>
</indexterm></title>
<para>If a definition is to be expanded <varname>FOREACH</varname>
element of the target expression it is possible to specify a
<varname>SEPARATOR</varname> expression: <programlisting>«EXPAND paramTypeAndName FOREACH params SEPARATOR ','»</programlisting>The
result of the separator expression<indexterm>
<primary>Expression</primary>
<secondary>separator</secondary>
</indexterm> will be written to the output between each evaluation
of the target definition. Not <emphasis>after</emphasis> each one,
but rather only in <emphasis>between</emphasis> two elements. This
comes in handy for things such as comma-separated parameter
lists.</para>
</section>
</section>
<section id="xpand_reference_foreach">
<title>FOREACH</title>
<para>This statement expands the body of the
<varname>FOREACH</varname> block for each element of the target
collection<indexterm>
<primary>Collection</primary>
</indexterm> that results from the expression. The current element
is bound to a variable with the specified name in the current context.
<programlisting>«FOREACH expression AS variableName [ITERATOR iterName] [SEPARATOR expression]»
a sequence of statements using variableName to access the
current element of the iteration
«ENDFOREACH»</programlisting>The body of a <varname>FOREACH</varname> block
can contain any other statements; specifically
<varname>FOREACH</varname> statements may be nested.</para>
<para>If <varname>ITERATOR</varname><indexterm>
<primary>ITERATOR</primary>
</indexterm> name is specified, an object of the type
<classname>xpand2::Iterator</classname> (see API doc for details) is
accessible using the specified name.</para>
<para>The <varname>SEPARATOR</varname> expression works in the same
way as the one for <link
linkend="xpand_reference_specifying_a_separator"><varname>EXPAND</varname></link>.</para>
<para><emphasis role="bold">Example: </emphasis><programlisting>«FOREACH {'A','B','C'} AS c ITERATOR iter SEPARATOR ','»
«iter.counter1» : «c»
«ENDFOREACH»</programlisting>The evaluation of the above statement results in
the following text: <programlisting>1 : A,
2 : B,
3 : C</programlisting></para>
</section>
<section id="xpand_reference_if">
<title>IF<indexterm>
<primary>IF</primary>
</indexterm></title>
<para>The <varname>IF</varname> statement supports conditional
expansion. Any number of <varname>ELSEIF</varname><indexterm>
<primary>ELSEIF</primary>
</indexterm> statements is allowed. The <varname>ELSE</varname>
block is optional. Every <varname>IF</varname> statement must be
closed with an <varname>ENDIF</varname><indexterm>
<primary>ENDIF</primary>
</indexterm>. The body of an <varname>IF</varname> block can contain
any other statement, specifically, <varname>IF</varname> statements
may be nested. <programlisting>«IF expression»
a sequence of statements
[ «ELSEIF expression» ]
a sequence of statements ]
[ «ELSE»
a sequence of statements ]
«ENDIF»</programlisting></para>
</section>
<section id="xpand_reference_protect">
<title>PROTECT<indexterm>
<primary>PROTECT</primary>
</indexterm></title>
<para>Protected Regions<indexterm>
<primary>Protected region</primary>
</indexterm> are used to mark sections in the generated code that
shall not be overridden again by the subsequent generator run. These
sections typically contain manually written code. <programlisting>«PROTECT CSTART expression CEND expression ID expression (DISABLE)?»
a sequence of statements
«ENDPROTECT»</programlisting>The values of
<classname>CSTART</classname><indexterm>
<primary>CSTART</primary>
</indexterm> and <classname>CEND</classname><indexterm>
<primary>CEND</primary>
</indexterm> expressions are used to enclose the protected regions
marker in the output. They should build valid comment beginning and
comment end strings corresponding to the generated target language
(e.g. <emphasis>"/*"</emphasis> and <emphasis>"*/"</emphasis> for
Java).</para>
<para>The following is an example for Java: <programlisting>«PROTECT CSTART "/*" CEND "*/" ID ElementsUniqueID»
here goes some content
«ENDPROTECT»</programlisting>The ID is set by the <varname>ID</varname>
expression and must be <emphasis>globally unique</emphasis> (at least
for one complete pass of the generator). To assure this these IDs are
usually concatenated. Some model types (e.g. UML2 models) contain
identifiers that could be used, which can be read using the <link
linkend="stdlib_uid_xmlid"><methodname>xmlId()</methodname> function
from stdlib</link>.</para>
<para>Generated target code looks like this: <programlisting>public class Person {
/*PROTECTED REGION ID(Person) ENABLED START*/
This protected region is enabled, therefore the contents will
always be preserved. If you want to get the default contents
from the template you must remove the ENABLED keyword (or even
remove the whole file :-))
/*PROTECTED REGION END*/
}</programlisting>Protected regions are generated in enabled state<indexterm>
<primary>Protected region</primary>
<secondary>Enable</secondary>
</indexterm> by default. Unless you manually disable<indexterm>
<primary>Protected region</primary>
<secondary>Disable</secondary>
</indexterm> them, by removing the <varname>ENABLED</varname>
keyword, they will always be preserved.</para>
<para>If you want the generator to generate disabled protected
regions, you need to add the <varname>DISABLE</varname> keyword inside
the declaration: <programlisting>«PROTECT CSTART '/*' CEND '*/' ID this.name DISABLE»</programlisting></para>
<para>The produced target code won't contain the
<classname>ENABLED</classname> flag then. In this case
<classname>ENABLED</classname> has to be added to the target region to
activate the protected region. Disabling protected regions by default
has the advantage that the protected region default content in the
template can be changed and all not yet activated regions would
contain the changed code after regeneration.</para>
</section>
<section id="xpand_reference_let">
<title>LET<indexterm>
<primary>LET</primary>
</indexterm></title>
<para><varname>LET</varname> lets you specify local
variables:<programlisting>«LET expression AS variableName»
a sequence of statements
«ENDLET»</programlisting>During the expansion of the body of the
<varname>LET</varname><indexterm>
<primary>LET</primary>
</indexterm> block, the value of the expression is bound to the
specified variable. Note that the expression will only be evaluated
once, independent from the number of usages of the variable within the
<varname>LET</varname> block.</para>
<para><emphasis role="bold">Example:</emphasis> <programlisting>«LET packageName + "." + className AS fqn»
the fully qualified name is: «fqn»;
«ENDLET»</programlisting></para>
<para>The variable value can not be reassigned within a
<classname>LET</classname> block.</para>
</section>
<section id="xpand_reference_error">
<title>ERROR<indexterm>
<primary>ERROR</primary>
</indexterm></title>
<para>The <varname>ERROR</varname> statement aborts the evaluation of
the templates by throwing an
<varname>XpandException</varname><indexterm>
<primary>XpandException</primary>
</indexterm> with the specified message. <programlisting>«ERROR expression»</programlisting>Note
that you should use this facility very sparingly, since it is better
practice to check for invalid models using constraints on the
metamodel, and not in the templates!</para>
</section>
<section id="xpand_reference_comments">
<title>Comments<indexterm>
<primary>Xpand</primary>
<secondary>Comments</secondary>
</indexterm></title>
<para>Comments are only allowed outside of tags. <programlisting>«REM»
text comment
«ENDREM»</programlisting>Comments may not contain a REM<indexterm>
<primary>REM</primary>
</indexterm> tag, this implies that comments are not nestable. A
comment may not have a white space between the
<classname>REM</classname> keyword and its brackets.</para>
<para><emphasis role="bold">Example:</emphasis> <programlisting>«REM»«LET expression AS variableName»«ENDREM»
a sequence of statements
«REM» «variableName.stuff»
«ENDLET»«ENDREM»</programlisting></para>
</section>
<section id="xpand_reference_expression_statement">
<title>Expression Statement<indexterm>
<primary>Xpand</primary>
<secondary>Expression statements</secondary>
</indexterm></title>
<para>Expressions support processing of the information provided by
the instantiated metamodel. <emphasis>Xpand</emphasis> provides
powerful expressions for selection, aggregation, and navigation.
<emphasis>Xpand</emphasis> uses the expressions sublanguage in almost
any statement that we have seen so far. The expression statement just
evaluates the contained expression and writes the result to the output
(using the <varname>toString()</varname> method of
<varname>java.lang.Object</varname>). Example: <programlisting>public class «this.name» {</programlisting>All
expressions defined by the expressions sublanguage are also available
in <emphasis>Xpand</emphasis>. You can invoke imported extensions.
(See the <emphasis><xref
linkend="r10_expressions_language" /></emphasis> and <emphasis><xref
linkend="Xtend_language" /> language reference</emphasis> for more
details).</para>
</section>
<section id="xpand_reference_controlling_generation_of_white_space">
<title>Controlling generation of whitespace</title>
<para>If you want to omit the output of superfluous
whitespace<indexterm>
<primary>Whitespace</primary>
<secondary>Omit</secondary>
</indexterm> you can add a minus sign just before any closing
bracket.</para>
<para><emphasis role="bold">Example:</emphasis> <programlisting>«FILE InterfaceName + ".java"-»
«IF hasPackage-»
package «InterfacePackageName»;
«ENDIF-»
...
«ENDFILE»</programlisting>The generated file would start with two new lines
(one after the <varname>FILE</varname> and one after the
<varname>IF</varname> statement) if the minus characters had not been
set.</para>
<para>In general, this mechanism works as follows: If a statement (or
comment) ends with such a minus all preceding whitespace up to the
newline<indexterm>
<primary>Newline</primary>
</indexterm> character (excluded!) is removed. Additionally all
following whitespace including the first newline character
(<varname>\r\n</varname> is handled as one character) is also
removed.</para>
</section>
</section>
<section id="xpand_reference_aspect-oriented_programming_in_xpand">
<title>Aspect-Oriented Programming in
<emphasis>Xpand</emphasis><indexterm>
<primary>AOP</primary>
</indexterm></title>
<para>Using the workflow engine it is now possible to package
(<emphasis>e.g.</emphasis> zip) a written generator and deliver it as a
kind of black box (this is often called a cartridge<indexterm>
<primary>cartridge</primary>
</indexterm>). If you want to use such a generator but need to change
some small generation stuff, you can make use of the
<varname>AROUND</varname><indexterm>
<primary>AROUND</primary>
</indexterm> aspects. <programlisting>«AROUND qualifiedDefinitionName(parameterList)? FOR type»
a sequence of statements
«ENDAROUND» </programlisting><varname>AROUND</varname> lets you add templates
in an non-invasive way (you do not need to touch the generator
templates). Because aspects are invasive, a template file containing
<varname>AROUND</varname> aspects must be wrapped by configuration (see
next section).</para>
<section id="xpand_reference_join_point_and_cut_syntax">
<title>Join Point<indexterm>
<primary>Join point</primary>
</indexterm><indexterm>
<primary>AOP</primary>
<secondary>Join point</secondary>
</indexterm> and Point Cut<indexterm>
<primary>Point cut</primary>
</indexterm><indexterm>
<primary>AOP</primary>
<secondary>Point cut</secondary>
</indexterm> Syntax</title>
<para>AOP is basically about weaving code into different points inside
the call graph of a software module. Such points are called
<emphasis>Join Points</emphasis><indexterm>
<primary>Join point</primary>
</indexterm>. In <emphasis>Xpand</emphasis>, there is only one join
point so far: a call to a definition.</para>
<para>You specify on which join points the contributed code should be
executed by specifying something like a 'query' on all available join
points. Such a query is called a <emphasis>point
cut</emphasis><indexterm>
<primary>Join point</primary>
</indexterm>. <programlisting>«AROUND [pointcut]»
do stuff
«ENDAROUND»</programlisting> A point cut consists of a fully qualified name,
parameter types and the target type.</para>
<section id="xpand_reference_definition_name">
<title>Definition Name</title>
<para>The definition name part of a point cut must match the fully
qualified name of the join point definition. Such expressions are
<emphasis>case sensitive</emphasis>. The asterisk character is used
to specify wildcards.</para>
<para>Some examples: <programlisting>my::Template::definition // definitions with the specified name
org::eclipse::xpand2::* // definitions prefixed with 'org::eclipse::xpand2::'
*Operation* // definitions containing the word 'Operation' in it.
* // all definitions</programlisting></para>
</section>
<section id="xpand_reference_parameter_types">
<title>Parameter Types</title>
<para>The parameters of the definitions we want to add our advice
to, can also be specified in the point cut. The rule is that the
type of the specified parameter must be the same or a supertype of
the corresponding parameter type (the dynamic type at runtime!) of
the definition to be called.</para>
<para>Additionally, one can set a wildcard at the end of the
parameter list, to specify that there might be an arbitrary number
of parameters of any kind.</para>
<para>Some examples: <programlisting>my::Templ::def() // templ def without parameters
my::Templ::def(String s) // templ def with exactly one parameter
// of type String
my::Templ::def(String s,*) // templ def with one or more parameters,
// where the first parameter is of type String
my::Templ::def(*) // templ def with any number of parameters</programlisting></para>
</section>
<section id="xpand_reference_target_type">
<title>Target Type</title>
<para>Finally, we have to specify the target type. This is
straightforward: <programlisting>my::Templ::def() FOR Object// templ def for any target type
my::Templ::def() FOR Entity// templ def objects of type Entity</programlisting></para>
</section>
</section>
<section id="xpand_reference_proceeding">
<title>Proceeding</title>
<para>Inside an advice, you might want to call the underlying
definition. This can be done using the implicit variable
<varname>targetDef</varname>, which is of the type
<type>xpand2::Definition</type> and which provides an operation
<methodname>proceed()</methodname>that invokes the underlying
definition with the original parameters (Note that you might have
changed any mutable object in the advice before).</para>
<para>If you want to control which parameters are to be passed to the
definition, you can use the operation <methodname>proceed</methodname>
(<classname>Object</classname> <varname>target</varname>,
<classname>List</classname> <varname>params</varname>). Please keep in
mind that no type checking is done in this context.</para>
<para>Additionally, there are some inspection properties (like
<varname>name</varname>, <varname>paramTypes</varname>, etc.)
available.</para>
</section>
</section>
<section id="xpand_reference_generator_workflow_component">
<title>Generator Workflow Component<indexterm>
<primary>Generator</primary>
<secondary>Workflow component</secondary>
</indexterm></title>
<para>This section describes the workflow component that is provided to
perform the code generation, i.e. run the templates. You should have a
basic idea of how the workflow engine works. A simple generator
component configuration could look as follows:<programlisting>&lt;component class="org.eclipse.xpand2.Generator"&gt;
&lt;fileEncoding value="ISO-8859-1"/&gt;
&lt;metaModel class="org.eclipse.xtend.typesystem.emf.EmfMetaModel"&gt;
&lt;metaModelPackage value="org.eclipse.emf.ecore.EcorePackage"/&gt;
&lt;/metaModel&gt;
&lt;expand value="somenamespace::example::Java::all FOR myModel"/&gt;
&lt;!-- aop configuration --&gt;
&lt;advices value='somenamespace::example::Advices1, example::Advices2'/&gt;
&lt;!-- output configuration --&gt;
&lt;outlet path='main/src-gen'&gt;
&lt;postprocessor class="org.eclipse.xpand2.output.JavaBeautifier"/&gt;
&lt;postprocessor class="org.eclipse.xtend.typesystem.xsd.XMLBeautifier"/&gt;
&lt;/outlet&gt;
&lt;outlet name='TO_SRC' path='main/src' overwrite='false'&gt;
&lt;postprocessor class="org.eclipse.xpand2.output.JavaBeautifier"/&gt;
&lt;postprocessor class="org.eclipse.xtend.typesystem.xsd.XMLBeautifier"/&gt;
&lt;/outlet&gt;
&lt;!-- optional: protected regions configuration --&gt;
&lt;prSrcPaths value="main/src"/&gt;
&lt;prDefaultExcludes value="false"/&gt;
&lt;prExcludes value="*.xml"/&gt;
&lt;/component&gt;</programlisting>Now, let us go through the different
properties one by one.</para>
<section id="xpand_reference_main_configuration">
<title>Main configuration</title>
<para>The first thing to note is that the qualified Java name of the
component is <varname>org.eclipse.xpand2.Generator</varname>.</para>
</section>
<section id="xpand_reference_encoding">
<title>Encoding</title>
<para>For <emphasis>Xpand</emphasis> it is important to have the file
encoding<indexterm>
<primary>File encoding</primary>
<secondary>encoding</secondary>
</indexterm> in mind because of the
<foreignphrase>guillemet</foreignphrase> characters <indexterm>
<primary>Guillemet</primary>
</indexterm> « » used to delimit keywords and property access. The
<varname>fileEncoding</varname> property<indexterm>
<primary>Generator</primary>
<secondary>fileEncoding property</secondary>
</indexterm> specifies the file encoding to use for reading the
templates, reading the protected regions and writing the generated
files. This property defaults to the default file encoding of your
JVM.</para>
<para>In a team that uses different operating systems or locales it is
a good idea to set the file encoding fixed for the Xpand project and
share the settings. Typical encodings used are UTF-8 or ISO-8859-1,
but any encoding having guillemet brackets is fine also.<footnote>
<para>On Mac OSX the default encoding is MacRoman, which is not a
good choice, since other operating systems are not aware of this
encoding. It is recommended to set the encoding to some more
common encoding, e.g. UTF-8, maybe even for the whole
workspace.</para>
</footnote></para>
<para>An false encoding can result in an error message of the
generator during runtime:</para>
<programlisting>1108 ERROR WorkflowRunner - [ERROR]: no viable alternative at input 'Â' on line 1</programlisting>
<para>In this case you have to configure the input encoding. A
<interface>ResourceManager</interface> is used to set the input
encoding. Use the <code>fileEncoding</code> property of the
<code>ResourceManager</code> inside the generator component to
configure the encoding of templates and extensions.</para>
<para>Example for <emphasis>MWE</emphasis>:</para>
<programlisting>&lt;component class="org.eclipse.xpand2.Generator"&gt;
&lt;metaModel idRef="mm_emf"/&gt;
&lt;expand
value="template::Template::main FOR model" /&gt;
&lt;outlet path="${src-gen}" &gt;
&lt;postprocessor class="org.eclipse.xpand2.output.JavaBeautifier" /&gt;
&lt;/outlet&gt;
&lt;resourceManager class ="org.eclipse.xtend.expression.ResourceManagerDefaultImpl"&gt;
&lt;fileEncoding value="ISO-8859-1"/&gt;
&lt;/resourceManager&gt;
&lt;/component&gt;</programlisting>
<para>Example for <emphasis>MWE2</emphasis>:</para>
<programlisting>component = org.eclipse.xpand2.Generator {
metaModel = org.eclipse.xtend.typesystem.emf.EmfRegistryMetaModel {}
expand = "templates::Template::main FOREACH model"
outlet = {
path = targetDir
}
resourceManager = org.eclipse.xtend.expression.ResourceManagerDefaultImpl {
fileEncoding = "ISO-8859-1"
}
}
</programlisting>
<para>The section <emphasis><xref
linkend="xpand_reference_output_configuration" /></emphasis> describes
how to configure the encoding of the generated files.</para>
</section>
<section id="xpand_reference_metamodel">
<title>Metamodel</title>
<para>The property <varname>metaModel</varname><indexterm>
<primary>Generator</primary>
<secondary>Metamodel configuration</secondary>
</indexterm> is used to tell the generator engine on which
metamodels the <emphasis>Xpand</emphasis> templates should be
evaluated. One can specify more than one metamodel here. Metamodel
implementations are required by the expression framework (see
<emphasis><xref linkend="r10_expressions_language" /></emphasis>) used
by <emphasis>Xpand2</emphasis>. In the example above we configured the
Ecore metamodel using the <classname>EMFMetaModel</classname>
implementation shipped with the core part of the
<emphasis>Xpand</emphasis> release.</para>
<para>A mandatory configuration is the <varname>expand</varname>
property. It expects a syntax similar to that of the
<varname>EXPAND</varname> statement (described above). The only
difference is that we omit the <varname>EXPAND</varname><indexterm>
<primary>EXPAND</primary>
</indexterm> keyword. Instead, we specify the name of the
property.</para>
<para>Examples: <programlisting>&lt;expand value="some::namespace::Template::define FOR mySlot"/&gt;</programlisting>
or: <programlisting>&lt;expand value="some::namespace::Template::define('foo') FOREACH {mySlot1,mySlot2}"/&gt;</programlisting>The
expressions are evaluated using the workflow context. Each slot is
mapped to a variable. For the examples above the workflow context
needs to contain elements in the slots <varname>'mySlot'</varname>,
<varname>'mySlot1'</varname> and <varname>'mySlot2'</varname>. It is
also possible to specify some complex expressions here. If, for
instance, the slot <varname>myModel</varname> contains a collection of
model elements one could write:<indexterm>
<primary>typeSelect</primary>
</indexterm> <programlisting>&lt;expand value="some::namespace::Template::define FOREACH myModel.typeSelect(Entity)"/&gt;</programlisting>This
selects all elements of type <emphasis>Entity</emphasis> contained in
the collection stored in the <varname>myModel</varname> slot.</para>
</section>
<section id="xpand_reference_output_configuration"
xreflabel="Output configuration">
<title>Output configuration</title>
<para>The second mandatory configuration is the specification of so
called outlets (a concept borrowed from AndroMDA). Outlets<indexterm>
<primary>Outlet</primary>
</indexterm> are responsible for writing the generated files to
disk.</para>
<para>Example <emphasis>MWE</emphasis>: <programlisting>&lt;component class="org.eclipse.xpand2.Generator"&gt;
...
&lt;outlet path='main/src-gen'/&gt;
&lt;outlet name='TO_SRC' path='main/src' overwrite='false'&gt;
&lt;fileEncoding value='ISO-8859-1'/&gt;
&lt;/outlet&gt;
&lt;fileEncoding value='ISO-8859-1'/&gt;
...
&lt;/component&gt;</programlisting>Example <emphasis>MWE2</emphasis>:
<programlisting>component = org.eclipse.xpand2.Generator {
metaModel = org.eclipse.xtend.typesystem.emf.EmfRegistryMetaModel {}
expand = "templates::Template::main FOREACH model"
outlet = {path = 'main/src-gen'}
outlet = {
name='TO_SRC'
path='main/src'
overwrite= false
fileEncoding = 'ISO-8859-1'
}
fileEncoding = 'ISO-8859-1'
...
}
</programlisting>In the examples there are two outlets configured. The first
one has no name and is therefore handled as the default outlet.
Default outlets are triggered by omitting an outlet name:
<programlisting>«FILE 'test/note.txt'»
# this goes to the default outlet
«ENDFILE»</programlisting>The configured base path is
'<filename>main/src-gen</filename>', so the file from above would go
to '<filename>main/src-gen/test/note.txt</filename>'.</para>
<para>The second outlet has a <varname>name</varname> ('TO_SRC')
specified. Additionally the flag <varname>overwrite</varname> is set
to <varname>false</varname> (defaults to <varname>true</varname>). The
following <emphasis>Xpand</emphasis> fragment <programlisting>«FILE 'test/note.txt' TO_SRC»
# this goes to the TO_SRC outlet
«ENDFILE»</programlisting>would cause the generator to write the contents to
'<filename>main/src/test/note.txt</filename>' if the file does not
already exist (the <varname>overwrite</varname> flag).</para>
<para>Another option called <varname>append</varname> (defaults to
<varname>false</varname>) causes the generator to append the generated
text to an existing file. If <varname>overwrite</varname> is set to
<varname>false</varname> this flag has no effect.</para>
<para>The encoding<indexterm>
<primary>File encoding</primary>
<secondary>encoding</secondary>
</indexterm> of the generated files can be configured at two
different levels. A file encoding can be defined for the complete
generator component. Therefore the <emphasis>fileEncoding</emphasis>
property inside the component definition has to be used (see the
examples above). You can also define a file encoding at outlet level.
Therefore the <emphasis>fileEncoding</emphasis> property inside the
outlet definition has to be used.</para>
</section>
<section id="xpand_reference_beautifier">
<title>PostProcessor <indexterm>
<primary>PostProcessor</primary>
</indexterm></title>
<para>Beautifying the generated code is a good idea. It is very
important that generated code looks good, because developers should be
able to understand it. On the other hand template files should look
good, too. It is thus best practice to write nice looking template
files and not to care how the generated code looks - and then you run
a beautifier over the generated code to fix that problem. Of course,
if a beautifier is not available, or if white space has syntactical
meaning (as in Python), you would have to write your templates with
that in mind (using the minus character before closing brackets as
described in a preceding section).</para>
<para>The <emphasis>Xpand</emphasis> workflow component can be
configured with multiple beautifiers:<programlisting>&lt;outlet ...&gt;
&lt;postprocessor class="org.eclipse.xpand2.output.JavaBeautifier"/&gt;
&lt;postprocessor class="org.eclipse.xtend.typesystem.xsd.XMLBeautifier"/&gt;
&lt;/outlet&gt;
</programlisting>These are the two beautifiers delivered with
<emphasis>Xpand</emphasis>. If you want to use your own beautifier,
you would just need to implement the
<classname>PostProcessor</classname> Java interface<indexterm>
<primary>PostProcessor</primary>
</indexterm>: <programlisting>package org.eclipse.xpand2.output;
public interface PostProcessor {
public void beforeWriteAndClose(FileHandle handle);
public void afterClose(FileHandle handle);
}</programlisting>The <varname>beforeWriteAndClose</varname> method is called
for each <varname>ENDFILE</varname> statement.</para>
<para>PostProcessors can also be used for othermeans than formatting,
like line counting.</para>
<section id="xpand_reference_javabeautifier">
<title>JavaBeautifier</title>
<para>The JavaBeautifier<indexterm>
<primary>JavaBeautifier</primary>
</indexterm> is based on the Eclipse Java formatter provides base
beautifying for Java files.</para>
</section>
<section id="xpand_reference_xmlbeautifier">
<title>XmlBeautifier</title>
<para>The XmlBeautifier is based on <emphasis>dom4j</emphasis> and
provides a single option <varname>fileExtensions</varname> (defaults
to "<filename>.xml</filename>, <filename>.xsl</filename>,
<filename>.wsdd</filename>, <filename>.wsdl</filename>") used to
specify which files should be pretty-printed.</para>
</section>
<section>
<title>CppBeautifier</title>
<para>The CppBeautifier leverages CDT for formatting C/C++ sources.
Thus CDT is required to use this code formatter. To use this
beautifier the plugin
<package>org.eclipse.xpand.support.cdt</package> must be added to
the plugin dependencies.</para>
</section>
</section>
<section id="xpand_reference_protected_region_configuration">
<title>Protected Region Configuration</title>
<para>Finally, you need to configure the protected region resolver, if
you want to use protected regions<indexterm>
<primary>Protected region</primary>
</indexterm>. <programlisting>&lt;prSrcPaths value="main/src"/&gt;
&lt;prDefaultExcludes value="false"/&gt;
&lt;prExcludes value="*.xml"/&gt;</programlisting>The
<emphasis>prSrcPaths</emphasis><indexterm>
<primary>prSrcPaths</primary>
</indexterm>property points to a comma-separated list of
directories. The protected region resolver will scan these directories
for files containing activated protected regions.</para>
<para>There are several file names which are excluded by default:
<programlisting>RCS, SCCS, CVS, CVS.adm, RCSLOG, cvslog.*, tags, TAGS, .make.state, .nse_depinfo, *~, #*,
.#*, ',*', _$*,*$, *.old, *.bak, *.BAK, *.orig, *.rej, .del-*, *.a, *.olb, *.o, *.obj,
*.so, *.exe, *.Z,* .elc, *.ln, core, .svn</programlisting> If you do not want
to exclude any of these, you must set
<varname>prDefaultExcludes</varname> to false. <programlisting>&lt;prDefaultExcludes value="false"/&gt;</programlisting>
If you want to add additional excludes, you should use the prExcludes
property. <programlisting>&lt;prExcludes value="*.xml,*.hbm"/&gt;</programlisting></para>
<note>
<para>It is bad practice to mix generated and non-generated code in
one artifact. Instead of using protected regions, you should try to
leverage the extension features of the used target language
(inheritance, inclusion, references, etc.) wherever possible. It is
very rare that the use of protected regions is an appropriate
solution.</para>
</note>
</section>
<section>
<title>VetoStrategy<indexterm>
<primary>VetoStrategy</primary>
</indexterm></title>
<para>The <emphasis>Xpand</emphasis> engine will generate code for
each processed <property>FILE</property> statement. This implies that
files are written that might not have changed to the previous
generator run. Normally it does not matter that files are rewritten.
There are at least two good reasons when it is better to avoid
rewriting of files:</para>
<orderedlist>
<listitem>
<para>The generated source code will be checked in. In general it
is not the recommended way to go to check in generated code, but
sometimes you will have to. Especially with CVS there is the
problem that rewritten files are recognized as modified, even if
they haven't changed. So the problem arises that identical files
get checked in again and again (or you revert it manually). When
working in teams the problem even becomes worse, since team
members will have conflicts when checking in.</para>
</listitem>
<listitem>
<para>When it can be predicted that the generator won't produce
different content before a file is even about to be created by a
FILE statement then this can boost performance. Of course it is
not trivial to predict that a specific file won't result in
different content before it is even created. This requires
information from a prior generator run and evaluation against the
current model to process. Usually a diff model would be used as
input for the decision.</para>
</listitem>
</orderedlist>
<para>Case 1) will prevent file writing after a
<property>FILE</property> statement has been evaluated, case 2) will
prevent creating a file at all.</para>
<para>To achieve this it is possible to add Veto Strategies to the
generator, which are implementations of interface
<classname>org.eclipse.xpand2.output.VetoStrategy</classname> or
<classname>org.eclipse.xpand2.output.VetoStrategy2</classname>. Use
<classname>VetoStrategy2</classname> if you implement your own.</para>
<para><classname>VetoStrategy2</classname> declares two
methods:</para>
<itemizedlist>
<listitem>
<para><methodname>boolean hasVetoBeforeOpen
(FileHandle)</methodname></para>
<para>This method will be called before a file is being opened and
generated. Return true to suppress the file creation.</para>
</listitem>
<listitem>
<para><methodname>boolean hasVeto (FileHandle)</methodname></para>
<para>This method will be called after a file has been produced
and after all configured PostProcessors have been invoked. Return
true to suppress writing the file.</para>
</listitem>
</itemizedlist>
<para>Veto Strategies are configured per Outlet. It is possible to add
multiple stratgy instances to each Outlet.</para>
<para><programlisting> &lt;component id="generator" class="org.eclipse.xpand2.Generator" skipOnErrors="true"&gt;
&lt;metaModel class="org.eclipse.xtend.typesystem.uml2.UML2MetaModel"/&gt;
&lt;expand value="templates::Root::Root FOR model"/&gt;
&lt;fileEncoding value="ISO-8859-1"/&gt;
&lt;outlet path="src-gen"&gt;
&lt;postprocessor class="org.eclipse.xpand2.output.JavaBeautifier"/&gt;
<emphasis role="bold">&lt;vetoStrategy class="org.eclipse.xpand2.output.NoChangesVetoStrategy"/&gt;</emphasis>
&lt;/outlet&gt;
&lt;/component&gt;
</programlisting>One <classname>VetoStrategy</classname> is already provided.
The
<classname>org.eclipse.xpand2.output.NoChangesVetoStrategy</classname>
<indexterm>
<primary>NoChangesVetoStrategy</primary>
</indexterm>is a simple implementation that will compare the
produced output, after it has been postprocessed, with the target
file. If the content is identical the strategy vetoes the file
writing. This strategy is effective, but has two severe
drawbacks:</para>
<orderedlist>
<listitem>
<para>The file has been created at least in memory before. This
consumes time and memory. If applying code formatting this usually
implies that the file is temporarily written.</para>
</listitem>
<listitem>
<para>The existing file must be read into memory. This also costs
time and memory.</para>
</listitem>
</orderedlist>
<para>Much better would be to even prevent the creation of files by
having a valid implementation for the
<classname>hasVetoBeforeOpen()</classname> method. Providing an
implementation that predicts that files do not have to be created
requires domain knowledge, thus a standard implementation is not
available.</para>
<para>The number of skipped files will be reported by the Generator
component like this:</para>
<para><programlisting>2192 INFO - Generator(generator): generating &lt;...&gt;
3792 INFO - <emphasis role="bold">Skipped writing of 2 files to outlet</emphasis> [default](src-gen)
</programlisting></para>
</section>
</section>
<section id="aop_template_introduction">
<title>Example for using Aspect-Oriented Programming in
<emphasis>Xpand</emphasis></title>
<para><indexterm>
<primary>AOP</primary>
<secondary>Xpand</secondary>
</indexterm>This example shows how to use aspect-oriented programming
techniques in <emphasis>Xpand</emphasis> templates. It is applicable to
EMF based and <emphasis>Classic</emphasis> systems. However, we explain
the idea based on the <emphasis>emfExample</emphasis>. Hence you should
read that before.</para>
</section>
<section id="aop_template_the_problem">
<title>The Problem</title>
<para>There are many circumstances when template-AOP is useful. Here are
two examples:</para>
<para><emphasis role="bold">Scenario 1:</emphasis> Assume you have a
nice generator that generates certain artifacts. The generator (or
cartridge) might be a third party product, delivered in a single JAR
file. Still you might want to adapt certain aspects of the generation
process <emphasis>without modifying the original
generator</emphasis>.</para>
<para><emphasis role="bold">Scenario 2:</emphasis> You are building a
family of generators that can generate variations of the generate code,
e.g. Implementations for different embedded platforms. In such a
scenario, you need to be able to express those differences
(variabilities) sensibly without creating a non-understandable chaos of
<emphasis>if</emphasis> statements in the templates.</para>
</section>
<section id="aop_template_example">
<title>Example</title>
<para>To illustrate the idea of extending a generator without "touching"
it, let us create a new project called
<classname>org.eclipse.demo.emf.datamodel.generator-aop</classname>. The
idea is that it will "extend" the original
<classname>org.eclipse.demo.emf.datamodel.generator</classname> project
introduced in the <emphasis>emfExample</emphasis>. So this new projects
needs to have a project dependency to the former one.</para>
<section id="aop_template_example_templates">
<title>Templates</title>
<para>An AOP system always needs to define a join point<indexterm>
<primary>join point</primary>
</indexterm> model; this is, you have to define, at which locations
of a (template) program you can add additional (template) code. In
<emphasis>Xpand</emphasis>, the join points are simply templates (i.e.
<emphasis>DEFINE .. ENDDEFINE</emphasis>) blocks. An "aspect template"
can be declared <emphasis>AROUND</emphasis><indexterm>
<primary>AROUND</primary>
</indexterm> previously existing templates. If you take a look at
the <classname>org.eclipse.demo.emf.datamodel.generator</classname>
source folder of the project, you can find the
<filename>Root.xpt</filename> template file. Inside, you can find a
template called <classname>Impl</classname> that generates the
implementation of the JavaBean.</para>
<programlisting language="Xpand">«DEFINE Entity FOR data::Entity»
«FILE baseClassFileName() »
// generated at «timestamp()»
public abstract class «baseClassName()» {
«EXPAND Impl»
}
«ENDFILE»
«ENDDEFINE»
«DEFINE Impl FOR data::Entity»
«EXPAND GettersAndSetters»
«ENDDEFINE»
«DEFINE Impl FOR data::PersistentEntity»
«EXPAND GettersAndSetters»
public void save() {
}
«ENDDEFINE»</programlisting>
<para>What we now want to accomplish is this: Whenever the
<emphasis>Impl</emphasis> template is executed, we want to run an
additional template that generates additional code (for example, some
kind of meta information for a given framework. The specific code at
this place is not important for the example here).</para>
<para>So, in our new project, we define the following template
file:</para>
<programlisting language="Xpand">«AROUND Impl FOR data::Entity»
«FOREACH attribute AS a»
public static final AttrInfo «a.name»Info = new AttrInfo(
"«a.name»", «a.type».class );
«ENDFOREACH»
«targetDef.proceed()»
«ENDAROUND»</programlisting>
<para>So, this new template wraps around the existing template called
<classname>Impl</classname> It first generates additional code and
then forwards the execution to the original template using
<methodname>targetDef.proceed()</methodname>. So, in effect, this is a
<varname>BEFORE</varname> advice. Moving the
<methodname>proceed</methodname> statement to the beginning makes it
an <varname>AFTER</varname> advice, omitting it, makes it an
override.</para>
</section>
<section id="aop_template_example_workflow_file">
<title>Workflow File<indexterm>
<primary>AOP</primary>
<secondary>Workflow</secondary>
</indexterm></title>
<para>Let us take a look at the workflow file to run this
generator:</para>
<programlisting language="xml">&lt;workflow&gt;
&lt;cartridge file="workflow.mwe"/&gt;
&lt;component adviceTarget="generator"
id="reflectionAdvice"
class="org.eclipse.xpand2.GeneratorAdvice"&gt;
&lt;advices value="templates::Advices"/&gt;
&lt;/component&gt;
&lt;/workflow&gt;</programlisting>
<para>Mainly, what we do here, is to call the original workflow file.
It has to be available from the classpath. After this cartridge call,
we define an additional workflow component, a so called
<emphasis>advice component</emphasis>. It specifies
<emphasis>generator</emphasis> as its
<emphasis>adviceTarget</emphasis>. That means, that all the properties
we define inside this advice component will be added to the component
referenced by name in the <emphasis>adviceTarget</emphasis> instead.
In our case, this is the generator. So, in effect, we add the
<classname>&lt;advices value="templates::Advices" /&gt;</classname> to
the original generator component (without invasively modifying its own
definition). This contributes the advice templates to the
generator.</para>
</section>
<section id="aop_template_example_running_the_new_generator">
<title>Running the new generator</title>
<para>Running the generator produces the following code:</para>
<programlisting language="Java">public abstract class PersonImplBase {
public static final AttrInfo
nameInfo = new AttrInfo("name", String.class);
public static final AttrInfo
name2Info = new AttrInfo("name2", String.class);
private String name;
private String name2;
public void setName(String value) {
this.name = value;
}
public String getName() {
return this.name;
}
public void setName2(String value) {
this.name2 = value;
}
public String getName2() {
return this.name2;
}
}</programlisting>
</section>
</section>
<section id="aop_template_more_ao">
<title>More Aspect Orientation</title>
<para>In general, the syntax for the
<emphasis>AROUND</emphasis><indexterm>
<primary>AROUND</primary>
</indexterm> construct is as follows:</para>
<programlisting language="Expand">«AROUND fullyQualifiedDefinitionNameWithWildcards
(Paramlist (*)?) FOR TypeName»
do Stuff
«ENDAROUND»</programlisting>
<para>Here are some examples:</para>
<programlisting>«AROUND *(*) FOR Object»</programlisting>
<para>matches all templates</para>
<programlisting>«AROUND *define(*) FOR Object»</programlisting>
<para>matches all templates with <emphasis>define</emphasis> at the end
of its name and any number of parameters</para>
<programlisting>«AROUND org::eclipse::xpand2::* FOR Entity»</programlisting>
<para>matches all templates with namespace
<emphasis>org::eclipse::xpand2::</emphasis> that do not have any
parameters and whose type is Entity or a subclass</para>
<programlisting>«AROUND *(String s) FOR Object»</programlisting>
<para>matches all templates that have exactly one
<classname>String</classname> parameter</para>
<programlisting>«AROUND *(String s,*) FOR Object»</programlisting>
<para>matches all templates that have at least one
<classname>String</classname> parameter</para>
<programlisting>«AROUND my::Template::definition(String s) FOR Entity»</programlisting>
<para>matches exactly this single definition</para>
<para>Inside an <varname>AROUND</varname>, there is the variable
<varname>targetDef</varname>, which has the type
<classname>xpand2::Definition</classname>. On this variable, you can
call <methodname>proceed</methodname>, and also query a number of other
things:</para>
<programlisting>«AROUND my::Template::definition(String s) FOR String»
log('invoking '+«targetDef.name»+' with '+this)
«targetDef.proceed()»
«ENDAROUND»</programlisting>
</section>
</section>
<section id="r10_profiler">
<title>Profiler</title>
<para>The <emphasis>ProfilerComponent</emphasis> allows you to measure the
time each check, Xtend function or Xpand define needed to be executed in
your workflow. It does so by acting as a callback of the
<emphasis>CheckComponent</emphasis>, <emphasis>XtendComponent</emphasis>
and <emphasis>XpandComponent</emphasis> where the time of each call will
be stored in a profiling model. From this data the profiler eventually
derives execution times with and without children, callers/callees with
the corresponding call counts and finally a call graph with respect to
recursive calls. A set of Xpand templates can transform the model to an
HTML report or a text file in the GNU GProf format.</para>
<figure>
<mediaobject>
<imageobject role="fo">
<imagedata fileref="images/Xpand/profiler.png" scale="30" />
</imageobject>
<imageobject role="html">
<imagedata fileref="images/Xpand/profiler.png" scale="95" />
</imageobject>
</mediaobject>
<title>Sample HTML output of the profiler</title>
</figure>
<para>Use the <emphasis>ProfilerComponent</emphasis> to wrap other
components inside a workflow. Denote a <emphasis>resultSlot</emphasis>
where the profiler stores the model in the end. Then, refer to this
component via <emphasis>idRef</emphasis> as a callback. As soon as the
component-tag of the profiler closes, it stores the derived profiling
model in the given slot. You are free to transform this model or you can
re-use one of the templates that come with profiler.</para>
<programlisting>
&lt;component id="profiler" class="org.eclipse.xtend.profiler.ProfilerComponent"&gt;
&lt;resultSlot value="profilingResult" /&gt;
&lt;component class="org.eclipse.xtend.check.CheckComponent"&gt;
&lt;vetoableCallback idRef="profiler" /&gt;
...
&lt;/component&gt;
&lt;component class="org.eclipse.xtend.XtendComponent"&gt;
&lt;vetoableCallback idRef="profiler" /&gt;
...
&lt;/component&gt;
&lt;component class="org.eclipse.xpand2.Generator"&gt;
&lt;vetoableCallback idRef="profiler" /&gt;
...
&lt;/component&gt;
&lt;/component&gt;
&lt;component class="org.eclipse.xpand2.Generator" fileEncoding="ISO-8859-1"&gt;
&lt;metaModel idRef="mm"/&gt;
&lt;expand value="org::eclipse::xtend::profiler::templates::Html::Main FOR profilingResult"/&gt;
&lt;outlet overwrite="true" path="profiling"/&gt;
&lt;/component&gt;
</programlisting>
<para>Currently, there are two different templates available to render the
profiling model <itemizedlist>
<listitem>
<para>org::eclipse::xtend::profiler::templates::Html::Main</para>
</listitem>
<listitem>
<para>org::eclipse::xtend::profiler::templates::GProf::Main</para>
</listitem>
</itemizedlist></para>
<para>The Xpand Wizard will produce a workflow called
<emphasis>workflowWithProfiler.mwe</emphasis> that demonstrates the
capabilities of the profiler. It puts the result in the folder
<emphasis>profiling</emphasis>.</para>
</section>
</chapter>