# Type System TypeData type TypeParameterized type

## Type System

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.

The Java API described here is located in the org.eclipse.xpand.type package and is a part of the subproject core.expressions.

### Types

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

#### Type Names

Types have a simple name (e.g. `String`) and an optional namespace used to distingish between two types with the same name (e.g. `my::metamodel`). The delimiter for name space fragments is a double colon "`::`". A fully qualified name looks like this:

    my::fully::qualified::MetaType

The namespace and name used by a specific type is defined by the corresponding `MetaModel` implementation. The `EmfMetaModel` , for instance, maps `EPackages` to namespace and `EClassifiers` to names. Therefore, the name of the Ecore element `EClassifier` is called:

    ecore::EClassifier

If you do not want to use namespaces (for whatever reason), you can always implement your own metamodel and map the names accordingly.

#### Collection Type Names

The built-in type system also contains the following collection types: `Collection`, `List` and `Set`. Because the expressions language is statically type checked and we do not like casts and `ClassCastExceptions`, we introduced the concept of parameterized types . The type system does not support full featured generics, because we do not need them.

The syntax is:

    Collection[my::Type]
    List[my::Type]
    Set[my::Type]

#### Features

Each type offers features. The type (resp. the metamodel) is responsible for mapping the features. There are three different kinds of features:

- Properties

- Operations

- Static properties

Properties 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 Operations . But in contrast to properties, they can have parameters. Static properties are the equivalent to enums or constants. They must be invoked statically and they do not have parameters.

### Built-In Types

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 API documentation.

#### `Object`

`Object` defines a couple of basic operations, like `equals()`. The property metaType provides access to Xpand's type for that Object. Every type has to extend `Object`.

#### `Void`

The `Void` 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 `null`. Sometimes it might be useful to use `Void` 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 `null`.

#### Simple types (Data types)

The type system doesn't have a concept data type. Data types are just types. As in OCL, we support the following types: `String`, `Boolean`, `Integer`, `Real`.

- `String` : A rich and convenient `String` library is especially important for code generation. The type system supports the '+' operator for concatenation, the usual `java.lang.String` operations (`length()`, etc.) and some special operations (like `toFirstUpper()`, `toFirstLower()`, regular expressions, etc. often needed in code generation templates).

- `Boolean` : `Boolean` offers the usual operators (Java syntax): &&, ||, !, etc.

- `Integer` and `Real` : `Integer` and `Real` offer the usual compare operators (<,>,<=,>=) and simple arithmetics (+,-,*,/). Note that `Integer` extends `Real`!

#### Collection types

The type system has three different Collection types. `Collection` is the base type, it provides several operations known from `java.util.Collection`. The other two types (`List` , `Set` ) correspond to their java.util equivalents, too.

#### Type system types

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 `Operation`, for instance) we have prefixed all of the types with the namespace `xpand2`. We have:

- `xpand2::Type`

- `xpand2::Feature`

- `xpand2::Property`

- `xpand2::StaticProperty`

- `xpand2::Operation`

You should be aware that if you name a type by name in an expression the object you get is in fact an `xpand2::Type`. A common use case is to prove that an object is of some type or its subtype, using the `instanceOf()` operation or exactly of one type.

    // 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

Note that this should be only used when really required. The recommended way to handle alternative implementations for a type hierarchy is using Multiple Dispatch.

### Metamodel Implementations (also known as Meta-Metamodels)

By default, the type system only knows the built-in types. In order to register your own metatypes (e.g. `Entity` or `State`), you need to register a respective metamodel implementation with the type system. Within a metamodel implementation the Xpand type system elements (`Type`, `Property`, `Operation)` are mapped to an arbitrary other type system (e.g. Java reflections, Ecore or XML Schema).

#### Example JavaMetaModel

For instance, if you want to have the following JavaBean act as a metatype (i.e. your model contains instances of the type):

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

You need to use the `JavaMetaModel` implementation which uses the ordinary Java reflection layer in order to map access to the model.

So, if you have the following expression in e.g. Xpand :

    myattr.name.toFirstUpper()

and `myattr` is the name of a local variable pointing to an instance of `Attribute`. The Xpand type system asks the metamodel implementations, if they 'know' a type for the instance of Attribute. If you have the `JavaMetaModel` registered it will return an `xpand2::Type` which maps to the underlying Java class. When the type is asked if it knows a property '`name`', it will inspect the Java class using the Java reflection API.

The JavaMetaModel implementation shipped with Xpand can be configured with a strategy [GOF95-Pattern] in order to control or change the mapping. For instance, the `JavaBeansStrategy` maps getter and setter methods to simple properties, so we would use this strategy for the example above.

#### Eclipse IDE MetaModelContributors

You should know that for each `Metamodel` implementation you use at runtime, you need to have a so called `MetamodelContributor` 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 Xpand is shipped with respective MetamodelContributors (see the corresponding docs for details). If you need to implement your own `MetamodelContributor` you should have a look at the Eclipse plug-in reference doc.

#### Configuring Metamodel implementations with the workflow

You need to configure your Xpand language components with the respective metamodel implementations.

A possible configuration of the `Xpand2` generator component looks like this:

    <component class="org.eclipse.xpand2.Generator">
       <metaModel class="org.eclipse.type.emf.EmfMetaModel">
          <metaModelPackage value="my.generated.MetaModel1Package"/>
       </metaModel>
       <metaModel class="org.eclipse.type.emf.EmfMetaModel">
          <metaModelFile value="my/java/package/metamodel2.ecore"/>
       </metaModel>
       ...
    </component>

In this example the `EmfMetaModel` implementation is configured two times. This means that we want to use two metamodels at the same time, both based on EMF. The metaModelPackage property is a property that is specific to the `EmfMetaModel` (located in the `org.eclipse.xtend.typesystem.emf` plugin). It points to the generated `EPackages` interface. The second meta model is configured using the Ecore file. You do no need to have a generated Ecore model for Xpand in order to work. The `EmfMetaModel` works with dynamic EMF models just as it works with generated EMF models.

Note that is recommended to prefer the `EmfRegistryMetaModel` instead of the `EmfMetaModel`, although `EmfMetaModel` is derived from the `EmfRegistryMetaModel`. Further it is recommended to use platform URIs (see API Doc URI) to refer to EMF resources.

The use of platform URIs in the workflow requires setting up EMF for standalone execution with the `StandaloneSetup` class from the `org.eclipse.emf.mwe.utils` plugin. Further, StandaloneSetup is used to register known EMF packages. An equivalent workflow configuration for the sample above would look like this:

    <bean class="org.eclipse.emf.mwe.utils.StandaloneSetup">
      <platformUri value=".."/>
      <registerGeneratedEPackage value="my.generated.MetaModel1Package"/>
      <registerEcoreFile value="platform:/resource/my/java/package/metamodel2.ecore"/>
    </bean>
    ...
    <component class="org.eclipse.xpand2.Generator">
       <metaModel class="org.eclipse.type.emf.EmfRegistryMetaModel"/>
       ...
    </component>

The `StandaloneSetup` 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.

Metamodel instances are often shared between different components that make use of expressions (most notably the Xpand `Generator`, `XtendComponent` and `CheckComponent`). Normally you don't want that a Metamodel instance configured and instantiated for each workflow component. MWE lets you instantiate a class using the `<bean>` 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:

    <bean class="org.eclipse.emf.mwe.utils.StandaloneSetup">
      <platformUri value=".."/>
      <registerGeneratedEPackage value="my.generated.MetaModel1Package"/>
      <registerEcoreFile value="platform:/resource/my/java/package/metamodel2.ecore"/>
    </bean>
    <bean id="mm_emf" class="org.eclipse.type.emf.EmfRegistryMetaModel"/>
    ...
    <component class="org.eclipse.xpand2.Generator">
       <metaModel idRef="mm_emf"/>
       ...
    </component>

### Using different Metamodel implementations (also known as Meta-Metamodels)

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 Xpand template. You just need to configure the respective MetaModel implementations.

If you want to do so you need to know how the type lookup works. Let us assume that we have an EMF metamodel and a model based on some Java classes. Then the following would be a possible configuration:

    <component class="org.eclipse.xpand2.Generator">
       <metaModel class="org.eclipse.internal.xtend.type.impl.java.JavaMetaModel"/>
       <metaModel class="org.eclipse.xtend.typesystem.emf.EmfRegistryMetaModel">
          <metaModelFile value="my/java/package/metamodel.ecore"/>
       </metaModel>

       ...
    </component>

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 `org.eclipse.emf.ecore.EObject` and it is a dynamic instance of an EMF EClass `MyType`.

We have three Metamodels:

1. Built-Ins (always the first one)

2. JavaMetaModel

3. EMFMetaModel - metamodel.ecore

The first one will return the type `Object` (not `java.lang.Object` but `Object` of Xpand !). At this point the type `Object` best fits the request, so it will act as the desired type.

The second metamodel returns a type called `org::eclipse::emf::ecore::EObject` The type system will check if the returned type is a specialization of the current 'best-fit' type (`Object`). It is, because it extends `Object` (Every metatype has to extend `Object`). At this time the type system assumes `org::eclipse::emf::ecore::EObject` to be the desired type.

The third metamodel will return `metamodel::MyType` which is the desired type. But unfortunately it doesn't extend `org::eclipse::emf::ecore::EObject` as it has nothing to do with those Java types. Instead it extends `emf::EObject` which extends `Object`.

We need to swap the configuration of the two metamodels to get the desired type.

    <component class="org.eclipse.xpand2.Generator">
       <metaModel class="org.eclipse.xtend.typesystem.emf.EmfMetaModel">
          <metaModelFile value="my/java/package/metamodel.ecore"/>
       </metaModel>
       <metaModel class="org.eclipse.internal.xtend.type.impl.java.JavaMetaModel"/>

       ...
    </component>

The order of the metamodels is important for the work within the Xpand-editors. The metamodels to work with can be configured inside the Xtend/Xpand -properties dialog. The Activated metamodel contributors table is a ordered list. The more specific metamodels have to be placed at the top of the list.

### Metamodel Reference

In the following, each of the built-in metamodels that come with Xpand will be documented. Furthermore, there will be some guidelines on how to implement your own metamodel.

#### EMF Metamodels

This section will describe the metamodels that can be used for EMF models. Please note that you have to execute one of the setup utility classes, `Setup` or `StandaloneSetup`, in your workflow before you can use one of the EMF metamodels.

##### The EMF Registry Metamodel (org.eclipse.xtend.typesystem.emf.EmfRegistryMetaModel)

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.

This metamodel provides the following configuration property:

Table 1. Properties of `EmfRegistryMetaModel`

Name of property | Description
--- | ---
`useSingleGlobalResourceSet` | This boolean property determines the way resource sets are used. If set to true , all model resources will be stored in a single global resource set. Otherwise, a separate resource set will be used for each model resource.

##### The EMF Metamodel (org.eclipse.xtend.typesystem.emf.EmfMetaModel)

This metamodel is a specialized version of the EMF registry 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.

This metamodel provides the following configuration properties:

Table 2. Properties of `EmfMetaModel`

Name of property | Description
--- | ---
`useSingleGlobalResourceSet` | This boolean property determines the way resource sets are used. If set to true , all model resources will be stored in a single global resource set. Otherwise, a separate resource set will be used for each model resource.
`metaModelFile` | Sets the path to the Ecore file that will be added to the metamodel.
`metaModelDescriptor` | Adds a model to the metamodel by specifying the name of an EPackage descriptor class.
`metaModelPackage` | Adds a model to the metamodel by specifying the name of an EPackage.

#### UML Metamodels

Xpand also provides several metamodels that allow to use UML models in conjunction with this model-to-text generation framework. Please note that you have to execute the setup utility class `Setup` in your workflow before you can use one of the UML metamodels

##### The UML2 Metamodel (org.eclipse.xtend.typesystem.uml2.UML2MetaModel)

This metamodel is a specialized version of the EMF metamodel . It provides access to UML2 models, and it has the following configuration properties:

Table 3. Properties of `UML2MetaModel`

Name of property | Description
--- | ---
`useSingleGlobalResourceSet` | This boolean property determines the way resource sets are used. If set to true , all model resources will be stored in a single global resource set. Otherwise, a separate resource set will be used for each model resource.
`modelFile` | Sets the path to the UML2 model file that will be added to the metamodel.

This implementation will be rarely used, since usually profiled UML models will be used and therefore the Profile Metamodel is.

##### The UML2 Profile Metamodel (org.eclipse.xtend.typesystem.uml2.profile.ProfileMetaModel)

This metamodel allows to apply UML profiles to UML2 models, and extends the UML2 Metamodel. It has the following configuration properties:

Table 4. Properties of `ProfileMetaModel`

Name of property | Description
--- | ---
`useSingleGlobalResourceSet` | This boolean property determines the way resource sets are used. If set to true , all model resources will be stored in a single global resource set. Otherwise, a separate resource set will be used for each model resource.
`modelFile` | Sets the path to the UML2 model file that will be added to the metamodel. Use resource URIs for the values.
`profile` | 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.

##### The XMI reader (org.eclipse.xtend.typesystem.uml2.profile.ProfilingExtensions.XmiReader)

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.

The `XMIReader` component provides the following configurable properties:

Table 5. Properties of `XMIReader`

Name of property | Description
--- | ---
metaModelFile | Sets the path to the Ecore file that will be added to the metamodel.
metaModelDescriptor | Adds a model to the metamodel by specifying the name of an EPackage descriptor class.
metaModelPackage | Adds a model to the metamodel by specifying the name of an EPackage.
outputSlot | Sets the name of the model slot where the read model will be stored in.
firstElementOnly | This boolean property determines if only the first model element of the XMI file will be used. If set to true , 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.

#### The Java Metamodel (org.eclipse.internal.xtend.type.impl.java.JavaMetaModel)

The Java metamodel allows normal Java classes as metatypes for your metamodel. The `JavaMetaClass` uses the strategy pattern to define how the elements are exactly mapped to the metamodel elements. There is a class called `org.eclipse.internal.xtend.type.impl.java.JavaBeansMetaModel` that is preconfigured with a strategy that maps simple Java beans onto the metamodel elements.

The Java metamodel has no configurable properties.

#### The XSD Metamodel (org.eclipse.xtend.typesystem.xsd.XSDMetaModel)

The XSD metamodel provides access to models implemented in the XML Schema Definition language. It has the following configuration properties:

Table 6. Properties of `XSDMetaModel`

Name of property | Description
--- | ---
`id` | Sets the ID of the current model.
`registerPackagesGlobally` | This boolean property determines if the model packages will be registered globally. If set to true , the model packages will be registered in the global registry. Otherwise, packages will not be registered.
`savePackagesPath` | Sets the path where model packages will be saved (in XMI format).

#### Implementing Your Own Metamodel

The Xpand 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:

1. Create a class that implements the `MetaModel` interface.

2. 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 `MetaModelContributor` or the `MetaModelContributor2` interface.

3. Finally, you have to extend the `org.eclipse.xtend.shared.ui.metaModelContributors` extension point in order to register your metamodel contributor with the Eclipse UI.