CDA-FHIR-Maps (R4)
0.1.1 - CI build

CDA-FHIR-Maps (R4), published by ahdis. This is not an authorized publication; it is the continuous build for version 0.1.1). This version is based on the current content of https://github.com/hl7ch/cda-fhir-maps/ and changes regularly. See the Directory of published versions

Bundle to CDA-CH

Format(s):

Narrative view

map "http://fhir.ch/ig/cda-fhir-maps/StructureMap/BundleToCdaCh" = "BundleToCdaCh"

// CDA-CH document, 2.16.756.5.30.1.1.10.1.14
// 2020-01-16 Oliver Egger, copyright ahdis ag, Apache License
// CDA-CH:  https://art-decor.org/art-decor/decor-templates--hl7chcda-
// FHIR CH-Core: http://fhir.ch/ig/ch-core/index.html

uses "http://hl7.org/fhir/cda/StructureDefinition/ClinicalDocument" alias ClinicalDocument as target
uses "http://hl7.org/fhir/cda/StructureDefinition/Author" alias Author as target
uses "http://hl7.org/fhir/cda/StructureDefinition/RecordTarget" alias RecordTarget as target
uses "http://hl7.org/fhir/cda/StructureDefinition/DataEnterer" alias DataEnterer as target
uses "http://hl7.org/fhir/cda/StructureDefinition/AssignedEntity" alias AssignedEntity as target
uses "http://hl7.org/fhir/StructureDefinition/Bundle" alias Bundle as source
uses "http://hl7.org/fhir/StructureDefinition/Composition" alias Composition as source
uses "http://hl7.org/fhir/StructureDefinition/Person" alias Person as source

imports "http://fhir.ch/ig/cda-fhir-maps/StructureMap/FhirToCdaTypes"
imports "http://fhir.ch/ig/cda-fhir-maps/StructureMap/BundleToCda"

// source: http://build.fhir.org/ig/hl7ch/ch-core/branches/master/StructureDefinition-ch-core-document.html
// target: https://art-decor.org/art-decor/decor-templates--hl7chcda-?id=2.16.756.5.30.1.1.10.1.14
group BundleToCdaCh(source bundle : Bundle, target cda : ClinicalDocument) {
  bundle ->  cda.recordTarget as recordTarget,  cda.author as author then BundleToClinicalDocumentCh(bundle, recordTarget, author, cda) "bundle";
}

// source: http://build.fhir.org/ig/hl7ch/ch-core/branches/master/StructureDefinition-ch-core-document.html
// target: https://art-decor.org/art-decor/decor-templates--hl7chcda-?id=2.16.756.5.30.1.1.10.1.14
group BundleToClinicalDocumentCh(source bundle : Bundle, target recordTarget : RecordTarget, target author : Author, target cda : ClinicalDocument) extends BundleToClinicalDocument {
  bundle ->  author.templateId as templateId,  templateId.root = '2.16.756.5.30.1.1.10.9.23' "tempalteId";
  bundle ->  recordTarget.templateId as templateId,  templateId.root = '2.16.756.5.30.1.1.10.2.1' "tempalteId";
  bundle ->  cda.custodian as custodian,  custodian.templateId as templateId,  templateId.root = '2.16.756.5.30.1.1.10.2.3' "tempalteId";
  bundle -> cda.realmCode as realmCode then {
    bundle -> realmCode.code = 'CHE' "CHE";
  } "realmCode";
  bundle -> cda.templateId as templateId then {
    bundle -> templateId.root = '2.16.840.1.113883.10.12.2' "root";
  } "componentAsStructuredBody";
  bundle -> cda.templateId as templateId then {
    bundle -> templateId.root = '2.16.756.5.30.1.1.10.1.9' "root";
  } "0-structuredBody";
  bundle.entry as entry then {
    entry.resource as resource where $this.ofType(FHIR.Composition) then CompositionClinicalDocumentCH(bundle, resource, cda);
  };
}

// _________________________ Section Level Templates _________________________
// source: http://build.fhir.org/ig/hl7ch/ch-core/branches/master/StructureDefinition-ch-core-composition-definitions.html#Composition.section
// target: https://art-decor.org/art-decor/decor-templates--hl7chcda-?id=2.16.756.5.30.1.1.10.3.2
group SectionCdaRemarksCoded(source bundle : Bundle, source section : Section, target cdasection : CdaSection) extends SectionCdaSection {
  section ->  cdasection.templateId as templateId,  templateId.root = '2.16.756.5.30.1.1.10.3.2' "templateId";
  section ->  cdasection.entry as entry,  entry.act as act,  act.classCode = 'ACT',  act.moodCode = 'EVN' then {
    section ->  act.templateId as templateId,  templateId.root = '2.16.756.5.30.1.1.10.4.2' "templateId";
    section ->  act.templateId as templateId,  templateId.root = '2.16.840.1.113883.10.20.1.40' "templateId";
    section ->  act.templateId as templateId,  templateId.root = '1.3.6.1.4.1.19376.1.5.3.1.4.2' "templateId";
    section ->  act.code as code,  code.code = '48767-8',  code.codeSystem = '2.16.840.1.113883.6.1',  code.codeSystemName = 'LOINC',  code.displayName = 'Annotation comment' "code";
    // <span id="co1">
    section.text as text then {
      text.div as div ->  act.text as text,  text.reference as reference,  reference.value = ('#' + %div.substring(%div.indexOf('id') + %div.substring(%div.indexOf('id')).indexOf('\"') + 1, %div.substring(%div.indexOf('id') + %div.substring(%div.indexOf('id')).indexOf('\"') + 1).indexOf('\"'))) "id";
    };
    section ->  act.statusCode as statusCode,  statusCode.code = 'completed' "completed";
  } "entry";
}

group SectionCdaOriginalRepresentationObservationMedia(source binary : Binary, source section : Section, target cdasection : CdaSection) {
  section -> cdasection.entry as entry then {
    binary -> entry.typeCode = 'DRIV' "driv";
    binary ->  entry.observationMedia as observationMedia,  observationMedia.classCode = 'OBS',  observationMedia.moodCode = 'EVN' then {
      section.entry as entry then {
        entry.extension as extension where $this.url = 'http://hl7.org/fhir/StructureDefinition/narrativeLink' then {
          extension.valueUrl as valueUrl -> observationMedia.ID = valueUrl "reference";
        } "narrativeLink";
      };
      binary ->  observationMedia.templateId as templateId,  templateId.root = '2.16.756.5.30.1.1.10.4.83' "templateId";
      binary ->  observationMedia.value as value,  value.mediaType = '2.16.756.5.30.1.1.10.4.83',  value.representation = 'B64' then {
        binary.contentType as contentType -> value.mediaType = contentType;
        binary.data as data -> value.data = data;
        binary.language as lang ->  observationMedia.languageCode as languageCode,  languageCode.code = lang "lang";
        binary where $this.language.exists() = false ->  observationMedia.languageCode as languageCode,  languageCode.nullFlavor = 'UNK' "langUnknown";
      } "value";
    } "observationMedia";
  } "entry";
}

// source: http://build.fhir.org/ig/hl7ch/ch-core/branches/master/StructureDefinition-ch-core-composition-definitions.html#Composition.section
// target: https://art-decor.org/art-decor/decor-templates--hl7chcda-?id=2.16.756.5.30.1.1.10.1.14
// target: https://art-decor.org/art-decor/decor-templates--hl7chcda-?id=2.16.756.5.30.1.1.10.4.83
group SectionCdaOriginalRepresentation(source bundle : Bundle, source section : Section, target cdasection : CdaSection) extends SectionCdaSection {
  section ->  cdasection.templateId as templateId,  templateId.root = '2.16.756.5.30.1.1.10.3.45' "templateId";
  bundle.entry as entry then {
    entry.fullUrl where ($this in %section.entry.reference) and $this.startsWith('urn:uuid') then {
      entry.resource as binary then SectionCdaOriginalRepresentationObservationMedia(binary, section, cdasection) "patient";
    } "fullUrlAsUuid";
    entry.resource as binary where ('Binary' + '/' + $this.id) in %section.entry.reference then SectionCdaOriginalRepresentationObservationMedia(binary, section, cdasection) "patient";
  } "patient";
}

// _________________________ Entry Level Templates   ________________________
// _________________________ Header Level Templates _________________________
// source: http://build.fhir.org/ig/hl7ch/ch-core/branches/master/StructureDefinition-ch-core-composition-epr.html
// target: https://art-decor.org/art-decor/decor-templates--hl7chcda-?id=2.16.756.5.30.1.1.10.9.12
group PersonAssignedEntityWithId(source person : Person, target assignedEntity : AssignedEntity) {
  person.identifier as identifier -> assignedEntity.id as id then IdentifierII(identifier, id);
  person.address as address -> assignedEntity.addr as addr then AddressAD(address, addr);
  person.name as humanname ->  assignedEntity.assignedPerson as assignedPerson,  assignedPerson.name as en then HumanNameEN(humanname, en);
}

// _________________________ Template Type not specified  ___________________
// source: http://hl7.org/fhir/R4/person.html
// target: https://art-decor.org/art-decor/decor-templates--hl7chcda-?id=2.16.756.5.30.1.1.10.9.36
group CompositionClinicalDocumentCH(source bundle : Bundle, source composition : Composition, target cda : ClinicalDocument) {
  composition.type as type then {
    type.coding as coding where $this.system = 'http://snomed.info/sct' ->  cda.code as code,  code.translation as translation then CodingCE(coding, translation) "translation";
  };
  composition.confidentiality as conf where $this.extension.where(url = 'http://fhir.ch/ig/ch-core/StructureDefinition/ch-ext-epr-confidentialitycode').exists() -> cda.confidentialityCode as cdaconf then {
    conf.extension as extension then {
      extension.valueCodeableConcept as valueCodeableConcept then {
        valueCodeableConcept.coding as coding then CodingCE(coding, cdaconf);
      };
    };
  } "confidentialityCode";
  // If setId exists as Composition.ch-ext-epr-setid, then map to ClinicalDocument.setId
  composition.extension as ext where $this.url = 'http://fhir.ch/ig/ch-core/StructureDefinition/ch-ext-epr-setid' -> cda.setId as setId then {
    ext.valueIdentifier as valueIdentifier then IdentifierII(valueIdentifier, setId) "IdentifierII";
  } "setIdMapped";
  // If setId doesn't exist, create ClinicalDocument.setId as UUID upper case
  composition as composition where $this.extension.where(url = 'http://fhir.ch/ig/ch-core/StructureDefinition/ch-ext-epr-setid').exists() = false -> cda.setId as setId then {
    composition ->  uuid() as uuid,  setId.root = (%uuid.upper()) "upper";
  } "setIdCreated";
  // If versionNumber exists as Composition.ch-ext-epr-versionnumber, then map to ClinicalDocument.versionNumber
  composition.extension as ext where $this.url = 'http://fhir.ch/ig/ch-core/StructureDefinition/ch-ext-epr-versionnumber' -> cda.versionNumber as versionNumber then {
    ext.valueUnsignedInt as valueUnsignedInt then IntegerINT(valueUnsignedInt, versionNumber) "IntegerInt";
  } "versionNumberMapped";
  // If versionNumber doesn't exist, create ClinicalDocument.versionNumber = 1
  composition as composition where $this.extension.where(url = 'http://fhir.ch/ig/ch-core/StructureDefinition/ch-ext-epr-versionnumber').exists() = false -> cda.versionNumber as versionNumber then {
    composition -> versionNumber.value = '1' "versionNumber";
  } "versionNumberCreated";
  composition.extension as extension where $this.url = 'http://fhir.ch/ig/ch-core/StructureDefinition/ch-ext-epr-informationrecipient' -> cda.informationRecipient as informationRecipient then {
    extension -> informationRecipient.typeCode = 'PRCP' "PRCP";
    extension ->  informationRecipient.templateId as templateId,  templateId.root = '2.16.756.5.30.1.1.10.2.4' "templateId";
    extension.valueReference as valueReference then {
      bundle.entry as entry then {
        entry.resource as patient where (($this.id = %valueReference.reference.substring(8)) or ($this.id = %valueReference.reference.substring(9))) -> informationRecipient.intendedRecipient as intendedRecipient then {
          patient.address as address -> intendedRecipient.addr as addr then AddressAD(address, addr);
          patient.name as humanname ->  intendedRecipient.informationRecipient as informationRecipient2,  informationRecipient2.name as en then HumanNameEN(humanname, en);
        } "intendedRecipient";
        entry.resource as organization where (($this.id = %valueReference.reference.substring(13)) or ($this.id = %valueReference.reference.substring(9))) ->  informationRecipient.intendedRecipient as intendedRecipient,  intendedRecipient.receivedOrganization as receivedOrganization then Organization2CdaOrganization(organization, receivedOrganization) "organization";
      } "patient";
    };
  } "informationRecipient";
  composition.extension as extension where $this.url = 'http://fhir.ch/ig/ch-core/StructureDefinition/ch-ext-epr-dataenterer' -> cda.dataEnterer as dataEnterer then {
    extension ->  dataEnterer.templateId as templateId,  templateId.root = '2.16.756.5.30.1.1.10.2.7' "templateId";
    extension.extension as extensionTime where $this.url = 'http://fhir.ch/ig/ch-core/StructureDefinition/ch-ext-epr-time' then {
      extensionTime.valueDateTime as valueDateTime -> dataEnterer.time as time then DateTimeTS(valueDateTime, time) "DateTime";
    } "extensionTime";
    extension.extension as extensionPerson where $this.url = 'enterer' then {
      extensionPerson.valueReference as valueReference then {
        bundle.entry as entry then {
          // Person/ or urn:uuid:
          entry.resource as person where (($this.id = %valueReference.reference.substring(7)) or ($this.id = %valueReference.reference.substring(9))) -> dataEnterer.assignedEntity as assignedEntity then PersonAssignedEntityWithId(person, assignedEntity) "AssignedEntityWithId";
        } "person";
      };
    } "extensionPerson";
  } "dataEnterer";
  composition.section as section where $this.code.coding.where((system = 'http://loinc.org') and (code = '55108-5')) -> cda.component as component then {
    section -> component.contextConductionInd = true "contextConductionInd";
    section ->  component.structuredBody as structuredBody,  structuredBody.component as component,  component.section as cdasection then SectionCdaOriginalRepresentation(bundle, section, cdasection) "cdasection";
  } "SectionCdaOriginalRepresentation";
  composition.section as section where $this.code.coding.where((system = 'http://loinc.org') and (code = '48767-8')) -> cda.component as component then {
    section -> component.contextConductionInd = true "contextConductionInd";
    section ->  component.structuredBody as structuredBody,  structuredBody.component as component,  component.section as cdasection then SectionCdaRemarksCoded(bundle, section, cdasection) "cdasection";
  } "SectionRemarksCoded";
}