Skip to main content

How do I transmute extended or generalized elements?

The standard CompositeBuilder.merge() pattern works directly against an ElementClass's own attributes and references. It doesn't know about elements attached through a Model Extension or a subclass of an abstract superclass . Those relationships aren't visible to a builder generated from the parent's own metamodel. Two situations need a different approach.

Transmuting into a Model Extension​

If the target metamodel is extendable, like elements::Component, you can attach your own elements as children, but the composite builder for Component has no knowledge of your metamodel, since the component doesn't (and shouldn't) know about extensions defined elsewhere. To transmute into an extension, the metamodel providing the extension needs to supply an adapter for the builder.

For example, the Workflow metamodel extends Component and provides a WorkflowCompositeExtensionAdapter, which lets a transmuter merge changes into workflow elementsFlow Element (FlowElement). [Deprecated ] A deprecated process modeling construct describing state transitions targeting a status field on a DataElement. through the normal ComponentCompositeBuilder:

ComponentCompositeBuilder.merge(flowElement.getComponent(), context, component -> {
component.extensions(new WorkflowCompositeExtensionAdapter(), workflow -> {
workflow.name("ExampleFlow");
});
});

If you're defining your own Model Extension, provide a matching CompositeExtensionAdapter alongside it so other transmuters (including your own) can merge into it the same way.

Transmuting a subclass of an abstract element​

The same problem shows up with generalization: a reference may target an abstract superclass, with the concrete subclass defined in another metamodel — so the builder generated for the superclass has no knowledge of that subclass either.

For example, SimpleValueType has a reference to the abstract ValueTypeRestriction element. Since ValueTypeRestriction isn't sealed, other metamodels can add their own subtypes, such as a DateInMonth restriction that only accepts dates in a given month. As with extensions, the metamodel providing the subclass supplies an adapter (here, DateInMonthCompositeAdapter) so transmuters can safely merge instances of it onto the superclass reference:

SimpleValueTypeCompositeBuilder.merge(simpleValueType, context, valueType -> {
valueType.restrictions(new DateInMonthCompositeAdapter(), dateInMonth -> {
dateInMonth.month("april");
});
});