Skip to main content

Creating mapping file

The mapping file can contain a number of different mappings. This guide will show some mapping examples, to help you get started.

Expressions in mapping files are written in OGNL.

For a more extensive explanation on expanderExpanderA unit of generation that combines a data tree instance (functional M1 model) with a template to generate an artifact. mapping, check the reference guide: Expander Mapping

Value​

<value name="component" eval="dataElement.component.name"/>

ConditionalValue​

In this example, the value fileName can be overwritten by defining the option 'demo.filename'.

<conditionalValue name="fileName">
<option if="dataElement.getOption('demo.fileName').defined" eval="dataElement.getOption('demo.fileName').value"/>
<defaultOption eval="dataElement.name"/>
</conditionalValue>

Group​

E.g. in this example the values in the group can be accessed in the template as <targetElement.packageName> and <targetElement.name>:

<group name="targetElement" if="field.linkField neq null">
<value name="name" eval="field.linkField.targetElement.name"/>
<value name="packageName" eval="field.linkField.targetElement.packageName"/>
</group>

List​

<!--
Get a list containing the names of the Fields in a DataElement.
-->
<list name="fields">
<foreach name="field" in="dataElement.fields"/>
<value name="name" eval="field.name"/>
</list>
Chaining For-Each

A list mapping can contain multiple <foreach> mappings. The iterations will be nested, but the end result will be a single flat list.

<!--
Obtain every field in a component.
-->
<list name="fields">
<foreach name="dataElement" in="component.dataElements"/>
<foreach name="field" in="dataElement.fields"/>
<value name="dataElementName" eval="dataElement.name"/>
<value name="name" eval="field.name"/>
</list>

Filtering List​

<list name="fields">
<foreach name="field" in="dataElement.fields"/>
<!-- Only take fields where the valueField is defined. -->
<filter name="isValueField" eval="field.valueField neq null"/>
<value name="name" eval="field.name"/>
</list>

Duplicates can be removed by using <distinct>.

<list name="fieldTypes">
<foreach name="field" in="dataElement.fields"/>
<filter name="isValueField" eval="field.valueField neq null"/>
<!-- Remove all items that are duplicates based on the value presented in the eval. -->
<distinct name="distinctTypes" eval="field.valueField.type"/>
<value name="name" eval="field.valueField.type.name"/>
</list>

Sorting​

<list name="fields">
<foreach name="field" in="dataElement.fields"/>
<value name="name" eval="field.name"/>
<!-- Sort by field name -->
<sorted eval="field.name"/>
</list>

List Composition​

<list name="fields">
<!-- Always add an id field -->
<item>
<value name="name" eval="'id'"/>
</item>
<foreach name="field" in="dataElement.fields"/>
<value name="name" eval="field.name"/>
</list>

Use <items> to combine lists.

<!--
Create a separate mapping for LinkFields and ValueFields and then combine them.
-->
<list name="fields">
<items>
<foreach name="field" in="dataElement.fields"/>
<filter name="isValueField" eval="field.valueField neq null"/>
<value name="name" eval="field.name"/>
<value name="type" eval="field.valueField.javaType"/>
</items>
<items>
<foreach name="field" in="dataElement.fields"/>
<filter name="isLinkField" eval="field.linkField neq null"/>
<value name="name" eval="field.name"/>
<value name="type" eval="field.linkField.linkFieldType.dataType"/>
</items>
</list>

Assert​

You can check if the model is valid by using asserts:

<assert name="versionField_isValueFieldType" message="Option `isVersion` can only be used in combination with a valueFieldType"
eval="field.valueField neq null"/>

Include​

Lastly, the include mapping will include another mapping file and add it to the mapping.

<include path="SomeCommonMapping.xml"/>
<!-- or -->
<include path="/path/to/SomeCommonMapping.xml"/>

Extending the scope​

It is possible to define new variables in the mapping scope, which can be used in other mapping statements.

For this you can use a let statement:

The mapping

<value name="name" eval="field.linkField.targetElement.name"/>
<value name="packageName" eval="field.linkField.targetElement.packageName"/>

can be simplified to:

<let name="targetElement" eval="field.linkField.targetElement"/>
<value name="name" eval="targetElement.name"/>
<value name="packageName" eval="targetElement.packageName"/>

Let statements can also be used to instantiate helper classes:

<let name="nameConverter" eval="new net.democritus.naming.ElementNameConverter()"/>
<value name="nameDashed" eval="nameConverter.getDashed(dataElement.name)"/>
Scopes in list and group statements

In both list and group statements, the variables defined with let statements within the list or group mapping cannot be accessed from outside these mappings.