Skip to main content

Expanders-Core 8.1.1

· 2 min read
Koen De Cock
Koen De Cock
R&D Engineer

Changes and improvements

  • String interpolation
  • Strict mode to catch errors in mapping.xml
  • New list mapping syntax
  • Improved stack-traces
  • Support for extending the context of artifact paths, mapping files etc.

String interpolation

String interpolation support in OGNL expressions for compact String creation.

<value name="path" eval="format('${component.name}/${component.version}')"/>

Strict mapping

Mapping file can use 'strict' mapping, which fails when using a variable that is not bound.

<mapping xmlns="https://schemas.normalizedsystems.org/xsd/expanders/2025/0/0/mapping"
strict="true">
<!-- Fails because typo refers to a non-existing variable. -->
<let name="dataElements" eval="componnet.dataElements"/>
note

This feature is not enabled by default to avoid breaking existing expanders. But it is recommended to use it when writing Expanders.

New list mapping syntax

<list name="valueFields">
<!-- for-each element replaces attributes in the header -->
<foreach name="dataElement" in="component.dataElements"/>
<foreach name="field" in="dataElement.fields"/>
<value name="field" eval="field.name"/>
<!-- Sort item by a specific value -->
<sorted eval="field.name"/>
</list>

<list name="names">
<!-- Add a single item -->
<item>
<value name="name" eval="component.name"/>
</item>
<!-- Combine multiple lists -->
<items>
<foreach name="dataElement" in="component.dataElements"/>
<value name="name" eval="dataElement.name"/>
</items>
<items>
<foreach name="taskElement" in="component.taskElements"/>
<value name="name" eval="taskElement.name"/>
</items>
</list>

See more

Improved stack-traces

Stack-traces of errors in the Expanders have been reworked to be more legible and provide more information.

net.democritus.expansion.mapping.PropertyMappingException: Encountered error trying to resolve Value<field>
at expression 'fild.name'
at <value name="field"> .(builder-test-mapping-syntax-25.0.xml:14)
at <list name="valueFields"> .(builder-test-mapping-syntax-25.0.xml:8)
at <mapping> .(builder-test-mapping-syntax-25.0.xml:2)
Bound variables {
/* for-each field in dataElement.fields .(builder-test-mapping-syntax-25.0.xml:10) */
field, __item = FieldComposite{testComp::Country::countryCode}
/* for-each dataElement in dataElements .(builder-test-mapping-syntax-25.0.xml:9) */
dataElement, __item = DataElementComposite{testComp::Country}
/* let dataElements = component.dataElements .(builder-test-mapping-syntax-25.0.xml:4) */
dataElements = [DataElementComposite{testComp::City}, DataElementComposite{testComp::Country}]
component = ComponentComposite{testComp}
}

at net.democritus.expansion.mapping.ognl.Evaluate.getValue(Evaluate.java:37)
at net.democritus.expansion.mapping.ognl.Evaluate.getValue(Evaluate.java:43)
...

Adding Variables to the mapping context/

If the default variables exposed to the Expanders, like artifactSubFolders, don't do the trick, it is now possible to define additional variable bindings.

Expander Variables

note

This functionality is intended to be used conservatively.