Skip to content

Cartridge validation and diagnostics

Cartridge validation checks contracts that only a Facility's output path can know. JoinedWorkz invokes it after model transformation and preparation, but before any Cartridge writes output for that model.

Extension contract

This page is for Facility and Cartridge developers. Application developers normally consume the diagnostics defined by a Facility.

1. Implement the validation hook

AbstractCartridge provides this hook:

java
public void validate(
        CmnModel model,
        ValidationIssueAcceptor issueAcceptor)

Keep the entry point small and delegate replaceable checks to injected helpers or protected methods:

java
@Override
public void validate(
        CmnModel model,
        ValidationIssueAcceptor issueAcceptor) {
    for (CmnObject modelElement : model.getModelElements()) {
        validateModelElement(modelElement, issueAcceptor);
    }
}

protected void validateModelElement(
        CmnObject modelElement,
        ValidationIssueAcceptor issueAcceptor) {
    // Validate only contracts owned by the current model.
}

Use dependency injection for specialized validators and helpers. Do not construct fallback implementations inside a Cartridge. Keep extension points replaceable so a specialized Facility can override behavior without changing the generic pipeline. Keep Facility classes and methods non-final, use protected rather than private extension helpers, and avoid static methods.

2. Validate only the supplied model

The central invariant is:

validate(model, issueAcceptor) validates the supplied CmnModel and the elements it owns—never imported models or unrelated cross-resource targets.

Do not follow CMN imports, referenced types, widgets or other cross-resource links to validate the referenced model. JoinedWorkz processes imported models as separate transformation, preparation, validation and Cartridge units and supplies the additional active Cartridges when required.

An owned containment hierarchy can be traversed when the rule applies to its children. A reference to an element in another model does not transfer validation ownership.

This convention prevents duplicate work during interactive Studio generation and ensures that diagnostics can be mapped to the correct source model.

3. Report expected model problems

Use ValidationIssueAcceptor for an expected violation of the Facility contract:

java
issueAcceptor.acceptError(
        modelElement,
        "textReport.invalidElement",
        "The element is not supported by TextReportCartridge.");

The first argument must be the transformed Core object in the current model that violates the rule. Use:

  • a stable, Facility-specific diagnostic code;
  • an actionable message that names the invalid value or missing requirement;
  • acceptError, acceptWarning or acceptInfo according to the actual severity; and
  • a structural-feature overload when the diagnostic belongs to one particular feature or list item.

Where a transformation origin is available for that Core object, Studio can map it back to its CMN source in the workspace. A Facility must not resolve Eclipse resources, create markers or copy line and offset information itself.

Use exceptions for unexpected implementation or runtime failures, not as a substitute for an expected model-validation diagnostic.

4. Keep phases separate

Profile Strategies belong to the preceding model-transformation phase. They calculate Core Model properties before Cartridge preparation starts; they are not a replacement for prepare(...). See Profile Strategies and calculated properties for that separate lifecycle.

The relevant Cartridge lifecycle is:

  1. prepare(CmnObject) derives state needed by later phases;
  2. validate(CmnModel, ValidationIssueAcceptor) reports contract violations;
  3. apply(CmnObject, Outlets, Properties) generates output only after validation succeeds.

Do not repeat the same defensive validation in apply(...) or in each generator helper. Generation can rely on the validation phase having accepted the current model. This keeps Studio saves responsive and lets Studio report a model diagnostic instead of encountering a later generator exception.

Validation must not mutate the model to make generation succeed. Put required derived state in the preparation phase and keep diagnostic checks side-effect-free.

5. Leave marker ownership to the framework

The CMN pipeline publishes validation issues, and the Studio integration routes and replaces their markers. It distinguishes:

  • the generation owner that caused the validation run; and
  • the source model element that owns the problem.

Within a Studio project, this infrastructure is responsible for routing source-mapped issues, rerunning affected local owners and removing obsolete markers. Facility code supplies the correct current-model issue target and remains independent of Eclipse and Maven execution details.

See Imported model processing and diagnostics for the user-visible import behavior.

6. Test the contract

Focused Cartridge tests should prove at least:

  • a valid current model reports no issue;
  • each invalid contract reports the expected severity, stable code and current-model target;
  • the check does not traverse imported models;
  • an error prevents apply(...) for that model; and
  • generation does not repeat the validation after it succeeds.

Test imported models as separate validation invocations. Pipeline-level tests, not Facility-specific traversal, should cover ordering, cyclic imports and the aborted output of a dependent importer.