Update snomed display names xquery
For updating displayName attributes of terminologyAssociations, valueSet concepts and template vocabulary items with the latest available description of a particular type from SNOMED CT (or country extension). This is useful because SNOMED CT updates in a different pace from projects and especially translations could occur after initial project setup. Operates on 1 project at a time.
Prerequisite: have SNOMED CT data installed at your site
Note: once applied to your project, there is no undo unless you keep a copy of the project as backup.
This xquery will perform the following actions:
- Based on all elements with @code, @codeSystem = SNOMED CT, and @displayName pick the currently available fsn from the requested refset
$refsetlanguage
, and the US English fallback fsn - If applying the
$update
is requested apply update, and leave a version statement in the project part - Return a report of what was done
To run the xquery below on the server:
- Open a webbrowser, surf to: http://<server>:8877
- Click on ‘dashboard’.
- Log in as ‘admin’.
- Open eXide.
- Click: ‘New XQuery’ (paste the xquery in the box below to the browserscreen)
- Click: ‘eval’ to run the xquery.
import module namespace get = "http://art-decor.org/ns/art-decor-settings" at "/db/apps/art/modules/art-decor-settings.xqm";
import module namespace art = "http://art-decor.org/ns/art" at "/db/apps/art/modules/art-decor.xqm";
import module namespace snomed = "http://art-decor.org/ns/terminology/snomed" at "/db/apps/terminology/snomed/api/api-snomed.xqm";
declare variable $codeSystemSNOMED := '2.16.840.1.113883.6.96';
(:31000146106 - Nederlandse taalreferentieset (foundation metadata concept):)
declare variable $refsetlanguage := '31000146106';
(:900000000000509007 - United States of America English language reference set:)
declare variable $refsetlanguage-us := '900000000000509007';
declare function local:getDisplayNameAndStatus($code as xs:string, $codeSystem as xs:string, $defaultLanguage as xs:string) as element()* {
if ($codeSystem = $codeSystemSNOMED) then
(:let $service-uri := concat($artDeepLinkTerminology,'snomed/getConcept/',encode-for-uri($code))
let $server-response := httpclient:get(xs:anyURI($service-uri),false(),$requestHeaders)
let $concept := $server-response/httpclient:body//concept[@conceptId = $code]:)
let $concept := $snomed:colDataBase//@conceptId[. = $code]/parent::concept
let $displayNames := $concept/desc[@active]
let $fsn := $concept/desc[@type = 'fsn'][@active][@languageRefsetId = $refsetlanguage-us]
let $langfsn := ($concept/desc[@type = 'fsn'][@active][@languageRefsetId = $refsetlanguage], $concept/desc[@type = 'pref'][@active][@languageRefsetId = $refsetlanguage])[1]
let $statusCode := if ($concept[@active]) then 'active' else if ($concept) then 'deprecated' else ('')
let $statusText := $statusCode
return
<concept code="{$code}" codeSystem="{$codeSystem}" displayName="{$fsn}" statusCode="{$statusCode}" statusText="{$statusText}">
{
if (empty($langfsn)) then () else attribute langfsn {$langfsn}
}
</concept>
else ()
};
declare function local:getReturnLines($terms as element()*, $namemap as item()) as element()* {
for $term in $terms[not(ancestor::valueSet)]
let $replacementTerm := map:get($namemap, $term/@code)/@langfsn
return
element {name($term)} {
$term/@*,
if (empty($replacementTerm)) then () else attribute replaceBy {$replacementTerm},
art:getConcept($term/@conceptId, $term/@conceptFlexibility)
}
,
for $termsByVS in $terms[ancestor::valueSet]
let $vsid := $termsByVS/ancestor::valueSet/@id
let $vsed := $termsByVS/ancestor::valueSet/@effectiveDate
group by $vsid, $vsed
return
<valueSet>
{
$termsByVS/ancestor::valueSet/@*,
for $term in $termsByVS
let $replacementTerm := map:get($namemap, $term/@code)/@langfsn
return
element {name($term)} {
$term/@*,
if (empty($replacementTerm)) then () else attribute replaceBy {$replacementTerm},
$term/node()
}
}
</valueSet>
};
declare function local:getReleaseNote($snomedConcepts as element()*, $resultConcepts as element()*) as element() {
if ($refsetlanguage = '31000146106') then
<version date="{substring(string(current-dateTime()), 1, 19)}" by="{get:strCurrentUserName()}">
<desc language="nl-NL">SNOMED CT concept weergavenamen bijgewerkt met Nederlandse termen voor zover beschikbaar. Totaal: {count($resultConcepts[self::terminologyAssociation] | $resultConcepts[self::valueSet]/(concept | exception | include))}
<ul>
<li>Terminologiekoppelingen: {count($resultConcepts[self::terminologyAssociation])}</li>
<li>Waardelijstconcepten {count($resultConcepts[self::valueSet]/(concept | exception | include))} in {count($resultConcepts[self::valueSet])} waardelijsten</li>
{
let $others := $resultConcepts[not(self::valueSet | self::terminologyAssociation)]
return
if (empty($others)) then () else <li>Anders: {count($others)}</li>
}
</ul>
</desc>
</version>
else (
<version date="{substring(string(current-dateTime()), 1, 19)}" by="{get:strCurrentUserName()}">
<desc language="nl-NL">SNOMED CT concept display names updated with currently available description. Total: {count($resultConcepts[self::terminologyAssociation] | $resultConcepts[self::valueSet]/(concept | exception | include))}
<ul>
<li>Terminology associations: {count($resultConcepts[self::terminologyAssociation])}</li>
<li>Vaslue set concepts {count($resultConcepts[self::valueSet]/(concept | exception | include))} in {count($resultConcepts[self::valueSet])} value sets</li>
{
let $others := $resultConcepts[not(self::valueSet | self::terminologyAssociation)]
return
if (empty($others)) then () else <li>Other: {count($others)}</li>
}
</ul>
</desc>
</version>
)
};
let $projectPrefix := if (request:exists()) then request:get-parameter('prefix', ()) else 'demo1-'
let $update := if (request:exists()) then request:get-parameter('update', 'false') = 'true' else false()
let $decor := if (empty($projectPrefix)) then () else collection('/db/apps/decor/data')/decor[project/@prefix = $projectPrefix]
let $snomedConcepts := if (empty($projectPrefix)) then () else collection('/db/apps/decor/data')/decor[project/@prefix = $projectPrefix]//*[@code][@displayName][@codeSystem = $codeSystemSNOMED][not(ancestor::template)]
let $namemap := map:new(
for $term in $snomedConcepts
let $conceptId := $term/@code
group by $conceptId
return
map:entry($conceptId, local:getDisplayNameAndStatus($conceptId, $term[1]/@codeSystem, 'nl-NL'))
)
let $resultConcepts := if (empty($snomedConcepts)) then () else local:getReturnLines($snomedConcepts, $namemap)
let $versionOrRelease := if (empty($snomedConcepts)) then () else local:getReleaseNote($snomedConcepts, $resultConcepts)
let $updateLines :=
if ($update) then
for $term in $snomedConcepts[@displayName]
let $replacementTerm := map:get($namemap, $term/@code)/@langfsn
return
if (empty($replacementTerm)) then () else
if ($term[@displayName = $replacementTerm]) then () else (
update value $term/@displayName with $replacementTerm
)
else ()
let $updateVersion :=
if ($update) then
if (empty($versionOrRelease)) then ( (: don't have anything to write:) ) else
if (empty($decor)) then ( (: don't have a project to write into :) ) else
if ($decor/project[version | release]) then
update insert $versionOrRelease preceding $decor/project/(release | version)[1]
else (
update insert $versionOrRelease into $decor/project
)
else ()
return (
<project prefix="{$projectPrefix}" update="{$update}">
{$versionOrRelease}
<x>{$resultConcepts}</x>
</project>
)