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

StructureMap: CDA-CH-EMED to Bundle

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

// Medication Entries
// 2020-10-30 Oliver Egger, copyright ahdis ag, Apache License
// CDA-CH-EMED:  https://art-decor.org/art-decor/decor-project--cdachemed-
// FHIR CH-EMED: http://fhir.ch/ig/ch-emed/index.html

uses "http://hl7.org/fhir/cda/StructureDefinition/ClinicalDocument" alias ClinicalDocument as source
uses "http://hl7.org/fhir/cda/StructureDefinition/AssignedAuthor" alias AssignedAuthor as source
uses "http://hl7.org/fhir/cda/StructureDefinition/AssignedEntity" alias AssignedEntity as source
uses "http://hl7.org/fhir/cda/StructureDefinition/Author" alias Author as source
uses "http://hl7.org/fhir/cda/StructureDefinition/CustodianOrganization" alias CustodianOrganization as source
uses "http://hl7.org/fhir/cda/StructureDefinition/IVL_TS" alias IVL_TS as source
uses "http://hl7.org/fhir/cda/StructureDefinition/EIVL_TS" alias EIVL_TS as source
uses "http://hl7.org/fhir/cda/StructureDefinition/Observation" alias Observation as source
uses "http://hl7.org/fhir/cda/StructureDefinition/PatientRole" alias PatientRole as source
uses "http://hl7.org/fhir/cda/StructureDefinition/RecordTarget" alias RecordTarget as source
uses "http://hl7.org/fhir/cda/StructureDefinition/Section" alias Section as source
uses "http://hl7.org/fhir/cda/StructureDefinition/SubstanceAdministration" alias SubstanceAdministration as source
uses "http://hl7.org/fhir/cda/StructureDefinition/SXPR_TS" alias SXPR_TS as source
uses "http://hl7.org/fhir/StructureDefinition/Bundle" alias Bundle as target
uses "http://hl7.org/fhir/StructureDefinition/Composition" alias Composition as produced
uses "http://hl7.org/fhir/StructureDefinition/Patient" alias Patient as produced
uses "http://hl7.org/fhir/StructureDefinition/Practitioner" alias Practitioner as produced
uses "http://hl7.org/fhir/StructureDefinition/Organization" alias Organization as produced
uses "http://hl7.org/fhir/StructureDefinition/MedicationStatement" alias MedicationStatement as produced
uses "http://hl7.org/fhir/StructureDefinition/Dosage" alias Dosage as produced
uses "http://hl7.org/fhir/StructureDefinition/Observation" alias Observation as produced

imports "http://fhir.ch/ig/cda-fhir-maps/StructureMap/CdaToFhirTypes"
imports "http://fhir.ch/ig/cda-fhir-maps/StructureMap/CdaToBundle"
imports "http://fhir.ch/ig/cda-fhir-maps/StructureMap/CdaChToBundle"

// source: https://art-decor.org/art-decor/decor-templates--cdachemed-?section=templates&id=2.16.756.5.30.1.1.10.4.2
// target: Annotation note (e.g. http://build.fhir.org/ig/hl7ch/ch-emed/branches/master/StructureDefinition-ch-emed-medicationstatement.html)
group AnnotationComment(source section : Section, source act : Act, target note : Annotation) {
  act.text as text then {
    text.data as data -> note.text = data "level3";
    text.reference as reference then {
      reference.value as value -> note.extension as ext then NarrativeLink(value, ext) "narrativeLink";
    };
  };
}

// source: https://art-decor.org/art-decor/decor-templates--cdachemed-?section=templates&id=2.16.756.5.30.1.1.10.4.33
// target: http://build.fhir.org/ig/hl7ch/ch-emed/branches/master/StructureDefinition-ch-emed-medicationdispense.html
group ManufacturedMaterialEntryContentModuleDispense(source src : Supply, target medicationDispense : MedicationDispense, target medication : Medication) {
  src ->  medication.id = 'med',  medicationDispense.medication = create('Reference') as vt,  vt.reference = '#med' "medication";
  // quantity value (number of packages)
  src.quantity as quantity -> medicationDispense.quantity as medDispQuantity then {
    // IHE-DIS: If the product-element contains package information, the unit attribute is not be present
    quantity.value as value -> medDispQuantity.value = value;
    // IHE-DIS: If the product-element does not contain package information, the unit attribut is present and the value SHALL be out of the UCUM code system
    quantity.unit as unit then {
      unit -> medDispQuantity.unit = unit "unit";
      unit -> medDispQuantity.system = 'http://unitsofmeasure.org' "ucum";
      unit -> medDispQuantity.code = unit "code";
    };
  };
  src.product as product then {
    product.manufacturedProduct as manufacturedProduct then {
      manufacturedProduct.manufacturedMaterial as manufacturedMaterial then {
        manufacturedMaterial.name as name where asContent.exists() = false ->  medication.code as fhircode,  fhircode.text = (%manufacturedMaterial.name.other) "code";
        manufacturedMaterial.asContent as asContent then {
          asContent.containerPackagedMedicine as containerPackagedMedicine then {
            containerPackagedMedicine.code as code -> medication.code as fhircode share medcode then CECodeableConcept(code, fhircode);
            containerPackagedMedicine.name as name -> medication.code as fhircode share medcode then {
              name -> fhircode.text = (%name.other) "text";
            } "text";
            containerPackagedMedicine.formCode as formCode -> medication.form as form then CECodeableConcept(formCode, form);
            // Package size
            containerPackagedMedicine.capacityQuantity as capacityQuantity ->  medication.amount = create('Ratio') as ratio,  ratio.denominator = create('Quantity') as denominator,  denominator.value = '1',  denominator.unit = 'Package',  denominator.system = 'http://unitsofmeasure.org',  denominator.code = '{Package}',  ratio.numerator = create('Quantity') as quantity then EmedPQQuantity(capacityQuantity, quantity);
          };
        };
        manufacturedMaterial.ingredient as ingredient -> medication.ingredient as ing then {
          ingredient.quantity as quantity -> ing.strength = create('Ratio') as strength then EmedRTOPQPQRatio(quantity, strength) "strength";
          ingredient.ingredient as medingredient then {
            medingredient.code as code ->  ing.item = create('CodeableConcept') as ingcode,  ingcode.text = (%medingredient.name.other) then CECodeableConcept(code, ingcode) "ingredientCode";
          };
        };
      };
    };
    // dosage for normal dosing, as no sequences are present there
    src.entryRelationship as entry then {
      entry.substanceAdministration as substanceAdministration then {
        substanceAdministration where $this.entryRelationship.sequenceNumber.exists() = false -> medicationDispense.dosageInstruction as dosage then DosageInstructionsStartStopFrequency(substanceAdministration, dosage) "dosage";
      };
    } "entry";
  };
}

group EmedPQQuantity(source src : PQ, target tgt : Quantity) {
  src.value as value -> tgt.value = value;
  src.unit as unit -> tgt.code = unit;
  src.unit as unit -> tgt.system = ('http://fhir.ch/ig/ch-emed/ValueSet/UnitCode'.resolve().compose.include.where(concept.where(code = %unit)).system);
  src.unit as unit -> tgt.unit = ('http://fhir.ch/ig/ch-emed/ValueSet/UnitCode'.resolve().compose.include.concept.where(code = %unit).display);
}

group EmedRTOPQPQRatio(source src : RTO_PQ_PQ, target tgt : Ratio) {
  src.numerator as numerator -> tgt.numerator as targetNumerator then EmedPQQuantity(numerator, targetNumerator);
  src.denominator as denominator -> tgt.denominator as targetDenominator then EmedPQQuantity(denominator, targetDenominator);
}

// source: https://art-decor.org/art-decor/decor-templates--cdachemed-?section=templates&id=2.16.756.5.30.1.1.10.4.33
// target: http://build.fhir.org/ig/hl7ch/ch-emed/branches/master/StructureDefinition-ch-emed-medicationstatement.html
group ManufacturedMaterialEntryContentModuleStatement(source src : SubstanceAdministration, target medicationStatement : MedicationStatement, target medication : Medication) {
  src ->  medication.id = 'med',  medicationStatement.medication = create('Reference') as vt,  vt.reference = '#med' "medication";
  src.consumable as consumable then {
    consumable.manufacturedProduct as manufacturedProduct then {
      manufacturedProduct.manufacturedMaterial as manufacturedMaterial then {
        manufacturedMaterial.name as name where asContent.exists() = false ->  medication.code as fhircode,  fhircode.text = (%manufacturedMaterial.name.other) "code";
        manufacturedMaterial.asContent as asContent then {
          asContent.containerPackagedMedicine as containerPackagedMedicine then {
            containerPackagedMedicine.code as code -> medication.code as fhircode share medcode then CECodeableConcept(code, fhircode);
            containerPackagedMedicine.name as name -> medication.code as fhircode share medcode then {
              name -> fhircode.text = (%name.other) "text";
            } "text";
            containerPackagedMedicine.formCode as formCode -> medication.form as form then CECodeableConcept(formCode, form);
            // Package size
            containerPackagedMedicine.capacityQuantity as capacityQuantity ->  medication.amount = create('Ratio') as ratio,  ratio.denominator = create('Quantity') as denominator,  denominator.value = '1',  denominator.unit = 'Package',  denominator.system = 'http://unitsofmeasure.org',  denominator.code = '{Package}',  ratio.numerator = create('Quantity') as quantity then EmedPQQuantity(capacityQuantity, quantity);
          };
        };
        manufacturedMaterial.ingredient as ingredient -> medication.ingredient as ing then {
          ingredient.quantity as quantity -> ing.strength = create('Ratio') as strength then EmedRTOPQPQRatio(quantity, strength) "strength";
          ingredient.ingredient as medingredient then {
            medingredient.code as code ->  ing.item = create('CodeableConcept') as ingcode,  ingcode.text = (%medingredient.name.other) then CECodeableConcept(code, ingcode) "ingredientCode";
          };
        };
      };
    };
    // dosage for normal dosing, as no sequences are present there
    src where $this.entryRelationship.sequenceNumber.exists() = false -> medicationStatement.dosage as dosage then DosageInstructionsStartStopFrequency(src, dosage) "dosage";
  };
}

// source: https://art-decor.org/art-decor/decor-templates--cdachemed-?section=templates&id=2.16.756.5.30.1.1.10.4.34
// target: http://build.fhir.org/ig/hl7ch/ch-emed/branches/master/StructureDefinition-ch-emed-medicationstatement.html
group MedicationTreatmentPlanItemEntryContentModule(source section : Section, source src : SubstanceAdministration, source patient : Patient, target medicationStatement : MedicationStatement) {
  // src.templateId as template then TemplateID(template, medicationStatement) "templateId";
  src.id -> medicationStatement.identifier;
  patient ->  medicationStatement.subject = create('Reference') as reference,  reference.reference = ('urn:uuid:' + %patient.id) "patient";
  src -> medicationStatement.status = 'completed' "completed";
  src.text as text then {
    text.reference as reference then {
      reference.value as value -> medicationStatement.extension as ext then NarrativeLink(value, ext) "narrativeLink";
    };
  };
  src -> medicationStatement.contained = create('Medication') as medication then ManufacturedMaterialEntryContentModuleStatement(src, medicationStatement, medication) "medication";
  src.entryRelationship as entry where typeCode = 'RSON' then {
    entry.observation as observation -> medicationStatement.reasonCode as reasonCode then TreatmentReasonEntryContentModule(section, observation, reasonCode) "reasonCode";
  } "41";
  src.entryRelationship as entry where ((typeCode = 'COMP') and (substanceAdministration.templateId.root = '2.16.756.5.30.1.1.10.4.52')) -> medicationStatement.dosage as dosage then DosageInstructionsNonStructuredEntryContentModule(section, entry, dosage) "52";
  src.entryRelationship as entry where ((typeCode = 'COMP') and (sequenceNumber.value >= 0)) -> medicationStatement.dosage as dosage then DosageInstructionsEntryDosageChange(src, entry, dosage) "36";
  src.entryRelationship as entry where ((typeCode = 'REFR') and substanceAdministration.templateId.where(root = '1.3.6.1.4.1.19376.1.9.1.3.10').exists()) -> medicationStatement.extension as ext then MTPReferenceEntryContentModule(entry, ext) "MTPReferenceEntry";
  src.entryRelationship as entry where ((typeCode = 'COMP') and act.templateId.where(root = '2.16.756.5.30.1.1.10.4.2').exists()) then {
    entry.act as act -> medicationStatement.note as note then AnnotationComment(section, act, note) "annotation";
  } "2";
  src.entryRelationship as entry where ((typeCode = 'COMP') and act.templateId.where(root = '1.3.6.1.4.1.19376.1.9.1.3.9.1').exists()) then {
    entry.act as act -> medicationStatement as medicationStatement then SubstitutionStatement(act, medicationStatement) "substitution";
  } "1";
}

// source https://art-decor.org/art-decor/decor-templates--ch-pharm-?id=2.16.756.5.30.1.1.10.4.36
// target: http://fhir.ch/ig/ch-emed/StructureDefinition/ch-emed-dosage-structured-split
// dosage for split dosing, with sequences
group DosageInstructionsEntryDosageChange(source src : substanceAdministration, source entry : entryRelationship, target dosage : Dosage) {
  entry.sequenceNumber as sequenceNumber then {
    sequenceNumber.value as val -> dosage.sequence = val;
  };
  src as src -> dosage as dosage then EffectiveTimeStartEnd(src, dosage) "effectiveTimeStartEnd";
  entry.substanceAdministration as src -> dosage as dosage then EffectiveTimeWhen(src, dosage) "effectiveTimeWhen";
  src.routeCode as routeCode -> dosage.route as route then CECodeableConcept(routeCode, route);
  entry.substanceAdministration as src -> dosage as dosage then DoseQuantity(src, dosage) "doseQuantity";
}

// effective time start & end for dosage
group EffectiveTimeStartEnd(source src : substanceAdministration, target dosage : Dosage) {
  src.effectiveTime : IVL_TS as effectiveTime -> dosage.timing as timing share sharetiming then {
    effectiveTime -> timing.repeat as repeat then {
      effectiveTime -> repeat.bounds = create('Period') as period then {
        effectiveTime.low as low then {
          low.value as lowDate -> period.start = lowDate "lowDate";
        };
        effectiveTime.high as high then {
          high.value as highDate -> period.end = highDate "highDate";
        };
      } "period";
    } "repeat";
  } "effectiveTime-IVL-TS";
}

// effective time when for dosage
group EffectiveTimeWhen(source src : substanceAdministration, target dosage : Dosage) {
  src.effectiveTime : EIVL_TS as effectiveTime -> dosage.timing as timing share sharetiming then {
    effectiveTime -> timing.repeat as repeat then {
      effectiveTime.event as event then {
        event.code as code -> repeat.when = code;
      };
    } "repeat";
  } "effectiveTime-EIVL-TS";
  src.effectiveTime : SXPR_TS as effectiveTime -> dosage.timing as timing share sharetiming then {
    effectiveTime -> timing.repeat as repeat then {
      effectiveTime.comp as comp then {
        comp.event as event then {
          event.code as code -> repeat.when = code;
        };
      };
    } "repeat";
  } "effectiveTime-SXPR-TS";
}

// source: https://art-decor.org/art-decor/decor-templates--cdachemed-?section=templates&id=2.16.756.5.30.1.1.10.4.41
// target: reasonCode Coding (e.g. http://build.fhir.org/ig/hl7ch/ig/ch-emed/StructureDefinition/ch-emed-medicationstatement)
group TreatmentReasonEntryContentModule(source section : Section, source observation : Observation, target reasonCode : Coding) {
  // extraxt text (Bluthochdruck) from id #mtpc.1.reason in section text <td ID="mtpc.1.reason">Bluthochdruck</td>
  observation.text as text then {
    text.data as data -> reasonCode.text = data "level3";
    text.reference as reference then {
      reference.value as value -> reasonCode.extension as ext then NarrativeLink(value, ext) "narrativeLink";
    };
  };
}

// source: https://art-decor.org/art-decor/decor-templates--ch-pharm-?section=templates&id=2.16.756.5.30.1.1.10.4.45
// target: http://build.fhir.org/ig/hl7ch/ch-emed/branches/master/StructureDefinition-ch-emed-ext-treatmentplan.html
group MTPReferenceEntryContentModule(source entryrelationship, target ext : Extension) {
  entryrelationship -> ext.url = 'http://fhir.ch/ig/ch-emed/StructureDefinition/ch-emed-ext-treatmentplan' "url";
  entryrelationship.substanceAdministration as substanceAdministration then {
    substanceAdministration.id as id -> ext.extension as ext then InnerExtensionId(id, ext) "innerExtensionId";
    substanceAdministration.reference as reference then {
      reference.externalDocument as externalDocument then {
        externalDocument.id as id -> ext.extension as ext then InnerExtensionExternalDocumentId(id, ext) "innerExtensionExternalDocumentId";
      };
    } "substanceAdministration";
  } "id";
}

// source: https://art-decor.org/art-decor/decor-templates--ch-pharm-?section=templates&id=2.16.756.5.30.1.1.10.4.52
// target: http://build.fhir.org/ig/hl7ch/ch-emed/branches/master/StructureDefinition-ch-emed-dosage-nonstructured.html
group DosageInstructionsNonStructuredEntryContentModule(source section : Section, source entry : Element, target dosage : Dosage) {
  // see MedicationTreatmentPlanItemEntryContentModule
  entry.substanceAdministration as observation then {
    observation.text as text then {
      text.data as data -> dosage.text = data "level3";
      text.reference as reference then {
        reference.value as value -> dosage.extension as ext then NarrativeLink(value, ext) "narrativeLink";
      };
    };
  } "observation";
}

// source: Substitution act Contains 1.3.6.1.4.1.19376.1.9.1.3.9.2 IHE Substitution Act Content Module
// target: http://build.fhir.org/ig/hl7ch/ch-emed/StructureDefinition-ch-emed-medicationdispense.html
group SubstitutionDispense(source act : Act, target medicationDispense : MedicationDispense) {
  act -> medicationDispense.substitution as substitution then {
    act ->  substitution.wasSubstituted as wasSubstituted,  wasSubstituted.value = 'true' "wasSubstituted";
    // act.code as code -> substitution.type as type then CECodeableConcept(code, type) "type";
    act.code as actCode ->  substitution.type as type,  type.coding as coding then {
      actCode ->  coding.system as systemCC,  systemCC.value = 'http://terminology.hl7.org/CodeSystem/v3-substanceAdminSubstitution' "system";
      actCode.code as code ->  coding.code as codeCC,  codeCC.value = code;
      actCode.displayName as display ->  coding.display as displayCC,  displayCC.value = display "display";
    } "allowedCC";
  } "substitution";
}

// source: https://art-decor.org/art-decor/decor-templates--cdachemed-?section=templates&id=2.16.756.5.30.1.1.10.4.42
// target: http://build.fhir.org/ig/hl7ch/ch-emed/branches/master/StructureDefinition-ch-emed-medicationdispense.html
group DispenseItemEntryContentModule(source section : Section, source src : Supply, source patient : Patient, target medicationDispense : MedicationDispense) {
  // src.templateId as template then TemplateID(template, medicationDispense) "templateId";
  src.id -> medicationDispense.identifier;
  patient ->  medicationDispense.subject = create('Reference') as reference,  reference.reference = ('urn:uuid:' + %patient.id) "patient";
  src -> medicationDispense.status = 'completed' "completed";
  src.text as text then {
    text.reference as reference then {
      reference.value as value -> medicationDispense.extension as ext then NarrativeLink(value, ext) "narrativeLink";
    };
  };
  src -> medicationDispense.contained = create('Medication') as medication then ManufacturedMaterialEntryContentModuleDispense(src, medicationDispense, medication) "medication";
  src.entryRelationship as entry where ((typeCode = 'COMP') and (substanceAdministration.templateId.root = '2.16.756.5.30.1.1.10.4.52')) -> medicationDispense.dosageInstruction as dosage then DosageInstructionsNonStructuredEntryContentModule(section, entry, dosage) "52";
  src.entryRelationship as entryRelationship then {
    entryRelationship.substanceAdministration as substanceAdministration then {
      // dosage for split dosing, as sequences are present there
      substanceAdministration.entryRelationship as entryRelationship where ((typeCode = 'COMP') and (sequenceNumber.value >= 0)) -> medicationDispense.dosageInstruction as dosage then DosageInstructionsEntryDosageChange(substanceAdministration, entryRelationship, dosage) "36";
    };
  };
  src.entryRelationship as entry where ((typeCode = 'REFR') and substanceAdministration.templateId.where(root = '1.3.6.1.4.1.19376.1.9.1.3.10').exists()) -> medicationDispense.extension as ext then MTPReferenceEntryContentModule(entry, ext) "MTPReferenceEntry";
  src.entryRelationship as entry where ((typeCode = 'COMP') and act.templateId.where(root = '2.16.756.5.30.1.1.10.4.2').exists()) then {
    entry.act as act -> medicationDispense.note as note then AnnotationComment(section, act, note) "annotation";
  } "2";
  src.entryRelationship as entry where ((typeCode = 'COMP') and act.templateId.where(root = '1.3.6.1.4.1.19376.1.9.1.3.9.2').exists()) then {
    entry.act as act -> medicationDispense as medicationDispense then SubstitutionDispense(act, medicationDispense) "substitution";
  } "2";
}

// dose quantity for dosage (application schema)
group DoseQuantity(source src : substanceAdministration, target dosage : Dosage) {
  src.doseQuantity as doseQuantity -> dosage.doseAndRate as doseAndRate then {
    doseQuantity.value as value -> doseAndRate.dose = create('Quantity') as quantity then {
      value -> quantity.value = value "value";
      doseQuantity.unit as unit -> quantity.code = unit;
      doseQuantity.unit as unit -> quantity.system = ('http://fhir.ch/ig/ch-emed/ValueSet/UnitCode'.resolve().compose.include.where(concept.where(code = %unit)).system);
      doseQuantity.unit as unit -> quantity.unit = ('http://fhir.ch/ig/ch-emed/ValueSet/UnitCode'.resolve().compose.include.concept.where(code = %unit).display);
    } "quantity";
  };
}

// source: Substitution permission Contains 1.3.6.1.4.1.19376.1.9.1.3.9.1 IHE Substitution Permission Content Module (DYNAMIC)
// target: http://build.fhir.org/ig/hl7ch/ch-emed/StructureDefinition-ch-emed-medicationrequest.html
group SubstitutionRequest(source act : Act, target medicationRequest : MedicationRequest) {
  act -> medicationRequest.substitution as substitution then {
    // act.code as code -> substitution.allowed = create('CodeableConcept') as allowedCC then CECodeableConcept(code, allowedCC) "allowedCC";
    act.code as actCode ->  substitution.allowed = create('CodeableConcept') as allowedCC,  allowedCC.coding as coding then {
      actCode ->  coding.system as systemCC,  systemCC.value = 'http://terminology.hl7.org/CodeSystem/v3-substanceAdminSubstitution' "system";
      actCode.code as code ->  coding.code as codeCC,  codeCC.value = code;
      actCode.displayName as display ->  coding.display as displayCC,  displayCC.value = display "display";
    } "allowedCC";
  } "substitutionRequest";
}

// source: Substitution permission Contains 1.3.6.1.4.1.19376.1.9.1.3.9.1 IHE Substitution Permission Content Module (DYNAMIC)
// target: http://build.fhir.org/ig/hl7ch/ch-emed/StructureDefinition-ch-emed-medicationstatement.html
group SubstitutionStatement(source act : Act, target medicationStatement : MedicationStatement) {
  act -> medicationStatement.extension as ext then {
    act -> ext.url = 'http://fhir.ch/ig/ch-emed/StructureDefinition/ch-emed-ext-substitution' then {
      // act.code as code -> ext.value = create('CodeableConcept') as valueCC then CECodeableConcept(code, valueCC) "valueCC";
      act.code as actCode ->  ext.value = create('CodeableConcept') as valueCC,  valueCC.coding as coding then {
        actCode ->  coding.system as systemCC,  systemCC.value = 'http://terminology.hl7.org/CodeSystem/v3-substanceAdminSubstitution' "system";
        actCode.code as code ->  coding.code as codeCC,  codeCC.value = code;
        actCode.displayName as display ->  coding.display as displayCC,  displayCC.value = display "display";
      } "valueCC";
    } "substitutionExtension";
  } "substitutionStatement";
}

// Number of packages
// source: https://art-decor.org/art-decor/decor-templates--cdachemed-?id=2.16.756.5.30.1.1.10.4.38
// target: http://build.fhir.org/ig/hl7ch/ch-emed/branches/master/StructureDefinition-ch-emed-medicationrequest.html
group PrescribedQuantity(source supply : Supply, target medicationRequest : MedicationRequest) {
  supply.quantity as quantity ->  medicationRequest.dispenseRequest as dispenseRequest,  dispenseRequest.quantity as quant then {
    // IHE-PRE: If the product-element contains package information, the unit attribute is not be present
    quantity.value as value -> quant.value = value;
    // IHE-PRE: If the product-element does not contain package information, the unit attribut is present and the value SHALL be out of the UCUM code system
    quantity.unit as unit then {
      unit -> quant.unit = unit "unit";
      unit -> quant.system = 'http://unitsofmeasure.org' "ucum";
      unit -> quant.code = unit "code";
    };
  };
}

// source: https://art-decor.org/art-decor/decor-templates--cdachemed-?section=templates&id=2.16.756.5.30.1.1.10.4.33
// target: http://build.fhir.org/ig/hl7ch/ch-emed/StructureDefinition-ch-emed-medicationrequest.html
group ManufacturedMaterialEntryContentModuleRequest(source src : SubstanceAdministration, target medicationRequest : MedicationRequest, target medication : Medication) {
  src ->  medication.id = 'med',  medicationRequest.medication = create('Reference') as vt,  vt.reference = '#med' "medication";
  src.consumable as consumable then {
    consumable.manufacturedProduct as manufacturedProduct then {
      manufacturedProduct.manufacturedMaterial as manufacturedMaterial then {
        manufacturedMaterial.name as name where asContent.exists() = false ->  medication.code as fhircode,  fhircode.text = (%manufacturedMaterial.name.other) "code";
        manufacturedMaterial.asContent as asContent then {
          asContent.containerPackagedMedicine as containerPackagedMedicine then {
            containerPackagedMedicine.code as code -> medication.code as fhircode share medcode then CECodeableConcept(code, fhircode);
            containerPackagedMedicine.name as name -> medication.code as fhircode share medcode then {
              name -> fhircode.text = (%name.other) "text";
            } "text";
            containerPackagedMedicine.formCode as formCode -> medication.form as form then CECodeableConcept(formCode, form);
            // Package size
            containerPackagedMedicine.capacityQuantity as capacityQuantity ->  medication.amount = create('Ratio') as ratio,  ratio.denominator = create('Quantity') as denominator,  denominator.value = '1',  denominator.unit = 'Package',  denominator.system = 'http://unitsofmeasure.org',  denominator.code = '{Package}',  ratio.numerator = create('Quantity') as quantity then EmedPQQuantity(capacityQuantity, quantity);
          };
        };
        manufacturedMaterial.ingredient as ingredient -> medication.ingredient as ing then {
          ingredient.quantity as quantity -> ing.strength = create('Ratio') as strength then EmedRTOPQPQRatio(quantity, strength) "strength";
          ingredient.ingredient as medingredient then {
            medingredient.code as code ->  ing.item = create('CodeableConcept') as ingcode,  ingcode.text = (%medingredient.name.other) then CECodeableConcept(code, ingcode) "ingredientCode";
          };
        };
      };
    };
    // dosage for normal dosing, as no sequences are present there
    src where $this.entryRelationship.sequenceNumber.exists() = false -> medicationRequest.dosageInstruction as dosage then DosageInstructionsStartStopFrequency(src, dosage) "dosage";
  };
}

// source: https://art-decor.org/art-decor/decor-templates--cdachemed-?section=templates&id=2.16.756.5.30.1.1.10.4.43
// target: http://build.fhir.org/ig/hl7ch/ch-emed/StructureDefinition-ch-emed-medicationrequest.html
group PrescriptionItemEntryContentModule(source section : Section, source src : SubstanceAdministration, source patient : Patient, target medicationRequest : MedicationRequest) {
  src.id -> medicationRequest.identifier;
  patient ->  medicationRequest.subject = create('Reference') as reference,  reference.reference = ('urn:uuid:' + %patient.id) "patient";
  src -> medicationRequest.status = 'completed' "completed";
  src -> medicationRequest.intent = 'order' "order";
  src.text as text then {
    text.reference as reference then {
      reference.value as value -> medicationRequest.extension as ext then NarrativeLink(value, ext) "narrativeLink";
    };
  };
  src -> medicationRequest.contained = create('Medication') as medication then ManufacturedMaterialEntryContentModuleRequest(src, medicationRequest, medication) "medication";
  src.entryRelationship as entry where typeCode = 'RSON' then {
    entry.observation as observation -> medicationRequest.reasonCode as reasonCode then TreatmentReasonEntryContentModule(section, observation, reasonCode) "reasonCode";
  } "41";
  src.entryRelationship as entry where ((typeCode = 'COMP') and (substanceAdministration.templateId.root = '2.16.756.5.30.1.1.10.4.52')) -> medicationRequest.dosageInstruction as dosage then DosageInstructionsNonStructuredEntryContentModule(section, entry, dosage) "52";
  // dosage for split dosing, as sequences are present there
  src.entryRelationship as entry where ((typeCode = 'COMP') and (sequenceNumber.value >= 0)) -> medicationRequest.dosageInstruction as dosage then DosageInstructionsEntryDosageChange(src, entry, dosage) "36";
  src.entryRelationship as entry where ((typeCode = 'REFR') and substanceAdministration.templateId.where(root = '1.3.6.1.4.1.19376.1.9.1.3.10').exists()) -> medicationRequest.extension as ext then MTPReferenceEntryContentModule(entry, ext) "MTPReferenceEntry";
  src.entryRelationship as entry where ((typeCode = 'COMP') and act.templateId.where(root = '2.16.756.5.30.1.1.10.4.2').exists()) then {
    entry.act as act -> medicationRequest.note as note then AnnotationComment(section, act, note) "annotation";
  } "2";
  src.repeatNumber as repeatNumber -> medicationRequest.dispenseRequest as dispenseRequest then {
    repeatNumber.value as val -> dispenseRequest.numberOfRepeatsAllowed = val "repeatNumber";
  } "repeats";
  src.entryRelationship as entry where ((typeCode = 'COMP') and supply.templateId.where(root = '1.3.6.1.4.1.19376.1.9.1.3.8').exists()) then {
    entry.supply as supply -> medicationRequest as medicationRequest then PrescribedQuantity(supply, medicationRequest) "quantity";
  } "8";
  src.entryRelationship as entry where ((typeCode = 'COMP') and act.templateId.where(root = '1.3.6.1.4.1.19376.1.9.1.3.9.1').exists()) then {
    entry.act as act -> medicationRequest as medicationRequest then SubstitutionRequest(act, medicationRequest) "substitution";
  } "1";
}

// source: https://art-decor.org/art-decor/decor-templates--ch-pharm-?id=2.16.756.5.30.1.1.10.4.35
// target: http://build.fhir.org/ig/hl7ch/ch-emed/StructureDefinition/ch-emed-dosage-structured-normal
// dosage for normal dosing, without sequences
group DosageInstructionsStartStopFrequency(source src : SubstanceAdministration, target dosage : Dosage) {
  src as src -> dosage as dosage then EffectiveTimeStartEnd(src, dosage) "effectiveTimeStartEnd";
  src as src -> dosage as dosage then EffectiveTimeWhen(src, dosage) "effectiveTimeWhen";
  src.routeCode as routeCode -> dosage.route as route then CECodeableConcept(routeCode, route);
  src as src -> dosage as dosage then DoseQuantity(src, dosage) "doseQuantity";
}

// source: https://art-decor.org/art-decor/decor-templates--cdachemed-?section=templates&id=2.16.756.5.30.1.1.10.4.44
// target: http://build.fhir.org/ig/hl7ch/ch-emed/StructureDefinition-ch-emed-observation.html
group PharmaceuticalAdviceItemEntryContentModule(source section : Section, source src : Observation, source patient : Patient, target observation : Observation, target bundle : Bundle) {
  src.id -> observation.identifier;
  patient ->  observation.subject = create('Reference') as reference,  reference.reference = ('urn:uuid:' + %patient.id) "patient";
  src -> observation.status = 'final' "final";
  src.effectiveTime as effectiveTime -> observation.effective = create('dateTime') as value then TSDateTime(effectiveTime, value) "value";
  src.entryRelationship as entry where ((typeCode = 'REFR') and substanceAdministration.templateId.where(root = '1.3.6.1.4.1.19376.1.9.1.3.10').exists()) -> observation.extension as ext then MTPReferenceEntryContentModule(entry, ext) "MTPReferenceEntry";
  src.entryRelationship as entry where ((typeCode = 'REFR') and substanceAdministration.templateId.where(root = '1.3.6.1.4.1.19376.1.9.1.3.7').exists()) ->  bundle.entry as e,  e.id = uuid() as uuid,  e.fullUrl = append('urn:uuid:', uuid),  e.resource = create('MedicationStatement') as medicationstatement,  observation.extension as ext,  ext.url = 'http://fhir.ch/ig/ch-emed/StructureDefinition/ch-emed-ext-medicationstatement-changed',  ext.value = create('Reference') as reference,  reference.reference = append('urn:uuid:', uuid) then {
    entry.substanceAdministration as substanceAdministration then MedicationTreatmentPlanItemEntryContentModule(section, substanceAdministration, patient, medicationstatement);
  } "cdaEntry";
  src.text as text -> observation.note as note then {
    text.data as data -> note.text = data "level3observation";
    text where (data.exists() = false) -> note.text = (%section.text.substring(%section.text.indexOf(%src.text.reference.value.substring(1))).substring(%section.text.substring(%section.text.indexOf(%src.text.reference.value.substring(1))).indexOf('>') + 1, %section.text.substring(%section.text.indexOf(%src.text.reference.value.substring(1))).indexOf('<') - %section.text.substring(%section.text.indexOf(%src.text.reference.value.substring(1))).indexOf('>') - 1)) "idRef";
    text.reference as reference then {
      reference.value as value -> note.extension as ext then NarrativeLink(value, ext) "narrativeLink";
    };
  } "note";
  src.code -> observation.code;
}

// _________________________ Template Type not specified   _________________________
// target: http://build.fhir.org/ig/hl7ch/ch-emed/branches/master/StructureDefinition-ch-emed-ext-treatmentplan.html
group InnerExtensionExternalDocumentId(source src, target ext : Extension) {
  src -> ext.url = 'externalDocumentId' "url";
  src -> ext.value = create('Identifier') as id then II(src, id) "value";
}

// target: http://build.fhir.org/ig/hl7ch/ch-emed/branches/master/StructureDefinition-ch-emed-ext-treatmentplan.html
group InnerExtensionId(source src, target ext : Extension) {
  src -> ext.url = 'id' "url";
  src -> ext.value = create('Identifier') as id then II(src, id) "value";
}