# Xtend

Like the expressions sublanguage that summarizes the syntax of expressions for all the other textual languages delivered with the Xpand framework, there is another commonly used language called Xtend .

This language provides the possibility to define rich libraries of independent operations and non-invasive metamodel extensions based on either Java methods or Xtend expressions. Those libraries can be referenced from all other textual languages that are based on the expressions framework.

### Xtend files

An Xtend file must reside in the Java class path of the used execution context. File extension must be `*.ext`. Let us have a look at an Xend file.

    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)
    ;

The example shows the following statements:

1. import statements

2. extension import statements

3. expression or java extensions

### Comments

We have single- and multi-line comments. The syntax for single line comments is:

    // my comment

Multi line comments are written like this:

    /* My multi line comment */

### Import Statements

Using the import statement one can import name spaces of different types.(see expressions framework reference documentation).

Syntax is:

    import my::imported::namespace;

Xtend does not support static imports or any similar concept. Therefore, the following is incorrect syntax:

    import my::imported::namespace::*; // WRONG! import my::Type; // WRONG!

### Extension Import Statement

You can import another Xtend file using the extension statement. The syntax is:

    extension fully::qualified::ExtensionFileName;

Note, that no file extension (`*.ext`) is specified.

#### Reexporting Extensions

If you want to export extensions from another extension file together with your local extensions, you can add the keyword `reexport` to the end of the respective extension import statement.

    extension fully::qualified::ExtensionFileName reexport;

### Extensions

The syntax of a simple expression extension is as follows:

    ReturnType extensionName(ParamType1 paramName1, ParamType2...): expression-using-params;

Example:

    String getterName(NamedElement ele) : 'get'+ele.name.firstUpper();

#### Extension Invocation

There are two different ways of how to invoke an extension. It can be invoked like a function:

    getterName(myNamedElement)

The other way to invoke an extension is through the "member syntax":

    myNamedElement.getterName()

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.

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.

The expression evaluation engine first looks for an appropriate operation before looking for an extension, in other words operations have higher precedence.

#### Type Inference

For most extensions, you do not need to specify the return type, 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.

For instance, if you have the following extension

    asList(Object o): {o};

the invocation of

    asList('text')

has the static type `List[String]`. This means you can call

    asList('text').get(0).toUpperCase()

The expression is statically type safe, because its return type is derived automatically.

There is always a return value, whether you specify it or not, even if you specify explicitly '`Void`'.

See the following example.

    modelTarget.ownedElements.addAllNotNull(modelSource.contents.duplicate())

In this example `duplicate()` dispatches polymorphically. Two of the extensions might look like:

    Void duplicate(Realization realization):
       realization.Specifier().duplicate()->
       realization.Realizer().duplicate()
    ;

    create target::Class duplicate(source::Class):
       ...
    ;

If a '`Realization`' is contained in the '`contents`' list of '`modelSource`', the '`Realizer`' of the '`Realization`' will be added to the '`ownedElements`' list of the '`modelTarget`'. If you do not want to add in the case that the contained element is a 'Realization' you might change the extension to:

    Void duplicate(Realization realization):
       realization.Specifier().duplicate()->
       realization.Realizer().duplicate() ->
       {}
    ;

#### Recursion

There is only one exception: For recursive extensions the return type cannot be inferred, therefore you need to specify it explicitly:

    String fullyQualifiedName(NamedElement n) : n.parent == null ? n.name :
       fullyQualifiedName(n.parent)+'::'+n.name
    ;

Recursive extensions are non-deterministic in a static context, therefore, it is necessary to specify a return type.

#### Cached Extensions

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 '`cached`' to the extension in order to achieve this:

    cached String getterName(NamedElement ele) :
       'get'+ele.name.firstUpper()
    ;

The `getterName` will be computed only once for each `NamedElement`.

#### Private Extensions

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 '`private`' in front of them:

    private internalHelper(NamedElement ele) :
       // implementation....
    ;

### Java Extensions

In some cases one does want to call a Java method from inside an expression. This can be done by providing a Java extension :

    Void myJavaExtension(String param) :
       JAVA my.Type.someMethod(java.lang.String)
    ;

The signature is the same as for any other extension. Its syntax is:

    JAVA fully.qualified.Type.someMethod(my.ParamType1,
                                           my.ParamType2,
                                           ...)
    ;

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.

Example:

If you have defined the following Java extension:

    String concat (String a, String b):
      JAVA my.Helper.concat(java.lang.String, java.lang.String);

and you have the following Java class:

    package my;

    public class Helper {
      public String concat(String a, String b){
        return a + b;
      }
    }

the expressions

    concat('Hello ',"world!")
    "Hello ".concat('world!')

both result are invoking the Java method `void concat(String a, String b).`

#### static vs non-static invocation

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.

#### IExecutionContextAware

It is possible with a Java Extension to gain access to the ExecutionContext, which enables to retrieve detailed runtime information on invocation. To use the current ExecutionContext in a Java extension the class must implement `org.eclipse.xtend.expression.IExecutionContextAware`

    public interface IExecutionContextAware {
      void setExecutionContext (ExecutionContext ctx);
    }

The invoked method must not be static.

### Create Extensions (Model Transformation)

The Xtend language supports additional support for model transformations. The concept is called create extension and it is explained a bit more comprehensive as usual.

Elements contained in a model are usually referenced multiple times. Consider the following model structure:

        P
       / \
      C1 C2
       \ /
        R

A package `P` contains two classes `C1` and `C2`. `C1` contains a reference `R` of type `C2` (`P` also references `C2`).

We could write the following extensions in order to transform an Ecore (EMF) model to our metamodel (Package, Class, Reference).

    Package toPackage(EPackage x) :
       let p = new Package :
          p.ownedMember.addAll(x.eClassifiers.toClass()) ->
          p;

    Class toClass(EClass x) :
       let c = new Class :
          c.attributes.addAll(x.eReferences.toReference()) ->
          c;

    Reference toReference(EReference x) :
       let r = new Reference :
          r.setType(x.eType.toClass()) ->
          r;

For an Ecore model with the above structure, the result would be:

        P
       / \
      C1 C2
      |
      R - C2

What happened? The `C2` class has been created 2 times (one time for the package containment and another time for the reference `R` that also refers to `C2`). We can solve the problem by adding the '`cached`' keyword to the second extension:

    cached toClass(EClass x) :
       let c = new Class :
          c.attributes.addAll(c.eAttributes.toAttribute()) ->
          c;

The process goes like this:

1. start create `P`

   1. start create `C1` (contained in `P`)

      1. start create `R` (contained in `C1`)

         1. start create `C2` (referenced from `R`)

         2. end (result `C2` is cached)

      2. end `R`

   2. end `C1`

   3. start get cached `C2` (contained in `P`)

2. end P

So this works very well. We will get the intended structure. But what about circular dependencies? For instance, `C2` could contain a `Reference` `R2` of type `C1` (bidirectional references):

The transformation would occur like this:

1. start create `P`

   1. start create `C1` (contained in `P`)

      1. start create `R` (contained in `C1`)

         1. start create `C2` (referenced from `R`)

            1. start create `R2` (contained in `C2`)

               1. start create `C1` (referenced from `R1`)... OOPS!

`C1` 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 `C1` was not returned so far, because it is still in construction.

The solution: create extensions!

The syntax is as follows:

    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());

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.

### Calling Extensions From Java

The previous section showed how to implement Extensions in Java. This section shows how to call Extensions from Java.

    // setup
    XtendFacade f = XtendFacade.create("my::path::MyExtensionFile");

    // use
    f.call("sayHello",new Object[]{"World"});

The called extension file looks like this:

    sayHello(String s) :
       "Hello " + s;

This example uses only features of the `BuiltinMetaModel`, in this case the "`+`" feature from the `StringTypeImpl`.

Here is another example, that uses the `JavaBeansMetaModel` strategy. This strategy provides as additional feature: the access to properties using the getter and setter methods.

For more information about type systems, see the Expressions reference documentation.

We have one JavaBean-like metamodel class:

    package mypackage;
    public class MyBeanMetaClass {
       private String myProp;
       public String getMyProp() { return myProp; }
       public void setMyProp(String s) { myProp = s;}
    }

in addition to the built-in metamodel type system, we register the `JavaMetaModel` with the `JavaBeansStrategy` for our facade. Now, we can use also this strategy in our extension:

    // 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}));

The called extension file looks like this:

    import mypackage;

    readMyProp(MyBeanMetaClass jb) :
       jb.myProp
    ;

### WorkflowComponent

With the additional support for model transformation, it makes sense to invoke Xtend within a workflow. A typical workflow configuration of the Xtend component looks like this:

    <component class="org.eclipse.xtend.XtendComponent">
       <metaModel class="org.eclipse.xtend.typesystem.emf.EmfMetaModel">
          <metaModelFile value="metamodel1.ecore"/>
       </metamodel>
       <metaModel class="org.eclipse.xtend.typesystem.type.emf.EmfMetaModel">
          <metaModelFile value="metamodel2.ecore"/>
       </metaModel>
       <invoke value="my::example::Trafo::transform(inputSlot)"/>
       <outputSlot value="transformedModel"/>
    </component>

Note that you can mix and use any kinds of metamodels (not only EMF metamodels).

### Aspect-Oriented Programming in Xtend

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 Xtend .

The following advice is weaved around every invocation of an extension whose name starts with 'my::generator::':

    around my::generator::*(*) :
      log('Invoking ' + ctx.name) -> ctx.proceed()
    ;

Around advices let you change behaviour in an non-invasive way (you do not need to touch the packaged extensions).

#### Join Point and Point Cut Syntax

Aspect orientaton is basically about weaving code into different points inside the call graph of a software module. Such points are called join points . In Xtend the join points are the extension invocations (Note that Xpand offers a similar feature, see the Xpand documentation).

One specifies 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 point cut.

    around [pointcut] :
       expression;

A point cut consists of a fully qualified name and a list of parameter declarations.

##### Extensions Name

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.

Some examples:

    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

### Warning

Be careful when using wildcards, because you will get an endless recursion, in case you weave an extension, which is called inside the advice.

##### Parameter Types

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.

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.

Some examples:

    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

##### Proceeding

Inside an advice, you might want to call the underlying definition. This can be done using the implicit variable `ctx`, which is of the type xtend::AdviceContext and provides an operation `proceed()` which invokes the underlying definition with the original parameters (Note that you might have changed any mutable object in the advice before).

If you want to control what parameters are to be passed to the definition, you can use the operation `proceed(List[Object] params)`. You should be aware, that in advices, no type checking is done.

Additionally, there are some inspection properties (like `name`, `paramTypes`, etc.) available.

#### Workflow configuration

To weave the defined advices into the different join points, you need to configure the `XtendComponent` with the qualified names of the Extension files containing the advices.

Example:

    <component class="org.eclipse.xtend.XtendComponent">
       <metaModel class="org.eclipse.xtend.typesystem.emf.EmfMetaModel">
          <metaModelFile value="metamodel1.ecore"/>
       </metamodel>
       <metaModel class="org.eclipse.xtend.typesystem.emf.EmfMetaModel">
          <metaModelFile value="metamodel2.ecore"/>
       </metaModel>

       <invoke value="my::example::Trafo::transform(inputSlot)"/>
          <outputSlot value="transformedModel"/>
       <advices value="my::Advices,my::Advices2"/>
    </component>

#### Model-to-Model transformation with Xtend

This example uses Eclipse EMF as the basis for model-to-model transformations. It builds on the emfExample documented elsewhere. Please read and install the emfExample first.

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.

#### Workflow

By now, you should know the role and structure of workflow files. Therefore, the interesting aspect of the workflow file below is the `XtendComponent` .

    <workflow>
       <property file="workflow.properties"/>
          ...
       <component class="org.eclipse.xtend.XtendComponent">
          <metaModel class="org.eclipse.xtend.typesystem.emf.EmfMetaModel">
             <metaModelPackage value="data.DataPackage"/>
          </metaModel>
          <invoke value="test::Trafo::duplicate(rootElement)"/>
          <outputSlot value="newModel"/>
       </component>
       ...
    </workflow>

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 `data.DataPackage` as the metamodel.

We then specify which function to invoke for the transformation. The statement `test::Trafo::duplicate(rootElement)` means to invoke:

- the `duplicate` function taking the contents of the `rootElement` slot as a parameter

- the function can be found in the `Trafo.ext` file

- and that in turn is in the classpath, in the testpackage.

#### The transformation

The transformation, as mentioned above, can be found in the `Trafo.ext` file in the `test` package in the `src` folder. Let us walk through the file.

So, first we import the metamodel.

    import data;

The next function is a so-called create extension . Create extensions, as a side effect when called, create an instance of the type given after the `create` keyword. In our case, the `duplicate` function creates an instance of `DataModel`. This newly created object can be referred to in the transformation by `this` (which is why `this` is specified behind the type). Since `this` can be omitted, we do not have to mention it explicitly in the transformation.

The function also takes an instance of `DataModel` as its only parameter. That object is referred to in the transformation as `s`. So, this function sets the name of the newly created `DataModel` 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 `duplicate()` operation is called for each `Entity`. This is the next function in the transformation.

    create DataModel this duplicate(DataModel s):
       entity.addAll(s.entity.duplicate()) ->
       setName(s.name);

The duplication function for entities is also a create extension. This time, it creates a new `Entity` for each old `Entity` passed in. Again, it copies the name and adds duplicates of the attributes and references to the new one.

    create Entity this duplicate(Entity old):
       attribute.addAll(old.attribute.duplicate()) ->
       reference.addAll(old.reference.duplicate()) ->
       setName(old.name);

The function that copies the attribute is rather straight forward, but ...

    create Attribute this duplicate(Attribute old):
       setName(old.name) ->
       setType(old.type);

... the one for the references is more interesting. Note that a reference, while being owned by some `Entity`, also references another Entity as its target. So, how do you make sure you do not duplicate the target twice? Xtend provides explicit support for this kind of situation. Create extensions are only executed once per tuple of parameters! So if, for example, the Entity behind the target reference had already been duplicated by calling the `duplicate` function with the respective parameter, the next time it will be called the exact same object will be returned . This is very useful for graph transformations.

    create EntityReference this duplicate(EntityReference old):
       setName( old.name ) ->
       setTarget( old.target.duplicate() );

For more information about the Xtend language please see the Xtend reference documentation.