Clinical Practice Guidelines Example Implementation Guide - Anthrax Post-Exposure Prophylaxis
1.1.0 - ci-build
Clinical Practice Guidelines Example Implementation Guide - Anthrax Post-Exposure Prophylaxis, published by HL7 International - Clinical Decision Support WG. This guide is not an authorized publication; it is the continuous build for version 1.1.0 built by the FHIR (HL7® FHIR® Standard) CI Build. This version is based on the current content of https://github.com/cqframework/cpg-example-anthrax/ and changes regularly. See the Directory of published versions
Draft as of 2024-08-23 |
{
"resourceType" : "Library",
"id" : "cds-connect-commons-library",
"text" : {
"status" : "generated",
"div" : "<div xmlns=\"http://www.w3.org/1999/xhtml\"><p class=\"res-header-id\"><b>Generated Narrative: Library cds-connect-commons-library</b></p><a name=\"cds-connect-commons-library\"> </a><a name=\"hccds-connect-commons-library\"> </a><a name=\"cds-connect-commons-library-en-US\"> </a><h2>Participants</h2><table class=\"grid\"><tr><td>Author</td><td>Alliance to Modernize Healthcare FFRDC</td></tr><tr><td>Endorser</td><td>Centers for Disease Control and Prevention</td></tr></table><h2>Contents</h2><p><code>text/cql</code></p><pre><code>// CDS Connect Commons for FHIRv400\n// Change log:\n// - 1.3.1:\n// - Changed C.dateRecorded to C.dateRecorded.value in ConditionLookBack\n// - Changed G.statusDate to G.statusDate.value in GoalLookBack\n// - 1.3.2:\n// - Added NotCancelled() and EncounterLookback() functions.\nlibrary CDS_Connect_Commons_for_FHIRv400 version '1.3.2'\n\nusing FHIR version '4.0.0'\n\n// Include the FHIRHelpers library for simplifying interacton w/ the FHIR data model\ninclude FHIRHelpers version '4.0.0' called FHIRHelpers\n\ncodesystem "Condition Verification Status Codes": 'http://terminology.hl7.org/CodeSystem/condition-ver-status'\ncodesystem "Condition Clinical Status Codes": 'http://terminology.hl7.org/CodeSystem/condition-clinical'\ncodesystem "AllergyIntolerance Verification Status Codes": 'http://terminology.hl7.org/CodeSystem/allergyintolerance-verification'\n\ncode "Condition verificationStatus confirmed code": 'confirmed' from "Condition Verification Status Codes" display 'Confirmed'\ncode "Condition clinicalStatus active code": 'active' from "Condition Clinical Status Codes" display 'Active'\ncode "Condition clinicalStatus recurrence code": 'recurrence' from "Condition Clinical Status Codes" display 'Recurrence'\ncode "Condition clinicalStatus relapse code": 'relapse' from "Condition Clinical Status Codes" display 'Relapse'\ncode "AllergyIntolerance verificationStatus confirmed code": 'confirmed' from "AllergyIntolerance Verification Status Codes" display 'Confirmed'\n\n// -------------------------------------------------- GENERAL ---------------------------------------------------------\n\n/**\n * A null-safe version of ToConcept. Whereas FHIRHelpers.ToConcept will take a null argument and produce a\n * System.Concept that is empty, this implementation returns null instead.\n * @param C - a FHIR CodeableConcept\n * @returns {System.Concept} a CQL Concept or null if null was passed in\n */\ndefine function NullSafeToConcept(Cpt FHIR.CodeableConcept):\n if Cpt is not null then FHIRHelpers.ToConcept(Cpt) else null\n\n/**\n * A null-safe version of ToInterval for Period. Whereas FHIRHelpers.ToInterval will take a null argument and produce a\n * System.Interval that is empty, this implementation returns null instead.\n * @param P - a FHIR Period\n * @returns {System.Interval} a CQL Interval or null if null was passed in\n */\ndefine function NullSafePeriodToInterval(Pd FHIR.Period):\n if Pd is not null then Interval[Pd."start".value, Pd."end".value] else null\n\n/**\n * A null-safe version of ToInterval for Range. Whereas FHIRHelpers.ToInterval will take a null argument and produce a\n * System.Interval that is empty, this implementation returns null instead.\n * @param P - a FHIR Range\n * @returns {System.Interval} a CQL Interval or null if null was passed in\n */\ndefine function NullSafeRangeToInterval(Rg FHIR.Range):\n if Rg is not null\n then Interval[NullSafeToQuantity(Rg.low), NullSafeToQuantity(Rg.high)]\n else null\n\n/**\n * Same as NullSafePeriodToInterval; kept for backward compatibility. [Deprecated]\n * @param P - a FHIR Period\n * @returns {System.Interval} a CQL Interval or null if null was passed in\n */\ndefine function NullSafeToInterval(Pd FHIR.Period):\n NullSafePeriodToInterval(Pd)\n\n/**\n * A null-safe version of ToQuantity. Whereas FHIRHelpers.ToQuantity will take a null argument and produce a\n * System.Quantity that is empty, this implementation returns null instead.\n * @param C - a FHIR Quantity\n * @returns {System.Quantity} a CQL Quantity or null if null was passed in\n */\ndefine function NullSafeToQuantity(Qty FHIR.Quantity):\n if Qty is not null then\n System.Quantity {\n value: Qty.value.value,\n unit: Coalesce(Qty.unit.value, Qty.code.value)\n }\n else null\n\n// -------------------------------------------------- OBSERVATIONS -----------------------------------------------------\n\n/**\n * Filters Observations by a concept rather than by a ValueSet. In CQL 1.3, this will be built into the retrieve,\n * but for now, we must use a query where clause.\n * @param Koncept - the concept to filter on (intentionally mispelled to avoid naming clashes)\n * @returns {List<Observation>} a list of Observations matching the concept, or null if null was passed in\n */\ndefine function ObservationsByConcept(Koncept System.Concept):\n [Observation] O where NullSafeToConcept(O.code) ~ Koncept\n\n/**\n * Observations that are complete and verified. In FHIR R4, there are two statuses that indicate this state: 'final'\n * and 'amended'.\n * @see https://www.hl7.org/fhir/valueset-observation-status.html\n * @param ObsList - a list of Observations\n * @returns {List<Observation>} a list of verified Observations, or null if null was passed in\n */\ndefine function Verified(ObsList List<Observation>):\n ObsList O where O.status.value in {'final', 'amended'}\n\n/**\n * Observations that have quantity values recorded in the requested unit.\n * @param ObsList - a list of Observations\n * @param Unit - the unit to require in the Observations quantity value\n * @returns {List<Observation>} a list of Observations with the required unit, or null if null was passed in\n */\ndefine function WithUnit(ObsList List<Observation>, Unit String):\n ObsList O where O.value.unit.value = Unit or O.value.code.value = Unit\n\n/**\n * Observations with an effective or issued date in the specified "look back" period. For example, LDL-C Tests in the\n * last 6 years.\n * TODO: Rename to LookBack once the execution engine supports overloaded functions.\n * @param ObsList - a list of Observations\n * @returns {List<Observation>} a list of Observations with effective or issued date specified lookback period, or null\n * if null was passed in\n */\ndefine function ObservationLookBack(ObsList List<Observation>, LookBack System.Quantity):\n ObsList O\n let LookBackInterval: Interval[Now() - LookBack, Now()]\n where O.effective.value in LookBackInterval\n or NullSafeToInterval(O.effective) overlaps LookBackInterval\n or O.issued.value in LookBackInterval\n\n/**\n * The most recent observation. For each Observation, this algorithm will use the FindDate function, which uses the\n * first non-null date value from these fields: effectiveDateTime, effectivePeriod.end, effectivePeriod.start, issued.\n * The found date will be used to compare Observations and determine the most recent one.\n * @see FindDate(Observation)\n * @param ObsList - a list of Observations\n * @returns {Observation} the most recent Observation from the list, or null if null was passed in\n */\ndefine function MostRecent(ObsList List<Observation>):\n Last(ObsList O sort by Coalesce(effective.value, effective."end".value, effective."start".value, issued.value))\n\n/**\n * Extracts the quantity value from an Observation, returning it as a CQL Quantity\n * @param Obs - an observation\n * @returns {System.Quantity} the Observation's value as a quantity, or null if there is no quantity value\n */\ndefine function QuantityValue(Obs Observation):\n NullSafeToQuantity(Obs.value)\n\n/**\n * Extracts the CodeableConcept value from an Observation, returning it as a CQL Concept\n * @param Obs - an observation\n * @returns {System.Concept} the Observation's value as a concept, or null if there is no CodeabeConcept value\n */\ndefine function ConceptValue(Obs Observation):\n NullSafeToConcept(Obs.value)\n\n/**\n * Finds the first non-null meaningful date that can be associated with this Observation. This will look through the\n * following fields in the following order: effectiveDateTime, effectivePeriod.end, effectivePeriod.start, issued.\n * @param Obs - an Observation\n * @returns {System.DateTime} the first non-null meaningful date, or null if non is found\n */\ndefine function FindDate(Obs Observation):\n Coalesce(Obs.effective.value, Obs.effective."end".value, Obs.effective."start".value, Obs.issued.value)\n\n// TODO: Confirm that this works as expected\n/**\n * The highest observation.\n * The value will be used to compare Observations and determine the highest one.\n * @param ObsList - a list of Observations\n * @returns {System.Quantity} the quantity with the highest value from the list, or null if null was passed in\n */\ndefine function HighestObservation(ObsList List<Observation>):\n Max(ObsList O return NullSafeToQuantity(O.value))\n\n\n// -------------------------------------------------- CONDITIONS -------------------------------------------------------\n\n/**\n * Filters Conditions by a concept rather than by a ValueSet. In CQL 1.3, this will be built into the retrieve,\n * but for now, we must use a query where clause.\n * @param Koncept - the concept to filter on (intentionally mispelled to avoid naming clashes)\n * @returns {List<Observation>} a list of Conditions matching the concept, or null if null was passed in\n */\ndefine function ConditionsByConcept(Koncept System.Concept):\n [Condition] C where NullSafeToConcept(C.code) ~ Koncept\n\n/**\n * Conditions that are confirmed. In FHIR R4, this is reflected by verificationStatus: 'confirmed'.\n * @see https://www.hl7.org/fhir/valueset-condition-ver-status.html\n * @param CondList - a list of Conditions\n * @returns {List<Condition>} a list of confirmed Conditions, or null if null was passed in\n */\ndefine function Confirmed(CondList List<Condition>):\n CondList C where C.verificationStatus.coding ~ "Condition verificationStatus confirmed code"\n\n/**\n * Conditions that are active. In FHIR R4, this is reflected by clinicalStatus: 'active' and the absence of any\n * abatement information (i.e., if it abated, it is no longer active).\n * TODO: Rename to Active once the execution engine supports overloaded functions.\n * @see https://www.hl7.org/fhir/valueset-condition-clinical.html\n * @param CondList - a list of Conditions\n * @returns {List<Condition>} a list of active Conditions, or null if null was passed in\n */\ndefine function ActiveCondition(CondList List<Condition>):\n CondList C\n where C.clinicalStatus.coding ~ "Condition clinicalStatus active code"\n and C.abatement is null\n\n/**\n * Conditions that are active or recurring. In FHIR R4, this is reflected by clinicalStatus: 'active', 'recurrence', or 'relapse'.\n * We do not check for null abatement information because it may have dates from when the now recurring condition\n * initially went into remission.\n * @see https://www.hl7.org/fhir/valueset-condition-clinical.html\n * @param CondList - a list of Conditions\n * @returns {List<Condition>} a list of active or recurring Conditions, or null if null was passed in\n */\ndefine function ActiveOrRecurring(CondList List<Condition>):\n CondList C where C.clinicalStatus.coding ~ "Condition clinicalStatus active code"\n or C.clinicalStatus.coding ~ "Condition clinicalStatus recurrence code"\n or C.clinicalStatus.coding ~ "Condition clinicalStatus relapse code"\n\n/**\n * Conditions with an onset or recorded date in the specified "look back" period. For example, pregnancy in\n * the last 42 weeks.\n * TODO: Rename to LookBack once the execution engine supports overloaded functions.\n * @param CondList - a list of Conditions\n * @returns {List<Condition>} a list of Conditions with onset or recorded date specified lookback period, or null\n * if null was passed in\n */\ndefine function ConditionLookBack(CondList List<Condition>, LookBack System.Quantity):\n CondList C\n let LookBackInterval: Interval[Now() - LookBack, Now()]\n where C.onset.value in LookBackInterval\n or NullSafeToInterval(C.onset) overlaps LookBackInterval\n or C.recordedDate.value in LookBackInterval\n // TODO Confirm these are the correct fields to use\n\n// -------------------------------------------------- PROCEDURES -------------------------------------------------------\n\n /**\n * Filters Procedures by a concept rather than by a ValueSet. In CQL 1.3, this will be built into the retrieve,\n * but for now, we must use a query where clause.\n * @param Koncept - the concept to filter on (intentionally mispelled to avoid naming clashes)\n * @returns {List<Procedure>} a list of Procedures matching the concept, or null if null was passed in\n */\n define function ProceduresByConcept(Koncept System.Concept):\n [Procedure] P where NullSafeToConcept(P.code) ~ Koncept\n\n/**\n * Procedures that are completed. In FHIR R4, this is reflected by status: 'completed'. In addition, the\n * notDone flag must be checked to ensure it is not 'true'.\n * @see https://www.hl7.org/fhir/valueset-event-status.html\n * @param ProcList - a list of Procedures\n * @returns {List<Procedure>} a list of completed Procedures, or null if null was passed in\n */\ndefine function Completed(ProcList List<Procedure>):\n ProcList P\n where P.status.value = 'completed'\n\n/**\n * Procedures that are in progress. In FHIR R4, this is reflected by status: 'in-progress'. In addition, the\n * notDone flag must be checked to ensure it is not 'true'.\n * @see https://www.hl7.org/fhir/valueset-event-status.html\n * @param ProcList - a list of Procedures\n * @returns {List<Procedure>} a list of completed Procedures, or null if null was passed in\n */\ndefine function ProcedureInProgress(ProcList List<Procedure>):\n ProcList P\n where P.status.value = 'in-progress'\n\n/**\n * Procedures that actually happened or are happening. In FHIR R4, there are a few properties that negate the\n * procedure, most notably when status is 'entered-in-error' or notDone is true.\n * @see https://www.hl7.org/fhir/valueset-event-status.html\n * @param ProcList - a list of Procedures\n * @returns {List<Procedure>} a list of Procedures that actually happened or are happening, or null if null was passed in\n */\ndefine function ProcedurePerformance(ProcList List<Procedure>):\n ProcList P\n where P.status.value != 'entered-in-error'\n\n/**\n * Procedures performed in the specified "look back" period. For example, PCIs performed in the\n * past 2 weeks.\n * TODO: Rename to LookBack once the execution engine supports overloaded functions.\n * @param ProcList - a list of Procedures\n * @param LookBack - the lookback period for when the procedure was performed\n * @returns {List<Procedure>} a list of Procedures performed in the look back period, or null if null\n * was passed in\n */\ndefine function ProcedureLookBack(ProcList List<Procedure>, LookBack System.Quantity):\n ProcList P\n let LookBackInterval: Interval[Now() - LookBack, Now()]\n where P.performed.value in LookBackInterval\n or NullSafeToInterval(P.performed) overlaps LookBackInterval\n\n// Note: ProcedureRequest and ReferralRequest resources have been replaced in FHIR R4 with the ServiceRequest resource.\n// TODO: When needed, come back and ServiceRequest helper functions.\n// // ---------------------------------------------- PROCEDUREREQUESTS ----------------------------------------------------\n\n// /**\n// * Filters ProcedureRequests by a concept rather than by a ValueSet. In CQL 1.3, this will be built into the retrieve,\n// * but for now, we must use a query where clause.\n// * @param Koncept - the concept to filter on (intentionally mispelled to avoid naming clashes)\n// * @returns {List<ProcedureRequest>} a list of ProcedureRequests matching the concept, or null if null was passed in\n// */\n// define function ProcedureRequestsByConcept(Koncept System.Concept):\n// [ProcedureRequest] P where NullSafeToConcept(P.code) ~ Koncept\n\n// /**\n// * ProcedureRequests that are accepted, in progress, or completed. In FHIR DSTU2, this is reflected by the corresponding\n// * status status values.\n// * @see http://hl7.org/fhir/DSTU2/valueset-procedure-request-status.html\n// * @param ProcReqList - a list of ProcedureRequests\n// * @returns {List<ProcedureRequest>} a list of accepted, in-progress, or completed ProcedureRequests,\n// * or null if null was passed in\n// */\n// define function ProcedureRequestAcceptedOrInProgressOrCompleted(ProcReqList List<ProcedureRequest>):\n// ProcReqList P\n// where P.status.value in List{'accepted', 'in-progress', 'completed'}\n\n// /**\n// * ProcedureRequests ordered in the specified "look back" period. For example, PCIs ordered in the\n// * past 2 weeks.\n// * TODO: Rename to LookBack once the execution engine supports overloaded functions.\n// * @param ProcReqList - a list of ProcedureRequests\n// * @param LookBack - the lookback period for when the procedure was ordered\n// * @returns {List<ProcedureRequest>} a list of ProcedureRequests ordered in the look back period, or null if null\n// * was passed in\n// */\n// define function ProcedureRequestLookBack(ProcReqList List<ProcedureRequest>, LookBack System.Quantity):\n// ProcReqList P\n// where P.authoredOn.value in Interval[Now() - LookBack, Now()]\n\n// // ----------------------------------------------- REFERRALREQUESTS ----------------------------------------------------\n\n// /**\n// * Filters ReferralRequests by a concept rather than by a ValueSet. In CQL 1.3, this will be built into the retrieve,\n// * but for now, we must use a query where clause.\n// * @param Koncept - the concept to filter on (intentionally mispelled to avoid naming clashes)\n// * @returns {List<ReferralRequest>} a list of ReferralRequests matching the concept, or null if null was passed in\n// */\n// define function ReferralRequestsByServiceRequestedConcept(Koncept System.Concept):\n// [ReferralRequest] R\n// where exists((R.serviceRequested) SRC where NullSafeToConcept(SRC) ~ Koncept)\n\n// /**\n// * ReferralRequests that are accepted, active, or completed. In FHIR DSTU2, this is reflected by the corresponding\n// * status status values.\n// * @see http://hl7.org/fhir/DSTU2/valueset-referralstatus.html\n// * @param ReferralList - a list of ReferralRequests\n// * @returns {List<ReferralRequest>} a list of accepted, active, or completed ReferralRequests,\n// * or null if null was passed in\n// */\n// define function ReferralRequestAcceptedOrActiveOrCompleted(ReferralList List<ReferralRequest>):\n// ReferralList R\n// where R.status.value in List{'accepted', 'active', 'completed'}\n\n// /**\n// * ReferralRequests requested in the specified "look back" period. For example, pace make insertions referrals sent\n// * in the past 2 weeks.\n// * TODO: Rename to LookBack once the execution engine supports overloaded functions.\n// * @param ReferralList - a list of ReferralRequests\n// * @param LookBack - the lookback period for when the referral was sent\n// * @returns {List<ReferralRequest>} a list of ReferralRequests sent in the look back period, or null if null\n// * was passed in\n// */\n// define function ReferralRequestLookBack(ReferralList List<ReferralRequest>, LookBack System.Quantity):\n// ReferralList R\n// where R.authoredOn.value in Interval[Now() - LookBack, Now()]\n\n// -------------------------------------------------- MEDICATIONS ------------------------------------------------------\n\n/**\n * Filters MedicationStatements by a concept rather than by a ValueSet. In CQL 1.3, this will be built into the retrieve,\n * but for now, we must use a query where clause.\n * @param Koncept - the concept to filter on (intentionally mispelled to avoid naming clashes)\n * @returns {List<MedicationStatement>} a list of MedicationStatement matching the concept, or null if null was passed in\n */\ndefine function MedicationStatementsByConcept(Koncept System.Concept):\n [MedicationStatement] M where NullSafeToConcept(M.medication) ~ Koncept\n\n/**\n * Filters MedicationRequests by a concept rather than by a ValueSet. In CQL 1.3, this will be built into the retrieve,\n * but for now, we must use a query where clause.\n * @param Koncept - the concept to filter on (intentionally mispelled to avoid naming clashes)\n * @returns {List<MedicationRequest>} a list of MedicationRequests matching the concept, or null if null was passed in\n */\ndefine function MedicationRequestsByConcept(Koncept System.Concept):\n [MedicationRequest] M where NullSafeToConcept(M.medication) ~ Koncept\n\n/**\n * Medications that are active, according to a statement, but not necessarily verified via a prescription. For example,\n * medications that a patient has self-reported to be taking. In FHIR R4, this is reflected by MedicationStatement\n * with status 'active', no flag indicating it wasn't taken, and no end date or an end date in the future.\n * TODO: Rename to Active once the execution engine supports overloaded functions.\n * @see https://www.hl7.org/fhir/valueset-medication-statement-status.html\n * @param MedList - a list of MedicationStatements\n * @returns {List<MedicationStatement>} a list of active medication statements, or null if null was passed in\n */\ndefine function ActiveMedicationStatement(MedList List<MedicationStatement>):\n MedList M\n let EffectivePeriod: NullSafeToInterval(M.effective)\n where M.status.value = 'active'\n and (end of EffectivePeriod is null or end of EffectivePeriod after Now())\n\n/**\n * Medications that are active or completed, according to a statement, but not necessarily verified via a prescription.\n * For example, medications that a patient has self-reported to be taking. In FHIR R4, this is reflected by\n * MedicationStatement with status 'active' or 'completed', and no flag indicating it wasn't taken.\n * TODO: Rename to ActiveOrCompleted once the execution engine supports overloaded functions.\n * @see https://www.hl7.org/fhir/valueset-medication-statement-status.html\n * @param MedList - a list of MedicationStatements\n * @returns {List<MedicationStatement>} a list of active or completed medication statements, or null if null was passed\n * in\n */\ndefine function ActiveOrCompletedMedicationStatement(MedList List<MedicationStatement>):\n MedList M\n where M.status.value = 'active'\n or M.status.value = 'completed'\n\n/**\n* Medications that are active, according to a prescription. In FHIR R4, this is reflected by MedicationRequest\n* with status 'active' and no dateEnded. There is currently an open question in the FHIR chat to determine if this\n* is the right approach.\n* @see https://www.hl7.org/fhir/valueset-medicationrequest-status.html\n* @param MedList - a list of MedicationRequests\n* @returns {List<MedicationRequest>} a list of active medication orders, or null if null was passed in\n*/\ndefine function ActiveMedicationRequest(MedList List<MedicationRequest>):\n MedList M\n where M.status.value = 'active'\n\n/**\n* Medications that are active or completed, according to a prescription. In FHIR R4, this is reflected by MedicationRequest\n* with status 'active' or 'completed'\n* @see https://www.hl7.org/fhir/valueset-medicationrequest-status.html\n* @param MedList - a list of MedicationRequests\n* @returns {List<MedicationRequest>} a list of active medication orders, or null if null was passed in\n*/\ndefine function ActiveOrCompletedMedicationRequest(MedList List<MedicationRequest>):\n MedList M\n where M.status.value = 'active'\n or M.status.value = 'completed'\n\n/**\n* Medications that are active, completed, or stopped, according to a prescription. In FHIR R4, this is reflected by\n* MedicationRequest with status 'active', 'completed', or 'stopped'\n* @see https://www.hl7.org/fhir/valueset-medicationrequest-status.html\n* @param MedList - a list of MedicationRequests\n* @returns {List<MedicationRequest>} a list of active medication orders, or null if null was passed in\n*/\ndefine function ActiveCompletedOrStoppedMedicationRequest(MedList List<MedicationRequest>):\n MedList M\n where M.status.value = 'active'\n or M.status.value = 'completed'\n or M.status.value = 'stopped'\n\n/**\n * MedicationStatement with an effective date in the specified "look back" period. For example, statements about opioid\n * use in the last 180 days.\n * TODO: Rename to LookBack once the execution engine supports overloaded functions.\n * @param MedList - a list of MedicationStatements\n * @param LookBack - a duration Quantity indicating how far back to look for MedicationStatements\n * @returns {List<MedicationStatement>} a list of MedicationStatements with effective date in the specified lookback\n * period, or null if null was passed in\n */\ndefine function MedicationStatementLookBack(MedList List<MedicationStatement>, LookBack System.Quantity):\n MedList M\n let LookBackInterval: Interval[Now() - LookBack, Now()]\n where M.effective.value in LookBackInterval\n or NullSafeToInterval(M.effective) overlaps LookBackInterval\n\n/**\n * MedicationRequests with a written date in the specified "look back" period. For example, opioid orders in the last\n * 180 days.\n * TODO: Rename to LookBack once the execution engine supports overloaded functions.\n * @param OrderList - a list of MedicationRequests\n * @param LookBack - a duration Quantity indicating how far back to look for MedicationRequests\n * @returns {List<MedicationRequest>} a list of MedicationRequests with written date in the specified lookback period,\n * or null if null was passed in\n */\ndefine function MedicationRequestLookBack(MedList List<MedicationRequest>, LookBack System.Quantity):\n MedList M where M.authoredOn.value in Interval[Now() - LookBack, Now()]\n\n// -------------------------------------------------- ENCOUNTERS ------------------------------------------------------\n\n/**\n * Filters Encounters by a concept rather than by a ValueSet. In CQL 1.3, this will be built into the retrieve,\n * but for now, we must use a query where clause.\n * @param Koncept - the concept to filter on (intentionally mispelled to avoid naming clashes)\n * @returns {List<Encounter>} a list of Encounters matching the concept, or null if null was passed in\n */\ndefine function EncountersByConcept(Koncept System.Concept):\n [Encounter] E where exists( (E.type) ET where NullSafeToConcept(ET) ~ Koncept )\n\n/**\n * Encounters that are in progress. In FHIR R4, this is reflected by status: 'in-progress'.\n * @see https://www.hl7.org/fhir/valueset-encounter-status.html\n * @param EncList - a list of Encounters\n * @returns {List<Encounter>} a list of in progress encounters, or null if null was passed in\n */\ndefine function InProgress(EncList List<Encounter>):\n EncList E\n where E.status.value = 'in-progress'\n\n/**\n * Encounters that have not been cancelled. In FHIR R4, this is reflected by andy status other \n * than: 'cancelled'.\n * @see https://www.hl7.org/fhir/valueset-encounter-status.html\n * @param EncList - a list of Encounters\n * @returns {List<Encounter>} a list of in progress encounters, or null if null was passed in\n */\ndefine function NotCancelled(EncList List<Encounter>):\n EncList E\n where E.status.value != 'cancelled'\n\n/**\n * Encounters performed in the specified "look back" period.\n * TODO: Rename to LookBack once the execution engine supports overloaded functions.\n * @param EncList - a list of Encounters\n * @param LookBack - the lookback period for when the encounter occurred\n * @returns {List<Encounter>} a list of Encounters occurring during the look back period, or null if null\n * was passed in\n */\ndefine function EncounterLookBack(EncList List<Encounter>, LookBack System.Quantity):\n EncList E\n let LookBackInterval: Interval[Now() - LookBack, Now()]\n where NullSafeToInterval(E.period) overlaps LookBackInterval\n\n// -------------------------------------------------- ALLERGY INTOLERANCES ---------------------------------------------\n\n/**\n * Filters AllergyIntolerances by a concept rather than by a ValueSet. In CQL 1.3, this will be built into the retrieve,\n * but for now, we must use a query where clause.\n * @param Koncept - the concept to filter on (intentionally mispelled to avoid naming clashes)\n * @returns {List<AllergyIntolerance>} a list of Allergy Intolerances matching the concept, or null if null was passed in\n */\ndefine function AllergyIntolerancesByConcept(Koncept System.Concept):\n [AllergyIntolerance] A where NullSafeToConcept(A.code) ~ Koncept\n\n/**\n* AllergyIntolerances that are active or confirmed. In FHIR R4, this is reflected by AllergyIntolerance\n* with verificationStatus 'active' or 'confirmed'\n* @see https://www.hl7.org/fhir/valueset-allergyintolerance-verification.html\n* @param AllergyIntolList - a list of AllergyIntolerances\n* @returns {List<AllergyIntolerance>} a list of active or confirmed allergy intolerances, or null if null was passed in\n*/\ndefine function ConfirmedAllergyIntolerance(AllergyIntolList List<AllergyIntolerance>):\n AllergyIntolList A\n where A.verificationStatus.coding ~ "AllergyIntolerance verificationStatus confirmed code"\n\n// -------------------------------------------------------- GOALS ------------------------------------------------------\n\n/**\n * Goals with a start, target, or status date in the specified "look back" period. For example, Pain Management Goals\n * in the last 2 years.\n * TODO: Rename to LookBack once the execution engine supports overloaded functions.\n * @param GoalList - a list of Goals\n * @returns {List<Goal>} a list of Goals with a start, target, or status date in the specified lookback period, or null\n * if null was passed in\n */\ndefine function GoalLookBack(GoalList List<Goal>, LookBack System.Quantity):\n GoalList G\n let LookBackInterval: Interval[Now() - LookBack, Now()]\n where G.start.value in LookBackInterval\n or G.target.dueD in LookBackInterval\n or G.start.value in LookBackInterval\n or G.statusDate.value in LookBackInterval\n</code></pre><p><code>No Content</code> (<code>application/elm+xml</code>)</p></div>"
},
"url" : "http://hl7.org/fhir/uv/cpg/anthrax/Library/cds-connect-commons-library",
"identifier" : [
{
"use" : "official",
"value" : "CDS_Connect_Commons_for_FHIRv400"
}
],
"version" : "1.1.0",
"name" : "CDS_Connect_Commons_for_FHIRv400_Library",
"title" : "CDS Connect Commons for FHIRv400",
"status" : "draft",
"experimental" : true,
"type" : {
"coding" : [
{
"system" : "http://terminology.hl7.org/CodeSystem/library-type",
"code" : "logic-library"
}
]
},
"date" : "2024-08-23T15:47:13+00:00",
"publisher" : "HL7 International - Clinical Decision Support WG",
"contact" : [
{
"name" : "HL7 International - Clinical Decision Support WG",
"telecom" : [
{
"system" : "url",
"value" : "http://www.hl7.org/Special/committees/dss/index.cfm"
}
]
}
],
"description" : "A library containing common methods used by CDS Connect-developed artifacts",
"jurisdiction" : [
{
"coding" : [
{
"system" : "http://unstats.un.org/unsd/methods/m49/m49.htm",
"code" : "001",
"display" : "World"
}
]
}
],
"topic" : [
{
"text" : "Anthrax"
},
{
"text" : "Emergency Medicine"
},
{
"text" : "Post-Exposure Prophylaxis"
}
],
"author" : [
{
"name" : "Alliance to Modernize Healthcare FFRDC"
}
],
"endorser" : [
{
"name" : "Centers for Disease Control and Prevention"
}
],
"content" : [
{
"contentType" : "text/cql",
"data" : "Ly8gQ0RTIENvbm5lY3QgQ29tbW9ucyBmb3IgRkhJUnY0MDAKLy8gQ2hhbmdlIGxvZzoKLy8gLSAxLjMuMToKLy8gICAtIENoYW5nZWQgQy5kYXRlUmVjb3JkZWQgdG8gQy5kYXRlUmVjb3JkZWQudmFsdWUgaW4gQ29uZGl0aW9uTG9va0JhY2sKLy8gICAtIENoYW5nZWQgRy5zdGF0dXNEYXRlIHRvIEcuc3RhdHVzRGF0ZS52YWx1ZSBpbiBHb2FsTG9va0JhY2sKLy8gLSAxLjMuMjoKLy8gICAtIEFkZGVkIE5vdENhbmNlbGxlZCgpIGFuZCBFbmNvdW50ZXJMb29rYmFjaygpIGZ1bmN0aW9ucy4KbGlicmFyeSBDRFNfQ29ubmVjdF9Db21tb25zX2Zvcl9GSElSdjQwMCB2ZXJzaW9uICcxLjMuMicKCnVzaW5nIEZISVIgdmVyc2lvbiAnNC4wLjAnCgovLyBJbmNsdWRlIHRoZSBGSElSSGVscGVycyBsaWJyYXJ5IGZvciBzaW1wbGlmeWluZyBpbnRlcmFjdG9uIHcvIHRoZSBGSElSIGRhdGEgbW9kZWwKaW5jbHVkZSBGSElSSGVscGVycyB2ZXJzaW9uICc0LjAuMCcgY2FsbGVkIEZISVJIZWxwZXJzCgpjb2Rlc3lzdGVtICJDb25kaXRpb24gVmVyaWZpY2F0aW9uIFN0YXR1cyBDb2RlcyI6ICdodHRwOi8vdGVybWlub2xvZ3kuaGw3Lm9yZy9Db2RlU3lzdGVtL2NvbmRpdGlvbi12ZXItc3RhdHVzJwpjb2Rlc3lzdGVtICJDb25kaXRpb24gQ2xpbmljYWwgU3RhdHVzIENvZGVzIjogJ2h0dHA6Ly90ZXJtaW5vbG9neS5obDcub3JnL0NvZGVTeXN0ZW0vY29uZGl0aW9uLWNsaW5pY2FsJwpjb2Rlc3lzdGVtICJBbGxlcmd5SW50b2xlcmFuY2UgVmVyaWZpY2F0aW9uIFN0YXR1cyBDb2RlcyI6ICdodHRwOi8vdGVybWlub2xvZ3kuaGw3Lm9yZy9Db2RlU3lzdGVtL2FsbGVyZ3lpbnRvbGVyYW5jZS12ZXJpZmljYXRpb24nCgpjb2RlICJDb25kaXRpb24gdmVyaWZpY2F0aW9uU3RhdHVzIGNvbmZpcm1lZCBjb2RlIjogJ2NvbmZpcm1lZCcgZnJvbSAiQ29uZGl0aW9uIFZlcmlmaWNhdGlvbiBTdGF0dXMgQ29kZXMiIGRpc3BsYXkgJ0NvbmZpcm1lZCcKY29kZSAiQ29uZGl0aW9uIGNsaW5pY2FsU3RhdHVzIGFjdGl2ZSBjb2RlIjogJ2FjdGl2ZScgZnJvbSAiQ29uZGl0aW9uIENsaW5pY2FsIFN0YXR1cyBDb2RlcyIgZGlzcGxheSAnQWN0aXZlJwpjb2RlICJDb25kaXRpb24gY2xpbmljYWxTdGF0dXMgcmVjdXJyZW5jZSBjb2RlIjogJ3JlY3VycmVuY2UnIGZyb20gIkNvbmRpdGlvbiBDbGluaWNhbCBTdGF0dXMgQ29kZXMiIGRpc3BsYXkgJ1JlY3VycmVuY2UnCmNvZGUgIkNvbmRpdGlvbiBjbGluaWNhbFN0YXR1cyByZWxhcHNlIGNvZGUiOiAncmVsYXBzZScgZnJvbSAiQ29uZGl0aW9uIENsaW5pY2FsIFN0YXR1cyBDb2RlcyIgZGlzcGxheSAnUmVsYXBzZScKY29kZSAiQWxsZXJneUludG9sZXJhbmNlIHZlcmlmaWNhdGlvblN0YXR1cyBjb25maXJtZWQgY29kZSI6ICdjb25maXJtZWQnIGZyb20gIkFsbGVyZ3lJbnRvbGVyYW5jZSBWZXJpZmljYXRpb24gU3RhdHVzIENvZGVzIiBkaXNwbGF5ICdDb25maXJtZWQnCgovLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSBHRU5FUkFMIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKLyoqCiAqIEEgbnVsbC1zYWZlIHZlcnNpb24gb2YgVG9Db25jZXB0LiAgV2hlcmVhcyBGSElSSGVscGVycy5Ub0NvbmNlcHQgd2lsbCB0YWtlIGEgbnVsbCBhcmd1bWVudCBhbmQgcHJvZHVjZSBhCiAqIFN5c3RlbS5Db25jZXB0IHRoYXQgaXMgZW1wdHksIHRoaXMgaW1wbGVtZW50YXRpb24gcmV0dXJucyBudWxsIGluc3RlYWQuCiAqIEBwYXJhbSBDIC0gYSBGSElSIENvZGVhYmxlQ29uY2VwdAogKiBAcmV0dXJucyB7U3lzdGVtLkNvbmNlcHR9IGEgQ1FMIENvbmNlcHQgb3IgbnVsbCBpZiBudWxsIHdhcyBwYXNzZWQgaW4KICovCmRlZmluZSBmdW5jdGlvbiBOdWxsU2FmZVRvQ29uY2VwdChDcHQgRkhJUi5Db2RlYWJsZUNvbmNlcHQpOgogIGlmIENwdCBpcyBub3QgbnVsbCB0aGVuIEZISVJIZWxwZXJzLlRvQ29uY2VwdChDcHQpIGVsc2UgbnVsbAoKLyoqCiAqIEEgbnVsbC1zYWZlIHZlcnNpb24gb2YgVG9JbnRlcnZhbCBmb3IgUGVyaW9kLiAgV2hlcmVhcyBGSElSSGVscGVycy5Ub0ludGVydmFsIHdpbGwgdGFrZSBhIG51bGwgYXJndW1lbnQgYW5kIHByb2R1Y2UgYQogKiBTeXN0ZW0uSW50ZXJ2YWwgdGhhdCBpcyBlbXB0eSwgdGhpcyBpbXBsZW1lbnRhdGlvbiByZXR1cm5zIG51bGwgaW5zdGVhZC4KICogQHBhcmFtIFAgLSBhIEZISVIgUGVyaW9kCiAqIEByZXR1cm5zIHtTeXN0ZW0uSW50ZXJ2YWx9IGEgQ1FMIEludGVydmFsIG9yIG51bGwgaWYgbnVsbCB3YXMgcGFzc2VkIGluCiAqLwpkZWZpbmUgZnVuY3Rpb24gTnVsbFNhZmVQZXJpb2RUb0ludGVydmFsKFBkIEZISVIuUGVyaW9kKToKICBpZiBQZCBpcyBub3QgbnVsbCB0aGVuIEludGVydmFsW1BkLiJzdGFydCIudmFsdWUsIFBkLiJlbmQiLnZhbHVlXSBlbHNlIG51bGwKCi8qKgogKiBBIG51bGwtc2FmZSB2ZXJzaW9uIG9mIFRvSW50ZXJ2YWwgZm9yIFJhbmdlLiAgV2hlcmVhcyBGSElSSGVscGVycy5Ub0ludGVydmFsIHdpbGwgdGFrZSBhIG51bGwgYXJndW1lbnQgYW5kIHByb2R1Y2UgYQogKiBTeXN0ZW0uSW50ZXJ2YWwgdGhhdCBpcyBlbXB0eSwgdGhpcyBpbXBsZW1lbnRhdGlvbiByZXR1cm5zIG51bGwgaW5zdGVhZC4KICogQHBhcmFtIFAgLSBhIEZISVIgUmFuZ2UKICogQHJldHVybnMge1N5c3RlbS5JbnRlcnZhbH0gYSBDUUwgSW50ZXJ2YWwgb3IgbnVsbCBpZiBudWxsIHdhcyBwYXNzZWQgaW4KICovCmRlZmluZSBmdW5jdGlvbiBOdWxsU2FmZVJhbmdlVG9JbnRlcnZhbChSZyBGSElSLlJhbmdlKToKICBpZiBSZyBpcyBub3QgbnVsbAogICAgdGhlbiBJbnRlcnZhbFtOdWxsU2FmZVRvUXVhbnRpdHkoUmcubG93KSwgTnVsbFNhZmVUb1F1YW50aXR5KFJnLmhpZ2gpXQogIGVsc2UgbnVsbAoKLyoqCiAqIFNhbWUgYXMgTnVsbFNhZmVQZXJpb2RUb0ludGVydmFsOyBrZXB0IGZvciBiYWNrd2FyZCBjb21wYXRpYmlsaXR5LiAgW0RlcHJlY2F0ZWRdCiAqIEBwYXJhbSBQIC0gYSBGSElSIFBlcmlvZAogKiBAcmV0dXJucyB7U3lzdGVtLkludGVydmFsfSBhIENRTCBJbnRlcnZhbCBvciBudWxsIGlmIG51bGwgd2FzIHBhc3NlZCBpbgogKi8KZGVmaW5lIGZ1bmN0aW9uIE51bGxTYWZlVG9JbnRlcnZhbChQZCBGSElSLlBlcmlvZCk6CiAgTnVsbFNhZmVQZXJpb2RUb0ludGVydmFsKFBkKQoKLyoqCiAqIEEgbnVsbC1zYWZlIHZlcnNpb24gb2YgVG9RdWFudGl0eS4gIFdoZXJlYXMgRkhJUkhlbHBlcnMuVG9RdWFudGl0eSB3aWxsIHRha2UgYSBudWxsIGFyZ3VtZW50IGFuZCBwcm9kdWNlIGEKICogU3lzdGVtLlF1YW50aXR5IHRoYXQgaXMgZW1wdHksIHRoaXMgaW1wbGVtZW50YXRpb24gcmV0dXJucyBudWxsIGluc3RlYWQuCiAqIEBwYXJhbSBDIC0gYSBGSElSIFF1YW50aXR5CiAqIEByZXR1cm5zIHtTeXN0ZW0uUXVhbnRpdHl9IGEgQ1FMIFF1YW50aXR5IG9yIG51bGwgaWYgbnVsbCB3YXMgcGFzc2VkIGluCiAqLwpkZWZpbmUgZnVuY3Rpb24gTnVsbFNhZmVUb1F1YW50aXR5KFF0eSBGSElSLlF1YW50aXR5KToKICBpZiBRdHkgaXMgbm90IG51bGwgdGhlbgogICAgU3lzdGVtLlF1YW50aXR5IHsKICAgICAgdmFsdWU6IFF0eS52YWx1ZS52YWx1ZSwKICAgICAgdW5pdDogQ29hbGVzY2UoUXR5LnVuaXQudmFsdWUsIFF0eS5jb2RlLnZhbHVlKQogICAgfQogIGVsc2UgbnVsbAoKLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gT0JTRVJWQVRJT05TIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCgovKioKICogRmlsdGVycyBPYnNlcnZhdGlvbnMgYnkgYSBjb25jZXB0IHJhdGhlciB0aGFuIGJ5IGEgVmFsdWVTZXQuICBJbiBDUUwgMS4zLCB0aGlzIHdpbGwgYmUgYnVpbHQgaW50byB0aGUgcmV0cmlldmUsCiAqIGJ1dCBmb3Igbm93LCB3ZSBtdXN0IHVzZSBhIHF1ZXJ5IHdoZXJlIGNsYXVzZS4KICogQHBhcmFtIEtvbmNlcHQgLSB0aGUgY29uY2VwdCB0byBmaWx0ZXIgb24gKGludGVudGlvbmFsbHkgbWlzcGVsbGVkIHRvIGF2b2lkIG5hbWluZyBjbGFzaGVzKQogKiBAcmV0dXJucyB7TGlzdDxPYnNlcnZhdGlvbj59IGEgbGlzdCBvZiBPYnNlcnZhdGlvbnMgbWF0Y2hpbmcgdGhlIGNvbmNlcHQsIG9yIG51bGwgaWYgbnVsbCB3YXMgcGFzc2VkIGluCiAqLwpkZWZpbmUgZnVuY3Rpb24gT2JzZXJ2YXRpb25zQnlDb25jZXB0KEtvbmNlcHQgU3lzdGVtLkNvbmNlcHQpOgogIFtPYnNlcnZhdGlvbl0gTyB3aGVyZSBOdWxsU2FmZVRvQ29uY2VwdChPLmNvZGUpIH4gS29uY2VwdAoKLyoqCiAqIE9ic2VydmF0aW9ucyB0aGF0IGFyZSBjb21wbGV0ZSBhbmQgdmVyaWZpZWQuIEluIEZISVIgUjQsIHRoZXJlIGFyZSB0d28gc3RhdHVzZXMgdGhhdCBpbmRpY2F0ZSB0aGlzIHN0YXRlOiAnZmluYWwnCiAqIGFuZCAnYW1lbmRlZCcuCiAqIEBzZWUgaHR0cHM6Ly93d3cuaGw3Lm9yZy9maGlyL3ZhbHVlc2V0LW9ic2VydmF0aW9uLXN0YXR1cy5odG1sCiAqIEBwYXJhbSBPYnNMaXN0IC0gYSBsaXN0IG9mIE9ic2VydmF0aW9ucwogKiBAcmV0dXJucyB7TGlzdDxPYnNlcnZhdGlvbj59IGEgbGlzdCBvZiB2ZXJpZmllZCBPYnNlcnZhdGlvbnMsIG9yIG51bGwgaWYgbnVsbCB3YXMgcGFzc2VkIGluCiAqLwpkZWZpbmUgZnVuY3Rpb24gVmVyaWZpZWQoT2JzTGlzdCBMaXN0PE9ic2VydmF0aW9uPik6CiAgT2JzTGlzdCBPIHdoZXJlIE8uc3RhdHVzLnZhbHVlIGluIHsnZmluYWwnLCAnYW1lbmRlZCd9CgovKioKICogT2JzZXJ2YXRpb25zIHRoYXQgaGF2ZSBxdWFudGl0eSB2YWx1ZXMgcmVjb3JkZWQgaW4gdGhlIHJlcXVlc3RlZCB1bml0LgogKiBAcGFyYW0gT2JzTGlzdCAtIGEgbGlzdCBvZiBPYnNlcnZhdGlvbnMKICogQHBhcmFtIFVuaXQgLSB0aGUgdW5pdCB0byByZXF1aXJlIGluIHRoZSBPYnNlcnZhdGlvbnMgcXVhbnRpdHkgdmFsdWUKICogQHJldHVybnMge0xpc3Q8T2JzZXJ2YXRpb24+fSBhIGxpc3Qgb2YgT2JzZXJ2YXRpb25zIHdpdGggdGhlIHJlcXVpcmVkIHVuaXQsIG9yIG51bGwgaWYgbnVsbCB3YXMgcGFzc2VkIGluCiAqLwpkZWZpbmUgZnVuY3Rpb24gV2l0aFVuaXQoT2JzTGlzdCBMaXN0PE9ic2VydmF0aW9uPiwgVW5pdCBTdHJpbmcpOgogIE9ic0xpc3QgTyB3aGVyZSBPLnZhbHVlLnVuaXQudmFsdWUgPSBVbml0IG9yIE8udmFsdWUuY29kZS52YWx1ZSA9IFVuaXQKCi8qKgogKiBPYnNlcnZhdGlvbnMgd2l0aCBhbiBlZmZlY3RpdmUgb3IgaXNzdWVkIGRhdGUgaW4gdGhlIHNwZWNpZmllZCAibG9vayBiYWNrIiBwZXJpb2QuICBGb3IgZXhhbXBsZSwgTERMLUMgVGVzdHMgaW4gdGhlCiAqIGxhc3QgNiB5ZWFycy4KICogVE9ETzogUmVuYW1lIHRvIExvb2tCYWNrIG9uY2UgdGhlIGV4ZWN1dGlvbiBlbmdpbmUgc3VwcG9ydHMgb3ZlcmxvYWRlZCBmdW5jdGlvbnMuCiAqIEBwYXJhbSBPYnNMaXN0IC0gYSBsaXN0IG9mIE9ic2VydmF0aW9ucwogKiBAcmV0dXJucyB7TGlzdDxPYnNlcnZhdGlvbj59IGEgbGlzdCBvZiBPYnNlcnZhdGlvbnMgd2l0aCBlZmZlY3RpdmUgb3IgaXNzdWVkIGRhdGUgc3BlY2lmaWVkIGxvb2tiYWNrIHBlcmlvZCwgb3IgbnVsbAogKiBpZiBudWxsIHdhcyBwYXNzZWQgaW4KICovCmRlZmluZSBmdW5jdGlvbiBPYnNlcnZhdGlvbkxvb2tCYWNrKE9ic0xpc3QgTGlzdDxPYnNlcnZhdGlvbj4sIExvb2tCYWNrIFN5c3RlbS5RdWFudGl0eSk6CiAgT2JzTGlzdCBPCiAgICBsZXQgTG9va0JhY2tJbnRlcnZhbDogSW50ZXJ2YWxbTm93KCkgLSBMb29rQmFjaywgTm93KCldCiAgICB3aGVyZSBPLmVmZmVjdGl2ZS52YWx1ZSBpbiBMb29rQmFja0ludGVydmFsCiAgICAgIG9yIE51bGxTYWZlVG9JbnRlcnZhbChPLmVmZmVjdGl2ZSkgb3ZlcmxhcHMgTG9va0JhY2tJbnRlcnZhbAogICAgICBvciBPLmlzc3VlZC52YWx1ZSBpbiBMb29rQmFja0ludGVydmFsCgovKioKICogVGhlIG1vc3QgcmVjZW50IG9ic2VydmF0aW9uLiAgRm9yIGVhY2ggT2JzZXJ2YXRpb24sIHRoaXMgYWxnb3JpdGhtIHdpbGwgdXNlIHRoZSBGaW5kRGF0ZSBmdW5jdGlvbiwgd2hpY2ggdXNlcyB0aGUKICogZmlyc3Qgbm9uLW51bGwgZGF0ZSB2YWx1ZSBmcm9tIHRoZXNlIGZpZWxkczogZWZmZWN0aXZlRGF0ZVRpbWUsIGVmZmVjdGl2ZVBlcmlvZC5lbmQsIGVmZmVjdGl2ZVBlcmlvZC5zdGFydCwgaXNzdWVkLgogKiBUaGUgZm91bmQgZGF0ZSB3aWxsIGJlIHVzZWQgdG8gY29tcGFyZSBPYnNlcnZhdGlvbnMgYW5kIGRldGVybWluZSB0aGUgbW9zdCByZWNlbnQgb25lLgogKiBAc2VlIEZpbmREYXRlKE9ic2VydmF0aW9uKQogKiBAcGFyYW0gT2JzTGlzdCAtIGEgbGlzdCBvZiBPYnNlcnZhdGlvbnMKICogQHJldHVybnMge09ic2VydmF0aW9ufSB0aGUgbW9zdCByZWNlbnQgT2JzZXJ2YXRpb24gZnJvbSB0aGUgbGlzdCwgb3IgbnVsbCBpZiBudWxsIHdhcyBwYXNzZWQgaW4KICovCmRlZmluZSBmdW5jdGlvbiBNb3N0UmVjZW50KE9ic0xpc3QgTGlzdDxPYnNlcnZhdGlvbj4pOgogIExhc3QoT2JzTGlzdCBPIHNvcnQgYnkgQ29hbGVzY2UoZWZmZWN0aXZlLnZhbHVlLCBlZmZlY3RpdmUuImVuZCIudmFsdWUsIGVmZmVjdGl2ZS4ic3RhcnQiLnZhbHVlLCBpc3N1ZWQudmFsdWUpKQoKLyoqCiAqIEV4dHJhY3RzIHRoZSBxdWFudGl0eSB2YWx1ZSBmcm9tIGFuIE9ic2VydmF0aW9uLCByZXR1cm5pbmcgaXQgYXMgYSBDUUwgUXVhbnRpdHkKICogQHBhcmFtIE9icyAtIGFuIG9ic2VydmF0aW9uCiAqIEByZXR1cm5zIHtTeXN0ZW0uUXVhbnRpdHl9IHRoZSBPYnNlcnZhdGlvbidzIHZhbHVlIGFzIGEgcXVhbnRpdHksIG9yIG51bGwgaWYgdGhlcmUgaXMgbm8gcXVhbnRpdHkgdmFsdWUKICovCmRlZmluZSBmdW5jdGlvbiBRdWFudGl0eVZhbHVlKE9icyBPYnNlcnZhdGlvbik6CiAgTnVsbFNhZmVUb1F1YW50aXR5KE9icy52YWx1ZSkKCi8qKgogKiBFeHRyYWN0cyB0aGUgQ29kZWFibGVDb25jZXB0IHZhbHVlIGZyb20gYW4gT2JzZXJ2YXRpb24sIHJldHVybmluZyBpdCBhcyBhIENRTCBDb25jZXB0CiAqIEBwYXJhbSBPYnMgLSBhbiBvYnNlcnZhdGlvbgogKiBAcmV0dXJucyB7U3lzdGVtLkNvbmNlcHR9IHRoZSBPYnNlcnZhdGlvbidzIHZhbHVlIGFzIGEgY29uY2VwdCwgb3IgbnVsbCBpZiB0aGVyZSBpcyBubyBDb2RlYWJlQ29uY2VwdCB2YWx1ZQogKi8KZGVmaW5lIGZ1bmN0aW9uIENvbmNlcHRWYWx1ZShPYnMgT2JzZXJ2YXRpb24pOgogIE51bGxTYWZlVG9Db25jZXB0KE9icy52YWx1ZSkKCi8qKgogKiBGaW5kcyB0aGUgZmlyc3Qgbm9uLW51bGwgbWVhbmluZ2Z1bCBkYXRlIHRoYXQgY2FuIGJlIGFzc29jaWF0ZWQgd2l0aCB0aGlzIE9ic2VydmF0aW9uLiAgVGhpcyB3aWxsIGxvb2sgdGhyb3VnaCB0aGUKICogZm9sbG93aW5nIGZpZWxkcyBpbiB0aGUgZm9sbG93aW5nIG9yZGVyOiBlZmZlY3RpdmVEYXRlVGltZSwgZWZmZWN0aXZlUGVyaW9kLmVuZCwgZWZmZWN0aXZlUGVyaW9kLnN0YXJ0LCBpc3N1ZWQuCiAqIEBwYXJhbSBPYnMgLSBhbiBPYnNlcnZhdGlvbgogKiBAcmV0dXJucyB7U3lzdGVtLkRhdGVUaW1lfSB0aGUgZmlyc3Qgbm9uLW51bGwgbWVhbmluZ2Z1bCBkYXRlLCBvciBudWxsIGlmIG5vbiBpcyBmb3VuZAogKi8KZGVmaW5lIGZ1bmN0aW9uIEZpbmREYXRlKE9icyBPYnNlcnZhdGlvbik6CiAgQ29hbGVzY2UoT2JzLmVmZmVjdGl2ZS52YWx1ZSwgT2JzLmVmZmVjdGl2ZS4iZW5kIi52YWx1ZSwgT2JzLmVmZmVjdGl2ZS4ic3RhcnQiLnZhbHVlLCBPYnMuaXNzdWVkLnZhbHVlKQoKLy8gVE9ETzogQ29uZmlybSB0aGF0IHRoaXMgd29ya3MgYXMgZXhwZWN0ZWQKLyoqCiAqIFRoZSBoaWdoZXN0IG9ic2VydmF0aW9uLgogKiBUaGUgdmFsdWUgd2lsbCBiZSB1c2VkIHRvIGNvbXBhcmUgT2JzZXJ2YXRpb25zIGFuZCBkZXRlcm1pbmUgdGhlIGhpZ2hlc3Qgb25lLgogKiBAcGFyYW0gT2JzTGlzdCAtIGEgbGlzdCBvZiBPYnNlcnZhdGlvbnMKICogQHJldHVybnMge1N5c3RlbS5RdWFudGl0eX0gdGhlIHF1YW50aXR5IHdpdGggdGhlIGhpZ2hlc3QgdmFsdWUgZnJvbSB0aGUgbGlzdCwgb3IgbnVsbCBpZiBudWxsIHdhcyBwYXNzZWQgaW4KICovCmRlZmluZSBmdW5jdGlvbiBIaWdoZXN0T2JzZXJ2YXRpb24oT2JzTGlzdCBMaXN0PE9ic2VydmF0aW9uPik6CiAgTWF4KE9ic0xpc3QgTyByZXR1cm4gTnVsbFNhZmVUb1F1YW50aXR5KE8udmFsdWUpKQoKCi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIENPTkRJVElPTlMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKLyoqCiAqIEZpbHRlcnMgQ29uZGl0aW9ucyBieSBhIGNvbmNlcHQgcmF0aGVyIHRoYW4gYnkgYSBWYWx1ZVNldC4gIEluIENRTCAxLjMsIHRoaXMgd2lsbCBiZSBidWlsdCBpbnRvIHRoZSByZXRyaWV2ZSwKICogYnV0IGZvciBub3csIHdlIG11c3QgdXNlIGEgcXVlcnkgd2hlcmUgY2xhdXNlLgogKiBAcGFyYW0gS29uY2VwdCAtIHRoZSBjb25jZXB0IHRvIGZpbHRlciBvbiAoaW50ZW50aW9uYWxseSBtaXNwZWxsZWQgdG8gYXZvaWQgbmFtaW5nIGNsYXNoZXMpCiAqIEByZXR1cm5zIHtMaXN0PE9ic2VydmF0aW9uPn0gYSBsaXN0IG9mIENvbmRpdGlvbnMgbWF0Y2hpbmcgdGhlIGNvbmNlcHQsIG9yIG51bGwgaWYgbnVsbCB3YXMgcGFzc2VkIGluCiAqLwpkZWZpbmUgZnVuY3Rpb24gQ29uZGl0aW9uc0J5Q29uY2VwdChLb25jZXB0IFN5c3RlbS5Db25jZXB0KToKICBbQ29uZGl0aW9uXSBDIHdoZXJlIE51bGxTYWZlVG9Db25jZXB0KEMuY29kZSkgfiBLb25jZXB0CgovKioKICogQ29uZGl0aW9ucyB0aGF0IGFyZSBjb25maXJtZWQuIEluIEZISVIgUjQsIHRoaXMgaXMgcmVmbGVjdGVkIGJ5IHZlcmlmaWNhdGlvblN0YXR1czogJ2NvbmZpcm1lZCcuCiAqIEBzZWUgaHR0cHM6Ly93d3cuaGw3Lm9yZy9maGlyL3ZhbHVlc2V0LWNvbmRpdGlvbi12ZXItc3RhdHVzLmh0bWwKICogQHBhcmFtIENvbmRMaXN0IC0gYSBsaXN0IG9mIENvbmRpdGlvbnMKICogQHJldHVybnMge0xpc3Q8Q29uZGl0aW9uPn0gYSBsaXN0IG9mIGNvbmZpcm1lZCBDb25kaXRpb25zLCBvciBudWxsIGlmIG51bGwgd2FzIHBhc3NlZCBpbgogKi8KZGVmaW5lIGZ1bmN0aW9uIENvbmZpcm1lZChDb25kTGlzdCBMaXN0PENvbmRpdGlvbj4pOgogIENvbmRMaXN0IEMgd2hlcmUgQy52ZXJpZmljYXRpb25TdGF0dXMuY29kaW5nIH4gIkNvbmRpdGlvbiB2ZXJpZmljYXRpb25TdGF0dXMgY29uZmlybWVkIGNvZGUiCgovKioKICogQ29uZGl0aW9ucyB0aGF0IGFyZSBhY3RpdmUuIEluIEZISVIgUjQsIHRoaXMgaXMgcmVmbGVjdGVkIGJ5IGNsaW5pY2FsU3RhdHVzOiAnYWN0aXZlJyBhbmQgdGhlIGFic2VuY2Ugb2YgYW55CiAqIGFiYXRlbWVudCBpbmZvcm1hdGlvbiAoaS5lLiwgaWYgaXQgYWJhdGVkLCBpdCBpcyBubyBsb25nZXIgYWN0aXZlKS4KICogVE9ETzogUmVuYW1lIHRvIEFjdGl2ZSBvbmNlIHRoZSBleGVjdXRpb24gZW5naW5lIHN1cHBvcnRzIG92ZXJsb2FkZWQgZnVuY3Rpb25zLgogKiBAc2VlIGh0dHBzOi8vd3d3LmhsNy5vcmcvZmhpci92YWx1ZXNldC1jb25kaXRpb24tY2xpbmljYWwuaHRtbAogKiBAcGFyYW0gQ29uZExpc3QgLSBhIGxpc3Qgb2YgQ29uZGl0aW9ucwogKiBAcmV0dXJucyB7TGlzdDxDb25kaXRpb24+fSBhIGxpc3Qgb2YgYWN0aXZlIENvbmRpdGlvbnMsIG9yIG51bGwgaWYgbnVsbCB3YXMgcGFzc2VkIGluCiAqLwpkZWZpbmUgZnVuY3Rpb24gQWN0aXZlQ29uZGl0aW9uKENvbmRMaXN0IExpc3Q8Q29uZGl0aW9uPik6CiAgQ29uZExpc3QgQwogICAgd2hlcmUgQy5jbGluaWNhbFN0YXR1cy5jb2RpbmcgfiAiQ29uZGl0aW9uIGNsaW5pY2FsU3RhdHVzIGFjdGl2ZSBjb2RlIgogICAgICBhbmQgQy5hYmF0ZW1lbnQgaXMgbnVsbAoKLyoqCiAqIENvbmRpdGlvbnMgdGhhdCBhcmUgYWN0aXZlIG9yIHJlY3VycmluZy4gSW4gRkhJUiBSNCwgdGhpcyBpcyByZWZsZWN0ZWQgYnkgY2xpbmljYWxTdGF0dXM6ICdhY3RpdmUnLCAncmVjdXJyZW5jZScsIG9yICdyZWxhcHNlJy4KICogV2UgZG8gbm90IGNoZWNrIGZvciBudWxsIGFiYXRlbWVudCBpbmZvcm1hdGlvbiBiZWNhdXNlIGl0IG1heSBoYXZlIGRhdGVzIGZyb20gd2hlbiB0aGUgbm93IHJlY3VycmluZyBjb25kaXRpb24KICogaW5pdGlhbGx5IHdlbnQgaW50byByZW1pc3Npb24uCiAqIEBzZWUgaHR0cHM6Ly93d3cuaGw3Lm9yZy9maGlyL3ZhbHVlc2V0LWNvbmRpdGlvbi1jbGluaWNhbC5odG1sCiAqIEBwYXJhbSBDb25kTGlzdCAtIGEgbGlzdCBvZiBDb25kaXRpb25zCiAqIEByZXR1cm5zIHtMaXN0PENvbmRpdGlvbj59IGEgbGlzdCBvZiBhY3RpdmUgb3IgcmVjdXJyaW5nIENvbmRpdGlvbnMsIG9yIG51bGwgaWYgbnVsbCB3YXMgcGFzc2VkIGluCiAqLwpkZWZpbmUgZnVuY3Rpb24gQWN0aXZlT3JSZWN1cnJpbmcoQ29uZExpc3QgTGlzdDxDb25kaXRpb24+KToKICBDb25kTGlzdCBDIHdoZXJlIEMuY2xpbmljYWxTdGF0dXMuY29kaW5nIH4gIkNvbmRpdGlvbiBjbGluaWNhbFN0YXR1cyBhY3RpdmUgY29kZSIKICAgIG9yIEMuY2xpbmljYWxTdGF0dXMuY29kaW5nIH4gIkNvbmRpdGlvbiBjbGluaWNhbFN0YXR1cyByZWN1cnJlbmNlIGNvZGUiCiAgICBvciBDLmNsaW5pY2FsU3RhdHVzLmNvZGluZyB+ICJDb25kaXRpb24gY2xpbmljYWxTdGF0dXMgcmVsYXBzZSBjb2RlIgoKLyoqCiAqIENvbmRpdGlvbnMgd2l0aCBhbiBvbnNldCBvciByZWNvcmRlZCBkYXRlIGluIHRoZSBzcGVjaWZpZWQgImxvb2sgYmFjayIgcGVyaW9kLiAgRm9yIGV4YW1wbGUsIHByZWduYW5jeSBpbgogKiB0aGUgbGFzdCA0MiB3ZWVrcy4KICogVE9ETzogUmVuYW1lIHRvIExvb2tCYWNrIG9uY2UgdGhlIGV4ZWN1dGlvbiBlbmdpbmUgc3VwcG9ydHMgb3ZlcmxvYWRlZCBmdW5jdGlvbnMuCiAqIEBwYXJhbSBDb25kTGlzdCAtIGEgbGlzdCBvZiBDb25kaXRpb25zCiAqIEByZXR1cm5zIHtMaXN0PENvbmRpdGlvbj59IGEgbGlzdCBvZiBDb25kaXRpb25zIHdpdGggb25zZXQgb3IgcmVjb3JkZWQgZGF0ZSBzcGVjaWZpZWQgbG9va2JhY2sgcGVyaW9kLCBvciBudWxsCiAqIGlmIG51bGwgd2FzIHBhc3NlZCBpbgogKi8KZGVmaW5lIGZ1bmN0aW9uIENvbmRpdGlvbkxvb2tCYWNrKENvbmRMaXN0IExpc3Q8Q29uZGl0aW9uPiwgTG9va0JhY2sgU3lzdGVtLlF1YW50aXR5KToKICBDb25kTGlzdCBDCiAgICBsZXQgTG9va0JhY2tJbnRlcnZhbDogSW50ZXJ2YWxbTm93KCkgLSBMb29rQmFjaywgTm93KCldCiAgICB3aGVyZSBDLm9uc2V0LnZhbHVlIGluIExvb2tCYWNrSW50ZXJ2YWwKICAgICAgb3IgTnVsbFNhZmVUb0ludGVydmFsKEMub25zZXQpIG92ZXJsYXBzIExvb2tCYWNrSW50ZXJ2YWwKICAgICAgb3IgQy5yZWNvcmRlZERhdGUudmFsdWUgaW4gTG9va0JhY2tJbnRlcnZhbAogICAgICAvLyBUT0RPIENvbmZpcm0gdGhlc2UgYXJlIHRoZSBjb3JyZWN0IGZpZWxkcyB0byB1c2UKCi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIFBST0NFRFVSRVMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKIC8qKgogICogRmlsdGVycyBQcm9jZWR1cmVzIGJ5IGEgY29uY2VwdCByYXRoZXIgdGhhbiBieSBhIFZhbHVlU2V0LiAgSW4gQ1FMIDEuMywgdGhpcyB3aWxsIGJlIGJ1aWx0IGludG8gdGhlIHJldHJpZXZlLAogICogYnV0IGZvciBub3csIHdlIG11c3QgdXNlIGEgcXVlcnkgd2hlcmUgY2xhdXNlLgogICogQHBhcmFtIEtvbmNlcHQgLSB0aGUgY29uY2VwdCB0byBmaWx0ZXIgb24gKGludGVudGlvbmFsbHkgbWlzcGVsbGVkIHRvIGF2b2lkIG5hbWluZyBjbGFzaGVzKQogICogQHJldHVybnMge0xpc3Q8UHJvY2VkdXJlPn0gYSBsaXN0IG9mIFByb2NlZHVyZXMgbWF0Y2hpbmcgdGhlIGNvbmNlcHQsIG9yIG51bGwgaWYgbnVsbCB3YXMgcGFzc2VkIGluCiAgKi8KIGRlZmluZSBmdW5jdGlvbiBQcm9jZWR1cmVzQnlDb25jZXB0KEtvbmNlcHQgU3lzdGVtLkNvbmNlcHQpOgogICBbUHJvY2VkdXJlXSBQIHdoZXJlIE51bGxTYWZlVG9Db25jZXB0KFAuY29kZSkgfiBLb25jZXB0CgovKioKICogUHJvY2VkdXJlcyB0aGF0IGFyZSBjb21wbGV0ZWQuIEluIEZISVIgUjQsIHRoaXMgaXMgcmVmbGVjdGVkIGJ5IHN0YXR1czogJ2NvbXBsZXRlZCcuICBJbiBhZGRpdGlvbiwgdGhlCiAqIG5vdERvbmUgZmxhZyBtdXN0IGJlIGNoZWNrZWQgdG8gZW5zdXJlIGl0IGlzIG5vdCAndHJ1ZScuCiAqIEBzZWUgaHR0cHM6Ly93d3cuaGw3Lm9yZy9maGlyL3ZhbHVlc2V0LWV2ZW50LXN0YXR1cy5odG1sCiAqIEBwYXJhbSBQcm9jTGlzdCAtIGEgbGlzdCBvZiBQcm9jZWR1cmVzCiAqIEByZXR1cm5zIHtMaXN0PFByb2NlZHVyZT59IGEgbGlzdCBvZiBjb21wbGV0ZWQgUHJvY2VkdXJlcywgb3IgbnVsbCBpZiBudWxsIHdhcyBwYXNzZWQgaW4KICovCmRlZmluZSBmdW5jdGlvbiBDb21wbGV0ZWQoUHJvY0xpc3QgTGlzdDxQcm9jZWR1cmU+KToKICBQcm9jTGlzdCBQCiAgICB3aGVyZSBQLnN0YXR1cy52YWx1ZSA9ICdjb21wbGV0ZWQnCgovKioKICogUHJvY2VkdXJlcyB0aGF0IGFyZSBpbiBwcm9ncmVzcy4gSW4gRkhJUiBSNCwgdGhpcyBpcyByZWZsZWN0ZWQgYnkgc3RhdHVzOiAnaW4tcHJvZ3Jlc3MnLiAgSW4gYWRkaXRpb24sIHRoZQogKiBub3REb25lIGZsYWcgbXVzdCBiZSBjaGVja2VkIHRvIGVuc3VyZSBpdCBpcyBub3QgJ3RydWUnLgogKiBAc2VlIGh0dHBzOi8vd3d3LmhsNy5vcmcvZmhpci92YWx1ZXNldC1ldmVudC1zdGF0dXMuaHRtbAogKiBAcGFyYW0gUHJvY0xpc3QgLSBhIGxpc3Qgb2YgUHJvY2VkdXJlcwogKiBAcmV0dXJucyB7TGlzdDxQcm9jZWR1cmU+fSBhIGxpc3Qgb2YgY29tcGxldGVkIFByb2NlZHVyZXMsIG9yIG51bGwgaWYgbnVsbCB3YXMgcGFzc2VkIGluCiAqLwpkZWZpbmUgZnVuY3Rpb24gUHJvY2VkdXJlSW5Qcm9ncmVzcyhQcm9jTGlzdCBMaXN0PFByb2NlZHVyZT4pOgogIFByb2NMaXN0IFAKICAgIHdoZXJlIFAuc3RhdHVzLnZhbHVlID0gJ2luLXByb2dyZXNzJwoKLyoqCiAqIFByb2NlZHVyZXMgdGhhdCBhY3R1YWxseSBoYXBwZW5lZCBvciBhcmUgaGFwcGVuaW5nLiBJbiBGSElSIFI0LCB0aGVyZSBhcmUgYSBmZXcgcHJvcGVydGllcyB0aGF0IG5lZ2F0ZSB0aGUKICogcHJvY2VkdXJlLCBtb3N0IG5vdGFibHkgd2hlbiBzdGF0dXMgaXMgJ2VudGVyZWQtaW4tZXJyb3InIG9yIG5vdERvbmUgaXMgdHJ1ZS4KICogQHNlZSBodHRwczovL3d3dy5obDcub3JnL2ZoaXIvdmFsdWVzZXQtZXZlbnQtc3RhdHVzLmh0bWwKICogQHBhcmFtIFByb2NMaXN0IC0gYSBsaXN0IG9mIFByb2NlZHVyZXMKICogQHJldHVybnMge0xpc3Q8UHJvY2VkdXJlPn0gYSBsaXN0IG9mIFByb2NlZHVyZXMgdGhhdCBhY3R1YWxseSBoYXBwZW5lZCBvciBhcmUgaGFwcGVuaW5nLCBvciBudWxsIGlmIG51bGwgd2FzIHBhc3NlZCBpbgogKi8KZGVmaW5lIGZ1bmN0aW9uIFByb2NlZHVyZVBlcmZvcm1hbmNlKFByb2NMaXN0IExpc3Q8UHJvY2VkdXJlPik6CiAgUHJvY0xpc3QgUAogICAgd2hlcmUgUC5zdGF0dXMudmFsdWUgIT0gJ2VudGVyZWQtaW4tZXJyb3InCgovKioKICogUHJvY2VkdXJlcyBwZXJmb3JtZWQgaW4gdGhlIHNwZWNpZmllZCAibG9vayBiYWNrIiBwZXJpb2QuICBGb3IgZXhhbXBsZSwgUENJcyBwZXJmb3JtZWQgaW4gdGhlCiAqIHBhc3QgMiB3ZWVrcy4KICogVE9ETzogUmVuYW1lIHRvIExvb2tCYWNrIG9uY2UgdGhlIGV4ZWN1dGlvbiBlbmdpbmUgc3VwcG9ydHMgb3ZlcmxvYWRlZCBmdW5jdGlvbnMuCiAqIEBwYXJhbSBQcm9jTGlzdCAtIGEgbGlzdCBvZiBQcm9jZWR1cmVzCiAqIEBwYXJhbSBMb29rQmFjayAtIHRoZSBsb29rYmFjayBwZXJpb2QgZm9yIHdoZW4gdGhlIHByb2NlZHVyZSB3YXMgcGVyZm9ybWVkCiAqIEByZXR1cm5zIHtMaXN0PFByb2NlZHVyZT59IGEgbGlzdCBvZiBQcm9jZWR1cmVzIHBlcmZvcm1lZCBpbiB0aGUgbG9vayBiYWNrIHBlcmlvZCwgb3IgbnVsbCBpZiBudWxsCiAqIHdhcyBwYXNzZWQgaW4KICovCmRlZmluZSBmdW5jdGlvbiBQcm9jZWR1cmVMb29rQmFjayhQcm9jTGlzdCBMaXN0PFByb2NlZHVyZT4sIExvb2tCYWNrIFN5c3RlbS5RdWFudGl0eSk6CiAgUHJvY0xpc3QgUAogICAgbGV0IExvb2tCYWNrSW50ZXJ2YWw6IEludGVydmFsW05vdygpIC0gTG9va0JhY2ssIE5vdygpXQogICAgd2hlcmUgUC5wZXJmb3JtZWQudmFsdWUgaW4gTG9va0JhY2tJbnRlcnZhbAogICAgICBvciBOdWxsU2FmZVRvSW50ZXJ2YWwoUC5wZXJmb3JtZWQpIG92ZXJsYXBzIExvb2tCYWNrSW50ZXJ2YWwKCi8vIE5vdGU6IFByb2NlZHVyZVJlcXVlc3QgYW5kIFJlZmVycmFsUmVxdWVzdCByZXNvdXJjZXMgaGF2ZSBiZWVuIHJlcGxhY2VkIGluIEZISVIgUjQgd2l0aCB0aGUgU2VydmljZVJlcXVlc3QgcmVzb3VyY2UuCi8vIFRPRE86IFdoZW4gbmVlZGVkLCBjb21lIGJhY2sgYW5kIFNlcnZpY2VSZXF1ZXN0IGhlbHBlciBmdW5jdGlvbnMuCi8vIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gUFJPQ0VEVVJFUkVRVUVTVFMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKLy8gIC8qKgovLyAgICogRmlsdGVycyBQcm9jZWR1cmVSZXF1ZXN0cyBieSBhIGNvbmNlcHQgcmF0aGVyIHRoYW4gYnkgYSBWYWx1ZVNldC4gIEluIENRTCAxLjMsIHRoaXMgd2lsbCBiZSBidWlsdCBpbnRvIHRoZSByZXRyaWV2ZSwKLy8gICAqIGJ1dCBmb3Igbm93LCB3ZSBtdXN0IHVzZSBhIHF1ZXJ5IHdoZXJlIGNsYXVzZS4KLy8gICAqIEBwYXJhbSBLb25jZXB0IC0gdGhlIGNvbmNlcHQgdG8gZmlsdGVyIG9uIChpbnRlbnRpb25hbGx5IG1pc3BlbGxlZCB0byBhdm9pZCBuYW1pbmcgY2xhc2hlcykKLy8gICAqIEByZXR1cm5zIHtMaXN0PFByb2NlZHVyZVJlcXVlc3Q+fSBhIGxpc3Qgb2YgUHJvY2VkdXJlUmVxdWVzdHMgbWF0Y2hpbmcgdGhlIGNvbmNlcHQsIG9yIG51bGwgaWYgbnVsbCB3YXMgcGFzc2VkIGluCi8vICAgKi8KLy8gIGRlZmluZSBmdW5jdGlvbiBQcm9jZWR1cmVSZXF1ZXN0c0J5Q29uY2VwdChLb25jZXB0IFN5c3RlbS5Db25jZXB0KToKLy8gICAgW1Byb2NlZHVyZVJlcXVlc3RdIFAgd2hlcmUgTnVsbFNhZmVUb0NvbmNlcHQoUC5jb2RlKSB+IEtvbmNlcHQKCi8vIC8qKgovLyAgKiBQcm9jZWR1cmVSZXF1ZXN0cyB0aGF0IGFyZSBhY2NlcHRlZCwgaW4gcHJvZ3Jlc3MsIG9yIGNvbXBsZXRlZC4gSW4gRkhJUiBEU1RVMiwgdGhpcyBpcyByZWZsZWN0ZWQgYnkgdGhlIGNvcnJlc3BvbmRpbmcKLy8gICogc3RhdHVzIHN0YXR1cyB2YWx1ZXMuCi8vICAqIEBzZWUgaHR0cDovL2hsNy5vcmcvZmhpci9EU1RVMi92YWx1ZXNldC1wcm9jZWR1cmUtcmVxdWVzdC1zdGF0dXMuaHRtbAovLyAgKiBAcGFyYW0gUHJvY1JlcUxpc3QgLSBhIGxpc3Qgb2YgUHJvY2VkdXJlUmVxdWVzdHMKLy8gICogQHJldHVybnMge0xpc3Q8UHJvY2VkdXJlUmVxdWVzdD59IGEgbGlzdCBvZiBhY2NlcHRlZCwgaW4tcHJvZ3Jlc3MsIG9yIGNvbXBsZXRlZCBQcm9jZWR1cmVSZXF1ZXN0cywKLy8gICogb3IgbnVsbCBpZiBudWxsIHdhcyBwYXNzZWQgaW4KLy8gICovCi8vIGRlZmluZSBmdW5jdGlvbiBQcm9jZWR1cmVSZXF1ZXN0QWNjZXB0ZWRPckluUHJvZ3Jlc3NPckNvbXBsZXRlZChQcm9jUmVxTGlzdCBMaXN0PFByb2NlZHVyZVJlcXVlc3Q+KToKLy8gICBQcm9jUmVxTGlzdCBQCi8vICAgICB3aGVyZSBQLnN0YXR1cy52YWx1ZSBpbiBMaXN0eydhY2NlcHRlZCcsICdpbi1wcm9ncmVzcycsICdjb21wbGV0ZWQnfQoKLy8gLyoqCi8vICAqIFByb2NlZHVyZVJlcXVlc3RzIG9yZGVyZWQgaW4gdGhlIHNwZWNpZmllZCAibG9vayBiYWNrIiBwZXJpb2QuICBGb3IgZXhhbXBsZSwgUENJcyBvcmRlcmVkIGluIHRoZQovLyAgKiBwYXN0IDIgd2Vla3MuCi8vICAqIFRPRE86IFJlbmFtZSB0byBMb29rQmFjayBvbmNlIHRoZSBleGVjdXRpb24gZW5naW5lIHN1cHBvcnRzIG92ZXJsb2FkZWQgZnVuY3Rpb25zLgovLyAgKiBAcGFyYW0gUHJvY1JlcUxpc3QgLSBhIGxpc3Qgb2YgUHJvY2VkdXJlUmVxdWVzdHMKLy8gICogQHBhcmFtIExvb2tCYWNrIC0gdGhlIGxvb2tiYWNrIHBlcmlvZCBmb3Igd2hlbiB0aGUgcHJvY2VkdXJlIHdhcyBvcmRlcmVkCi8vICAqIEByZXR1cm5zIHtMaXN0PFByb2NlZHVyZVJlcXVlc3Q+fSBhIGxpc3Qgb2YgUHJvY2VkdXJlUmVxdWVzdHMgb3JkZXJlZCBpbiB0aGUgbG9vayBiYWNrIHBlcmlvZCwgb3IgbnVsbCBpZiBudWxsCi8vICAqIHdhcyBwYXNzZWQgaW4KLy8gICovCi8vIGRlZmluZSBmdW5jdGlvbiBQcm9jZWR1cmVSZXF1ZXN0TG9va0JhY2soUHJvY1JlcUxpc3QgTGlzdDxQcm9jZWR1cmVSZXF1ZXN0PiwgTG9va0JhY2sgU3lzdGVtLlF1YW50aXR5KToKLy8gICBQcm9jUmVxTGlzdCBQCi8vICAgICB3aGVyZSBQLmF1dGhvcmVkT24udmFsdWUgaW4gSW50ZXJ2YWxbTm93KCkgLSBMb29rQmFjaywgTm93KCldCgovLyAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSBSRUZFUlJBTFJFUVVFU1RTIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCi8vICAvKioKLy8gICAqIEZpbHRlcnMgUmVmZXJyYWxSZXF1ZXN0cyBieSBhIGNvbmNlcHQgcmF0aGVyIHRoYW4gYnkgYSBWYWx1ZVNldC4gIEluIENRTCAxLjMsIHRoaXMgd2lsbCBiZSBidWlsdCBpbnRvIHRoZSByZXRyaWV2ZSwKLy8gICAqIGJ1dCBmb3Igbm93LCB3ZSBtdXN0IHVzZSBhIHF1ZXJ5IHdoZXJlIGNsYXVzZS4KLy8gICAqIEBwYXJhbSBLb25jZXB0IC0gdGhlIGNvbmNlcHQgdG8gZmlsdGVyIG9uIChpbnRlbnRpb25hbGx5IG1pc3BlbGxlZCB0byBhdm9pZCBuYW1pbmcgY2xhc2hlcykKLy8gICAqIEByZXR1cm5zIHtMaXN0PFJlZmVycmFsUmVxdWVzdD59IGEgbGlzdCBvZiBSZWZlcnJhbFJlcXVlc3RzIG1hdGNoaW5nIHRoZSBjb25jZXB0LCBvciBudWxsIGlmIG51bGwgd2FzIHBhc3NlZCBpbgovLyAgICovCi8vICBkZWZpbmUgZnVuY3Rpb24gUmVmZXJyYWxSZXF1ZXN0c0J5U2VydmljZVJlcXVlc3RlZENvbmNlcHQoS29uY2VwdCBTeXN0ZW0uQ29uY2VwdCk6Ci8vICAgIFtSZWZlcnJhbFJlcXVlc3RdIFIKLy8gICAgd2hlcmUgZXhpc3RzKChSLnNlcnZpY2VSZXF1ZXN0ZWQpIFNSQyB3aGVyZSBOdWxsU2FmZVRvQ29uY2VwdChTUkMpIH4gS29uY2VwdCkKCi8vIC8qKgovLyAgKiBSZWZlcnJhbFJlcXVlc3RzIHRoYXQgYXJlIGFjY2VwdGVkLCBhY3RpdmUsIG9yIGNvbXBsZXRlZC4gSW4gRkhJUiBEU1RVMiwgdGhpcyBpcyByZWZsZWN0ZWQgYnkgdGhlIGNvcnJlc3BvbmRpbmcKLy8gICogc3RhdHVzIHN0YXR1cyB2YWx1ZXMuCi8vICAqIEBzZWUgaHR0cDovL2hsNy5vcmcvZmhpci9EU1RVMi92YWx1ZXNldC1yZWZlcnJhbHN0YXR1cy5odG1sCi8vICAqIEBwYXJhbSBSZWZlcnJhbExpc3QgLSBhIGxpc3Qgb2YgUmVmZXJyYWxSZXF1ZXN0cwovLyAgKiBAcmV0dXJucyB7TGlzdDxSZWZlcnJhbFJlcXVlc3Q+fSBhIGxpc3Qgb2YgYWNjZXB0ZWQsIGFjdGl2ZSwgb3IgY29tcGxldGVkIFJlZmVycmFsUmVxdWVzdHMsCi8vICAqIG9yIG51bGwgaWYgbnVsbCB3YXMgcGFzc2VkIGluCi8vICAqLwovLyBkZWZpbmUgZnVuY3Rpb24gUmVmZXJyYWxSZXF1ZXN0QWNjZXB0ZWRPckFjdGl2ZU9yQ29tcGxldGVkKFJlZmVycmFsTGlzdCBMaXN0PFJlZmVycmFsUmVxdWVzdD4pOgovLyAgIFJlZmVycmFsTGlzdCBSCi8vICAgICB3aGVyZSBSLnN0YXR1cy52YWx1ZSBpbiBMaXN0eydhY2NlcHRlZCcsICdhY3RpdmUnLCAnY29tcGxldGVkJ30KCi8vIC8qKgovLyAgKiBSZWZlcnJhbFJlcXVlc3RzIHJlcXVlc3RlZCBpbiB0aGUgc3BlY2lmaWVkICJsb29rIGJhY2siIHBlcmlvZC4gIEZvciBleGFtcGxlLCBwYWNlIG1ha2UgaW5zZXJ0aW9ucyByZWZlcnJhbHMgc2VudAovLyAgKiBpbiB0aGUgcGFzdCAyIHdlZWtzLgovLyAgKiBUT0RPOiBSZW5hbWUgdG8gTG9va0JhY2sgb25jZSB0aGUgZXhlY3V0aW9uIGVuZ2luZSBzdXBwb3J0cyBvdmVybG9hZGVkIGZ1bmN0aW9ucy4KLy8gICogQHBhcmFtIFJlZmVycmFsTGlzdCAtIGEgbGlzdCBvZiBSZWZlcnJhbFJlcXVlc3RzCi8vICAqIEBwYXJhbSBMb29rQmFjayAtIHRoZSBsb29rYmFjayBwZXJpb2QgZm9yIHdoZW4gdGhlIHJlZmVycmFsIHdhcyBzZW50Ci8vICAqIEByZXR1cm5zIHtMaXN0PFJlZmVycmFsUmVxdWVzdD59IGEgbGlzdCBvZiBSZWZlcnJhbFJlcXVlc3RzIHNlbnQgaW4gdGhlIGxvb2sgYmFjayBwZXJpb2QsIG9yIG51bGwgaWYgbnVsbAovLyAgKiB3YXMgcGFzc2VkIGluCi8vICAqLwovLyBkZWZpbmUgZnVuY3Rpb24gUmVmZXJyYWxSZXF1ZXN0TG9va0JhY2soUmVmZXJyYWxMaXN0IExpc3Q8UmVmZXJyYWxSZXF1ZXN0PiwgTG9va0JhY2sgU3lzdGVtLlF1YW50aXR5KToKLy8gICBSZWZlcnJhbExpc3QgUgovLyAgICAgd2hlcmUgUi5hdXRob3JlZE9uLnZhbHVlIGluIEludGVydmFsW05vdygpIC0gTG9va0JhY2ssIE5vdygpXQoKLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gTUVESUNBVElPTlMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCgovKioKICogRmlsdGVycyBNZWRpY2F0aW9uU3RhdGVtZW50cyBieSBhIGNvbmNlcHQgcmF0aGVyIHRoYW4gYnkgYSBWYWx1ZVNldC4gIEluIENRTCAxLjMsIHRoaXMgd2lsbCBiZSBidWlsdCBpbnRvIHRoZSByZXRyaWV2ZSwKICogYnV0IGZvciBub3csIHdlIG11c3QgdXNlIGEgcXVlcnkgd2hlcmUgY2xhdXNlLgogKiBAcGFyYW0gS29uY2VwdCAtIHRoZSBjb25jZXB0IHRvIGZpbHRlciBvbiAoaW50ZW50aW9uYWxseSBtaXNwZWxsZWQgdG8gYXZvaWQgbmFtaW5nIGNsYXNoZXMpCiAqIEByZXR1cm5zIHtMaXN0PE1lZGljYXRpb25TdGF0ZW1lbnQ+fSBhIGxpc3Qgb2YgTWVkaWNhdGlvblN0YXRlbWVudCBtYXRjaGluZyB0aGUgY29uY2VwdCwgb3IgbnVsbCBpZiBudWxsIHdhcyBwYXNzZWQgaW4KICovCmRlZmluZSBmdW5jdGlvbiBNZWRpY2F0aW9uU3RhdGVtZW50c0J5Q29uY2VwdChLb25jZXB0IFN5c3RlbS5Db25jZXB0KToKICBbTWVkaWNhdGlvblN0YXRlbWVudF0gTSB3aGVyZSBOdWxsU2FmZVRvQ29uY2VwdChNLm1lZGljYXRpb24pIH4gS29uY2VwdAoKLyoqCiAqIEZpbHRlcnMgTWVkaWNhdGlvblJlcXVlc3RzIGJ5IGEgY29uY2VwdCByYXRoZXIgdGhhbiBieSBhIFZhbHVlU2V0LiAgSW4gQ1FMIDEuMywgdGhpcyB3aWxsIGJlIGJ1aWx0IGludG8gdGhlIHJldHJpZXZlLAogKiBidXQgZm9yIG5vdywgd2UgbXVzdCB1c2UgYSBxdWVyeSB3aGVyZSBjbGF1c2UuCiAqIEBwYXJhbSBLb25jZXB0IC0gdGhlIGNvbmNlcHQgdG8gZmlsdGVyIG9uIChpbnRlbnRpb25hbGx5IG1pc3BlbGxlZCB0byBhdm9pZCBuYW1pbmcgY2xhc2hlcykKICogQHJldHVybnMge0xpc3Q8TWVkaWNhdGlvblJlcXVlc3Q+fSBhIGxpc3Qgb2YgTWVkaWNhdGlvblJlcXVlc3RzIG1hdGNoaW5nIHRoZSBjb25jZXB0LCBvciBudWxsIGlmIG51bGwgd2FzIHBhc3NlZCBpbgogKi8KZGVmaW5lIGZ1bmN0aW9uIE1lZGljYXRpb25SZXF1ZXN0c0J5Q29uY2VwdChLb25jZXB0IFN5c3RlbS5Db25jZXB0KToKICBbTWVkaWNhdGlvblJlcXVlc3RdIE0gd2hlcmUgTnVsbFNhZmVUb0NvbmNlcHQoTS5tZWRpY2F0aW9uKSB+IEtvbmNlcHQKCi8qKgogKiBNZWRpY2F0aW9ucyB0aGF0IGFyZSBhY3RpdmUsIGFjY29yZGluZyB0byBhIHN0YXRlbWVudCwgYnV0IG5vdCBuZWNlc3NhcmlseSB2ZXJpZmllZCB2aWEgYSBwcmVzY3JpcHRpb24uICBGb3IgZXhhbXBsZSwKICogbWVkaWNhdGlvbnMgdGhhdCBhIHBhdGllbnQgaGFzIHNlbGYtcmVwb3J0ZWQgdG8gYmUgdGFraW5nLiAgSW4gRkhJUiBSNCwgdGhpcyBpcyByZWZsZWN0ZWQgYnkgTWVkaWNhdGlvblN0YXRlbWVudAogKiB3aXRoIHN0YXR1cyAnYWN0aXZlJywgbm8gZmxhZyBpbmRpY2F0aW5nIGl0IHdhc24ndCB0YWtlbiwgYW5kIG5vIGVuZCBkYXRlIG9yIGFuIGVuZCBkYXRlIGluIHRoZSBmdXR1cmUuCiAqIFRPRE86IFJlbmFtZSB0byBBY3RpdmUgb25jZSB0aGUgZXhlY3V0aW9uIGVuZ2luZSBzdXBwb3J0cyBvdmVybG9hZGVkIGZ1bmN0aW9ucy4KICogQHNlZSBodHRwczovL3d3dy5obDcub3JnL2ZoaXIvdmFsdWVzZXQtbWVkaWNhdGlvbi1zdGF0ZW1lbnQtc3RhdHVzLmh0bWwKICogQHBhcmFtIE1lZExpc3QgLSBhIGxpc3Qgb2YgTWVkaWNhdGlvblN0YXRlbWVudHMKICogQHJldHVybnMge0xpc3Q8TWVkaWNhdGlvblN0YXRlbWVudD59IGEgbGlzdCBvZiBhY3RpdmUgbWVkaWNhdGlvbiBzdGF0ZW1lbnRzLCBvciBudWxsIGlmIG51bGwgd2FzIHBhc3NlZCBpbgogKi8KZGVmaW5lIGZ1bmN0aW9uIEFjdGl2ZU1lZGljYXRpb25TdGF0ZW1lbnQoTWVkTGlzdCBMaXN0PE1lZGljYXRpb25TdGF0ZW1lbnQ+KToKICBNZWRMaXN0IE0KICAgIGxldCBFZmZlY3RpdmVQZXJpb2Q6IE51bGxTYWZlVG9JbnRlcnZhbChNLmVmZmVjdGl2ZSkKICAgIHdoZXJlIE0uc3RhdHVzLnZhbHVlID0gJ2FjdGl2ZScKICAgICAgYW5kIChlbmQgb2YgRWZmZWN0aXZlUGVyaW9kIGlzIG51bGwgb3IgZW5kIG9mIEVmZmVjdGl2ZVBlcmlvZCBhZnRlciBOb3coKSkKCi8qKgogKiBNZWRpY2F0aW9ucyB0aGF0IGFyZSBhY3RpdmUgb3IgY29tcGxldGVkLCBhY2NvcmRpbmcgdG8gYSBzdGF0ZW1lbnQsIGJ1dCBub3QgbmVjZXNzYXJpbHkgdmVyaWZpZWQgdmlhIGEgcHJlc2NyaXB0aW9uLgogKiBGb3IgZXhhbXBsZSwgbWVkaWNhdGlvbnMgdGhhdCBhIHBhdGllbnQgaGFzIHNlbGYtcmVwb3J0ZWQgdG8gYmUgdGFraW5nLiAgSW4gRkhJUiBSNCwgdGhpcyBpcyByZWZsZWN0ZWQgYnkKICogTWVkaWNhdGlvblN0YXRlbWVudCB3aXRoIHN0YXR1cyAnYWN0aXZlJyBvciAnY29tcGxldGVkJywgYW5kIG5vIGZsYWcgaW5kaWNhdGluZyBpdCB3YXNuJ3QgdGFrZW4uCiAqIFRPRE86IFJlbmFtZSB0byBBY3RpdmVPckNvbXBsZXRlZCBvbmNlIHRoZSBleGVjdXRpb24gZW5naW5lIHN1cHBvcnRzIG92ZXJsb2FkZWQgZnVuY3Rpb25zLgogKiBAc2VlIGh0dHBzOi8vd3d3LmhsNy5vcmcvZmhpci92YWx1ZXNldC1tZWRpY2F0aW9uLXN0YXRlbWVudC1zdGF0dXMuaHRtbAogKiBAcGFyYW0gTWVkTGlzdCAtIGEgbGlzdCBvZiBNZWRpY2F0aW9uU3RhdGVtZW50cwogKiBAcmV0dXJucyB7TGlzdDxNZWRpY2F0aW9uU3RhdGVtZW50Pn0gYSBsaXN0IG9mIGFjdGl2ZSBvciBjb21wbGV0ZWQgbWVkaWNhdGlvbiBzdGF0ZW1lbnRzLCBvciBudWxsIGlmIG51bGwgd2FzIHBhc3NlZAogKiAgIGluCiAqLwpkZWZpbmUgZnVuY3Rpb24gQWN0aXZlT3JDb21wbGV0ZWRNZWRpY2F0aW9uU3RhdGVtZW50KE1lZExpc3QgTGlzdDxNZWRpY2F0aW9uU3RhdGVtZW50Pik6CiAgTWVkTGlzdCBNCiAgICB3aGVyZSBNLnN0YXR1cy52YWx1ZSA9ICdhY3RpdmUnCiAgICAgIG9yIE0uc3RhdHVzLnZhbHVlID0gJ2NvbXBsZXRlZCcKCi8qKgoqIE1lZGljYXRpb25zIHRoYXQgYXJlIGFjdGl2ZSwgYWNjb3JkaW5nIHRvIGEgcHJlc2NyaXB0aW9uLiAgSW4gRkhJUiBSNCwgdGhpcyBpcyByZWZsZWN0ZWQgYnkgTWVkaWNhdGlvblJlcXVlc3QKKiB3aXRoIHN0YXR1cyAnYWN0aXZlJyBhbmQgbm8gZGF0ZUVuZGVkLiAgVGhlcmUgaXMgY3VycmVudGx5IGFuIG9wZW4gcXVlc3Rpb24gaW4gdGhlIEZISVIgY2hhdCB0byBkZXRlcm1pbmUgaWYgdGhpcwoqIGlzIHRoZSByaWdodCBhcHByb2FjaC4KKiBAc2VlIGh0dHBzOi8vd3d3LmhsNy5vcmcvZmhpci92YWx1ZXNldC1tZWRpY2F0aW9ucmVxdWVzdC1zdGF0dXMuaHRtbAoqIEBwYXJhbSBNZWRMaXN0IC0gYSBsaXN0IG9mIE1lZGljYXRpb25SZXF1ZXN0cwoqIEByZXR1cm5zIHtMaXN0PE1lZGljYXRpb25SZXF1ZXN0Pn0gYSBsaXN0IG9mIGFjdGl2ZSBtZWRpY2F0aW9uIG9yZGVycywgb3IgbnVsbCBpZiBudWxsIHdhcyBwYXNzZWQgaW4KKi8KZGVmaW5lIGZ1bmN0aW9uIEFjdGl2ZU1lZGljYXRpb25SZXF1ZXN0KE1lZExpc3QgTGlzdDxNZWRpY2F0aW9uUmVxdWVzdD4pOgogIE1lZExpc3QgTQogICAgd2hlcmUgTS5zdGF0dXMudmFsdWUgPSAnYWN0aXZlJwoKLyoqCiogTWVkaWNhdGlvbnMgdGhhdCBhcmUgYWN0aXZlIG9yIGNvbXBsZXRlZCwgYWNjb3JkaW5nIHRvIGEgcHJlc2NyaXB0aW9uLiAgSW4gRkhJUiBSNCwgdGhpcyBpcyByZWZsZWN0ZWQgYnkgTWVkaWNhdGlvblJlcXVlc3QKKiB3aXRoIHN0YXR1cyAnYWN0aXZlJyBvciAnY29tcGxldGVkJwoqIEBzZWUgaHR0cHM6Ly93d3cuaGw3Lm9yZy9maGlyL3ZhbHVlc2V0LW1lZGljYXRpb25yZXF1ZXN0LXN0YXR1cy5odG1sCiogQHBhcmFtIE1lZExpc3QgLSBhIGxpc3Qgb2YgTWVkaWNhdGlvblJlcXVlc3RzCiogQHJldHVybnMge0xpc3Q8TWVkaWNhdGlvblJlcXVlc3Q+fSBhIGxpc3Qgb2YgYWN0aXZlIG1lZGljYXRpb24gb3JkZXJzLCBvciBudWxsIGlmIG51bGwgd2FzIHBhc3NlZCBpbgoqLwpkZWZpbmUgZnVuY3Rpb24gQWN0aXZlT3JDb21wbGV0ZWRNZWRpY2F0aW9uUmVxdWVzdChNZWRMaXN0IExpc3Q8TWVkaWNhdGlvblJlcXVlc3Q+KToKICBNZWRMaXN0IE0KICAgIHdoZXJlIE0uc3RhdHVzLnZhbHVlID0gJ2FjdGl2ZScKICAgICAgb3IgTS5zdGF0dXMudmFsdWUgPSAnY29tcGxldGVkJwoKLyoqCiogTWVkaWNhdGlvbnMgdGhhdCBhcmUgYWN0aXZlLCBjb21wbGV0ZWQsIG9yIHN0b3BwZWQsIGFjY29yZGluZyB0byBhIHByZXNjcmlwdGlvbi4gIEluIEZISVIgUjQsIHRoaXMgaXMgcmVmbGVjdGVkIGJ5CiogTWVkaWNhdGlvblJlcXVlc3Qgd2l0aCBzdGF0dXMgJ2FjdGl2ZScsICdjb21wbGV0ZWQnLCBvciAnc3RvcHBlZCcKKiBAc2VlIGh0dHBzOi8vd3d3LmhsNy5vcmcvZmhpci92YWx1ZXNldC1tZWRpY2F0aW9ucmVxdWVzdC1zdGF0dXMuaHRtbAoqIEBwYXJhbSBNZWRMaXN0IC0gYSBsaXN0IG9mIE1lZGljYXRpb25SZXF1ZXN0cwoqIEByZXR1cm5zIHtMaXN0PE1lZGljYXRpb25SZXF1ZXN0Pn0gYSBsaXN0IG9mIGFjdGl2ZSBtZWRpY2F0aW9uIG9yZGVycywgb3IgbnVsbCBpZiBudWxsIHdhcyBwYXNzZWQgaW4KKi8KZGVmaW5lIGZ1bmN0aW9uIEFjdGl2ZUNvbXBsZXRlZE9yU3RvcHBlZE1lZGljYXRpb25SZXF1ZXN0KE1lZExpc3QgTGlzdDxNZWRpY2F0aW9uUmVxdWVzdD4pOgogIE1lZExpc3QgTQogICAgd2hlcmUgTS5zdGF0dXMudmFsdWUgPSAnYWN0aXZlJwogICAgICBvciBNLnN0YXR1cy52YWx1ZSA9ICdjb21wbGV0ZWQnCiAgICAgIG9yIE0uc3RhdHVzLnZhbHVlID0gJ3N0b3BwZWQnCgovKioKICogTWVkaWNhdGlvblN0YXRlbWVudCB3aXRoIGFuIGVmZmVjdGl2ZSBkYXRlIGluIHRoZSBzcGVjaWZpZWQgImxvb2sgYmFjayIgcGVyaW9kLiAgRm9yIGV4YW1wbGUsIHN0YXRlbWVudHMgYWJvdXQgb3Bpb2lkCiAqIHVzZSBpbiB0aGUgbGFzdCAxODAgZGF5cy4KICogVE9ETzogUmVuYW1lIHRvIExvb2tCYWNrIG9uY2UgdGhlIGV4ZWN1dGlvbiBlbmdpbmUgc3VwcG9ydHMgb3ZlcmxvYWRlZCBmdW5jdGlvbnMuCiAqIEBwYXJhbSBNZWRMaXN0IC0gYSBsaXN0IG9mIE1lZGljYXRpb25TdGF0ZW1lbnRzCiAqIEBwYXJhbSBMb29rQmFjayAtIGEgZHVyYXRpb24gUXVhbnRpdHkgaW5kaWNhdGluZyBob3cgZmFyIGJhY2sgdG8gbG9vayBmb3IgTWVkaWNhdGlvblN0YXRlbWVudHMKICogQHJldHVybnMge0xpc3Q8TWVkaWNhdGlvblN0YXRlbWVudD59IGEgbGlzdCBvZiBNZWRpY2F0aW9uU3RhdGVtZW50cyB3aXRoIGVmZmVjdGl2ZSBkYXRlIGluIHRoZSBzcGVjaWZpZWQgbG9va2JhY2sKICogcGVyaW9kLCBvciBudWxsIGlmIG51bGwgd2FzIHBhc3NlZCBpbgogKi8KZGVmaW5lIGZ1bmN0aW9uIE1lZGljYXRpb25TdGF0ZW1lbnRMb29rQmFjayhNZWRMaXN0IExpc3Q8TWVkaWNhdGlvblN0YXRlbWVudD4sIExvb2tCYWNrIFN5c3RlbS5RdWFudGl0eSk6CiAgTWVkTGlzdCBNCiAgICBsZXQgTG9va0JhY2tJbnRlcnZhbDogSW50ZXJ2YWxbTm93KCkgLSBMb29rQmFjaywgTm93KCldCiAgICB3aGVyZSBNLmVmZmVjdGl2ZS52YWx1ZSBpbiBMb29rQmFja0ludGVydmFsCiAgICAgIG9yIE51bGxTYWZlVG9JbnRlcnZhbChNLmVmZmVjdGl2ZSkgb3ZlcmxhcHMgTG9va0JhY2tJbnRlcnZhbAoKLyoqCiAqIE1lZGljYXRpb25SZXF1ZXN0cyB3aXRoIGEgd3JpdHRlbiBkYXRlIGluIHRoZSBzcGVjaWZpZWQgImxvb2sgYmFjayIgcGVyaW9kLiAgRm9yIGV4YW1wbGUsIG9waW9pZCBvcmRlcnMgaW4gdGhlIGxhc3QKICogMTgwIGRheXMuCiAqIFRPRE86IFJlbmFtZSB0byBMb29rQmFjayBvbmNlIHRoZSBleGVjdXRpb24gZW5naW5lIHN1cHBvcnRzIG92ZXJsb2FkZWQgZnVuY3Rpb25zLgogKiBAcGFyYW0gT3JkZXJMaXN0IC0gYSBsaXN0IG9mIE1lZGljYXRpb25SZXF1ZXN0cwogKiBAcGFyYW0gTG9va0JhY2sgLSBhIGR1cmF0aW9uIFF1YW50aXR5IGluZGljYXRpbmcgaG93IGZhciBiYWNrIHRvIGxvb2sgZm9yIE1lZGljYXRpb25SZXF1ZXN0cwogKiBAcmV0dXJucyB7TGlzdDxNZWRpY2F0aW9uUmVxdWVzdD59IGEgbGlzdCBvZiBNZWRpY2F0aW9uUmVxdWVzdHMgd2l0aCB3cml0dGVuIGRhdGUgaW4gdGhlIHNwZWNpZmllZCBsb29rYmFjayBwZXJpb2QsCiAqIG9yIG51bGwgaWYgbnVsbCB3YXMgcGFzc2VkIGluCiAqLwpkZWZpbmUgZnVuY3Rpb24gTWVkaWNhdGlvblJlcXVlc3RMb29rQmFjayhNZWRMaXN0IExpc3Q8TWVkaWNhdGlvblJlcXVlc3Q+LCBMb29rQmFjayBTeXN0ZW0uUXVhbnRpdHkpOgogIE1lZExpc3QgTSB3aGVyZSBNLmF1dGhvcmVkT24udmFsdWUgaW4gSW50ZXJ2YWxbTm93KCkgLSBMb29rQmFjaywgTm93KCldCgovLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSBFTkNPVU5URVJTIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKLyoqCiAqIEZpbHRlcnMgRW5jb3VudGVycyBieSBhIGNvbmNlcHQgcmF0aGVyIHRoYW4gYnkgYSBWYWx1ZVNldC4gIEluIENRTCAxLjMsIHRoaXMgd2lsbCBiZSBidWlsdCBpbnRvIHRoZSByZXRyaWV2ZSwKICogYnV0IGZvciBub3csIHdlIG11c3QgdXNlIGEgcXVlcnkgd2hlcmUgY2xhdXNlLgogKiBAcGFyYW0gS29uY2VwdCAtIHRoZSBjb25jZXB0IHRvIGZpbHRlciBvbiAoaW50ZW50aW9uYWxseSBtaXNwZWxsZWQgdG8gYXZvaWQgbmFtaW5nIGNsYXNoZXMpCiAqIEByZXR1cm5zIHtMaXN0PEVuY291bnRlcj59IGEgbGlzdCBvZiBFbmNvdW50ZXJzIG1hdGNoaW5nIHRoZSBjb25jZXB0LCBvciBudWxsIGlmIG51bGwgd2FzIHBhc3NlZCBpbgogKi8KZGVmaW5lIGZ1bmN0aW9uIEVuY291bnRlcnNCeUNvbmNlcHQoS29uY2VwdCBTeXN0ZW0uQ29uY2VwdCk6CiAgW0VuY291bnRlcl0gRSB3aGVyZSBleGlzdHMoIChFLnR5cGUpIEVUIHdoZXJlIE51bGxTYWZlVG9Db25jZXB0KEVUKSB+IEtvbmNlcHQgKQoKLyoqCiAqIEVuY291bnRlcnMgdGhhdCBhcmUgaW4gcHJvZ3Jlc3MuIEluIEZISVIgUjQsIHRoaXMgaXMgcmVmbGVjdGVkIGJ5IHN0YXR1czogJ2luLXByb2dyZXNzJy4KICogQHNlZSBodHRwczovL3d3dy5obDcub3JnL2ZoaXIvdmFsdWVzZXQtZW5jb3VudGVyLXN0YXR1cy5odG1sCiAqIEBwYXJhbSBFbmNMaXN0IC0gYSBsaXN0IG9mIEVuY291bnRlcnMKICogQHJldHVybnMge0xpc3Q8RW5jb3VudGVyPn0gYSBsaXN0IG9mIGluIHByb2dyZXNzIGVuY291bnRlcnMsIG9yIG51bGwgaWYgbnVsbCB3YXMgcGFzc2VkIGluCiAqLwpkZWZpbmUgZnVuY3Rpb24gSW5Qcm9ncmVzcyhFbmNMaXN0IExpc3Q8RW5jb3VudGVyPik6CiAgRW5jTGlzdCBFCiAgICB3aGVyZSBFLnN0YXR1cy52YWx1ZSA9ICdpbi1wcm9ncmVzcycKCi8qKgogKiBFbmNvdW50ZXJzIHRoYXQgaGF2ZSBub3QgYmVlbiBjYW5jZWxsZWQuIEluIEZISVIgUjQsIHRoaXMgaXMgcmVmbGVjdGVkIGJ5ICBhbmR5IHN0YXR1cyBvdGhlciAKICogdGhhbjogJ2NhbmNlbGxlZCcuCiAqIEBzZWUgaHR0cHM6Ly93d3cuaGw3Lm9yZy9maGlyL3ZhbHVlc2V0LWVuY291bnRlci1zdGF0dXMuaHRtbAogKiBAcGFyYW0gRW5jTGlzdCAtIGEgbGlzdCBvZiBFbmNvdW50ZXJzCiAqIEByZXR1cm5zIHtMaXN0PEVuY291bnRlcj59IGEgbGlzdCBvZiBpbiBwcm9ncmVzcyBlbmNvdW50ZXJzLCBvciBudWxsIGlmIG51bGwgd2FzIHBhc3NlZCBpbgogKi8KZGVmaW5lIGZ1bmN0aW9uIE5vdENhbmNlbGxlZChFbmNMaXN0IExpc3Q8RW5jb3VudGVyPik6CiAgRW5jTGlzdCBFCiAgICB3aGVyZSBFLnN0YXR1cy52YWx1ZSAhPSAnY2FuY2VsbGVkJwoKLyoqCiAqIEVuY291bnRlcnMgcGVyZm9ybWVkIGluIHRoZSBzcGVjaWZpZWQgImxvb2sgYmFjayIgcGVyaW9kLgogKiBUT0RPOiBSZW5hbWUgdG8gTG9va0JhY2sgb25jZSB0aGUgZXhlY3V0aW9uIGVuZ2luZSBzdXBwb3J0cyBvdmVybG9hZGVkIGZ1bmN0aW9ucy4KICogQHBhcmFtIEVuY0xpc3QgLSBhIGxpc3Qgb2YgRW5jb3VudGVycwogKiBAcGFyYW0gTG9va0JhY2sgLSB0aGUgbG9va2JhY2sgcGVyaW9kIGZvciB3aGVuIHRoZSBlbmNvdW50ZXIgb2NjdXJyZWQKICogQHJldHVybnMge0xpc3Q8RW5jb3VudGVyPn0gYSBsaXN0IG9mIEVuY291bnRlcnMgb2NjdXJyaW5nIGR1cmluZyB0aGUgbG9vayBiYWNrIHBlcmlvZCwgb3IgbnVsbCBpZiBudWxsCiAqIHdhcyBwYXNzZWQgaW4KICovCmRlZmluZSBmdW5jdGlvbiBFbmNvdW50ZXJMb29rQmFjayhFbmNMaXN0IExpc3Q8RW5jb3VudGVyPiwgTG9va0JhY2sgU3lzdGVtLlF1YW50aXR5KToKICBFbmNMaXN0IEUKICAgIGxldCBMb29rQmFja0ludGVydmFsOiBJbnRlcnZhbFtOb3coKSAtIExvb2tCYWNrLCBOb3coKV0KICAgIHdoZXJlIE51bGxTYWZlVG9JbnRlcnZhbChFLnBlcmlvZCkgb3ZlcmxhcHMgTG9va0JhY2tJbnRlcnZhbAoKLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gQUxMRVJHWSBJTlRPTEVSQU5DRVMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCgovKioKICogRmlsdGVycyBBbGxlcmd5SW50b2xlcmFuY2VzIGJ5IGEgY29uY2VwdCByYXRoZXIgdGhhbiBieSBhIFZhbHVlU2V0LiAgSW4gQ1FMIDEuMywgdGhpcyB3aWxsIGJlIGJ1aWx0IGludG8gdGhlIHJldHJpZXZlLAogKiBidXQgZm9yIG5vdywgd2UgbXVzdCB1c2UgYSBxdWVyeSB3aGVyZSBjbGF1c2UuCiAqIEBwYXJhbSBLb25jZXB0IC0gdGhlIGNvbmNlcHQgdG8gZmlsdGVyIG9uIChpbnRlbnRpb25hbGx5IG1pc3BlbGxlZCB0byBhdm9pZCBuYW1pbmcgY2xhc2hlcykKICogQHJldHVybnMge0xpc3Q8QWxsZXJneUludG9sZXJhbmNlPn0gYSBsaXN0IG9mIEFsbGVyZ3kgSW50b2xlcmFuY2VzIG1hdGNoaW5nIHRoZSBjb25jZXB0LCBvciBudWxsIGlmIG51bGwgd2FzIHBhc3NlZCBpbgogKi8KZGVmaW5lIGZ1bmN0aW9uIEFsbGVyZ3lJbnRvbGVyYW5jZXNCeUNvbmNlcHQoS29uY2VwdCBTeXN0ZW0uQ29uY2VwdCk6CiAgW0FsbGVyZ3lJbnRvbGVyYW5jZV0gQSB3aGVyZSBOdWxsU2FmZVRvQ29uY2VwdChBLmNvZGUpIH4gS29uY2VwdAoKLyoqCiogQWxsZXJneUludG9sZXJhbmNlcyB0aGF0IGFyZSBhY3RpdmUgb3IgY29uZmlybWVkLiAgSW4gRkhJUiBSNCwgdGhpcyBpcyByZWZsZWN0ZWQgYnkgQWxsZXJneUludG9sZXJhbmNlCiogd2l0aCB2ZXJpZmljYXRpb25TdGF0dXMgJ2FjdGl2ZScgb3IgJ2NvbmZpcm1lZCcKKiBAc2VlIGh0dHBzOi8vd3d3LmhsNy5vcmcvZmhpci92YWx1ZXNldC1hbGxlcmd5aW50b2xlcmFuY2UtdmVyaWZpY2F0aW9uLmh0bWwKKiBAcGFyYW0gQWxsZXJneUludG9sTGlzdCAtIGEgbGlzdCBvZiBBbGxlcmd5SW50b2xlcmFuY2VzCiogQHJldHVybnMge0xpc3Q8QWxsZXJneUludG9sZXJhbmNlPn0gYSBsaXN0IG9mIGFjdGl2ZSBvciBjb25maXJtZWQgYWxsZXJneSBpbnRvbGVyYW5jZXMsIG9yIG51bGwgaWYgbnVsbCB3YXMgcGFzc2VkIGluCiovCmRlZmluZSBmdW5jdGlvbiBDb25maXJtZWRBbGxlcmd5SW50b2xlcmFuY2UoQWxsZXJneUludG9sTGlzdCBMaXN0PEFsbGVyZ3lJbnRvbGVyYW5jZT4pOgogIEFsbGVyZ3lJbnRvbExpc3QgQQogICAgd2hlcmUgQS52ZXJpZmljYXRpb25TdGF0dXMuY29kaW5nIH4gIkFsbGVyZ3lJbnRvbGVyYW5jZSB2ZXJpZmljYXRpb25TdGF0dXMgY29uZmlybWVkIGNvZGUiCgovLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSBHT0FMUyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCi8qKgogKiBHb2FscyB3aXRoIGEgc3RhcnQsIHRhcmdldCwgb3Igc3RhdHVzIGRhdGUgaW4gdGhlIHNwZWNpZmllZCAibG9vayBiYWNrIiBwZXJpb2QuICBGb3IgZXhhbXBsZSwgUGFpbiBNYW5hZ2VtZW50IEdvYWxzCiAqIGluIHRoZSBsYXN0IDIgeWVhcnMuCiAqIFRPRE86IFJlbmFtZSB0byBMb29rQmFjayBvbmNlIHRoZSBleGVjdXRpb24gZW5naW5lIHN1cHBvcnRzIG92ZXJsb2FkZWQgZnVuY3Rpb25zLgogKiBAcGFyYW0gR29hbExpc3QgLSBhIGxpc3Qgb2YgR29hbHMKICogQHJldHVybnMge0xpc3Q8R29hbD59IGEgbGlzdCBvZiBHb2FscyB3aXRoIGEgc3RhcnQsIHRhcmdldCwgb3Igc3RhdHVzIGRhdGUgaW4gdGhlIHNwZWNpZmllZCBsb29rYmFjayBwZXJpb2QsIG9yIG51bGwKICogaWYgbnVsbCB3YXMgcGFzc2VkIGluCiAqLwpkZWZpbmUgZnVuY3Rpb24gR29hbExvb2tCYWNrKEdvYWxMaXN0IExpc3Q8R29hbD4sIExvb2tCYWNrIFN5c3RlbS5RdWFudGl0eSk6CiAgR29hbExpc3QgRwogICAgbGV0IExvb2tCYWNrSW50ZXJ2YWw6IEludGVydmFsW05vdygpIC0gTG9va0JhY2ssIE5vdygpXQogICAgd2hlcmUgRy5zdGFydC52YWx1ZSBpbiBMb29rQmFja0ludGVydmFsCiAgICAgIG9yIEcudGFyZ2V0LmR1ZUQgaW4gTG9va0JhY2tJbnRlcnZhbAogICAgICBvciBHLnN0YXJ0LnZhbHVlIGluIExvb2tCYWNrSW50ZXJ2YWwKICAgICAgb3IgRy5zdGF0dXNEYXRlLnZhbHVlIGluIExvb2tCYWNrSW50ZXJ2YWwK"
},
{
"contentType" : "application/elm+xml"
}
]
}