From 7878352237db6f6f392ea2305c50b086d44f96c6 Mon Sep 17 00:00:00 2001 From: Sebastian Iancu Date: Tue, 28 Apr 2026 12:48:21 +0200 Subject: [PATCH 01/10] Clarify Level Removal in Simplified Formats spec (SPECITS-94) Separate container attribute elision from wrapper type collapse, tighten conditional EVENT rule, add worked example (SPECITS-94). Verified against reference implementations: - Better web-template MediumWebTemplateCompactor.ALWAYS_COMPACTABLE_CLASSES and EHRbase openEHR_SDK FlatHelper.skip(): both unconditionally skip ITEM_TREE / _LIST / _SINGLE / _TABLE / _STRUCTURE and HISTORY; CLUSTER is absent from both lists, hence retained in paths. - EVENT conditional rule corresponds to Better.SINGLE_COMPACTABLE_CLASSES with typesMatch (any rmType ending "EVENT") and EHRbase groupingBy(aqlPath).filter(isEvent); parent is HISTORY, max=1. - Empirical confirmation: Better test fixture IDCR_-_Laboratory_Test_Report(1).json shows CLUSTER nodes (laboratory_test_panel, laboratory_result:0) appearing in Flat paths under archetype-id aliases while container attribute names (data, events, items) are absent. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../master00-amendment_record.adoc | 9 +- .../master04-basic_concepts.adoc | 82 +++++++++++++++---- 2 files changed, 73 insertions(+), 18 deletions(-) diff --git a/docs/simplified_formats/master00-amendment_record.adoc b/docs/simplified_formats/master00-amendment_record.adoc index 35998e55..43f01143 100644 --- a/docs/simplified_formats/master00-amendment_record.adoc +++ b/docs/simplified_formats/master00-amendment_record.adoc @@ -6,10 +6,15 @@ 4+^h|*ITS_REST Release (unreleased)* -|[[latest_issue]]1.1.0 +|[[latest_issue]]1.1.1 +|{spec_tickets}/SPECITS-94[SPECITS-94^]. Clarified Level Removal (attribute elision vs wrapper collapse); tightened `EVENT` rule; added example. +|REST WG +|[[latest_issue_date]]28 Apr 2026 + +|1.1.0 |{spec_tickets}/SPECITS-61[SPECITS-61^]. Cleanup and consolidate Simplified Formats specification; Deprecating Simplified Data Template (SDT) specification |REST WG -|[[latest_issue_date]]05 Nov 2025 +|05 Nov 2025 4+^h|*ITS_REST Release 1.0.3* diff --git a/docs/simplified_formats/master04-basic_concepts.adoc b/docs/simplified_formats/master04-basic_concepts.adoc index 38822c3c..01926d96 100644 --- a/docs/simplified_formats/master04-basic_concepts.adoc +++ b/docs/simplified_formats/master04-basic_concepts.adoc @@ -843,32 +843,82 @@ Algorithm for converting structured format to flat: == Level Removal -Certain RM types are omitted from paths to simplify the structure. -These types do not typically carry significant clinical information and would unnecessarily complicate the path structure. +Paths in Flat and Structured formats omit two distinct kinds of segments relative to the canonical RM path: -=== Always Removed +1. *Container attribute names* of `LOCATABLE`-to-`LOCATABLE` relationships are never present as path segments -- the parent connects directly to the child via the child's archetype node-id alias. +2. In addition, certain *wrapper node types* are themselves collapsed -- their archetype node-id is also dropped -- because they act only as structural slots and carry no clinically meaningful identity at that level. -The following node types are always removed from paths, but their respective data carrying attribute is taken as the value at that specific level: +=== Container Attributes Elided from Paths -* `ITEM_TREE` replaced by `ITEM_TREE.items` -* `ITEM_LIST` replaced by `ITEM_LIST.items` -* `ITEM_SINGLE` replaced by `ITEM_SINGLE.item` -* `ITEM_TABLE` replaced by `ITEM_TABLE.rows` -* `HISTORY` replaced by `HISTORY.events` +The following RM attribute names are universally absent from paths: -=== Conditionally Removed +* `COMPOSITION.content` +* `SECTION.items` +* `OBSERVATION.data`, `OBSERVATION.state`, `OBSERVATION.protocol` +* `EVALUATION.data`, `EVALUATION.protocol` +* `INSTRUCTION.activities`, `INSTRUCTION.protocol` +* `ACTION.description`, `ACTION.protocol` +* `ADMIN_ENTRY.data` +* `ACTIVITY.description` +* `HISTORY.events` +* `EVENT.data`, `EVENT.state` +* `ITEM_TREE.items`, `ITEM_LIST.items`, `ITEM_SINGLE.item`, `ITEM_TABLE.rows` +* `CLUSTER.items` -The following types are removed when they meet specific criteria. +=== Always Collapsed Wrapper Types -An `EVENT` node is removed when: +In addition to the attribute elision above, the following wrapper node types are themselves collapsed -- their archetype node-id is also dropped, so the parent connects directly to the wrapper's contents: -1. Its maximum occurrence is 1 (i.e., `max = 1`) -2. AND it has no sibling `EVENT` nodes in the same parent +* `ITEM_STRUCTURE` (abstract) and its concrete subtypes: +** `ITEM_TREE` +** `ITEM_LIST` +** `ITEM_SINGLE` +** `ITEM_TABLE` +* `HISTORY` + +These types act as fixed structural slots in their parent (`ENTRY` for the `ITEM_STRUCTURE` family; `OBSERVATION` for `HISTORY`) and have no archetype node-id distinct from that slot. + +=== Conditionally Collapsed Wrapper Types + +An `EVENT` node is collapsed when both of the following hold: + +1. Its maximum occurrence is 1 (i.e., `max = 1`), AND +2. No sibling `EVENT` nodes (of any concrete event type) exist in the same parent `HISTORY`. `EVENT` nodes are retained when: -* Multiple `EVENT` types exist in the same `OBSERVATION` (e.g., `POINT_EVENT` and `INTERVAL_EVENT`) -* The `EVENT` can occur multiple times +* Multiple `EVENT` types exist in the same parent `HISTORY` (e.g., a `POINT_EVENT` alongside an `INTERVAL_EVENT`), or +* The `EVENT` can occur multiple times (`max > 1`). + +=== Example + +Take a single measurement magnitude inside a laboratory result panel. The canonical RM path is: + +[source] +---- +/content[openEHR-EHR-OBSERVATION.laboratory_test_result.v1] + /data[at0001] + /events[at0002] + /data[at0003] + /items[openEHR-EHR-CLUSTER.laboratory_test_panel.v1] + /items[openEHR-EHR-CLUSTER.laboratory_test_analyte.v1] + /items[at0001] + /value +---- + +The same field in Flat form: + +[source] +---- +laboratory_test_report/laboratory_test/laboratory_test_panel/laboratory_result:0/result_value|magnitude +---- + +Differences: + +* Container attribute names (`content`, `data`, `events`, `items`, `value`) are elided wherever they appear. +* The `HISTORY` (`at0001`) and `ITEM_TREE` (`at0003`) wrapper nodes are collapsed; the `EVENT` (`at0002`) is conditionally collapsed (here `max=1`, single event type). +* The `OBSERVATION` and the two `CLUSTER` nodes are retained under their archetype-id aliases (`laboratory_test`, `laboratory_test_panel`, `laboratory_result`); the inner `CLUSTER` repeats, hence the `:0` instance index. +* `ELEMENT.value` is replaced by the `|magnitude` attribute suffix. == Validation From 6c0a0d5cd27b3804804e7ae3467a62cfc9cf66f9 Mon Sep 17 00:00:00 2001 From: Sebastian Iancu Date: Tue, 28 Apr 2026 13:06:47 +0200 Subject: [PATCH 02/10] Add |other suffix on DV_CODED_TEXT for open value-sets (SPECITS-94) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add table row + JSON example in DV_CODED_TEXT class section, add type-switch sub-section, add cross-cutting Open Value-Sets section in basic_concepts (SPECITS-94). Verified against reference implementations: - EHRbase openEHR_SDK DvTextRMUnmarshaller.java (L43-46): when the WebTemplateInput has suffix:"other", the FLAT value at |other is written into DvText.value; otherwise standard "value" handling applies. Confirms |other → DV_TEXT on ingest. - EHRbase DvTextStdConfiguration.java (L41-42): mirror — emits DvText.value via the |other suffix when the WebTemplate input declares suffix:"other". Confirms round-trip on read. - Better web-template AbstractRawToStructuredConverter.kt#isCodedTextForOtherAttribute (L243-244): a DvText instance at a DV_CODED_TEXT-constrained leaf is accepted as a valid match iff WebTemplateInput.listOpen=true. Confirms the open-value-set gating. - Better CodePhraseWebTemplateInputBuilder.kt (L115-119): propagates C_STRING.listOpen=true onto the WebTemplateInput, which is the upstream signal driving the |other branch. - Discourse evidence: topic 11790 (2026-02, E. Eschmann/S. Iancu) raised the spec gap; topic 6317 (2025-02, S. Spiska/I. McNicoll) confirmed Better/EHRbase parity on the suffix:"other", type:"TEXT" web-template emission. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../master00-amendment_record.adoc | 2 +- .../master04-basic_concepts.adoc | 15 +++++++++++ .../master05-rm_mapping.adoc | 25 +++++++++++++++++++ 3 files changed, 41 insertions(+), 1 deletion(-) diff --git a/docs/simplified_formats/master00-amendment_record.adoc b/docs/simplified_formats/master00-amendment_record.adoc index 43f01143..ee9feac2 100644 --- a/docs/simplified_formats/master00-amendment_record.adoc +++ b/docs/simplified_formats/master00-amendment_record.adoc @@ -7,7 +7,7 @@ 4+^h|*ITS_REST Release (unreleased)* |[[latest_issue]]1.1.1 -|{spec_tickets}/SPECITS-94[SPECITS-94^]. Clarified Level Removal (attribute elision vs wrapper collapse); tightened `EVENT` rule; added example. +|{spec_tickets}/SPECITS-94[SPECITS-94^]. Clarified Level Removal (attribute elision vs wrapper collapse) and `EVENT` rule; documented `\|other` suffix for `DV_CODED_TEXT` open value-sets. |REST WG |[[latest_issue_date]]28 Apr 2026 diff --git a/docs/simplified_formats/master04-basic_concepts.adoc b/docs/simplified_formats/master04-basic_concepts.adoc index 01926d96..6fe34b35 100644 --- a/docs/simplified_formats/master04-basic_concepts.adoc +++ b/docs/simplified_formats/master04-basic_concepts.adoc @@ -921,6 +921,21 @@ Differences: * `ELEMENT.value` is replaced by the `|magnitude` attribute suffix. +[[open_value_sets]] +== Open Value-Sets and the `|other` Suffix + +When an archetype constrains a leaf to `DV_CODED_TEXT` with an _open_ value-set -- the bound terminology lists recommended codes but the constraint also accepts values outside the list (`listOpen: true` in the web template; non-`limit-to-list` in ADL) -- the same leaf may at runtime carry either a `DV_CODED_TEXT` (chosen from the list) or a `DV_TEXT` (free-text value). + +Many archetypes deliberately combine a recommended coded list with free-text fallback (e.g. `state_of_dress`, `confounding_factors`, `overall_test_status`). Without a dedicated FLAT-level discriminator the `DV_CODED_TEXT` vs `DV_TEXT` branch would have to be inferred from value patterns, which is fragile and ambiguous. The `|other` suffix makes the branch explicit at the FLAT level and removes the need for receivers to reason about it. + +* On *write*: clients supply the free-text value via `|other: ""`. The server persists the leaf as a `DV_TEXT` in the canonical RM (not as a `DV_CODED_TEXT` with empty `defining_code`). +* On *read*: when the leaf carries a `DV_TEXT` whose archetype constraint is `DV_CODED_TEXT` with `listOpen: true`, the server SHOULD emit it via `|other: ""` so that round-trip equality holds at the FLAT level. +* `|other` is mutually exclusive with `|code`, `|value` and `|terminology` on the same leaf path; servers MUST reject combinations. +* `|other` MUST be rejected when the constraint is closed (`listOpen: false`). + +The per-suffix table is in the <> class section. + + == Validation Implementations SHOULD validate: diff --git a/docs/simplified_formats/master05-rm_mapping.adoc b/docs/simplified_formats/master05-rm_mapping.adoc index ba371583..c798ae5c 100644 --- a/docs/simplified_formats/master05-rm_mapping.adoc +++ b/docs/simplified_formats/master05-rm_mapping.adoc @@ -1878,6 +1878,15 @@ See RM specification of the https://specifications.openehr.org/releases/RM/lates } ---- +Free-text value when the archetype constraint allows an open value-set (`listOpen: true` in the web template): + +[source,json] +---- +{ + "conformance-ehrbase.de.v0/conformance_section/conformance_observation/any_event:0/dv_coded_text|other": "free-text value not in the coded list" +} +---- + [cols="5*", options="header"] |=== | Flat Path @@ -1904,6 +1913,12 @@ See RM specification of the https://specifications.openehr.org/releases/RM/lates | (yes) | only required for external terminologies +| `\|other` +| String +| _value_ (as `<>`) +| no +| Free-text value used when the constraint allows an open value-set (`listOpen: true` in the web template). When `\|other` is set, `\|code`, `\|value` and `\|terminology` MUST NOT be set; the leaf is serialised in the canonical RM as a `DV_TEXT` rather than a `DV_CODED_TEXT`. + | `\|formatting` | String | formatting @@ -1929,6 +1944,16 @@ See RM specification of the https://specifications.openehr.org/releases/RM/lates | |=== +=== When a `DV_CODED_TEXT` becomes a `DV_TEXT` + +Where the archetype constraint allows an open value-set (`listOpen: true` in the web template; non-`limit-to-list` in ADL), a leaf bound to `DV_CODED_TEXT` may be populated with a free-text value via the `\|other` suffix. In that case: + +* the canonical RM serialisation of the leaf is a <>, not a `DV_CODED_TEXT` with empty `defining_code`; +* `\|other` is mutually exclusive with `\|code`, `\|value` and `\|terminology` on the same leaf; +* on a closed list (`listOpen: false`), `\|other` MUST be rejected. + +See <> for the cross-cutting rule and rationale. + [[DV_ORDINAL]] == DV_ORDINAL From aec4f758fa7500583eed88f8b9668183a5ee59eb Mon Sep 17 00:00:00 2001 From: Sebastian Iancu Date: Tue, 28 Apr 2026 13:20:32 +0200 Subject: [PATCH 03/10] Add `|preferred_term` suffix on `DV_CODED_TEXT` (SPECITS-94) In Simplified Formats spec, mapping to `defining_code.preferred_term` and aligning with the existing `CODE_PHRASE` mapping; update mutex rules with `|other`. Closes the gap raised in https://discourse.openehr.org/t/rm-mappings-dv-coded-text-preferred-term-missing/11780 (SPECITS-94). Co-Authored-By: Claude Opus 4.7 (1M context) --- .../simplified_formats/master00-amendment_record.adoc | 2 +- docs/simplified_formats/master05-rm_mapping.adoc | 11 +++++++++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/docs/simplified_formats/master00-amendment_record.adoc b/docs/simplified_formats/master00-amendment_record.adoc index ee9feac2..b592354e 100644 --- a/docs/simplified_formats/master00-amendment_record.adoc +++ b/docs/simplified_formats/master00-amendment_record.adoc @@ -7,7 +7,7 @@ 4+^h|*ITS_REST Release (unreleased)* |[[latest_issue]]1.1.1 -|{spec_tickets}/SPECITS-94[SPECITS-94^]. Clarified Level Removal (attribute elision vs wrapper collapse) and `EVENT` rule; documented `\|other` suffix for `DV_CODED_TEXT` open value-sets. +|{spec_tickets}/SPECITS-94[SPECITS-94^]. Clarified Level Removal (attribute elision vs wrapper collapse) and `EVENT` rule; added `\|other` and `\|preferred_term` suffixes on `DV_CODED_TEXT`. |REST WG |[[latest_issue_date]]28 Apr 2026 diff --git a/docs/simplified_formats/master05-rm_mapping.adoc b/docs/simplified_formats/master05-rm_mapping.adoc index c798ae5c..347383e3 100644 --- a/docs/simplified_formats/master05-rm_mapping.adoc +++ b/docs/simplified_formats/master05-rm_mapping.adoc @@ -1863,6 +1863,7 @@ See RM specification of the https://specifications.openehr.org/releases/RM/lates "conformance-ehrbase.de.v0/conformance_section/conformance_observation/any_event:0/dv_coded_text|value": "term1", "conformance-ehrbase.de.v0/conformance_section/conformance_observation/any_event:0/dv_coded_text|code": "at0006", "conformance-ehrbase.de.v0/conformance_section/conformance_observation/any_event:0/dv_coded_text|terminology": "local", + "conformance-ehrbase.de.v0/conformance_section/conformance_observation/any_event:0/dv_coded_text|preferred_term": "Term One", "conformance-ehrbase.de.v0/conformance_section/conformance_observation/any_event:0/dv_coded_text|formatting": "plain", "conformance-ehrbase.de.v0/conformance_section/conformance_observation/any_event:0/dv_coded_text/_language|code": "en", "conformance-ehrbase.de.v0/conformance_section/conformance_observation/any_event:0/dv_coded_text/_language|terminology": "ISO_639-1", @@ -1913,11 +1914,17 @@ Free-text value when the archetype constraint allows an open value-set (`listOpe | (yes) | only required for external terminologies +| `\|preferred_term` +| String +| defining_code.preferred_term +| no +| Optional preferred display rubric for the `defining_code`. See the `\|preferred_term` row of <> for the analogous mapping on a bare `CODE_PHRASE`. + | `\|other` | String | _value_ (as `<>`) | no -| Free-text value used when the constraint allows an open value-set (`listOpen: true` in the web template). When `\|other` is set, `\|code`, `\|value` and `\|terminology` MUST NOT be set; the leaf is serialised in the canonical RM as a `DV_TEXT` rather than a `DV_CODED_TEXT`. +| Free-text value used when the constraint allows an open value-set (`listOpen: true` in the web template). When `\|other` is set, `\|code`, `\|value`, `\|terminology` and `\|preferred_term` MUST NOT be set; the leaf is serialised in the canonical RM as a `DV_TEXT` rather than a `DV_CODED_TEXT`. | `\|formatting` | String @@ -1949,7 +1956,7 @@ Free-text value when the archetype constraint allows an open value-set (`listOpe Where the archetype constraint allows an open value-set (`listOpen: true` in the web template; non-`limit-to-list` in ADL), a leaf bound to `DV_CODED_TEXT` may be populated with a free-text value via the `\|other` suffix. In that case: * the canonical RM serialisation of the leaf is a <>, not a `DV_CODED_TEXT` with empty `defining_code`; -* `\|other` is mutually exclusive with `\|code`, `\|value` and `\|terminology` on the same leaf; +* `\|other` is mutually exclusive with `\|code`, `\|value`, `\|terminology` and `\|preferred_term` on the same leaf; * on a closed list (`listOpen: false`), `\|other` MUST be rejected. See <> for the cross-cutting rule and rationale. From d234b7861bfdef062a45a7362e16d903e948c072 Mon Sep 17 00:00:00 2001 From: Sebastian Iancu Date: Tue, 28 Apr 2026 13:37:35 +0200 Subject: [PATCH 04/10] Add AGENTS.md amendment-record and implementation-reference rules Signed-off-by: Sebastian Iancu --- AGENTS.md | 52 +++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 47 insertions(+), 5 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 03f8d68e..7c8ccbaa 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -125,8 +125,26 @@ How the polymorphic openEHR Reference Model is encoded in OpenAPI: upstream (Better, EHRbase) or in `simplified_formats`. - **No tests.** This project has none and none are expected; do not scaffold a test framework. -- **Trace numbers in commits.** History references Jira tickets (`SPECITS-NN`) — - follow that style. +- **Commit messages: short subject, optional body, Jira ticket on the subject + line.** Follow GitHub-style conventions: a concise subject line (target ~70 + characters, hard limit ~72) written in the imperative mood and capturing the + headline change. When a Jira ticket exists, reference it on the subject line + in the form `(SPECITS-NN)` (or the equivalent project key — `SPECPR`, + `SPECRM`, …) so `git log --oneline` stays scannable. If the change needs + more context — rationale, cross-references to upstream issues/Discourse + threads, lists of touched files, links to implementations consulted — put + it in the commit body, separated from the subject by a blank line. Reserve + the body for information that doesn't already live in the diff or the + amendment record; the amendment record stays terse (see the rule above) + precisely because the commit body carries the full story. +- **Keep amendment-record entries short and succinct.** `master00-amendment_record.adoc` + in each AsciiDoc spec is a one-line-per-issue ledger, not a changelog narrative. + Each entry should be a single sentence (or a short semicolon-separated list when + one ticket bundles related fixes), naming the headline change and the affected + RM/FLAT names in backticks. Keep the full rationale and worked examples in the + spec body and in the commit message / PR description — not in the amendment record. + When extending an existing unreleased entry rather than adding a new row, fold + the new headline into the existing list with a `;` separator and stop there. ### Recurring schema-alignment pitfalls @@ -176,9 +194,33 @@ before editing: - HL7 SMART App Launch IG — - SMART Health IT — - `docs/simplified_formats/` and `docs/simplified_data_template/` - - EHRbase SDT docs — - - Better Care WebTemplate — - - WebTemplate test suite — + - EHRbase SDT user docs — + - EHRbase FLAT data-types reference (canonical examples for every RM type) — + + - EHRbase server source — + - EHRbase openEHR SDK (Java; FLAT/STRUCTURED un/marshalling) — + ; relevant subtree: + `serialisation/src/main/java/org/ehrbase/openehr/sdk/serialisation/`. + - Better Care WebTemplate (Kotlin reference implementation) — + ; the FLAT path-suffix conventions + are codified in two parallel trees: + - `src/main/kotlin/care/better/platform/web/template/converter/flat/mapper/ToFlatMapper.kt` + — emits the FLAT keys/suffixes for each RM type. + - `src/main/kotlin/care/better/platform/web/template/converter/raw/factory/leaf/Factory.kt` + — parses inbound FLAT keys back to RM (and lists tolerated input aliases). + - Better WebTemplate test suite (golden FLAT/STRUCTURED fixtures) — + + - openEHR Discourse (ITS / Platform categories) — + for raised gaps, + e.g. . + +For any Simplified-Formats edit that affects path suffixes, attribute names, or +mutex rules, the **two implementations are the tie-breaker** when prose and +intuition disagree: the FLAT path-suffix vocabulary the spec normatively documents +must match what Better's `*ToFlatMapper.kt` emits and what EHRbase's +`09_flat/01_data_types/index.rst` shows. Known intentional divergences from the +RM attribute names (`|mediatype` vs `media_type`, `|alternatetext` vs +`alternate_text`) are baked into both implementations and must be preserved. URLs were live-checked at last edit; verify before quoting and keep the bibliography in each `master.adoc` in sync. From e68fe903c9a110c10bff1d93835b2db384aa3637 Mon Sep 17 00:00:00 2001 From: Sebastian Iancu Date: Tue, 28 Apr 2026 13:42:02 +0200 Subject: [PATCH 05/10] Fix LINK |target and DV_MULTIMEDIA |mediatype mappings (SPECITS-94) Replace duplicate `|type` row with `|target` (mapping to `target.value`); rename `|media_type` to `|mediatype` to match the canonical convention used by both Better's `web-template` (`DvMultimediaToFlatMapper.kt`) and ehrbase (`09_flat/01_data_types/index.rst`); note the intentional divergence from RM attribute names on both `|mediatype` and `|alternatetext` (SPECITS-94). Co-Authored-By: Claude Opus 4.7 (1M context) --- docs/simplified_formats/master00-amendment_record.adoc | 2 +- docs/simplified_formats/master05-rm_mapping.adoc | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/simplified_formats/master00-amendment_record.adoc b/docs/simplified_formats/master00-amendment_record.adoc index b592354e..060803e2 100644 --- a/docs/simplified_formats/master00-amendment_record.adoc +++ b/docs/simplified_formats/master00-amendment_record.adoc @@ -7,7 +7,7 @@ 4+^h|*ITS_REST Release (unreleased)* |[[latest_issue]]1.1.1 -|{spec_tickets}/SPECITS-94[SPECITS-94^]. Clarified Level Removal (attribute elision vs wrapper collapse) and `EVENT` rule; added `\|other` and `\|preferred_term` suffixes on `DV_CODED_TEXT`. +|{spec_tickets}/SPECITS-94[SPECITS-94^]. Clarified Level Removal (attribute elision vs wrapper collapse) and `EVENT` rule; added `\|other` and `\|preferred_term` suffixes on `DV_CODED_TEXT`; fixed `LINK` (`\|target`) and `DV_MULTIMEDIA` (`\|mediatype`) mappings. |REST WG |[[latest_issue_date]]28 Apr 2026 diff --git a/docs/simplified_formats/master05-rm_mapping.adoc b/docs/simplified_formats/master05-rm_mapping.adoc index 347383e3..3cf05b72 100644 --- a/docs/simplified_formats/master05-rm_mapping.adoc +++ b/docs/simplified_formats/master05-rm_mapping.adoc @@ -922,9 +922,9 @@ See RM specification of the https://specifications.openehr.org/releases/RM/lates | yes | -| `\|type` +| `\|target` | STRING -| type.value +| target.value | yes | |=== @@ -2918,7 +2918,7 @@ See RM specification of the https://specifications.openehr.org/releases/RM/lates | no | -| `\|media_type` +| `\|mediatype` | String | media_type.code_string | Yes From a952dd123c7036ec6a8ce26b9e4d82f58bcbd642 Mon Sep 17 00:00:00 2001 From: Sebastian Iancu Date: Tue, 28 Apr 2026 14:29:43 +0200 Subject: [PATCH 06/10] Fix EVENT_CONTEXT table and add PARTICIPATION section (SPECITS-94) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The EVENT_CONTEXT table held a copy of PARTY_IDENTIFIED's columns (`|name`/`|id`/`|id_scheme`/`|id_namespace`/`/_identifier:i`) which matched neither the RM nor any reference implementation; the buggy `_location` example value used a date-time string for what RM defines as a free-text `String`; PARTICIPATION had no section even though `_participation:i` is referenced from many tables. Replaced with the actual EVENT_CONTEXT shape, verified against: - RM BMM: `EVENT_CONTEXT` has `start_time`/`setting` (mandatory), `end_time`/`location`/`health_care_facility`/`participations` (optional), and `other_context` (archetyped, not a FLAT leaf). - Better `EventContextToFlatMapper.kt`: emits literally `/_end_time`, `/_location`, `/_health_care_facility`, `/_participation:i`; delegates `start_time`/`setting` to the WebTemplate primary pass. - ehrbase `EventContextMarshalPostprocessor.java`: identical paths (`term + "/_end_time"`, `term + "/_location"`, `handleRmAttribute(..., "health_care_facility")`, `"_participation:" + i`). Added PARTICIPATION section documenting the inlined `performer` (PARTY_IDENTIFIED) flattening — `|function`, `|mode`, `|name`, `|id`, `|id_scheme`, `|id_namespace`, `|identifiers_{id,issuer,assigner,type}:i` — verified against Better's `ParticipationToFlatMapper.kt` (`mapInternal` + `mapPartyRef`) and ehrbase `ParticipationConfig.buildChildValues`. The `|id_namespace` row maps to `performer.external_ref.namespace` (RM `OBJECT_REF.namespace` is on the reference itself, not nested under `id: OBJECT_ID`); both implementations confirm — Better reads `rmObject.namespace` on `ObjectRef`, ehrbase reads `ObjectRef::getNamespace`. Note: PARTICIPATION's `time` (`DV_INTERVAL`) is not emitted by either implementation and has no FLAT path. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../master00-amendment_record.adoc | 2 +- .../master05-rm_mapping.adoc | 120 ++++++++++++++++-- 2 files changed, 112 insertions(+), 10 deletions(-) diff --git a/docs/simplified_formats/master00-amendment_record.adoc b/docs/simplified_formats/master00-amendment_record.adoc index 060803e2..37a811ae 100644 --- a/docs/simplified_formats/master00-amendment_record.adoc +++ b/docs/simplified_formats/master00-amendment_record.adoc @@ -7,7 +7,7 @@ 4+^h|*ITS_REST Release (unreleased)* |[[latest_issue]]1.1.1 -|{spec_tickets}/SPECITS-94[SPECITS-94^]. Clarified Level Removal (attribute elision vs wrapper collapse) and `EVENT` rule; added `\|other` and `\|preferred_term` suffixes on `DV_CODED_TEXT`; fixed `LINK` (`\|target`) and `DV_MULTIMEDIA` (`\|mediatype`) mappings. +|{spec_tickets}/SPECITS-94[SPECITS-94^]. Clarified Level Removal (attribute elision vs wrapper collapse) and `EVENT` rule; added `\|other` and `\|preferred_term` suffixes on `DV_CODED_TEXT`; fixed `LINK` (`\|target`) and `DV_MULTIMEDIA` (`\|mediatype`) mappings; corrected `EVENT_CONTEXT` table and added `PARTICIPATION` section. |REST WG |[[latest_issue_date]]28 Apr 2026 diff --git a/docs/simplified_formats/master05-rm_mapping.adoc b/docs/simplified_formats/master05-rm_mapping.adoc index 3cf05b72..50822c7d 100644 --- a/docs/simplified_formats/master05-rm_mapping.adoc +++ b/docs/simplified_formats/master05-rm_mapping.adoc @@ -1303,7 +1303,7 @@ See RM specification of the https://specifications.openehr.org/releases/RM/lates "conformance-ehrbase.de.v0/context/_participation:0|id_namespace": "HOSPITAL-NS", "conformance-ehrbase.de.v0/context/start_time": "2021-12-21T14:19:31.649613+01:00", "conformance-ehrbase.de.v0/context/_end_time": "2021-12-21T15:19:31.649613+01:00", - "conformance-ehrbase.de.v0/context/_location": "2021-12-21T15:19:31.649613+01:00", + "conformance-ehrbase.de.v0/context/_location": "Ward A3, Room 12", "conformance-ehrbase.de.v0/context/setting|code": "238", "conformance-ehrbase.de.v0/context/setting|value": "other care", "conformance-ehrbase.de.v0/context/setting|terminology": "openehr" @@ -1318,37 +1318,139 @@ See RM specification of the https://specifications.openehr.org/releases/RM/lates | Required | Note +| `/start_time` +| <> +| start_time +| yes +| + +| `/setting` +| <> +| setting +| yes +| ValueSet (openEHR `setting` group) + +| `/_end_time` +| <> +| end_time +| no +| + +| `/_location` +| String +| location +| no +| Free-text label (e.g. "Ward A3"); not a date-time. + +| `/_health_care_facility` +| <> +| health_care_facility +| no +| + +| `/_participation:i` +| <> +| participations +| no +| +|=== + +NOTE: `other_context` (RM `ITEM_STRUCTURE`) is not represented as a leaf in this table; archetyped context content is serialised under its own archetype-id paths within the COMPOSITION body, not under `/context`. The leading underscore on `_end_time`, `_location`, `_health_care_facility` and `_participation:i` marks them as optional RM-level attributes (see <>). + +[[PARTICIPATION]] +== PARTICIPATION + +See RM specification of the https://specifications.openehr.org/releases/RM/latest/common.html#_participation_class[PARTICIPATION] class. + +The `performer` (`PARTY_IDENTIFIED`) is inlined: its attributes are emitted at the same level as `function` and `mode`, rather than nested under `/performer`. + +[source,json] +---- +{ + "conformance-ehrbase.de.v0/context/_participation:0|function": "requester", + "conformance-ehrbase.de.v0/context/_participation:0|mode": "face-to-face communication", + "conformance-ehrbase.de.v0/context/_participation:0|name": "Dr. Marcus Johnson", + "conformance-ehrbase.de.v0/context/_participation:0|id": "199", + "conformance-ehrbase.de.v0/context/_participation:0|id_scheme": "HOSPITAL-NS", + "conformance-ehrbase.de.v0/context/_participation:0|id_namespace": "HOSPITAL-NS", + "conformance-ehrbase.de.v0/context/_participation:0|identifiers_id:0": "122", + "conformance-ehrbase.de.v0/context/_participation:0|identifiers_issuer:0": "issuer", + "conformance-ehrbase.de.v0/context/_participation:0|identifiers_assigner:0": "assigner", + "conformance-ehrbase.de.v0/context/_participation:0|identifiers_type:0": "type" +} +---- + +[cols="5*", options="header"] +|=== +| Flat Path +| Flat type +| RM Path +| Required +| Note + +| `\|function` +| String +| function.value +| yes +| + +| `\|mode` +| String +| mode.value +| no +| ValueSet (openEHR `participation mode` group) + | `\|name` | String -| name +| performer.name | no | | `\|id` | String -| external_ref.id.value +| performer.external_ref.id.value | no | | `\|id_scheme` | String -| external_ref.id.scheme +| performer.external_ref.id.scheme | no | | `\|id_namespace` | String -| external_ref.id.namespace +| performer.external_ref.namespace | (yes) -| required if id is set +| required if `\|id` is set. (RM `OBJECT_REF` has `namespace` directly on the reference, not nested under `id`.) -| `/_identifier:i` -| <> -| identifiers +| `\|identifiers_id:i` +| String +| performer.identifiers[i].id +| no +| + +| `\|identifiers_issuer:i` +| String +| performer.identifiers[i].issuer +| no +| + +| `\|identifiers_assigner:i` +| String +| performer.identifiers[i].assigner +| no +| + +| `\|identifiers_type:i` +| String +| performer.identifiers[i].type | no | |=== +NOTE: PARTICIPATION's `time` (RM `DV_INTERVAL`) is not currently emitted by FLAT mappings. Entries with a constrained participation `time` interval require the canonical RM JSON form. + [[OBJECT_REF]] == OBJECT_REF From d11cbf66b8bbc65bc8dc374f836a13b9ece39c50 Mon Sep 17 00:00:00 2001 From: Sebastian Iancu Date: Tue, 28 Apr 2026 14:30:28 +0200 Subject: [PATCH 07/10] Fix `|id_namespace` RM path on PARTY tables (SPECITS-94) PARTY_SELF, PARTY_IDENTIFIED and PARTY_RELATED tables mapped `|id_namespace` to `external_ref.id.namespace`. RM `OBJECT_REF` defines `namespace: String` directly on the reference (not under its inner `id: OBJECT_ID`), so the correct RM path is `external_ref.namespace`. Verified against: - RM BMM `OBJECT_REF`: properties are `id: OBJECT_ID`, `namespace: String`, `type: String`. `OBJECT_ID` only carries `value`; `namespace` is not nested. - Better `web-template` flat mapping (`PartyIdentifiedToFlatMapper` / `mapPartyRef` invoked from PARTICIPATION): `flatMappingContext["...|id_namespace"] = rmObject.namespace` where `rmObject` is `ObjectRef`. - ehrbase openEHR_SDK `ParticipationConfig.java`: `Optional...map(PartyProxy::getExternalRef).map(ObjectRef::getNamespace)`. Co-Authored-By: Claude Opus 4.7 (1M context) --- docs/simplified_formats/master00-amendment_record.adoc | 2 +- docs/simplified_formats/master05-rm_mapping.adoc | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/simplified_formats/master00-amendment_record.adoc b/docs/simplified_formats/master00-amendment_record.adoc index 37a811ae..bf5a5594 100644 --- a/docs/simplified_formats/master00-amendment_record.adoc +++ b/docs/simplified_formats/master00-amendment_record.adoc @@ -7,7 +7,7 @@ 4+^h|*ITS_REST Release (unreleased)* |[[latest_issue]]1.1.1 -|{spec_tickets}/SPECITS-94[SPECITS-94^]. Clarified Level Removal (attribute elision vs wrapper collapse) and `EVENT` rule; added `\|other` and `\|preferred_term` suffixes on `DV_CODED_TEXT`; fixed `LINK` (`\|target`) and `DV_MULTIMEDIA` (`\|mediatype`) mappings; corrected `EVENT_CONTEXT` table and added `PARTICIPATION` section. +|{spec_tickets}/SPECITS-94[SPECITS-94^]. Clarified Level Removal (attribute elision vs wrapper collapse) and `EVENT` rule; added `\|other` and `\|preferred_term` suffixes on `DV_CODED_TEXT`; fixed `LINK` (`\|target`) and `DV_MULTIMEDIA` (`\|mediatype`) mappings; corrected `EVENT_CONTEXT` table and added `PARTICIPATION` section; corrected PARTY `\|id_namespace` RM path. |REST WG |[[latest_issue_date]]28 Apr 2026 diff --git a/docs/simplified_formats/master05-rm_mapping.adoc b/docs/simplified_formats/master05-rm_mapping.adoc index 50822c7d..94648b21 100644 --- a/docs/simplified_formats/master05-rm_mapping.adoc +++ b/docs/simplified_formats/master05-rm_mapping.adoc @@ -1626,7 +1626,7 @@ See RM specification of the https://specifications.openehr.org/releases/RM/lates | `\|id_namespace` | String -| external_ref.id.namespace +| external_ref.namespace | (yes) | required if id is set |=== @@ -1685,7 +1685,7 @@ See RM specification of the https://specifications.openehr.org/releases/RM/lates | `\|id_namespace` | String -| external_ref.id.namespace +| external_ref.namespace | (yes) | required if id is set @@ -1756,7 +1756,7 @@ See RM specification of the https://specifications.openehr.org/releases/RM/lates | `\|id_namespace` | String -| external_ref.id.namespace +| external_ref.namespace | (yes) | required if id is set From eaff1d8b9c896d3402794ea13f86f6769d08f1fd Mon Sep 17 00:00:00 2001 From: Sebastian Iancu Date: Tue, 28 Apr 2026 14:32:25 +0200 Subject: [PATCH 08/10] Document PARTICIPATION `/relationship` for PARTY_RELATED (SPECITS-94) When PARTICIPATION's `performer` is a `PARTY_RELATED` (sub-type of `PARTY_IDENTIFIED` that adds a `relationship: DV_CODED_TEXT`), ehrbase emits the relationship as a sub-path under the participation with the standard DV_CODED_TEXT suffixes: /_participation:i/relationship|code /_participation:i/relationship|value /_participation:i/relationship|terminology Verified against: - ehrbase openEHR_SDK `PartyRelatedStdConfig.addRelationship`: builds `newTerm = currentTerm + "/" + "relationship"` and delegates to the DvCodedText StdConfig, then calls registered postprocessors for the `relationship` sub-tree. - ehrbase `ParticipationConfig.buildChildValues` invokes `addRelationship` when the performer is a `PartyRelated`. Better divergence: - Better `ParticipationToFlatMapper.kt` checks only `if (performer is PartyIdentified)` and inlines name / id / identifiers; the PartyRelated `relationship` is silently dropped. Section calls this divergence out so producers know that the path is ehrbase-readable but not round-trippable through Better at present. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../master00-amendment_record.adoc | 2 +- .../master05-rm_mapping.adoc | 33 +++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/docs/simplified_formats/master00-amendment_record.adoc b/docs/simplified_formats/master00-amendment_record.adoc index bf5a5594..e521e780 100644 --- a/docs/simplified_formats/master00-amendment_record.adoc +++ b/docs/simplified_formats/master00-amendment_record.adoc @@ -7,7 +7,7 @@ 4+^h|*ITS_REST Release (unreleased)* |[[latest_issue]]1.1.1 -|{spec_tickets}/SPECITS-94[SPECITS-94^]. Clarified Level Removal (attribute elision vs wrapper collapse) and `EVENT` rule; added `\|other` and `\|preferred_term` suffixes on `DV_CODED_TEXT`; fixed `LINK` (`\|target`) and `DV_MULTIMEDIA` (`\|mediatype`) mappings; corrected `EVENT_CONTEXT` table and added `PARTICIPATION` section; corrected PARTY `\|id_namespace` RM path. +|{spec_tickets}/SPECITS-94[SPECITS-94^]. Clarified Level Removal (attribute elision vs wrapper collapse) and `EVENT` rule; added `\|other` and `\|preferred_term` suffixes on `DV_CODED_TEXT`; fixed `LINK` (`\|target`) and `DV_MULTIMEDIA` (`\|mediatype`) mappings; corrected `EVENT_CONTEXT` table and added `PARTICIPATION` section; corrected PARTY `\|id_namespace` RM path; documented PARTICIPATION `/relationship` for `PARTY_RELATED` performer. |REST WG |[[latest_issue_date]]28 Apr 2026 diff --git a/docs/simplified_formats/master05-rm_mapping.adoc b/docs/simplified_formats/master05-rm_mapping.adoc index 94648b21..b7abcc9e 100644 --- a/docs/simplified_formats/master05-rm_mapping.adoc +++ b/docs/simplified_formats/master05-rm_mapping.adoc @@ -1451,6 +1451,39 @@ The `performer` (`PARTY_IDENTIFIED`) is inlined: its attributes are emitted at t NOTE: PARTICIPATION's `time` (RM `DV_INTERVAL`) is not currently emitted by FLAT mappings. Entries with a constrained participation `time` interval require the canonical RM JSON form. +[[participation_party_related]] +=== PARTY_RELATED performer + +When the `performer` is a `PARTY_RELATED` (a sub-type of `PARTY_IDENTIFIED` that carries a `relationship: DV_CODED_TEXT`), the `relationship` attribute is emitted as a sub-path under the participation, with the standard <> suffixes (`\|code`, `\|value`, `\|terminology`): + +[source,json] +---- +{ + "conformance-ehrbase.de.v0/context/_participation:0|function": "next of kin", + "conformance-ehrbase.de.v0/context/_participation:0|name": "Susan Doe", + "conformance-ehrbase.de.v0/context/_participation:0/relationship|code": "10", + "conformance-ehrbase.de.v0/context/_participation:0/relationship|value": "mother", + "conformance-ehrbase.de.v0/context/_participation:0/relationship|terminology": "openehr" +} +---- + +[cols="5*", options="header"] +|=== +| Flat Path +| Flat type +| RM Path +| Required +| Note + +| `/relationship` +| <> +| relationship (when `performer` is `PARTY_RELATED`) +| (yes) +| Required when `performer` is a `PARTY_RELATED`; not present otherwise. +|=== + +NOTE: Implementation status — ehrbase reads and writes this path (`PartyRelatedStdConfig.addRelationship`); Better's `ParticipationToFlatMapper` currently treats the performer as `PARTY_IDENTIFIED` only and does not emit `relationship`. Producers that need cross-implementation portability for a `PARTY_RELATED` performer should either fall back to canonical RM JSON or limit usage to ehrbase-side flows until parity is established. + [[OBJECT_REF]] == OBJECT_REF From 5574be555810ca3b677cba7fe3d5cf622c892b7b Mon Sep 17 00:00:00 2001 From: Sebastian Iancu Date: Tue, 28 Apr 2026 14:47:08 +0200 Subject: [PATCH 09/10] Expand DV_PROPORTION table and fix `|normal_status` RM path (SPECITS-94) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Three rows that the JSON example in the spec already used were missing from (or wrong in) the DV_PROPORTION table: - `|precision` — RM `DV_PROPORTION.precision: Integer`. `0` implies integral, `-1` implies no limit. - `|accuracy` — RM `DV_AMOUNT.accuracy: Real` (inherited). - `|accuracy_is_percent` — RM `DV_AMOUNT.accuracy_is_percent: Boolean` (inherited). Selects whether `|accuracy` is a percentage or an absolute quantity. - `|normal_status` — RM Path was `normal_status` (which is a `CODE_PHRASE` per `DV_ORDERED`); corrected to `normal_status.code_string`. The FLAT carries only the code; the enclosing `CODE_PHRASE` terminology is implicitly `openehr` (ValueSet `normal_statuses`, codes `HHH`/`HH`/`H`/`N`/`L`/`LL`/`LLL`). Also fixed an unrelated typo in the existing `|magnitude_status` ValueSet note: `(",>,>=,<,<=,~)` -> `(=,>,>=,<,<=,~)` to include `=` and remove the stray opening quote. Verified against the relevant marshal/postprocessor sources: - ehrbase openEHR_SDK `DVProportionConfig.buildChildValues`: emits `numerator`, `denominator`, `type`, `precision`, plus the bare magnitude. - ehrbase `DvAmountPostprocessor.process`: emits `accuracy` and `accuracy_is_percent` for every `DV_AMOUNT` descendant. - ehrbase `DvOrderedPostprocessor.process`: emits `normal_status` as `CodePhrase::getCodeString` (code only). - Better `web-template` `DvProportionToFlatMapper`: emits `numerator`, `denominator`, `type`, bare magnitude (numerator/denominator); chains super for `magnitude_status` and `normal_status`. `DvOrderedToFlatMapper` writes `|normal_status = normalStatus?.codeString`. `DvProportionFactory` derives `precision` from the AM template constraint. Spec text remains implementation-neutral: it states the canonical RM mapping for each suffix without referring to which engines emit which fields. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../master00-amendment_record.adoc | 2 +- .../master05-rm_mapping.adoc | 24 ++++++++++++++++--- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/docs/simplified_formats/master00-amendment_record.adoc b/docs/simplified_formats/master00-amendment_record.adoc index e521e780..71555803 100644 --- a/docs/simplified_formats/master00-amendment_record.adoc +++ b/docs/simplified_formats/master00-amendment_record.adoc @@ -7,7 +7,7 @@ 4+^h|*ITS_REST Release (unreleased)* |[[latest_issue]]1.1.1 -|{spec_tickets}/SPECITS-94[SPECITS-94^]. Clarified Level Removal (attribute elision vs wrapper collapse) and `EVENT` rule; added `\|other` and `\|preferred_term` suffixes on `DV_CODED_TEXT`; fixed `LINK` (`\|target`) and `DV_MULTIMEDIA` (`\|mediatype`) mappings; corrected `EVENT_CONTEXT` table and added `PARTICIPATION` section; corrected PARTY `\|id_namespace` RM path; documented PARTICIPATION `/relationship` for `PARTY_RELATED` performer. +|{spec_tickets}/SPECITS-94[SPECITS-94^]. Clarified Level Removal (attribute elision vs wrapper collapse) and `EVENT` rule; added `\|other` and `\|preferred_term` suffixes on `DV_CODED_TEXT`; fixed `LINK` (`\|target`) and `DV_MULTIMEDIA` (`\|mediatype`) mappings; corrected `EVENT_CONTEXT` table and added `PARTICIPATION` section; corrected PARTY `\|id_namespace` RM path; documented PARTICIPATION `/relationship` for `PARTY_RELATED` performer; expanded `DV_PROPORTION` table (`\|precision`, `\|accuracy`, `\|accuracy_is_percent`; `\|normal_status` RM path). |REST WG |[[latest_issue_date]]28 Apr 2026 diff --git a/docs/simplified_formats/master05-rm_mapping.adoc b/docs/simplified_formats/master05-rm_mapping.adoc index b7abcc9e..58f84141 100644 --- a/docs/simplified_formats/master05-rm_mapping.adoc +++ b/docs/simplified_formats/master05-rm_mapping.adoc @@ -2470,6 +2470,12 @@ See RM specification of the https://specifications.openehr.org/releases/RM/lates | yes | ValueSet proportion_kind +| `\|precision` +| Integer +| precision +| no +| Number of decimal places to which `\|numerator` and `\|denominator` are expressed. Value `0` implies integral; `-1` implies no limit. + | | Real | magnitude @@ -2480,13 +2486,25 @@ See RM specification of the https://specifications.openehr.org/releases/RM/lates | String | magnitude_status | no -| ValueSet (",>,>=,<,\<=,~) +| ValueSet (=,>,>=,<,\<=,~) + +| `\|accuracy` +| Real +| accuracy +| no +| Half-range accuracy of measurement. Interpretation depends on `\|accuracy_is_percent`. A value of `0` means accuracy is 100% (no error). + +| `\|accuracy_is_percent` +| Boolean +| accuracy_is_percent +| no +| When `true`, `\|accuracy` is a percentage (0–100); when `false` or absent, `\|accuracy` is an absolute quantity in the same units as the value. | `\|normal_status` | String -| normal_status +| normal_status.code_string | no -| ValueSet normal_status +| ValueSet `normal_statuses` (codes `HHH`, `HH`, `H`, `N`, `L`, `LL`, `LLL`). The FLAT carries only the `code_string`; the underlying `CODE_PHRASE` terminology is implicitly `openehr`. | `/_normal_range` | <> From b7114a0bb6ba3becbac88edfac8990799ed4ec94 Mon Sep 17 00:00:00 2001 From: Sebastian Iancu Date: Tue, 28 Apr 2026 15:01:09 +0200 Subject: [PATCH 10/10] Fix temporal-types tables and sweep recurring DV row bugs (SPECITS-94) DV_DATE_TIME / DV_TIME copy-paste fixes: - DV_DATE_TIME header link `_dv_date_class[DV_DATE]` -> `_dv_date_time_class[DV_DATE_TIME]`. - DV_TIME header link `_dv_date_class[DV_DATE]` -> `_dv_time_class[DV_TIME]`. - DV_TIME first JSON example used `dv_date: "2022-01-12"` -> corrected to `dv_time: "13:22:34.000868+01:00"`. - Bare-path notes: - DV_DATE_TIME: "ISO8601 date" -> "ISO8601 date-time". - DV_TIME: "ISO8601 date" -> "ISO8601 time". (DV_DATE bare-path note left as "ISO8601 date".) Recurring sweep across DV_COUNT / DV_DATE / DV_DATE_TIME / DV_TIME / DV_DURATION / DV_QUANTITY (same fixes already applied to DV_PROPORTION): - `|magnitude_status` ValueSet note `(",>,>=,<,<=,~)` -> `(=,>,>=,<,<=,~)` (stray quote, missing `=`). - `|normal_status` RM Path `normal_status` -> `normal_status.code_string`, with note that the FLAT carries only the `code_string` and the enclosing `CODE_PHRASE` terminology is implicitly `openehr` (codes HHH, HH, H, N, L, LL, LLL). DV_COUNT row additions (mirroring DV_PROPORTION / DV_QUANTITY / DV_DURATION): - Added `|accuracy` (Real -> `accuracy`) and `|accuracy_is_percent` (Boolean -> `accuracy_is_percent`). DV_DURATION cosmetic: `|accuracy_is_percent` Flat-Path cell missing the `\|` formatting -> restored. Verified bare-path and inheritance dispatch against: - ehrbase openEHR_SDK `DvDateTimePostprocessor` / `DvTimePostprocessor` (operate on `term` itself, no suffix); `DvDateTimeRMUnmarshaller.handle` uses `setValue(currentTerm, null, ...)`. - ehrbase `DVCountConfig.buildChildValues` writes magnitude with `null` suffix (bare path). - ehrbase `StdFromCompositionWalker.findPostprocessors` walks the superclass chain -> a `DvCount` instance picks up `DvAmountPostprocessor` (emits `accuracy`, `accuracy_is_percent`), `DvQuantifiedPostprocessor` (`magnitude_status`), and `DvOrderedPostprocessor` (`normal_status` as `CodePhrase::getCodeString`, ranges). - ehrbase unmarshal `DvAmountPostprocessor` symmetrically reads `accuracy` and `accuracy_is_percent`. - Better `web-template` `DvCountToFlatMapper`, `DvDateTimeToFlatMapper`, `DvTimeToFlatMapper` all write `flatConversionContext[webTemplatePath]` (no suffix). Better's `DvOrderedToFlatMapper` writes `|normal_status` as `normalStatus?.codeString`. Spec text remains implementation-neutral. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../master00-amendment_record.adoc | 2 +- .../master05-rm_mapping.adoc | 60 +++++++++++-------- 2 files changed, 37 insertions(+), 25 deletions(-) diff --git a/docs/simplified_formats/master00-amendment_record.adoc b/docs/simplified_formats/master00-amendment_record.adoc index 71555803..64d6c959 100644 --- a/docs/simplified_formats/master00-amendment_record.adoc +++ b/docs/simplified_formats/master00-amendment_record.adoc @@ -7,7 +7,7 @@ 4+^h|*ITS_REST Release (unreleased)* |[[latest_issue]]1.1.1 -|{spec_tickets}/SPECITS-94[SPECITS-94^]. Clarified Level Removal (attribute elision vs wrapper collapse) and `EVENT` rule; added `\|other` and `\|preferred_term` suffixes on `DV_CODED_TEXT`; fixed `LINK` (`\|target`) and `DV_MULTIMEDIA` (`\|mediatype`) mappings; corrected `EVENT_CONTEXT` table and added `PARTICIPATION` section; corrected PARTY `\|id_namespace` RM path; documented PARTICIPATION `/relationship` for `PARTY_RELATED` performer; expanded `DV_PROPORTION` table (`\|precision`, `\|accuracy`, `\|accuracy_is_percent`; `\|normal_status` RM path). +|{spec_tickets}/SPECITS-94[SPECITS-94^]. Clarified Level Removal (attribute elision vs wrapper collapse) and `EVENT` rule; added `\|other` and `\|preferred_term` suffixes on `DV_CODED_TEXT`; fixed `LINK` (`\|target`) and `DV_MULTIMEDIA` (`\|mediatype`) mappings; corrected `EVENT_CONTEXT` table and added `PARTICIPATION` section; corrected PARTY `\|id_namespace` RM path; documented PARTICIPATION `/relationship` for `PARTY_RELATED` performer; expanded `DV_PROPORTION` table (`\|precision`, `\|accuracy`, `\|accuracy_is_percent`; `\|normal_status` RM path); fixed `DV_DATE_TIME` / `DV_TIME` headers and bare-path notes; swept recurring `\|magnitude_status` and `\|normal_status` row corrections across `DV_COUNT` / `DV_DATE` / `DV_DATE_TIME` / `DV_TIME` / `DV_DURATION` / `DV_QUANTITY`; added `\|accuracy` / `\|accuracy_is_percent` to `DV_COUNT`. |REST WG |[[latest_issue_date]]28 Apr 2026 diff --git a/docs/simplified_formats/master05-rm_mapping.adoc b/docs/simplified_formats/master05-rm_mapping.adoc index 58f84141..2b3ea4f9 100644 --- a/docs/simplified_formats/master05-rm_mapping.adoc +++ b/docs/simplified_formats/master05-rm_mapping.adoc @@ -2366,13 +2366,13 @@ See RM specification of the https://specifications.openehr.org/releases/RM/lates | String | magnitude_status | no -| ValueSet (",>,>=,<,\<=,~) +| ValueSet (=,>,>=,<,\<=,~) | `\|normal_status` | String -| normal_status +| normal_status.code_string | no -| ValueSet normal_status +| ValueSet `normal_statuses` (codes `HHH`, `HH`, `H`, `N`, `L`, `LL`, `LLL`). The FLAT carries only the `code_string`; the underlying `CODE_PHRASE` terminology is implicitly `openehr`. | `\|accuracy` | Real @@ -2564,13 +2564,25 @@ See RM specification of the https://specifications.openehr.org/releases/RM/lates | String | magnitude_status | no -| ValueSet (",>,>=,<,\<=,~) +| ValueSet (=,>,>=,<,\<=,~) | `\|normal_status` | String -| normal_status +| normal_status.code_string | no -| ValueSet normal_status +| ValueSet `normal_statuses` (codes `HHH`, `HH`, `H`, `N`, `L`, `LL`, `LLL`). The FLAT carries only the `code_string`; the underlying `CODE_PHRASE` terminology is implicitly `openehr`. + +| `\|accuracy` +| Real +| accuracy +| no +| Half-range accuracy of measurement. Interpretation depends on `\|accuracy_is_percent`. A value of `0` means accuracy is 100% (no error). + +| `\|accuracy_is_percent` +| Boolean +| accuracy_is_percent +| no +| When `true`, `\|accuracy` is a percentage (0–100); when `false` or absent, `\|accuracy` is an absolute quantity in the same units as the value. | `/_normal_range` | <> @@ -2635,13 +2647,13 @@ See RM specification of the https://specifications.openehr.org/releases/RM/lates | String | magnitude_status | no -| ValueSet (",>,>=,<,\<=,~) +| ValueSet (=,>,>=,<,\<=,~) | `\|normal_status` | String -| normal_status +| normal_status.code_string | no -| ValueSet normal_status +| ValueSet `normal_statuses` (codes `HHH`, `HH`, `H`, `N`, `L`, `LL`, `LLL`). The FLAT carries only the `code_string`; the underlying `CODE_PHRASE` terminology is implicitly `openehr`. | `/_normal_range` | <> @@ -2659,7 +2671,7 @@ See RM specification of the https://specifications.openehr.org/releases/RM/lates [[DV_DATE_TIME]] == DV_DATE_TIME -See RM specification of the https://specifications.openehr.org/releases/RM/latest/data_types.html#_dv_date_class[DV_DATE] class. +See RM specification of the https://specifications.openehr.org/releases/RM/latest/data_types.html#_dv_date_time_class[DV_DATE_TIME] class. [source,json] ---- @@ -2695,7 +2707,7 @@ See RM specification of the https://specifications.openehr.org/releases/RM/lates | String | value | Yes -| ISO8601 date +| ISO8601 date-time | `/_accuracy` | <> @@ -2707,13 +2719,13 @@ See RM specification of the https://specifications.openehr.org/releases/RM/lates | String | magnitude_status | no -| ValueSet (",>,>=,<,\<=,~) +| ValueSet (=,>,>=,<,\<=,~) | `\|normal_status` | String -| normal_status +| normal_status.code_string | no -| ValueSet normal_status +| ValueSet `normal_statuses` (codes `HHH`, `HH`, `H`, `N`, `L`, `LL`, `LLL`). The FLAT carries only the `code_string`; the underlying `CODE_PHRASE` terminology is implicitly `openehr`. | `/_normal_range` | <> @@ -2730,12 +2742,12 @@ See RM specification of the https://specifications.openehr.org/releases/RM/lates == DV_TIME -See RM specification of the https://specifications.openehr.org/releases/RM/latest/data_types.html#_dv_date_class[DV_DATE] class. +See RM specification of the https://specifications.openehr.org/releases/RM/latest/data_types.html#_dv_time_class[DV_TIME] class. [source,json] ---- { - "conformance-ehrbase.de.v0/conformance_section/conformance_observation/any_event:0/dv_date": "2022-01-12" + "conformance-ehrbase.de.v0/conformance_section/conformance_observation/any_event:0/dv_time": "13:22:34.000868+01:00" } ---- @@ -2766,7 +2778,7 @@ See RM specification of the https://specifications.openehr.org/releases/RM/lates | String | value | Yes -| ISO8601 date +| ISO8601 time | `/_accuracy` | <> @@ -2778,13 +2790,13 @@ See RM specification of the https://specifications.openehr.org/releases/RM/lates | String | magnitude_status | no -| ValueSet (",>,>=,<,\<=,~) +| ValueSet (=,>,>=,<,\<=,~) | `\|normal_status` | String -| normal_status +| normal_status.code_string | no -| ValueSet normal_status +| ValueSet `normal_statuses` (codes `HHH`, `HH`, `H`, `N`, `L`, `LL`, `LLL`). The FLAT carries only the `code_string`; the underlying `CODE_PHRASE` terminology is implicitly `openehr`. | `/_normal_range` | <> @@ -2847,7 +2859,7 @@ See RM specification of the https://specifications.openehr.org/releases/RM/lates | no | -| accuracy_is_percent +| `\|accuracy_is_percent` | Boolean | accuracy_is_percent | no @@ -2857,13 +2869,13 @@ See RM specification of the https://specifications.openehr.org/releases/RM/lates | String | magnitude_status | no -| ValueSet (",>,>=,<,\<=,~) +| ValueSet (=,>,>=,<,\<=,~) | `\|normal_status` | String -| normal_status +| normal_status.code_string | no -| ValueSet normal_status +| ValueSet `normal_statuses` (codes `HHH`, `HH`, `H`, `N`, `L`, `LL`, `LLL`). The FLAT carries only the `code_string`; the underlying `CODE_PHRASE` terminology is implicitly `openehr`. | `/_normal_range` | <>