Skip to main content

Validation Rules

An expansion-resource can define Validation Rules to validate models.

Validation Rules are integrated into the Radiant. You can also generate reports on command line

Adding new Rules

To add a new rule, create a class that implements ValidatableRule and add @ValidationRule and @ValidationGroup:

@ValidationRule(
element = "elements::Application",
severity = ValidationSeverity.ERROR,
reason = "Short explanation",
description = "More detailed description"
)
@ValidationGroup("My Rules")
public class MyNewRule implements ValidatableRule<ApplicationComposite> {

@Override
public void validate(ApplicationComposite application, Critiques critiques) {
// implement validation
}

}

The target element can be any element. Just make sure that generic type of the interface matches the Composite of that element.

Conditional Rules

If a rule only applies to a subset of element, you can make it conditional. Conditional Rules need to implement the ConditionalRule interface:

@ValidationRule(
element = "elements::Application",
severity = ValidationSeverity.WARNING,
reason = "Short explanation",
description = "More detailed description"
)
@ValidationGroup("Missing Defaults")
public class MyNewRule implements ValidatableRule<ApplicationComposite>, ConditionalRule<ApplicationComposite> {

@Override
public boolean guard(ApplicationComposite application) {
// implement check when the rule is applicable
}

@Override
public void validate(ApplicationComposite application, Critiques critiques) {
// implement validation
}

}

Formatting critiques

To provide the user with clear critiques, you can use formatting to include variables into the message.

  ...
@Override
public void validate(ApplicationComposite app, Critiques critiques) {
// both {element} and {<elementName>} can be used to substitue a reference
critiques.add(app, "{element} has an issue");
critiques.add(app, "{application} has an issue");

// additional arguments can be referenced through {<index>}, starting at 1
critiques.add(app, "{element} did not contain {1}", "components");

// or they can be passed as a Map and referenced by {<key>}
Map<String,Object> arguments = Map.of("missing", "components");
critiques.add(app, "{element} did not contain {missing}", arguments);
}
...

Writing tests

To test your validation rules, there is a ValidationRuleTester class.

class MyNewRuleTest {

private final TestModelBuilder modelBuilder = new TestModelBuilder();
private final ValidationRuleTester<ApplicationComposite> tester = new ValidationRuleTester<>(this);

// Create model test rule
private ApplicationComposite baseModel() {
ApplicationSpec spec = application("testApp");
return modelBuilder.build(spec);
}

@Test
public void testPassing() {
tester.testPassing(baseModel());
}

@Test
public void testFailing() {
ApplicationComposite model = baseModel();
// Do some changes
tester.testFailing(model, "expected errors");
}

@Test
public void testGuard() {
tester.testGuard(baseModel());
}

@Test
public void testFailGuard() {
ApplicationComposite model = baseModel();
// Do some changes
tester.testFailGuard(model);
}
}

Creating a new validation project

To create a new validation resource project you will need to create a maven project.

Add the following dependencies to the project:

<dependencies>
<!-- Provides metamodel classes, like ApplicationComposite -->
<dependency>
<groupId>net.democritus.metamodel</groupId>
<artifactId>prime-core</artifactId>
<version>2024.8.0</version>
</dependency>
<!-- Provides annotations and interfaces for the validation rules -->
<dependency>
<groupId>net.democritus.validations.model</groupId>
<artifactId>validations-core</artifactId>
<version>3.7.0</version>
</dependency>

<!-- Provides tester class -->
<dependency>
<groupId>net.democritus.validations.model</groupId>
<artifactId>validations-test-support</artifactId>
<version>3.7.0</version>
<scope>test</scope>
</dependency>
</dependencies>

Then, add the expansionResource goal (if not already present):

<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>
</execution>
</executions>
</plugin>
...
</plugins>