Cumuluz Translate Implementation Guide
0.1.0 - ci-build
Cumuluz Translate Implementation Guide - Local Development build (v0.1.0) built by the FHIR (HL7® FHIR® Standard) Build Tools. See the Directory of published versions
The runtime follows one consistent route:
STU3 source profile -> logical model -> R4 target profile
The service is profile-aware on both sides.
It does not flatten the problem into a generic resource-to-resource conversion where every Patient, Condition, or Procedure is treated as equivalent regardless of profile semantics.
That keeps the translation explicit when multiple ZIB or target-profile versions overlap in the same ecosystem.
The logical layer is the semantic handoff between source and target.
It exists to:
nl-core, eu-base, and EPS targets without pushing profile-specific resource mapping into the HTTP layerThe main mapping assets live under:
src/main/resources/mappings/structuremaps/zib2017-to-logicalsrc/main/resources/mappings/structuremaps/nlcore2017-to-logicalsrc/main/resources/mappings/structuremaps/bgz2017-to-logicalsrc/main/resources/mappings/structuremaps/pzp2017-to-logicalsrc/main/resources/mappings/structuremaps/eafspraak2017-to-logicalsrc/main/resources/mappings/structuremaps/pzp-questionnairesrc/main/resources/mappings/structuremaps/logical-to-eubasesrc/main/resources/mappings/structuremaps/logical-to-epssrc/main/resources/mappings/structuremaps/logical-to-nlcoresrc/main/resources/mappings/structuremaps/logical-to-pzpsrc/main/resources/mappings/structuremaps/logical-to-r4src/main/resources/mappings/structuremaps/sharedThe logical model definitions live under:
logical-models/input/fshThe published IG also includes the generated logical StructureDefinition artifacts so readers can inspect the actual intermediate model pages.
For the concrete map inventory, see Structure Maps. For the intermediate semantic layer, see Logical Models.
The .map files use FHIR StructureMap syntax and are parsed by HAPI, but the service executes them with its local deterministic StructureMap executor.
They should be read as visible mapping assets for this translator, not as a guarantee that every map will run unchanged on another StructureMap engine.
Porting the maps elsewhere would require equivalent support for the local logical models, local ConceptMaps, STU3-shaped source context, and the target-write behavior used by the local executor.
The HTTP layer is intentionally thin.
It is responsible for:
OperationOutcomeThe translation layer is responsible for:
It should not silently substitute a different profile family when the requested route is missing.
The validator is responsible for:
OperationOutcomeFor a single-resource $transform request, the runtime takes these steps:
Parameters resource.source resource and parse it with the STU3 parser.meta.profile.validationMode: enforce, report, or none.Parameters response containing the translated result, the resolved targetProfile, optional logical output, and optional validation outcome.For a Bundle $transform request, the same route resolution and mapping chain is applied per entry. Each entry supplies its source profile through entry.resource.meta.profile. The target can come from the entry-level translation-target-profile extension, the top-level targetProfile, or PZP profile-pair inference for PZP entries.
EPS document Bundle output is a special Bundle-level target. A STU3 source Bundle targeting http://hl7.eu/fhir/eps/StructureDefinition/bundle-eu-eps is translated entry by entry through the EPS resource maps, then assembled into a document Bundle with a Composition, section references, and stable fullUrls.
QuestionnaireResponse extraction is not part of $transform. It has its own operation because one completed form can produce multiple clinical resources.
The registry is the source of truth for supported profile pairs. It contains:
nl-core, eu-base, EPS, or base R4 targets where implementedACP-Patient routes to nl-core-Patient, patient-eu-core, and patient-eu-epsThe service deliberately reports unsupported route pairs instead of changing the target family behind the client's back. Current examples:
ACP-Procedure targets nl-core-Procedure-event, but not EU Base or EPS Procedure because those target profiles require performed timing that the PZP source profile does not requireThese are contract decisions, not missing controller conditionals.
Transform-time validation is controlled only by validationMode.
enforce validates the translated R4 result and blocks error or fatal issues.report validates and returns diagnostics without blocking the translated result.none skips transform-time validation.The $transform operation does not accept a validate parameter. That parameter belongs to QuestionnaireResponse extraction, while standalone validation uses POST /fhir/r4/$validate.
Validation is target-side R4 validation. Structural errors, max-cardinality errors, unknown profiles, and missing mapped target requirements remain blocking in enforce mode. The runtime only relaxes a narrow set of known offline terminology/package expansion issues where the mapped code is covered by local terminology fragments or installed examples; those relaxations are logged and counted in the validation summary.
The IG examples are kept profile-valid for publication. The nl-core Patient target map normalizes known STU3 BCP-47 communication-language codings to the ISO 639-1 coding shape expected by nl-core Patient, for example urn:ietf:bcp:47#nl-NL to urn:oid:1.0.639.1#nl.
Clients can discover the service in several ways:
CapabilityStatement at /fhir/stu3-r4/metadataOperationDefinition at /fhir/stu3-r4/OperationDefinition/bgz-transformBundle at /fhir/stu3-r4/translation-indexOperationDefinition at /fhir/OperationDefinition/extract-questionnaire-responseThe translation-index endpoint is especially useful when a client needs a machine-readable inventory of supported pairs instead of a narrative guide.
When route coverage changes, update these pages in the same change:
The runtime discovery endpoint /fhir/stu3-r4/translation-index should match the narrative matrix. If they differ, the registry and docs should be reconciled before publishing the IG.
This guide documents what the service actually supports now.
That includes:
nl-core or eu-base profile is available for that routeThis keeps the IG honest. It should describe the current contract first, then leave room for future expansion.
One practical consequence is that the examples can be richer than a minimal field list when that helps readers see which fields really survive translation and which ones are intentionally left behind.