POC - Mapping CDA to FHIR
0.1.0 - ci-build

POC - Mapping CDA to FHIR - Local Development build (v0.1.0) built by the FHIR (HL7® FHIR® Standard) Build Tools. See the Directory of published versions

## StructureMap: Mapping de CDAFr vers FHIR Bundle (A partir des sources de Oliver Egger)

Official URL: https://interop.esante.gouv.fr/ig/fhir/mappingcdafhir/StructureMap/CdaFrToBundle | Version: 0.1.0
Draft as of 2025-11-07 | Computable Name: CdaFrToBundle

Mapping de CDAFr vers FHIR Bundle (A partir des sources de Oliver Egger)

    map "https://interop.esante.gouv.fr/ig/fhir/mappingcdafhir/StructureMap/CdaFrToBundle" = "CdaFrToBundle"

    // Mapping de CDAFr vers FHIR Bundle (A partir des sources de Oliver Egger)

    uses "http://hl7.org/cda/stds/core/StructureDefinition/ClinicalDocument" alias ClinicalDocument as source
    uses "http://hl7.org/cda/stds/core/StructureDefinition/Section" alias Section as source
    uses "http://hl7.org/cda/stds/core/StructureDefinition/PatientRole" alias PatientRole as source
    uses "http://hl7.org/cda/stds/core/StructureDefinition/DataEnterer" alias DataEnterer as source
    uses "http://hl7.org/fhir/StructureDefinition/Bundle" alias Bundle as target
    uses "http://hl7.org/fhir/StructureDefinition/Composition" alias Composition as target
    uses "http://hl7.org/fhir/StructureDefinition/Patient" alias Patient as target
    uses "http://hl7.org/fhir/StructureDefinition/Person" alias Person as target
    uses "http://hl7.org/fhir/StructureDefinition/Practitioner" alias Practitioner as target
    uses "http://hl7.org/fhir/StructureDefinition/PractitionerRole" alias PractitionerRole as target
    uses "http://hl7.org/fhir/StructureDefinition/Organization" alias Organization as target

    imports "https://interop.esante.gouv.fr/ig/fhir/mappingcdafhir/StructureMap/CdaToFHIRTypes"
    imports "https://interop.esante.gouv.fr/ig/fhir/mappingcdafhir/StructureMap/CdaToBundle"

    // _________________________ Document Level Template  _________________________
    // source: https://art-decor.org/art-decor/decor-templates--hl7chcda-?id=2.16.756.5.30.1.1.10.1.14
    // target: http://build.fhir.org/ig/hl7ch/ch-core/branches/master/StructureDefinition-ch-core-document.html
    group CdaFrToBundle(source cda : ClinicalDocument, target bundle : Bundle) {
      cda ->  bundle.entry as e,  e.resource = create('Composition') as composition,  composition.id = uuid() as uuid,  e.fullUrl = append('urn:uuid:', uuid),  bundle.entry as e2,  e2.resource = create('Patient') as patient,  patient.id = uuid() as uuid2,  e2.fullUrl = append('urn:uuid:', uuid2) then ClinicalDocumentFrToBundle(cda, patient, composition, bundle) "ClinicalDocumentToBody";
    }

    // source: https://art-decor.org/art-decor/decor-templates--hl7chcda-?id=2.16.756.5.30.1.1.10.1.14
    // target: http://build.fhir.org/ig/hl7ch/ch-core/branches/master/StructureDefinition-ch-core-document.html
    // group ClinicalDocumentFrToBundle(source cda : ClinicalDocument, target patient : Patient, target composition : Composition, target bundle : Bundle)
    // extends ClinicalDocumentToBundle {
    // cda then ClinicalDocumentCompositionFr(cda, composition, patient, bundle) "composition";
    // cda.component as component then {
    // component.structuredBody as body then {
    // body.component as component then {
    // component.section as srcSection where (templateId.where(root='2.16.756.5.30.1.1.10.3.2')) -> composition.section as tgtSection
    // then ClinicalDocumentSection(cda, srcSection, patient, tgtSection, bundle);
    // component.section as srcSection where (templateId.where(root='2.16.756.5.30.1.1.10.3.45')) -> composition.section as tgtSection
    // then SectionOriginalRepresentation(cda, srcSection, patient, tgtSection, bundle);
    // } "component";
    // } "body";
    // } "component";
    // }
    // _________________________ Section Level Templates _________________________
    // source: https://art-decor.org/art-decor/decor-templates--hl7chcda-?id=2.16.756.5.30.1.1.10.1.14
    // target: http://build.fhir.org/ig/hl7ch/ch-core/branches/master/StructureDefinition-ch-core-composition-definitions.html#Composition.section
    // TODO: not excplicitly modeled in CH-Core
    group SectionOriginalRepresentation(source cda : ClinicalDocument, source src : Section, source patient : Patient, target tgt, target bundle : Bundle) extends ClinicalDocumentSection {
      src.entry as cdaEntry ->  bundle.entry as e,  e.resource = create('Binary') as binary,  binary.id = uuid() as uuid,  e.fullUrl = append('urn:uuid:', uuid) as urnuuid,  tgt.entry = create('Reference') as reference,  reference.reference = urnuuid then {
        cdaEntry.observationMedia as observationMedia then {
          observationMedia then ObservationMedia(observationMedia, binary) "observationMedia";
          observationMedia.ID as value -> reference.extension as ext then NarrativeLink(value, ext) "narrativeLink";
        };
      } "cdaEntry";
    }

    // _________________________ Entry Level Templates   ________________________
    // source: https://art-decor.org/art-decor/decor-templates--hl7chcda-?id=2.16.756.5.30.1.1.10.4.83
    // TODO: not excplicitly modeled in CH-Core
    group ObservationMedia(source observationMedia, target binary : Binary) {
      observationMedia.value as value then {
        value.mediaType as mediaType -> binary.contentType = mediaType "contentType";
        value -> binary.data = (value.dataBase64Binary) "dataString";
      };
      observationMedia.languageCode as languageCode then {
        languageCode.code as lang -> binary.language = lang "lang";
      };
    }

    // _________________________ Header Level Templates _________________________
    // source: https://art-decor.org/art-decor/decor-templates--hl7chcda-?id=2.16.756.5.30.1.1.10.9.36
    // target: http://build.fhir.org/ig/hl7ch/ch-core/branches/master/StructureDefinition-ch-ext-epr-confidentialitycode.html
    group ChExtEprConfidentialityCode(source src : CE, target ext : Extension) {
      src -> ext.url = 'http://fhir.ch/ig/ch-core/StructureDefinition/ch-ext-epr-confidentialitycode' "url";
      src -> ext.value = create('CodeableConcept') as value then CECodeableConcept(src, value) "code";
    }

    // source: https://art-decor.org/art-decor/decor-templates--hl7chcda-?id=2.16.756.5.30.1.1.10.9.36
    // target: http://build.fhir.org/ig/hl7ch/ch-core/branches/master/StructureDefinition-ch-ext-epr-informationrecipient.html
    group ChExtEprInformationRecipient(source src : IntendedRecipient, target patient : Patient, target ext : Extension) {
      src -> ext.url = 'http://fhir.ch/ig/ch-core/StructureDefinition/ch-ext-epr-informationrecipient' "url";
      src ->  ext.value = create('Reference') as reference,  reference.reference = ('urn:uuid:' + %patient.id) "value";
      src.addr as addr -> patient.address as address then ADAddress(addr, address) "address";
      src.informationRecipient as informationRecipient then {
        informationRecipient.name as cdaname -> patient.name as fhirname then ENHumanName(cdaname, fhirname);
      };
    }

    // source: https://art-decor.org/art-decor/decor-templates--hl7chcda-?id=2.16.756.5.30.1.1.10.9.36
    // target: http://build.fhir.org/ig/hl7ch/ch-core/branches/master/StructureDefinition-ch-ext-epr-informationrecipient.html
    group ChExtEprInformationRecipientOrganization(source src : IntendedRecipient, target organization : Organization, target ext : Extension) {
      src -> ext.url = 'http://fhir.ch/ig/ch-core/StructureDefinition/ch-ext-epr-informationrecipient' "url";
      src ->  ext.value = create('Reference') as reference,  reference.reference = ('urn:uuid:' + %organization.id) "value";
      src.receivedOrganization as receivedOrganization then ClinicalDocumentOrganization(receivedOrganization, organization) "organization";
    }

    // source: https://art-decor.org/art-decor/decor-templates--hl7chcda-?section=templates&id=2.16.756.5.30.1.1.10.2.7
    // target: http://build.fhir.org/ig/hl7ch/ch-core/StructureDefinition-ch-ext-epr-dataenterer.html
    group ChExtEprDataEnterer(source src : DataEnterer, target bundle : Bundle, target practitionerRole : PractitionerRole, target ext : Extension) {
      src -> ext.url = 'http://fhir.ch/ig/ch-core/StructureDefinition/ch-ext-epr-dataenterer' "url";
      src.assignedEntity as assignedEntity ->  ext.extension as ext,  ext.url = 'enterer',  ext.value = create('Reference') as reference,  reference.reference = ('urn:uuid:' + %practitionerRole.id) "PractitionerRole";
      src.time as time -> ext.extension as exttime then ChExtEprTime(time, exttime);
      src.assignedEntity as assignedEntity then {
        assignedEntity ->  bundle.entry as e,  e.resource = create('Practitioner') as practitioner,  practitioner.id = uuid() as uuid,  e.fullUrl = append('urn:uuid:', uuid),  practitionerRole.practitioner = create('Reference') as reference,  reference.reference = append('urn:uuid:', uuid) then ClinicalDocumentEntityPractitioner(assignedEntity, practitioner) "Practitioner";
        assignedEntity.representedOrganization as representedOrganization ->  bundle.entry as e,  e.resource = create('Organization') as organization,  organization.id = uuid() as uuid2,  e.fullUrl = append('urn:uuid:', uuid2),  practitionerRole.organization = create('Reference') as referenceOrg,  referenceOrg.reference = append('urn:uuid:', uuid2) then ClinicalDocumentOrganization(representedOrganization, organization) "Organization";
      };
    }

    // // _________________________ Template Type not specified  ___________________
    // // source: https://art-decor.org/art-decor/decor-templates--hl7chcda-?id=2.16.756.5.30.1.1.10.9.36
    // // target: http://build.fhir.org/ig/hl7ch/ch-core/branches/master/StructureDefinition-ch-core-composition-epr.html
    group ClinicalDocumentCompositionFr(source src : ClinicalDocument, target tgt : Composition, target patientResource : Patient, target bundle : Bundle) {
      src.confidentialityCode as confidentialityCode then {
        confidentialityCode.code as v where ('http://fhir.ch/ig/ch-epr-term/ValueSet/DocumentEntry.confidentialityCode'.resolve().compose.include.concept.where($this.code = src.confidentialityCode.code).exists()) ->  tgt.confidentiality = translate(v, 'http://fhir.ch/ig/ch-core/ConceptMap/documententry-confidentialitycode-to-fhir', 'code') as fhirconf,  fhirconf.extension as ext then ChExtEprConfidentialityCode(confidentialityCode, ext) "confCode";
      };
      src.informationRecipient as informationRecipient -> bundle.entry as e then {
        informationRecipient.intendedRecipient as intendedRecipient where $this.receivedOrganization.exists() = false ->  e.resource = create('Patient') as recipient,  recipient.id = uuid() as uuid,  e.fullUrl = append('urn:uuid:', uuid),  tgt.extension as ext then ChExtEprInformationRecipient(intendedRecipient, recipient, ext) "informationRecipient";
        informationRecipient.intendedRecipient as intendedRecipient then {
          intendedRecipient.receivedOrganization ->  e.resource = create('Organization') as recipient,  recipient.id = uuid() as uuid2,  e.fullUrl = append('urn:uuid:', uuid2),  tgt.extension as ext then ChExtEprInformationRecipientOrganization(intendedRecipient, recipient, ext) "informationRecipientOrganization";
        } "intendedRecipientAsOrganization";
      } "entry";
      src.dataEnterer as dataEnterer ->  bundle.entry as e,  e.resource = create('PractitionerRole') as practitionerRole,  practitionerRole.id = uuid() as uuid,  e.fullUrl = append('urn:uuid:', uuid),  tgt.extension as ext then ChExtEprDataEnterer(dataEnterer, bundle, practitionerRole, ext);
    }