Stored Functions

Content-Type: text/xml
URN: urn:dhis2.org:csd:stored-function:aggregate_hw_export

Description



 
    Returns DHIS2 DXF quaterly report of number of health workers by facility 
    
    Reuqest parameters:
      assigningAuthorityName: the assignining authority name for the csd:facility/csd:otherID in which the DHIS code is stored
  

Definition

Source:
declare namespace csd = "urn:ihe:iti:csd:2013";
declare variable $careServicesRequest as item() external;

let $facilities := /csd:CSD/csd:facilityDirectory/csd:facility
let $active_providers := /csd:CSD/csd:providerDirectory/csd:provider[./csd:record/@status = "106-001"]

let $year := year-from-date(current-date())
let $month := month-from-date(current-date())
let $quarter := 
  if ($month < 4) then "1"
  else if ($month < 7) then "2"
  else if ($month < 10) then "3"
  else "4"
let $period := concat($year , 'Q',$quarter)

return 
  <dxf xmlns="http://dhis2.org/schema/dxf/2.0"> 
    <dataValueSet>
      {
	for $fac in $facilities
	let $fac_id := upper-case(string($fac/@entityID))
	let $facurn := substring($fac_id,10)
	let $fac_providers := $active_providers[./csd:facilities/csd:facility[upper-case(./@entityID)=$fac_id]]
	let $count := count($fac_providers)
	where $facurn  and $count > 0   
	return <dataValue period="{$period}" orgUnit="{$facurn}" dataElement="numProviders" value="{$count}" />
      }
    </dataValueSet>
  </dxf>
Content-Type: text/xml
URN: urn:dhis2.org:csd:stored-function:csd2dxf

Description



 
    Returns DHIS2 DXF Metadata representation of CSD facilties and organizations for import into a DHIS2 instance 
  

Definition

Source:
import module namespace dxf2csd = "http://dhis2.org/csd/dxf/2.0";
import module namespace csd_webconf =  "https://github.com/openhie/openinfoman/csd_webconf";
import module namespace csd_dm = "https://github.com/openhie/openinfoman/csd_dm";
import module namespace svs_lsvs = "https://github.com/openhie/openinfoman/svs_lsvs";

declare namespace svs = "urn:ihe:iti:svs:2008";
declare namespace csd = "urn:ihe:iti:csd:2013";
declare namespace dxf = "http://dhis2.org/csd/dxf/2.0";

declare variable $careServicesRequest as item() external; 

let $doc_name := string($careServicesRequest/@resource)
let $doc := csd_dm:open_document($doc_name)

let $facilities := $doc/csd:CSD/csd:facilityDirectory/csd:facility
let $svcs := $doc/csd:CSD/csd:serviceDirectory/csd:service
let $orgs := $doc/csd:CSD/csd:organizationDirectory/csd:organization


let $fac_type_ids := ("1.3.6.1.4.1.21367.200.103")

let $org_unit_groups :=   
  for $fac_type_id in $fac_type_ids	  
  let $fac_types :=  svs_lsvs:get_single_version_value_set(string($fac_type_id) )	  
  return
    for $concept in $fac_types//svs:Concept
    let $code := string($concept/@code)
    let $scheme := string($concept/@codeSystem)
    let $name := string($concept/@displayName)
    return <dxf:organisationUnitGroup code="{$code}" name="{$name}" codeSystem="{$scheme}"/>

return 
    <dxf:metaData>
      <dxf:organisationUnits>
        {
	  for $org in dxf2csd:ensure_properly_ordered_orgs($orgs)
	  return dxf2csd:make_org_from_org($doc,$org) 
	}
        {
	  for $fac in $facilities
	  return dxf2csd:make_org_from_fac($doc,$fac) 
	}
      </dxf:organisationUnits>


      <dxf:organisationUnitGroups>
        { 
	  for $org_unit_group in $org_unit_groups
	  let $code := string($org_unit_group/@code)
	  let $scheme := string($org_unit_group/@codeSystem)
	  let $name := string($org_unit_group/@name)
	  let $short_name := substring(string($org_unit_group/@name),1,50)
	    return 
	    <dxf:organisationUnitGroup code="{$code}" name="{$name}" shortName="{$short_name}">
	      <dxf:organisationUnits>
		{
		  for $fac in $facilities[./csd:codedType[@codingScheme = $scheme and @code = $code]]
		  let $uuid := dxf2csd:extract_uuid_from_entityid($fac/@entityID)
		  let $fac_name := $fac/csd:primaryName/text()
		  let $id := string($fac/@entityID)
		  return     
		     <dxf:organisationUnit uuid="{$uuid}" id="{$id}" name="{$fac_name}" />
		}
	      </dxf:organisationUnits>
	    </dxf:organisationUnitGroup>
	}
      </dxf:organisationUnitGroups>

      { 
      if (count($org_unit_groups) > 0)
      then
        <dxf:organisationUnitGroupSets>
	  <dxf:organisationUnitGroupSet name='Facility Type'>
	    <dxf:description>Facility Type</dxf:description>
	    <dxf:compulsory>true</dxf:compulsory>
	    <dxf:dataDimension>true</dxf:dataDimension>
	    <dxf:organisationUnitGroups>
	      {
		for $org_unit_group in $org_unit_groups
		let $code := string($org_unit_group/@code)
		let $scheme := string($org_unit_group/@codeSystem)
		let $name := string($org_unit_group/@name)
		return   <dxf:organisationUnitGroup code="{$code}" name="{$name}" />
	      }
	    </dxf:organisationUnitGroups>
	  </dxf:organisationUnitGroupSet>	
	</dxf:organisationUnitGroupSets>
      else () 
      }

    </dxf:metaData>
Content-Type: application/zip
URN: urn:dhis.org:transform_to_dxf:v2.19

Description



 
    Returns DHIS2 DXF Metadata representation of CSD providers, facilties and organizations for import into a DHIS2 instance 
    
    Request parameters are:
    
      
	csd:organization
	0..1 csd:organization element with @entityID attribute.  If present, will generate only the organisation unit hierarchy
	underneath the specified organization. Will also include all the parent organization units.  
      
      
	processUsers
	0..1 processUsers  element has integer attribute @value.  Defaults to 1 which means we process provides as DHIS2 users.
      
      
	preserveUUIDs
	0..1 processUUIDs  element has integer attribute @value.  Defaults to 1 which means we preserve DHIS2 UUIDs, if present, when creating the DXF metadata for import.
      
    
  

Definition

Source:
import module namespace dxf2csd = "http://dhis2.org/csd/dxf/2.0";
import module namespace csd_webconf =  "https://github.com/openhie/openinfoman/csd_webconf";
import module namespace csd_dm = "https://github.com/openhie/openinfoman/csd_dm";
import module namespace svs_lsvs = "https://github.com/openhie/openinfoman/svs_lsvs";
import module namespace util = "https://github.com/openhie/openinfoman-dhis/util";
import module namespace functx = "http://www.functx.com";
import module namespace archive = "http://basex.org/modules/archive";

declare namespace svs = "urn:ihe:iti:svs:2008";
declare namespace csd = "urn:ihe:iti:csd:2013";
declare namespace dxf = "http://dhis2.org/schema/dxf/2.0";

declare variable $careServicesRequest as item() external; 

let $doc_name := string($careServicesRequest/@resource)
let $processUsers := 
  if (exists($careServicesRequest/processUsers/@value))
  then ($careServicesRequest/processUsers/@value = 1)
  else true()
let $preserveUUIDs := 
  if (exists($careServicesRequest/preserveUUIDs/@value))
  then ($careServicesRequest/preserveUUIDs/@value = 1)
  else true()

let $onlyDirectChildren := 
  if (exists($careServicesRequest/onlyDirectChildren/@value))
  then ($careServicesRequest/onlyDirectChildren/@value = 1)
  else true()

let $zip := 
  if (exists($careServicesRequest/zip/@value))
  then ($careServicesRequest/zip/@value = 1)
  else true()
let $req_org_id :=    $careServicesRequest/csd:organization/@entityID 
let $req_ou_group_schemes:= distinct-values($careServicesRequest/orgUnitGroupSchemes/orgUnitGroupScheme/text())


let $t0 :=
  (
    trace($processUsers,'Process users: '),
    trace($preserveUUIDs,'Preserve UUIDs: '),
    trace($onlyDirectChildren,'Only Direct Children: '),
    trace($zip,'Zip: '),
    trace($req_org_id,'Requested Org EntityID: '),
    trace($req_ou_group_schemes,'Request Org Group Schemes: ')
  )

let $doc := csd_dm:open_document($doc_name)
  (:the organziation we want to import to:)



let $svcs := $doc/csd:CSD/csd:serviceDirectory/csd:service

let $orgs := 
  if (functx:all-whitespace($req_org_id))
  then dxf2csd:ensure_properly_ordered_orgs($doc/csd:CSD/csd:organizationDirectory/csd:organization)
  else 
    let $all_orgs := $doc/csd:CSD/csd:organizationDirectory/csd:organization
    let $org := $all_orgs[@entityID = $req_org_id]
    return 
      if (not(exists($org)))
      then ()
      else
	if ($onlyDirectChildren)
	then (util:get_parent_orgs($all_orgs,$org),$org,$all_orgs[./csd:parent[@entityID = $req_org_id]])
	else (util:get_parent_orgs($all_orgs,$org),$org,util:get_child_orgs($all_orgs,$org))  (: this comes back properly ordered for DHIS2 import :)


let $facilities := 
  if (functx:all-whitespace($req_org_id))
  then $doc/csd:CSD/csd:facilityDirectory/csd:facility
  else  $doc/csd:CSD/csd:facilityDirectory/csd:facility[./csd:organizations/csd:organization = $orgs]

let $provs := 
  if ($processUsers)
  then $doc/csd:CSD/csd:providerDirectory/csd:provider
  else ()



let $ou_oids := 
  for $dhis_url in distinct-values(($orgs/csd:record/@sourceDirectory,$facilities/csd:record/@sourceDirectory))
  let $namespace_uuid := util:uuid_generate($dhis_url,$util:namespace_uuid)
  let $oid := concat('2.25.',util:hexdec(util:uuid_generate('rootoid',$namespace_uuid)))	
  return $oid

    
let $dxf := 
    <dxf:metaData>
      <dxf:users>
      {
	for $prov in $provs

	let $dhis_url := string(($prov/csd:record/@sourceDirectory)[1])
	let $dhis_id :=  ($prov/csd:otherID[@assigningAuthorityName=concat($dhis_url,"/api/users") and @code="id"])[1]/text()	  
	let $namespace_uuid := util:uuid_generate($dhis_url,$util:namespace_uuid)
	let $oid := concat('2.25.',util:hexdec(util:uuid_generate('rootoid',$namespace_uuid)))	

	let $name := ($prov/csd:demographic/csd:name/csd:commonName)[1]/text()
	let $surname := ($prov/csd:demographic/csd:name/csd:surname)[1]/text()
	let $firstname := ($prov/csd:demographic/csd:name/csd:forename)[1]/text()
	let $username := dxf2csd:extract_uuid_from_entityid(string($prov/@entityID))
	let $phone := ($prov/csd:contactPoint/csd:codedType[@code="BP" and @codingScheme="urn:ihe:iti:csd:2013:contactPoint"])[1]/text()
	let $email := ($prov/csd:contactPoint/csd:codedType[@code="EMAIL" and @codingScheme="urn:ihe:iti:csd:2013:contactPoint"])[1]/text()
	let $ag_oid := concat($oid,'.4')
	let $ur_oid := concat($oid,'.1')
	let $urs := 
	   for $o_id in $prov/csd:codedType[@codingScheme = $ur_oid]
	   return <dxf:userRole id="{string($o_id/@code)}"/>
	let $uags := 
	   for $o_id in $prov/csd:codedType[@codingScheme = $ag_oid]
	   return <dxf:userAuthorityGroup id="{string($o_id/@code)}"/>
	let $p_orgs := 
	  for $org in $prov/csd:organizations/csd:organization
	  let $ou_uuid := 
	    if ($preserveUUIDs) 
	    then ($facilities[@entityID = $org/@entityID]/csd:otherID[@assigningAuthorityName = concat($dhis_url,"/api/organisationUnits") and @code="uuid"])[1]/text()
	    else ()
	  return 
	    if (functx:all-whitespace($ou_uuid)) 
	    then () 
	    else  <dxf:organisationUnit uuid="{$ou_uuid}"/>

	      
	return
	  <dxf:user name="{$name}" >
	    {if (functx:all-whitespace($dhis_id)) then () else  @id}
	    <dxf:surname>{$surname}</dxf:surname>
	    <dxf:firstName>{$firstname}</dxf:firstName>
	    {if (functx:all-whitespace($email)) then () else <dxf:email>{$email}</dxf:email>}
	    {if (functx:all-whitespace($phone)) then () else <dxf:phoneNumber>{$email}</dxf:phoneNumber>}
	    <dxf:userCredenitals>
	      <dxf:username>{$username}</dxf:username> 
	      <dxf:userRoles>{$urs}</dxf:userRoles>
	      <dxf:userAuthorityGroups>{$uags}</dxf:userAuthorityGroups>
	    </dxf:userCredenitals>
	    <dxf:organisationUnits>
	      {$p_orgs}
	    </dxf:organisationUnits>
	  </dxf:user>
        }
      </dxf:users>

      <dxf:userRoles>
	{
	  let $oids := 
	    for $dhis_url in distinct-values($provs/csd:record/@sourceDirectory)
	    let $namespace_uuid := util:uuid_generate($dhis_url,$util:namespace_uuid)
	    let $oid := concat('2.25.',util:hexdec(util:uuid_generate('rootoid',$namespace_uuid)))	
	    return $oid
	  
	  return 
	  for $oid in $oids
            let $ur_oid := concat($oid,'.1')
	    let $svs := svs_lsvs:get_single_version_value_set($ur_oid)
	    return
	      if (not(exists($svs)))
	      then ()
              else 
		for $val in $svs//svs:concept
		return 
		  <dxf:userRole name="{$val/@displayName}" id="{$val/@code}">
		    <dxf:description>{string($val/@displayName)}</dxf:description>
		  </dxf:userRole>
	}
      </dxf:userRoles>
      <dxf:userAuthorityGroups>
	{
	  let $oids := 
	    for $dhis_url in distinct-values($provs/csd:record/@sourceDirectory)
	    let $namespace_uuid := util:uuid_generate($dhis_url,$util:namespace_uuid)
	    let $oid := concat('2.25.',util:hexdec(util:uuid_generate('rootoid',$namespace_uuid)))	
	    return $oid
	  
	  return 
	  for $oid in $oids
            let $ag_oid := concat($oid,'.4')
	    let $svs := svs_lsvs:get_single_version_value_set($ag_oid)
	    return
	      if (not(exists($svs)))
	      then ()
              else 
		for $val in $svs//svs:concept
		return 
		  <dxf:userAuthorityGroup name="{$val/@displayName}" id="{$val/@code}">
		    <dxf:description>{string($val/@displayName)}</dxf:description>
		  </dxf:userAuthorityGroup>
	}
      </dxf:userAuthorityGroups>





      <dxf:organisationUnits>
        {	 
	  let $processOrgUnit := function($org) {
	    let $dhis_url := string($org/csd:record/@sourceDirectory)
	    let $dhis_uuid :=
	      if ($preserveUUIDs) 
	      then ($org/csd:otherID[@assigningAuthorityName=concat($dhis_url,"/api/organisationUnits") and @code="uuid"])[1]/text()
	      else ()
	    let $dhis_code := ($org/csd:otherID[@assigningAuthorityName=concat($dhis_url,"/api/organisationUnits") and @code="code"])[1]/text()
	   
	    let $level_code := string(($org/csd:codedType[@codingScheme=concat("urn:" ,$dhis_url,"/api/organisationUnitLevels")])[1]/@code)
	    let $level := 
	      if (not(functx:all-whitespace($level_code)))
	      then $level_code
	      else dxf2csd:get_level($doc,$org)

	    let $name := $org/csd:primaryName/text()

	    let $uuid :=
	      if ($preserveUUIDs)
	      then 
	        if (not(functx:all-whitespace($dhis_uuid)))
		then $dhis_uuid
	        else ()
	      else ()

	    let $entity_uuid := 
	      if (functx:all-whitespace($dhis_uuid))
	      then dxf2csd:extract_uuid_from_entityid(string($org/@entityID))
	      else string($dhis_uuid)


	    let $dhis_code := ($org/csd:otherID[@assigningAuthorityName=concat($dhis_url,"/api/organisationUnits") and @code="code"])[1]/text()

	    let $id_code := ($org/csd:otherID[@assigningAuthorityName=concat($dhis_url,"/api/organisationUnits") and @code="id"])[1]/text()
	    let $id :=
	      if (not(functx:all-whitespace($id_code)))
	      then $id_code
	      else dxf2csd:extract_id_from_entityid(string($org/@entityID)) 

	    let $created := dxf2csd:fixup_date($org/csd:record/@created)
	    let $lm := dxf2csd:fixup_date($org/csd:record/@updated)

	    let $porg_id := $org/csd:parent/@entityID
	    let $porg := $orgs[@entityID = $porg_id]
	    let $porg_dhis_uuid := ($porg/csd:otherID[@assigningAuthorityName=concat($dhis_url,"/api/organisationUnits") and @code="uuid"])[1]
	    let $parent :=
	      if (functx:all-whitespace($porg_id))
	      then () (: no parent :)
	      else if (not(functx:all-whitespace($porg_dhis_uuid)))
	      then <dxf:parent uuid="{$porg_dhis_uuid}"/>
  	      else <dxf:parent id="{dxf2csd:extract_id_from_entityid(string($porg_id))}"/>
	    let $avs :=
	      <dxf:attributeValues>
	        <dxf:attributeValue>
	  	  <dxf:attribute name="entityID"/>
		  <dxf:value>{$entity_uuid}</dxf:value>
	        </dxf:attributeValue>
	      </dxf:attributeValues>
		    
	    return 
	      <dxf:organisationUnit 
                level="{$level}"
		name="{$name}"
		shortName="{substring($name,1,50)}"
		id="{$id}"
		lastUpdated="{$lm}"
		created="{$created}"
		>
		{
		  if (($preserveUUIDs) and (not(functx:all-whitespace($uuid))))
		  then attribute uuid {$uuid}
		  else ()
	        }
		{ 
	          if (functx:all-whitespace($dhis_code))
		  then ()
	          else attribute code {$dhis_code}
		}
		{$parent}
		{$avs}
		<dxf:openingDate>1970-01-01</dxf:openingDate> 
	      </dxf:organisationUnit>
	  }	  

	  let $orgunit_funcs :=     
  	    for $orgUnit in $orgs
	    return function() {$processOrgUnit($orgUnit)}

	  return async:fork-join($orgunit_funcs)

	}
        {
	  let $processFac := function($fac) {
	    let $dhis_url := string($fac/csd:record/@sourceDirectory)
	    let $dhis_uuid := ($fac/csd:otherID[@assigningAuthorityName=concat($dhis_url,"/api/organisationUnits") and @code="uuid"])[1]
	    let $dhis_id := ($fac/csd:otherID[@assigningAuthorityName=concat($dhis_url,"/api/organisationUnits") and @code="id"])[1]
            let $dhis_code := ($fac/csd:otherID[@assigningAuthorityName=concat($dhis_url,"/api/organisationUnits") and @code="code"])[1]/text()
	    return 
  	      let $level := dxf2csd:get_level($doc,$fac)
	      let $name := $fac/csd:primaryName/text()
	      let $uuid := 
	        if (functx:all-whitespace($dhis_uuid))
	        then dxf2csd:extract_uuid_from_entityid(string($fac/@entityID))
	        else string($dhis_uuid)
              let $id := 
	        if (functx:all-whitespace($dhis_id))
	        then dxf2csd:extract_id_from_entityid(string($fac/@entityID)) 
	        else string($dhis_id)
	      let $created := dxf2csd:fixup_date($fac/csd:record/@created)
	      let $lm := dxf2csd:fixup_date($fac/csd:record/@updated)

	      (: in CSD we can have multiple "parents" but not so DXF.  We just choose the first one    :)
	      let $org_id := ($orgs[@entityID = ($fac/csd:organizations/csd:organization)[1]/@entityID ])[1]
	      let $org := $orgs[@entity_id = $org_id]
	      let $org_dhis_uuid := ($org/csd:otherID[@assigningAuthorityName=concat($dhis_url,"/api/organisationUnits") and @code="uuid"])[1]
	      let $parent := 
	        if (functx:all-whitespace($org_id))
	        then ()  (: no parent :)
	        else if (not(functx:all-whitespace($org_dhis_uuid)))
	          then <dxf:parent id="{$org_dhis_uuid}"/>
	          else <dxf:parent id="{dxf2csd:extract_id_from_entityid(string($org_id))}"/>
	      let $avs :=
	        <dxf:attributeValues>
  		  <dxf:attributeValue>  
		    <dxf:attribute name="entityID"/>
		    <dxf:value>{$uuid}</dxf:value>
		  </dxf:attributeValue>
	        </dxf:attributeValues>
	
	      return 
	        <dxf:organisationUnit 
                  level="{$level}"
		  name="{$name}"
		  shortName="{substring($name,1,50)}"
		  lastUpdated="{$lm}"
		  created="{$created}"
		  >
		  {
		    if (not(functx:all-whitespace($uuid)))
		    then attribute uuid {$uuid}
		    else ()
	          }
		  {
		    if (not(functx:all-whitespace($id)))
		    then attribute id {$id}
		    else ()
	          }
		  { 
		   if (functx:all-whitespace($dhis_code))
		   then ()
		   else attribute code {$dhis_code}
		  }
		 {$parent}
		 {$avs}
		 <dxf:openingDate>1970-01-01</dxf:openingDate> 
	       </dxf:organisationUnit>
	  }

	  let $fac_funcs :=     
  	    for $fac in $facilities
	    let $dhis_url := string($fac/csd:record/@sourceDirectory)
	    let $dhis_uuid := ($fac/csd:otherID[@assigningAuthorityName=concat($dhis_url,"/api/organisationUnits") and @code="uuid"])[1]
	    let $dhis_id := ($fac/csd:otherID[@assigningAuthorityName=concat($dhis_url,"/api/organisationUnits") and @code="id"])[1]
	    let $org := 
	      if (functx:all-whitespace($dhis_uuid))
	      then ()
	      else ($orgs[./csd:otherID[@assigningAuthorityName=concat($dhis_url,"/api/organisationUnits") and @code="uuid" and ./text() = $dhis_uuid]])[1]
	    where not(exists($org)) 	    (: remove the facilities that have already been created from a DHIS2 org unit:)

	    return function() {$processFac($fac)}

	  return async:fork-join($fac_funcs)

	}
      </dxf:organisationUnits>


      <dxf:organisationUnitGroups>    
        {
	  
	  let $ou_group_schemes := distinct-values((
	    $req_ou_group_schemes,
	    for $oid in $ou_oids return  concat($oid,'.3')
	      ))
	    
	  for $ou_group_scheme in $ou_group_schemes
	  let $types :=  svs_lsvs:get_single_version_value_set(string($ou_group_scheme) )	  

	  let $org_unit_groups :=   
  	    for $concept in $types//svs:Concept
	    let $code := string($concept/@code)
	    let $scheme := string($concept/@codeSystem)
	    let $name := string($concept/@displayName)
	    return <dxf:organisationUnitGroup code="{$code}" name="{$name}" />

	  for $org_unit_group in $org_unit_groups
	  let $code := string($org_unit_group/@code)
	  let $scheme := string($org_unit_group/@codeSystem)
	  let $name := string($org_unit_group/@name)
	  let $short_name := substring(string($org_unit_group/@name),1,50)
	    return 
	    <dxf:organisationUnitGroup code="{$code}" name="{$name}" shortName="{$short_name}">
	      <dxf:organisationUnits>
		{
		  for $ent in ($facilities,$orgs)[./csd:codedType[@codingScheme = $scheme and @code = $code]]
		  let $uuid := dxf2csd:extract_uuid_from_entityid($ent/@entityID)
		  let $ent_name := $ent/csd:primaryName/text()
		  let $id := dxf2csd:extract_id_from_entityid(string($ent/@entityID)) 
		  return     
		     <dxf:organisationUnit uuid="{$uuid}" id="{$id}" name="{$ent_name}" />
		}
	      </dxf:organisationUnits>
	    </dxf:organisationUnitGroup>
	}
      </dxf:organisationUnitGroups>


      <dxf:organisationUnitLevels>
	{
	  
	  for $oid in $ou_oids
            let $level_oid := concat($oid,'.2')
	    let $svs := svs_lsvs:get_single_version_value_set($level_oid)
	    return
	      if (not(exists($svs)))
	      then ()
              else 
		for $val in $svs//svs:concept
		return 
		  <dxf:organisationUnitLevel name="{$val/@displayName}" id="{$val/@code}"/>

	}
       
      </dxf:organisationUnitLevels>

    </dxf:metaData>


let $out := 
  if ($zip)
  then archive:create(   <archive:entry>csd_dxf.xml</archive:entry>, serialize($dxf))
  else $dxf

return $out
Content-Type: text/xml
URN: urn:dhis2.org:csd:stored-function:dxf2csd

Description



 
    Updates the CSD document with a transform of the DHIS2 DXF.  
  

Definition

Source:
import module namespace dxf2csd = "http://dhis2.org/csd/dxf/2.0";
import module namespace csd_webconf =  "https://github.com/openhie/openinfoman/csd_webconf";
import module namespace csd_dm = "https://github.com/openhie/openinfoman/csd_dm";


declare variable $careServicesRequest as item() external;


let $csd := dxf2csd:extract-directory($careServicesRequest/dxf,$careServicesRequest/oid)
let $doc_name := string($careServicesRequest/@resource)
let $doc := csd_dm:open_document($doc_name)
return  csd_dm:add($csd,$doc_name)

Content-Type: text/xml
URN: urn:dhis2.org:csd:stored-function:dxf2svs

Description



 
    Update SVS lists from a DHIS2 MetaData Export
  

Definition

Source:
import module namespace dxf2csd = "http://dhis2.org/csd/dxf/2.0";
import module namespace csd_webconf =  "https://github.com/openhie/openinfoman/csd_webconf";
import module namespace csd_dm = "https://github.com/openhie/openinfoman/csd_dm";
import module namespace svs_lsvs = "https://github.com/openhie/openinfoman/svs_lsvs";

declare namespace dxf = "http://dhis2.org/schema/dxf/2.0";
declare namespace svs = "urn:ihe:iti:svs:2008";

declare variable $careServicesRequest as item() external;



let $version := concat(year-from-date(current-date()),'.',month-from-date(current-date()),'.',day-from-date(current-date()))

return (
  let $list_name := "DHIS2 Organization Unit Levels"
  let $id := dxf2csd:oid_orgtype($careServicesRequest/oid/text())
  let $svs := 
  <svs:ValueSet id="{$id}" version="{$version}" displayName="{$list_name}">
    <svs:ConceptList xml:lang="en-US">
      {
	for $level in $careServicesRequest/dxf/dxf:metaData/dxf:organisationUnitLevels/dxf:organisationUnitLevel
	return   <svs:Concept code="{$level/@level}" displayName="{$level/@name}" codeSystem="{$id}"/>
      }
    </svs:ConceptList>
  </svs:ValueSet>
  return svs_lsvs:insert($svs)
  ,
  let $list_name := "DHIS2 User Role List"
  let $id := dxf2csd:oid_hwtype($careServicesRequest/oid/text())
  let $svs := 
  <svs:ValueSet id="{$id}" version="{$version}" displayName="{$list_name}">
    <svs:ConceptList xml:lang="en-US">
      {
        for $role in $careServicesRequest/dxf/dxf:metaData/dxf:userRoles/dxf:userRole
        return   <svs:Concept code="{$role/@id}" displayName="{$role/@name}" codeSystem="{$id}"/>
      }
    </svs:ConceptList>
  </svs:ValueSet>
  return svs_lsvs:insert($svs)
)

Content-Type: text/xml
URN: urn:dhis.org:extract_from_dxf:v2.19

Description



    
This extracts all organisation units matching the given facility conditions as a CSD facility entity.  
It also extracts all organisation units a CSD organization entity.  
In the case that a CSD facility entity is created, it will have as an organizational association to it's corresponding organization entity.
These two entities will have distinct entity IDs (UUIDs)

This Also creates SVS for relevant terminologies (e.g. Organisation Unit Groups and Levels )

Imports: DHIS2 metadata export of Organsation Units, Organisation Unit Group,  Organisation Unit Group Set, Organization Unit Level from DHIS2 2.19

This optionally processes DHIS2 Users as health workers (CSD Providers).
In order to do so, you will need to have included Users, UserRoles and UserAuthorityGroups in your DXF2 meta-data extract.

    
  

Definition

Source:
declare namespace csd = "urn:ihe:iti:csd:2013"; 

declare namespace svs = "urn:ihe:iti:svs:2008";
declare namespace dxf = "http://dhis2.org/schema/dxf/2.0";
declare namespace adx = "http://www.openhie.org/adx";

import module namespace csd_webconf =  "https://github.com/openhie/openinfoman/csd_webconf";
import module namespace csd_dm = "https://github.com/openhie/openinfoman/csd_dm";
import module namespace svs_lsvs = "https://github.com/openhie/openinfoman/svs_lsvs";
import module namespace functx = "http://www.functx.com";
import module namespace util = "https://github.com/openhie/openinfoman-dhis/util";
import module namespace async = "http://basex.org/modules/async";

declare variable $careServicesRequest as item() external; 



let $dhis_url := replace($careServicesRequest/URL/text(),'/+$','')
let $namespace_uuid := util:uuid_generate($dhis_url,$util:namespace_uuid)

let $dxf := $careServicesRequest/dxf
let $facility_group_codes := $careServicesRequest/groupCodes/groupCode/text()
let $facility_levels := $careServicesRequest/levels/level/text()
let $do_hws :=  ($careServicesRequest/usersAreHealthWorkers/text() = '1')
let $do_srvcs :=  ($careServicesRequest/dataelementsAreServices/text() = '1')

let $t_oid := $careServicesRequest/oid/text()  
let $oid :=      
  if (not(functx:all-whitespace($t_oid)))
  then $t_oid
  else 
    (:generate it from the uuid :)
    concat('2.25.',util:hexdec(util:uuid_generate('rootoid',$namespace_uuid)))

let $orgUnits := $dxf/dxf:metaData/dxf:organisationUnits/dxf:organisationUnit
let $orgGroups := $dxf/dxf:metaData/dxf:organisationUnitGroups/dxf:organisationUnitGroup
let $userRoles := $dxf/dxf:metaData/dxf:userRoles
let $dataSets := $dxf/dxf:metaData/dxf:dataSets
let $dataElements := $dxf/dxf:metaData/dxf:dataElements
let $catCombos := $dxf/dxf:metaData/dxf:categoryCombos
  
let $doc_name := string($careServicesRequest/@resource)
let $doc := csd_dm:open_document($doc_name)
let $org_dir := $doc/csd:CSD/csd:organizationDirectory
let $fac_dir := $doc/csd:CSD/csd:facilityDirectory
let $prov_dir := $doc/csd:CSD/csd:providerDirectory
let $srvc_dir := $doc/csd:CSD/csd:serviceDirectory

let $now := current-dateTime()



(: cache some node calculations :)
let $org_otherids := $org_dir/csd:organization/csd:otherID[@code='id']
let $orggroups_by_ou := $orgGroups/dxf:organisationUnits/dxf:organisationUnit

let $process_orgunit := function($orgUnit) {
  let $level := xs:integer($orgUnit/@level)
  let $id := $orgUnit/@id
  let $uuid := string($orgUnit/@uuid)

  let $displayName:=string($orgUnit/@name)
  let $org_code:=string($orgUnit/@code)
  let $pid:=string($orgUnit/dxf:parent/@id)

  let $lm := util:fixup_date($orgUnit/@lastUpdated)
  let $created := util:fixup_date($orgUnit/@created)
  let $groups := $orggroups_by_ou[@id = $id]/../..  (:clause should expect to match more than one. go to grandparent orgUnitGroup's :)
(:  let $groups := $orgGroups[./dxf:organisationUnits/dxf:organisationUnit[@id = $id]] :)
  let $group_codes := $groups/@code

  (:if there is an existing CSD UUID / entityID in DHIS2 we should keep it to referencer the org unit :)
  let $entity_uuid :=((($orgUnit/dxf:attributeValues/dxf:attributeValue[./dxf:attribute[@name='entityID']])[1])/dxf:value[1])/text()
  let $facEntityID := concat("urn:uuid:",util:uuid_generate(concat('facility:',$id),$namespace_uuid))
  let $orgEntityID :=
    if (not(functx:all-whitespace($entity_uuid)))
    then concat("urn:uuid:",$entity_uuid)
    else if (not(functx:all-whitespace($uuid)))
    then concat("urn:uuid:",$uuid)  
    else  concat("urn:uuid:",util:uuid_generate(concat('organization:',$id),$namespace_uuid))

          
  (:the parent org may be:
     1) in the dxf document being imported (highest precedence)
     2) in the destination csd document
     3) nowhere 

    in the case of 1) we want the parent's csd entity id to match the entity id of the parent org unit being imported
       case 1) happens if $porg is found
    in the case of 2) we want to use the parent id of the 
       in case is if $porg is not found but there is a csd:organization with the correct entity if in the dest. doc
    in the case of 3) we want to put it under our global root element for the import
    :)
    
  let $porg := ($orgUnits[@id=$pid])[1]
  let $parentEntityID :=     
    if (exists($porg))  (: there is a matching parent organization in the imported dxf document :)
    then  
      (:see if there is a DHIS2 attribute for the csd_entity ID :)
      let $p_entity_uuid :=((($porg/dxf:attributeValues/dxf:attributeValue[./dxf:attribute[@name='entityID']])[1])/dxf:value[1])/text()
      let $p_uuid := string($porg/@uuid)
      return
        if (not(functx:all-whitespace($p_entity_uuid))) 
        then concat("urn:uuid:",$p_entity_uuid)
	else if (not(functx:all-whitespace($p_uuid)))
        then concat("urn:uuid:",$p_uuid)
        else concat("urn:uuid:",util:uuid_generate(concat('organization:',$pid),$namespace_uuid))
    else (: we didn't find a matching parent organization in the dxf document, but may already be in target:)
      let $peorg := ($org_otherids[./text() = $pid])[1]/..  (: get the parent csd:organization element :)
(:      let $peorg := ($org_dir/csd:organization[./csd:otherID[@code='id' and ./text() = $pid]])[1] :)
      return
	if (exists($peorg))
        then $peorg/@entityID
        else ()

(:   let $puuid :=
     if (exists($porg))
     then  $porg/@uuid
     else if (exists($peorg))
     then  $peorg/@entityID
     else false
:)	  

  let $mainname := <csd:primaryName>{$displayName}</csd:primaryName>

  (:set up local identifiers:)
  let $other_ids := (
    <csd:otherID assigningAuthorityName="{$dhis_url}/api/organisationUnits" code="id">{string($id)}</csd:otherID>
    ,
    if (not(functx:all-whitespace($org_code)))
    then <csd:otherID assigningAuthorityName="{$dhis_url}/api/organisationUnits" code="code">{string($org_code)}</csd:otherID>
    else ()
    ,
    if (not(functx:all-whitespace($uuid)))
    then <csd:otherID assigningAuthorityName="{$dhis_url}/api/organisationUnits" code="uuid">{string($uuid)}</csd:otherID>
    else ()
    )

  (:set up codes:)
  let $level_code := <csd:codedType code="{$level}" codingScheme="urn:{$dhis_url}/api/organisationUnitLevels"/>
  let $group_cts :=
    for $group_code in $group_codes
    return <csd:codedType codingScheme="urn:{$dhis_url}/api/organisationUnitGroups" code="{$group_code}" />

  let $geo_data :=
     (
       util:get_geocode($orgUnit)
       ,util:get_shape($orgUnit)
     )
  let $name := <csd:primaryName>{string($orgUnit/@name)}</csd:primaryName>
  let $record :=  <csd:record created="{$created}" updated="{$lm}" status="Active" sourceDirectory="{$dhis_url}"/>
    

  (:first we extract all org units matching our facility conditions :)
  let $fac_srvcs :=
    if (not($do_srvcs))
    then ()
    else 
      (: get data sets that are associated to this org unit :)
      let $dsets := $dataSets/dxf:dataSet[dxf:organisationUnits/dxf:organisationUnit/@id = $id]
      return 
	(
	  (:each data set is a service :)
	  for $ds in $dsets
	  let $ds_id := string($ds/@id)
	  let $ds_uuid := string($ds/@uuid)
	  let $ds_entityID :=
	    if (not(functx:all-whitespace($ds_uuid)))
	    then concat("urn:uuid:",$ds_uuid)  
	    else  concat("urn:uuid:",util:uuid_generate(concat('service:',$ds_id),$namespace_uuid))
	  return <csd:service entityID="{$ds_entityID}"/>    
	  ,
	  (:each data element is a service :)
	  let $des :=
            for $dset in $dsets
	    return $dataElements/dxf:dataElement[@id = $dset/dxf:dataElements/dxf:dataElement/@id]
	  return 
            for $de in  $des
	    let $de_id := $de/@id
	    let $de_uuid := $de/@uuid
	    let $srvc_entity_id := 
	      if (not(functx:all-whitespace($de_uuid)))
	      then concat("urn:uuid:",$de_uuid)
	      else concat("urn:uuid:",util:uuid_generate(concat('service:',$de_id),$namespace_uuid))
	    return <csd:service entityID="{$srvc_entity_id}"/>
	  )

  let $fac_entity :=
    if (($group_codes = $facility_group_codes) or ( $level = $facility_levels)) 
    then
      <csd:facility entityID="{$facEntityID}">
	{$other_ids}
	{$level_code}
	{$group_cts}
	{$mainname}
	{$geo_data}
	<csd:organizations><csd:organization entityID="{$orgEntityID}">{$fac_srvcs}</csd:organization></csd:organizations>
	{$record}
      </csd:facility>
    else ()

  (:next we create an organization for each organisation unit.

    NOTE: this means that each organisation unit which matches as a facility will have two CSD 
          entities created a facility and an organization.  These two entities will have distinct
          UUIDs.  
   :)
     (:Should put in a CP to point geo codes for orgs as service delivery area :)

  let $org_entity :=
  <csd:organization entityID="{$orgEntityID}">
      {$other_ids}
      {$level_code}
      {$group_cts}
      {$mainname}
      {$geo_data}
      <csd:parent  entityID="{$parentEntityID}"/>
      {$record}
    </csd:organization>
  return ($org_entity,$fac_entity)

}


let $entities :=  
  let $orgunit_funcs :=     
    for $orgUnit in $orgUnits
    return function() {$process_orgunit($orgUnit)}
  return async:fork-join($orgunit_funcs)



let $process_users := function($user) {  
    let $id := string($user/@id)
    let $entityID := concat("urn:uuid:",util:uuid_generate(concat('provider:',$id),$namespace_uuid))
    let $ur_oid := concat($oid,'.1')
    let $ag_oid := concat($oid,'.4')
    let $uuid := string($user/@uuid)
    let $code:=string($user/dxf:userCredentials/@code)
    let $fore := $user/dxf:firstName/text()
    let $sur := $user/dxf:surname/text()
    let $email := $user/dxf:email/text()
    let $phone := $user/dxf:phoneNumber/text()
    let $lm := util:fixup_date($user/@lastUpdated)
    let $created := util:fixup_date($user/@created)
    let $urs := $user/dxf:userCredentials/dxf:userRoles/dxf:userRole
    let $ags := $user/dxf:userCredentials/dxf:userAuthorityGroups/dxf:userAuthorityGroup


    let $entity_uuid :=((($user/dxf:attributeValues/dxf:attributeValue[./dxf:attribute[@name='entityID']])[1])/dxf:value[1])/text()
    let $provEntityID :=
      if (not(functx:all-whitespace($entity_uuid)))
      then concat("urn:uuid:",$entity_uuid)
      else if (not(functx:all-whitespace($uuid)))
      then concat("urn:uuid:",$uuid)  
      else  concat("urn:uuid:",util:uuid_generate(concat('provider:',$id),$namespace_uuid))

    return 
    <csd:provider entityID="{$provEntityID}">
      <csd:otherID assigningAuthorityName="{$dhis_url}/api/users" code="id">{$id}</csd:otherID>
      {
	if (not(functx:all-whitespace($code)))
	then <csd:otherID assigningAuthorityName="{$dhis_url}/api/users" code="code">{$code}</csd:otherID>
        else ()
      }
      {
	if (not(functx:all-whitespace($uuid)))
	then <csd:otherID assigningAuthorityName="{$dhis_url}/api/users" code="uuid">{$uuid}</csd:otherID>
	else ()
      }
      {
	for $ag in $ags
	return 
	<csd:codedType code="{$ag/@id}" codingScheme="{$ag_oid}"/>
      }
      {
	for $ur in $urs
	return 
	<csd:codedType code="{$ur/@id}" codingScheme="{$ur_oid}"/>
      }
      {
	if (count(($urs,$ags)) = 0) 
	  then <csd:codedType code="NOROLE" codingScheme="{$ur_oid}"/>
	else ()

      }
      <csd:demographic>
	<csd:name>
	  <csd:commonName>{$sur}, {$fore}</csd:commonName>
	  <csd:forename>{$fore}</csd:forename>
	  <csd:surname>{$sur}</csd:surname>
	</csd:name>
	{
	  if ($phone) then
	  <csd:contactPoint>
	    <csd:codedType code="BP" codingScheme="urn:ihe:iti:csd:2013:contactPoint">{$phone}</csd:codedType>
	  </csd:contactPoint>
        else ()
	}
	{
	  if ($email) then
	  <csd:contactPoint>
	    <csd:codedType code="EMAIL" codingScheme="urn:ihe:iti:csd:2013:contactPoint">{$email}</csd:codedType>
	  </csd:contactPoint>
	else ()
	}
      </csd:demographic>
      {
	let $torgs := $user/dxf:organisationUnits/dxf:organisationUnit
	let $orgs := 
          for $torg in $torgs 
	  let $tid :=  $torg/@id
	  let $torg1 := ($orgUnits[@id=$tid])[1]
	  let $entity_uuid :=((($torg1/dxf:attributeValues/dxf:attributeValue[./dxf:attribute[@name='entityID']])[1])/dxf:value[1])/text()

    	  let $orgEntityID :=
	     if (not(functx:all-whitespace($entity_uuid)))
	     then concat("urn:uuid:" , $entity_uuid)
	     else concat("urn:uuid:",util:uuid_generate(concat('organization:',string($torg/@id)),$namespace_uuid))
          where  (exists($entities[@entityID = $orgEntityID]) or exists( $org_dir/csd:organization[@entityID = $orgEntityID]))
	  return <csd:organization entityID="{$orgEntityID}"/>
	  
	return 
	  if (count($orgs) > 0) then
	  <csd:organizations>{$orgs}</csd:organizations>
	  else ()
      }
      {
	let $tfacs := $user/dxf:organisationUnits/dxf:organisationUnit
	let $facs := 
          for $tfac in $tfacs 
	  let $tfac_id := $tfac/@id
    	  let $facEntityID := concat("urn:uuid:",util:uuid_generate(concat('facility:',string($tfac_id)),$namespace_uuid))
	  let $fac_srvcs := 
	    if (not($do_srvcs))
	    then ()
	    else 
	      for $r in $urs
	      let $r_id := $r/@id
	      let $role := ($userRoles/dxf:userRole[@id = $r_id])[1]
	      for $ds_ref in $role/dxf:dataSets/dxf:dataSet
	        let $ds_id := $ds_ref/@id
		let $ds := ($dataSets/dxf:dataSet[@id = $ds_id])[1]
		let $ds_orgunit := $ds/dxf:organisationUnits/dxf:organisationUnit[@id = $tfac_id]
		for $de in  $ds_orgunit/../../dxf:dataElements/dxf:dataElement
		  let $de_id := $de/@id
		  let $de_uuid := $de/@uuid
		  let $srvc_entity_id := 
		    if (not(functx:all-whitespace($de_uuid)))
		    then concat("urn:uuid:",$de_uuid)
		    else concat("urn:uuid:",util:uuid_generate(concat('service:',$de_id),$namespace_uuid))
	          return <csd:service entityID="{$srvc_entity_id}"/>
	  where  (exists($entities[@entityID = $facEntityID]) or exists( $org_dir/csd:facility[@entityID = $facEntityID]))
	  return <csd:facility entityID="{$facEntityID}">{$fac_srvcs}</csd:facility>
	  
	return 
	  if (count($facs) > 0) then
	  <csd:facilities>{$facs}</csd:facilities>
	  else ()
      }
    <csd:record created="{$created}" updated="{$lm}" status="106-001" sourceDirectory="{$dhis_url}"/>
    </csd:provider>
}


let $process_dataelements := function($de) {
    let $de_id := string($de/@id)
    let $name := string($de/@name)
    let $code := string($de/@code)
(:    let $entityID := concat("urn:uuid:",util:uuid_generate(concat('service:',$de_id),$namespace_uuid)) :)
    let $cat_id := $de/dxf:categoryCombo/@id
    let $cc :=  ($catCombos/dxf:categoryCombo[@id = $cat_id])[1]
    let $cc_code := string($cc/@code)
    let $created := util:fixup_date($de/@created)
    let $lm := util:fixup_date($de/@lastUpdated)

    let $uuid := string($de/@uuid)
    let $entity_uuid :=((($de/dxf:attributeValues/dxf:attributeValue[./dxf:attribute[@name='entityID']])[1])/dxf:value[1])/text()
    let $srvcEntityID :=
      if (not(functx:all-whitespace($entity_uuid)))
      then concat("urn:uuid:",$entity_uuid)
      else if (not(functx:all-whitespace($uuid)))
      then concat("urn:uuid:",$uuid)  
      else  concat("urn:uuid:",util:uuid_generate(concat('service:',$de_id),$namespace_uuid))
 

(:
    let $cc_id := $cc/@id
    let $cc_oid := string-join(for $cp in string-to-codepoints(string($cc_id)) return string($cp))
:)  
    let $disaggregatorSet := 
      for $disag in  $cc/dxf:categories/dxf:category
      let $disag_id := $disag/@id
      let $disag_code := $disag/@code
      let $disag_oid := string-join(for $cp in string-to-codepoints(string($disag_code)) return string($cp))
      let $doid :=  concat($oid , '.6.' , $disag_oid )
      let $attr_display:= string($disag/@name)
      let $attr := $disag_code
	(:need to be able to make it into an attribute for compatibility with ADX :)
(:
        try {
	  attribute {xs:string($disag_code)} {()}
	} catch * {
	  ''
	}
:)
      let $attr_name := string($attr)
      where ( not(functx:all-whitespace($attr_name))  and  not($attr_display = 'default')) 
      return <adx:disaggregator  id="{$doid}" refid="{$disag_id}" code="{$attr_name}">{$attr_display}</adx:disaggregator>

    return 
      <csd:service entityID="{$srvcEntityID}">
	<csd:primaryName>{$name}</csd:primaryName>
	<csd:otherID assigningAuthorityName="{$dhis_url}/api/dataElements" code="id">{$de_id}</csd:otherID>
	{     
	  if (not(functx:all-whitespace($uuid)))
	  then <csd:otherID assigningAuthorityName="{$dhis_url}/api/dataElements" code="uuid">{string($uuid)}</csd:otherID>
	  else ()
	}
	{ if (not(functx:all-whitespace($code)))
	  then <csd:otherID assigningAuthorityName="{$dhis_url}/api/dataElements" code="code">{$code}</csd:otherID>
	  else ()
	}

	{
	  if (count($disaggregatorSet) = 0) 
	  then ()
	  else 
	    <csd:extension urn="urn:http://www.openhie.org/adx" type="disaggregators">
	      <adx:disaggregatorSet id="{$cat_id}" code="{$cc_code}">
		{$disaggregatorSet}
	      </adx:disaggregatorSet>
	    </csd:extension>
	}
	{
	   <csd:extension urn="urn:http://www.dhis2.org/api/dataElement">
	     <dxf:dataElement shortname="{$de/@shortName}">
	       {$de/dxf:aggregationType}
	       {$de/dxf:dataDimension}
	       {$de/dxf:domainType}
	       {$de/dxf:type}
	       {$de/dxf:numberType}
	       {$de/dxf:aggregationOperator}
	       {$de/dxf:url}
	       {$de/dxf:zeroIsSignificant}
	     </dxf:dataElement>
	   </csd:extension>
	}

	<csd:record 
          created="{util:fixup_date($de/@created)}" 
          updated="{util:fixup_date($de/@lastUpdated)}" 
          status="Active" 
	  sourceDirectory="{$dhis_url}"/>        
      </csd:service>

}


let $process_dataset := function($ds) {
    let $ds_id := string($ds/@id)
    let $des := $ds/dxf:dataElements/dxf:dataElement
    let $name := string($ds/@name)
    let $s_name := string($ds/@shortName)
    let $pt := string($ds/dxf:periodType) 
    let $code := string($ds/@code)

    let $uuid := string($ds/@uuid)
    let $entityID :=
      if (not(functx:all-whitespace($uuid)))
      then concat("urn:uuid:",$uuid)  
      else  concat("urn:uuid:",util:uuid_generate(concat('service:',$ds_id),$namespace_uuid))


    let $cat_id := $ds/dxf:categoryCombo/@id
    let $cc :=  ($catCombos/dxf:categoryCombo[@id = $cat_id])[1]
    let $cc_code := string($cc/@code)

    let $disaggregatorSet := 
      for $disag in  $cc/dxf:categories/dxf:category
      let $disag_id := $disag/@id
      let $disag_code := $disag/@code
      let $disag_oid := string-join(for $cp in string-to-codepoints(string($disag_code)) return string($cp))
      let $doid :=  concat($oid , '.6.' , $disag_oid )
      let $attr_display:= string($disag/@name)
      let $attr := $disag_code
      let $attr_name := string($attr)
      where ( not(functx:all-whitespace($attr_name))  and  not($attr_display = 'default')) 
      return <adx:disaggregator  id="{$doid}"  code="{$attr_name}">{$attr_display}</adx:disaggregator>
 
    return 
      <csd:service entityID="{$entityID}">
	<csd:primaryName>{$name}</csd:primaryName>
	<csd:otherID assigningAuthorityName="{$dhis_url}/api/dataSets" code="id">{$ds_id}</csd:otherID>
	{     
	  if (not(functx:all-whitespace($uuid)))
	  then <csd:otherID assigningAuthorityName="{$dhis_url}/api/dataSets" code="uuid">{string($uuid)}</csd:otherID>
	  else ()
	}
	{ if (not(functx:all-whitespace($code)))
	  then <csd:otherID assigningAuthorityName="{$dhis_url}/api/dataSets" code="code">{$code}</csd:otherID>
	  else ()
	}
	{
	  if (count($disaggregatorSet) = 0) 
	  then ()
	  else 
	    <csd:extension urn="urn:http://www.openhie.org/adx" type="disaggregators">
	      <adx:disaggregatorSet id="{$cat_id}" code="{$cc_code}">
		{$disaggregatorSet}
	      </adx:disaggregatorSet>
	    </csd:extension>
	}

	{
	  if (count($des) = 0) 
	  then ()
	  else 
	    <csd:extension urn="urn:http://www.openhie.org/adx" type="dataSet">
	      {
              for $de in $des
	      let $de_id := string($de/@id)
	      let $uuid := string($de/@uuid)
	      let $entity_uuid :=((($de/dxf:attributeValues/dxf:attributeValue[./dxf:attribute[@name='entityID']])[1])/dxf:value[1])/text()
	      let $srvcEntityID :=
		if (not(functx:all-whitespace($entity_uuid)))
		then concat("urn:uuid:",$entity_uuid)
	        else if (not(functx:all-whitespace($uuid)))
		then concat("urn:uuid:",$uuid)  
	        else  concat("urn:uuid:",util:uuid_generate(concat('service:',$de_id),$namespace_uuid))
 	      return <csd:service entityID="{$srvcEntityID}"/>
	      }
	    </csd:extension>
	}

	<csd:record 
          created="{util:fixup_date($ds/@created)}" 
          updated="{util:fixup_date($ds/@lastUpdated)}" 
          status="Active" 
	  sourceDirectory="{$dhis_url}"/>        
      </csd:service>


(:    let $entityID := concat("urn:uuid:",util:uuid_generate(concat('service:',$de_id),$namespace_uuid)) :)

}




let $process_categories := function($category) {
    let $disag_code := string($category/@code)
    let $disag_oid := string-join(for $cp in string-to-codepoints(string($disag_code)) return string($cp))      
    let $disag_date := xs:dateTime(substring(string($category/@lastUpdated),1,19))
    let $disag_name := string($category/@name)
    let $disag_id := string($category/@id)
    let $svs_vals_0 :=    
      for $catOption in $category/dxf:categoryOptions/dxf:categoryOption
      let $disag_opt_date := xs:dateTime(substring(string($catOption/@lastUpdated),1,19))
      let $disag_opt_name := string($catOption/@name)
      let $date := max(($disag_date,$disag_date,$disag_opt_date))
      where (not((functx:all-whitespace($disag_opt_name)) )) 
      return <svs:Concept code="{$disag_opt_name}" displayName="{$disag_opt_name}" codeSystem="{$dhis_url}/adx/disaggregators/{$disag_code}" lu="{$date}"/>

    let $date := max(( for $d in $svs_vals_0/@lu return xs:dateTime($d)))
    let $svs_vals_1 := functx:remove-attributes-deep($svs_vals_0,'lu')
    
    let $oid :=  concat($oid , '.6.' , $disag_oid)	

    let $attr := $disag_code

    let $svs_doc :=
      <svs:ValueSet  xmlns:svs="urn:ihe:iti:svs:2008" id="{$oid}" version="{$date}" displayName="[ADX {$disag_code}] Disaggregator for {$disag_name}. ( {$disag_id
} ) Published {$date}.  ">
	<svs:ConceptList xml:lang="en-US" >{$svs_vals_1}</svs:ConceptList>
      </svs:ValueSet>
    where ( not(functx:all-whitespace($disag_code))  and not($disag_name = 'default'))   
    return $svs_doc
}
	

(: create dhis2 users as health workers/providers if requested :)

let $providers := 
  if (not($do_hws))
  then ()
  else 
    let $prov_funcs := 
      for $user in $dxf/dxf:metaData/dxf:users/dxf:user 
      return function() {$process_users($user)}
    return async:fork-join($prov_funcs)


(: Create CSD Services for DHIS2 Data Elements :) 


let $srvcs := 
  if (not($do_srvcs))
  then ()
  else 
    (
    let $de_funcs := 
      for $de in ($dataElements/dxf:dataElement)
      return function() {$process_dataelements($de)}
    return async:fork-join($de_funcs)
    ,
    let $ds_funcs := 
      for $ds in $dataSets/dxf:dataSet
      return function() {$process_dataset($ds)}
    return async:fork-join($ds_funcs)
    )


(: Create an SVS list for each of the disaggregator sets in  the service :)
let $categories := $dxf/dxf:metaData/dxf:categories/dxf:category

let $svs_srvcs := 
  if (not($do_srvcs))
  then ()
  else
(:    for $category in $categories :)
    let $cat_funcs := 
       for $category in $categories[ @id  = $catCombos/dxf:categoryCombo/dxf:categories/dxf:category/@id]
       return function() {$process_categories($category)}
    return async:fork-join($cat_funcs)



(: Create an SVS list for the Org Unit Levels :)
	
let $level_oid := concat($oid,'.2')
let $levels := $dxf/dxf:metaData/dxf:organisationUnitLevels/dxf:organisationUnitLevel
let $level_version := max(for $date in $levels/@lastUpdated return xs:dateTime(util:fixup_date($date)))
let $svs_levels :=
  <svs:ValueSet  xmlns:svs="urn:ihe:iti:svs:2008" id="{$level_oid}" version="{$level_version}" displayName="Organisation Unit Levels for DHIS at {$dhis_url}">
    <svs:ConceptList xml:lang="en-US" >
      {
	for $level in $levels
	return <svs:Concept code="{$level/@level}" displayName="{$level/@name}" codeSystem="{$dhis_url}/api/organisationUnitLevels" />
      }
    </svs:ConceptList>
  </svs:ValueSet>


(: Create an SVS list for the Org Unit Groups :)
let $group_oid := concat($oid,'.3')
let $group_version := max(for $date in $orgGroups/@lastUpdated return xs:dateTime(util:fixup_date($date)))
let $svs_groups :=
  <svs:ValueSet  xmlns:svs="urn:ihe:iti:svs:2008" id="{$group_oid}" version="{$group_version}" displayName="Organisation Unit Groups at {$dhis_url}">
    <svs:ConceptList xml:lang="en-US" >
      {
	for $group in $orgGroups
	return <svs:Concept code="{$group/@code}" displayName="{$group/@name}" codeSystem="{$dhis_url}/api/organisationUnitGroups" />
      }
    </svs:ConceptList>
  </svs:ValueSet>



let $svs_providers := 
  if (not($do_hws))
  then ()
  else 
    let $urs := $dxf/dxf:metaData/dxf:userRoles/dxf:userRole
    let $ags := $dxf/dxf:metaData/dxf:userAuthorityGroups/dxf:userAuthorityGroup
    let $urs_version := max(for $date in $urs/@lastUpdated return xs:dateTime(util:fixup_date($date)))
    let $ags_version := max(for $date in $ags/@lastUpdated return xs:dateTime(util:fixup_date($date)))
    let $ur_oid := concat($oid,'.1')
    let $ag_oid := concat($oid,'.4')
    let $svs_urs := 
      <svs:ValueSet  xmlns:svs="urn:ihe:iti:svs:2008" id="{$ur_oid}" version="{$group_version}" displayName="User Role at {$dhis_url}">
	<svs:ConceptList xml:lang="en-US" >
	  {
	    for $ur in ($urs,<userRole id='NOROLE' name='No Role'/>)
	    return <svs:Concept code="{$ur/@id}" displayName="{$ur/@name}" codeSystem="{$dhis_url}/api/userRoles" />
	  }
	</svs:ConceptList>
      </svs:ValueSet>
    let $svs_ags := 
      <svs:ValueSet  xmlns:svs="urn:ihe:iti:svs:2008" id="{$ag_oid}" version="{$group_version}" displayName="Authority Groups at {$dhis_url}">
	<svs:ConceptList xml:lang="en-US" >
	  {
	    for $ag in $ags
	    return <svs:Concept code="{$ag/@id}" displayName="{$ag/@name}" codeSystem="{$dhis_url}/api/userAuthorityGroups" />
	  }
	</svs:ConceptList>
      </svs:ValueSet>


    return ($svs_urs, $svs_ags)

let $svs_docs := ($svs_levels,$svs_groups,$svs_providers,$svs_srvcs)

 
(:Insert everything we generated into the database :)

return (
  for $entity in ( $entities,$providers, $srvcs)
  let $id := $entity/@entityID
  return 
    if (local-name($entity) = 'facility')
    then 
      let $existing_fac := $fac_dir/csd:facility[@entityID = $id]
      return
        if (not(exists($existing_fac)))
        then (insert node $entity into $fac_dir)
        else (replace node $existing_fac with $entity)
    else if (local-name($entity) = 'organization')
    then
      let $existing_org := $org_dir/csd:organization[@entityID = $id]
      return
        if (not(exists($existing_org)))
        then (insert node $entity into $org_dir)
        else (replace node $existing_org with $entity)
    else if (local-name($entity) = 'provider')
    then
      let $existing_prov := $prov_dir/csd:provider[@entityID = $id]
      return
        if (not(exists($existing_prov)))
        then (insert node $entity into $prov_dir)
        else (replace node $existing_prov with $entity)
    else if (local-name($entity) = 'service')
    then
      let $existing_srvc := $srvc_dir/csd:service[@entityID = $id]
      return
        if (not(exists($existing_srvc)))
        then (insert node $entity into $srvc_dir)
        else (replace node $existing_srvc with $entity)

    else (insert node $entity into /)
    

  ,
  for $svs_doc in $svs_docs return svs_lsvs:insert($svs_doc) 

)