Skip to content

Introduce rule applicability framework (validation profile + agenda filter) (TEDEFO-5035)#77

Merged
rousso merged 4 commits into
developfrom
feature/TEDEFO-5029-analyze-emd
Apr 29, 2026
Merged

Introduce rule applicability framework (validation profile + agenda filter) (TEDEFO-5035)#77
rousso merged 4 commits into
developfrom
feature/TEDEFO-5029-analyze-emd

Conversation

@rousso
Copy link
Copy Markdown
Contributor

@rousso rousso commented Apr 28, 2026

Second analyser-side step of TEDEFO-5029 (epic: run the SDK Analyzer against the live MDD), addressing TEDEFO-5035.

The analyser becomes aware of the context in which a validation run is happening (which SDK major version, what kind of source backs the content), and individual Drools rules can declare which contexts they apply to via DRL metadata annotations. Rules without annotations apply to every context — so existing rules continue to fire for every run with no DRL change required, and the file-backed CI gate stays exactly as it was.

New types and behaviour

  • SourceKind (enum: FILE, DATABASE).
  • ValidationProfile (immutable value: int sdkMajor, SourceKind sourceKind).
  • SdkContentSource gains SourceKind getSourceKind() (non-default by design — forces every implementation to be explicit).
  • SdkValidator.validate() builds a ValidationProfile lazily from the loaded SdkMetadata (major) and source.getSourceKind(), and threads it through to RulesRunner.execute(unit, profile, rules...).
  • A new ApplicabilityFilter reads @sdkMajor(...) and @source(...) metadata on each rule and AND's it against the active profile. A rule applies iff every annotated axis matches — annotation-absent on an axis means "any value on that axis."

Triage of obvious file-only rules

Four existing rules now carry @source(FILE): Document types use existing schemaLocation, Codelist indicated in codelists index exists, Codelist files are indicated in codelists index, and Codelist filenames are as expected. They fire under FILE and are skipped under DATABASE. Broader rule triage is intentionally deferred to a follow-up.

Defensive null guard on DocumentTypeFact.schemaLocationExists

The framework's premise that "FILE source = always has a path" doesn't hold if a custom source declares SourceKind.FILE without backing the content with a real path (e.g. an in-memory or archive-backed reader). The null guard is restored with a comment explaining why; a regression test (fileSourceWithDocumentTypeAndNoSdkRootDoesNotThrow) covers the case end-to-end.

Verification

  • mvn test: 176 tests green (148 Cucumber + 28 JUnit, 0 failures, 0 errors).
    • DroolsApplicabilityIntegrationTest (11 tests) compiles a small DRL through the real Drools engine and locks in the metadata-shape assumption underpinning ApplicabilityFilter — runtime guard against future Drools upgrades.
    • ApplicabilityFilterTest (7 tests) covers the four-corner profile matrix.
    • SdkValidatorProfileFilteringTest (3 tests) drives the full validate() pipeline: a @source(FILE) rule fires under FILE, is skipped under DATABASE, and a custom FILE source with a document type but no sdkRoot does not NPE.
  • Standalone analyser JAR vs Phase-0 baselines (after normalising timestamps, JVM object hashes, sort order):
    • SDK 1.14.2 (clean release): exit 0, 26 lines, 0 errors — byte-identical.
    • eForms-SDK efx-2 (in-progress): exit 1, 11478 lines, 5724 errors — byte-identical.
  • The file-backed CI gate is unchanged.

Intentional API breaks (no external Java consumers)

  • SdkContentSource adds a non-default method getSourceKind(). Per the design, every implementation must declare its kind explicitly. Both in-tree implementations (SdkLoader, EmptySdkContentSource test stub) declare FILE. Phase 3a's EmdSdkContentSource in mdm-cli will declare DATABASE.
  • RulesRunner.execute(unit, String...) becomes RulesRunner.execute(unit, ValidationProfile, String...). There is exactly one production call site (SdkValidator.fireRules).

The analyser has no known external Java consumers and a major version bump is on the horizon. mdm-cli (the only known internal consumer) doesn't implement SdkContentSource today and isn't affected by the break.

Test-mode caveat

When SdkValidator.fireRules(String...) is called without first calling validate(), the active profile is null and RulesRunner bypasses the applicability filter entirely. This preserves the behaviour of legacy step-by-step Cucumber tests in SdkValidationSteps. The bypass is documented on SdkValidator.fireRules and on the SdkValidator.profile field, and a WARN log line is emitted whenever it triggers — a non-test caller doing this would be loud.

Follow-ups (separate PRs)

  • TEDEFO-5032 (Phase 3a, mdm-cli-side): EmdSdkContentSource declaring SourceKind.DATABASE consumes this framework and naturally inherits clean rule selection.
  • Broader rule triage of remaining file-only / SDK-version-specific rules (e.g. SDK 1 vs SDK 2 @sdkMajor annotations).

@rousso rousso requested a review from rouschr April 28, 2026 20:54
Copy link
Copy Markdown
Contributor

@rouschr rouschr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are a lot of changes, I think I will understand this better on the side of the MDM analyse-emd

@rousso rousso merged commit 41c092c into develop Apr 29, 2026
2 checks passed
@rousso rousso deleted the feature/TEDEFO-5029-analyze-emd branch April 29, 2026 15:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants