Gravitate Health FHIR Implementation Guide
0.1.0 - CI Build

Gravitate Health FHIR Implementation Guide, published by Gravitate Health Project. This guide is not an authorized publication; it is the continuous build for version 0.1.0 built by the FHIR (HL7® FHIR® Standard) CI Build. This version is based on the current content of https://github.com/hl7-eu/gravitate-health/ and changes regularly. See the Directory of published versions

: rmm-lens - TTL Representation

Draft as of 2024-07-30

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 xsd: <http://www.w3.org/2001/XMLSchema#> .

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

 a fhir:Library ;
  fhir:nodeRole fhir:treeRoot ;
  fhir:id [ fhir:v "rmm-lens"] ; # 
  fhir:meta [
    ( fhir:profile [
fhir:v "http://hl7.eu/fhir/ig/gravitate-health/StructureDefinition/lens"^^xsd:anyURI ;
fhir:link <http://hl7.eu/fhir/ig/gravitate-health/StructureDefinition/lens>     ] )
  ] ; # 
  fhir:text [
fhir:status [ fhir:v "generated" ] ;
fhir:div "<div xmlns=\"http://www.w3.org/1999/xhtml\"><p class=\"res-header-id\"><b>Generated Narrative: Library rmm-lens</b></p><a name=\"rmm-lens\"> </a><a name=\"hcrmm-lens\"> </a><a name=\"rmm-lens-en-US\"> </a><h2>Parameters</h2><table class=\"grid\"><tr><td/><td>in</td><td/><td/><td>CodeableConcept</td><td>parameter if it exists</td></tr></table><h2>Contents</h2><p><code>application/javascript</code></p><pre><code>let pvData = pv;\nlet htmlData = html;\n\nlet epiData = epi;\nlet ipsData = ips;\n\nlet getSpecification = () =&gt; {\n    return &quot;1.0.0&quot;;\n};\n\nlet enhance = async () =&gt; {\n\n    console.log(&quot;__________ RMM LENS EXECUTION STARTED _____________&quot;)\n    // Proves that IPS exists\n    let response;\n\n    let medicinalProductDefinitionId = getMedicinalProductDefinitionId(epi);\n\n    let listOfSMResponse = await fetch(&quot;https://gravitate-health.lst.tfo.upm.es/epi/api/fhir/DocumentReference?subject=&quot; + medicinalProductDefinitionId);\n    let listOfSM = await listOfSMResponse.json();\n\n    let epiReference = epi.entry[0].resource.subject[0].reference;\n\n    for (let i = 0; i &lt; listOfSM.entry.length; i++) {\n        let sm = listOfSM.entry[i];\n        let smReference = sm.resource.subject.reference;\n        \n        if (smReference == epiReference) {\n            console.log(&quot;SM Reference: &quot;, smReference, &quot; matched with EPI Reference: &quot;, epiReference);\n            \n            // Create the extension at the beggining. TODO see where it should be\n            if (epi.entry[0].resource.section[0].section[0].extension === undefined) {\n                epi.entry[0].resource.section[0].section[0].extension = [];\n            }\n\n            let smAttachment = sm.resource.content[0].attachment\n\n            let codeAndDisplay = getCodeAndDisplay(smAttachment);\n            console.log(&quot;GetCodeAndDisplay: &quot;, codeAndDisplay)\n            if (codeAndDisplay === undefined) {\n                continue;\n            }\n\n            let newExtension;\n\n            //if (codeAndDisplay.code.includes(&quot;inapp&quot;)) {\n            if (smAttachment.data !== undefined) {\n                newExtension = {\n                    extension: [\n                        {\n                            url: &quot;type&quot;,\n                            valueCodeableConcept: {\n                                coding: [\n                                    {\n                                        system: &quot;http://hl7.eu/fhir/ig/gravitate-health/CodeSystem/type-of-data-cs&quot;,\n                                        code: codeAndDisplay.code,\n                                        display: codeAndDisplay.display\n                                    }\n                                ]\n                            }\n                        },\n                        {\n                            url: &quot;concept&quot;,\n                            valueBase64Binary: smAttachment.data\n                        }\n                    ],\n                    url: &quot;http://hl7.eu/fhir/ig/gravitate-health/StructureDefinition/AdditionalInformation&quot;\n                }\n            //} else {\n            } else if (smAttachment.url !== undefined) {\n                newExtension = {\n                    extension: [\n                        {\n                            url: &quot;type&quot;,\n                            valueCodeableConcept: {\n                                coding: [\n                                    {\n                                        system: &quot;http://hl7.eu/fhir/ig/gravitate-health/CodeSystem/type-of-data-cs&quot;,\n                                        code: codeAndDisplay.code,\n                                        display: codeAndDisplay.display\n                                    }\n                                ]\n\n                            }\n                        },\n                        {\n                            url: &quot;concept&quot;,\n                            valueUrl: smAttachment.url\n                        }\n                    ],\n                    url: &quot;http://hl7.eu/fhir/ig/gravitate-health/StructureDefinition/AdditionalInformation&quot;\n                }\n            }\n\n            console.log(&quot;NEW EXTENSION: &quot;, newExtension)\n\n            // Check if extension already exists before adding it\n            let currentExtensions = epi.entry[0].resource.section[0].section[0].extension;\n            if (currentExtensions.length &gt; 0) {\n                let extensionExists = false;\n                for (let j = 0; j &lt; currentExtensions.length; j++) {\n                    if (deepEqual(currentExtensions[j], newExtension)) {\n                        extensionExists = true;\n                        break;\n                    }\n                }\n                if (!extensionExists) epi.entry[0].resource.section[0].section[0].extension.push(newExtension);\n            } else {\n                epi.entry[0].resource.section[0].section[0].extension.push(newExtension);\n            }\n            //epi.entry[0].resource.section[0].section[0].extension.push(newExtension);\n\n        }\n    }\n\n    console.log(&quot;__________ RMM LENS EXECUTION FINISHED _____________&quot;)\n    return response\n\n};\n\ngetMedicinalProductDefinitionId = (bundle) =&gt; {\n    for (let i = 0; i &lt; bundle.entry.length; i++) {\n        if (bundle.entry[i].resource.resourceType === &quot;MedicinalProductDefinition&quot;) {\n            return bundle.entry[i].resource.id;\n        }\n    }\n    return null;\n}\n\ngetCodeAndDisplay = (attachment) =&gt; {\n    console.log(&quot;Function getCodeAndDisplay&quot;)\n    console.log(&quot;Attachment: &quot;, attachment)\n    if (attachment.contentType === &quot;text/html&quot;) {\n        if (attachment.duration) {\n            if (attachment.url.includes(&quot;youtube&quot;)) {\n                return {\n                    code: &quot;video-inapp&quot;,\n                    display: &quot;VIDEO&quot;\n                }\n            } else {\n                return {\n                    code: &quot;audio-inapp&quot;,\n                    display: &quot;AUDIO&quot;\n                }\n            }\n\n        } else {\n            return {\n                code: &quot;image-inapp&quot;,\n                display: &quot;IMG&quot;\n            }\n        }\n    } else {\n        switch (attachment.contentType) {\n            case &quot;video/mp4&quot;:\n                return {\n                    code: &quot;video&quot;,\n                    display: &quot;VIDEO&quot;\n                }\n            case &quot;application/pdf&quot;:\n                return {\n                    code: &quot;pdf&quot;,\n                    display: &quot;PDF&quot;\n                }\n            case &quot;audio/mpeg&quot;:\n                return {\n                    code: &quot;audio&quot;,\n                    display: &quot;AUDIO&quot;\n                }\n            case &quot;image/jpg&quot;:\n                return {\n                    code: &quot;image&quot;,\n                    display: &quot;IMG&quot;\n                }\n            case &quot;image/jpeg&quot;:\n                return {\n                    code: &quot;image&quot;,\n                    display: &quot;IMG&quot;\n                }\n        }\n    }\n}\n\nfunction deepEqual(object1, object2) {\n    const keys1 = Object.keys(object1);\n    const keys2 = Object.keys(object2);\n  \n    if (keys1.length !== keys2.length) {\n      return false;\n    }\n  \n    for (const key of keys1) {\n      const val1 = object1[key];\n      const val2 = object2[key];\n      const areObjects = isObject(val1) &amp;&amp; isObject(val2);\n      if (\n        areObjects &amp;&amp; !deepEqual(val1, val2) ||\n        !areObjects &amp;&amp; val1 !== val2\n      ) {\n        return false;\n      }\n    }\n  \n    return true;\n  }\n  \n  function isObject(object) {\n    return object != null &amp;&amp; typeof object === 'object';\n  }\n\nreturn {\n    enhance: enhance,\n    getSpecification: getSpecification,\n};</code></pre></div>"
  ] ; # 
  fhir:extension ( [
fhir:url [ fhir:v "http://hl7.eu/fhir/ig/gravitate-health/StructureDefinition/lee-version"^^xsd:anyURI ] ;
fhir:value [ fhir:v "dev" ]
  ] ) ; # 
  fhir:url [ fhir:v "http://hl7.eu/fhir/ig/gravitate-health/Library/mock-lib"^^xsd:anyURI] ; # 
  fhir:identifier ( [
fhir:system [ fhir:v "http://gravitate-health.lst.tfo.upm.es"^^xsd:anyURI ] ;
fhir:value [ fhir:v "rmm-lens" ]
  ] ) ; # 
  fhir:version [ fhir:v "0.1.0"] ; # 
  fhir:name [ fhir:v "rmm-lens"] ; # 
  fhir:title [ fhir:v "rmm-lens"] ; # 
  fhir:status [ fhir:v "draft"] ; # 
  fhir:experimental [ fhir:v "true"^^xsd:boolean] ; # 
  fhir:type [
    ( fhir:coding [
fhir:code [ fhir:v "logical-library" ]     ] )
  ] ; # 
  fhir:date [ fhir:v "2024-07-30T10:17:53.758Z"^^xsd:dateTime] ; # 
  fhir:publisher [ fhir:v "Gravitate Health Project"] ; # 
  fhir:contact ( [
fhir:name [ fhir:v "Gravitate Health Project" ] ;
    ( fhir:telecom [
fhir:system [ fhir:v "url" ] ;
fhir:value [ fhir:v "https://www.gravitatehealth.eu/" ]     ] )
  ] [
fhir:name [ fhir:v "Gravitate Health Project" ] ;
    ( fhir:telecom [
fhir:system [ fhir:v "url" ] ;
fhir:value [ fhir:v "https://www.gravitatehealth.eu/" ]     ] )
  ] ) ; # 
  fhir:description [ fhir:v "Lens that aplies RMM to a leaflet"] ; # 
  fhir:purpose [ fhir:v "Match the RMM of an ePI to a leaflet"] ; # 
  fhir:usage [ fhir:v "Apply this lens into a leaflet to search for its RMM"] ; # 
  fhir:copyright [ fhir:v "© 2024 Gravitate Health"] ; # 
  fhir:parameter ( [
fhir:use [ fhir:v "in" ] ;
fhir:documentation [ fhir:v "parameter if it exists" ] ;
fhir:type [ fhir:v "CodeableConcept" ]
  ] ) ; # 
  fhir:content ( [
fhir:contentType [ fhir:v "application/javascript" ] ;
fhir:data [ fhir:v "bGV0IHB2RGF0YSA9IHB2OwpsZXQgaHRtbERhdGEgPSBodG1sOwoKbGV0IGVwaURhdGEgPSBlcGk7CmxldCBpcHNEYXRhID0gaXBzOwoKbGV0IGdldFNwZWNpZmljYXRpb24gPSAoKSA9PiB7CiAgICByZXR1cm4gIjEuMC4wIjsKfTsKCmxldCBlbmhhbmNlID0gYXN5bmMgKCkgPT4gewoKICAgIGNvbnNvbGUubG9nKCJfX19fX19fX19fIFJNTSBMRU5TIEVYRUNVVElPTiBTVEFSVEVEIF9fX19fX19fX19fX18iKQogICAgLy8gUHJvdmVzIHRoYXQgSVBTIGV4aXN0cwogICAgbGV0IHJlc3BvbnNlOwoKICAgIGxldCBtZWRpY2luYWxQcm9kdWN0RGVmaW5pdGlvbklkID0gZ2V0TWVkaWNpbmFsUHJvZHVjdERlZmluaXRpb25JZChlcGkpOwoKICAgIGxldCBsaXN0T2ZTTVJlc3BvbnNlID0gYXdhaXQgZmV0Y2goImh0dHBzOi8vZ3Jhdml0YXRlLWhlYWx0aC5sc3QudGZvLnVwbS5lcy9lcGkvYXBpL2ZoaXIvRG9jdW1lbnRSZWZlcmVuY2U/c3ViamVjdD0iICsgbWVkaWNpbmFsUHJvZHVjdERlZmluaXRpb25JZCk7CiAgICBsZXQgbGlzdE9mU00gPSBhd2FpdCBsaXN0T2ZTTVJlc3BvbnNlLmpzb24oKTsKCiAgICBsZXQgZXBpUmVmZXJlbmNlID0gZXBpLmVudHJ5WzBdLnJlc291cmNlLnN1YmplY3RbMF0ucmVmZXJlbmNlOwoKICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbGlzdE9mU00uZW50cnkubGVuZ3RoOyBpKyspIHsKICAgICAgICBsZXQgc20gPSBsaXN0T2ZTTS5lbnRyeVtpXTsKICAgICAgICBsZXQgc21SZWZlcmVuY2UgPSBzbS5yZXNvdXJjZS5zdWJqZWN0LnJlZmVyZW5jZTsKICAgICAgICAKICAgICAgICBpZiAoc21SZWZlcmVuY2UgPT0gZXBpUmVmZXJlbmNlKSB7CiAgICAgICAgICAgIGNvbnNvbGUubG9nKCJTTSBSZWZlcmVuY2U6ICIsIHNtUmVmZXJlbmNlLCAiIG1hdGNoZWQgd2l0aCBFUEkgUmVmZXJlbmNlOiAiLCBlcGlSZWZlcmVuY2UpOwogICAgICAgICAgICAKICAgICAgICAgICAgLy8gQ3JlYXRlIHRoZSBleHRlbnNpb24gYXQgdGhlIGJlZ2dpbmluZy4gVE9ETyBzZWUgd2hlcmUgaXQgc2hvdWxkIGJlCiAgICAgICAgICAgIGlmIChlcGkuZW50cnlbMF0ucmVzb3VyY2Uuc2VjdGlvblswXS5zZWN0aW9uWzBdLmV4dGVuc2lvbiA9PT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICAgICAgICBlcGkuZW50cnlbMF0ucmVzb3VyY2Uuc2VjdGlvblswXS5zZWN0aW9uWzBdLmV4dGVuc2lvbiA9IFtdOwogICAgICAgICAgICB9CgogICAgICAgICAgICBsZXQgc21BdHRhY2htZW50ID0gc20ucmVzb3VyY2UuY29udGVudFswXS5hdHRhY2htZW50CgogICAgICAgICAgICBsZXQgY29kZUFuZERpc3BsYXkgPSBnZXRDb2RlQW5kRGlzcGxheShzbUF0dGFjaG1lbnQpOwogICAgICAgICAgICBjb25zb2xlLmxvZygiR2V0Q29kZUFuZERpc3BsYXk6ICIsIGNvZGVBbmREaXNwbGF5KQogICAgICAgICAgICBpZiAoY29kZUFuZERpc3BsYXkgPT09IHVuZGVmaW5lZCkgewogICAgICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIGxldCBuZXdFeHRlbnNpb247CgogICAgICAgICAgICAvL2lmIChjb2RlQW5kRGlzcGxheS5jb2RlLmluY2x1ZGVzKCJpbmFwcCIpKSB7CiAgICAgICAgICAgIGlmIChzbUF0dGFjaG1lbnQuZGF0YSAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICAgICAgICBuZXdFeHRlbnNpb24gPSB7CiAgICAgICAgICAgICAgICAgICAgZXh0ZW5zaW9uOiBbCiAgICAgICAgICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVybDogInR5cGUiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWVDb2RlYWJsZUNvbmNlcHQ6IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2Rpbmc6IFsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3lzdGVtOiAiaHR0cDovL2hsNy5ldS9maGlyL2lnL2dyYXZpdGF0ZS1oZWFsdGgvQ29kZVN5c3RlbS90eXBlLW9mLWRhdGEtY3MiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29kZTogY29kZUFuZERpc3BsYXkuY29kZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpc3BsYXk6IGNvZGVBbmREaXNwbGF5LmRpc3BsYXkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIF0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgfSwKICAgICAgICAgICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgdXJsOiAiY29uY2VwdCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZUJhc2U2NEJpbmFyeTogc21BdHRhY2htZW50LmRhdGEKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIF0sCiAgICAgICAgICAgICAgICAgICAgdXJsOiAiaHR0cDovL2hsNy5ldS9maGlyL2lnL2dyYXZpdGF0ZS1oZWFsdGgvU3RydWN0dXJlRGVmaW5pdGlvbi9BZGRpdGlvbmFsSW5mb3JtYXRpb24iCiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIC8vfSBlbHNlIHsKICAgICAgICAgICAgfSBlbHNlIGlmIChzbUF0dGFjaG1lbnQudXJsICE9PSB1bmRlZmluZWQpIHsKICAgICAgICAgICAgICAgIG5ld0V4dGVuc2lvbiA9IHsKICAgICAgICAgICAgICAgICAgICBleHRlbnNpb246IFsKICAgICAgICAgICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgdXJsOiAidHlwZSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZUNvZGVhYmxlQ29uY2VwdDogewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvZGluZzogWwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzeXN0ZW06ICJodHRwOi8vaGw3LmV1L2ZoaXIvaWcvZ3Jhdml0YXRlLWhlYWx0aC9Db2RlU3lzdGVtL3R5cGUtb2YtZGF0YS1jcyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2RlOiBjb2RlQW5kRGlzcGxheS5jb2RlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlzcGxheTogY29kZUFuZERpc3BsYXkuZGlzcGxheQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXQoKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgfSwKICAgICAgICAgICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgdXJsOiAiY29uY2VwdCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZVVybDogc21BdHRhY2htZW50LnVybAogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgXSwKICAgICAgICAgICAgICAgICAgICB1cmw6ICJodHRwOi8vaGw3LmV1L2ZoaXIvaWcvZ3Jhdml0YXRlLWhlYWx0aC9TdHJ1Y3R1cmVEZWZpbml0aW9uL0FkZGl0aW9uYWxJbmZvcm1hdGlvbiIKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQoKICAgICAgICAgICAgY29uc29sZS5sb2coIk5FVyBFWFRFTlNJT046ICIsIG5ld0V4dGVuc2lvbikKCiAgICAgICAgICAgIC8vIENoZWNrIGlmIGV4dGVuc2lvbiBhbHJlYWR5IGV4aXN0cyBiZWZvcmUgYWRkaW5nIGl0CiAgICAgICAgICAgIGxldCBjdXJyZW50RXh0ZW5zaW9ucyA9IGVwaS5lbnRyeVswXS5yZXNvdXJjZS5zZWN0aW9uWzBdLnNlY3Rpb25bMF0uZXh0ZW5zaW9uOwogICAgICAgICAgICBpZiAoY3VycmVudEV4dGVuc2lvbnMubGVuZ3RoID4gMCkgewogICAgICAgICAgICAgICAgbGV0IGV4dGVuc2lvbkV4aXN0cyA9IGZhbHNlOwogICAgICAgICAgICAgICAgZm9yIChsZXQgaiA9IDA7IGogPCBjdXJyZW50RXh0ZW5zaW9ucy5sZW5ndGg7IGorKykgewogICAgICAgICAgICAgICAgICAgIGlmIChkZWVwRXF1YWwoY3VycmVudEV4dGVuc2lvbnNbal0sIG5ld0V4dGVuc2lvbikpIHsKICAgICAgICAgICAgICAgICAgICAgICAgZXh0ZW5zaW9uRXhpc3RzID0gdHJ1ZTsKICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgaWYgKCFleHRlbnNpb25FeGlzdHMpIGVwaS5lbnRyeVswXS5yZXNvdXJjZS5zZWN0aW9uWzBdLnNlY3Rpb25bMF0uZXh0ZW5zaW9uLnB1c2gobmV3RXh0ZW5zaW9uKTsKICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgIGVwaS5lbnRyeVswXS5yZXNvdXJjZS5zZWN0aW9uWzBdLnNlY3Rpb25bMF0uZXh0ZW5zaW9uLnB1c2gobmV3RXh0ZW5zaW9uKTsKICAgICAgICAgICAgfQogICAgICAgICAgICAvL2VwaS5lbnRyeVswXS5yZXNvdXJjZS5zZWN0aW9uWzBdLnNlY3Rpb25bMF0uZXh0ZW5zaW9uLnB1c2gobmV3RXh0ZW5zaW9uKTsKCiAgICAgICAgfQogICAgfQoKICAgIGNvbnNvbGUubG9nKCJfX19fX19fX19fIFJNTSBMRU5TIEVYRUNVVElPTiBGSU5JU0hFRCBfX19fX19fX19fX19fIikKICAgIHJldHVybiByZXNwb25zZQoKfTsKCmdldE1lZGljaW5hbFByb2R1Y3REZWZpbml0aW9uSWQgPSAoYnVuZGxlKSA9PiB7CiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGJ1bmRsZS5lbnRyeS5sZW5ndGg7IGkrKykgewogICAgICAgIGlmIChidW5kbGUuZW50cnlbaV0ucmVzb3VyY2UucmVzb3VyY2VUeXBlID09PSAiTWVkaWNpbmFsUHJvZHVjdERlZmluaXRpb24iKSB7CiAgICAgICAgICAgIHJldHVybiBidW5kbGUuZW50cnlbaV0ucmVzb3VyY2UuaWQ7CiAgICAgICAgfQogICAgfQogICAgcmV0dXJuIG51bGw7Cn0KCmdldENvZGVBbmREaXNwbGF5ID0gKGF0dGFjaG1lbnQpID0+IHsKICAgIGNvbnNvbGUubG9nKCJGdW5jdGlvbiBnZXRDb2RlQW5kRGlzcGxheSIpCiAgICBjb25zb2xlLmxvZygiQXR0YWNobWVudDogIiwgYXR0YWNobWVudCkKICAgIGlmIChhdHRhY2htZW50LmNvbnRlbnRUeXBlID09PSAidGV4dC9odG1sIikgewogICAgICAgIGlmIChhdHRhY2htZW50LmR1cmF0aW9uKSB7CiAgICAgICAgICAgIGlmIChhdHRhY2htZW50LnVybC5pbmNsdWRlcygieW91dHViZSIpKSB7CiAgICAgICAgICAgICAgICByZXR1cm4gewogICAgICAgICAgICAgICAgICAgIGNvZGU6ICJ2aWRlby1pbmFwcCIsCiAgICAgICAgICAgICAgICAgICAgZGlzcGxheTogIlZJREVPIgogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgcmV0dXJuIHsKICAgICAgICAgICAgICAgICAgICBjb2RlOiAiYXVkaW8taW5hcHAiLAogICAgICAgICAgICAgICAgICAgIGRpc3BsYXk6ICJBVURJTyIKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQoKICAgICAgICB9IGVsc2UgewogICAgICAgICAgICByZXR1cm4gewogICAgICAgICAgICAgICAgY29kZTogImltYWdlLWluYXBwIiwKICAgICAgICAgICAgICAgIGRpc3BsYXk6ICJJTUciCiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICB9IGVsc2UgewogICAgICAgIHN3aXRjaCAoYXR0YWNobWVudC5jb250ZW50VHlwZSkgewogICAgICAgICAgICBjYXNlICJ2aWRlby9tcDQiOgogICAgICAgICAgICAgICAgcmV0dXJuIHsKICAgICAgICAgICAgICAgICAgICBjb2RlOiAidmlkZW8iLAogICAgICAgICAgICAgICAgICAgIGRpc3BsYXk6ICJWSURFTyIKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgY2FzZSAiYXBwbGljYXRpb24vcGRmIjoKICAgICAgICAgICAgICAgIHJldHVybiB7CiAgICAgICAgICAgICAgICAgICAgY29kZTogInBkZiIsCiAgICAgICAgICAgICAgICAgICAgZGlzcGxheTogIlBERiIKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgY2FzZSAiYXVkaW8vbXBlZyI6CiAgICAgICAgICAgICAgICByZXR1cm4gewogICAgICAgICAgICAgICAgICAgIGNvZGU6ICJhdWRpbyIsCiAgICAgICAgICAgICAgICAgICAgZGlzcGxheTogIkFVRElPIgogICAgICAgICAgICAgICAgfQogICAgICAgICAgICBjYXNlICJpbWFnZS9qcGciOgogICAgICAgICAgICAgICAgcmV0dXJuIHsKICAgICAgICAgICAgICAgICAgICBjb2RlOiAiaW1hZ2UiLAogICAgICAgICAgICAgICAgICAgIGRpc3BsYXk6ICJJTUciCiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIGNhc2UgImltYWdlL2pwZWciOgogICAgICAgICAgICAgICAgcmV0dXJuIHsKICAgICAgICAgICAgICAgICAgICBjb2RlOiAiaW1hZ2UiLAogICAgICAgICAgICAgICAgICAgIGRpc3BsYXk6ICJJTUciCiAgICAgICAgICAgICAgICB9CiAgICAgICAgfQogICAgfQp9CgpmdW5jdGlvbiBkZWVwRXF1YWwob2JqZWN0MSwgb2JqZWN0MikgewogICAgY29uc3Qga2V5czEgPSBPYmplY3Qua2V5cyhvYmplY3QxKTsKICAgIGNvbnN0IGtleXMyID0gT2JqZWN0LmtleXMob2JqZWN0Mik7CiAgCiAgICBpZiAoa2V5czEubGVuZ3RoICE9PSBrZXlzMi5sZW5ndGgpIHsKICAgICAgcmV0dXJuIGZhbHNlOwogICAgfQogIAogICAgZm9yIChjb25zdCBrZXkgb2Yga2V5czEpIHsKICAgICAgY29uc3QgdmFsMSA9IG9iamVjdDFba2V5XTsKICAgICAgY29uc3QgdmFsMiA9IG9iamVjdDJba2V5XTsKICAgICAgY29uc3QgYXJlT2JqZWN0cyA9IGlzT2JqZWN0KHZhbDEpICYmIGlzT2JqZWN0KHZhbDIpOwogICAgICBpZiAoCiAgICAgICAgYXJlT2JqZWN0cyAmJiAhZGVlcEVxdWFsKHZhbDEsIHZhbDIpIHx8CiAgICAgICAgIWFyZU9iamVjdHMgJiYgdmFsMSAhPT0gdmFsMgogICAgICApIHsKICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgIH0KICAgIH0KICAKICAgIHJldHVybiB0cnVlOwogIH0KICAKICBmdW5jdGlvbiBpc09iamVjdChvYmplY3QpIHsKICAgIHJldHVybiBvYmplY3QgIT0gbnVsbCAmJiB0eXBlb2Ygb2JqZWN0ID09PSAnb2JqZWN0JzsKICB9CgpyZXR1cm4gewogICAgZW5oYW5jZTogZW5oYW5jZSwKICAgIGdldFNwZWNpZmljYXRpb246IGdldFNwZWNpZmljYXRpb24sCn07"^^xsd:base64Binary ]
  ] ) . #