Skip to content

Implement CTerminologyCode.constraint as String#761

Merged
MattijsK merged 18 commits into
670_feature_archie_4_major_versionfrom
643_terminology_contstraint_type_to_string
Jun 18, 2026
Merged

Implement CTerminologyCode.constraint as String#761
MattijsK merged 18 commits into
670_feature_archie_4_major_versionfrom
643_terminology_contstraint_type_to_string

Conversation

@MattijsK

@MattijsK MattijsK commented Mar 5, 2026

Copy link
Copy Markdown
Collaborator

Summary

This PR fixes #643. The openEHR specification has CTerminologyCode.constraint as a single String, but Archie modeled it as List<String>. This PR aligns Archie with the spec.

Changes

Core model (CTerminologyCode)

  • constraint field changed from List<String> to String; getConstraint() now returns String
  • addConstraint(String) removed; setConstraint(String) takes a single value
  • getConstraintAsList() added as a convenience method for call sites that need list semantics, returning a singleton list or an empty list

Abstract primitive object interface (CPrimitiveObject)

  • getConstraint() return type is now the Constraint type parameter, allowing each subclass to specify its own type
  • getConstraintAsList() added as abstract (returning List<?>), implemented in all subclasses; annotated @JsonIgnore so it is not serialised as a separate property
  • addConstraint() removed from the abstract interface

ADL 1.4 → ADL 2 conversion

ADL 1.4 allows inline multi-code constraints (e.g. [local::at0001, at0002] and [snomed-ct::12345, 67890]) which have no direct single-string ADL 2 equivalent. To keep CTerminologyCode aligned with the openEHR spec (single-string constraint) while still being able to parse ADL 1.4, a dedicated intermediate
type is introduced:

  • New class CTerminologyCodeADL14 mirrors the pre-refactor CTerminologyCode API (List<String> constraint, addConstraint(String), etc.). It exists only inside the ADL 1.4 parsing/conversion pipeline; the converter replaces it with a CTerminologyCode before any ADL 2 output is produced.
    (ADLArchetypeSerializer is an ADL 2 serializer and has no serializer registered for CTerminologyCodeADL14 — by design, since this type should never survive conversion.)
  • The ADL 1.4 parser (Adl14PrimitivesConstraintParser, Adl14CComplexObjectParser, CDVOrdinalItem) now produces CTerminologyCodeADL14 instead of CTerminologyCode, preserving multi-code lists exactly as written.
  • ADL14TermConstraintConverter operates on CTerminologyCodeADL14, applying the existing multi-code logic (collapsing multiple at-codes into a synthesised ac-code value set, creating term bindings for external codes, etc.). When done, each CTerminologyCodeADL14 is replaced in its parent
    (CAttribute.children or CPrimitiveTuple.members) with a proper CTerminologyCode carrying the single converted constraint string. Downstream code (serializer, validators) only ever sees ADL 2 CTerminologyCode.
  • PreviousConversionApplier.gatherUsedValueSets continues to use CTerminologyCode because it runs after the converter has performed the swap.

Serialisation

  • JSON deserialisation of the old array format ("constraint": ["at1"]) is handled by the existing UNWRAP_SINGLE_VALUE_ARRAYS Jackson feature

Tests

  • Added backwards-compatibility tests for deserialising the old List<String> JSON form
  • Added LargeSetOfADL14sTest.testDemoArchetype(), which parses a demo ADL 1.4 archetype exercising (almost) every constraint type and then: asserts every CTerminologyCodeADL14 in the parsed tree has a non-empty constraint (guarding against the silent multi-code parsing regression that bulk-parse tests miss,
    since they only count parse exceptions); and converts it to ADL 2, asserting serialize → reparse → serialize-again produces identical text
  • Added unit tests for CTerminologyCode, CTerminologyCodeADL14, the converter's toAdl2 field-copy step, and the ADL 1.4 terminology-code parser branches

@MattijsK MattijsK changed the base branch from master to 670_feature_archie_4_major_version March 5, 2026 13:22
@codecov

codecov Bot commented Apr 9, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 51.44033% with 118 lines in your changes missing coverage. Please review.
✅ Project coverage is 72.20%. Comparing base (0b5c5a8) to head (95817bb).

Files with missing lines Patch % Lines
...p/archie/aom/primitives/CTerminologyCodeADL14.java 32.59% 86 Missing and 5 partials ⚠️
...dap/archie/adl14/ADL14TermConstraintConverter.java 79.59% 4 Missing and 6 partials ⚠️
.../nedap/archie/aom/primitives/CTerminologyCode.java 53.84% 2 Missing and 4 partials ⚠️
.../nedap/archie/adl14/PreviousConversionApplier.java 40.00% 2 Missing and 1 partial ⚠️
...a/com/nedap/archie/adl14/aom14/CDVOrdinalItem.java 0.00% 2 Missing ⚠️
...er/adl/constraints/CTerminologyCodeSerializer.java 50.00% 0 Missing and 2 partials ⚠️
...a/com/nedap/archie/adl14/ADL14NodeIDConverter.java 0.00% 0 Missing and 1 partial ⚠️
...e/adl14/treewalkers/Adl14CComplexObjectParser.java 66.66% 1 Missing ⚠️
...main/java/com/nedap/archie/aom/utils/AOMUtils.java 0.00% 0 Missing and 1 partial ⚠️
.../archie/creation/ExampleJsonInstanceGenerator.java 50.00% 0 Missing and 1 partial ⚠️
Additional details and impacted files
@@                           Coverage Diff                            @@
##             670_feature_archie_4_major_version     #761      +/-   ##
========================================================================
- Coverage                                 72.42%   72.20%   -0.22%     
- Complexity                                 7213     7241      +28     
========================================================================
  Files                                       678      679       +1     
  Lines                                     23312    23462     +150     
  Branches                                   3776     3817      +41     
========================================================================
+ Hits                                      16883    16941      +58     
- Misses                                     4701     4786      +85     
- Partials                                   1728     1735       +7     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@MattijsK MattijsK changed the title ctermcode.constraint type to string Implement CTerminologyCode.constraint as String Apr 9, 2026
@MattijsK MattijsK marked this pull request as ready for review April 9, 2026 08:50
@MattijsK MattijsK linked an issue Apr 9, 2026 that may be closed by this pull request
@VeraPrinsen VeraPrinsen self-requested a review April 10, 2026 08:57
Comment thread aom/src/main/java/com/nedap/archie/aom/CPrimitiveObject.java Outdated
Comment thread aom/src/main/java/com/nedap/archie/aom/primitives/CTerminologyCode.java Outdated
Comment thread aom/src/main/java/com/nedap/archie/aom/primitives/CTerminologyCode.java Outdated
public abstract List<Constraint> getConstraint();
public abstract Constraint getConstraint();

public abstract void setConstraint(List<Constraint> constraint);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This abstract method can stay, but just with the parameter Constraint instead of List

Comment thread aom/src/main/java/com/nedap/archie/aom/primitives/CTerminologyCode.java Outdated
... and use this in ADL14 related classes.

Instead of the new CTerminologyCode with the pendingCodes object.
@MattijsK MattijsK requested a review from VeraPrinsen May 19, 2026 08:37
Comment thread aom/src/main/java/com/nedap/archie/adl14/ADL14TermConstraintConverter.java Outdated
* tests didn't catch because they only counted parse exceptions.
*/
@Test
public void testDemoArchetype() throws Exception {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I think we should also test that serialising a parsed ADL1.4 archetype results in the same ADL as it was in the file before. This can also be tested in the ADLArchetypeSerializerParserRoundtripTest maybe, but that file currently only tests ADL2 archetypes I think

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

With this test I'm curious to know if serialising the ADL1.4 goes right as we know have a CTerminologyCodeSerializer class, but not one for the CTerminologyCodeADL14.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Unfortunately, there is no ADL 1.4 serializer in Archie. So a full round trip test, the way you suggest, is not possible. But I've tried to simply add more things to the test to hopefully be more certain.. please take a look...

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

The ADLArchetypeSerializer works for both ADL2 and ADL1.4. The reason the serializer is broken is because of it cannot serialize the new CTerminologyCodeADL14 yet. Just as we have a copy of the CTerminologyCode now, we also need a copy of the CTerminologyCodeSerializer and add it to the constraintSerializers in the ADLDefinitionSerializer class.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

During pairprogramming: serializer isn't suited for ADL1.4, so scrap this!

Comment thread aom/src/main/java/com/nedap/archie/adl14/ADL14TermConstraintConverter.java Outdated
@MattijsK MattijsK requested a review from VeraPrinsen June 1, 2026 07:49

@VeraPrinsen VeraPrinsen left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

One requested change about the Serializer

* tests didn't catch because they only counted parse exceptions.
*/
@Test
public void testDemoArchetype() throws Exception {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

The ADLArchetypeSerializer works for both ADL2 and ADL1.4. The reason the serializer is broken is because of it cannot serialize the new CTerminologyCodeADL14 yet. Just as we have a copy of the CTerminologyCode now, we also need a copy of the CTerminologyCodeSerializer and add it to the constraintSerializers in the ADLDefinitionSerializer class.

@MattijsK MattijsK requested a review from VeraPrinsen June 11, 2026 08:41
@MattijsK MattijsK merged commit 65bf163 into 670_feature_archie_4_major_version Jun 18, 2026
2 of 4 checks passed
@MattijsK MattijsK deleted the 643_terminology_contstraint_type_to_string branch June 18, 2026 08:35
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.

CTerminologyCode.constraint has incorrect type

2 participants