fixed issue in base library where we are filtering by modification date. THIS NEEDS A CP

(:~
: This is the Care Services Discovery base XQuery module
: @version 1.0
: @see http://ihe.net
:
:)
module namespace csd = "urn:ihe:iti:csd:2013" ;
declare default element  namespace   "urn:ihe:iti:csd:2013";

(:~
 : this function accepts a list of items to filter by address
 :
 : @param $items - a list of items to filter by their <address/> child elements
 : @param $components - a list of address component values.  Each item should have an @component attribute indicating the component type. The text content is the component value.
 : @return all items in $items which have address/addressLine which matches exactly (case insensitive) on each of the given components.
 : @since 1.0
 :
:)
declare function csd:filter_by_address($items as item()*,$components as item()*) as item()*
{
    if (count($components) = 0
       or not ($components[1]/@component)
       or not ($components[1]/text())
    )
    then  $items
    else
           let $comp := fn:upper-case($components[1]/@component)
           let $val := fn:upper-case($components[1]/text())
           return csd:filter_by_address(
              $items[address/addressLine[fn:upper-case(@component) = $comp and fn:upper-case(text()) = $val]],
              fn:subsequence($components,2)
          )
};

(:~
 : this function accepts a list of items to filter by type
 :
 : @param $items - a list of items to filter by their <codedType/> child elements
 : @param $codedtype - a coded type, if specified, to filter the $items list by type.  A @code attribute, if present, results in selecting those $items with matching codedType/@code (case-insensitive) exactly.  Text content, if present,  results in selecting the $items whose codedType/text() contains that value (case-insensitive) with the given @codingSchema (case-insensitive)
 : @return all items in $items which match as above
 : @since 1.0
 :
:)
declare function csd:filter_by_coded_type($items as item()*, $codedtype as item()) as item()*
{
     if ($codedtype/@code and $codedtype/@codingSchema)
     then
        let $code := fn:upper-case($codedtype/@code)
	    let $cSchema := $codedtype/@codingSchema
        return $items[codedType[
                @code = @code
 	            and
                @codingSchema = $cSchema
                ]
            ]
     else $items
};

(:~
 : this function accepts a list of items to filter by their primary name
 :
 : @param $items - a list of items to filter by their <primaryName/> child elements
 : @param $primaryName - a name, if specified, to filter the $items list by their <primaryName/> child elements.  The text content of $primaryName, if present, results in selecting those $items containing that content. Case-insenisitive.
 : @return all items in $items which match as above
 : @since 1.0
 :
:)
declare function csd:filter_by_primary_name($items as item()*,$primaryName as item()) as item()*
{

      if ($primaryName)
      then
          let $u_primaryName := fn:upper-case($primaryName)
          return $items[contains(fn:upper-case(./primaryName) , $u_primaryName)]
      else $items
};

(:~
 : this function accepts a list of items to filter by their primary name or other name
 :
 : @param $items - a list of items to filter by their <primaryName/> and <otherName/> child elements
 : @param $name - a name, if specified, to filter the $items list by either their <primaryName/> or <otherName/> child elements .  The text content of $name, if present, results in selecting those $items containing that content. Case-insenisitive.
 : @return all items in $items which match as above
 : @since 1.0
 :
:)
declare function csd:filter_by_name($items as item()*,$name as item()) as item()*
{
       if ($name)
       then
          let $u_name := fn:upper-case($name)
          return $items[
                   contains(fn:upper-case(./primaryName) , $u_name)
                   or ./otherName[contains(fn:upper-case(.),$u_name)]
                   ]
       else $items
};

(:~
 : this function accepts a list of items to filter by their primary id
 :
 : @param $items - a list of items to filter by their primary id
 : @param $id - a uniqueID, if present with an non-empty @oid attribute then it is used to filter the $items list by their @oid attributes by performing an exact match of the @oid $id.
 : @return all items in $items which match as above
 : @since 1.0
 :
:)
declare function csd:filter_by_primary_id($items as item()*,$id as item()) as item()*
{
       if ($id/@oid)
       then $items[@oid =$id/@oid]
       else $items
};

(:~
 : this function accepts a list of items to filter by their  by their <otherId/> child elements
 :
 : @param $items - a list of items to filter by their id
 : @param $id - an otherIDI, if specified, to filter the $items list by their @code and @assigningAuthorityName attributes any child <otherID> elements by performing an exact, case-insensitive match of the @code and @assigningAuthorityName attributes of $id.
 : @return all items in $items which match as above
 : @since 1.0
 :
:)
declare function csd:filter_by_other_id($items as item()*,$id as item()) as item()*
{
       if ($id/@assigningAuthorityName)
       then
           let $aaName := fn:upper-case($id/@assigningAuthorityName	)
           let $code := fn:upper-case($id/@code)
           return $items[
                          otherID[
                            fn:upper-case(@assigningAuthorityName)=$aaName
                            and
 			   fn:upper-case(@code)=$code
                         ]
                        ]
        else $items
};

(:~
 : this function accepts a list of items to filter by their common name
 :
 : @param $items - a list of items to filter by their common name
 : @param $name - an xs:string, if specified, to filter the $items list selecting those whose child demographic/name/commonName child-element whose text content contains the text content of $name (case insensitive)
 : @return all items in $items which match as above
 : @since 1.0
 :
:)
declare function csd:filter_by_common_name($items as item()*, $name as item()) as item()*
{
       if ($name)
       then
           let $u_name:= fn:upper-case($name)
           return $items[contains(fn:upper-case(demographic/name/commonName) ,$u_name)]
       else $items
};

(:~
 : this function accepts a list of items to filter by their surname
 :
 : @param $items - a list of items to filter by their surname
 : @param $name - an xs:string, if specified, to filter the $items list selecting those whose child demographic/name/surname child-element whose text content contains the text content of $name (case insensitive)
 : @return all items in $items which match as above
 : @since 1.0
 :
:)
declare function csd:filter_by_surname($items as item()*, $name as item()) as item()*
{
       if ($name)
       then
           let $u_name:= fn:upper-case($name)
           return $items[contains(fn:upper-case(demographic/name/surname) ,$u_name)]
       else $items
};

(:~
 : this function accepts a list of items to filter by the start of their surname
 :
 : @param $items - a list of items to filter by their surname
 : @param $name - an xs:string, if specified, to filter the $items list selecting those whose child demographic/name/surname child-element whose text content starts with the text content of $name (case insensitive)
 : @return all items in $items which match as above
 : @since 1.0
 :
:)
declare function csd:filter_by_surname_starts_with($items as item()*, $name as item()) as item()*
{
       if ($name)
       then
           let $u_name:= fn:upper-case($name)
           return $items[starts-with(fn:upper-case(demographic/name/surname) ,$u_name)]
       else $items
};

(:~
 : this function accepts a list of items to filter by their forename
 :
 : @param $items - a list of items to filter by their forename
 : @param $name - an xs:string, if specified, to filter the $items list selecting those whose child demographic/name/forename child-element whose text content contains the text content of $name (case insensitive)
 : @return all items in $items which match as above
 : @since 1.0
 :
:)
declare function csd:filter_by_forename($items as item()*, $name as item()) as item()*
{
       if ($name)
       then
           let $u_name:= fn:upper-case($name)
           return $items[contains(fn:upper-case(demographic/name/forename) ,$u_name)]
       else $items
};

(:~
 : this function accepts a list of items to filter by the start of their forename
 :
 : @param $items - a list of items to filter by their forename
 : @param $name - an xs:string, if specified, to filter the $items list selecting those whose child demographic/name/forename child-element whose text content starts with the text content of $name (case insensitive)
 : @return all items in $items which match as above
 : @since 1.0
 :
:)
declare function csd:filter_by_forename_starts_with($items as item()*, $name as item()) as item()*
{
       if ($name)
       then
           let $u_name:= fn:upper-case($name)
           return $items[starts-with(fn:upper-case(demographic/name/forename) ,$u_name)]
       else $items
};

(:~
 : this function accepts a list of items to filter by their record details
 :
 : @param $items - a list of items to filter by their record details
 : @param $record - a csd:record, if specified, to filter the $items list selecting those whose child record/@status matches $record/@status exactly (case insensitive) if $record/@status is presnet non-empty and record/@updated is at least $record/@updated if the later is present and non-empty
 : @return all items in $items which match as above
 : @since 1.0
 :
:)
declare function csd:filter_by_record($items as item()*, $record as item()) as item()*
{
    let $items1:=
        if (not($record/@status) )
        then $items
        else
             let $u_status:= fn:upper-case($record/@status)
             return $items[fn:upper-case(record/@status) = $u_status]
    return
        if (not($record/@updated) )
        then $items1
        else $items1[record/@updated >= $record/@updated ]

};

(:~
 : this function accepts a list of items to limit to a subset
 :
 : @param $items - a list of items to limit
 : @param $start - a start index for limiting the item list.  If not specified then defaults to 1
 : @param $max - a maximum number of results to return.  If negattive or not specified returns all restults.
 : @return all items in $items which match as above
 : @since 1.0
 :
:)
declare function csd:limit_items($items as item()*, $start as item(),$max as item()) as item()*
{
        if (not(fn:number($start)) or xs:integer($start) < 1)
        then if (not(fn:number($max)) or xs:integer($max) < 0)
            then $items
            else $items[position() <= xs:integer($max)]
        else if (fn:number($max) and xs:integer($max) >= 0)
        then $items[position() >= xs:integer($start) and position() < (xs:integer($start) + xs:integer(max))]
        else $items[position() >= xs:integer($start)]

 };

(:~
 : this function accepts a list of items to filter against a list of organizations
 :
 : @param $items - a list of items to filter by their record details
 : @param $orgs - a list of organizations that to filter $items against.  A member of $items is kept if there is at least one member of $orgs to which it is associated to
 : @return all items in $items which match as above
 : @since 1.0
 :
:)
declare function csd:filter_by_organizations($items as item()*,$orgs as item()*) as item()*
{
    if (count($orgs) = 0 )
    then  ()
    else
    	$items[organizations/organization/@oid = $orgs[1]/@oid ]
        union
        csd:filter_by_organizations($items, fn:subsequence($orgs,2))
};

(:~
 : this function accepts a list of items to filter against a list of facilities
 :
 : @param $items - a list of items to filter by their record details
 : @param $orgs - a list of facilities that to filter $items against.  A member of $items is kept if there is at least one member of $facs to which it is associated to
 : @return all items in $items which match as above
 : @since 1.0
 :
:)
declare function csd:filter_by_facilities($items as item()*,$facs as item()*) as item()*
{
    if (count($facs) = 0 )
    then  ()
    else
    	$items[facilities/facility/@oid  = $facs[1]/@oid]
        union
        csd:filter_by_facilities($items, fn:subsequence($facs,2))
};

(:~
 : this function accepts a list of organizations and augments it to invclude all (grand-)*child organizations that are present within the given organization directory
 : @param $orgs - a list of organizations
 : @param $orgdir - the organization directory we are looking within to find (grand-)*child organizations
 : @return all organizations of $orgdir which are (grand-)*child organization of the list or given organizations $orgs. includes $orgs.
:)
declare function csd:join_child_organizations($orgs as item()*,$orgdir as item()) as item()*
{
     if (count($orgs) = 0)
     then ()
     else
        csd:get_child_organizations($orgs[1],$orgdir)
        union
        csd:join_child_organizations(fn:subsequence($orgs,2),$orgdir)
};

(:~
 : this function returns a list of all (grand-)*child organizations of a given organization with the given organization directory
 : @param $org - an organization
 : @param $orgdir - the organization directory we are looking within to find (grand-)*child organizations
 : @return all organizations of $orgdir which are (grand-)*child organization of the list or given organization $org. includes $org.
:)
declare function csd:get_child_organizations($org as item(),$orgdir as item()) as item()*
{
    if (not($org))
    then ()
    else
       let $root := fn:upper-case($org/@root)
       let $extension := fn:upper-case($org/@extension)
       let $child_orgs := $orgdir/organization[
                               fn:upper-case(parent/@root)=$root
                               and fn:upper-case(parent/@extension)=$extension
                               ]
       return ($org,csd:join_child_organizations($child_orgs,$orgdir))
};

(:~
 : this function returns a list of all (grand-)*parent organizations of a given organization with the given organization directory
 : @param $org - an organization
 : @param $orgdir - the organization directory we are looking within to find (grand-)*parent organizations
 : @return all organizations of $orgdir which are (grand-)*parent organization of the list or given organization $org. includes $org.
:)
declare function csd:get_parent_organizations($org as item(),$orgdir as item()) as item()*
{
    if (not($org/parent/@root))
    then $org
    else
       let $root := fn:upper-case($org/parent/@root)
       let $extension := fn:upper-case($org/parent/@extension)
       return (
                $org ,
               csd:get_parent_organizations(
                    $orgdir/organization[
                        fn:upper-case(@root)=$root and fn:upper-case(@extension)=$extension
                        ],
                    $orgdir
                    )
               )
};

(:~
 : this function accepts a list of organizations and augments it to invclude all (grand-)*parent organizations that are present within the given organization directory
 : @param $orgs - a list of organizations
 : @param $orgdir - the organization directory we are looking within to find (grand-)*parent organizations
 : @return all organizations of $orgdir which are (grand-)*parent organization of the list or given organizations $orgs. includes $orgs.
:)
declare function csd:join_parent_organizations($orgs as item()*,$orgdir as item()) as item()*
{
     if (count($orgs) = 0)
     then ()
     else
        csd:get_parent_organizations($orgs[1],$orgdir)
        union
        csd:join_parent_organizations(fn:subsequence($orgs,2),$orgdir)
};

(:~
: This is the Care Services Discovery base XQuery module
: @version 1.0
: @see http://ihe.net
:
:)
module namespace csd = "urn:ihe:iti:csd:2013" ;
declare default element  namespace   "urn:ihe:iti:csd:2013";

(:~
 : this function accepts a list of items to filter by address
 :
 : @param $items - a list of items to filter by their <address/> child elements
 : @param $components - a list of address component values.  Each item should have an @component attribute indicating the component type. The text content is the component value.
 : @return all items in $items which have address/addressLine which matches exactly (case insensitive) on each of the given components.
 : @since 1.0
 :
:)
declare function csd:filter_by_address($items as item()*,$components as item()*) as item()*
{
    if (count($components) = 0
       or not ($components[1]/@component)
       or not ($components[1]/text())
    )
    then  $items
    else
           let $comp := fn:upper-case($components[1]/@component)
           let $val := fn:upper-case($components[1]/text())
           return csd:filter_by_address(
              $items[address/addressLine[fn:upper-case(@component) = $comp and fn:upper-case(text()) = $val]],
              fn:subsequence($components,2)
          )
};

(:~
 : this function accepts a list of items to filter by type
 :
 : @param $items - a list of items to filter by their <codedType/> child elements
 : @param $codedtype - a coded type, if specified, to filter the $items list by type.  A @code attribute, if present, results in selecting those $items with matching codedType/@code (case-insensitive) exactly.  Text content, if present,  results in selecting the $items whose codedType/text() contains that value (case-insensitive) with the given @codingSchema (case-insensitive)
 : @return all items in $items which match as above
 : @since 1.0
 :
:)
declare function csd:filter_by_coded_type($items as item()*, $codedtype as item()) as item()*
{
     if ($codedtype/@code and $codedtype/@codingSchema)
     then
        let $code := fn:upper-case($codedtype/@code)
	    let $cSchema := $codedtype/@codingSchema
        return $items[codedType[
                @code = @code
 	            and
                @codingSchema = $cSchema
                ]
            ]
     else $items
};

(:~
 : this function accepts a list of items to filter by their primary name
 :
 : @param $items - a list of items to filter by their <primaryName/> child elements
 : @param $primaryName - a name, if specified, to filter the $items list by their <primaryName/> child elements.  The text content of $primaryName, if present, results in selecting those $items containing that content. Case-insenisitive.
 : @return all items in $items which match as above
 : @since 1.0
 :
:)
declare function csd:filter_by_primary_name($items as item()*,$primaryName as item()) as item()*
{

      if ($primaryName)
      then
          let $u_primaryName := fn:upper-case($primaryName)
          return $items[contains(fn:upper-case(./primaryName) , $u_primaryName)]
      else $items
};

(:~
 : this function accepts a list of items to filter by their primary name or other name
 :
 : @param $items - a list of items to filter by their <primaryName/> and <otherName/> child elements
 : @param $name - a name, if specified, to filter the $items list by either their <primaryName/> or <otherName/> child elements .  The text content of $name, if present, results in selecting those $items containing that content. Case-insenisitive.
 : @return all items in $items which match as above
 : @since 1.0
 :
:)
declare function csd:filter_by_name($items as item()*,$name as item()) as item()*
{
       if ($name)
       then
          let $u_name := fn:upper-case($name)
          return $items[
                   contains(fn:upper-case(./primaryName) , $u_name)
                   or ./otherName[contains(fn:upper-case(.),$u_name)]
                   ]
       else $items
};

(:~
 : this function accepts a list of items to filter by their primary id
 :
 : @param $items - a list of items to filter by their primary id
 : @param $id - a uniqueID, if present with an non-empty @oid attribute then it is used to filter the $items list by their @oid attributes by performing an exact match of the @oid $id.
 : @return all items in $items which match as above
 : @since 1.0
 :
:)
declare function csd:filter_by_primary_id($items as item()*,$id as item()) as item()*
{
       if ($id/@oid)
       then $items[@oid =$id/@oid]
       else $items
};

(:~
 : this function accepts a list of items to filter by their  by their <otherId/> child elements
 :
 : @param $items - a list of items to filter by their id
 : @param $id - an otherIDI, if specified, to filter the $items list by their @code and @assigningAuthorityName attributes any child <otherID> elements by performing an exact, case-insensitive match of the @code and @assigningAuthorityName attributes of $id.
 : @return all items in $items which match as above
 : @since 1.0
 :
:)
declare function csd:filter_by_other_id($items as item()*,$id as item()) as item()*
{
       if ($id/@assigningAuthorityName)
       then
           let $aaName := fn:upper-case($id/@assigningAuthorityName	)
           let $code := fn:upper-case($id/@code)
           return $items[
                          otherID[
                            fn:upper-case(@assigningAuthorityName)=$aaName
                            and
 			   fn:upper-case(@code)=$code
                         ]
                        ]
        else $items
};

(:~
 : this function accepts a list of items to filter by their common name
 :
 : @param $items - a list of items to filter by their common name
 : @param $name - an xs:string, if specified, to filter the $items list selecting those whose child demographic/name/commonName child-element whose text content contains the text content of $name (case insensitive)
 : @return all items in $items which match as above
 : @since 1.0
 :
:)
declare function csd:filter_by_common_name($items as item()*, $name as item()) as item()*
{
       if ($name)
       then
           let $u_name:= fn:upper-case($name)
           return $items[contains(fn:upper-case(demographic/name/commonName) ,$u_name)]
       else $items
};

(:~
 : this function accepts a list of items to filter by their surname
 :
 : @param $items - a list of items to filter by their surname
 : @param $name - an xs:string, if specified, to filter the $items list selecting those whose child demographic/name/surname child-element whose text content contains the text content of $name (case insensitive)
 : @return all items in $items which match as above
 : @since 1.0
 :
:)
declare function csd:filter_by_surname($items as item()*, $name as item()) as item()*
{
       if ($name)
       then
           let $u_name:= fn:upper-case($name)
           return $items[contains(fn:upper-case(demographic/name/surname) ,$u_name)]
       else $items
};

(:~
 : this function accepts a list of items to filter by the start of their surname
 :
 : @param $items - a list of items to filter by their surname
 : @param $name - an xs:string, if specified, to filter the $items list selecting those whose child demographic/name/surname child-element whose text content starts with the text content of $name (case insensitive)
 : @return all items in $items which match as above
 : @since 1.0
 :
:)
declare function csd:filter_by_surname_starts_with($items as item()*, $name as item()) as item()*
{
       if ($name)
       then
           let $u_name:= fn:upper-case($name)
           return $items[starts-with(fn:upper-case(demographic/name/surname) ,$u_name)]
       else $items
};

(:~
 : this function accepts a list of items to filter by their forename
 :
 : @param $items - a list of items to filter by their forename
 : @param $name - an xs:string, if specified, to filter the $items list selecting those whose child demographic/name/forename child-element whose text content contains the text content of $name (case insensitive)
 : @return all items in $items which match as above
 : @since 1.0
 :
:)
declare function csd:filter_by_forename($items as item()*, $name as item()) as item()*
{
       if ($name)
       then
           let $u_name:= fn:upper-case($name)
           return $items[contains(fn:upper-case(demographic/name/forename) ,$u_name)]
       else $items
};

(:~
 : this function accepts a list of items to filter by the start of their forename
 :
 : @param $items - a list of items to filter by their forename
 : @param $name - an xs:string, if specified, to filter the $items list selecting those whose child demographic/name/forename child-element whose text content starts with the text content of $name (case insensitive)
 : @return all items in $items which match as above
 : @since 1.0
 :
:)
declare function csd:filter_by_forename_starts_with($items as item()*, $name as item()) as item()*
{
       if ($name)
       then
           let $u_name:= fn:upper-case($name)
           return $items[starts-with(fn:upper-case(demographic/name/forename) ,$u_name)]
       else $items
};

(:~
 : this function accepts a list of items to filter by their record details
 :
 : @param $items - a list of items to filter by their record details
 : @param $record - a csd:record, if specified, to filter the $items list selecting those whose child record/@status matches $record/@status exactly (case insensitive) if $record/@status is presnet non-empty and record/@updated is at least $record/@updated if the later is present and non-empty
 : @return all items in $items which match as above
 : @since 1.0
 :
:)
declare function csd:filter_by_record($items as item()*, $record as item()) as item()*
{
    let $items1:=
        if (not($record/@status) )
        then $items
        else
             let $u_status:= fn:upper-case($record/@status)
             return $items[fn:upper-case(record/@status) = $u_status]
    return
        if (not($record/@updated) or not(xs:dateTime($record/@updated)))
        then $items1
        else $items1[record/@updated >= $record/@updated ]

};

(:~
 : this function accepts a list of items to limit to a subset
 :
 : @param $items - a list of items to limit
 : @param $start - a start index for limiting the item list.  If not specified then defaults to 1
 : @param $max - a maximum number of results to return.  If negattive or not specified returns all restults.
 : @return all items in $items which match as above
 : @since 1.0
 :
:)
declare function csd:limit_items($items as item()*, $start as item(),$max as item()) as item()*
{
        if (not(fn:number($start)) or xs:integer($start) < 1)
        then if (not(fn:number($max)) or xs:integer($max) < 0)
            then $items
            else $items[position() <= xs:integer($max)]
        else if (fn:number($max) and xs:integer($max) >= 0)
        then $items[position() >= xs:integer($start) and position() < (xs:integer($start) + xs:integer(max))]
        else $items[position() >= xs:integer($start)]

 };

(:~
 : this function accepts a list of items to filter against a list of organizations
 :
 : @param $items - a list of items to filter by their record details
 : @param $orgs - a list of organizations that to filter $items against.  A member of $items is kept if there is at least one member of $orgs to which it is associated to
 : @return all items in $items which match as above
 : @since 1.0
 :
:)
declare function csd:filter_by_organizations($items as item()*,$orgs as item()*) as item()*
{
    if (count($orgs) = 0 )
    then  ()
    else
    	$items[organizations/organization/@oid = $orgs[1]/@oid ]
        union
        csd:filter_by_organizations($items, fn:subsequence($orgs,2))
};

(:~
 : this function accepts a list of items to filter against a list of facilities
 :
 : @param $items - a list of items to filter by their record details
 : @param $orgs - a list of facilities that to filter $items against.  A member of $items is kept if there is at least one member of $facs to which it is associated to
 : @return all items in $items which match as above
 : @since 1.0
 :
:)
declare function csd:filter_by_facilities($items as item()*,$facs as item()*) as item()*
{
    if (count($facs) = 0 )
    then  ()
    else
    	$items[facilities/facility/@oid  = $facs[1]/@oid]
        union
        csd:filter_by_facilities($items, fn:subsequence($facs,2))
};

(:~
 : this function accepts a list of organizations and augments it to invclude all (grand-)*child organizations that are present within the given organization directory
 : @param $orgs - a list of organizations
 : @param $orgdir - the organization directory we are looking within to find (grand-)*child organizations
 : @return all organizations of $orgdir which are (grand-)*child organization of the list or given organizations $orgs. includes $orgs.
:)
declare function csd:join_child_organizations($orgs as item()*,$orgdir as item()) as item()*
{
     if (count($orgs) = 0)
     then ()
     else
        csd:get_child_organizations($orgs[1],$orgdir)
        union
        csd:join_child_organizations(fn:subsequence($orgs,2),$orgdir)
};

(:~
 : this function returns a list of all (grand-)*child organizations of a given organization with the given organization directory
 : @param $org - an organization
 : @param $orgdir - the organization directory we are looking within to find (grand-)*child organizations
 : @return all organizations of $orgdir which are (grand-)*child organization of the list or given organization $org. includes $org.
:)
declare function csd:get_child_organizations($org as item(),$orgdir as item()) as item()*
{
    if (not($org))
    then ()
    else
       let $root := fn:upper-case($org/@root)
       let $extension := fn:upper-case($org/@extension)
       let $child_orgs := $orgdir/organization[
                               fn:upper-case(parent/@root)=$root
                               and fn:upper-case(parent/@extension)=$extension
                               ]
       return ($org,csd:join_child_organizations($child_orgs,$orgdir))
};

(:~
 : this function returns a list of all (grand-)*parent organizations of a given organization with the given organization directory
 : @param $org - an organization
 : @param $orgdir - the organization directory we are looking within to find (grand-)*parent organizations
 : @return all organizations of $orgdir which are (grand-)*parent organization of the list or given organization $org. includes $org.
:)
declare function csd:get_parent_organizations($org as item(),$orgdir as item()) as item()*
{
    if (not($org/parent/@root))
    then $org
    else
       let $root := fn:upper-case($org/parent/@root)
       let $extension := fn:upper-case($org/parent/@extension)
       return (
                $org ,
               csd:get_parent_organizations(
                    $orgdir/organization[
                        fn:upper-case(@root)=$root and fn:upper-case(@extension)=$extension
                        ],
                    $orgdir
                    )
               )
};

(:~
 : this function accepts a list of organizations and augments it to invclude all (grand-)*parent organizations that are present within the given organization directory
 : @param $orgs - a list of organizations
 : @param $orgdir - the organization directory we are looking within to find (grand-)*parent organizations
 : @return all organizations of $orgdir which are (grand-)*parent organization of the list or given organizations $orgs. includes $orgs.
:)
declare function csd:join_parent_organizations($orgs as item()*,$orgdir as item()) as item()*
{
     if (count($orgs) = 0)
     then ()
     else
        csd:get_parent_organizations($orgs[1],$orgdir)
        union
        csd:join_parent_organizations(fn:subsequence($orgs,2),$orgdir)
};


fixup redirect

fixup redirect

module namespace page = 'http://basex.org/modules/web-page';

import module namespace csd_webconf =  "https://github.com/openhie/openinfoman/csd_webconf";
import module namespace csd_webui =  "https://github.com/openhie/openinfoman/csd_webui";
import module namespace csr_proc = "https://github.com/openhie/openinfoman/csr_proc";
declare   namespace   xforms = "http://www.w3.org/2002/xforms";
declare namespace xs = "http://www.w3.org/2001/XMLSchema";
declare   namespace   csd = "urn:ihe:iti:csd:2013";
declare default element  namespace   "urn:ihe:iti:csd:2013";

declare variable $page:xsl := "../resources/doc_careServiceFunctions.xsl";

declare
  %rest:path("/CSD/storedFunctions")
  %rest:GET
  %output:method("xhtml")
  function page:csr_list()
{
if (not (db:is-xml($csd_webconf:db,$csr_proc:stored_functions_doc))) then
  csd_webui:redirect("CSD/storedFunctions/init")
else
  let $new := page:new_stored_function()
  let $reload:=

Registered Stored Queries

{count(csr_proc:stored_functions($csd_webconf:db))} Stored Functions

{count(csr_proc:stored_updating_functions($csd_webconf:db))} Stored Updating Functions

Reload stored functions from disk

    Export Documentation

Export Functions

Clear All Stored Functions

  let $list := page:function_list()
  return page:wrapper(($reload,$list),$new)
};

declare updating
  %rest:path("/CSD/storedFunctions/upload")
  %rest:consumes("application/xml", "text/xml", "multipart/form-data")
  %rest:form-param("upload","{$upload}")
  %rest:POST
  function page:upload($upload)
{
 for $name    in map:keys($upload)
 let $content := $upload($name)
 let $func := parse-xml(bin:decode-string($content, 'UTF-8'))
 return
   (
     csr_proc:load_stored_function($csd_webconf:db,$func/careServicesFunction)
     ,
     csd_webui:redirect_out("CSD/storedFunctions")
  )

};

declare function page:new_stored_function()
{

Upload careServicesFunction Document

   <form method='post' action="/CSD/storedFunctions/upload"  enctype="multipart/form-data">
   Upload<input name='upload' type='file'/>
   <input type="submit" value="submit"/>
   </form>

Create New Stored Function

   <form method='post' action="/CSD/storedFunctions/create"  enctype="multipart/form-data">
     URN<input    size="42" name="urn" value="urn:uuid:{random:uuid()}"  readonly="readonly"/>

     Content Type<input    cols="80" name="content" value="text/html"/>

     Description<textarea  rows="20" cols="80" name="description" ></textarea>

     XQuery<textarea  rows="20" cols="80" name="query" ></textarea>

     <input type="submit" value="submit"/>
   </form>

};

declare  updating
  %rest:path("/CSD/storedFunctions/delete/{$urn}")
  function page:delete($urn)
  {
    (
      csr_proc:delete_stored_function($csd_webconf:db,$urn),
      csd_webui:redirect_out("CSD/storedFunctions")
    )

};

declare
  %rest:path("/CSD/storedFunctions/download/{$urn}")
  function page:download($urn)
  {
    let $node := (
      csr_proc:get_function_definition($csd_webconf:db,$urn),
      csr_proc:get_updating_function_definition($csd_webconf:db,$urn)
    )[1]
    return $node

};

declare  updating
  %rest:path("/CSD/storedFunctions/clear")
  function page:clear()
  {
    (
      csr_proc:clear_stored_functions($csd_webconf:db),
      csd_webui:redirect_out("CSD/storedFunctions")
    )

};

declare  updating
  %rest:path("/CSD/storedFunctions/create")
  %rest:consumes("application/xml", "text/xml", "multipart/form-data")
  %rest:POST
  %rest:form-param("query","{$query}")
  %rest:form-param("description","{$description}")
  %rest:form-param("content", "{$content}","application/xml")
  %rest:form-param("urn", "{$urn}")
  function page:create($urn,$query,$description,$content)
{
(  if ($urn) then
   let $func :=
   <careServicesFunction urn="{$urn}" content-type="{$content}">
     <description>{$description}</description>
     <definition>{$query}</definition>
   </careServicesFunction>
   return csr_proc:load_stored_function($csd_webconf:db,$func)
  else (),
    csd_webui:redirect_out("CSD/storedFunctions")
)
};

declare updating
  %rest:path("/CSD/storedFunctions/init")
  %rest:GET
  function page:init()
{
  (csr_proc:init($csd_webconf:db),
  csd_webui:redirect_out("CSD/storedFunctions")
  )
};

declare updating
  %rest:path("/CSD/storedFunctions/reload")
  %rest:GET
  function page:reload()
{
  (csr_proc:load_functions_from_files($csd_webconf:db),
  csd_webui:redirect_out("CSD/storedFunctions")
  )
};

declare function page:display_function($function,$updating) {
  let  $urn := string($function/@urn)
  return
    {if ($updating) then  "(Updating) " else ()}
    URN: {string($urn)}

    Method:

{string($function/definition)}

    Content: {string(csr_proc:lookup_stored_content_type($csd_webconf:db,$urn)) }

    Description:
{$function/description}

    Instance:

{serialize($function/xforms:instance/careServicesRequest,map{'indent':'yes'})}

    {if (exists($function/@method)) then  ("Method: ",string($function/@method),
) else () }
    {if (exists($function/xs:schema)) then  ("Schema: ",string($function/xs:schema),
) else () }
    {if (count( $function/xforms:bind) > 0) then
    ("Bindings: ",

        {for $bind in $function/xforms:bind return
Node set: {string($bind/@nodeset)}
Type: {string($bind/@type)}
}

    ) else ()
    }

};

declare
  %rest:path("/CSD/storedFunctions/export_funcs")
  %rest:GET
  function page:export_funcs()
{
  <careServiceFunctions
    xmlns:xforms="http://www.w3.org/2002/xforms"
    xmlns:csd="urn:ihe:iti:csd:2013"
    xmlns:xi="http://www.w3.org/2001/XInclude"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:hfp="http://www.w3.org/2001/XMLSchema-hasFacetAndProperty"
     >
  {(
    csr_proc:stored_functions($csd_webconf:db)
    ,csr_proc:stored_updating_functions($csd_webconf:db)
   )}
 </careServiceFunctions>
};

declare
  %rest:path("/CSD/storedFunctions/export_doc")
  %rest:GET
  %output:method("xhtml")
  function page:export_doc()
{
  let $funcs :=
  <careServiceFunctions
    xmlns:xforms="http://www.w3.org/2002/xforms"
    xmlns:csd="urn:ihe:iti:csd:2013"
    xmlns:xi="http://www.w3.org/2001/XInclude"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:hfp="http://www.w3.org/2001/XMLSchema-hasFacetAndProperty"
     >
  {(
    csr_proc:stored_functions($csd_webconf:db)
    ,csr_proc:stored_updating_functions($csd_webconf:db)
   )}
 </careServiceFunctions>
(: return $funcs :)
 return xslt:transform($funcs,doc($page:xsl))
};

declare function page:function_list()  {

Function List

    {
      for $function in (csr_proc:stored_functions($csd_webconf:db),csr_proc:stored_updating_functions($csd_webconf:db))
      return

URN: {string($function/@urn)} {"  "}

	{substring(string($function/description),1,100)}
	{if (string-length(string($function/description)) > 100) then "..." else ()}

      View
      Download
      Delete

    }

    {
      (
	for $function in csr_proc:stored_functions($csd_webconf:db)
	return
{page:display_function($function,false())}

       ,
        for $function in csr_proc:stored_updating_functions($csd_webconf:db)
        return
{page:display_function($function,true())}

      )
    }

};

declare
  %rest:path("/CSD/storedFunctions.json")
  %rest:GET
  function page:export_function_details_json()
  {
  xml-to-json(page:get_export_function_details())
  };

declare
  %rest:path("/CSD/storedFunctions.xml")
  %rest:GET
  function page:export_function_details_xml(){
    page:get_export_function_details()
};

declare function page:get_export_function_details() {
    <map xmlns="http://www.w3.org/2005/xpath-functions">
      {
	for $function in (csr_proc:stored_functions($csd_webconf:db))
	let $urn:= string($function/@urn)
	return
	<map key="{$urn}">
	  <boolean key="updating">false</boolean>
	  <string key="description">{string($function/description)}</string>
	  <string key="definition">{string($function/definition)}</string>
	  <string key="content-type">{string(csr_proc:lookup_stored_content_type($csd_webconf:db,$urn))}</string>
	</map>
      }
      {
	for $function in (csr_proc:stored_updating_functions($csd_webconf:db))
	let $urn:= string($function/@urn)
	return
	<map key="{string($function/@urn)}">
	  <boolean key="updating">true</boolean>
	  <string key="description">{string($function/description)}</string>
	  <string key="definition">{string($function/definition)}</string>
	  <string key="content-type">{string(csr_proc:lookup_stored_content_type($csd_webconf:db,$urn))}</string>
	</map>

      }
    </map>
};

declare function page:wrapper($list,$new) {
  let $headers := (
    <link rel="stylesheet" type="text/css" media="screen"   href="{csd_webui:generateURL('static/bootstrap/js/tab.js')}"/>
   ,
  )
  let $content :=
    (

Available Functions

Upload Function

      ,

{$list}

{$new}

    )
  return csd_webconf:wrapper($content,$headers)
};

module namespace page = 'http://basex.org/modules/web-page';

import module namespace csd_webconf =  "https://github.com/openhie/openinfoman/csd_webconf";
import module namespace csd_webui =  "https://github.com/openhie/openinfoman/csd_webui";
import module namespace csr_proc = "https://github.com/openhie/openinfoman/csr_proc";
declare   namespace   xforms = "http://www.w3.org/2002/xforms";
declare namespace xs = "http://www.w3.org/2001/XMLSchema";
declare   namespace   csd = "urn:ihe:iti:csd:2013";
declare default element  namespace   "urn:ihe:iti:csd:2013";

declare variable $page:xsl := "../resources/doc_careServiceFunctions.xsl";

declare
  %rest:path("/CSD/storedFunctions")
  %rest:GET
  %output:method("xhtml")
  function page:csr_list()
{
if (not (db:is-xml($csd_webconf:db,$csr_proc:stored_functions_doc))) then
  csd_webui:redirect("CSD/storedFunctions/init")
else
  let $new := page:new_stored_function()
  let $reload:=

Registered Stored Queries

{count(csr_proc:stored_functions($csd_webconf:db))} Stored Functions

{count(csr_proc:stored_updating_functions($csd_webconf:db))} Stored Updating Functions

Reload stored functions from disk

    Export Documentation

Export Functions

Clear All Stored Functions

  let $list := page:function_list()
  return page:wrapper(($reload,$list),$new)
};

declare updating
  %rest:path("/CSD/storedFunctions/upload")
  %rest:consumes("application/xml", "text/xml", "multipart/form-data")
  %rest:form-param("upload","{$upload}")
  %rest:POST
  function page:upload($upload)
{
 for $name    in map:keys($upload)
 let $content := $upload($name)
 let $func := parse-xml(bin:decode-string($content, 'UTF-8'))
 return
   (
     csr_proc:load_stored_function($csd_webconf:db,$func/careServicesFunction)
     ,
     csd_webui:redirect_out("CSD/storedFunctions")
  )

};

declare function page:new_stored_function()
{

Upload careServicesFunction Document

   <form method='post' action="/CSD/storedFunctions/upload"  enctype="multipart/form-data">
   Upload<input name='upload' type='file'/>
   <input type="submit" value="submit"/>
   </form>

Create New Stored Function

   <form method='post' action="/CSD/storedFunctions/create"  enctype="multipart/form-data">
     URN<input    size="42" name="urn" value="urn:uuid:{random:uuid()}"  readonly="readonly"/>

     Content Type<input    cols="80" name="content" value="text/html"/>

     Description<textarea  rows="20" cols="80" name="description" ></textarea>

     XQuery<textarea  rows="20" cols="80" name="query" ></textarea>

     <input type="submit" value="submit"/>
   </form>

};

declare  updating
  %rest:path("/CSD/storedFunctions/delete/{$urn}")
  function page:delete($urn)
  {
    (
      csr_proc:delete_stored_function($csd_webconf:db,$urn),
      csd_webui:redirect_out("CSD/storedFunctions")
    )

};

declare
  %rest:path("/CSD/storedFunctions/download/{$urn}")
  function page:download($urn)
  {
    let $node := (
      csr_proc:get_function_definition($csd_webconf:db,$urn),
      csr_proc:get_updating_function_definition($csd_webconf:db,$urn)
    )[1]
    return $node

};

declare  updating
  %rest:path("/CSD/storedFunctions/clear")
  function page:clear()
  {
    (
      csr_proc:clear_stored_functions($csd_webconf:db),
      csd_webui:redirect_out("CSD/storedFunctions")
    )

};

declare  updating
  %rest:path("/CSD/storedFunctions/create")
  %rest:consumes("application/xml", "text/xml", "multipart/form-data")
  %rest:POST
  %rest:form-param("query","{$query}")
  %rest:form-param("description","{$description}")
  %rest:form-param("content", "{$content}","application/xml")
  %rest:form-param("urn", "{$urn}")
  function page:create($urn,$query,$description,$content)
{
(  if ($urn) then
   let $func :=
   <careServicesFunction urn="{$urn}" content-type="{$content}">
     <description>{$description}</description>
     <definition>{$query}</definition>
   </careServicesFunction>
   return csr_proc:load_stored_function($csd_webconf:db,$func)
  else (),
    csd_webui:redirect_out("CSD/storedFunctions")
)
};

declare updating
  %rest:path("/CSD/storedFunctions/init")
  %rest:GET
  function page:init()
{
  (csr_proc:init($csd_webconf:db),
  csd_webui:redirect_out("CSD/storedFunctions")
  )
};

declare updating
  %rest:path("/CSD/storedFunctions/reload")
  %rest:GET
  function page:reload()
{
  (csr_proc:load_functions_from_files($csd_webconf:db),
  csd_webui:redirect_out("CSD/storedFunctions")
  )
};

declare function page:display_function($function,$updating) {
  let  $urn := string($function/@urn)
  return
    {if ($updating) then  "(Updating) " else ()}
    URN: {string($urn)}

    Method:

{string($function/definition)}

    Content: {string(csr_proc:lookup_stored_content_type($csd_webconf:db,$urn)) }

    Description:
{$function/description}

    Instance:

{serialize($function/xforms:instance/careServicesRequest,map{'indent':'yes'})}

    {if (exists($function/@method)) then  ("Method: ",string($function/@method),
) else () }
    {if (exists($function/xs:schema)) then  ("Schema: ",string($function/xs:schema),
) else () }
    {if (count( $function/xforms:bind) > 0) then
    ("Bindings: ",

        {for $bind in $function/xforms:bind return
Node set: {string($bind/@nodeset)}
Type: {string($bind/@type)}
}

    ) else ()
    }

};

declare
  %rest:path("/CSD/storedFunctions/export_funcs")
  %rest:GET
  function page:export_funcs()
{
  <careServiceFunctions
    xmlns:xforms="http://www.w3.org/2002/xforms"
    xmlns:csd="urn:ihe:iti:csd:2013"
    xmlns:xi="http://www.w3.org/2001/XInclude"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:hfp="http://www.w3.org/2001/XMLSchema-hasFacetAndProperty"
     >
  {(
    csr_proc:stored_functions($csd_webconf:db)
    ,csr_proc:stored_updating_functions($csd_webconf:db)
   )}
 </careServiceFunctions>
};

declare
  %rest:path("/CSD/storedFunctions/export_doc")
  %rest:GET
  %output:method("xhtml")
  function page:export_doc()
{
  let $funcs :=
  <careServiceFunctions
    xmlns:xforms="http://www.w3.org/2002/xforms"
    xmlns:csd="urn:ihe:iti:csd:2013"
    xmlns:xi="http://www.w3.org/2001/XInclude"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:hfp="http://www.w3.org/2001/XMLSchema-hasFacetAndProperty"
     >
  {(
    csr_proc:stored_functions($csd_webconf:db)
    ,csr_proc:stored_updating_functions($csd_webconf:db)
   )}
 </careServiceFunctions>
(: return $funcs :)
 return xslt:transform($funcs,doc($page:xsl))
};

declare function page:function_list()  {

Function List

    {
      for $function in (csr_proc:stored_functions($csd_webconf:db),csr_proc:stored_updating_functions($csd_webconf:db))
      return

URN: {string($function/@urn)} {"  "}

	{substring(string($function/description),1,100)}
	{if (string-length(string($function/description)) > 100) then "..." else ()}

      View
      Download
      Delete

    }

    {
      (
	for $function in csr_proc:stored_functions($csd_webconf:db)
	return
{page:display_function($function,false())}

       ,
        for $function in csr_proc:stored_updating_functions($csd_webconf:db)
        return
{page:display_function($function,true())}

      )
    }

};

declare
  %rest:path("/CSD/storedFunctions.json")
  %rest:GET
  function page:export_function_details_json()
  {
  xml-to-json(page:get_export_function_details())
  };

declare
  %rest:path("/CSD/storedFunctions.xml")
  %rest:GET
  function page:export_function_details_xml(){
    page:get_export_function_details()
};

declare function page:get_export_function_details() {
    <map xmlns="http://www.w3.org/2005/xpath-functions">
      {
	for $function in (csr_proc:stored_functions($csd_webconf:db))
	let $urn:= string($function/@urn)
	return
	<map key="{$urn}">
	  <boolean key="updating">false</boolean>
	  <string key="description">{string($function/description)}</string>
	  <string key="definition">{string($function/definition)}</string>
	  <string key="content-type">{string(csr_proc:lookup_stored_content_type($csd_webconf:db,$urn))}</string>
	</map>
      }
      {
	for $function in (csr_proc:stored_updating_functions($csd_webconf:db))
	let $urn:= string($function/@urn)
	return
	<map key="{string($function/@urn)}">
	  <boolean key="updating">true</boolean>
	  <string key="description">{string($function/description)}</string>
	  <string key="definition">{string($function/definition)}</string>
	  <string key="content-type">{string(csr_proc:lookup_stored_content_type($csd_webconf:db,$urn))}</string>
	</map>

      }
    </map>
};

declare function page:wrapper($list,$new) {
  let $headers := (
    <link rel="stylesheet" type="text/css" media="screen"   href="{csd_webui:generateURL('static/bootstrap/js/tab.js')"/>
   ,
  )
  let $content :=
    (

Available Functions

Upload Function

      ,

{$list}

{$new}

    )
  return csd_webconf:wrapper($content,$headers)
};


Refined link to DFST home

Refined link to DFST home

(:~
 : DITA for Small Teams
 :
 : Link management application RESTXQ implementation.
 :
 : Copyright (c) 2015 DITA for Small Teams (dita-for-small-teams.org)
 :
 : See the BaseX RESTXQ documentation for details on how the RESTXQ
 : mechanism works.
 :
 :)
module namespace page = 'http://basex.org/modules/web-page';

(:~
 : This function generates the welcome page.
 : @return HTML page
 :)
declare
  %rest:path("/")
  %output:method("xhtml")
  %output:omit-xml-declaration("no")
  %output:doctype-public("-//W3C//DTD XHTML 1.0 Transitional//EN")
  %output:doctype-system("http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd")
  function page:start()
  as element(Q{http://www.w3.org/1999/xhtml}html)
{

      <title>DITA for Small Teams Link Manager</title>
      <link rel="stylesheet" type="text/css" href="static/style.css"/>

www.dita-for-small-teams.org

DITA for Small Teams Link Manager

Actions go here

};

(:~
 : This function returns an XML response message.
 : @param $world  string to be included in the response
 : @return response element
 :)
declare
  %rest:path("/hello/{$world}")
  %rest:GET
  function page:hello(
    $world as xs:string)
    as element(response)
{
  <response>
    <title>Hello { $world }!</title>
    <time>The current time is: { current-time() }</time>
  </response>
};

(:~
 : This function returns the result of a form request.
 : @param  $message  message to be included in the response
 : @param $agent  user agent string
 : @return response element
 :)
declare
  %rest:path("/form")
  %rest:POST
  %rest:form-param("message","{$message}", "(no message)")
  %rest:header-param("User-Agent", "{$agent}")
  function page:hello-postman(
    $message as xs:string,
    $agent   as xs:string*)
    as element(response)
{
  <response type='form'>
    <message>{ $message }</message>
    <user-agent>{ $agent }</user-agent>
  </response>
};


Added tests for specifying width of month, failing tests set to pending

xquery version "3.0";

module namespace fd="http://exist-db.org/xquery/test/format-dates";

declare namespace test="http://exist-db.org/xquery/xqsuite";

declare
    %test:args("2012-06-26")
    %test:assertEquals("26.6.2012")
    %test:args("2012-06-01")
    %test:assertEquals("1.6.2012")
function fd:simple-date($date as xs:date) {
    format-date($date, "[D].[M].[Y]")
};

declare
    %test:args("2012-06-26")
    %test:assertEquals("26.06.2012")
    %test:args("2012-06-01")
    %test:assertEquals("01.06.2012")
function fd:simple-format($date as xs:date) {
    format-date($date, "[D00].[M01].[Y0]")
};

declare
    %test:args("2012-06-26")
    %test:assertEquals("26.6.2012")
    %test:args("2012-06-01")
    %test:assertEquals("1.6.2012")
function fd:format-month-numeric-width($date as xs:date) {
    format-date($date, "[D,1-2].[M,*-*].[Y,*]")
};

declare
    %test:pending
    %test:args("2012-06-26")
    %test:assertEquals("26 JUN 2012")
    %test:args("1970-10-07")
    %test:assertEquals("07 OCT 1970")
function fd:format-month-string-width-caps($date as xs:date) {
    format-date($date, "[D01] [MN,*-3] [Y0001]")
};

declare
    %test:pending
    %test:args("2012-06-26")
    %test:assertEquals("26 Jun 2012")
    %test:args("1970-10-07")
    %test:assertEquals("07 Oct 1970")
function fd:format-month-string-width-title($date as xs:date) {
    format-date($date, "[D01] [MNn,*-3] [Y0001]")
};

declare
    %test:args("2012-06-26")
    %test:assertEquals("Tuesday, June 26, 2012")
    %test:args("1970-10-07")
    %test:assertEquals("Wednesday, October 7, 1970")
function fd:format-names($date as xs:date) {
    format-date($date, "[FNn], [MNn] [D], [Y]")
};

declare
    %test:pending
    %test:args("2012-06-26")
    %test:assertEquals("Tue Jun 26 2012")
    %test:args("1970-10-07")
    %test:assertEquals("Wed Oct 7 1970")
function fd:format-names-width($date as xs:date) {
    format-date($date, "[FNn,*-3] [MNn] [D] [Y]")
};

declare
    %test:args("2012-06-26")
    %test:assertEquals("Tuesday, June 26th, 2012")
    %test:args("2012-06-01")
    %test:assertEquals("Friday, June 1st, 2012")
    %test:args("2012-06-02")
    %test:assertEquals("Saturday, June 2nd, 2012")
    %test:args("2012-06-03")
    %test:assertEquals("Sunday, June 3rd, 2012")
function fd:format-ordinal($date as xs:date) {
    format-date($date, "[FNn], [MNn] [D0o], [Y]")
};

declare
    %test:args("2002-12-31")
    %test:assertEquals("[2002-12-31]")
function fd:format-square-brackets($date as xs:date) {
    format-date($date, "[[[Y0001]-[M01]-[D01]]]")
};

declare
    %test:args("2012-06-26T23:14:22.566+02:00")
    %test:assertEquals("11:14 pm on Tuesday, June 26th, 2012")
function fd:format-dateTime($date as xs:dateTime) {
    format-dateTime($date, "[h00]:[m00] [P] on [FNn], [MNn] [D1o], [Y]")
};

declare
    %test:args("2012-06-26+02:00")
    %test:assertEquals("20120626GMT+02:00")
function fd:format-date-z($date as xs:date) {
    format-date($date, "[Y0001][M01][D01][z]")
};

declare
    %test:args("2012-06-26+02:00")
    %test:assertEquals("20120626+02:00")
function fd:format-date-Z($date as xs:date) {
    format-date($date, "[Y0001][M01][D01][Z]")
};

declare
    %test:args("2012-06-26T23:14:22.566+02:00")
    %test:assertEquals("20120626231422GMT+02:00")
function fd:format-dateTime-z($date as xs:dateTime) {
    format-dateTime($date, "[Y0001][M01][D01][H01][m01][s01][z]")
};

declare
    %test:args("2012-06-26T23:14:22.566+02:00")
    %test:assertEquals("20120626231422+02:00")
function fd:format-dateTime-Z($date as xs:dateTime) {
    format-dateTime($date, "[Y0001][M01][D01][H01][m01][s01][Z]")
};

declare
    %test:args("2012-06-26T23:14:22.566")
    %test:assertEquals("20120626231422")
function fd:format-dateTime-no-tz-z($date as xs:dateTime) {
    format-dateTime($date, "[Y0001][M01][D01][H01][m01][s01][z]")
};

declare
    %test:args("2012-06-26T23:14:22.566")
    %test:assertEquals("20120626231422")
function fd:format-dateTime-no-tz-Z($date as xs:dateTime) {
    format-dateTime($date, "[Y0001][M01][D01][H01][m01][s01][Z]")
};

declare
    %test:args("17:45:50")
    %test:assertEquals("17:45:50")
    %test:args("09:45:50")
    %test:assertEquals("09:45:50")
function fd:simple-time($time as xs:time) {
    format-time($time, "[H00]:[m00]:[s]")
};

declare
    %test:args("17:45:50")
    %test:assertEquals("05:45 pm")
    %test:args("09:45:50")
    %test:assertEquals("09:45 am")
function fd:time-am-pm($time as xs:time) {
    format-time($time, "[h00]:[m00] [P]")
};

declare
    %test:assertError
function fd:date-format-in-format-time() {
    format-time(current-time(), "[Y]")
};

declare
    %test:assertError
function fd:time-format-in-format-date() {
    format-date(current-dateTime(), "[H]")
};

declare
    %test:args("2012-06-27T10:21:55.082+02:00")
    %test:assertEquals("Mittwoch, 27. Juni 2012")
    %test:args("1970-10-07T10:21:55.082+02:00")
    %test:assertEquals("Mittwoch, 7. Oktober 1970")
function fd:language($date as xs:dateTime) {
    format-date($date, "[FNn], [D1o] [MNn] [Y]", "de", (), ())
};

declare
    %test:args("2012-06-27T10:21:55.082+02:00")
    %test:assertEquals("Среда, 27 Июня 2012")
    %test:args("1970-10-07T10:21:55.082+02:00")
    %test:assertEquals("Среда, 7 Октября 1970")
function fd:language-ru($date as xs:dateTime) {
    format-date($date, "[FNn], [D1o] [MNn] [Y]", "ru", (), ())
};

xquery version "3.0";

module namespace fd="http://exist-db.org/xquery/test/format-dates";

declare namespace test="http://exist-db.org/xquery/xqsuite";

declare
    %test:args("2012-06-26")
    %test:assertEquals("26.6.2012")
    %test:args("2012-06-01")
    %test:assertEquals("1.6.2012")
function fd:simple-date($date as xs:date) {
    format-date($date, "[D].[M].[Y]")
};

declare
    %test:args("2012-06-26")
    %test:assertEquals("26.06.2012")
    %test:args("2012-06-01")
    %test:assertEquals("01.06.2012")
function fd:simple-format($date as xs:date) {
    format-date($date, "[D00].[M01].[Y0]")
};

declare
    %test:args("2012-06-26")
    %test:assertEquals("26.6.2012")
    %test:args("2012-06-01")
    %test:assertEquals("1.6.2012")
function fd:format-width($date as xs:date) {
    format-date($date, "[D,1-2].[M,*-*].[Y,*]")
};

declare
    %test:args("2012-06-26")
    %test:assertEquals("Tuesday, June 26, 2012")
    %test:args("2012-06-01")
    %test:assertEquals("Friday, June 1, 2012")
function fd:format-names($date as xs:date) {
    format-date($date, "[FNn], [MNn] [D], [Y]")
};

declare
    %test:args("2012-06-26")
    %test:assertEquals("Tuesday, June 26th, 2012")
    %test:args("2012-06-01")
    %test:assertEquals("Friday, June 1st, 2012")
    %test:args("2012-06-02")
    %test:assertEquals("Saturday, June 2nd, 2012")
    %test:args("2012-06-03")
    %test:assertEquals("Sunday, June 3rd, 2012")
function fd:format-ordinal($date as xs:date) {
    format-date($date, "[FNn], [MNn] [D0o], [Y]")
};

declare
    %test:args("2012-06-26T23:14:22.566+02:00")
    %test:assertEquals("11:14 pm on Tuesday, June 26th, 2012")
function fd:format-dateTime($date as xs:dateTime) {
    format-dateTime($date, "[h00]:[m00] [P] on [FNn], [MNn] [D1o], [Y]")
};

declare
    %test:args("2012-06-26+02:00")
    %test:assertEquals("20120626GMT+02:00")
function fd:format-date-z($date as xs:date) {
    format-date($date, "[Y0001][M01][D01][z]")
};

declare
    %test:args("2012-06-26+02:00")
    %test:assertEquals("20120626+02:00")
function fd:format-date-Z($date as xs:date) {
    format-date($date, "[Y0001][M01][D01][Z]")
};

declare
    %test:args("2012-06-26T23:14:22.566+02:00")
    %test:assertEquals("20120626231422GMT+02:00")
function fd:format-dateTime-z($date as xs:dateTime) {
    format-dateTime($date, "[Y0001][M01][D01][H01][m01][s01][z]")
};

declare
    %test:args("2012-06-26T23:14:22.566+02:00")
    %test:assertEquals("20120626231422+02:00")
function fd:format-dateTime-Z($date as xs:dateTime) {
    format-dateTime($date, "[Y0001][M01][D01][H01][m01][s01][Z]")
};

declare
    %test:args("2012-06-26T23:14:22.566")
    %test:assertEquals("20120626231422")
function fd:format-dateTime-no-tz-z($date as xs:dateTime) {
    format-dateTime($date, "[Y0001][M01][D01][H01][m01][s01][z]")
};

declare
    %test:args("2012-06-26T23:14:22.566")
    %test:assertEquals("20120626231422")
function fd:format-dateTime-no-tz-Z($date as xs:dateTime) {
    format-dateTime($date, "[Y0001][M01][D01][H01][m01][s01][Z]")
};

declare
    %test:args("17:45:50")
    %test:assertEquals("17:45:50")
    %test:args("09:45:50")
    %test:assertEquals("09:45:50")
function fd:simple-time($time as xs:time) {
    format-time($time, "[H00]:[m00]:[s]")
};

declare
    %test:args("17:45:50")
    %test:assertEquals("05:45 pm")
    %test:args("09:45:50")
    %test:assertEquals("09:45 am")
function fd:time-am-pm($time as xs:time) {
    format-time($time, "[h00]:[m00] [P]")
};

declare
    %test:assertError
function fd:date-format-in-format-time() {
    format-time(current-time(), "[Y]")
};

declare
    %test:assertError
function fd:time-format-in-format-date() {
    format-date(current-dateTime(), "[H]")
};

declare
    %test:args("2012-06-27T10:21:55.082+02:00")
    %test:assertEquals("Mittwoch, 27. Juni 2012")
    %test:args("1970-10-07T10:21:55.082+02:00")
    %test:assertEquals("Mittwoch, 7. Oktober 1970")
function fd:language($date as xs:dateTime) {
    format-date($date, "[FNn], [D1o] [MNn] [Y]", "de", (), ())
};

declare
    %test:args("2012-06-27T10:21:55.082+02:00")
    %test:assertEquals("Среда, 27 Июня 2012")
    %test:args("1970-10-07T10:21:55.082+02:00")
    %test:assertEquals("Среда, 7 Октября 1970")
function fd:language-ru($date as xs:dateTime) {
    format-date($date, "[FNn], [D1o] [MNn] [Y]", "ru", (), ())
};