Clinical Practice Guidelines
1.0.0 - ci-build International flag

Clinical Practice Guidelines, published by HL7 International - Clinical Decision Support WG. This is not an authorized publication; it is the continuous build for version 1.0.0). This version is based on the current content of https://github.com/HL7/cqf-recommendations/ and changes regularly. See the Directory of published versions

: Opioid CDS R4 Common Logic - TTL Representation

Active as of 2018-03-25

Raw ttl | Download

@prefix fhir: <http://hl7.org/fhir/> .
@prefix owl: <http://www.w3.org/2002/07/owl#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix sct: <http://snomed.info/id/> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .

# - resource -------------------------------------------------------------------

 a fhir:Library ;
  fhir:nodeRole fhir:treeRoot ;
  fhir:id [ fhir:v "OpioidCDSR4Common"] ; # 
  fhir:text [
fhir:status [ fhir:v "generated" ] ;
fhir:div "<div xmlns=\"http://www.w3.org/1999/xhtml\"><h2>Participants</h2><table class=\"grid\"><tr><td>Author</td><td>Kensaku Kawamoto, MD, PhD, MHS</td></tr><tr><td>Author</td><td>Bryn Rhodes</td></tr><tr><td>Author</td><td>Floyd Eisenberg, MD, MPH</td></tr><tr><td>Author</td><td>Robert McClure, MD, MPH</td></tr></table><h2>Related Artifacts</h2><table class=\"grid\"><tr><td>documentation</td><td>CDC guideline for prescribing opioids for chronic pain</td><td>https://www.cdc.gov/mmwr/volumes/65/rr/rr6501e1.htm?CDC_AA_refVal=https%3A%2F%2Fwww.cdc.gov%2Fmmwr%2Fvolumes%2F65%2Frr%2Frr6501e1er.htm</td></tr></table><h2>Contents</h2><p><code>text/cql</code></p><pre><code class=\"language-sql\">library OpioidCDSR4Common version '0.1.0'\n\nusing FHIR version '4.0.0'\n\ninclude FHIRHelpers version '4.0.0' called FHIRHelpers\ninclude OMTKLogic version '0.0.0' called OMTKLogic\n\ncodesystem &quot;SNOMED&quot;: 'http://snomed.info/sct'\ncodesystem &quot;Medication Request Category Codes&quot;: 'http://terminology.hl7.org/CodeSystem/medicationrequest-category'\n\nvalueset &quot;Active Condition&quot;: 'http://hl7.org/fhir/uv/cpg/ValueSet/cpg-active-condition'\nvalueset &quot;Benzodiazepines&quot;: 'http://fhir.org/guides/cdc/opioid-cds/ValueSet/benzodiazepines'\n// TODO: Fix this name\nvalueset &quot;End of Life Conditions&quot;: 'http://fhir.org/guides/cdc/opioid-cds/ValueSet/end-of-life-conditions'\n// Harvested from VSAC - OID: 2.16.840.1.113762.1.4.1108.15\n// NOTE: This harvest note is incorrect, none of the following 3 value sets contain any of the codes in the above referenced valueset\n// Rob will construct an appropriate hospice value set aligned with current eCQM program usage and we will use that when available\nvalueset &quot;Hospice Disposition&quot;: 'http://fhir.org/guides/cdc/opioid-cds/ValueSet/hospice-disposition'\nvalueset &quot;Hospice Finding Codes&quot;: 'http://fhir.org/guides/cdc/opioid-cds/ValueSet/hospice-finding'\nvalueset &quot;Hospice Procedure Codes&quot;: 'http://fhir.org/guides/cdc/opioid-cds/ValueSet/hospice-procedure'\nvalueset &quot;Illicit Drug Screening&quot;: 'http://fhir.org/guides/cdc/opioid-cds/ValueSet/illicit-drug-urine-screening'\n// Harvested from VSAC - OID: 2.16.840.1.113883.3.526.3.1259\nvalueset &quot;Limited Life Expectancy Conditions&quot;: 'http://fhir.org/guides/cdc/opioid-cds/ValueSet/limited-life-expectancy-conditions'\nvalueset &quot;Long Acting Opioids&quot;: 'http://fhir.org/guides/cdc/opioid-cds/ValueSet/long-acting-opioids'\nvalueset &quot;Naloxone&quot;: 'http://fhir.org/guides/cdc/opioid-cds/ValueSet/naloxone'\nvalueset &quot;Risk Assessment&quot;: 'http://fhir.org/guides/cdc/opioid-cds/ValueSet/opioid-abuse-assessment'\nvalueset &quot;Opioid Drug Screening&quot;: 'http://fhir.org/guides/cdc/opioid-cds/ValueSet/opioid-urine-screening'\nvalueset &quot;Ambulatory Abuse Potential Opioids&quot;: 'http://fhir.org/guides/cdc/opioid-cds/ValueSet/opioids-abused-in-ambulatory-care'\nvalueset &quot;Substance Abuse&quot;: 'http://fhir.org/guides/cdc/opioid-cds/ValueSet/substance-abuse'\n\n// TODO: Turn this into a valueset\ncode &quot;Referral to Hospice&quot;: '306205009' from &quot;SNOMED&quot;\n// TODO: Turn this into a valueset\ncode &quot;Outpatient&quot;: 'outpatient' from &quot;Medication Request Category Codes&quot;\n\n// TODO: Capture process decisions for long-term opioid use\ndefine IsForChronicPain: true\n\ndefine &quot;Active Ambulatory Opioid Rx&quot;:\n  [MedicationRequest: &quot;Ambulatory Abuse Potential Opioids&quot;] Rx\n    where Rx.status = 'active'\n      and ToCodes(Rx.category.coding) contains &quot;Outpatient&quot;\n\ndefine &quot;Active Ambulatory Benzodiazepine Rx&quot;:\n  [MedicationRequest: &quot;Benzodiazepines&quot;] Rx\n    where Rx.status = 'active'\n      and ToCodes(Rx.category.coding) contains &quot;Outpatient&quot;\n\ndefine &quot;Active Ambulatory Naloxone Rx&quot;:\n  [MedicationRequest: &quot;Naloxone&quot;] Rx\n    where Rx.status = 'active'\n      and ToCodes(Rx.category.coding) contains &quot;Outpatient&quot;\n\ndefine &quot;Ambulatory Opioid Rx&quot;:\n  [MedicationRequest: &quot;Ambulatory Abuse Potential Opioids&quot;] Rx\n      where ToCodes(Rx.category.coding) contains &quot;Outpatient&quot;\n\ndefine &quot;End of Life Assessment&quot;:\n  // 1. Conditions indicating end of life or with limited life expectancy\n  exists (\n    (\n      [Condition: &quot;End of Life Conditions&quot;] C\n        where C.clinicalStatus in &quot;Active Condition&quot;\n    )\n    union\n    (\n      [Condition: code in &quot;Limited Life Expectancy Conditions&quot;] C\n        where C.clinicalStatus in &quot;Active Condition&quot;\n    )\n  )\n  // 2. Admitted/referred/discharged to hospice care\n  or exists (\n    (\n      [ServiceRequest: code in &quot;Referral to Hospice&quot;] RR\n        where RR.status in { 'active', 'completed' }\n    )\n    union\n    (\n      [ServiceRequest: code in &quot;Hospice Procedure Codes&quot;] P\n        where P.status in { 'in-progress', 'completed' }\n    )\n    union\n    (\n      [ServiceRequest: code in &quot;Hospice Procedure Codes&quot;] E\n        where E.status in { 'planned', 'arrived', 'in-progress', 'finished', 'onleave' }\n    )\n    union\n    (\n      [Observation: code in &quot;Hospice Finding Codes&quot;] O\n        where not (O.status in { 'unknown', 'entered-in-error', 'cancelled' })\n    )\n    union\n    (\n      [Encounter] E\n        where\n          (\n            if E.hospitalization.dischargeDisposition.coding is null\n                or not exists (E.hospitalization.dischargeDisposition.coding)\n              then false\n            else E.hospitalization.dischargeDisposition in &quot;Hospice Disposition&quot;\n          )\n          and E.status in { 'planned', 'arrived', 'in-progress', 'finished', 'onleave' }\n    )\n  )\n\ndefine function Prescriptions(Orders List&lt;MedicationRequest&gt;):\n  Orders O\n    let\n      // NOTE: Assuming medication is specified as a CodeableConcept with a single RxNorm code\n      rxNormCode: ToCode(O.medication.coding[0]),\n      medicationName: OMTKLogic.GetMedicationName(rxNormCode),\n      // NOTE: Assuming a single dosage instruction element\n      dosageInstruction: O.dosageInstruction[0],\n      repeat: dosageInstruction.timing.repeat,\n      frequency: Coalesce(repeat.frequencyMax.value, repeat.frequency.value),\n      period: System.Quantity { value: repeat.period.value, unit: repeat.periodUnit.value },\n      doseDescription:\n        Coalesce(\n          // There should be a conversion from FHIR.SimpleQuantity to System.Quantity\n          if dosageInstruction.doseAndRate[0].dose is FHIR.Range\n            then ToString(ToQuantity(dosageInstruction.doseAndRate[0].dose.low))\n                          + '-' + ToString(ToQuantity(dosageInstruction.doseAndRate[0].dose.high))\n                          + dosageInstruction.doseAndRate[0].dose.high.unit.value\n            else ToString(ToQuantity(dosageInstruction.doseAndRate[0].dose)),\n            ''\n        ),\n      frequencyDescription:\n        ToString(dosageInstruction.timing.repeat.frequency.value) +\n          Coalesce(\n            '-' + ToString(dosageInstruction.timing.repeat.frequencyMax.value),\n            ''\n          )\n    return {\n      rxNormCode: rxNormCode,\n      isDraft: O.status.value = 'draft',\n      // NOTE: Assuming asNeeded is expressed as a boolean\n      isPRN: dosageInstruction.asNeeded.value,\n      prescription:\n        if dosageInstruction.text is not null then\n          medicationName + ' ' + dosageInstruction.text.value\n        else\n          // TODO: Shouldn't need the .value here on asNeededBoolean\n          medicationName + ' ' + doseDescription + ' q' + frequencyDescription + (if dosageInstruction.asNeeded.value then ' PRN' else ''),\n      // TODO: Shouldn't need the ToQuantity here...\n      dose: if dosageInstruction.doseAndRate[0].dose is FHIR.Range\n            then ToQuantity(dosageInstruction.doseAndRate[0].dose.high)\n            else ToQuantity(dosageInstruction.doseAndRate[0].dose),\n      dosesPerDay: Coalesce(OMTKLogic.ToDaily(frequency, period), 1.0)\n    }\n\ndefine function MME(prescriptions List&lt;MedicationRequest&gt;):\n  (Prescriptions(prescriptions)) P\n    let mme: SingletonFrom(OMTKLogic.CalculateMMEs({ { rxNormCode: P.rxNormCode, doseQuantity: P.dose, dosesPerDay: P.dosesPerDay } }))\n    return {\n      rxNormCode: P.rxNormCode,\n      isDraft: P.isDraft,\n      isPRN: P.isPRN,\n      prescription: P.prescription,\n      dailyDose: mme.dailyDoseDescription,\n      conversionFactor: mme.conversionFactor,\n      mme: mme.mme\n    }\n\ndefine function TotalMME(prescriptions List&lt;MedicationRequest&gt;):\n  System.Quantity {\n    value: Sum((MME(prescriptions)) M return M.mme.value),\n    unit: 'mg/d'\n  }\n\ndefine function ProbableDaysInRange(Orders List&lt;MedicationRequest&gt;, daysPast Integer, numDaysInDaysPast Integer):\n  Orders orders\n    let\n      frequency: orders.dosageInstruction[0].timing.repeat.frequency.value,\n      period: orders.dosageInstruction[0].timing.repeat.period.value,\n      periodDays: GetPeriodDays(orders.dosageInstruction[0].timing.repeat.periodUnit.value),\n      dosesPerDay:\n        if (frequency / (period * periodDays)) &gt;= 1.0\n        then 1.0\n        else frequency / (period * periodDays),\n      repeat: orders.dispenseRequest.numberOfRepeatsAllowed.value,\n      supplyDuration: GetDurationInDays(orders.dispenseRequest.expectedSupplyDuration),\n      validityPeriod: days between orders.dispenseRequest.validityPeriod.&quot;start&quot;.value and Today(),\n      endDifference:\n        if orders.dispenseRequest.validityPeriod.&quot;end&quot;.value &lt; Today()\n        then days between orders.dispenseRequest.validityPeriod.&quot;end&quot;.value and Today()\n        else 0\n    return\n      if (repeat * supplyDuration) &lt; numDaysInDaysPast then false\n      else\n        (dosesPerDay * ((repeat * supplyDuration) / validityPeriod) * (daysPast - endDifference)) &gt;= numDaysInDaysPast\n\ndefine function GetPeriodDays(value System.String):\n  case\n    when value = 'a' then 365.0\n    when value = 'mo' then 30.0\n    when value = 'h' then 1.0/24.0\n    when value = 'min' then 1.0/24.0*60.0\n    when value = 's' then 1.0/24.0*60.0*60.0\n    when value = 'ms' then 1.0/24.0*60.0*60.0*1000.0\n    else 1.0\n  end\n\n  define function GetDurationInDays(value FHIR.Duration):\n    case\n      when StartsWith(value.unit.value, 'a') then value.value.value * 365.0\n      when StartsWith(value.unit.value, 'mo') then value.value.value * 30.0\n      when StartsWith(value.unit.value, 'wk') then value.value.value * 7.0\n      when StartsWith(value.unit.value, 'd') then value.value.value\n      when StartsWith(value.unit.value, 'h') then value.value.value / 24.0\n      when StartsWith(value.unit.value, 'min') then value.value.value / 60.0 / 24.0\n      when StartsWith(value.unit.value, 's') then value.value.value / 60.0 / 60.0 / 24.0\n      when StartsWith(value.unit.value, 'ms') then value.value.value / 60.0 / 60.0 / 24.0 / 1000.0\n      else Message(1000, true, 'Undefined', 'Error', 'Unsupported duration unit')\n    end\n\ndefine function GetIngredient(rxNormCode Code):\n  OMTKLogic.GetIngredients(rxNormCode).ingredientName\n\ndefine function GetIngredients(rxNormCodes List&lt;Code&gt;):\n  rxNormCodes rnc return GetIngredient(rnc)\n\ndefine function GetMedicationNames(medications List&lt;MedicationRequest&gt;):\n  medications M\n    return OMTKLogic.GetIngredients(ToRxNormCode(M.medication.coding)).rxNormCode.display\n\n/*\n*  Conversion Functions\n*/\n\ndefine function ToCode(coding FHIR.Coding):\n  System.Code {\n    code: coding.code.value,\n    system: coding.system.value,\n    version: coding.version.value,\n    display: coding.display.value\n  }\n\ndefine function ToCodes(coding List&lt;FHIR.Coding&gt;):\n  coding c return ToCode(c)\n\ndefine function ToRxNormCode(coding List&lt;FHIR.Coding&gt;):\n  singleton from (\n    coding C where C.system = 'http://www.nlm.nih.gov/research/umls/rxnorm'\n  )\n\ndefine function ToQuantity(quantity FHIR.Quantity):\n  System.Quantity { value: quantity.value.value, unit: quantity.unit.value }\n</code></pre><p><code>No Content</code> (<code>application/elm+xml</code>)</p></div>"
  ] ; # 
  fhir:url [ fhir:v "http://fhir.org/guides/cdc/opioid-cds/Library/OpioidCDSR4Common"^^xsd:anyURI] ; # 
  fhir:version [ fhir:v "1.0.0"] ; # 
  fhir:name [ fhir:v "OpioidCDSR4Common"] ; # 
  fhir:title [ fhir:v "Opioid CDS R4 Common Logic"] ; # 
  fhir:status [ fhir:v "active"] ; # 
  fhir:experimental [ fhir:v "true"^^xsd:boolean] ; # 
  fhir:type [
    ( fhir:coding [
fhir:system [ fhir:v "http://terminology.hl7.org/CodeSystem/library-type"^^xsd:anyURI ] ;
fhir:code [ fhir:v "logic-library" ] ;
fhir:display [ fhir:v "Logic Library" ]     ] )
  ] ; # 
  fhir:date [ fhir:v "2018-03-25T13:49:09-06:00"^^xsd:dateTime] ; # 
  fhir:publisher [ fhir:v "HL7 International - Clinical Decision Support WG"] ; # 
  fhir:contact ( [
fhir:name [ fhir:v "HL7 International - Clinical Decision Support WG" ] ;
    ( fhir:telecom [
fhir:system [ fhir:v "url" ] ;
fhir:value [ fhir:v "http://www.hl7.org/Special/committees/dss/index.cfm" ]     ] )
  ] ) ; # 
  fhir:description [ fhir:v "Common Opioid Decision Support Logic for use in implementing CDC Opioid Prescribing Guidelines."] ; # 
  fhir:useContext ( [
fhir:code [
fhir:system [ fhir:v "http://terminology.hl7.org/CodeSystem/usage-context-type"^^xsd:anyURI ] ;
fhir:code [ fhir:v "focus" ] ;
fhir:display [ fhir:v "Clinical Focus" ]     ] ;
fhir:value [
a fhir:CodeableConcept ;
      ( fhir:coding [
a sct:182888003 ;
fhir:system [ fhir:v "http://snomed.info/sct"^^xsd:anyURI ] ;
fhir:code [ fhir:v "182888003" ] ;
fhir:display [ fhir:v "Medication requested (situation)" ]       ] )     ]
  ] [
fhir:code [
fhir:system [ fhir:v "http://terminology.hl7.org/CodeSystem/usage-context-type"^^xsd:anyURI ] ;
fhir:code [ fhir:v "focus" ] ;
fhir:display [ fhir:v "Clinical Focus" ]     ] ;
fhir:value [
a fhir:CodeableConcept ;
      ( fhir:coding [
a sct:82423001 ;
fhir:system [ fhir:v "http://snomed.info/sct"^^xsd:anyURI ] ;
fhir:code [ fhir:v "82423001" ] ;
fhir:display [ fhir:v "Chronic pain (finding)" ]       ] )     ]
  ] ) ; # 
  fhir:jurisdiction ( [
    ( fhir:coding [
fhir:system [ fhir:v "http://unstats.un.org/unsd/methods/m49/m49.htm"^^xsd:anyURI ] ;
fhir:code [ fhir:v "001" ] ;
fhir:display [ fhir:v "World" ]     ] )
  ] ) ; # 
  fhir:purpose [ fhir:v "This library contains common logic across recommendations including MME calculations, conversions, and looking up codes in valuesets."] ; # 
  fhir:usage [ fhir:v "This library is used for decision support for opioid guideline recommendations when applying PlanDefinitions."] ; # 
  fhir:copyright [ fhir:v "© CDC 2016+."] ; # 
  fhir:topic ( [
fhir:text [ fhir:v "Opioid Prescribing" ]
  ] ) ; # 
  fhir:author ( [
fhir:name [ fhir:v "Kensaku Kawamoto, MD, PhD, MHS" ]
  ] [
fhir:name [ fhir:v "Bryn Rhodes" ]
  ] [
fhir:name [ fhir:v "Floyd Eisenberg, MD, MPH" ]
  ] [
fhir:name [ fhir:v "Robert McClure, MD, MPH" ]
  ] ) ; # 
  fhir:relatedArtifact ( [
fhir:type [ fhir:v "documentation" ] ;
fhir:display [ fhir:v "CDC guideline for prescribing opioids for chronic pain" ] ;
fhir:url [ fhir:v "https://www.cdc.gov/mmwr/volumes/65/rr/rr6501e1.htm?CDC_AA_refVal=https%3A%2F%2Fwww.cdc.gov%2Fmmwr%2Fvolumes%2F65%2Frr%2Frr6501e1er.htm"^^xsd:anyURI ] ;
fhir:document [
fhir:url [ fhir:v "https://www.cdc.gov/mmwr/volumes/65/rr/rr6501e1.htm?CDC_AA_refVal=https%3A%2F%2Fwww.cdc.gov%2Fmmwr%2Fvolumes%2F65%2Frr%2Frr6501e1er.htm"^^xsd:anyURI ]     ]
  ] ) ; # 
  fhir:content ( [
fhir:contentType [ fhir:v "text/cql" ] ;
fhir:data [ fhir:v "bGlicmFyeSBPcGlvaWRDRFNSNENvbW1vbiB2ZXJzaW9uICcwLjEuMCcKCnVzaW5nIEZISVIgdmVyc2lvbiAnNC4wLjAnCgppbmNsdWRlIEZISVJIZWxwZXJzIHZlcnNpb24gJzQuMC4wJyBjYWxsZWQgRkhJUkhlbHBlcnMKaW5jbHVkZSBPTVRLTG9naWMgdmVyc2lvbiAnMC4wLjAnIGNhbGxlZCBPTVRLTG9naWMKCmNvZGVzeXN0ZW0gIlNOT01FRCI6ICdodHRwOi8vc25vbWVkLmluZm8vc2N0Jwpjb2Rlc3lzdGVtICJNZWRpY2F0aW9uIFJlcXVlc3QgQ2F0ZWdvcnkgQ29kZXMiOiAnaHR0cDovL3Rlcm1pbm9sb2d5LmhsNy5vcmcvQ29kZVN5c3RlbS9tZWRpY2F0aW9ucmVxdWVzdC1jYXRlZ29yeScKCnZhbHVlc2V0ICJBY3RpdmUgQ29uZGl0aW9uIjogJ2h0dHA6Ly9obDcub3JnL2ZoaXIvdXYvY3BnL1ZhbHVlU2V0L2NwZy1hY3RpdmUtY29uZGl0aW9uJwp2YWx1ZXNldCAiQmVuem9kaWF6ZXBpbmVzIjogJ2h0dHA6Ly9maGlyLm9yZy9ndWlkZXMvY2RjL29waW9pZC1jZHMvVmFsdWVTZXQvYmVuem9kaWF6ZXBpbmVzJwovLyBUT0RPOiBGaXggdGhpcyBuYW1lCnZhbHVlc2V0ICJFbmQgb2YgTGlmZSBDb25kaXRpb25zIjogJ2h0dHA6Ly9maGlyLm9yZy9ndWlkZXMvY2RjL29waW9pZC1jZHMvVmFsdWVTZXQvZW5kLW9mLWxpZmUtY29uZGl0aW9ucycKLy8gSGFydmVzdGVkIGZyb20gVlNBQyAtIE9JRDogMi4xNi44NDAuMS4xMTM3NjIuMS40LjExMDguMTUKLy8gTk9URTogVGhpcyBoYXJ2ZXN0IG5vdGUgaXMgaW5jb3JyZWN0LCBub25lIG9mIHRoZSBmb2xsb3dpbmcgMyB2YWx1ZSBzZXRzIGNvbnRhaW4gYW55IG9mIHRoZSBjb2RlcyBpbiB0aGUgYWJvdmUgcmVmZXJlbmNlZCB2YWx1ZXNldAovLyBSb2Igd2lsbCBjb25zdHJ1Y3QgYW4gYXBwcm9wcmlhdGUgaG9zcGljZSB2YWx1ZSBzZXQgYWxpZ25lZCB3aXRoIGN1cnJlbnQgZUNRTSBwcm9ncmFtIHVzYWdlIGFuZCB3ZSB3aWxsIHVzZSB0aGF0IHdoZW4gYXZhaWxhYmxlCnZhbHVlc2V0ICJIb3NwaWNlIERpc3Bvc2l0aW9uIjogJ2h0dHA6Ly9maGlyLm9yZy9ndWlkZXMvY2RjL29waW9pZC1jZHMvVmFsdWVTZXQvaG9zcGljZS1kaXNwb3NpdGlvbicKdmFsdWVzZXQgIkhvc3BpY2UgRmluZGluZyBDb2RlcyI6ICdodHRwOi8vZmhpci5vcmcvZ3VpZGVzL2NkYy9vcGlvaWQtY2RzL1ZhbHVlU2V0L2hvc3BpY2UtZmluZGluZycKdmFsdWVzZXQgIkhvc3BpY2UgUHJvY2VkdXJlIENvZGVzIjogJ2h0dHA6Ly9maGlyLm9yZy9ndWlkZXMvY2RjL29waW9pZC1jZHMvVmFsdWVTZXQvaG9zcGljZS1wcm9jZWR1cmUnCnZhbHVlc2V0ICJJbGxpY2l0IERydWcgU2NyZWVuaW5nIjogJ2h0dHA6Ly9maGlyLm9yZy9ndWlkZXMvY2RjL29waW9pZC1jZHMvVmFsdWVTZXQvaWxsaWNpdC1kcnVnLXVyaW5lLXNjcmVlbmluZycKLy8gSGFydmVzdGVkIGZyb20gVlNBQyAtIE9JRDogMi4xNi44NDAuMS4xMTM4ODMuMy41MjYuMy4xMjU5CnZhbHVlc2V0ICJMaW1pdGVkIExpZmUgRXhwZWN0YW5jeSBDb25kaXRpb25zIjogJ2h0dHA6Ly9maGlyLm9yZy9ndWlkZXMvY2RjL29waW9pZC1jZHMvVmFsdWVTZXQvbGltaXRlZC1saWZlLWV4cGVjdGFuY3ktY29uZGl0aW9ucycKdmFsdWVzZXQgIkxvbmcgQWN0aW5nIE9waW9pZHMiOiAnaHR0cDovL2ZoaXIub3JnL2d1aWRlcy9jZGMvb3Bpb2lkLWNkcy9WYWx1ZVNldC9sb25nLWFjdGluZy1vcGlvaWRzJwp2YWx1ZXNldCAiTmFsb3hvbmUiOiAnaHR0cDovL2ZoaXIub3JnL2d1aWRlcy9jZGMvb3Bpb2lkLWNkcy9WYWx1ZVNldC9uYWxveG9uZScKdmFsdWVzZXQgIlJpc2sgQXNzZXNzbWVudCI6ICdodHRwOi8vZmhpci5vcmcvZ3VpZGVzL2NkYy9vcGlvaWQtY2RzL1ZhbHVlU2V0L29waW9pZC1hYnVzZS1hc3Nlc3NtZW50Jwp2YWx1ZXNldCAiT3Bpb2lkIERydWcgU2NyZWVuaW5nIjogJ2h0dHA6Ly9maGlyLm9yZy9ndWlkZXMvY2RjL29waW9pZC1jZHMvVmFsdWVTZXQvb3Bpb2lkLXVyaW5lLXNjcmVlbmluZycKdmFsdWVzZXQgIkFtYnVsYXRvcnkgQWJ1c2UgUG90ZW50aWFsIE9waW9pZHMiOiAnaHR0cDovL2ZoaXIub3JnL2d1aWRlcy9jZGMvb3Bpb2lkLWNkcy9WYWx1ZVNldC9vcGlvaWRzLWFidXNlZC1pbi1hbWJ1bGF0b3J5LWNhcmUnCnZhbHVlc2V0ICJTdWJzdGFuY2UgQWJ1c2UiOiAnaHR0cDovL2ZoaXIub3JnL2d1aWRlcy9jZGMvb3Bpb2lkLWNkcy9WYWx1ZVNldC9zdWJzdGFuY2UtYWJ1c2UnCgovLyBUT0RPOiBUdXJuIHRoaXMgaW50byBhIHZhbHVlc2V0CmNvZGUgIlJlZmVycmFsIHRvIEhvc3BpY2UiOiAnMzA2MjA1MDA5JyBmcm9tICJTTk9NRUQiCi8vIFRPRE86IFR1cm4gdGhpcyBpbnRvIGEgdmFsdWVzZXQKY29kZSAiT3V0cGF0aWVudCI6ICdvdXRwYXRpZW50JyBmcm9tICJNZWRpY2F0aW9uIFJlcXVlc3QgQ2F0ZWdvcnkgQ29kZXMiCgovLyBUT0RPOiBDYXB0dXJlIHByb2Nlc3MgZGVjaXNpb25zIGZvciBsb25nLXRlcm0gb3Bpb2lkIHVzZQpkZWZpbmUgSXNGb3JDaHJvbmljUGFpbjogdHJ1ZQoKZGVmaW5lICJBY3RpdmUgQW1idWxhdG9yeSBPcGlvaWQgUngiOgogIFtNZWRpY2F0aW9uUmVxdWVzdDogIkFtYnVsYXRvcnkgQWJ1c2UgUG90ZW50aWFsIE9waW9pZHMiXSBSeAogICAgd2hlcmUgUnguc3RhdHVzID0gJ2FjdGl2ZScKICAgICAgYW5kIFRvQ29kZXMoUnguY2F0ZWdvcnkuY29kaW5nKSBjb250YWlucyAiT3V0cGF0aWVudCIKCmRlZmluZSAiQWN0aXZlIEFtYnVsYXRvcnkgQmVuem9kaWF6ZXBpbmUgUngiOgogIFtNZWRpY2F0aW9uUmVxdWVzdDogIkJlbnpvZGlhemVwaW5lcyJdIFJ4CiAgICB3aGVyZSBSeC5zdGF0dXMgPSAnYWN0aXZlJwogICAgICBhbmQgVG9Db2RlcyhSeC5jYXRlZ29yeS5jb2RpbmcpIGNvbnRhaW5zICJPdXRwYXRpZW50IgoKZGVmaW5lICJBY3RpdmUgQW1idWxhdG9yeSBOYWxveG9uZSBSeCI6CiAgW01lZGljYXRpb25SZXF1ZXN0OiAiTmFsb3hvbmUiXSBSeAogICAgd2hlcmUgUnguc3RhdHVzID0gJ2FjdGl2ZScKICAgICAgYW5kIFRvQ29kZXMoUnguY2F0ZWdvcnkuY29kaW5nKSBjb250YWlucyAiT3V0cGF0aWVudCIKCmRlZmluZSAiQW1idWxhdG9yeSBPcGlvaWQgUngiOgogIFtNZWRpY2F0aW9uUmVxdWVzdDogIkFtYnVsYXRvcnkgQWJ1c2UgUG90ZW50aWFsIE9waW9pZHMiXSBSeAogICAgICB3aGVyZSBUb0NvZGVzKFJ4LmNhdGVnb3J5LmNvZGluZykgY29udGFpbnMgIk91dHBhdGllbnQiCgpkZWZpbmUgIkVuZCBvZiBMaWZlIEFzc2Vzc21lbnQiOgogIC8vIDEuIENvbmRpdGlvbnMgaW5kaWNhdGluZyBlbmQgb2YgbGlmZSBvciB3aXRoIGxpbWl0ZWQgbGlmZSBleHBlY3RhbmN5CiAgZXhpc3RzICgKICAgICgKICAgICAgW0NvbmRpdGlvbjogIkVuZCBvZiBMaWZlIENvbmRpdGlvbnMiXSBDCiAgICAgICAgd2hlcmUgQy5jbGluaWNhbFN0YXR1cyBpbiAiQWN0aXZlIENvbmRpdGlvbiIKICAgICkKICAgIHVuaW9uCiAgICAoCiAgICAgIFtDb25kaXRpb246IGNvZGUgaW4gIkxpbWl0ZWQgTGlmZSBFeHBlY3RhbmN5IENvbmRpdGlvbnMiXSBDCiAgICAgICAgd2hlcmUgQy5jbGluaWNhbFN0YXR1cyBpbiAiQWN0aXZlIENvbmRpdGlvbiIKICAgICkKICApCiAgLy8gMi4gQWRtaXR0ZWQvcmVmZXJyZWQvZGlzY2hhcmdlZCB0byBob3NwaWNlIGNhcmUKICBvciBleGlzdHMgKAogICAgKAogICAgICBbU2VydmljZVJlcXVlc3Q6IGNvZGUgaW4gIlJlZmVycmFsIHRvIEhvc3BpY2UiXSBSUgogICAgICAgIHdoZXJlIFJSLnN0YXR1cyBpbiB7ICdhY3RpdmUnLCAnY29tcGxldGVkJyB9CiAgICApCiAgICB1bmlvbgogICAgKAogICAgICBbU2VydmljZVJlcXVlc3Q6IGNvZGUgaW4gIkhvc3BpY2UgUHJvY2VkdXJlIENvZGVzIl0gUAogICAgICAgIHdoZXJlIFAuc3RhdHVzIGluIHsgJ2luLXByb2dyZXNzJywgJ2NvbXBsZXRlZCcgfQogICAgKQogICAgdW5pb24KICAgICgKICAgICAgW1NlcnZpY2VSZXF1ZXN0OiBjb2RlIGluICJIb3NwaWNlIFByb2NlZHVyZSBDb2RlcyJdIEUKICAgICAgICB3aGVyZSBFLnN0YXR1cyBpbiB7ICdwbGFubmVkJywgJ2Fycml2ZWQnLCAnaW4tcHJvZ3Jlc3MnLCAnZmluaXNoZWQnLCAnb25sZWF2ZScgfQogICAgKQogICAgdW5pb24KICAgICgKICAgICAgW09ic2VydmF0aW9uOiBjb2RlIGluICJIb3NwaWNlIEZpbmRpbmcgQ29kZXMiXSBPCiAgICAgICAgd2hlcmUgbm90IChPLnN0YXR1cyBpbiB7ICd1bmtub3duJywgJ2VudGVyZWQtaW4tZXJyb3InLCAnY2FuY2VsbGVkJyB9KQogICAgKQogICAgdW5pb24KICAgICgKICAgICAgW0VuY291bnRlcl0gRQogICAgICAgIHdoZXJlCiAgICAgICAgICAoCiAgICAgICAgICAgIGlmIEUuaG9zcGl0YWxpemF0aW9uLmRpc2NoYXJnZURpc3Bvc2l0aW9uLmNvZGluZyBpcyBudWxsCiAgICAgICAgICAgICAgICBvciBub3QgZXhpc3RzIChFLmhvc3BpdGFsaXphdGlvbi5kaXNjaGFyZ2VEaXNwb3NpdGlvbi5jb2RpbmcpCiAgICAgICAgICAgICAgdGhlbiBmYWxzZQogICAgICAgICAgICBlbHNlIEUuaG9zcGl0YWxpemF0aW9uLmRpc2NoYXJnZURpc3Bvc2l0aW9uIGluICJIb3NwaWNlIERpc3Bvc2l0aW9uIgogICAgICAgICAgKQogICAgICAgICAgYW5kIEUuc3RhdHVzIGluIHsgJ3BsYW5uZWQnLCAnYXJyaXZlZCcsICdpbi1wcm9ncmVzcycsICdmaW5pc2hlZCcsICdvbmxlYXZlJyB9CiAgICApCiAgKQoKZGVmaW5lIGZ1bmN0aW9uIFByZXNjcmlwdGlvbnMoT3JkZXJzIExpc3Q8TWVkaWNhdGlvblJlcXVlc3Q+KToKICBPcmRlcnMgTwogICAgbGV0CiAgICAgIC8vIE5PVEU6IEFzc3VtaW5nIG1lZGljYXRpb24gaXMgc3BlY2lmaWVkIGFzIGEgQ29kZWFibGVDb25jZXB0IHdpdGggYSBzaW5nbGUgUnhOb3JtIGNvZGUKICAgICAgcnhOb3JtQ29kZTogVG9Db2RlKE8ubWVkaWNhdGlvbi5jb2RpbmdbMF0pLAogICAgICBtZWRpY2F0aW9uTmFtZTogT01US0xvZ2ljLkdldE1lZGljYXRpb25OYW1lKHJ4Tm9ybUNvZGUpLAogICAgICAvLyBOT1RFOiBBc3N1bWluZyBhIHNpbmdsZSBkb3NhZ2UgaW5zdHJ1Y3Rpb24gZWxlbWVudAogICAgICBkb3NhZ2VJbnN0cnVjdGlvbjogTy5kb3NhZ2VJbnN0cnVjdGlvblswXSwKICAgICAgcmVwZWF0OiBkb3NhZ2VJbnN0cnVjdGlvbi50aW1pbmcucmVwZWF0LAogICAgICBmcmVxdWVuY3k6IENvYWxlc2NlKHJlcGVhdC5mcmVxdWVuY3lNYXgudmFsdWUsIHJlcGVhdC5mcmVxdWVuY3kudmFsdWUpLAogICAgICBwZXJpb2Q6IFN5c3RlbS5RdWFudGl0eSB7IHZhbHVlOiByZXBlYXQucGVyaW9kLnZhbHVlLCB1bml0OiByZXBlYXQucGVyaW9kVW5pdC52YWx1ZSB9LAogICAgICBkb3NlRGVzY3JpcHRpb246CiAgICAgICAgQ29hbGVzY2UoCiAgICAgICAgICAvLyBUaGVyZSBzaG91bGQgYmUgYSBjb252ZXJzaW9uIGZyb20gRkhJUi5TaW1wbGVRdWFudGl0eSB0byBTeXN0ZW0uUXVhbnRpdHkKICAgICAgICAgIGlmIGRvc2FnZUluc3RydWN0aW9uLmRvc2VBbmRSYXRlWzBdLmRvc2UgaXMgRkhJUi5SYW5nZQogICAgICAgICAgICB0aGVuIFRvU3RyaW5nKFRvUXVhbnRpdHkoZG9zYWdlSW5zdHJ1Y3Rpb24uZG9zZUFuZFJhdGVbMF0uZG9zZS5sb3cpKQogICAgICAgICAgICAgICAgICAgICAgICAgICsgJy0nICsgVG9TdHJpbmcoVG9RdWFudGl0eShkb3NhZ2VJbnN0cnVjdGlvbi5kb3NlQW5kUmF0ZVswXS5kb3NlLmhpZ2gpKQogICAgICAgICAgICAgICAgICAgICAgICAgICsgZG9zYWdlSW5zdHJ1Y3Rpb24uZG9zZUFuZFJhdGVbMF0uZG9zZS5oaWdoLnVuaXQudmFsdWUKICAgICAgICAgICAgZWxzZSBUb1N0cmluZyhUb1F1YW50aXR5KGRvc2FnZUluc3RydWN0aW9uLmRvc2VBbmRSYXRlWzBdLmRvc2UpKSwKICAgICAgICAgICAgJycKICAgICAgICApLAogICAgICBmcmVxdWVuY3lEZXNjcmlwdGlvbjoKICAgICAgICBUb1N0cmluZyhkb3NhZ2VJbnN0cnVjdGlvbi50aW1pbmcucmVwZWF0LmZyZXF1ZW5jeS52YWx1ZSkgKwogICAgICAgICAgQ29hbGVzY2UoCiAgICAgICAgICAgICctJyArIFRvU3RyaW5nKGRvc2FnZUluc3RydWN0aW9uLnRpbWluZy5yZXBlYXQuZnJlcXVlbmN5TWF4LnZhbHVlKSwKICAgICAgICAgICAgJycKICAgICAgICAgICkKICAgIHJldHVybiB7CiAgICAgIHJ4Tm9ybUNvZGU6IHJ4Tm9ybUNvZGUsCiAgICAgIGlzRHJhZnQ6IE8uc3RhdHVzLnZhbHVlID0gJ2RyYWZ0JywKICAgICAgLy8gTk9URTogQXNzdW1pbmcgYXNOZWVkZWQgaXMgZXhwcmVzc2VkIGFzIGEgYm9vbGVhbgogICAgICBpc1BSTjogZG9zYWdlSW5zdHJ1Y3Rpb24uYXNOZWVkZWQudmFsdWUsCiAgICAgIHByZXNjcmlwdGlvbjoKICAgICAgICBpZiBkb3NhZ2VJbnN0cnVjdGlvbi50ZXh0IGlzIG5vdCBudWxsIHRoZW4KICAgICAgICAgIG1lZGljYXRpb25OYW1lICsgJyAnICsgZG9zYWdlSW5zdHJ1Y3Rpb24udGV4dC52YWx1ZQogICAgICAgIGVsc2UKICAgICAgICAgIC8vIFRPRE86IFNob3VsZG4ndCBuZWVkIHRoZSAudmFsdWUgaGVyZSBvbiBhc05lZWRlZEJvb2xlYW4KICAgICAgICAgIG1lZGljYXRpb25OYW1lICsgJyAnICsgZG9zZURlc2NyaXB0aW9uICsgJyBxJyArIGZyZXF1ZW5jeURlc2NyaXB0aW9uICsgKGlmIGRvc2FnZUluc3RydWN0aW9uLmFzTmVlZGVkLnZhbHVlIHRoZW4gJyBQUk4nIGVsc2UgJycpLAogICAgICAvLyBUT0RPOiBTaG91bGRuJ3QgbmVlZCB0aGUgVG9RdWFudGl0eSBoZXJlLi4uCiAgICAgIGRvc2U6IGlmIGRvc2FnZUluc3RydWN0aW9uLmRvc2VBbmRSYXRlWzBdLmRvc2UgaXMgRkhJUi5SYW5nZQogICAgICAgICAgICB0aGVuIFRvUXVhbnRpdHkoZG9zYWdlSW5zdHJ1Y3Rpb24uZG9zZUFuZFJhdGVbMF0uZG9zZS5oaWdoKQogICAgICAgICAgICBlbHNlIFRvUXVhbnRpdHkoZG9zYWdlSW5zdHJ1Y3Rpb24uZG9zZUFuZFJhdGVbMF0uZG9zZSksCiAgICAgIGRvc2VzUGVyRGF5OiBDb2FsZXNjZShPTVRLTG9naWMuVG9EYWlseShmcmVxdWVuY3ksIHBlcmlvZCksIDEuMCkKICAgIH0KCmRlZmluZSBmdW5jdGlvbiBNTUUocHJlc2NyaXB0aW9ucyBMaXN0PE1lZGljYXRpb25SZXF1ZXN0Pik6CiAgKFByZXNjcmlwdGlvbnMocHJlc2NyaXB0aW9ucykpIFAKICAgIGxldCBtbWU6IFNpbmdsZXRvbkZyb20oT01US0xvZ2ljLkNhbGN1bGF0ZU1NRXMoeyB7IHJ4Tm9ybUNvZGU6IFAucnhOb3JtQ29kZSwgZG9zZVF1YW50aXR5OiBQLmRvc2UsIGRvc2VzUGVyRGF5OiBQLmRvc2VzUGVyRGF5IH0gfSkpCiAgICByZXR1cm4gewogICAgICByeE5vcm1Db2RlOiBQLnJ4Tm9ybUNvZGUsCiAgICAgIGlzRHJhZnQ6IFAuaXNEcmFmdCwKICAgICAgaXNQUk46IFAuaXNQUk4sCiAgICAgIHByZXNjcmlwdGlvbjogUC5wcmVzY3JpcHRpb24sCiAgICAgIGRhaWx5RG9zZTogbW1lLmRhaWx5RG9zZURlc2NyaXB0aW9uLAogICAgICBjb252ZXJzaW9uRmFjdG9yOiBtbWUuY29udmVyc2lvbkZhY3RvciwKICAgICAgbW1lOiBtbWUubW1lCiAgICB9CgpkZWZpbmUgZnVuY3Rpb24gVG90YWxNTUUocHJlc2NyaXB0aW9ucyBMaXN0PE1lZGljYXRpb25SZXF1ZXN0Pik6CiAgU3lzdGVtLlF1YW50aXR5IHsKICAgIHZhbHVlOiBTdW0oKE1NRShwcmVzY3JpcHRpb25zKSkgTSByZXR1cm4gTS5tbWUudmFsdWUpLAogICAgdW5pdDogJ21nL2QnCiAgfQoKZGVmaW5lIGZ1bmN0aW9uIFByb2JhYmxlRGF5c0luUmFuZ2UoT3JkZXJzIExpc3Q8TWVkaWNhdGlvblJlcXVlc3Q+LCBkYXlzUGFzdCBJbnRlZ2VyLCBudW1EYXlzSW5EYXlzUGFzdCBJbnRlZ2VyKToKICBPcmRlcnMgb3JkZXJzCiAgICBsZXQKICAgICAgZnJlcXVlbmN5OiBvcmRlcnMuZG9zYWdlSW5zdHJ1Y3Rpb25bMF0udGltaW5nLnJlcGVhdC5mcmVxdWVuY3kudmFsdWUsCiAgICAgIHBlcmlvZDogb3JkZXJzLmRvc2FnZUluc3RydWN0aW9uWzBdLnRpbWluZy5yZXBlYXQucGVyaW9kLnZhbHVlLAogICAgICBwZXJpb2REYXlzOiBHZXRQZXJpb2REYXlzKG9yZGVycy5kb3NhZ2VJbnN0cnVjdGlvblswXS50aW1pbmcucmVwZWF0LnBlcmlvZFVuaXQudmFsdWUpLAogICAgICBkb3Nlc1BlckRheToKICAgICAgICBpZiAoZnJlcXVlbmN5IC8gKHBlcmlvZCAqIHBlcmlvZERheXMpKSA+PSAxLjAKICAgICAgICB0aGVuIDEuMAogICAgICAgIGVsc2UgZnJlcXVlbmN5IC8gKHBlcmlvZCAqIHBlcmlvZERheXMpLAogICAgICByZXBlYXQ6IG9yZGVycy5kaXNwZW5zZVJlcXVlc3QubnVtYmVyT2ZSZXBlYXRzQWxsb3dlZC52YWx1ZSwKICAgICAgc3VwcGx5RHVyYXRpb246IEdldER1cmF0aW9uSW5EYXlzKG9yZGVycy5kaXNwZW5zZVJlcXVlc3QuZXhwZWN0ZWRTdXBwbHlEdXJhdGlvbiksCiAgICAgIHZhbGlkaXR5UGVyaW9kOiBkYXlzIGJldHdlZW4gb3JkZXJzLmRpc3BlbnNlUmVxdWVzdC52YWxpZGl0eVBlcmlvZC4ic3RhcnQiLnZhbHVlIGFuZCBUb2RheSgpLAogICAgICBlbmREaWZmZXJlbmNlOgogICAgICAgIGlmIG9yZGVycy5kaXNwZW5zZVJlcXVlc3QudmFsaWRpdHlQZXJpb2QuImVuZCIudmFsdWUgPCBUb2RheSgpCiAgICAgICAgdGhlbiBkYXlzIGJldHdlZW4gb3JkZXJzLmRpc3BlbnNlUmVxdWVzdC52YWxpZGl0eVBlcmlvZC4iZW5kIi52YWx1ZSBhbmQgVG9kYXkoKQogICAgICAgIGVsc2UgMAogICAgcmV0dXJuCiAgICAgIGlmIChyZXBlYXQgKiBzdXBwbHlEdXJhdGlvbikgPCBudW1EYXlzSW5EYXlzUGFzdCB0aGVuIGZhbHNlCiAgICAgIGVsc2UKICAgICAgICAoZG9zZXNQZXJEYXkgKiAoKHJlcGVhdCAqIHN1cHBseUR1cmF0aW9uKSAvIHZhbGlkaXR5UGVyaW9kKSAqIChkYXlzUGFzdCAtIGVuZERpZmZlcmVuY2UpKSA+PSBudW1EYXlzSW5EYXlzUGFzdAoKZGVmaW5lIGZ1bmN0aW9uIEdldFBlcmlvZERheXModmFsdWUgU3lzdGVtLlN0cmluZyk6CiAgY2FzZQogICAgd2hlbiB2YWx1ZSA9ICdhJyB0aGVuIDM2NS4wCiAgICB3aGVuIHZhbHVlID0gJ21vJyB0aGVuIDMwLjAKICAgIHdoZW4gdmFsdWUgPSAnaCcgdGhlbiAxLjAvMjQuMAogICAgd2hlbiB2YWx1ZSA9ICdtaW4nIHRoZW4gMS4wLzI0LjAqNjAuMAogICAgd2hlbiB2YWx1ZSA9ICdzJyB0aGVuIDEuMC8yNC4wKjYwLjAqNjAuMAogICAgd2hlbiB2YWx1ZSA9ICdtcycgdGhlbiAxLjAvMjQuMCo2MC4wKjYwLjAqMTAwMC4wCiAgICBlbHNlIDEuMAogIGVuZAoKICBkZWZpbmUgZnVuY3Rpb24gR2V0RHVyYXRpb25JbkRheXModmFsdWUgRkhJUi5EdXJhdGlvbik6CiAgICBjYXNlCiAgICAgIHdoZW4gU3RhcnRzV2l0aCh2YWx1ZS51bml0LnZhbHVlLCAnYScpIHRoZW4gdmFsdWUudmFsdWUudmFsdWUgKiAzNjUuMAogICAgICB3aGVuIFN0YXJ0c1dpdGgodmFsdWUudW5pdC52YWx1ZSwgJ21vJykgdGhlbiB2YWx1ZS52YWx1ZS52YWx1ZSAqIDMwLjAKICAgICAgd2hlbiBTdGFydHNXaXRoKHZhbHVlLnVuaXQudmFsdWUsICd3aycpIHRoZW4gdmFsdWUudmFsdWUudmFsdWUgKiA3LjAKICAgICAgd2hlbiBTdGFydHNXaXRoKHZhbHVlLnVuaXQudmFsdWUsICdkJykgdGhlbiB2YWx1ZS52YWx1ZS52YWx1ZQogICAgICB3aGVuIFN0YXJ0c1dpdGgodmFsdWUudW5pdC52YWx1ZSwgJ2gnKSB0aGVuIHZhbHVlLnZhbHVlLnZhbHVlIC8gMjQuMAogICAgICB3aGVuIFN0YXJ0c1dpdGgodmFsdWUudW5pdC52YWx1ZSwgJ21pbicpIHRoZW4gdmFsdWUudmFsdWUudmFsdWUgLyA2MC4wIC8gMjQuMAogICAgICB3aGVuIFN0YXJ0c1dpdGgodmFsdWUudW5pdC52YWx1ZSwgJ3MnKSB0aGVuIHZhbHVlLnZhbHVlLnZhbHVlIC8gNjAuMCAvIDYwLjAgLyAyNC4wCiAgICAgIHdoZW4gU3RhcnRzV2l0aCh2YWx1ZS51bml0LnZhbHVlLCAnbXMnKSB0aGVuIHZhbHVlLnZhbHVlLnZhbHVlIC8gNjAuMCAvIDYwLjAgLyAyNC4wIC8gMTAwMC4wCiAgICAgIGVsc2UgTWVzc2FnZSgxMDAwLCB0cnVlLCAnVW5kZWZpbmVkJywgJ0Vycm9yJywgJ1Vuc3VwcG9ydGVkIGR1cmF0aW9uIHVuaXQnKQogICAgZW5kCgpkZWZpbmUgZnVuY3Rpb24gR2V0SW5ncmVkaWVudChyeE5vcm1Db2RlIENvZGUpOgogIE9NVEtMb2dpYy5HZXRJbmdyZWRpZW50cyhyeE5vcm1Db2RlKS5pbmdyZWRpZW50TmFtZQoKZGVmaW5lIGZ1bmN0aW9uIEdldEluZ3JlZGllbnRzKHJ4Tm9ybUNvZGVzIExpc3Q8Q29kZT4pOgogIHJ4Tm9ybUNvZGVzIHJuYyByZXR1cm4gR2V0SW5ncmVkaWVudChybmMpCgpkZWZpbmUgZnVuY3Rpb24gR2V0TWVkaWNhdGlvbk5hbWVzKG1lZGljYXRpb25zIExpc3Q8TWVkaWNhdGlvblJlcXVlc3Q+KToKICBtZWRpY2F0aW9ucyBNCiAgICByZXR1cm4gT01US0xvZ2ljLkdldEluZ3JlZGllbnRzKFRvUnhOb3JtQ29kZShNLm1lZGljYXRpb24uY29kaW5nKSkucnhOb3JtQ29kZS5kaXNwbGF5CgovKgoqICBDb252ZXJzaW9uIEZ1bmN0aW9ucwoqLwoKZGVmaW5lIGZ1bmN0aW9uIFRvQ29kZShjb2RpbmcgRkhJUi5Db2RpbmcpOgogIFN5c3RlbS5Db2RlIHsKICAgIGNvZGU6IGNvZGluZy5jb2RlLnZhbHVlLAogICAgc3lzdGVtOiBjb2Rpbmcuc3lzdGVtLnZhbHVlLAogICAgdmVyc2lvbjogY29kaW5nLnZlcnNpb24udmFsdWUsCiAgICBkaXNwbGF5OiBjb2RpbmcuZGlzcGxheS52YWx1ZQogIH0KCmRlZmluZSBmdW5jdGlvbiBUb0NvZGVzKGNvZGluZyBMaXN0PEZISVIuQ29kaW5nPik6CiAgY29kaW5nIGMgcmV0dXJuIFRvQ29kZShjKQoKZGVmaW5lIGZ1bmN0aW9uIFRvUnhOb3JtQ29kZShjb2RpbmcgTGlzdDxGSElSLkNvZGluZz4pOgogIHNpbmdsZXRvbiBmcm9tICgKICAgIGNvZGluZyBDIHdoZXJlIEMuc3lzdGVtID0gJ2h0dHA6Ly93d3cubmxtLm5paC5nb3YvcmVzZWFyY2gvdW1scy9yeG5vcm0nCiAgKQoKZGVmaW5lIGZ1bmN0aW9uIFRvUXVhbnRpdHkocXVhbnRpdHkgRkhJUi5RdWFudGl0eSk6CiAgU3lzdGVtLlF1YW50aXR5IHsgdmFsdWU6IHF1YW50aXR5LnZhbHVlLnZhbHVlLCB1bml0OiBxdWFudGl0eS51bml0LnZhbHVlIH0K"^^xsd:base64Binary ]
  ] [
fhir:contentType [ fhir:v "application/elm+xml" ]
  ] ) . #