added documentation for the params of the probe-index-range-general function

xquery version "3.0";

(:
 : Copyright 2006-2009 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 defines a set of functions to probe and refresh indexes which are
 : declared in the prolog of a module.
 :
 :
This module is part of Zorba's XQuery Data
 : Definition Facility. All the indexes managed by this module
 : have to be pre-declared in the prolog of a library module. Please refer to the
 : general documentation
 : for more information and examples.

 :
 : @see Data Lifecycle
 : @see XQuery Data Definition Facility
 : @see http://www.zorba-xquery.com/modules/store/static/indexes/ddl
 : @see http://www.zorba-xquery.com/modules/store/static/collections/dml
 : @see http://www.zorba-xquery.com/modules/store/static/collections/ddl
 : @see http://www.zorba-xquery.com/modules/store/static/integrity_constraints/ddl
 : @see http://www.zorba-xquery.com/modules/store/static/integrity_constraints/dml
 : @see http://www.zorba-xquery.com/errors
 :
 : @author Zorba Team
 :
 : @project store/indexes/static
 :
 :)
module namespace idml = "http://www.zorba-xquery.com/modules/store/static/indexes/dml";

declare namespace zerr = "http://www.zorba-xquery.com/errors";
declare namespace ann = "http://www.zorba-xquery.com/annotations";

declare namespace ver = "http://www.zorba-xquery.com/options/versioning";

declare option ver:module-version "2.0";

(:~
 :
The probe-index-point-value function retrieves from an index the domain
 : nodes associated by value equality with a given search tuple.
 : The search tuple consists of a number of search keys, where
 : each search key is either an atomic item or the empty sequence.  The number
 : of search keys given must be equal to the number of keys declared for the
 : index. Since the number of keys differs from one index to another, this
 : function is variadic.

 :
 :
The result of the function is either an error or the set of domain nodes for
 : which the following xquery expression returns true:

 :
 :

 : $key1 eq $node/keyExpr1 and ... and $keyM eq $node/keyExprM
 :

 : where keyExpri is the expression specified in the i-th keyspec
 : of the index.
 :
 : @param $name The QName of the index to probe
 : @param $key_i the search keys used to probe the index with. The i-th search
 :        key corresponds to the i-th key expression in the index declaration.
 : @return The set of domain nodes that satisfy the search condition.
 :
 : @error zerr:ZDDY0021 if the index with name $name is not declared.
 : @error zerr:ZDDY0023 if the index with name $name does not exist.
 : @error zerr:ZDDY0025 if the number of search keys passed as arguments is not
 :        the same as the number of keys declared for the index.
 : @error err:XPTY0004 if a non-empty seach key is given, whose type does not match
 :        the sequence type specified in the corresponding keyspec.
 :
 :)
declare %ann:variadic function idml:probe-index-point-value(
  $name as xs:QName,
  $key_i as xs:anyAtomicType?) as node()*  external;

(:~
 :
The probe-index-point-general function retrieves from an index the domain
 : nodes associated by general equality with a given search sequence
 : . The search sequence consists of an arbitrary number of
 : search keys, where each search key is an atomic item. The function
 : is supported by general indexes only. Its result is either an error or the
 : set of domain nodes for which the following xquery expression returns true:

 :

 : $keys = $node/keyExpr
 :

 : where keyExpr is the expression specified in the keyspec of the index (remember
 : that for general indexes, there can be only one keyspec).
 :
 : @param $name The QName of the index to probe.
 : @param $key The search sequence.
 : @return The set of domain nodes that satisfy the search condition.
 :
 : @error zerr:ZDDY0021 if the index with name $name is not declared.
 : @error zerr:ZDDY0023 if the index with name $name does not exist.
 : @error zerr:ZDDY0029 if the index is not general.
 : @error err:XPTY0004  if the search sequence contains a search key, whose
 :        type does not match the sequence type specified in the keyspec of
 :        the index.
 :)
declare function idml:probe-index-point-general(
  $name as xs:QName,
  $key  as xs:anyAtomicType*) as node()*  external;

(:~
 :
The probe-index-range-value function retrieves the domain nodes associated
 : by value order-comparison (operators le, lt, ge, gt) with a given search
 : box. The search box is specified as a number M of rangespecs
 : , where each rangespec consists of six values. The number M must be
 : greater than 0 and less than or equal to the number N of keyspecs found in the
 : index declaration. If M is less than N, then the "missing" rangespecs are
 : assumed to have the following value: [(), (), false, false, false, false].
 : As a result, we can assume that M is equal to N (Remember that for general
 : indexes, there can be only one IndexKeySpec, and as a result, for general
 : indexes, M = N = 1). Since the number of keys differs from one index to
 : another, this function is variadic.

 :
 :
The ith rangespec corresponds to the ith keyspec, and
 : specifies a search condition on the key values that are produced by evaluating
 : that keyspec for every domain node. Specifically, we define the ith
 : rangespec result as the set of domain nodes for which the
 : following xquery expression returns true:

 :
 :

 : if ($haveLowerBound-i and $haveUpperBound-i) then
 :   $lowerBound-i lop $node/keyExpr-i and $node/keyExpr-i uop $upperBound-i
 : else if ($haveLowerBound-i) then
 :   $lowerBound-i lop $node/keyExpr-i
 : else if ($haveUpperBound-i) then
 :   $node/keyExpr-i uop $upperBound-i
 : else
 :   fn:true()
 :

 :
 :
where keyExpr-i is the expression specified by the ith keyspec
 : of the index, lop is either the le or the lt operator depending on whether
 : $lowerBoundsIncluded-i is true or false, and uop is either the le or the
 : lt operator depending on whether $upperBoundsIncluded-i is true or false.

 :
 :
The result of the probe-index-range-value function is either an error,
 : or the intersection of all the rangespec results.

 :
 : @param $name The QName of the index to probe
 : @param $lowerBound-i The lower bound in a range of key values.
 : @param $upperBound-i The upper bound in a range of key values.
 : @param $haveLowerBound-i If false, then there is no lower bound, or
 :        equivalently, the lower bound is -INFINITY. Otherwise, the lower
 :        bound is the one given by the lowerBound-i value.
 : @param $haveUpperBound-i If false, then there is no upper bound, or
 :        equivalently, the upper bound is +INFINITY. Otherwise, the upper
 :        bound is the one given by the upperBound-i value.
 : @param $lowerBoundIncluded-i If false, then the range is open from below,
 :        i.e., the lowerBound-i value is not considered part of the
 :        range. Otherwise, the range is closed from below, i.e., the
 :        lowerBound-i value is part of the range.
 : @param $upperBoundIncluded-i If false, then the range is open from above,
 :        i.e., the upperBound-i value is not considered part of the
 :        range. Otherwise, the range is closed from above, i.e., the
 :        upperBound-i value is part of the range.
 : @return The set of domain nodes that satisfy the search condition.
 :
 : @error zerr:ZDDY0021 if the index with name $name is not declared.
 : @error zerr:ZDDY0023 if the index with name $name does not exist.
 : @error zerr:ZDDY0025 if the number of rangespecs passed as arguments
 :        is zero or greater than the number of keys declared for the index.
 : @error zerr:ZDDY0026 if the index is not a range index.
 : @error err:XPTY0004  if $haveLowerBound-i is true and $lowerBound-i is an
 :        atomic item whose type does not match the sequence type specified
 :        by the ith keyspec, or $haveUpperBound-i is true and
 :        $upperBound-i is an atomic item whose type does not match the
 :        sequence type specified by the ith keyspec.
 : @error zerr:ZDDY0034 if (a) the index is general (in which case there is
 :        only one rangespac), (b) the index is untyped, (c) there is both a
 :        lower and an upper bound, and (d) if T1 and T2 are the types of the
 :        lower and upper bound, neither T1 is a subtype of T2 nor T2 is a
 :        subtype of T1.
 :)
declare %ann:variadic function idml:probe-index-range-value(
  $name                 as xs:QName,
  $lowerBound-i         as xs:anyAtomicType?,
  $upperBound-i         as xs:anyAtomicType?,
  $haveLowerBound-i     as xs:boolean,
  $haveUpperBound-i     as xs:boolean,
  $lowerBoundIncluded-i as xs:boolean,
  $upperBoundIncluded-i as xs:boolean) as node()*  external;

(:~
 :
The probe-index-range-general function retrieves the domain nodes associated
 : by general order-comparison (operators <=, <, >=, >) with one or two
 : search sequences. Each search sequence consists of an
 : arbitrary number of search keys, where each search key is
 : an atomic item. This method is supported by general range indexes only. Its
 : result is either an error or the set of domain nodes for which the following
 : xquery expression returns true:

 :
 :

 : if ($haveLowerBound and $haveUpperBound) then
 :   $lowerBoundKeys lop $node/keyExpr and $node/keyExpr uop $upperBoundKeys
 : else if ($haveLowerBound) then
 :   $lowerBoundKeys lop $node/keyExpr
 : else if ($haveUpperBound) then
 :   $node/keyExpr uop $upperBoundKeys
 : else
 :   fn:true()
 :

 :
 :
where keyExpr is the expression specified in the keyspec of the index,
 : lop is either the <= or the < operator depending on whether
 : $lowerBoundsIncluded is true or false, and uop is either the <= or the
 : < operator depending on whether $upperBoundsIncluded is true or false
.
 :
 : @param $name The QName of the index to probe.
 : @param $lowerBound The lower bound search sequence.
 : @param $upperBound The upper bound search sequence.
 : @param $haveLowerBound Whether a lower bound search sequence exists or not.
 : @param $haveUpperBound Whether an upper bound search sequence exists or not.
 : @param $lowerBoundIncluded Whether to use the <= or the < operator when
 :        comparing a search key from $lowerBound with an index key.
 : @param $upperBoundIncluded Whether to use the <= or the < operator when
 :        comparing an index key with a search key from $upperBound.
 : @return The set of domain nodes that satisfy the search condition
 :
 : @error zerr:ZDDY0021 if the index with name $name is not declared.
 : @error zerr:ZDDY0023 if the index with name $name does not exist.
 : @error zerr:ZDDY0030 if the index is not a general range index.
 : @error err:XPTY0004  if $haveLowerBound is true and $lowerBoundKeys constains
 : an atomic item whose type does not match the sequence type specified by the
 : index keyspec, or $haveUpperBound is true and $upperBoundKeys contains an
 : atomic item whose type does not match the sequence type specified by the
 : index keyspec.
 :)
declare function idml:probe-index-range-general(
  $name               as xs:QName,
  $lowerBound         as xs:anyAtomicType*,
  $upperBound         as xs:anyAtomicType*,
  $haveLowerBound     as xs:boolean,
  $haveUpperBound     as xs:boolean,
  $lowerBoundIncluded as xs:boolean,
  $upperBoundIncluded as xs:boolean) as node()*  external;

(:~
 : The refresh-index function is an updating function which updates
 : the index with the given name.
 : Note that if the maintenance property of the index is automatic,
 : this function is a NOP.
 :
 : @param $name The QName of the index to refresh.
 : @return The result of the function is an empty XDM instance and a
 :         pending update list which, when applied, refreshes the contents
 :         of the index.that consists of a
 :
 : @error zerr:ZDDY0021 if the index with name $name is not declared.
 : @error zerr:ZDDY0023 if the index with name $name does not exist.
 :)
declare updating function idml:refresh-index($name as xs:QName) external;

xquery version "3.0";

(:
 : Copyright 2006-2009 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 defines a set of functions to probe and refresh indexes which are
 : declared in the prolog of a module.
 :
 :
This module is part of Zorba's XQuery Data
 : Definition Facility. All the indexes managed by this module
 : have to be pre-declared in the prolog of a library module. Please refer to the
 : general documentation
 : for more information and examples.

 :
 : @see Data Lifecycle
 : @see XQuery Data Definition Facility
 : @see http://www.zorba-xquery.com/modules/store/static/indexes/ddl
 : @see http://www.zorba-xquery.com/modules/store/static/collections/dml
 : @see http://www.zorba-xquery.com/modules/store/static/collections/ddl
 : @see http://www.zorba-xquery.com/modules/store/static/integrity_constraints/ddl
 : @see http://www.zorba-xquery.com/modules/store/static/integrity_constraints/dml
 : @see http://www.zorba-xquery.com/errors
 :
 : @author Zorba Team
 :
 : @project store/indexes/static
 :
 :)
module namespace idml = "http://www.zorba-xquery.com/modules/store/static/indexes/dml";

declare namespace zerr = "http://www.zorba-xquery.com/errors";
declare namespace ann = "http://www.zorba-xquery.com/annotations";

declare namespace ver = "http://www.zorba-xquery.com/options/versioning";

declare option ver:module-version "2.0";

(:~
 :
The probe-index-point-value function retrieves from an index the domain
 : nodes associated by value equality with a given search tuple.
 : The search tuple consists of a number of search keys, where
 : each search key is either an atomic item or the empty sequence.  The number
 : of search keys given must be equal to the number of keys declared for the
 : index. Since the number of keys differs from one index to another, this
 : function is variadic.

 :
 :
The result of the function is either an error or the set of domain nodes for
 : which the following xquery expression returns true:

 :
 :

 : $key1 eq $node/keyExpr1 and ... and $keyM eq $node/keyExprM
 :

 : where keyExpri is the expression specified in the i-th keyspec
 : of the index.
 :
 : @param $name The QName of the index to probe
 : @param $key_i the search keys used to probe the index with. The i-th search
 :        key corresponds to the i-th key expression in the index declaration.
 : @return the set of domain nodes that satisfy the search condition.
 :
 : @error zerr:ZDDY0021 if the index with name $name is not declared.
 : @error zerr:ZDDY0023 if the index with name $name does not exist.
 : @error zerr:ZDDY0025 if the number of search keys passed as arguments is not
 :        the same as the number of keys declared for the index.
 : @error err:XPTY0004 if a non-empty seach key is given, whose type does not match
 :        the sequence type specified in the corresponding keyspec.
 :
 :)
declare %ann:variadic function idml:probe-index-point-value(
  $name as xs:QName,
  $key_i as xs:anyAtomicType?) as node()*  external;

(:~
 :
The probe-index-point-general function retrieves from an index the domain
 : nodes associated by general equality with a given search sequence
 : . The search sequence consists of an arbitrary number of
 : search keys, where each search key is an atomic item. The function
 : is supported by general indexes only. Its result is either an error or the
 : set of domain nodes for which the following xquery expression returns true:

 :

 : $keys = $node/keyExpr
 :

 : where keyExpr is the expression specified in the keyspec of the index (remember
 : that for general indexes, there can be only one keyspec).
 :
 : @param $name The QName of the index to probe.
 : @param $key The search sequence.
 : @return the set of domain nodes that satisfy the search condition.
 :
 : @error zerr:ZDDY0021 if the index with name $name is not declared.
 : @error zerr:ZDDY0023 if the index with name $name does not exist.
 : @error zerr:ZDDY0029 if the index is not general.
 : @error err:XPTY0004  if the search sequence contains a search key, whose
 :        type does not match the sequence type specified in the keyspec of
 :        the index.
 :)
declare function idml:probe-index-point-general(
  $name as xs:QName,
  $key  as xs:anyAtomicType*) as node()*  external;

(:~
 :
The probe-index-range-value function retrieves the domain nodes associated
 : by value order-comparison (operators le, lt, ge, gt) with a given search
 : box. The search box is specified as a number M of rangespecs
 : , where each rangespec consists of six values. The number M must be
 : greater than 0 and less than or equal to the number N of keyspecs found in the
 : index declaration. If M is less than N, then the "missing" rangespecs are
 : assumed to have the following value: [(), (), false, false, false, false].
 : As a result, we can assume that M is equal to N (Remember that for general
 : indexes, there can be only one IndexKeySpec, and as a result, for general
 : indexes, M = N = 1). Since the number of keys differs from one index to
 : another, this function is variadic.

 :
 :
The ith rangespec corresponds to the ith keyspec, and
 : specifies a search condition on the key values that are produced by evaluating
 : that keyspec for every domain node. Specifically, we define the ith
 : rangespec result as the set of domain nodes for which the
 : following xquery expression returns true:

 :
 :

 : if ($haveLowerBound-i and $haveUpperBound-i) then
 :   $lowerBound-i lop $node/keyExpr-i and $node/keyExpr-i uop $upperBound-i
 : else if ($haveLowerBound-i) then
 :   $lowerBound-i lop $node/keyExpr-i
 : else if ($haveUpperBound-i) then
 :   $node/keyExpr-i uop $upperBound-i
 : else
 :   fn:true()
 :

 :
 :
where keyExpr-i is the expression specified by the ith keyspec
 : of the index, lop is either the le or the lt operator depending on whether
 : $lowerBoundsIncluded-i is true or false, and uop is either the le or the
 : lt operator depending on whether $upperBoundsIncluded-i is true or false.

 :
 :
The result of the probe-index-range-value function is either an error,
 : or the intersection of all the rangespec results.

 :
 : @param $name The QName of the index to probe
 : @param $lowerBound-i The lower bound in a range of key values.
 : @param $upperBound-i The upper bound in a range of key values.
 : @param $haveLowerBound-i If false, then there is no lower bound, or
 :        equivalently, the lower bound is -INFINITY. Otherwise, the lower
 :        bound is the one given by the lowerBound-i value.
 : @param $haveUpperBound-i If false, then there is no upper bound, or
 :        equivalently, the upper bound is +INFINITY. Otherwise, the upper
 :        bound is the one given by the upperBound-i value.
 : @param $lowerBoundIncluded-i If false, then the range is open from below,
 :        i.e., the lowerBound-i value is not considered part of the
 :        range. Otherwise, the range is closed from below, i.e., the
 :        lowerBound-i value is part of the range.
 : @param $upperBoundIncluded-i If false, then the range is open from above,
 :        i.e., the upperBound-i value is not considered part of the
 :        range. Otherwise, the range is closed from above, i.e., the
 :        upperBound-i value is part of the range.
 : @return the set of domain nodes that satisfy the search condition.
 :
 : @error zerr:ZDDY0021 if the index with name $name is not declared.
 : @error zerr:ZDDY0023 if the index with name $name does not exist.
 : @error zerr:ZDDY0025 if the number of rangespecs passed as arguments
 :        is zero or greater than the number of keys declared for the index.
 : @error zerr:ZDDY0026 if the index is not a range index.
 : @error err:XPTY0004  if $haveLowerBound-i is true and $lowerBound-i is an
 :        atomic item whose type does not match the sequence type specified
 :        by the ith keyspec, or $haveUpperBound-i is true and
 :        $upperBound-i is an atomic item whose type does not match the
 :        sequence type specified by the ith keyspec.
 : @error zerr:ZDDY0034 if (a) the index is general (in which case there is
 :        only one rangespac), (b) the index is untyped, (c) there is both a
 :        lower and an upper bound, and (d) if T1 and T2 are the types of the
 :        lower and upper bound, neither T1 is a subtype of T2 nor T2 is a
 :        subtype of T1.
 :)
declare %ann:variadic function idml:probe-index-range-value(
  $name                 as xs:QName,
  $lowerBound-i         as xs:anyAtomicType?,
  $upperBound-i         as xs:anyAtomicType?,
  $haveLowerBound-i     as xs:boolean,
  $haveUpperBound-i     as xs:boolean,
  $lowerBoundIncluded-i as xs:boolean,
  $upperBoundIncluded-i as xs:boolean) as node()*  external;

(:~
 :
The probe-index-range-general function retrieves the domain nodes associated
 : by general order-comparison (operators <=, <, >=, >) with one or two
 : search sequences. Each search sequence consists of an
 : arbitrary number of search keys, where each search key is
 : an atomic item. This method is supported by general range indexes only. Its
 : result is either an error or the set of domain nodes for which the following
 : xquery expression returns true:

 :
 :

 : if ($haveLowerBound and $haveUpperBound) then
 :   $lowerBoundKeys lop $node/keyExpr and $node/keyExpr uop $upperBoundKeys
 : else if ($haveLowerBound) then
 :   $lowerBoundKeys lop $node/keyExpr
 : else if ($haveUpperBound) then
 :   $node/keyExpr uop $upperBoundKeys
 : else
 :   fn:true()
 :

 :
 :
where keyExpr is the expression specified in the keyspec of the index,
 : lop is either the <= or the < operator depending on whether
 : $lowerBoundsIncluded is true or false, and uop is either the <= or the
 : < operator depending on whether $upperBoundsIncluded is true or false
.
 :
 : @param $name The QName of the index to probe.
 : @return the set of domain nodes that satisfy the search condition
 :
 : @error zerr:ZDDY0021 if the index with name $name is not declared.
 : @error zerr:ZDDY0023 if the index with name $name does not exist.
 : @error zerr:ZDDY0030 if the index is not a general range index.
 : @error err:XPTY0004  if $haveLowerBound is true and $lowerBoundKeys constains
 : an atomic item whose type does not match the sequence type specified by the
 : index keyspec, or $haveUpperBound is true and $upperBoundKeys contains an
 : atomic item whose type does not match the sequence type specified by the
 : index keyspec.
 :)
declare function idml:probe-index-range-general(
  $name               as xs:QName,
  $lowerBound         as xs:anyAtomicType*,
  $upperBound         as xs:anyAtomicType*,
  $haveLowerBound     as xs:boolean,
  $haveupperBound     as xs:boolean,
  $lowerBoundIncluded as xs:boolean,
  $upperBoundIncluded as xs:boolean) as node()*  external;

(:~
 : The refresh-index function is an updating function which updates
 : the index with the given name.
 : Note that if the maintenance property of the index is automatic,
 : this function is a NOP.
 :
 : @param $name The QName of the index to refresh.
 : @return The result of the function is an empty XDM instance and a
 :         pending update list which, when applied, refreshes the contents
 :         of the index.that consists of a
 :
 : @error zerr:ZDDY0021 if the index with name $name is not declared.
 : @error zerr:ZDDY0023 if the index with name $name does not exist.
 :)
declare updating function idml:refresh-index($name as xs:QName) external;


added curl usage info for stored functions

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

import 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_webconf =  "https://github.com/openhie/openinfoman/csd_webconf";
import module namespace csd_webui =  "https://github.com/openhie/openinfoman/csd_webui";

declare   namespace   csd = "urn:ihe:iti:csd:2013";
declare default element  namespace   "urn:ihe:iti:csd:2013";

declare variable $page:csd_docs := csd_dm:registered_documents($csd_webconf:db);

declare
  %rest:path("/CSD/csr/{$name}/careServicesRequest")
  %rest:POST("{$careServicesRequest}")
  function page:csr($name,$careServicesRequest)
{
if (csd_dm:document_source_exists($csd_webconf:db,$name)) then
 csr_proc:process_CSR($csd_webconf:db,$careServicesRequest/careServicesRequest,$name,csd_webui:generateURL())
else
  (:need appropriate error handling:)
  ()

};

declare
  %rest:path("/CSD/csr/{$name}/careServicesRequest/{$search}")
  %rest:consumes("application/xml", "text/xml", "multipart/form-data")
  %rest:POST("{$requestParams}")
  function page:csr2($name,$requestParams,$search)
{
let $careServicesRequest :=
  <csd:careServicesRequest>
    <csd:function urn="{$search}">{$requestParams}</csd:function>
  </csd:careServicesRequest>
return
  if (csd_dm:document_source_exists($csd_webconf:db,$name)) then
    csr_proc:process_CSR($csd_webconf:db,$careServicesRequest,$name,csd_webui:generateURL())
  else
    (:need appropriate error handling:)
  ()

};

declare updating
  %rest:path("/CSD/csr/{$name}/careServicesRequest/update")
  %rest:consumes("application/xml", "text/xml", "multipart/form-data")
  %rest:POST("{$careServicesRequest}")
  function page:csr_updating($name,$careServicesRequest)
{
  if (csd_dm:document_source_exists($csd_webconf:db,$name)) then
    csr_proc:process_updating_CSR($csd_webconf:db,$careServicesRequest/csd:careServicesRequest,$name,csd_webui:generateURL())
  else
    (:need appropriate error handling:)
    ()
};

declare updating
  %rest:path("/CSD/csr/{$name}/careServicesRequest/update/{$search}")
  %rest:consumes("application/xml", "text/xml", "multipart/form-data")
  %rest:POST("{$requestParams}")
  function page:csr_updating($name,$requestParams,$search)
{
let $careServicesRequest :=
  <csd:careServicesRequest>
    <csd:function urn="{$search}">{$requestParams}</csd:function>
  </csd:careServicesRequest>
return
if (csd_dm:document_source_exists($csd_webconf:db,$name)) then
 csr_proc:process_updating_CSR($csd_webconf:db,$careServicesRequest,$name,csd_webui:generateURL())
else
  (:need appropriate error handling:)
  ()

};

declare
  %rest:path("/CSD/csr/{$name}/adhoc")
  %rest:consumes("application/xml", "text/xml", "multipart/form-data")
  %rest:POST
  %rest:form-param("adhoc","{$adhoc}")
  %rest:form-param("content", "{$content}","application/xml")
function page:adhoc($name,$adhoc,$content) {
if (csd_dm:document_source_exists($csd_webconf:db,$name)) then
let  $adhoc_doc := csr_proc:create_adhoc_doc(string($adhoc),$content)
  return  csr_proc:process_CSR($csd_webconf:db, $adhoc_doc,$name,csd_webui:generateURL())
else
  (:need appropriate error handling:)
  ()

};

declare
  %rest:path("/CSD/csr")
  %rest:GET
  %output:method("xhtml")
  function page:csr_list()
{
let $response := page:endpoints()
return csd_webui:wrapper($response)
};

declare
  %rest:path("/CSD/csr/{$name}/careServicesRequest")
  %output:method("xhtml")
  function page:csr($name)
{
  let $contents :=
    (

      Example Usage:

curl -X POST -H 'content-type: text/xml'  --data-binary @request.xml $URL

      where $URL is one of the below and request.xml is an XML file containing a <csd:requestParams/> element

    ,

{
    (
      for $function in csr_proc:stored_functions($csd_webconf:db)
      let $url := csd_webui:generateURL(("CSD/csr", $name , "careServicesRequest", string($function/@urn)))
      return

Name: {string($function/@urn)}

URL: {$url}

Full Description

      ,
      for $function in csr_proc:stored_updating_functions($csd_webconf:db)
      let $url := csd_webui:generateURL(("CSD/csr", $name , "careServicesRequest/update", string($function/@urn)))
      return

Name: {string($function/@urn)} (updating)

URL: {$url}

Full Description

    )
    }

    )
  return csd_webui:wrapper($contents)
};

declare function page:endpoints() {

Care Services Request - Endpoints

      {
	for $name in $page:csd_docs
	return

	  Submit Care Services Request for {$name} at:

{csd_webui:generateURL(('CSD/csr/',$name,'/careServicesRequest'))}

	  Submit ad-hoc query:
	  <form method='post' action="/CSD/csr/{$name}/adhoc"  enctype="multipart/form-data">
	    Ad-Hoc Query<textarea  rows="10" cols="80" name="adhoc" >{$page:sample}</textarea>

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

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

      }

};

declare variable $page:sample :=
"declare namespace csd = 'urn:ihe:iti:csd:2013';

You have {count(/csd:CSD/csd:providerDirectory/*)} providers.

You have {count(/csd:CSD/csd:facilityDirectory/*)} facilities.

You have {count(/csd:CSD/csd:organizationDirectory/*)} organizations.

You have {count(/csd:CSD/csd:serviceDirectory/*)} services.

";

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

import 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_webconf =  "https://github.com/openhie/openinfoman/csd_webconf";
import module namespace csd_webui =  "https://github.com/openhie/openinfoman/csd_webui";

declare   namespace   csd = "urn:ihe:iti:csd:2013";
declare default element  namespace   "urn:ihe:iti:csd:2013";

declare variable $page:csd_docs := csd_dm:registered_documents($csd_webconf:db);

declare
  %rest:path("/CSD/csr/{$name}/careServicesRequest")
  %rest:POST("{$careServicesRequest}")
  function page:csr($name,$careServicesRequest)
{
if (csd_dm:document_source_exists($csd_webconf:db,$name)) then
 csr_proc:process_CSR($csd_webconf:db,$careServicesRequest/careServicesRequest,$name,csd_webui:generateURL())
else
  (:need appropriate error handling:)
  ()

};

declare
  %rest:path("/CSD/csr/{$name}/careServicesRequest/{$search}")
  %rest:consumes("application/xml", "text/xml", "multipart/form-data")
  %rest:POST("{$requestParams}")
  function page:csr2($name,$requestParams,$search)
{
let $careServicesRequest :=
  <csd:careServicesRequest>
    <csd:function urn="{$search}">{$requestParams}</csd:function>
  </csd:careServicesRequest>
return
  if (csd_dm:document_source_exists($csd_webconf:db,$name)) then
    csr_proc:process_CSR($csd_webconf:db,$careServicesRequest,$name,csd_webui:generateURL())
  else
    (:need appropriate error handling:)
  ()

};

declare updating
  %rest:path("/CSD/csr/{$name}/careServicesRequest/update")
  %rest:consumes("application/xml", "text/xml", "multipart/form-data")
  %rest:POST("{$careServicesRequest}")
  function page:csr_updating($name,$careServicesRequest)
{
  if (csd_dm:document_source_exists($csd_webconf:db,$name)) then
    csr_proc:process_updating_CSR($csd_webconf:db,$careServicesRequest/csd:careServicesRequest,$name,csd_webui:generateURL())
  else
    (:need appropriate error handling:)
    ()
};

declare updating
  %rest:path("/CSD/csr/{$name}/careServicesRequest/update/{$search}")
  %rest:consumes("application/xml", "text/xml", "multipart/form-data")
  %rest:POST("{$requestParams}")
  function page:csr_updating($name,$requestParams,$search)
{
let $careServicesRequest :=
  <csd:careServicesRequest>
    <csd:function urn="{$search}">{$requestParams}</csd:function>
  </csd:careServicesRequest>
return
if (csd_dm:document_source_exists($csd_webconf:db,$name)) then
 csr_proc:process_updating_CSR($csd_webconf:db,$careServicesRequest,$name,csd_webui:generateURL())
else
  (:need appropriate error handling:)
  ()

};

declare
  %rest:path("/CSD/csr/{$name}/adhoc")
  %rest:consumes("application/xml", "text/xml", "multipart/form-data")
  %rest:POST
  %rest:form-param("adhoc","{$adhoc}")
  %rest:form-param("content", "{$content}","application/xml")
function page:adhoc($name,$adhoc,$content) {
if (csd_dm:document_source_exists($csd_webconf:db,$name)) then
let  $adhoc_doc := csr_proc:create_adhoc_doc(string($adhoc),$content)
  return  csr_proc:process_CSR($csd_webconf:db, $adhoc_doc,$name,csd_webui:generateURL())
else
  (:need appropriate error handling:)
  ()

};

declare
  %rest:path("/CSD/csr")
  %rest:GET
  %output:method("xhtml")
  function page:csr_list()
{
let $response := page:endpoints()
return csd_webui:wrapper($response)
};

declare
  %rest:path("/CSD/csr/{$name}/careServicesRequest")
  %output:method("xhtml")
  function page:csr($name)
{
  let $contents :=

{
    (
      for $function in csr_proc:stored_functions($csd_webconf:db)
      let $url := csd_webui:generateURL(("CSD/csr", $name , "careServicesRequest", string($function/@urn)))
      return

Name: {string($function/@urn)}

URL: {$url}

Full Description

      ,
      for $function in csr_proc:stored_updating_functions($csd_webconf:db)
      let $url := csd_webui:generateURL(("CSD/csr", $name , "careServicesRequest/update", string($function/@urn)))
      return

Name: {string($function/@urn)} (updating)

URL: {$url}

Full Description

    )
    }

  return csd_webui:wrapper($contents)
};

declare function page:endpoints() {

Care Services Request - Endpoints

      {
	for $name in $page:csd_docs
	return

	  Submit Care Services Request for {$name} at:

{csd_webui:generateURL(('CSD/csr/',$name,'/careServicesRequest'))}

	  Submit ad-hoc query:
	  <form method='post' action="/CSD/csr/{$name}/adhoc"  enctype="multipart/form-data">
	    Ad-Hoc Query<textarea  rows="10" cols="80" name="adhoc" >{$page:sample}</textarea>

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

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

      }

};

declare variable $page:sample :=
"declare namespace csd = 'urn:ihe:iti:csd:2013';

You have {count(/csd:CSD/csd:providerDirectory/*)} providers.

You have {count(/csd:CSD/csd:facilityDirectory/*)} facilities.

You have {count(/csd:CSD/csd:organizationDirectory/*)} organizations.

You have {count(/csd:CSD/csd:serviceDirectory/*)} services.

";


Made output of collectresults more useable for w3c website

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

declare option exist:serialize "method=xml indent=yes";
declare option exist:output-size-limit "-1";
declare namespace response="http://exist-db.org/xquery/response";
declare namespace empty="";

let $product-version := util:system-property("product-version")
let $product-build := util:system-property("product-build")
let $revision := system:get-revision()
let $test-suite := doc('/db/XQTS/XQTSCatalog.xml')/*:test-suite/@version
let $dummy := response:set-header("Content-Disposition", concat(
	"attachment; filename="results_XQTS-" , $test-suite , "_eXist-" ,
	$product-version , '_' , $product-build , ".xml"" ) )

let $cases := fn:collection(  '/db/XQTS' )//test-case
return
<test-suite-result xmlns="http://www.w3.org/2005/02/query-test-XQTSResult">
    <implementation name="eXist-db" version="{$product-version} (revision {$revision} {$product-build})" anonymous-result-column="false">

        <organization name="eXist Open Source Native XML database"  website="http://www.exist-db.org" anonymous="false"/>

        <submittor name="eXist XQTS testsuite runner" email="eXistAdmin@gmail.com"/>

        <description>

eXist is an Open Source native XML database featuring efficient,
                index-based XQuery processing, automatic indexing, extensions for full-text
                search,  XUpdate  support and tight integration with existing XML development tools.

        </description>

        <implementation-defined-items>

        </implementation-defined-items>

        <features>

        <feature name="Minimal Conformance" supported="true"/>
        <feature name="Schema Import" supported="false"/>
        <feature name="Schema Validation" supported="false"/>
        <feature name="Static Typing" supported="false"/>
        <feature name="Static Typing Extensions" supported="false"/>
        <feature name="Full Axis" supported="true"/>
        <feature name="Module" supported="true"/>
        <feature name="Serialization" supported="true"/>
        <feature name="Trivial XML Embedding" supported="false"/>
				  </features>

        <context-properties>

        </context-properties>

    </implementation>

    <syntax>XQuery</syntax>

    <test-run dateRun="{fn:current-dateTime()}">
        <test-suite version="{$test-suite}"/>
        <transformation>

No unusual transformations.

        </transformation>
        <comparison>

No unusual comparisons

        </comparison>
        <otherComments>

The test run took n seconds.

        </otherComments>
    </test-run>

{
    for $case in $cases
    order by $case/@name
    return <test-case name="{$case/@name}" result="{$case/@result}" />
}
</test-suite-result>

declare option exist:serialize "method=xml indent=yes";
declare option exist:output-size-limit "-1";
declare namespace response="http://exist-db.org/xquery/response";
declare namespace empty="";

let $product-version := util:system-property("product-version")
let $product-build := util:system-property("product-build")
let $test-suite := doc('/db/XQTS/XQTSCatalog.xml')/*:test-suite/@version
let $dummy := response:set-header("Content-Disposition", concat(
	"attachment; filename="results_XQTS-" , $test-suite , "_eXist-" ,
	$product-version , '_' , $product-build , ".xml"" ) )

let $cases := fn:collection(  '/db/XQTS' )//test-case
return
<test-suite-result xmlns="http://www.w3.org/2005/02/query-test-XQTSResult">
        <implementation name="eXist-{$product-version}" version="{$product-build}" anonymous-result-column="false">

                <organization name="eXist Open Source native XML database"  website="http://www.exist-db.org" anonymous="false"/>

                <submittor name="eXist XQTS testsuite runner" email="eXistAdmin@gmail.com"/>

                <description>

eXist is an Open Source native XML database featuring efficient,
                        index-based XQuery processing, automatic indexing, extensions for full-text
                        search,  XUpdate  support and tight integration with existing XML development tools.

                </description>

                <implementation-defined-items>

                </implementation-defined-items>

                <features>

                <feature name="Minimal Conformance" supported="true"/>
                <feature name="Schema Import" supported="false"/>
                <feature name="Schema Validation" supported="false"/>
                <feature name="Static Typing" supported="false"/>
                <feature name="Static Typing Extensions" supported="false"/>
                <feature name="Full Axis" supported="true"/>
                <feature name="Module" supported="true"/>
                <feature name="Serialization" supported="true"/>
                <feature name="Trivial XML Embedding" supported="false"/>
						  </features>

                <context-properties>

                </context-properties>

        </implementation>

        <syntax>XQuery</syntax>

        <test-run dateRun="{fn:current-dateTime()}">
                <test-suite version="{$test-suite}"/>
                <transformation>

No unusual transformations.

                </transformation>
                <comparison>

No unusual comparisons

                </comparison>
                <otherComments>

The test run took n seconds.

                </otherComments>
        </test-run>

{
		(: for $case in fn:collection(  '/db/XQTS' )//*:test-case :)
    for $case in $cases
    order by $case/@name
    return <test-case name="{$case/@name}" result="{$case/@result}" />
}
</test-suite-result>


Change xqDoc script for ignoring main modules.

module namespace doc2html = "http://www.zorba-xquery.com/modules/internal/xqdoc-lib";

import module namespace file = "http://www.zorba-xquery.com/modules/file";
import module namespace xqd = "http://www.zorba-xquery.com/modules/xqdoc";

import module namespace xqdg = "http://www.zorba-xquery.com/modules/internal/xqdoc-xhtml";

import schema namespace xqdoc = "http://www.xqdoc.org/1.0";

declare copy-namespaces preserve, inherit;

(:~
 : This variable contains the relative paths to directories that contain
 : example code fragments that are included.
 :)
declare variable $doc2html:examplePath as xs:string* := (
    'test/rbkt/Queries/zorba',
    'test/update/Queries',
    'test/rbkt/ExpQueryResults/zorba',
    'test/update/ExpectedTestResults'
);

declare variable $doc2html:stepBacks as xs:string := "../../../../../../../../../../../../../../../../../../../../";

(:~
 : This variable contains all the modules names part of the left menu
 :)
declare variable $doc2html:indexCollector := <modules/>;

(:~
 : This variable contains all the schemas imported bythe modules
 :)
declare variable $doc2html:schemasCollector := <schemas/>;

declare function doc2html:getFileName($moduleURI as xs:string) as xs:string
{
    replace(
        replace($moduleURI, "/", "_"),
        "http:__",
        ""
    )
};

declare sequential function doc2html:clearFolder($folderPath as xs:string, $pattern as xs:string) as xs:string*
{
  if(fn:not(file:exists($folderPath))) then
    ""
  else
    for $file in file:files($folderPath, $pattern, fn:true())
    let $filePath := fn:concat($folderPath, file:path-separator(), $file)
    return
      try {
        file:remove($filePath);
        concat("
  SUCCESS: ", $filePath);
      } catch * ($error_code) {
        concat("
  FAILED: ", $filePath)
      }
};

(:~
 : This function generates the XQDoc XML for all the modules found in $modulesPath
 : and writes the resulting XML documents in $targetPath. The hierarchy is preserved.
 :
 : @param $modulePath where to search for modules recursively.
 : @param $targetPath where to generate the XQDoc XML documents.
 : @return The function returns a string sequence with a status messge for each
 :         module processed.
 :)
declare sequential function doc2html:generateXQDocXml(
  $modulesPath as xs:string, $xqdocXmlPath as xs:string
) as xs:string* {
  for $filedirs in tokenize($modulesPath, ";")
  for $file in file:files($filedirs, "\.xq$", fn:true())
  let $filePath := fn:concat($filedirs, file:path-separator(), $file)
  let $xqdoc := xqd:xqdoc(file:path-to-uri($filePath))
  let $moduleDoc := $xqdoc/xqdoc:module
  let $moduleName := $moduleDoc/xqdoc:name
  let $moduleUri := $moduleDoc/xqdoc:uri
  return
    try {
      file:mkdirs($xqdocXmlPath, false());
      let $x := fn:count(file:files($xqdocXmlPath, "\.xml$", fn:true())) + 1
      let $xqdocFileName := fn:concat($xqdocXmlPath, file:path-separator(), doc2html:getFileName($moduleUri), ".xml")
      return
      file:write($xqdocFileName, $xqdoc, <s method="xml" indent="yes" />/@*);
      concat("
SUCCESS: ", $moduleUri, " (", ()(:$xqdocFileName:), ")");
    } catch * ($error_code) {
      concat("
FAILED: ", $moduleUri, " (", ()(:$xqdocFileName:), ")")
    }
};

(:~
 : This function removes the internal functionality from an XQDoc XML node.
 :
 : @param $xqdoc The XQDdoc XML node to remove the functionality from.
 : @return The xqdoc node without the internal functionality.
 :)
declare sequential function doc2html:removeInternalFunctionality($xqdoc as node()) as node() {
  delete node $xqdoc/xqdoc:functions/xqdoc:function[fn:starts-with(fn:data(xqdoc:comment/xqdoc:description), "Helper function")];
  $xqdoc;
};

(:~
 : This function generates the XQDoc XHTML pages for all the XQDoc XML
 : documents found in $xqdocPath and writes the resulting pages to in
 : $targetPath. The hierarchy is preserved.
 :
 : @param $indexPath path to the XHTML index page.
 :)
declare sequential function doc2html:generateXQDocXhtml(
  $indexPath      as xs:string, $xqdocXmlPath   as xs:string,
  $xqdocXhtmlPath as xs:string, $leftMenu as element(menu),
  $modulesPath    as xs:string
) as xs:string* {
  let $indexHtmlDoc := file:read-xml($indexPath)
  return
  for $file in file:files($xqdocXmlPath, "\.xml$", fn:true())
  let $stepsFromIndex := fn:count(fn:tokenize($file, fn:concat("\", file:path-separator()))) - 2
  let $xmlFilePath := concat($xqdocXmlPath, file:path-separator(), $file)
  let $xhtmlFilePath := concat($xqdocXhtmlPath, file:path-separator(), fn:replace($file, "\.xml$", ".html"))
  let $xhtmlFileDir :=
    let $segments := fn:tokenize($xhtmlFilePath, fn:concat("\", file:path-separator()))
    let $lastSegm := $segments[fn:count($segments)]
    return fn:substring-before($xhtmlFilePath, $lastSegm)
  return
    try {
      let $xqdoc := doc2html:removeInternalFunctionality(file:read-xml($xmlFilePath)/xqdoc:xqdoc)
      let $moduleDoc := $xqdoc/xqdoc:module
      let $moduleName := $moduleDoc/xqdoc:name
      let $moduleUri := $moduleDoc/xqdoc:uri
      let $menu :=
{string($leftMenu/@title)}

      let $menu := doc2html:createModuleTable($leftMenu, $menu, $moduleUri)
      let $xhtml := xqdg:doc($xqdoc, $menu, $doc2html:indexCollector, $doc2html:schemasCollector)
      return block {
        file:mkdirs($xhtmlFileDir, false());

        doc2html:configure-xhtml($xhtml, $stepsFromIndex, $modulesPath);

        file:write($xhtmlFilePath, $xhtml, <s method="xhtml" indent="yes" />/@*);

        concat("
SUCCESS: ", $moduleUri, " (", $xhtmlFilePath, ")");
      }
    } catch * ($error_code) {
      concat("
FAILED: ", $xhtmlFilePath)
    }
};

declare sequential function doc2html:gatherSchemas(
  $modulesPath as xs:string) as xs:string* {

  for $filedirs in tokenize($modulesPath, ";")
  for $file in file:files($filedirs, "\.xsd$", fn:true())
  let $xsdFilePath := concat($modulesPath, file:path-separator(), $file)
  return
    try {
      let $xqdoc := file:read-xml($xsdFilePath)
      let $xsdUri := $xqdoc/xs:schema/@targetNamespace
      return block {
          doc2html:collectModule($xsdUri, $xsdFilePath, $doc2html:schemasCollector);
          concat("
  SUCCESS: ", $xsdUri, " (", $xsdFilePath, ")");
        }
      } catch * ($error_code) {
        concat("
  FAILED: ", $xsdFilePath)
      }
};
(:~
 : This function gathers the names of the XQDoc XHTML pages for all the XQDoc XML
 : documents found in $xqdocXmlPath. The hierarchy is preserved.
 :)
declare sequential function doc2html:gatherModules(
  $xqdocXmlPath as xs:string
){
  for $file in file:files($xqdocXmlPath, "\.xml$", fn:true())
  let $xmlFilePath := concat($xqdocXmlPath, file:path-separator(), $file)
  let $xhtmlRelativeFilePath := fn:replace($file, "\.xml$", ".html")
  let $xhtmlRelativeFilePathSlash := fn:replace($xhtmlRelativeFilePath, fn:concat("\", file:path-separator()), "/")
  return
  try {
      let $xqdoc := doc2html:removeInternalFunctionality(file:read-xml($xmlFilePath)/xqdoc:xqdoc)
      let $moduleDoc := $xqdoc/xqdoc:module
      let $moduleUri := $moduleDoc/xqdoc:uri
      return if($moduleDoc/@type = "library") then
        block {
          doc2html:collectModule($moduleUri/text(), $xhtmlRelativeFilePath, $doc2html:indexCollector);
          concat("
SUCCESS: ", $moduleUri, " (", $xmlFilePath, ")");
        }
       else concat("
Ignore main module: ", $xmlFilePath)
    } catch * ($error_code) {
      concat("
FAILED: ", $xmlFilePath)
    }
};

declare sequential function doc2html:collectModule ($moduleUri as xs:string, $relativeFileName as xs:string, $collector) {
  insert node <module uri="{$moduleUri}" file="{$relativeFileName}" /> as last into $collector;
};

declare sequential function doc2html:getFilePath (
  $filename as xs:string, $modulesPath as xs:string
) as xs:string* {
  let $zorbaPath := replace($modulesPath,"/modules","")
  for $relPath in $doc2html:examplePath
  let $path := concat($zorbaPath,'/',$relPath)
  let $test := file:files($path,concat("^",$filename,"$"),fn:true())[1]
  return
  if (fn:exists($test)) then
    $test
  else
    ()
};

declare function doc2html:get-path-to-index ($stepsBack) as xs:string
{
  (: Error prone: stepsBack > stepBacks :)
  fn:substring($doc2html:stepBacks, 1, 3 * $stepsBack)
};

declare sequential function doc2html:configure-xhtml (
  $xhtml, $stepsFromIndex as xs:integer,
  $modulesPath as xs:string
) {
  let $pathToIndex := doc2html:get-path-to-index($stepsFromIndex)
  return
  (: replace the <test> nodes with eiter links to the actual files or inline the actual files based on the 'type' attribute value :)
  for $file in $xhtml//*:include
  let $type := $file/@type
  let $path := doc2html:getFilePath($file/text(), $modulesPath)
  let $read_text := file:read-text($path)
  return block {
  (: at the moment there is no way to ship the files defined as links with the packages/installers
    if (matches($type, "link")) then
      replace node $file with {$path}
    else :)
    if (matches($type, "inline")) then
      replace node $file with
        if (fn:exists($path)) then

 {$path}:

{$read_text}

        else

No example matching pattern '{$file/text()}' was found. Please update 'examplePath' variable.

        else ()
  };

  (: replace the function type description with images :)
  let $xquSpec := "http://www.w3.org/TR/xquery-update-10/",
      $xqsSpec := "http://www.w3.org/TR/xquery-sx-10/#dt-sequential-function",
      $xq11Spec := "http://www.w3.org/TR/xquery-11/#FunctionDeclns"
  let $pathToIndex := doc2html:get-path-to-index($stepsFromIndex)
  let $imagesPath := concat($pathToIndex, "images/")
  for $typeTd in $xhtml//*:td
  where $typeTd/@class eq "type"
  let $type := $typeTd/text()
  return block {
    if (matches($type, "updating")) then
      replace node $typeTd/text() with

    else if (matches($type, "sequential")) then
      replace node $typeTd/text() with

    else if (matches($type, "nondeterministic")) then
      replace node $typeTd/text() with

    else ();
  };

  (: replace the function names description with images+name of the functions :)
  let $xquSpec := "http://www.w3.org/TR/xquery-update-10/",
      $xqsSpec := "http://www.w3.org/TR/xquery-sx-10/#dt-sequential-function",
      $xq11Spec := "http://www.w3.org/TR/xquery-11/#FunctionDeclns"
  let $pathToIndex := doc2html:get-path-to-index($stepsFromIndex)
  let $imagesPath := concat($pathToIndex, "images/")
  for $func in $xhtml//*:div
  where $func/@class eq "subsection"
  let $funcName := $func/text()
  return block {
    if (starts-with($funcName, "updating")) then
      replace node $func/text() with
        (,
        text {substring-after($funcName, "updating")})

    else if (starts-with($funcName, "sequential")) then
      replace node $func/text() with
        (,
        text {substring-after($funcName, "sequential")})

    else if (starts-with($funcName, "nondeterministic")) then
      replace node $func/text() with
        (,
        text {substring-after($funcName, "nondeterministic")})
    else ();
  };

  $xhtml;
};

declare sequential function doc2html:createModuleTable($leftMenu as element(menu), $root, $moduleUri) {
  for $cat1 in $leftMenu/category
  return block {
    doc2html:createModuleHelper($root, $cat1, $moduleUri);
    for $cat2 in $cat1/category
    let $table2 := $root/li[fn:last()]/ul
    return block {
      doc2html:createModuleHelper($table2, $cat2, $moduleUri);
      for $cat3 in $cat2/category
      let $table3 := $root/li[fn:last()]/ul/li[fn:last()]/ul
      return block {
        doc2html:createModuleHelper($table3, $cat3, $moduleUri);
      };
    };
  };

  $root;
};

declare sequential function doc2html:createModuleHelper($table, $category, $moduleUri)
{
  block {
    insert nodes
{data($category/@name)}

    {
     for $module in $doc2html:indexCollector/module
      order by fn:data($module/@uri)
      return
        if(fn:starts-with(fn:string($module/@uri),data($category/@uri))
           and fn:not(fn:contains (fn:substring-after(data($module/@uri),fn:concat(data($category/@uri),'/')),'/'))) then
          if(fn:string($module/@uri) = $moduleUri) then

{fn:substring-after(data($module/@uri),fn:concat(data($category/@uri),'/'))}

          else

{fn:substring-after(data($module/@uri),fn:concat(data($category/@uri),'/'))}

        else ()
    }

    as last into $table
  };

  $table;
};

(:~
 : This function reads, updates and returns the new index.html.
 :
 : @param $indexPath Where to search for XML XQDoc documents recursively.
 : @return The content of the new index.html.
 :)
declare sequential function doc2html:generateIndexHtml($indexPath as xs:string, $menu, $modules) as document-node() {
    let $indexHtmlDoc := file:read-xml($indexPath)
    return block {
        insert nodes $menu
        as last into $indexHtmlDoc/*:html/*:body/*:div[@id='main']/*:div[@id='leftMenu'];

        let $module_list := $indexHtmlDoc/*:html/*:body/*:div[@id='main']/*:div[@id='rightcontent']/*:div[@id='module_list']
        return
          if ($module_list)
          then
            insert node $modules as last into $module_list
          else
            ();

        $indexHtmlDoc;
    }
};

declare sequential function doc2html:main(
  $modulePath as xs:string, $xqdocBuildPath as xs:string,
  $indexHtmlPath as xs:string
) {
  let $leftMenu :=
  <menu title="XQuery Modules">
  <category name="http://expath.org/ns" uri="http://expath.org/ns" />
  <category name="http://www.zorba-xquery.com/modules" uri="http://www.zorba-xquery.com/modules" >
    <category name="email" uri="http://www.zorba-xquery.com/modules/email" />
    <category name="excel" uri="http://www.zorba-xquery.com/modules/excel" />
    <category name="image" uri="http://www.zorba-xquery.com/modules/image" />
    <category name="introspection" uri="http://www.zorba-xquery.com/modules/introspection" />
    <category name="security" uri="http://www.zorba-xquery.com/modules/security" />
    <category name="oauth" uri="http://www.zorba-xquery.com/modules/oauth" />
    <category name="webservices" uri="http://www.zorba-xquery.com/modules/webservices" >
      <category name="google" uri="http://www.zorba-xquery.com/modules/webservices/google" />
      <category name="yahoo" uri="http://www.zorba-xquery.com/modules/webservices/yahoo" />
    </category>
  </category>
  <category name="http://www.w3.org/2005" uri="http://www.w3.org/2005" />
  </menu>
  let $menu :=

      {string($leftMenu/@title)}

  return doc2html:main($menu, $leftMenu, $modulePath, $xqdocBuildPath, $indexHtmlPath)
};

declare sequential function doc2html:main(
  $menu as element(ul),  $leftMenu as element(menu),
  $modulePath as xs:string, $xqdocBuildPath as xs:string,
  $indexHtmlPath as xs:string
) {
  declare $xqdocXmlPath   as xs:string := fn:concat($xqdocBuildPath, file:path-separator(), "xml");
  declare $xqdocXhtmlPath as xs:string := fn:concat($xqdocBuildPath, file:path-separator(), "xhtml");
  declare $xqdocSchemasPath as xs:string := fn:concat($xqdocBuildPath, file:path-separator(), "schemas");

  (: generate the XQDoc XML for all the modules :)
  if (file:mkdirs($xqdocXmlPath, false())) then
  (
    doc2html:clearFolder($xqdocXmlPath,"\.xml$"),
    doc2html:generateXQDocXml($modulePath, $xqdocXmlPath)
  )
  else
    error()
  ;

  (: generate the XQDoc XHTML for all the modules :)
  let $absoluteXhtmlDir := concat($xqdocBuildPath, "/xhtml")
  return
  if (file:mkdirs($absoluteXhtmlDir, false())) then
  (
    doc2html:clearFolder($xqdocXhtmlPath,"xqdoc\.html$"),
    doc2html:gatherModules($xqdocXmlPath),
    doc2html:gatherSchemas($xqdocSchemasPath),
    doc2html:generateXQDocXhtml($indexHtmlPath, $xqdocXmlPath, $xqdocXhtmlPath, $leftMenu, $modulePath)
  )
  else
    error()
  ;

  let $left :=

                {string($leftMenu/@title)}

  let $index1 := doc2html:createModuleTable($leftMenu, $left, "index.html")
  let $right :=

  let $index2 := doc2html:createModuleTable($leftMenu, $right, "index.html")
  let $doc := doc2html:generateIndexHtml($indexHtmlPath, $index1, $index2)
  return doc2html:configure-xhtml($doc/*:html, 0, $modulePath)
  ;

};

module namespace doc2html = "http://www.zorba-xquery.com/modules/internal/xqdoc-lib";

import module namespace file = "http://www.zorba-xquery.com/modules/file";
import module namespace xqd = "http://www.zorba-xquery.com/modules/xqdoc";

import module namespace xqdg = "http://www.zorba-xquery.com/modules/internal/xqdoc-xhtml";

import schema namespace xqdoc = "http://www.xqdoc.org/1.0";

declare copy-namespaces preserve, inherit;

(:~
 : This variable contains the relative paths to directories that contain
 : example code fragments that are included.
 :)
declare variable $doc2html:examplePath as xs:string* := (
    'test/rbkt/Queries/zorba',
    'test/update/Queries',
    'test/rbkt/ExpQueryResults/zorba',
    'test/update/ExpectedTestResults'
);

declare variable $doc2html:stepBacks as xs:string := "../../../../../../../../../../../../../../../../../../../../";

(:~
 : This variable contains all the modules names part of the left menu
 :)
declare variable $doc2html:indexCollector := <modules/>;

(:~
 : This variable contains all the schemas imported bythe modules
 :)
declare variable $doc2html:schemasCollector := <schemas/>;

declare function doc2html:getFileName($moduleURI as xs:string) as xs:string
{
    replace(
        replace($moduleURI, "/", "_"),
        "http:__",
        ""
    )
};

declare sequential function doc2html:clearFolder($folderPath as xs:string, $pattern as xs:string) as xs:string*
{
  if(fn:not(file:exists($folderPath))) then
    ""
  else
    for $file in file:files($folderPath, $pattern, fn:true())
    let $filePath := fn:concat($folderPath, file:path-separator(), $file)
    return
      try {
        file:remove($filePath);
        concat("
  SUCCESS: ", $filePath);
      } catch * ($error_code) {
        concat("
  FAILED: ", $filePath)
      }
};

(:~
 : This function generates the XQDoc XML for all the modules found in $modulesPath
 : and writes the resulting XML documents in $targetPath. The hierarchy is preserved.
 :
 : @param $modulePath where to search for modules recursively.
 : @param $targetPath where to generate the XQDoc XML documents.
 : @return The function returns a string sequence with a status messge for each
 :         module processed.
 :)
declare sequential function doc2html:generateXQDocXml(
  $modulesPath as xs:string, $xqdocXmlPath as xs:string
) as xs:string* {
  for $filedirs in tokenize($modulesPath, ";")
  for $file in file:files($filedirs, "\.xq$", fn:true())
  let $filePath := fn:concat($filedirs, file:path-separator(), $file)
  let $xqdoc := xqd:xqdoc(file:path-to-uri($filePath))
  let $moduleDoc := $xqdoc/xqdoc:module
  let $moduleName := $moduleDoc/xqdoc:name
  let $moduleUri := $moduleDoc/xqdoc:uri
  return
    try {
      file:mkdirs($xqdocXmlPath, false());
      let $x := fn:count(file:files($xqdocXmlPath, "\.xml$", fn:true())) + 1
      let $xqdocFileName := fn:concat($xqdocXmlPath, file:path-separator(), doc2html:getFileName($moduleUri), ".xml")
      return
      file:write($xqdocFileName, $xqdoc, <s method="xml" indent="yes" />/@*);
      concat("
SUCCESS: ", $moduleUri, " (", ()(:$xqdocFileName:), ")");
    } catch * ($error_code) {
      concat("
FAILED: ", $moduleUri, " (", ()(:$xqdocFileName:), ")")
    }
};

(:~
 : This function removes the internal functionality from an XQDoc XML node.
 :
 : @param $xqdoc The XQDdoc XML node to remove the functionality from.
 : @return The xqdoc node without the internal functionality.
 :)
declare sequential function doc2html:removeInternalFunctionality($xqdoc as node()) as node() {
  delete node $xqdoc/xqdoc:functions/xqdoc:function[fn:starts-with(fn:data(xqdoc:comment/xqdoc:description), "Helper function")];
  $xqdoc;
};

(:~
 : This function generates the XQDoc XHTML pages for all the XQDoc XML
 : documents found in $xqdocPath and writes the resulting pages to in
 : $targetPath. The hierarchy is preserved.
 :
 : @param $indexPath path to the XHTML index page.
 :)
declare sequential function doc2html:generateXQDocXhtml(
  $indexPath      as xs:string, $xqdocXmlPath   as xs:string,
  $xqdocXhtmlPath as xs:string, $leftMenu as element(menu),
  $modulesPath    as xs:string
) as xs:string* {
  let $indexHtmlDoc := file:read-xml($indexPath)
  return
  for $file in file:files($xqdocXmlPath, "\.xml$", fn:true())
  let $stepsFromIndex := fn:count(fn:tokenize($file, fn:concat("\", file:path-separator()))) - 2
  let $xmlFilePath := concat($xqdocXmlPath, file:path-separator(), $file)
  let $xhtmlFilePath := concat($xqdocXhtmlPath, file:path-separator(), fn:replace($file, "\.xml$", ".html"))
  let $xhtmlFileDir :=
    let $segments := fn:tokenize($xhtmlFilePath, fn:concat("\", file:path-separator()))
    let $lastSegm := $segments[fn:count($segments)]
    return fn:substring-before($xhtmlFilePath, $lastSegm)
  return
    try {
      let $xqdoc := doc2html:removeInternalFunctionality(file:read-xml($xmlFilePath)/xqdoc:xqdoc)
      let $moduleDoc := $xqdoc/xqdoc:module
      let $moduleName := $moduleDoc/xqdoc:name
      let $moduleUri := $moduleDoc/xqdoc:uri
      let $menu :=
{string($leftMenu/@title)}

      let $menu := doc2html:createModuleTable($leftMenu, $menu, $moduleUri)
      let $xhtml := xqdg:doc($xqdoc, $menu, $doc2html:indexCollector, $doc2html:schemasCollector)
      return block {
        file:mkdirs($xhtmlFileDir, false());

        doc2html:configure-xhtml($xhtml, $stepsFromIndex, $modulesPath);

        file:write($xhtmlFilePath, $xhtml, <s method="xhtml" indent="yes" />/@*);

        concat("
SUCCESS: ", $moduleUri, " (", $xhtmlFilePath, ")");
      }
    } catch * ($error_code) {
      concat("
FAILED: ", $xhtmlFilePath)
    }
};

declare sequential function doc2html:gatherSchemas(
  $modulesPath as xs:string) as xs:string* {

  for $filedirs in tokenize($modulesPath, ";")
  for $file in file:files($filedirs, "\.xsd$", fn:true())
  let $xsdFilePath := concat($modulesPath, file:path-separator(), $file)
  return
    try {
      let $xqdoc := file:read-xml($xsdFilePath)
      let $xsdUri := $xqdoc/xs:schema/@targetNamespace
      return block {
          doc2html:collectModule($xsdUri, $xsdFilePath, $doc2html:schemasCollector);
          concat("
  SUCCESS: ", $xsdUri, " (", $xsdFilePath, ")");
        }
      } catch * ($error_code) {
        concat("
  FAILED: ", $xsdFilePath)
      }
};
(:~
 : This function gathers the names of the XQDoc XHTML pages for all the XQDoc XML
 : documents found in $xqdocXmlPath. The hierarchy is preserved.
 :)
declare sequential function doc2html:gatherModules(
  $xqdocXmlPath as xs:string
){
  for $file in file:files($xqdocXmlPath, "\.xml$", fn:true())
  let $xmlFilePath := concat($xqdocXmlPath, file:path-separator(), $file)
  let $xhtmlRelativeFilePath := fn:replace($file, "\.xml$", ".html")
  let $xhtmlRelativeFilePathSlash := fn:replace($xhtmlRelativeFilePath, fn:concat("\", file:path-separator()), "/")
  return
  try {
      let $xqdoc := doc2html:removeInternalFunctionality(file:read-xml($xmlFilePath)/xqdoc:xqdoc)
      let $moduleDoc := $xqdoc/xqdoc:module
      let $moduleUri := $moduleDoc/xqdoc:uri
      return block {
        doc2html:collectModule($moduleUri/text(), $xhtmlRelativeFilePath, $doc2html:indexCollector);
        concat("
SUCCESS: ", $moduleUri, " (", $xmlFilePath, ")");
      }
    } catch * ($error_code) {
      concat("
FAILED: ", $xmlFilePath)
    }
};

declare sequential function doc2html:collectModule ($moduleUri as xs:string, $relativeFileName as xs:string, $collector) {
  insert node <module uri="{$moduleUri}" file="{$relativeFileName}" /> as last into $collector;
};

declare sequential function doc2html:getFilePath (
  $filename as xs:string, $modulesPath as xs:string
) as xs:string* {
  let $zorbaPath := replace($modulesPath,"/modules","")
  for $relPath in $doc2html:examplePath
  let $path := concat($zorbaPath,'/',$relPath)
  let $test := file:files($path,concat("^",$filename,"$"),fn:true())[1]
  return
  if (fn:exists($test)) then
    $test
  else
    ()
};

declare function doc2html:get-path-to-index ($stepsBack) as xs:string
{
  (: Error prone: stepsBack > stepBacks :)
  fn:substring($doc2html:stepBacks, 1, 3 * $stepsBack)
};

declare sequential function doc2html:configure-xhtml (
  $xhtml, $stepsFromIndex as xs:integer,
  $modulesPath as xs:string
) {
  let $pathToIndex := doc2html:get-path-to-index($stepsFromIndex)
  return
  (: replace the <test> nodes with eiter links to the actual files or inline the actual files based on the 'type' attribute value :)
  for $file in $xhtml//*:include
  let $type := $file/@type
  let $path := doc2html:getFilePath($file/text(), $modulesPath)
  let $read_text := file:read-text($path)
  return block {
  (: at the moment there is no way to ship the files defined as links with the packages/installers
    if (matches($type, "link")) then
      replace node $file with {$path}
    else :)
    if (matches($type, "inline")) then
      replace node $file with
        if (fn:exists($path)) then

 {$path}:

{$read_text}

        else

No example matching pattern '{$file/text()}' was found. Please update 'examplePath' variable.

        else ()
  };

  (: replace the function type description with images :)
  let $xquSpec := "http://www.w3.org/TR/xquery-update-10/",
      $xqsSpec := "http://www.w3.org/TR/xquery-sx-10/#dt-sequential-function",
      $xq11Spec := "http://www.w3.org/TR/xquery-11/#FunctionDeclns"
  let $pathToIndex := doc2html:get-path-to-index($stepsFromIndex)
  let $imagesPath := concat($pathToIndex, "images/")
  for $typeTd in $xhtml//*:td
  where $typeTd/@class eq "type"
  let $type := $typeTd/text()
  return block {
    if (matches($type, "updating")) then
      replace node $typeTd/text() with

    else if (matches($type, "sequential")) then
      replace node $typeTd/text() with

    else if (matches($type, "nondeterministic")) then
      replace node $typeTd/text() with

    else ();
  };

  (: replace the function names description with images+name of the functions :)
  let $xquSpec := "http://www.w3.org/TR/xquery-update-10/",
      $xqsSpec := "http://www.w3.org/TR/xquery-sx-10/#dt-sequential-function",
      $xq11Spec := "http://www.w3.org/TR/xquery-11/#FunctionDeclns"
  let $pathToIndex := doc2html:get-path-to-index($stepsFromIndex)
  let $imagesPath := concat($pathToIndex, "images/")
  for $func in $xhtml//*:div
  where $func/@class eq "subsection"
  let $funcName := $func/text()
  return block {
    if (starts-with($funcName, "updating")) then
      replace node $func/text() with
        (,
        text {substring-after($funcName, "updating")})

    else if (starts-with($funcName, "sequential")) then
      replace node $func/text() with
        (,
        text {substring-after($funcName, "sequential")})

    else if (starts-with($funcName, "nondeterministic")) then
      replace node $func/text() with
        (,
        text {substring-after($funcName, "nondeterministic")})
    else ();
  };

  $xhtml;
};

declare sequential function doc2html:createModuleTable($leftMenu as element(menu), $root, $moduleUri) {
  for $cat1 in $leftMenu/category
  return block {
    doc2html:createModuleHelper($root, $cat1, $moduleUri);
    for $cat2 in $cat1/category
    let $table2 := $root/li[fn:last()]/ul
    return block {
      doc2html:createModuleHelper($table2, $cat2, $moduleUri);
      for $cat3 in $cat2/category
      let $table3 := $root/li[fn:last()]/ul/li[fn:last()]/ul
      return block {
        doc2html:createModuleHelper($table3, $cat3, $moduleUri);
      };
    };
  };

  $root;
};

declare sequential function doc2html:createModuleHelper($table, $category, $moduleUri)
{
  block {
    insert nodes
{data($category/@name)}

    {
     for $module in $doc2html:indexCollector/module
      order by fn:data($module/@uri)
      return
        if(fn:starts-with(fn:string($module/@uri),data($category/@uri))
           and fn:not(fn:contains (fn:substring-after(data($module/@uri),fn:concat(data($category/@uri),'/')),'/'))) then
          if(fn:string($module/@uri) = $moduleUri) then

{fn:substring-after(data($module/@uri),fn:concat(data($category/@uri),'/'))}

          else

{fn:substring-after(data($module/@uri),fn:concat(data($category/@uri),'/'))}

        else ()
    }

    as last into $table
  };

  $table;
};

(:~
 : This function reads, updates and returns the new index.html.
 :
 : @param $indexPath Where to search for XML XQDoc documents recursively.
 : @return The content of the new index.html.
 :)
declare sequential function doc2html:generateIndexHtml($indexPath as xs:string, $menu, $modules) as document-node() {
    let $indexHtmlDoc := file:read-xml($indexPath)
    return block {
        insert nodes $menu
        as last into $indexHtmlDoc/*:html/*:body/*:div[@id='main']/*:div[@id='leftMenu'];

        let $module_list := $indexHtmlDoc/*:html/*:body/*:div[@id='main']/*:div[@id='rightcontent']/*:div[@id='module_list']
        return
          if ($module_list)
          then
            insert node $modules as last into $module_list
          else
            ();

        $indexHtmlDoc;
    }
};

declare sequential function doc2html:main(
  $modulePath as xs:string, $xqdocBuildPath as xs:string,
  $indexHtmlPath as xs:string
) {
  let $leftMenu :=
  <menu title="XQuery Modules">
  <category name="http://expath.org/ns" uri="http://expath.org/ns" />
  <category name="http://www.zorba-xquery.com/modules" uri="http://www.zorba-xquery.com/modules" >
    <category name="email" uri="http://www.zorba-xquery.com/modules/email" />
    <category name="excel" uri="http://www.zorba-xquery.com/modules/excel" />
    <category name="image" uri="http://www.zorba-xquery.com/modules/image" />
    <category name="introspection" uri="http://www.zorba-xquery.com/modules/introspection" />
    <category name="security" uri="http://www.zorba-xquery.com/modules/security" />
    <category name="oauth" uri="http://www.zorba-xquery.com/modules/oauth" />
    <category name="webservices" uri="http://www.zorba-xquery.com/modules/webservices" >
      <category name="google" uri="http://www.zorba-xquery.com/modules/webservices/google" />
      <category name="yahoo" uri="http://www.zorba-xquery.com/modules/webservices/yahoo" />
    </category>
  </category>
  <category name="http://www.w3.org/2005" uri="http://www.w3.org/2005" />
  </menu>
  let $menu :=

      {string($leftMenu/@title)}

  return doc2html:main($menu, $leftMenu, $modulePath, $xqdocBuildPath, $indexHtmlPath)
};

declare sequential function doc2html:main(
  $menu as element(ul),  $leftMenu as element(menu),
  $modulePath as xs:string, $xqdocBuildPath as xs:string,
  $indexHtmlPath as xs:string
) {
  declare $xqdocXmlPath   as xs:string := fn:concat($xqdocBuildPath, file:path-separator(), "xml");
  declare $xqdocXhtmlPath as xs:string := fn:concat($xqdocBuildPath, file:path-separator(), "xhtml");
  declare $xqdocSchemasPath as xs:string := fn:concat($xqdocBuildPath, file:path-separator(), "schemas");

  (: generate the XQDoc XML for all the modules :)
  if (file:mkdirs($xqdocXmlPath, false())) then
  (
    doc2html:clearFolder($xqdocXmlPath,"\.xml$"),
    doc2html:generateXQDocXml($modulePath, $xqdocXmlPath)
  )
  else
    error()
  ;

  (: generate the XQDoc XHTML for all the modules :)
  let $absoluteXhtmlDir := concat($xqdocBuildPath, "/xhtml")
  return
  if (file:mkdirs($absoluteXhtmlDir, false())) then
  (
    doc2html:clearFolder($xqdocXhtmlPath,"xqdoc\.html$"),
    doc2html:gatherModules($xqdocXmlPath),
    doc2html:gatherSchemas($xqdocSchemasPath),
    doc2html:generateXQDocXhtml($indexHtmlPath, $xqdocXmlPath, $xqdocXhtmlPath, $leftMenu, $modulePath)
  )
  else
    error()
  ;

  let $left :=

                {string($leftMenu/@title)}

  let $index1 := doc2html:createModuleTable($leftMenu, $left, "index.html")
  let $right :=

  let $index2 := doc2html:createModuleTable($leftMenu, $right, "index.html")
  let $doc := doc2html:generateIndexHtml($indexHtmlPath, $index1, $index2)
  return doc2html:configure-xhtml($doc/*:html, 0, $modulePath)
  ;

};