Transmuters
Transmuters can modify the model in a structural way. They are a great tool for keeping models up-to-date or to add a complex feature.
Transmuters can be executed from the µRadiant or from command line.
Adding new Transmuters
To add a new Transmuter, create a class that implements ModelTransmuter
and add @Transmutation
:
@Transmutation(
element = "elements::DataElement",
description = "Some description of what the transmuter will change."
)
public class AddSomething implements ModelTransmuter<DataElementComposite> {
@Override
public void transmute(DataElementComposite dataElement, ModelTransmutationContext context) {
// Implement transmutation
}
}
Composite Builder Classes
To help with the implementation of the transmuters, you can make use of the CompositeBuilder
classes.
These classes provide an API to merge new changes into existing models.
Use the merge()
method to update an element.
DataElementCompositeBuilder.merge(dataElement, context, de -> {
// Set the packageName to a new value
de.packageName("net.demo.new.package");
// Create a field named `foo` or update it if it already exists
de.fields(field -> {
field.name("foo");
field.isInfoField(true);
field.valueField(vf -> {
vf.valueFieldType("::String");
});
});
});
You can also merge with a Component to create new DataElements etc.
ComponentCompositeBuilder.merge(dataElement.getComponent(), context, component -> {
component.dataElements(newDataElement -> {
newDataElement.name(dataElement.getName() + "History");
});
});
Writing tests
You can use the TransmuterTester
class to test transmutations.
public class AddSomethingTest {
private final ModelSpecBuilder specBuilder = new ModelSpecBuilder();
// If the test is named after the tested class, the TransmuterTester will find it automatically
private final TransmuterTester tester = TransmuterTester.forTest(this);
@Test
void testTransmute() {
// Create a model to test
DataElementComposite model = specBuilder.buildAndFind(
component("testComp",
dataElement("City")),
dataElement("testComp::CityUpdate"));
tester.testTransmute(model, de -> {
// Assert that the model has been updated
assertThat(de.getComponent().getDataElements(), hasItem(
isElement(dataElement("testComp::CityHistory"))
));
});
}
}
The specBuilder field has been made public to allow the TransmuterTester to configure itself. It is also possible to pass the context object to the tester instead.
private final ModelSpecBuilder specBuilder = new ModelSpecBuilder();
private final TransmuterTester tester = TransmuterTester.forTest(this, specBuilder.getContext());
Creating a new transmutation project
To create a new transmutation resource project you will need to create a maven project.
Add the following dependencies to the project:
<dependencies>
<!-- Provides annotations and interfaces for the transmuters -->
<dependency>
<groupId>net.democritus.model</groupId>
<artifactId>modelTransmutations-core</artifactId>
<version>2.5.0</version>
</dependency>
<!-- Provides CompositeBuilder classes for elements -->
<dependency>
<groupId>net.democritus.model</groupId>
<artifactId>prime-builders</artifactId>
<version>2.5.0</version>
</dependency>
<!-- Provides tester class -->
<dependency>
<groupId>net.democritus.model</groupId>
<artifactId>modelTransmutations-test-support</artifactId>
<version>2.5.0</version>
<scope>test</scope>
</dependency>
</dependencies>
If not present yet, add the expansionResource
goal to the <plugins>
section in your pom.xml.
Also make sure it has the includeClassPathDependencies
flag enabled.
<plugins>
<plugin>
<groupId>net.democritus.maven.plugins</groupId>
<artifactId>expanders-maven-plugin</artifactId>
<version>${expanders-maven-plugin.version}</version>
<executions>
<execution>
<goals>
<goal>expansionResource</goal>
</goals>
<configuration>
<includeClassPathDependencies>true</includeClassPathDependencies>
</configuration>
</execution>
</executions>
</plugin>
...
</plugins>
This flag directs the expansionResource manifest generator to include a list of all compile project dependencies.
This way, the expanders will fetch these dependencies when expanding.
Without this, the prime-builders
jar might not be present or might be the wrong version.