fixup csd_webap_ui

fixup csd_webap_ui

(:~
: This is a module conttaining configuration options for the openinfoman webap
: @version 1.0
: @see https://github.com/openhie/openinfoman @see http://ihe.net
:
:)

module namespace csd_webui = "https://github.com/openhie/openinfoman/csd_webui";
import module namespace csd_webconf =  "https://github.com/openhie/openinfoman/csd_webconf";
import module namespace request = "http://exquery.org/ns/request";

declare function csd_webui:generateURL() {
  csd_webui:generateURL(())
};

declare function csd_webui:generateURL($end) {
  let $cend :=
    string-join(
      for $e in $end
      return replace(replace(string($e),'^/+',''),'/+$','')
      ,'/')

  let $cbegin :=
    if (functx:all-whitespace($csd_webconf:baseurl))
    then concat(request:scheme(),"://",request:hostname(),":",request:port())
    else replace($csd_webconf:baseurl, '/+$', '')

  return concat($cbegin,'/',$cend)

};

declare function csd_webui:nocache($response)
{(
  <rest:response>
    <http:response >
      <http:header name="Cache-Control" value="must-revalidate,no-cache,no-store"/>
    </http:response>
  </rest:response>
  ,
  $response
)};

declare function csd_webui:redirect() as element(restxq:redirect) {
  csd_webui:redirect(())
};

declare function csd_webui:redirect($end ) as element(restxq:redirect)
{
  <restxq:redirect>{ csd_webui:generateURL($end }</restxq:redirect>
};

declare function csd_webui:redirect_out() as element(restxq:redirect) {
  csd_webui:redirect_out(())
};

declare function csd_webui:redirect_out($end ) as element(restxq:redirect)
{
  db:output(<restxq:redirect>{ csd_webui:generateURL($end }</restxq:redirect>)
};

declare function csd_webui:wrapper($content) {
  csd_webui:wrapper($content,())
};

declare function csd_webui:wrapper($content,$headers) {

    <link href="{$csd_webui:generateURL('static/bootstrap/css/bootstrap.css')}" rel="stylesheet"/>
    <link href="{$csd_webui:generateURL('static/bootstrap/css/bootstrap-theme.css')}" rel="stylesheet"/>
    <link rel="shortcut icon" href="{$csd_webui:generateURL(,'static/favicon.ico')}"/>

(:~
: This is a module conttaining configuration options for the openinfoman webap
: @version 1.0
: @see https://github.com/openhie/openinfoman @see http://ihe.net
:
:)

module namespace csd_webui = "https://github.com/openhie/openinfoman/csd_webui";
import module namespace csd_webconf =  "https://github.com/openhie/openinfoman/csd_webconf";
import module namespace request = "http://exquery.org/ns/request";

declare function csd_webui:generateURL() {
  csd_webui:generateURL(())
};

declare function csd_webui:generateURL($end) {
  let $cend :=
    functx:string-join(
      for $e in $end
      return replace(replace(string($e),'^/+',''),'/+$','')
      ,'/')

  let $cbegin :=
    if (functx:all-whitespace($csd_webconf:baseurl))
    then concat(request:scheme(),"://",request:hostname(),":",request:port())
    else replace($csd_webconf:baseurl, '/+$', '')

  return concat($cbegin,'/',$cend)

};

declare function csd_webui:nocache($response)
{(
  <rest:response>
    <http:response >
      <http:header name="Cache-Control" value="must-revalidate,no-cache,no-store"/>
    </http:response>
  </rest:response>
  ,
  $response
)};

declare function csd_webui:redirect() as element(restxq:redirect) {
  csd_webui:redirect(())
};

declare function csd_webui:redirect($end ) as element(restxq:redirect)
{
  <restxq:redirect>{ csd_webui:generateURL($end }</restxq:redirect>
};

declare function csd_webui:redirect_out() as element(restxq:redirect) {
  csd_webui:redirect_out(())
};

declare function csd_webui:redirect_out($end ) as element(restxq:redirect)
{
  db:output(<restxq:redirect>{ csd_webui:generateURL($end }</restxq:redirect>)
};

declare function csd_webui:wrapper($content) {
  csd_webui:wrapper($content,())
};

declare function csd_webui:wrapper($content,$headers) {

    <link href="{$csd_webui:generateURL('static/bootstrap/css/bootstrap.css')}" rel="stylesheet"/>
    <link href="{$csd_webui:generateURL('static/bootstrap/css/bootstrap-theme.css')}" rel="stylesheet"/>
    <link rel="shortcut icon" href="{$csd_webui:generateURL(,'static/favicon.ico')}"/>


Fixed bug where ancestor topics were generated for ancestors that don't have feeds.

svn path=/trunk/eXist-1.0/; revision=3896

<feed xmlns="http://www.w3.org/2005/Atom"
xmlns:atom="http://www.w3.org/2005/Atom">
   {
     "
",
     /atom:feed/atom:title,
     "
",
     /atom:feed/atom:id,
     "
",
     /atom:feed/atom:updated,
     "
",
     /atom:feed/atom:entry[atom:category[@scheme='http://www.smallx.com/Ontology/Atopic/2006/1/0/topic/relation' and @term='subtopic']]
   }
   {
      let $current := substring-before(base-uri(/atom:feed),'/.feed.atom'),
           $current-path := substring-after($current,'/db')
         return (
            <link rel="alternate" href="/atom/content{substring-after($current,'/db')}" type="application/atom+xml"/>,
           "
",
            let $parts := tokenize($current-path,'/')
               for $i in (1 to count($parts)-1)
                   let $apath := string-join(subsequence($parts,1,$i),'/'),
                       $feed := document(concat($apath,'/.feed.atom'))/atom:feed
                     return if ($feed and not($feed/atom:category[@scheme='http://www.smallx.com/Ontology/Atopic/2006/1/0/display' and @term='false']))
                       then (<entry>
                            {
                                "
",
                                $feed/atom:id,
                                "
",
                                $feed/atom:title,
                                "
",
                                $feed/atom:updated,
                                "
",
                                <category scheme="http://www.smallx.com/Ontology/Atopic/2006/1/0/topic/relation" term="ancestor"/>,
                                "
",
                                <link rel="alternate" href="/atom/content/{$apath}" type="application/atom+xml"/>,
                                "
",
                                <summary>
                                     {
                                         $feed/atom:subtitle/@type,
                                         $feed/atom:subtitle/node()
                                     }
                                </summary>,
                                "
"
                             }
                            </entry>,
                            "
"
                            )
                       else (),
            for $i in (collection($current)/atom:feed)
               let $path :=  substring-before(base-uri($i),'/.feed.atom'),
                   $prefix := concat($current,'/')
                  return if ($current!=$path and not(contains(substring-after($path,$prefix),'/'))
                             and not($i/atom:category[@scheme='http://www.smallx.com/Ontology/Atopic/2006/1/0/display' and @term='false']))
                     then (<entry>
                            {
                                "
",
                                $i/atom:id,
                                "
",
                                $i/atom:title,
                                "
",
                                $i/atom:updated,
                                "
",
                                <category scheme="http://www.smallx.com/Ontology/Atopic/2006/1/0/topic/relation" term="subtopic"/>,
                                "
",
                                <link rel="alternate" href="/atom/content{substring-after($path,'/db')}" type="application/atom+xml"/>,
                                "
",
                                <summary>
                                     {
                                         $i/atom:subtitle/@type,
                                         $i/atom:subtitle/node()
                                     }
                                </summary>,
                                "
"
                             }
                            </entry>,
                            "
"
                            )
                     else ()
         )
   }
</feed>

<feed xmlns="http://www.w3.org/2005/Atom"
xmlns:atom="http://www.w3.org/2005/Atom">
   {
     "
",
     /atom:feed/atom:title,
     "
",
     /atom:feed/atom:id,
     "
",
     /atom:feed/atom:updated,
     "
",
     /atom:feed/atom:entry[atom:category[@scheme='http://www.smallx.com/Ontology/Atopic/2006/1/0/topic/relation' and @term='subtopic']]
   }
   {
      let $current := substring-before(base-uri(/atom:feed),'/.feed.atom'),
           $current-path := substring-after($current,'/db')
         return (
            <link rel="alternate" href="/atom/content{substring-after($current,'/db')}" type="application/atom+xml"/>,
           "
",
            let $parts := tokenize($current-path,'/')
               for $i in (1 to count($parts)-1)
                   let $apath := string-join(subsequence($parts,1,$i),'/'),
                       $feed := document(concat($apath,'/.feed.atom'))/atom:feed
                     return if (not($feed/atom:category[@scheme='http://www.smallx.com/Ontology/Atopic/2006/1/0/display' and @term='false']))
                       then (<entry>
                            {
                                "
",
                                $feed/atom:id,
                                "
",
                                $feed/atom:title,
                                "
",
                                $feed/atom:updated,
                                "
",
                                <category scheme="http://www.smallx.com/Ontology/Atopic/2006/1/0/topic/relation" term="ancestor"/>,
                                "
",
                                <link rel="alternate" href="/atom/content/{$apath}" type="application/atom+xml"/>,
                                "
",
                                <summary>
                                     {
                                         $feed/atom:subtitle/@type,
                                         $feed/atom:subtitle/node()
                                     }
                                </summary>,
                                "
"
                             }
                            </entry>,
                            "
"
                            )
                       else (),
            for $i in (collection($current)/atom:feed)
               let $path :=  substring-before(base-uri($i),'/.feed.atom'),
                   $prefix := concat($current,'/')
                  return if ($current!=$path and not(contains(substring-after($path,$prefix),'/'))
                             and not($i/atom:category[@scheme='http://www.smallx.com/Ontology/Atopic/2006/1/0/display' and @term='false']))
                     then (<entry>
                            {
                                "
",
                                $i/atom:id,
                                "
",
                                $i/atom:title,
                                "
",
                                $i/atom:updated,
                                "
",
                                <category scheme="http://www.smallx.com/Ontology/Atopic/2006/1/0/topic/relation" term="subtopic"/>,
                                "
",
                                <link rel="alternate" href="/atom/content{substring-after($path,'/db')}" type="application/atom+xml"/>,
                                "
",
                                <summary>
                                     {
                                         $i/atom:subtitle/@type,
                                         $i/atom:subtitle/node()
                                     }
                                </summary>,
                                "
"
                             }
                            </entry>,
                            "
"
                            )
                     else ()
         )
   }
</feed>


[ignore] bibliographic demo: small fix to function callback

svn path=/trunk/eXist/; revision=12073

(:~
    jQuery module: a set of functions to extend HTML forms with AJAX
    functionality, based on the jQuery javascript library.

    Use: each function takes an XML configuration element as parameter.
    You can either call functions directly from another XQuery module
    or pass a template page to the jquery:process-templates function.
    jquery:process-templates will parse the template page and expand all
    jquery:* elements it knows.

:)
module namespace jquery="http://exist-db.org/xquery/jquery";

import module namespace util="http://exist-db.org/xquery/util";
import module namespace request="http://exist-db.org/xquery/request";
import module namespace session="http://exist-db.org/xquery/session";

declare function jquery:script($node as element()?) as xs:string? {
    string-join($node/node(), "")
};

(:~
    Outputs the HTML script and link tags which are required by jQuery.
    You need to call this function once in your HTML head.

<![CDATA[<jquery:header base="scripts/jquery" cssbase="scripts/jquery/css"/>]]>

:)
declare function jquery:header($config as element(jquery:header)) as element()* {
    let $base := $config/@base/string()
    let $cssbase := if ($config/@cssbase) then $config/@cssbase/string() else $base
    return (

            }

};

(:~
    Creates a repeatable set of form fields. Clicking the trigger will
    clone a given part of the form. The new element is inserted immediately
    after the cloned element.

    The element to be cloned should have a class 'repeat'. It can be an arbitrary
    HTML node. Form fields within the repeated element should have a name attribute
    ending with a number (usually 1), e.g. "input1", "phone1". After inserting a new
    clone, the script will change the names for all form elements in the inserted
    element. So "phone1" will become "phone2" and so on.

    The function expects a configuration element jquery:form-repeat as parameter.
    Two attributes should be specified:

form: a jQuery selector pointing to the HTML form element

trigger: a jQuery selector pointing to the HTML element on which
       the user should click to insert a new row into the form

    Example:

<jquery:form-repeat trigger="#add-field" form="#search-form"/>

    @param $config the jquery:form-repeat configuration element
:)
declare function jquery:form-repeat($config as element(jquery:form-repeat)) as element() {
    let $formSelector := $config/@form/string()
    let $trigger := $config/@trigger/string()
    let $delete := $config/@delete/string()
    let $onReady := $config/@on-ready/string()
    return

};

(:~
    Toggles an HTML block upon the click on a link or button.
    The contents of the HTML block are retrieved via AJAX from
    the URL given in attribute "href".

<![CDATA[
        <jquery:toggle href="filters.xql?type=date"
            trigger="#filters li:nth-child(3) .expand"/>
    ]]>

href: the URL to load the HTML content block from

trigger: jQuery selector pointing to the trigger element
            on which the user should click

callback: optional callback javascript function which will
            be called once the contents of the toggle block are loaded.
            The function receives the trigger element as first parameter,
            the id of the toggle block as second.

:)
declare function jquery:toggle($config as element(jquery:toggle)) as element()+ {
    let $id0 := $config/@id/string()
    let $id := if ($id0) then $id0 else util:uuid()
    let $trigger := $config/@trigger/string()
    let $href := $config/@href/string()
    let $callback := $config/@callback/string()
    let $beforeCallback := $config/@beforeCallback/string()
    return (
        if (empty($id0)) then

        else (),

    )
};

(:~
    <jquery:paginate id="results" attribute="results"
        href="retrieve" navcontainer="#results-head .navbar"/>
:)
declare function jquery:paginate($config as element(jquery:paginate)) as element()+ {
    let $hits := session:get-attribute($config/@attribute)
    let $id := if ($config/@id) then $config/@id else 'jquery-paginate'
    let $onReady := $config/@on-ready/string()
    return (

,

    )
};

(:~
    Helper function for jquery:input-field()
:)
declare function jquery:extra-params($id as xs:string, $auto as element(jquery:autocomplete)) {
    if ($auto/jquery:param) then
        string-join(
            for $param in $auto/jquery:param
            return
                concat($param/@name, ': function () { ',
                    " return ", $param/@function, '.call($("#', $id, '"));}'),
            ', '
        )
    else
        ()
};

(:~
    Create an HTML input element. Copies all attributes of the jquery:input
    element. If no value attribute is present, the function will look up the
    parameter in the HTTP request, and if the parameter is set, add it as value
    attribute.

<![CDATA[<jquery:input name="input1"/>]]>

:)
declare function jquery:input-field($node as element(jquery:input)) as element()+ {
    let $name := $node/@name/string()
    let $id := if ($node/@id) then $node/@id/string() else util:uuid()
    return (
        if ($node/jquery:autocomplete) then
            let $auto := $node/jquery:autocomplete
            let $width := if ($auto/@width) then $auto/@width/string() else 200
            let $multiple := if ($auto/@multiple) then $auto/@multiple/string() else "false"
            let $matchContains := if ($auto/@matchContains) then $auto/@matchContains/string() else "false"
            let $minLength := if ($auto/@minLength) then $auto/@minLength/string() else "3"
            return

        else
            (),
        <input>
        { $node/@* }
        { if (empty($node/@id)) then attribute id { $id } else () }
        {
            if (empty($node/@value)) then
                attribute value { request:get-parameter($name, "") }
            else
                ()
        }
        </input>
    )
};

(:~
    { jquery:extra-params($id, $auto) }
                        width: { $width },
                        minChars: 3
    Create an HTML select element. Copies all attributes of the jquery:select
    element. jquery:select should contain zero or more jquery:option elements
    which are transformed into HTML option elements. Each option must have a
    value attribute and may have an optional text content. Both are copied to
    the generated HTML option.

    For each option, the HTTP request is checked for a corresponding parameter
    value. If present, the option will be selected.

<![CDATA[
        <jquery:select name="sort">
            <jquery:option value="Author"/>
            <jquery:option value="Title"/>
            <jquery:option value="Date Issued"/>
        </jquery:select>
    ]]>

:)
declare function jquery:select-field($node as element(jquery:select)) as element() {
    let $name := $node/@name/string()
    let $value := request:get-parameter($name, "")
    return
        <select>
        { $node/@* }
        {
            for $option in $node/jquery:option
            return
                <option>
                { $option/@value }
                { if ($option/@value eq $value) then attribute selected { "selected" } else () }
                { if ($option/text()) then $option/text() else $option/@value/string() }
                </option>
        }
        </select>
};

declare function jquery:button($node as element(jquery:button)) as element()+ {
    let $id := if ($node/@id) then $node/@id/string() else util:uuid()
    return (
        <button id="{$id}">{$node/@*[not(local-name(.) = 'id')], $node/node()}</button>,

    )
};

declare function jquery:accordion($config as element(jquery:ajax-accordion)) as element()+ {
    let $id := if ($config/@id) then $config/@id else 'jquery-accordion'
    return (

        {
            for $panel in $config/jquery:panel
            return (

{$panel/@id}{$panel/@title/string()}
,

                {
                    for $child in $panel/node() return
                        jquery:process-templates($child)
                }

            )
        }

,

    )
};

declare function jquery:dialog($config as element(jquery:dialog)) as node()* {
    let $trigger := $config/@trigger
    let $id := $config/@id
    let $modal := $config/@modal = 'true'
    let $buttons :=
        string-join(
            for $button in $config/jquery:button
            return
                if ($button/@id eq 'cancel') then
                    string-join(('"', $button/@label, '": function() { $(this).dialog("close"); }'), "")
                else if ($button/@id eq 'submit') then
                    string-join(('"', $button/@label, '": function() { $("#', $id/string(), ' form").submit(); }'), "")
                else if ($button/@function) then
                    string-join(('"', $button/@label, '": function () { ', $button/@function, '($(this)); }'), "")
                else
                    string-join(('"', $button/@label, '": function() {', $button/node(), '}'), "")
            , ", ")
    return

            { $id, for $child in $config/node()[not(self::jquery:*)] return jquery:process-templates($child) }

};

(:~
    Main function to process an HTML template. All jquery:* elements
    in the template are expanded, if known.
:)
declare function jquery:process-templates($node as node()) as node()* {
    typeswitch ($node)
        case element(jquery:form-repeat) return
            jquery:form-repeat($node)
        case element(jquery:tabset) return
            jquery:tabset($node)
        case element(jquery:toggle) return
            jquery:toggle($node)
        case element(jquery:paginate) return
            jquery:paginate($node)
        case element(jquery:input) return
            jquery:input-field($node)
        case element(jquery:select) return
            jquery:select-field($node)
        case element(jquery:button) return
            jquery:button($node)
        case element(jquery:ajax-accordion) return
            jquery:accordion($node)
        case element(jquery:dialog) return
            jquery:dialog($node)
        case element(jquery:header) return
            jquery:header($node)
        case element() return
            element { node-name($node) } {
                $node/@*,
                for $child in $node/node()
                return
                    jquery:process-templates($child)
            }
        default return
            $node
};

(:~
    jQuery module: a set of functions to extend HTML forms with AJAX
    functionality, based on the jQuery javascript library.

    Use: each function takes an XML configuration element as parameter.
    You can either call functions directly from another XQuery module
    or pass a template page to the jquery:process-templates function.
    jquery:process-templates will parse the template page and expand all
    jquery:* elements it knows.

:)
module namespace jquery="http://exist-db.org/xquery/jquery";

import module namespace util="http://exist-db.org/xquery/util";
import module namespace request="http://exist-db.org/xquery/request";
import module namespace session="http://exist-db.org/xquery/session";

declare function jquery:script($node as element()?) as xs:string? {
    string-join($node/node(), "")
};

(:~
    Outputs the HTML script and link tags which are required by jQuery.
    You need to call this function once in your HTML head.

<![CDATA[<jquery:header base="scripts/jquery" cssbase="scripts/jquery/css"/>]]>

:)
declare function jquery:header($config as element(jquery:header)) as element()* {
    let $base := $config/@base/string()
    let $cssbase := if ($config/@cssbase) then $config/@cssbase/string() else $base
    return (

            }

};

(:~
    Creates a repeatable set of form fields. Clicking the trigger will
    clone a given part of the form. The new element is inserted immediately
    after the cloned element.

    The element to be cloned should have a class 'repeat'. It can be an arbitrary
    HTML node. Form fields within the repeated element should have a name attribute
    ending with a number (usually 1), e.g. "input1", "phone1". After inserting a new
    clone, the script will change the names for all form elements in the inserted
    element. So "phone1" will become "phone2" and so on.

    The function expects a configuration element jquery:form-repeat as parameter.
    Two attributes should be specified:

form: a jQuery selector pointing to the HTML form element

trigger: a jQuery selector pointing to the HTML element on which
       the user should click to insert a new row into the form

    Example:

<jquery:form-repeat trigger="#add-field" form="#search-form"/>

    @param $config the jquery:form-repeat configuration element
:)
declare function jquery:form-repeat($config as element(jquery:form-repeat)) as element() {
    let $formSelector := $config/@form/string()
    let $trigger := $config/@trigger/string()
    let $delete := $config/@delete/string()
    let $onReady := $config/@on-ready/string()
    return

};

(:~
    Toggles an HTML block upon the click on a link or button.
    The contents of the HTML block are retrieved via AJAX from
    the URL given in attribute "href".

<![CDATA[
        <jquery:toggle href="filters.xql?type=date"
            trigger="#filters li:nth-child(3) .expand"/>
    ]]>

href: the URL to load the HTML content block from

trigger: jQuery selector pointing to the trigger element
            on which the user should click

callback: optional callback javascript function which will
            be called once the contents of the toggle block are loaded.
            The function receives the trigger element as first parameter,
            the id of the toggle block as second.

:)
declare function jquery:toggle($config as element(jquery:toggle)) as element()+ {
    let $id0 := $config/@id/string()
    let $id := if ($id0) then $id0 else util:uuid()
    let $trigger := $config/@trigger/string()
    let $href := $config/@href/string()
    let $callback := $config/@callback/string()
    let $beforeCallback := $config/@beforeCallback/string()
    return (
        if (empty($id0)) then

        else (),

    )
};

(:~
    <jquery:paginate id="results" attribute="results"
        href="retrieve" navcontainer="#results-head .navbar"/>
:)
declare function jquery:paginate($config as element(jquery:paginate)) as element()+ {
    let $hits := session:get-attribute($config/@attribute)
    let $id := if ($config/@id) then $config/@id else 'jquery-paginate'
    let $onReady := $config/@on-ready/string()
    return (

,

    )
};

(:~
    Helper function for jquery:input-field()
:)
declare function jquery:extra-params($id as xs:string, $auto as element(jquery:autocomplete)) {
    if ($auto/jquery:param) then
        string-join(
            for $param in $auto/jquery:param
            return
                concat($param/@name, ': function () { ',
                    " return ", $param/@function, '.call($("#', $id, '"));}'),
            ', '
        )
    else
        ()
};

(:~
    Create an HTML input element. Copies all attributes of the jquery:input
    element. If no value attribute is present, the function will look up the
    parameter in the HTTP request, and if the parameter is set, add it as value
    attribute.

<![CDATA[<jquery:input name="input1"/>]]>

:)
declare function jquery:input-field($node as element(jquery:input)) as element()+ {
    let $name := $node/@name/string()
    let $id := if ($node/@id) then $node/@id/string() else util:uuid()
    return (
        if ($node/jquery:autocomplete) then
            let $auto := $node/jquery:autocomplete
            let $width := if ($auto/@width) then $auto/@width/string() else 200
            let $multiple := if ($auto/@multiple) then $auto/@multiple/string() else "false"
            let $matchContains := if ($auto/@matchContains) then $auto/@matchContains/string() else "false"
            let $minLength := if ($auto/@minLength) then $auto/@minLength/string() else "3"
            return

        else
            (),
        <input>
        { $node/@* }
        { if (empty($node/@id)) then attribute id { $id } else () }
        {
            if (empty($node/@value)) then
                attribute value { request:get-parameter($name, "") }
            else
                ()
        }
        </input>
    )
};

(:~
    { jquery:extra-params($id, $auto) }
                        width: { $width },
                        minChars: 3
    Create an HTML select element. Copies all attributes of the jquery:select
    element. jquery:select should contain zero or more jquery:option elements
    which are transformed into HTML option elements. Each option must have a
    value attribute and may have an optional text content. Both are copied to
    the generated HTML option.

    For each option, the HTTP request is checked for a corresponding parameter
    value. If present, the option will be selected.

<![CDATA[
        <jquery:select name="sort">
            <jquery:option value="Author"/>
            <jquery:option value="Title"/>
            <jquery:option value="Date Issued"/>
        </jquery:select>
    ]]>

:)
declare function jquery:select-field($node as element(jquery:select)) as element() {
    let $name := $node/@name/string()
    let $value := request:get-parameter($name, "")
    return
        <select>
        { $node/@* }
        {
            for $option in $node/jquery:option
            return
                <option>
                { $option/@value }
                { if ($option/@value eq $value) then attribute selected { "selected" } else () }
                { if ($option/text()) then $option/text() else $option/@value/string() }
                </option>
        }
        </select>
};

declare function jquery:button($node as element(jquery:button)) as element()+ {
    let $id := if ($node/@id) then $node/@id/string() else util:uuid()
    return (
        <button id="{$id}">{$node/@*[not(local-name(.) = 'id')], $node/node()}</button>,

    )
};

declare function jquery:accordion($config as element(jquery:ajax-accordion)) as element()+ {
    let $id := if ($config/@id) then $config/@id else 'jquery-accordion'
    return (

        {
            for $panel in $config/jquery:panel
            return (

{$panel/@id}{$panel/@title/string()}
,

                {
                    for $child in $panel/node() return
                        jquery:process-templates($child)
                }

            )
        }

,

    )
};

declare function jquery:dialog($config as element(jquery:dialog)) as node()* {
    let $trigger := $config/@trigger
    let $id := $config/@id
    let $modal := $config/@modal = 'true'
    let $buttons :=
        string-join(
            for $button in $config/jquery:button
            return
                if ($button/@id eq 'cancel') then
                    string-join(('"', $button/@label, '": function() { $("#', $id/string(), '").dialog("close"); }'), "")
                else if ($button/@id eq 'submit') then
                    string-join(('"', $button/@label, '": function() { $("#', $id/string(), ' form").submit(); }'), "")
                else if ($button/@function) then
                    string-join(('"', $button/@label, '": function () { ', $button/@function, '($("#', $id/string(), '")); }'), "")
                else
                    string-join(('"', $button/@label, '": function() {', $button/node(), '}'), "")
            , ", ")
    return

            { $id, for $child in $config/node()[not(self::jquery:*)] return jquery:process-templates($child) }

};

(:~
    Main function to process an HTML template. All jquery:* elements
    in the template are expanded, if known.
:)
declare function jquery:process-templates($node as node()) as node()* {
    typeswitch ($node)
        case element(jquery:form-repeat) return
            jquery:form-repeat($node)
        case element(jquery:tabset) return
            jquery:tabset($node)
        case element(jquery:toggle) return
            jquery:toggle($node)
        case element(jquery:paginate) return
            jquery:paginate($node)
        case element(jquery:input) return
            jquery:input-field($node)
        case element(jquery:select) return
            jquery:select-field($node)
        case element(jquery:button) return
            jquery:button($node)
        case element(jquery:ajax-accordion) return
            jquery:accordion($node)
        case element(jquery:dialog) return
            jquery:dialog($node)
        case element(jquery:header) return
            jquery:header($node)
        case element() return
            element { node-name($node) } {
                $node/@*,
                for $child in $node/node()
                return
                    jquery:process-templates($child)
            }
        default return
            $node
};


Comment fix.

Comment fix.

jsoniq version "1.0";

(:
 : Copyright 2006-2013 The FLWOR Foundation.
 :
 : Licensed under the Apache License, Version 2.0 (the "License");
 : you may not use this file except in compliance with the License.
 : You may obtain a copy of the License at
 :
 : http://www.apache.org/licenses/LICENSE-2.0
 :
 : Unless required by applicable law or agreed to in writing, software
 : distributed under the License is distributed on an "AS IS" BASIS,
 : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 : See the License for the specific language governing permissions and
 : limitations under the License.
 :)

(:===========================================================================:)

(:~
 : This module provides functions for performing FTP commands.
 :

 : @author Paul J. Lucas
 : @library cURL Library
 : @project Zorba/Input Output/FTP Client
 :)
module namespace ftp = "http://zorba.io/modules/ftp-client";

declare namespace an = "http://zorba.io/annotations";
declare namespace ver = "http://zorba.io/options/versioning";

declare option ver:module-version "1.0";

(:~
 : Attempts to connect to an FTP server specified by the given URI.
 :
 : @param $uri The address of the FTP server to connect to.
 : It may either be simple host-name
 : (ftp.example.com)
 : or a URI using the ftp
 : or ftps (FTP over SSL/TLS)
 : schemes
 : (ftp://ftp.example.com).
 : If the latter,
 : the URI may also contain
 : username,
 : password,
 : and
 : port
 : authority subcomponents
 : per RFC 3986.
 : @param $options The options to use:
 :

 :
user

 :

 :        The user to log in as;
 :        default: "ftp" (for anonymous FTP).
 :        If $uri is actually a URI instead of a simple host-name,
 :        the user, if specified, must be part of the URI
 :        and the value of this option is ignored.
 :

 :
password

 :

 :        The password to use to log in;
 :        default: "ftp@example.com" (for anonymous FTP).
 :        If $uri is actually a URI instead of a simple host-name,
 :        the password, if specified, must be part of the URI
 :        and the value of this option is ignored.
 :

 :
port

 :

 :        The port number to use;
 :        default: whatever the default for the protocol is.
 :        If $uri is actually a URI instead of a simple host-name,
 :        the port, if specified, must be part of the URI
 :        and the value of this option is ignored.
 :

 :
protocol

 :

 :        The protocol to use,
 :        either "ftp' or "ftps";
 :        default: "ftp".
 :        If $uri is actually a URI instead of a simple host-name,
 :        the protocol, if specified, must be part of the URI
 :        and the value of this option is ignored.
 :

 :
SSL-communication

 :

 :        Whether to use SSL/TLS, one of:
 :

 :
"none"

 :
Don't use SSL.

 :
"try"

 :
Try using SSL, but, if unsuccessful, continue anyway.

 :
"control"

 :
Require SSL for the control connection.

 :
"all"

 :
Require SSL for all communication.

 :

 :        default:
 :        "none" for protocol "ftp"
 :        and
 :        "all" for protocol "ftps".
 :        Note that any value other than "none"
 :        for "ftp" implies explicit SSL;
 :        use of "ftps" implies implicit SSL.
 :        See "Methods of invoking security."
 :

 :
SSL-verify

 :

 :        When doing FTP over SSL/TLS,
 :        whether to verify the authenticity of the server's certificate
 :        and that the certificate is for that server;
 :        default: true.
 :        (You should never set this to false
 :        unless you are testing your own FTP server
 :        with a self-signed certificate.)
 :

 :
trace

 :

 :        Whether to emit information to standard error
 :        tracing the communication between the FTP client and server;
 :        default: false.
 :

 :

 : @return an opaque URI that serves as a connection handle to be used with
 : other functions in this module.
 : @error ftp:ALREADY_CONNECTED if $uri is already connected to.
 : @error ftp:INVALID_ARGUMENT if any option is invalid.
 : @error ftp:FTP_ERROR if there was some other FTP error.
 :)
declare %an:sequential function
ftp:connect( $uri as string, $options as object )
  as anyURI external;

(:~
 : Deletes a file from the FTP server.
 :
 : @param $conn The opaque URI connection handle previously returned by
 : ftp:connect().
 : @param $remote-path The path of the file to delete.
 : @error ftp:INVALID_ARGUMENT if $remote-path is empty.
 : @error ftp:NOT_CONNECTED if $conn is either an invalid handle
 : or is no longer a valid handle.
 : @error ftp:FTP_ERROR if there was some other FTP error.
 :)
declare %an:sequential function
ftp:delete( $conn as string, $remote-path as string )
  external;

(:~
 : Disconnects from an FTP server.
 :
 : @param $conn The opaque URI connection handle previously returned by
 : ftp:connect().
 : After successful completion of of this function, the handle is no longer
 : valid.
 : @error ftp:NOT_CONNECTED if $conn is either an invalid handle
 : or is no longer a valid handle.
 : @error ftp:FTP_ERROR if there was some other FTP error.
 :)
declare %an:sequential function
ftp:disconnect( $conn as anyURI )
  external;

(:~
 : Gets a binary file from the FTP server.
 :
 : @param $conn The opaque URI connection handle previously returned by
 : ftp:connect().
 : @param $remote-path The path of the file to get.
 : @return the binary content of $remote-path.
 : @error ftp:INVALID_ARGUMENT if $remote-path is empty.
 : @error ftp:NOT_CONNECTED if $conn is either an invalid handle
 : or is no longer a valid handle.
 : @error ftp:FTP_ERROR if there was some other FTP error.
 :)
declare %an:sequential function
ftp:get-binary( $conn as anyURI, $remote-path as string )
  as base64Binary external;

(:~
 : Gets a text file from the FTP server.
 :
 : @param $conn The opaque URI connection handle previously returned by
 : ftp:connect().
 : @param $remote-path The path of the file to get.  It must not be empty.
 : @param $encoding The character encoding of the file.
 : @return the text content of $remote-path.
 : @error ftp:INVALID_ARGUMENT if $remote-path is empty
 : or $encoding is either an invalid or unsupported encoding.
 : @error ftp:NOT_CONNECTED if $conn is either an invalid handle
 : or is no longer a valid handle.
 : @error ftp:FTP_ERROR if there was some other FTP error.
 :)
declare %an:sequential function
ftp:get-text( $conn as anyURI, $remote-path as string, $encoding as string )
  as string external;

(:~
 : Gets a text file, presumed to be encoded in UTF-8, from the FTP server.
 :
 : @param $conn The opaque URI connection handle previously returned by
 : ftp:connect().
 : @param $remote-path The path of the file to get.  It must not be empty.
 : @return the text content of $remote-path.
 : @error ftp:INVALID_ARGUMENT if $remote-path is empty.
 : @error ftp:NOT_CONNECTED if $conn is either an invalid handle
 : or is no longer a valid handle.
 : @error ftp:FTP_ERROR if there was some other FTP error.
 :)
declare %an:sequential function
ftp:get-text( $conn as anyURI, $remote-path as string )
  as string
{
  ftp:get-text( $conn, $remote-path, "UTF-8" )
};

(:~
 : Gets a listing for a directory on an FTP server.
 :
 : @param $conn The opaque URI connection handle previously returned by
 : ftp:connect().
 : @param $remote-path The full path of the directory on the FTP server to get
 : the directory listing for.
 : An empty path is equivalent to /.
 : @return Returns a sequence of JSON objects, one per file or subdirectory in
 : the listing.
 : @error ftp:NOT_CONNECTED if $conn is either an invalid handle
 : or is no longer a valid handle.
 : @error ftp:FTP_ERROR if there was some other FTP error.
 :)
declare %an:sequential function
ftp:list( $conn as anyURI, $remote-path as string )
  as object* external;

(:~
 : Creates a directory on the FTP server.
 :
 : @param $conn The opaque URI connection handle previously returned by
 : ftp:connect().
 : @param $remote-path The path of the new directory to create.
 : @error ftp:INVALID_ARGUMENT if $remote-path is empty.
 : @error ftp:NOT_CONNECTED if $conn is either an invalid handle
 : or is no longer a valid handle.
 : @error ftp:FTP_ERROR if there was some other FTP error.
 :)
declare %an:sequential function
ftp:mkdir( $conn as string, $remote-path as string )
  external;

(:~
 : Uploads binary data to a file to the FTP server.
 :
 : @param $conn The opaque URI connection handle previously returned by
 : ftp:connect().
 : @param $binary The binary data to upload.
 : @param $remote-path The path of the file to upload to. It must not be empty.
 : @error ftp:INVALID_ARGUMENT if $remote-path is empty.
 : @error ftp:NOT_CONNECTED if $conn is either an invalid handle
 : or is no longer a valid handle.
 : @error ftp:FTP_ERROR if there was some other FTP error.
 :)
declare %an:sequential function
ftp:put-binary( $conn as anyURI, $binary as base64Binary,
                $remote-path as string )
  external;

(:~
 : Uploads text to a file to the FTP server.
 :
 : @param $conn The opaque URI connection handle previously returned by
 : ftp:connect().
 : @param $text The text to upload.
 : @param $remote-path The path of the file to upload to. It must not be empty.
 : @param $encoding The character encoding of the file.
 : @error ftp:INVALID_ARGUMENT if $remote-path is empty
 : or $encoding is either an invalid or unsupported encoding.
 : @error ftp:NOT_CONNECTED if $conn is either an invalid handle
 : or is no longer a valid handle.
 : @error ftp:FTP_ERROR if there was some other FTP error.
 :)
declare %an:sequential function
ftp:put-text( $conn as anyURI, $text as string, $remote-path as string,
              $encoding as string )
  external;

(:~
 : Uploads text to a UTF-8 encoded file on the FTP server.
 :
 : @param $conn The opaque URI connection handle previously returned by
 : ftp:connect().
 : @param $text The text to upload.
 : @param $remote-path The path of the file to upload to. It must not be empty.
 : @error ftp:INVALID_ARGUMENT if $remote-path is empty.
 : @error ftp:NOT_CONNECTED if $conn is either an invalid handle
 : or is no longer a valid handle.
 : @error ftp:FTP_ERROR if there was some other FTP error.
 :)
declare %an:sequential function
ftp:put-text( $conn as anyURI, $text as string, $remote-path as string )
{
  ftp:put-text( $conn, $text, $remote-path, "UTF-8" )
};

(:~
 : Renames a file or directory on an FTP server.
 :
 : @param $conn The opaque URI connection handle previously returned by
 : ftp:connect().
 : @param $remote-from-path The path of the file or directory to rename.
 : @param $remote-to-path The new name.
 : @error ftp:INVALID_ARGUMENT if $remote-from-path or
 : $remote-to-path is empty.
 : @error ftp:NOT_CONNECTED if $conn is either an invalid handle
 : or is no longer a valid handle.
 : @error ftp:FTP_ERROR if there was some other FTP error.
 :)
declare %an:sequential function
ftp:rename( $conn as string, $remote-from-path as string,
            $remote-to-path as string )
  external;

(:~
 : Removes a directory from the FTP server.
 :
 : @param $conn The opaque URI connection handle previously returned by
 : ftp:connect().
 : @param $remote-path The path of the directory to remove.
 : @error ftp:INVALID_ARGUMENT if $remote-path is empty.
 : @error ftp:NOT_CONNECTED if $conn is either an invalid handle
 : or is no longer a valid handle.
 : @error ftp:FTP_ERROR if there was some other FTP error.
 :)
declare %an:sequential function
ftp:rmdir( $conn as string, $remote-path as string )
  external;

(:===========================================================================:)

(: vim:set syntax=xquery et sw=2 ts=2: :)

jsoniq version "1.0";

(:
 : Copyright 2006-2013 The FLWOR Foundation.
 :
 : Licensed under the Apache License, Version 2.0 (the "License");
 : you may not use this file except in compliance with the License.
 : You may obtain a copy of the License at
 :
 : http://www.apache.org/licenses/LICENSE-2.0
 :
 : Unless required by applicable law or agreed to in writing, software
 : distributed under the License is distributed on an "AS IS" BASIS,
 : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 : See the License for the specific language governing permissions and
 : limitations under the License.
 :)

(:===========================================================================:)

(:~
 : This module provides functions for performing FTP commands.
 :

 : @author Paul J. Lucas
 : @library cURL Library
 : @project Zorba/Input Output/FTP Client
 :)
module namespace ftp = "http://zorba.io/modules/ftp-client";

declare namespace an = "http://zorba.io/annotations";
declare namespace ver = "http://zorba.io/options/versioning";

declare option ver:module-version "1.0";

(:~
 : Attempts to connect to an FTP server specified by the given URI.
 :
 : @param $uri The address of the FTP server to connect to.
 : It may either be simple host-name
 : (ftp.example.com)
 : or a URI using the ftp
 : or ftps (FTP over SSL/TLS)
 : schemes
 : (ftp://ftp.example.com).
 : If the latter,
 : the URI may also contain
 : username,
 : password,
 : and
 : port
 : authority subcomponents
 : per RFC 3986.
 : @param $options The options to use:
 :

 :
user

 :

 :        The user to log in as;
 :        default: "ftp" (for anonymous FTP).
 :        If $uri is actually a URI instead of a simple host-name,
 :        the user, if specified, must be part of the URI
 :        and the value of this option is ignored.
 :

 :
password

 :

 :        The password to use to log in;
 :        default: "ftp@example.com" (for anonymous FTP).
 :        If $uri is actually a URI instead of a simple host-name,
 :        the password, if specified, must be part of the URI
 :        and the value of this option is ignored.
 :

 :
port

 :

 :        The port number to use;
 :        default: whatever the default for the protocol is.
 :        If $uri is actually a URI instead of a simple host-name,
 :        the port, if specified, must be part of the URI
 :        and the value of this option is ignored.
 :

 :
protocol

 :

 :        The protocol to use,
 :        either "ftp' or "ftps";
 :        default: "ftp".
 :        If $uri is actually a URI instead of a simple host-name,
 :        the protocol, if specified, must be part of the URI
 :        and the value of this option is ignored.
 :

 :
SSL-communication

 :

 :        Whether to use SSL/TLS, one of:
 :

 :
"none"

 :
Don't use SSL.

 :
"try"

 :
Try using SSL, but, if unsuccessful, continue anyway.

 :
"control"

 :
Require SSL for the control connection.

 :
"all"

 :
Require SSL for all communication.

 :

 :        default:
 :        "none" for protocol "ftp"
 :        and
 :        "all" for protocol "ftps"
 :        Note that any value other than "none"
 :        for "ftp" implies explicit SSL;
 :        use of "ftps" implies implicit SSL.
 :        See "Methods of invoking security."
 :

 :
SSL-verify

 :

 :        When doing FTP over SSL/TLS,
 :        whether to verify the authenticity of the server's certificate
 :        and that the certificate is for that server;
 :        default: true.
 :        (You should never set this to false
 :        unless you are testing your own FTP server
 :        with a self-signed certificate.)
 :

 :
trace

 :

 :        Whether to emit information to standard error
 :        tracing the communication between the FTP client and server;
 :        default: false.
 :

 :

 : @return an opaque URI that serves as a connection handle to be used with
 : other functions in this module.
 : @error ftp:ALREADY_CONNECTED if $uri is already connected to.
 : @error ftp:INVALID_ARGUMENT if any option is invalid.
 : @error ftp:FTP_ERROR if there was some other FTP error.
 :)
declare %an:sequential function
ftp:connect( $uri as string, $options as object )
  as anyURI external;

(:~
 : Deletes a file from the FTP server.
 :
 : @param $conn The opaque URI connection handle previously returned by
 : ftp:connect().
 : @param $remote-path The path of the file to delete.
 : @error ftp:INVALID_ARGUMENT if $remote-path is empty.
 : @error ftp:NOT_CONNECTED if $conn is either an invalid handle
 : or is no longer a valid handle.
 : @error ftp:FTP_ERROR if there was some other FTP error.
 :)
declare %an:sequential function
ftp:delete( $conn as string, $remote-path as string )
  external;

(:~
 : Disconnects from an FTP server.
 :
 : @param $conn The opaque URI connection handle previously returned by
 : ftp:connect().
 : After successful completion of of this function, the handle is no longer
 : valid.
 : @error ftp:NOT_CONNECTED if $conn is either an invalid handle
 : or is no longer a valid handle.
 : @error ftp:FTP_ERROR if there was some other FTP error.
 :)
declare %an:sequential function
ftp:disconnect( $conn as anyURI )
  external;

(:~
 : Gets a binary file from the FTP server.
 :
 : @param $conn The opaque URI connection handle previously returned by
 : ftp:connect().
 : @param $remote-path The path of the file to get.
 : @return the binary content of $remote-path.
 : @error ftp:INVALID_ARGUMENT if $remote-path is empty.
 : @error ftp:NOT_CONNECTED if $conn is either an invalid handle
 : or is no longer a valid handle.
 : @error ftp:FTP_ERROR if there was some other FTP error.
 :)
declare %an:sequential function
ftp:get-binary( $conn as anyURI, $remote-path as string )
  as base64Binary external;

(:~
 : Gets a text file from the FTP server.
 :
 : @param $conn The opaque URI connection handle previously returned by
 : ftp:connect().
 : @param $remote-path The path of the file to get.  It must not be empty.
 : @param $encoding The character encoding of the file.
 : @return the text content of $remote-path.
 : @error ftp:INVALID_ARGUMENT if $remote-path is empty
 : or $encoding is either an invalid or unsupported encoding.
 : @error ftp:NOT_CONNECTED if $conn is either an invalid handle
 : or is no longer a valid handle.
 : @error ftp:FTP_ERROR if there was some other FTP error.
 :)
declare %an:sequential function
ftp:get-text( $conn as anyURI, $remote-path as string, $encoding as string )
  as string external;

(:~
 : Gets a text file, presumed to be encoded in UTF-8, from the FTP server.
 :
 : @param $conn The opaque URI connection handle previously returned by
 : ftp:connect().
 : @param $remote-path The path of the file to get.  It must not be empty.
 : @return the text content of $remote-path.
 : @error ftp:INVALID_ARGUMENT if $remote-path is empty.
 : @error ftp:NOT_CONNECTED if $conn is either an invalid handle
 : or is no longer a valid handle.
 : @error ftp:FTP_ERROR if there was some other FTP error.
 :)
declare %an:sequential function
ftp:get-text( $conn as anyURI, $remote-path as string )
  as string
{
  ftp:get-text( $conn, $remote-path, "UTF-8" )
};

(:~
 : Gets a listing for a directory on an FTP server.
 :
 : @param $conn The opaque URI connection handle previously returned by
 : ftp:connect().
 : @param $remote-path The full path of the directory on the FTP server to get
 : the directory listing for.
 : An empty path is equivalent to /.
 : @return Returns a sequence of JSON objects, one per file or subdirectory in
 : the listing.
 : @error ftp:NOT_CONNECTED if $conn is either an invalid handle
 : or is no longer a valid handle.
 : @error ftp:FTP_ERROR if there was some other FTP error.
 :)
declare %an:sequential function
ftp:list( $conn as anyURI, $remote-path as string )
  as object* external;

(:~
 : Creates a directory on the FTP server.
 :
 : @param $conn The opaque URI connection handle previously returned by
 : ftp:connect().
 : @param $remote-path The path of the new directory to create.
 : @error ftp:INVALID_ARGUMENT if $remote-path is empty.
 : @error ftp:NOT_CONNECTED if $conn is either an invalid handle
 : or is no longer a valid handle.
 : @error ftp:FTP_ERROR if there was some other FTP error.
 :)
declare %an:sequential function
ftp:mkdir( $conn as string, $remote-path as string )
  external;

(:~
 : Uploads binary data to a file to the FTP server.
 :
 : @param $conn The opaque URI connection handle previously returned by
 : ftp:connect().
 : @param $binary The binary data to upload.
 : @param $remote-path The path of the file to upload to. It must not be empty.
 : @error ftp:INVALID_ARGUMENT if $remote-path is empty.
 : @error ftp:NOT_CONNECTED if $conn is either an invalid handle
 : or is no longer a valid handle.
 : @error ftp:FTP_ERROR if there was some other FTP error.
 :)
declare %an:sequential function
ftp:put-binary( $conn as anyURI, $binary as base64Binary,
                $remote-path as string )
  external;

(:~
 : Uploads text to a file to the FTP server.
 :
 : @param $conn The opaque URI connection handle previously returned by
 : ftp:connect().
 : @param $text The text to upload.
 : @param $remote-path The path of the file to upload to. It must not be empty.
 : @param $encoding The character encoding of the file.
 : @error ftp:INVALID_ARGUMENT if $remote-path is empty
 : or $encoding is either an invalid or unsupported encoding.
 : @error ftp:NOT_CONNECTED if $conn is either an invalid handle
 : or is no longer a valid handle.
 : @error ftp:FTP_ERROR if there was some other FTP error.
 :)
declare %an:sequential function
ftp:put-text( $conn as anyURI, $text as string, $remote-path as string,
              $encoding as string )
  external;

(:~
 : Uploads text to a UTF-8 encoded file on the FTP server.
 :
 : @param $conn The opaque URI connection handle previously returned by
 : ftp:connect().
 : @param $text The text to upload.
 : @param $remote-path The path of the file to upload to. It must not be empty.
 : @error ftp:INVALID_ARGUMENT if $remote-path is empty.
 : @error ftp:NOT_CONNECTED if $conn is either an invalid handle
 : or is no longer a valid handle.
 : @error ftp:FTP_ERROR if there was some other FTP error.
 :)
declare %an:sequential function
ftp:put-text( $conn as anyURI, $text as string, $remote-path as string )
{
  ftp:put-text( $conn, $text, $remote-path, "UTF-8" )
};

(:~
 : Renames a file or directory on an FTP server.
 :
 : @param $conn The opaque URI connection handle previously returned by
 : ftp:connect().
 : @param $remote-from-path The path of the file or directory to rename.
 : @param $remote-to-path The new name.
 : @error ftp:INVALID_ARGUMENT if $remote-from-path or
 : $remote-to-path is empty.
 : @error ftp:NOT_CONNECTED if $conn is either an invalid handle
 : or is no longer a valid handle.
 : @error ftp:FTP_ERROR if there was some other FTP error.
 :)
declare %an:sequential function
ftp:rename( $conn as string, $remote-from-path as string,
            $remote-to-path as string )
  external;

(:~
 : Removes a directory from the FTP server.
 :
 : @param $conn The opaque URI connection handle previously returned by
 : ftp:connect().
 : @param $remote-path The path of the directory to remove.
 : @error ftp:INVALID_ARGUMENT if $remote-path is empty.
 : @error ftp:NOT_CONNECTED if $conn is either an invalid handle
 : or is no longer a valid handle.
 : @error ftp:FTP_ERROR if there was some other FTP error.
 :)
declare %an:sequential function
ftp:rmdir( $conn as string, $remote-path as string )
  external;

(:===========================================================================:)

(: vim:set syntax=xquery et sw=2 ts=2: :)


removed unreferenced library csd_proc

removed unreferenced library csd_proc

(:~
: This is the Care Services Discovery RESTful document processor
: @version 1.0
: @see https://github.com/openhie/openinfoman
:
:)
module namespace csr_proc = "https://github.com/openhie/openinfoman/csr_proc";

import module namespace csd_dm = "https://github.com/openhie/openinfoman/csd_dm";

declare   namespace   csd = "urn:ihe:iti:csd:2013";
declare namespace xquery = "http://basex.org/modules/xquery";

(:this should proabably be moved to the database :)
declare variable $csr_proc:stored_query_dir := concat(file:current-dir() , "../resources/stored_query_definitions");
declare variable $csr_proc:stored_updating_query_dir := concat(file:current-dir() , "../resources/stored_updating_query_definitions");

declare variable $csr_proc:stored_functions_doc := 'stored_functions.xml';
declare variable $csr_proc:stored_updating_functions_doc := 'stored_updating_functions.xml';

declare function csr_proc:stored_functions($db) {
 db:open($db,$csr_proc:stored_functions_doc)/careServicesFunctions/csd:careServicesFunction
};

declare function csr_proc:stored_updating_functions($db) {
 db:open($db,$csr_proc:stored_updating_functions_doc)/careServicesFunctions/csd:careServicesFunction
};

declare updating function csr_proc:init($db) {
  (
    if (not (db:is-xml($db,$csr_proc:stored_updating_functions_doc))) then
      db:add($db, <careServicesFunctions/>,$csr_proc:stored_updating_functions_doc)
    else
      ()
      ,
    if (not (db:is-xml($db,$csr_proc:stored_functions_doc))) then
      db:add($db, <careServicesFunctions/>,$csr_proc:stored_functions_doc)
    else
      ()
  )
};

declare updating function csr_proc:clear_stored_functions($db) {
  (
    db:delete($db,$csr_proc:stored_functions_doc)
    ,db:delete($db,$csr_proc:stored_updating_functions_doc)
    ,csr_proc:init($db)
    )

};

declare updating function csr_proc:load_functions_from_files($db) {
  (
    if (file:is-dir($csr_proc:stored_query_dir)) then
      for $file in file:list($csr_proc:stored_query_dir,boolean('false'),"*.xml")
      let $func := doc(concat($csr_proc:stored_query_dir,'/',$file))/csd:careServicesFunction
      return if (exists($func)) then csr_proc:load_stored_function($db,$func) else ()
    else()
      ,
    if (file:is-dir($csr_proc:stored_updating_query_dir)) then
      for $file in file:list($csr_proc:stored_updating_query_dir,boolean('false'),"*.xml")
      let $func := doc(concat($csr_proc:stored_updating_query_dir,'/',$file))/csd:careServicesFunction
      return if (exists($func)) then csr_proc:load_stored_updating_function($db,$func) else ()
    else ()
  )
};

declare updating function csr_proc:delete_stored_function($db,$urn) {
  let $stored_updating_functions := db:open($db,$csr_proc:stored_updating_functions_doc)/careServicesFunctions/*
  let $stored_functions := db:open($db,$csr_proc:stored_functions_doc)/careServicesFunctions/*
  let $functions := ($stored_functions,$stored_updating_functions)

  let $old := $functions[@urn = $urn]
  return if ($old) then delete node $old else ()

};

declare updating function csr_proc:load_stored_updating_function($db,$func) {
  let $stored_updating_functions := db:open($db,$csr_proc:stored_updating_functions_doc)/careServicesFunctions
  let $urn := $func/@urn
  let $old := $stored_updating_functions/csd:careServicesFunction[@urn = $urn]
  return
    if (exists($urn)) then
      if (exists($old))
	then
	(delete node $old,
	insert node $func into $stored_updating_functions
	)
      else
	insert node $func into $stored_updating_functions
  else ()
};

declare updating function csr_proc:load_stored_function($db,$func) {
  let $stored_functions := db:open($db,$csr_proc:stored_functions_doc)/careServicesFunctions
  let $urn := $func/@urn
  let $old := $stored_functions/csd:careServicesFunction[@urn = $urn]
  return
    if (exists($urn) and exists($stored_functions)) then
      if (exists($old))
	then
	(delete node $old,
	insert node $func into $stored_functions
	)
      else
	insert node $func into $stored_functions
    else ()
};

declare function csr_proc:process_CSR($db,$careServicesRequest, $doc_name,$base_url)
{
csr_proc:process_CSR($db,$careServicesRequest, $doc_name, $base_url,map:merge(()))
};

declare function csr_proc:process_CSR($db,$careServicesRequest, $doc_name,$base_url,$bindings as map(*))
{
let $function :=$careServicesRequest/csd:function
let $adhoc :=$careServicesRequest/csd:expression
return if (exists($function))
then
  let $urn := string($function/@urn)
  return
    if ($urn = 'urn:ihe:iti:csd:2014:adhoc')
    then
      csr_proc:process_CSR_adhoc($db,$careServicesRequest/csd:function,$doc_name,$bindings)
    else
      let $csr :=
      <csd:careServicesRequest>
	<csd:function urn="{$urn}" resource='{$doc_name}' base_url='{$base_url}'>
	  {($function/*)[1]}
	</csd:function>
      </csd:careServicesRequest>
      return csr_proc:process_CSR_stored($db,$csr,$bindings)
else if (exists($adhoc))
then
  csr_proc:process_CSR_adhoc($db,$adhoc,$doc_name,$bindings)
else
 (:
  <rest:response>
    <http:response status="400" message="Invalid care services request.">
      <http:header name="Content-Language" value="en"/>
      <http:header name="Content-Type" value="text/html; charset=utf-8"/>
    </http:response>
  </rest:response>
  :)
  $careServicesRequest

};

declare function csr_proc:process_CSR_adhoc($db,$expression,$doc_name) {
   csr_proc:process_CSR_adhoc($expression,$doc_name,map:merge(()))
};

declare function csr_proc:process_CSR_adhoc($db,$expression,$doc_name,$bindings as map(*))
{

let $doc :=  csd_dm:open_document($db,$doc_name)

let $expr :=string($expression)
return if ($expr) then
  let $result := xquery:eval($expr,map{"":$doc},$bindings)
  return(
   <rest:response>
   <http:response status="200" >
      <http:header name="Content-Type" value="{$expression/@content-type}"/>
    </http:response>
  </rest:response>
  ,$result
 )
else
   <rest:response>
     <http:response status="400" message="No ad-hoc expression" />
  </rest:response>
};

declare function csr_proc:process_CSR_stored($db,$careServicesRequest)
{
  csr_proc:process_CSR_stored($db,$careServicesRequest,map:merge(()))
};

declare function csr_proc:process_CSR_stored($db,$careServicesRequest,$bindings as map(*))
{
let $function :=$careServicesRequest/csd:function
let $stored_functions := csr_proc:stored_functions($db)
let $urn := string($function/@urn)
let $definition := ($stored_functions[@urn = $urn])[1]/csd:definition/text()
let $content_type := csr_proc:lookup_stored_content_type($db,$function/@urn)
let $doc_name := string($function/@resource)
let $doc :=  csd_dm:open_document($db,$doc_name)

let $results0 := csr_proc:process_CSR_stored_results($db,$doc,$careServicesRequest,$bindings)

return if (exists($definition)) then
  let $results1:=
    if ($function/@encapsulated) then
      csr_proc:wrap_result($results0,$content_type)
    else $results0
  return
    (
    <rest:response>
      <http:response status="200" >
	<http:header name="Content-Type" value="{$content_type}"/>
      </http:response>
    </rest:response>
    ,
    $results1
    )
else
  <rest:response>
    <http:response status="404" message="No registered function with URN='{$function/@urn}'.">
      <http:header name="Content-Language" value="en"/>
      <http:header name="Content-Type" value="text/html; charset=utf-8"/>
    </http:response>
  </rest:response>
};

declare function csr_proc:wrap_result($result,$content-type) {
 <csd:careServicesResponse content-type="{$content-type}"><csd:result>{$result}</csd:result></csd:careServicesResponse>
};

declare function csr_proc:process_CSR_stored_results($db,$doc,$careServicesRequest)
{
  csr_proc:process_CSR_stored_results($db,$doc,$careServicesRequest,map:merge(()))
};

declare function csr_proc:process_CSR_stored_results($db,$doc,$careServicesRequest,$bindings as map(*))
{
let $function :=
  if (exists($careServicesRequest/csd:function ))
  then $careServicesRequest/csd:function
  else $careServicesRequest

let $urn :=
  if (exists($careServicesRequest/csd:function ))
  then string($function/@urn)
  else string($function/@function)

let $doc_name :=  string($function/@resource)
let $base_url :=  string($function/@base_url)

let $stored_functions := csr_proc:stored_functions($db)
let $definition := ($stored_functions[@urn = $urn])[1]/csd:definition/text()

let $options := csr_proc:lookup_stored_options($db,$function/@urn)

let $requestParams :=
 <csd:requestParams resource='{$doc_name}' function='{$urn}' base_url='{$base_url}'>
   {
     if ($function/csd:requestParams) then $function/csd:requestParams/*
   else $function/requestParams/*
   }
 </csd:requestParams>

let $csr_bindings :=  map{'':$doc,'careServicesRequest':$requestParams}
let $all_bindings :=  map:merge(($csr_bindings, $bindings))

return if (exists($definition)) then
  xquery:eval($definition,$all_bindings,$options)
else ()
};

declare function csr_proc:create_adhoc_doc($adhoc_query,$content_type) {
let $content := if ($content_type) then $content_type else "application/xml"
return
 <csd:careServicesRequest xmlns:csd='urn:ihe:iti:csd:2013'>
  <csd:expression content-type='{$content}'>
  {$adhoc_query}
  </csd:expression>
</csd:careServicesRequest>

};

declare function csr_proc:get_function_definition($db,$urn) {
  csr_proc:stored_functions($db)[@urn = $urn][1]
};

declare function csr_proc:get_updating_function_definition($db,$urn) {
  csr_proc:stored_updating_functions($db)[@urn = $urn][1]
};

declare function csr_proc:get_any_function_definition($db,$urn) {
  (csr_proc:stored_updating_functions($db)[@urn = $urn] , csr_proc:stored_functions($db)[@urn = $urn])[1]
};

declare updating function csr_proc:process_updating_CSR($db,$function,$doc_name,$base_url)
{
  csr_proc:process_updating_CSR($db,$function,$doc_name,$base_url,map:merge(()))
};

declare updating function csr_proc:process_updating_CSR_results($db,$function)
{
  csr_proc:process_updating_CSR_results($db,$function,map:merge(()))
};

declare updating function csr_proc:process_updating_CSR_results($db,$careServicesRequest, $bindings as map(*)) {
let $function :=$careServicesRequest//csd:function
let $doc_name := string($function/@resource)
let $base_url := string($function/@base_url)
let $doc := csd_dm:open_document($db,$doc_name)
let $urn := $function/@urn
let $stored_updating_functions := csr_proc:stored_updating_functions($db)
let $definition := $stored_updating_functions[@urn = $urn][1]/csd:definition/text()
let $content_type := csr_proc:lookup_stored_content_type($db,$function/@urn)
let $requestParams := <csd:requestParams resource='{$doc_name}' function='{$urn}' base_url='{$base_url}'>
  {
    if ($function/csd:requestParams) then $function/csd:requestParams/*
    else $function/requestParams/*
  }
</csd:requestParams>

let $csr_bindings :=  map{'':$doc,'careServicesRequest':$requestParams}
let $all_bindings :=  map:merge(($csr_bindings, $bindings))

let $options := csr_proc:lookup_stored_options($db,$function/@urn)

return if (exists($definition)) then
  (
  xquery:update($definition,$all_bindings,$options)
  )
else  ()

};

declare updating function csr_proc:process_updating_CSR_stored_results($db,$doc,$careServicesRequest)
{
  csr_proc:process_updating_CSR_stored_results($db,$doc,$careServicesRequest,map:merge(()))
};

declare updating function csr_proc:process_updating_CSR_stored_results($db,$doc,$careServicesRequest,$bindings as map(*))
{
let $stored_updating_functions := csr_proc:stored_updating_functions($db)

let $csr_bindings :=  map{'':$doc,'careServicesRequest':$careServicesRequest}
let $all_bindings :=  map:merge(($csr_bindings, $bindings))
let $function := $careServicesRequest/@function
let $options := csr_proc:lookup_stored_options($db,$function)
let $definition := $stored_updating_functions[@urn = $function][1]/csd:definition/text()
let $out := serialize($careServicesRequest)
return if (exists($definition)) then
  xquery:update($definition,$all_bindings,$options)
else
    db:output(
    <rest:response>
      <http:response status="404" message="No registered updating function with URN='{$function}'">
	<http:header name="Content-Language" value="en"/>
	<http:header name="Content-Type" value="text/html; charset=utf-8"/>
      </http:response>
    </rest:response>
       )
};

declare updating function csr_proc:process_updating_CSR($db,$careServicesRequest, $doc_name, $base_url,$bindings as map(*))
{

let $doc := csd_dm:open_document($db,$doc_name)
let $function := ($careServicesRequest//csd:function)[1]
let $urn := string($function/@urn)
let $content_type := csr_proc:lookup_stored_content_type($db,$function/@urn)
let $requestParams := <csd:requestParams resource="{$doc_name}" function="{$urn}" base_url="{$base_url}">
  {
    if (exists($function/csd:requestParams)) then $function/csd:requestParams/*
    else $function/requestParams/*
  }
</csd:requestParams>
return csr_proc:process_updating_CSR_stored_results($db,$doc,$requestParams,$bindings)
};

declare function csr_proc:lookup_stored_options($db,$urn)
{
  let $stored_updating_functions := csr_proc:stored_updating_functions($db)
  let $stored_functions := csr_proc:stored_functions($db)
  let $func := ($stored_functions[@urn = $urn], $stored_updating_functions[@urn = $urn])[1]
   return  ($func/csd:extension[@urn='urn:openhie.org:openinfoman:csr_processor' and  @type='xquery:options']/xquery:options)[1]
     (: See: http://docs.basex.org/wiki/XQuery_Module :)
};

declare function csr_proc:lookup_stored_content_type($db,$urn)
{
  let $stored_updating_functions := csr_proc:stored_updating_functions($db)
  let $stored_functions := csr_proc:stored_functions($db)
  return string(($stored_functions[@urn = $urn]/@content-type, $stored_updating_functions[@urn = $urn]/@content-type  , "text/xml")[1])
};

(:~
: This is the Care Services Discovery RESTful document processor
: @version 1.0
: @see https://github.com/openhie/openinfoman
:
:)
module namespace csr_proc = "https://github.com/openhie/openinfoman/csr_proc";

import module namespace csd_dm = "https://github.com/openhie/openinfoman/csd_dm";
import module namespace csd_mcs = "https://github.com/openhie/openinfoman/csd_mcs";

declare   namespace   csd = "urn:ihe:iti:csd:2013";
declare namespace xquery = "http://basex.org/modules/xquery";

(:this should proabably be moved to the database :)
declare variable $csr_proc:stored_query_dir := concat(file:current-dir() , "../resources/stored_query_definitions");
declare variable $csr_proc:stored_updating_query_dir := concat(file:current-dir() , "../resources/stored_updating_query_definitions");

declare variable $csr_proc:stored_functions_doc := 'stored_functions.xml';
declare variable $csr_proc:stored_updating_functions_doc := 'stored_updating_functions.xml';

declare function csr_proc:stored_functions($db) {
 db:open($db,$csr_proc:stored_functions_doc)/careServicesFunctions/csd:careServicesFunction
};

declare function csr_proc:stored_updating_functions($db) {
 db:open($db,$csr_proc:stored_updating_functions_doc)/careServicesFunctions/csd:careServicesFunction
};

declare updating function csr_proc:init($db) {
  (
    if (not (db:is-xml($db,$csr_proc:stored_updating_functions_doc))) then
      db:add($db, <careServicesFunctions/>,$csr_proc:stored_updating_functions_doc)
    else
      ()
      ,
    if (not (db:is-xml($db,$csr_proc:stored_functions_doc))) then
      db:add($db, <careServicesFunctions/>,$csr_proc:stored_functions_doc)
    else
      ()
  )
};

declare updating function csr_proc:clear_stored_functions($db) {
  (
    db:delete($db,$csr_proc:stored_functions_doc)
    ,db:delete($db,$csr_proc:stored_updating_functions_doc)
    ,csr_proc:init($db)
    )

};

declare updating function csr_proc:load_functions_from_files($db) {
  (
    if (file:is-dir($csr_proc:stored_query_dir)) then
      for $file in file:list($csr_proc:stored_query_dir,boolean('false'),"*.xml")
      let $func := doc(concat($csr_proc:stored_query_dir,'/',$file))/csd:careServicesFunction
      return if (exists($func)) then csr_proc:load_stored_function($db,$func) else ()
    else()
      ,
    if (file:is-dir($csr_proc:stored_updating_query_dir)) then
      for $file in file:list($csr_proc:stored_updating_query_dir,boolean('false'),"*.xml")
      let $func := doc(concat($csr_proc:stored_updating_query_dir,'/',$file))/csd:careServicesFunction
      return if (exists($func)) then csr_proc:load_stored_updating_function($db,$func) else ()
    else ()
  )
};

declare updating function csr_proc:delete_stored_function($db,$urn) {
  let $stored_updating_functions := db:open($db,$csr_proc:stored_updating_functions_doc)/careServicesFunctions/*
  let $stored_functions := db:open($db,$csr_proc:stored_functions_doc)/careServicesFunctions/*
  let $functions := ($stored_functions,$stored_updating_functions)

  let $old := $functions[@urn = $urn]
  return if ($old) then delete node $old else ()

};

declare updating function csr_proc:load_stored_updating_function($db,$func) {
  let $stored_updating_functions := db:open($db,$csr_proc:stored_updating_functions_doc)/careServicesFunctions
  let $urn := $func/@urn
  let $old := $stored_updating_functions/csd:careServicesFunction[@urn = $urn]
  return
    if (exists($urn)) then
      if (exists($old))
	then
	(delete node $old,
	insert node $func into $stored_updating_functions
	)
      else
	insert node $func into $stored_updating_functions
  else ()
};

declare updating function csr_proc:load_stored_function($db,$func) {
  let $stored_functions := db:open($db,$csr_proc:stored_functions_doc)/careServicesFunctions
  let $urn := $func/@urn
  let $old := $stored_functions/csd:careServicesFunction[@urn = $urn]
  return
    if (exists($urn) and exists($stored_functions)) then
      if (exists($old))
	then
	(delete node $old,
	insert node $func into $stored_functions
	)
      else
	insert node $func into $stored_functions
    else ()
};

declare function csr_proc:process_CSR($db,$careServicesRequest, $doc_name,$base_url)
{
csr_proc:process_CSR($db,$careServicesRequest, $doc_name, $base_url,map:merge(()))
};

declare function csr_proc:process_CSR($db,$careServicesRequest, $doc_name,$base_url,$bindings as map(*))
{
let $function :=$careServicesRequest/csd:function
let $adhoc :=$careServicesRequest/csd:expression
return if (exists($function))
then
  let $urn := string($function/@urn)
  return
    if ($urn = 'urn:ihe:iti:csd:2014:adhoc')
    then
      csr_proc:process_CSR_adhoc($db,$careServicesRequest/csd:function,$doc_name,$bindings)
    else
      let $csr :=
      <csd:careServicesRequest>
	<csd:function urn="{$urn}" resource='{$doc_name}' base_url='{$base_url}'>
	  {($function/*)[1]}
	</csd:function>
      </csd:careServicesRequest>
      return csr_proc:process_CSR_stored($db,$csr,$bindings)
else if (exists($adhoc))
then
  csr_proc:process_CSR_adhoc($db,$adhoc,$doc_name,$bindings)
else
 (:
  <rest:response>
    <http:response status="400" message="Invalid care services request.">
      <http:header name="Content-Language" value="en"/>
      <http:header name="Content-Type" value="text/html; charset=utf-8"/>
    </http:response>
  </rest:response>
  :)
  $careServicesRequest

};

declare function csr_proc:process_CSR_adhoc($db,$expression,$doc_name) {
   csr_proc:process_CSR_adhoc($expression,$doc_name,map:merge(()))
};

declare function csr_proc:process_CSR_adhoc($db,$expression,$doc_name,$bindings as map(*))
{

let $doc :=  csd_dm:open_document($db,$doc_name)

let $expr :=string($expression)
return if ($expr) then
  let $result := xquery:eval($expr,map{"":$doc},$bindings)
  return(
   <rest:response>
   <http:response status="200" >
      <http:header name="Content-Type" value="{$expression/@content-type}"/>
    </http:response>
  </rest:response>
  ,$result
 )
else
   <rest:response>
     <http:response status="400" message="No ad-hoc expression" />
  </rest:response>
};

declare function csr_proc:process_CSR_stored($db,$careServicesRequest)
{
  csr_proc:process_CSR_stored($db,$careServicesRequest,map:merge(()))
};

declare function csr_proc:process_CSR_stored($db,$careServicesRequest,$bindings as map(*))
{
let $function :=$careServicesRequest/csd:function
let $stored_functions := csr_proc:stored_functions($db)
let $urn := string($function/@urn)
let $definition := ($stored_functions[@urn = $urn])[1]/csd:definition/text()
let $content_type := csr_proc:lookup_stored_content_type($db,$function/@urn)
let $doc_name := string($function/@resource)
let $doc :=  csd_dm:open_document($db,$doc_name)

let $results0 := csr_proc:process_CSR_stored_results($db,$doc,$careServicesRequest,$bindings)

return if (exists($definition)) then
  let $results1:=
    if ($function/@encapsulated) then
      csr_proc:wrap_result($results0,$content_type)
    else $results0
  return
    (
    <rest:response>
      <http:response status="200" >
	<http:header name="Content-Type" value="{$content_type}"/>
      </http:response>
    </rest:response>
    ,
    $results1
    )
else
  <rest:response>
    <http:response status="404" message="No registered function with URN='{$function/@urn}'.">
      <http:header name="Content-Language" value="en"/>
      <http:header name="Content-Type" value="text/html; charset=utf-8"/>
    </http:response>
  </rest:response>
};

declare function csr_proc:wrap_result($result,$content-type) {
 <csd:careServicesResponse content-type="{$content-type}"><csd:result>{$result}</csd:result></csd:careServicesResponse>
};

declare function csr_proc:process_CSR_stored_results($db,$doc,$careServicesRequest)
{
  csr_proc:process_CSR_stored_results($db,$doc,$careServicesRequest,map:merge(()))
};

declare function csr_proc:process_CSR_stored_results($db,$doc,$careServicesRequest,$bindings as map(*))
{
let $function :=
  if (exists($careServicesRequest/csd:function ))
  then $careServicesRequest/csd:function
  else $careServicesRequest

let $urn :=
  if (exists($careServicesRequest/csd:function ))
  then string($function/@urn)
  else string($function/@function)

let $doc_name :=  string($function/@resource)
let $base_url :=  string($function/@base_url)

let $stored_functions := csr_proc:stored_functions($db)
let $definition := ($stored_functions[@urn = $urn])[1]/csd:definition/text()

let $options := csr_proc:lookup_stored_options($db,$function/@urn)

let $requestParams :=
 <csd:requestParams resource='{$doc_name}' function='{$urn}' base_url='{$base_url}'>
   {
     if ($function/csd:requestParams) then $function/csd:requestParams/*
   else $function/requestParams/*
   }
 </csd:requestParams>

let $csr_bindings :=  map{'':$doc,'careServicesRequest':$requestParams}
let $all_bindings :=  map:merge(($csr_bindings, $bindings))

return if (exists($definition)) then
  xquery:eval($definition,$all_bindings,$options)
else ()
};

declare function csr_proc:create_adhoc_doc($adhoc_query,$content_type) {
let $content := if ($content_type) then $content_type else "application/xml"
return
 <csd:careServicesRequest xmlns:csd='urn:ihe:iti:csd:2013'>
  <csd:expression content-type='{$content}'>
  {$adhoc_query}
  </csd:expression>
</csd:careServicesRequest>

};

declare function csr_proc:get_function_definition($db,$urn) {
  csr_proc:stored_functions($db)[@urn = $urn][1]
};

declare function csr_proc:get_updating_function_definition($db,$urn) {
  csr_proc:stored_updating_functions($db)[@urn = $urn][1]
};

declare function csr_proc:get_any_function_definition($db,$urn) {
  (csr_proc:stored_updating_functions($db)[@urn = $urn] , csr_proc:stored_functions($db)[@urn = $urn])[1]
};

declare updating function csr_proc:process_updating_CSR($db,$function,$doc_name,$base_url)
{
  csr_proc:process_updating_CSR($db,$function,$doc_name,$base_url,map:merge(()))
};

declare updating function csr_proc:process_updating_CSR_results($db,$function)
{
  csr_proc:process_updating_CSR_results($db,$function,map:merge(()))
};

declare updating function csr_proc:process_updating_CSR_results($db,$careServicesRequest, $bindings as map(*)) {
let $function :=$careServicesRequest//csd:function
let $doc_name := string($function/@resource)
let $base_url := string($function/@base_url)
let $doc := csd_dm:open_document($db,$doc_name)
let $urn := $function/@urn
let $stored_updating_functions := csr_proc:stored_updating_functions($db)
let $definition := $stored_updating_functions[@urn = $urn][1]/csd:definition/text()
let $content_type := csr_proc:lookup_stored_content_type($db,$function/@urn)
let $requestParams := <csd:requestParams resource='{$doc_name}' function='{$urn}' base_url='{$base_url}'>
  {
    if ($function/csd:requestParams) then $function/csd:requestParams/*
    else $function/requestParams/*
  }
</csd:requestParams>

let $csr_bindings :=  map{'':$doc,'careServicesRequest':$requestParams}
let $all_bindings :=  map:merge(($csr_bindings, $bindings))

let $options := csr_proc:lookup_stored_options($db,$function/@urn)

return if (exists($definition)) then
  (
  xquery:update($definition,$all_bindings,$options)
  )
else  ()

};

declare updating function csr_proc:process_updating_CSR_stored_results($db,$doc,$careServicesRequest)
{
  csr_proc:process_updating_CSR_stored_results($db,$doc,$careServicesRequest,map:merge(()))
};

declare updating function csr_proc:process_updating_CSR_stored_results($db,$doc,$careServicesRequest,$bindings as map(*))
{
let $stored_updating_functions := csr_proc:stored_updating_functions($db)

let $csr_bindings :=  map{'':$doc,'careServicesRequest':$careServicesRequest}
let $all_bindings :=  map:merge(($csr_bindings, $bindings))
let $function := $careServicesRequest/@function
let $options := csr_proc:lookup_stored_options($db,$function)
let $definition := $stored_updating_functions[@urn = $function][1]/csd:definition/text()
let $out := serialize($careServicesRequest)
return if (exists($definition)) then
  xquery:update($definition,$all_bindings,$options)
else
    db:output(
    <rest:response>
      <http:response status="404" message="No registered updating function with URN='{$function}'">
	<http:header name="Content-Language" value="en"/>
	<http:header name="Content-Type" value="text/html; charset=utf-8"/>
      </http:response>
    </rest:response>
       )
};

declare updating function csr_proc:process_updating_CSR($db,$careServicesRequest, $doc_name, $base_url,$bindings as map(*))
{

let $doc := csd_dm:open_document($db,$doc_name)
let $function := ($careServicesRequest//csd:function)[1]
let $urn := string($function/@urn)
let $content_type := csr_proc:lookup_stored_content_type($db,$function/@urn)
let $requestParams := <csd:requestParams resource="{$doc_name}" function="{$urn}" base_url="{$base_url}">
  {
    if (exists($function/csd:requestParams)) then $function/csd:requestParams/*
    else $function/requestParams/*
  }
</csd:requestParams>
return csr_proc:process_updating_CSR_stored_results($db,$doc,$requestParams,$bindings)
};

declare function csr_proc:lookup_stored_options($db,$urn)
{
  let $stored_updating_functions := csr_proc:stored_updating_functions($db)
  let $stored_functions := csr_proc:stored_functions($db)
  let $func := ($stored_functions[@urn = $urn], $stored_updating_functions[@urn = $urn])[1]
   return  ($func/csd:extension[@urn='urn:openhie.org:openinfoman:csr_processor' and  @type='xquery:options']/xquery:options)[1]
     (: See: http://docs.basex.org/wiki/XQuery_Module :)
};

declare function csr_proc:lookup_stored_content_type($db,$urn)
{
  let $stored_updating_functions := csr_proc:stored_updating_functions($db)
  let $stored_functions := csr_proc:stored_functions($db)
  return string(($stored_functions[@urn = $urn]/@content-type, $stored_updating_functions[@urn = $urn]/@content-type  , "text/xml")[1])
};