Add back a few old routing examples

Add back a few old routing examples

xquery version "3.0";

(:~
 : Example Fold App
 :
 : @version 0.1
 : @author Marc van Grootel
 : @see https://github.com/xokomola/fold-app
 :)
module namespace app ='http://xokomola.com/xquery/fold';

declare default function namespace 'http://xokomola.com/xquery/fold/routes';

import module namespace route = 'http://xokomola.com/xquery/fold/routes'
    at 'fold/core/routes.xqm';
import module namespace res = 'http://xokomola.com/xquery/fold/response'
    at 'fold/core/response.xqm';
import module namespace μ = 'http://xokomola.com/xquery/origami/μ'
    at 'origami/mu.xqm';
import module namespace wrap = 'http://xokomola.com/xquery/fold/middleware'
    at 'fold/core/middleware.xqm';
import module namespace handler = 'http://xokomola.com/xquery/fold/handler'
    at 'fold/core/handler.xqm';
import module namespace req = 'http://xokomola.com/xquery/fold/request'
    at 'fold/core/request.xqm';

declare variable $app:landing-content as element(page) :=
    <page>
        <hero>
            <h>
                Write Web applications using XQuery 3 and the BaseX XML database
            </h>
        </hero>
        <values>
            <col>
                <h>BaseX</h>

A fast, lightweight XQuery 3 XML database that comes with batteries included.

                Try BaseX
            </col>
            <col>
                <h>+ Fold</h>

Compose request handlers and middleware to build web applications
                and REST services.

                Try Fold
            </col>
            <col>
                <h>+ Origami</h>

Composable page templates. Can also be used as general templating library.

                Try Origami
            </col>
        </values>
        <help>
            <h>Need help getting started?</h>

Learn how to build web applications using Origami and Fold.

            View tutorials
        </help>
        <categories>
            <h>Demos</h>

Try out various demos

            Start now!
        </categories>
    </page>;

(: ---- /math service ---- :)

declare function app:routes()
{
    route:route($app:routes)
};

declare variable $app:routes := (
    context('/math', $app:sum-routes),
    (: sniffer is pretty expensive and almost triples the response time :)
    (: wrap:sniffer(context('/simple',        $app:simple-routes)), :)
    context('/simple',        $app:simple-routes),
    GET(('/pingpong/{turns}', map { 'turns': '\d+' }), app:pingpong(app:bat('ping'), app:bat('pong'), 'turns')),
    GET('/', function($req) {
        app:landing-page($app:landing-content)
    }),
    (: we never get here e.g. with /lsdkfjl :)
    not-found(<not-found>No more examples for you!</not-found>)
);

declare variable $app:simple-routes := (
    GET('/greeting/{name}', function($request) { res:ok('Hello ' || req:get-param($request, 'name') || '!') }),
    GET('/dump',            wrap:params(handler:dump#1)),
    GET('/context',         function($request) { res:ok(inspect:context()) }),
    GET('/txt',             function($request) { 'hello i am ', ' just a string' }),
    GET('/xml',             function($request) { <hello><world/></hello> }),
    POST('/post',           wrap:params(handler:dump#1)),
    not-found(<not-found>No more examples for you!</not-found>)
);

declare variable $app:sum-routes := (
    GET(('/sum/{a}/{b}', map { 'a': '\d+', 'b': '\d+' }),
        ('a|integer', 'b|integer'),
        app:sum#2)
);

declare function app:sum($x as xs:integer, $y as xs:integer) {
    'Sum is: ' || $x + $y
};

(:~
 : A silly ping-pong game.
 :
 : /examples/pingpong/40
 : starts a game of 40 turns between two players.
 :)
declare function app:pingpong($h1, $h2, $turns) {
    function($request) {
        let $n := xs:integer($request('params')($turns))
        return
            res:ok(hof:until(
                function($x) { $x('hits') eq $n },
                app:play($h2, $h1),
                map:merge(($request, map { 'hits': 0 }))
            )('body'))
    }
};

(:~ Makes a pingpong bat :)
declare function app:bat($sound as xs:string) {
    function($request) {
        let $body :=
            $request('body') || $sound || ' #' || $request('hits') || '
'
        return
            map:merge(($request, map { 'body': $body })) }
};

(:~ Take turns between player 1 and 2 :)
declare function app:play($h1, $h2)  {
    function($request) {
        let $request := map:merge(($request, map { 'hits': $request('hits') + 1 }))
        return
            if ($request('hits') mod 2 = 0) then
                $h1($request)
            else
                $h2($request)
    }
};

declare function app:landing-page($content)
{
    app:page(['h:body',
        ['h:div', map { 'class': 'section hero' },
            ['h:div', map { 'class': 'container' },
                ['h:div', map { 'class': 'row' },
                    ['h:div', map { 'class': 'one-half column' },
                        ['h:h4', map { 'class': 'hero-heading' },
                            μ:content($content/hero/h) ],
                        for $link in $content/hero/a
                        return
                            ['h:a', map { 'class': 'button button-primary', 'href': fn:string($link/@href) },
                                μ:content($link)]
                    ],
                    ['h:div', map { 'class': 'one-half column phones' },
                        ['h:img', map { 'class': 'phone', 'src': '/static/logo240.png' }]
                    ]
                ]
            ]
        ],

        ['h:div', map { 'class': 'section values' },
            ['h:div', map { 'class': 'container' },
                ['h:div', map { 'class': 'row' },
                    for $sect in $content/values/col
                    return
                        ['h:div', map { 'class': 'one-third column value' },
                            ['h:h4', map { 'class': 'value-heading' }, μ:content($sect/h)],
                            ['h:p', map { 'class': 'value-description' }, μ:content($sect/p)]
                        ]
                ],
                ['h:div', map { 'class': 'row' },
                    for $sect in $content/values/col
                    return
                        ['h:div', map { 'class': 'one-third column value' },
                            for $link in $sect/a
                            return
                                ['h:a', map { 'class': 'button button-primary', 'href': fn:string($link/@href) },
                                    μ:content($link)]
                        ]

                ]
            ]
        ],

        ['h:div', map { 'class': 'section get-help' },
            ['h:div', map { 'class': 'container' },
                ['h:h3', map { 'class': 'section-heading' }, μ:content($content/help/h)],
                ['h:p', map { 'class': 'section-description' }, μ:content($content/help/p)],
                ['h:a', map { 'class': 'button button-primary', 'href': fn:string($content/help/a/@href) },
                    μ:content($content/help/a)]
            ]
        ],

        ['h:div', map { 'class': 'section categories' },
            ['h:div', map { 'class': 'container' },
                ['h:h3', map { 'class': 'section-heading' }, μ:content($content/categories/h)],
                ['h:p', map { 'class': 'section-description' },
                    μ:content($content/categories/p)],
                ['h:a', map { 'class': 'button button-primary', 'href': fn:string($content/categories/a/@href) },
                    μ:content($content/categories/a)]
            ]
        ]
    ])
};

declare function app:page($items as array(*)?)
{
    res:ok(μ:xml(
        ['h:html',
            ['h:head',
                ['h:meta', map { 'charset': 'utf-8' }],
                ['h:title', 'Fold & Origami Example App'],
                ['h:meta', map { 'name': 'viewport', 'content': 'width=device-width, initial-scale=1'}],
                ['h:link', map { 'href': 'http://fonts.googleapis.com/css?family=Raleway:400,300,600', 'rel': 'stylesheet', 'type': 'text/css' }],
                ['h:link', map { 'rel': 'stylesheet', 'href': '/static/css/normalize.css' }],
                ['h:link', map { 'rel': 'stylesheet', 'href': '/static/css/skeleton.css' }],
                ['h:link', map { 'rel': 'stylesheet', 'href': '/static/css/custom.css' }],
                ['h:link', map { 'rel': 'icon', 'type': 'image/png', 'href': '/static/images/favicon.png' }]
            ],
            $items
        ]))
};

xquery version "3.0";

(:~
 : Example Fold App
 :
 : @version 0.1
 : @author Marc van Grootel
 : @see https://github.com/xokomola/fold-app
 :)
module namespace app ='http://xokomola.com/xquery/fold';

declare default function namespace 'http://xokomola.com/xquery/fold/routes';

import module namespace route = 'http://xokomola.com/xquery/fold/routes'
    at 'fold/core/routes.xqm';
import module namespace res = 'http://xokomola.com/xquery/fold/response'
    at 'fold/core/response.xqm';
import module namespace μ = 'http://xokomola.com/xquery/origami/μ'
    at 'origami/mu.xqm';

declare variable $app:landing-content as element(page) :=
    <page>
        <hero>
            <h>
                Write Web applications using XQuery 3 and the BaseX XML database
            </h>
        </hero>
        <values>
            <col>
                <h>BaseX</h>

A fast, lightweight XQuery 3 XML database that comes with batteries included.

                Try BaseX
            </col>
            <col>
                <h>+ Fold</h>

Compose request handlers and middleware to build web applications
                and REST services.

                Try Fold
            </col>
            <col>
                <h>+ Origami</h>

Composable page templates. Can also be used as general templating library.

                Try Origami
            </col>
        </values>
        <help>
            <h>Need help getting started?</h>

Learn how to build web applications using Origami and Fold.

            View tutorials
        </help>
        <categories>
            <h>Demos</h>

Try out various demos

            Start now!
        </categories>
    </page>;

(: ---- /math service ---- :)

declare function app:routes()
{
    route:route($app:routes)
};

declare variable $app:routes := (
    context('/math', $app:sum-routes),
    GET('/', function($req) {
        app:landing-page($app:landing-content)
    })
);

declare variable $app:sum-routes := (
    GET(('/sum/{a}/{b}', map { 'a': '\d+', 'b': '\d+' }),
        ('a|integer', 'b|integer'),
        app:sum#2)
);

declare function app:sum($x as xs:integer, $y as xs:integer) {
    'Sum is: ' || $x + $y
};

declare function app:landing-page($content)
{
    app:page(['h:body',
        ['h:div', map { 'class': 'section hero' },
            ['h:div', map { 'class': 'container' },
                ['h:div', map { 'class': 'row' },
                    ['h:div', map { 'class': 'one-half column' },
                        ['h:h4', map { 'class': 'hero-heading' },
                            μ:content($content/hero/h)],
                        for $link in $content/hero/a
                        return
                            ['h:a', map { 'class': 'button button-primary', 'href': fn:string($link/@href) },
                                μ:content($link)]
                    ],
                    ['h:div', map { 'class': 'one-half column phones' },
                        ['h:img', map { 'class': 'phone', 'src': '/static/logo240.png' }]
                    ]
                ]
            ]
        ],

        ['h:div', map { 'class': 'section values' },
            ['h:div', map { 'class': 'container' },
                ['h:div', map { 'class': 'row' },
                    for $sect in $content/values/col
                    return
                        ['h:div', map { 'class': 'one-third column value' },
                            ['h:h4', map { 'class': 'value-heading' }, μ:content($sect/h)],
                            ['h:p', map { 'class': 'value-description' }, μ:content($sect/p)]
                        ]
                ],
                ['h:div', map { 'class': 'row' },
                    for $sect in $content/values/col
                    return
                        ['h:div', map { 'class': 'one-third column value' },
                            for $link in $sect/a
                            return
                                ['h:a', map { 'class': 'button button-primary', 'href': fn:string($link/@href) },
                                    μ:content($link)]
                        ]

                ]
            ]
        ],

        ['h:div', map { 'class': 'section get-help' },
            ['h:div', map { 'class': 'container' },
                ['h:h3', map { 'class': 'section-heading' }, μ:content($content/help/h)],
                ['h:p', map { 'class': 'section-description' }, μ:content($content/help/p)],
                ['h:a', map { 'class': 'button button-primary', 'href': fn:string($content/help/a/@href) },
                    μ:content($content/help/a)]
            ]
        ],

        ['h:div', map { 'class': 'section categories' },
            ['h:div', map { 'class': 'container' },
                ['h:h3', map { 'class': 'section-heading' }, μ:content($content/categories/h)],
                ['h:p', map { 'class': 'section-description' },
                    μ:content($content/categories/p)],
                ['h:a', map { 'class': 'button button-primary', 'href': fn:string($content/categories/a/@href) },
                    μ:content($content/categories/a)]
            ]
        ]
    ])
};

declare function app:page($items as array(*)?)
{
    res:ok(μ:xml(
        ['h:html',
            ['h:head',
                ['h:meta', map { 'charset': 'utf-8' }],
                ['h:title', 'Fold & Origami Example App'],
                ['h:meta', map { 'name': 'viewport', 'content': 'width=device-width, initial-scale=1'}],
                ['h:link', map { 'href': 'http://fonts.googleapis.com/css?family=Raleway:400,300,600', 'rel': 'stylesheet', 'type': 'text/css' }],
                ['h:link', map { 'rel': 'stylesheet', 'href': '/static/css/normalize.css' }],
                ['h:link', map { 'rel': 'stylesheet', 'href': '/static/css/skeleton.css' }],
                ['h:link', map { 'rel': 'stylesheet', 'href': '/static/css/custom.css' }],
                ['h:link', map { 'rel': 'icon', 'type': 'image/png', 'href': '/static/images/favicon.png' }]
            ],
            $items
        ]))
};


added namespaces to SVS responses

added namespaces to SVS responses

(:~
: This is the Care Services Discovery stored query registry
: @version 1.0
: @see https://github.com/his-interop/openinfoman
:
:)
module namespace svs_lsvs = "https://github.com/his-interop/openinfoman/svs_lsvs";
declare namespace svs = "urn:ihe:iti:svs:2008";

(:WARNING: ValueSet have @id while DesribedValueSet has @ID:)

declare variable $svs_lsvs:vers := "1.1";
declare variable $svs_lsvs:base_path := '../resources/shared_value_sets/';
declare variable $svs_lsvs:valuesets_doc := "DescribedSharedValueSets.xml";
declare variable $svs_lsvs:sample_value_set_list := svs_lsvs:get_sample_value_set_list();
declare variable $svs_lsvs:blank_valuesets :=  <DescribedValueSets version="{$svs_lsvs:vers}"/>;

declare updating function svs_lsvs:init_store($db) {
  if (not(db:is-xml($db,$svs_lsvs:valuesets_doc))) then
    db:add($db, $svs_lsvs:blank_valuesets,$svs_lsvs:valuesets_doc)
  else
    ()
};

declare function svs_lsvs:store_exists($db) {
  db:is-xml($db,$svs_lsvs:valuesets_doc)
};

declare function svs_lsvs:sample_sets() {
  for $file in file:list($svs_lsvs:base_path,true(),'*.xml')
  return file:resolve-path(concat($svs_lsvs:base_path,"/",$file))
};

declare function svs_lsvs:get_sample_value_set_list() {
<DescribedValueSets version="{$svs_lsvs:vers}">
  {
  for $file in svs_lsvs:sample_sets()
  let $value_set_doc := doc($file)
  let $id :=text{$value_set_doc/svs:ValueSet/@id} (:ValueSet have @id while DesribedValueSet has @ID:)
  let $displayName :=text{$value_set_doc/svs:ValueSet/@displayName}
  let $version :=text{$value_set_doc/svs:ValueSet/@version}
  return
    if ($id)
      then
      <svs:DescribedValueSet ID="{$id}" file="{$file}" displayName="{$displayName}" version="{$version}"/>
    else (<noID>{$file}</noID>)
  }
</DescribedValueSets>
};

declare function svs_lsvs:get_all_value_set_list($db) {
  let $vsets := db:open($db,$svs_lsvs:valuesets_doc)
  let $existing_ids := $vsets//svs:DescribedValueSet/@ID
  let $available_ids := $svs_lsvs:sample_value_set_list//svs:DescribedValueSet/@ID
  return <DescribedValueSets version="{$svs_lsvs:vers}">
  {
    (
      for $id in $existing_ids
      return if ($id = $available_ids)
	then   $svs_lsvs:sample_value_set_list/svs:DescribedValueSet[@ID=$id]
      else  <svs:DescribedValueSet
	ID="{$id}"
	displayName="{$vsets//svs:DescribedValueSet[@ID = $id]/@displayName}"
	version="{$vsets//svs:DescribedValueSet[@ID = $id]/@version}"/>
      ,
      for $id in $available_ids
      where not($id = $existing_ids)
      return    $svs_lsvs:sample_value_set_list/svs:DescribedValueSet[@ID=$id]
      )
  }
  </DescribedValueSets>
};

declare function svs_lsvs:get_document_source($id) {
  text{$svs_lsvs:sample_value_set_list/svs:DescribedValueSet[@ID=$id]/@file}
};

declare function svs_lsvs:exists($db,$id) {
  svs_lsvs:store_exists($db)
  and
  exists(db:open($db,$svs_lsvs:valuesets_doc)//svs:DescribedValueSet[@ID = $id])
};

declare updating function svs_lsvs:load($db,$id) {
  if (not(svs_lsvs:exists($db,$id)))  then
    let $doc_source := svs_lsvs:get_document_source($id)
    return if (not($doc_source))
      then  ()
    else
      let $svs_sets := db:open($db,$svs_lsvs:valuesets_doc)/DescribedValueSets
      let $svs := parse-xml(file:read-text($doc_source))
      for $val_set in $svs//svs:ValueSet
      let $described_val_set :=
      <svs:DescribedValueSet ID="{$val_set/@id}" displayName="{$val_set/@displayName}" version="{$val_set/@version}">
	{$val_set/*}
      </svs:DescribedValueSet>
      return insert node $described_val_set into $svs_sets
  else
    ()
};

declare updating function svs_lsvs:reload($db,$id) {
  let $vsets := db:open($db,$svs_lsvs:valuesets_doc)
  let $existing := $vsets//svs:DescribedValueSet[@ID = $id]
  return
    if (exists($existing))
      then
        (delete node $existing,
	svs_lsvs:load($db,$id))
      else
	svs_lsvs:load($db,$id)
};

declare function svs_lsvs:get_multiple_described_value_sets($db,$filter) {
  let $dvs0 := db:open($db,$svs_lsvs:valuesets_doc)//svs:DescribedValueSet
  let $dvs1 := if (not($filter/@ID = '')) then $dvs0[@ID = $filter/@ID] else $dvs0
  let $dvs2 := if (not($filter/@DisplayNameContains = '')) then $dvs1[contains(@displayName,$filter/@DisplayNameContains)] else $dvs1
  let $dvs3 := if (not($filter/@SourceContains = '')) then $dvs2[contains(./svs:Source,$filter/@SourceContains)] else $dvs2
  let $dvs4 := if (not($filter/@PurposeContains = '')) then $dvs3[contains(./svs:Purpose,$filter/@PurposeContains)] else $dvs3
  let $dvs5 := if (not($filter/@DefinitionContains = '')) then $dvs4[contains(./svs:Definition,$filter/@DefinitionContains)] else $dvs4
  let $dvs6 := if (not($filter/@GroupContains = '')) then $dvs5[contains(./svs:Group,$filter/@GroupContains)] else $dvs5
  let $dvs7 := if (not($filter/@GroupOID = '')) then $dvs6[./svs:Group = $filter/@GroupOID] else $dvs6
  let $dvs8 := if (not($filter/@EffectiveDateBefore = '')) then $dvs7[./svs:EffectiveDate < @EffectiveDateBefore] else $dvs7
  let $dvs9 := if (not($filter/@EffectiveDateAfter = '')) then $dvs8[./svs:EffectiveDate > @EffectiveDateAfter] else $dvs8
  let $dvs10 := if (not($filter/@ExpirationDateBefore = '')) then $dvs9[./svs:ExpirationDate < @ExpirationDateBefore] else $dvs9
  let $dvs11 := if (not($filter/@ExpirationDateAfter = '')) then $dvs10[./svs:ExpirationDate > @ExpirationDateAfter] else $dvs10
  let $dvs12 := if (not($filter/@CreationDateBefore = '')) then $dvs11[./svs:CreationDate < @CreationDateBefore] else $dvs11
  let $dvs13 := if (not($filter/@CreationDateAfter = '')) then $dvs12[./svs:CreationDate > @CreationDateAfter] else $dvs12
  let $dvs14 := if (not($filter/@RevisionDateBefore = '')) then $dvs13[./svs:RevisionDate < @RevisionDateBefore] else $dvs13
  let $dvs15 := if (not($filter/@RevisionDateAfter = '')) then $dvs14[./svs:RevisionDate > @RevisionDateAfter] else $dvs14

  return  <svs:RetrieveMultipleValueSetsResponse >{$dvs15} </svs:RetrieveMultipleValueSetsResponse>

};

declare function svs_lsvs:get_single_version_value_set($db,$id, $version,$lang) {
  let $vs0 := db:open($db,$svs_lsvs:valuesets_doc)//svs:DescribedValueSet[@ID=$id]
  let $vers := if (not($version = '')) then $version else max(xs:int($vs0/@version))
  let $vs1:= $vs0[@version = $vers]

  let $concept_lists :=
    if (not($lang = ''))
      then
      $vs1/svs:ConceptList[@xml:lang = $lang]
    else
      $vs1/svs:ConceptList

  return
  <svs:RetrieveValueSetResponse version="{$vers}" id="{$id}">
    {
      for $concept_list in $concept_lists
      let $val_set := $concept_list/..
      return
	(:ValueSet have @id while DesribedValueSet has @ID:)
	<svs:ValueSet id="{$val_set/@ID}" displayName="{$val_set/@displayName}" version="{$val_set/@version}">
	  {$concept_list}
	</svs:ValueSet>

    }
  </svs:RetrieveValueSetResponse>
};

declare function svs_lsvs:get_single_version_code($db,$code,$id, $version,$lang) {
  let $vs0 := db:open($db,$svs_lsvs:valuesets_doc)//svs:DescribedValueSet[@ID=$id]
  let $vers := if (not($version = '')) then $version else max(xs:int($vs0/@version))
  let $vs1:= $vs0[@version = $vers]

  let $concept_lists :=
    if (not($lang = ''))
      then
      $vs1/svs:ConceptList[@xml:lang = $lang]
    else
      $vs1/svs:ConceptList

  let $concepts :=  $concept_lists/svs:Concept[@code = $code]

  return <RetrieveValueSetCodeResponse> (:Not to SVS standard :)
  {
    for $concept in $concepts
    let $concept_list := $concept/..
    let $val_set := $concept_list/..
    return
      (:ValueSet have @id while DesribedValueSet has @ID:)
    <svs:ValueSet id="{$val_set/@ID}" displayName="{$val_set/@displayName}" version="{$val_set/@version}">
      <svs:ConceptList xml:lang="$concept_list/@xml:lang">
	{$concept}
      </svs:ConceptList>
    </svs:ValueSet>
  }
  </RetrieveValueSetCodeResponse>
};

(:~
: This is the Care Services Discovery stored query registry
: @version 1.0
: @see https://github.com/his-interop/openinfoman
:
:)
module namespace svs_lsvs = "https://github.com/his-interop/openinfoman/svs_lsvs";
declare namespace svs = "urn:ihe:iti:svs:2008";

(:WARNING: ValueSet have @id while DesribedValueSet has @ID:)

declare variable $svs_lsvs:vers := "1.1";
declare variable $svs_lsvs:base_path := '../resources/shared_value_sets/';
declare variable $svs_lsvs:valuesets_doc := "DescribedSharedValueSets.xml";
declare variable $svs_lsvs:sample_value_set_list := svs_lsvs:get_sample_value_set_list();
declare variable $svs_lsvs:blank_valuesets :=  <DescribedValueSets version="{$svs_lsvs:vers}"/>;

declare updating function svs_lsvs:init_store($db) {
  if (not(db:is-xml($db,$svs_lsvs:valuesets_doc))) then
    db:add($db, $svs_lsvs:blank_valuesets,$svs_lsvs:valuesets_doc)
  else
    ()
};

declare function svs_lsvs:store_exists($db) {
  db:is-xml($db,$svs_lsvs:valuesets_doc)
};

declare function svs_lsvs:sample_sets() {
  for $file in file:list($svs_lsvs:base_path,true(),'*.xml')
  return file:resolve-path(concat($svs_lsvs:base_path,"/",$file))
};

declare function svs_lsvs:get_sample_value_set_list() {
<DescribedValueSets version="{$svs_lsvs:vers}">
  {
  for $file in svs_lsvs:sample_sets()
  let $value_set_doc := doc($file)
  let $id :=text{$value_set_doc/svs:ValueSet/@id} (:ValueSet have @id while DesribedValueSet has @ID:)
  let $displayName :=text{$value_set_doc/svs:ValueSet/@displayName}
  let $version :=text{$value_set_doc/svs:ValueSet/@version}
  return
    if ($id)
      then
      <svs:DescribedValueSet ID="{$id}" file="{$file}" displayName="{$displayName}" version="{$version}"/>
    else (<noID>{$file}</noID>)
  }
</DescribedValueSets>
};

declare function svs_lsvs:get_all_value_set_list($db) {
  let $vsets := db:open($db,$svs_lsvs:valuesets_doc)
  let $existing_ids := $vsets//svs:DescribedValueSet/@ID
  let $available_ids := $svs_lsvs:sample_value_set_list//svs:DescribedValueSet/@ID
  return <DescribedValueSets version="{$svs_lsvs:vers}">
  {
    (
      for $id in $existing_ids
      return if ($id = $available_ids)
	then   $svs_lsvs:sample_value_set_list/svs:DescribedValueSet[@ID=$id]
      else  <svs:DescribedValueSet
	ID="{$id}"
	displayName="{$vsets//svs:DescribedValueSet[@ID = $id]/@displayName}"
	version="{$vsets//svs:DescribedValueSet[@ID = $id]/@version}"/>
      ,
      for $id in $available_ids
      where not($id = $existing_ids)
      return    $svs_lsvs:sample_value_set_list/svs:DescribedValueSet[@ID=$id]
      )
  }
  </DescribedValueSets>
};

declare function svs_lsvs:get_document_source($id) {
  text{$svs_lsvs:sample_value_set_list/svs:DescribedValueSet[@ID=$id]/@file}
};

declare function svs_lsvs:exists($db,$id) {
  svs_lsvs:store_exists($db)
  and
  exists(db:open($db,$svs_lsvs:valuesets_doc)//svs:DescribedValueSet[@ID = $id])
};

declare updating function svs_lsvs:load($db,$id) {
  if (not(svs_lsvs:exists($db,$id)))  then
    let $doc_source := svs_lsvs:get_document_source($id)
    return if (not($doc_source))
      then  ()
    else
      let $svs_sets := db:open($db,$svs_lsvs:valuesets_doc)/DescribedValueSets
      let $svs := parse-xml(file:read-text($doc_source))
      for $val_set in $svs//svs:ValueSet
      let $described_val_set :=
      <svs:DescribedValueSet ID="{$val_set/@id}" displayName="{$val_set/@displayName}" version="{$val_set/@version}">
	{$val_set/*}
      </svs:DescribedValueSet>
      return insert node $described_val_set into $svs_sets
  else
    ()
};

declare updating function svs_lsvs:reload($db,$id) {
  let $vsets := db:open($db,$svs_lsvs:valuesets_doc)
  let $existing := $vsets//svs:DescribedValueSet[@ID = $id]
  return
    if (exists($existing))
      then
        (delete node $existing,
	svs_lsvs:load($db,$id))
      else
	svs_lsvs:load($db,$id)
};

declare function svs_lsvs:get_multiple_described_value_sets($db,$filter) {
  let $dvs0 := db:open($db,$svs_lsvs:valuesets_doc)//svs:DescribedValueSet
  let $dvs1 := if (not($filter/@ID = '')) then $dvs0[@ID = $filter/@ID] else $dvs0
  let $dvs2 := if (not($filter/@DisplayNameContains = '')) then $dvs1[contains(@displayName,$filter/@DisplayNameContains)] else $dvs1
  let $dvs3 := if (not($filter/@SourceContains = '')) then $dvs2[contains(./svs:Source,$filter/@SourceContains)] else $dvs2
  let $dvs4 := if (not($filter/@PurposeContains = '')) then $dvs3[contains(./svs:Purpose,$filter/@PurposeContains)] else $dvs3
  let $dvs5 := if (not($filter/@DefinitionContains = '')) then $dvs4[contains(./svs:Definition,$filter/@DefinitionContains)] else $dvs4
  let $dvs6 := if (not($filter/@GroupContains = '')) then $dvs5[contains(./svs:Group,$filter/@GroupContains)] else $dvs5
  let $dvs7 := if (not($filter/@GroupOID = '')) then $dvs6[./svs:Group = $filter/@GroupOID] else $dvs6
  let $dvs8 := if (not($filter/@EffectiveDateBefore = '')) then $dvs7[./svs:EffectiveDate < @EffectiveDateBefore] else $dvs7
  let $dvs9 := if (not($filter/@EffectiveDateAfter = '')) then $dvs8[./svs:EffectiveDate > @EffectiveDateAfter] else $dvs8
  let $dvs10 := if (not($filter/@ExpirationDateBefore = '')) then $dvs9[./svs:ExpirationDate < @ExpirationDateBefore] else $dvs9
  let $dvs11 := if (not($filter/@ExpirationDateAfter = '')) then $dvs10[./svs:ExpirationDate > @ExpirationDateAfter] else $dvs10
  let $dvs12 := if (not($filter/@CreationDateBefore = '')) then $dvs11[./svs:CreationDate < @CreationDateBefore] else $dvs11
  let $dvs13 := if (not($filter/@CreationDateAfter = '')) then $dvs12[./svs:CreationDate > @CreationDateAfter] else $dvs12
  let $dvs14 := if (not($filter/@RevisionDateBefore = '')) then $dvs13[./svs:RevisionDate < @RevisionDateBefore] else $dvs13
  let $dvs15 := if (not($filter/@RevisionDateAfter = '')) then $dvs14[./svs:RevisionDate > @RevisionDateAfter] else $dvs14

  return  <RetrieveMultipleValueSetsResponse >{$dvs15} </RetrieveMultipleValueSetsResponse>

};

declare function svs_lsvs:get_single_version_value_set($db,$id, $version,$lang) {
  let $vs0 := db:open($db,$svs_lsvs:valuesets_doc)//svs:DescribedValueSet[@ID=$id]
  let $vers := if (not($version = '')) then $version else max(xs:int($vs0/@version))
  let $vs1:= $vs0[@version = $vers]

  let $concept_lists :=
    if (not($lang = ''))
      then
      $vs1/svs:ConceptList[@xml:lang = $lang]
    else
      $vs1/svs:ConceptList

  return
  <RetrieveValueSetResponse version="{$vers}" id="{$id}">
    {
      for $concept_list in $concept_lists
      let $val_set := $concept_list/..
      return
	(:ValueSet have @id while DesribedValueSet has @ID:)
	<svs:ValueSet id="{$val_set/@ID}" displayName="{$val_set/@displayName}" version="{$val_set/@version}">
	  {$concept_list}
	</svs:ValueSet>

    }
  </RetrieveValueSetResponse>
};

declare function svs_lsvs:get_single_version_code($db,$code,$id, $version,$lang) {
  let $vs0 := db:open($db,$svs_lsvs:valuesets_doc)//svs:DescribedValueSet[@ID=$id]
  let $vers := if (not($version = '')) then $version else max(xs:int($vs0/@version))
  let $vs1:= $vs0[@version = $vers]

  let $concept_lists :=
    if (not($lang = ''))
      then
      $vs1/svs:ConceptList[@xml:lang = $lang]
    else
      $vs1/svs:ConceptList

  let $concepts :=  $concept_lists/svs:Concept[@code = $code]

  return <RetrieveValueSetCodeResponse> (:Not to SVS standard :)
  {
    for $concept in $concepts
    let $concept_list := $concept/..
    let $val_set := $concept_list/..
    return
      (:ValueSet have @id while DesribedValueSet has @ID:)
    <svs:ValueSet id="{$val_set/@ID}" displayName="{$val_set/@displayName}" version="{$val_set/@version}">
      <svs:ConceptList xml:lang="$concept_list/@xml:lang">
	{$concept}
      </svs:ConceptList>
    </svs:ValueSet>
  }
  </RetrieveValueSetCodeResponse>
};


added tracking when the record was created/updated

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 uuid = "https://github.com/openhie/openinfoman-datim/uuid";
declare namespace csd  =  "urn:ihe:iti:csd:2013";
let $facilities_service_dir := "Facilities"
let $CHW_doc_name := "CHW"
let $doc :=  csd_dm:open_document($csd_webconf:db,$facilities_service_dir)
let $chw_file := file:read-text("./chw.json")
let $json := json:parse($chw_file)
let $data :=
<csd:CSD xmlns:csd="urn:ihe:iti:csd:2013">
  <csd:organizationDirectory/>
  <csd:serviceDirectory/>
  <csd:facilityDirectory/>
  <csd:providerDirectory>
{
for $record in $json/json/_
let $facility_uuid := string($doc//csd:facility[string(./csd:otherID[@code="code"])=data($record/health__centre____code)]/@entityID)
let $referal_facility_uuid := string($doc//csd:facility[string(./csd:otherID[@code="code"])=data($record/referral__hospital____code)]/@entityID)
return
    <csd:provider xmlns:csd="urn:ihe:iti:csd:2013" entityID="{concat("urn:uuid:",random:uuid())}">
      <csd:otherID assigningAuthorityName="2.25.18004676417021084690567854557565765659015601" code="5">{data($record/national__id)}</csd:otherID>
      <csd:demographic>
        <csd:name>
          <csd:commonName>{fn:normalize-space(concat(data($record/given__name),data($record/surname)))}</csd:commonName>
          <csd:surname>{fn:normalize-space(data($record/surname))}</csd:surname>
          <csd:forename>{fn:normalize-space(data($record/given__name))}</csd:forename>
        </csd:name>
        <csd:gender>{data($record/sex)}</csd:gender>
        <csd:dateOfBirth>{data($record/date__of__birth)}</csd:dateOfBirth>
      </csd:demographic>
      <csd:facilities>
        <csd:facility entityID="{$facility_uuid}">
        </csd:facility>
      </csd:facilities>
      <csd:referalHospital entityID="{$referal_facility_uuid}"></csd:referalHospital>
      <csd:record created="{data($record/created)}" updated="{data($record/updated)}" sourceDirectory="http://rapidsms.moh.gov.rw:5000/ws/rest/v1/chws" status="106-002"/>
    </csd:provider>
}
</csd:providerDirectory>
</csd:CSD>
return
csd_dm:add($csd_webconf:db,$data,$CHW_doc_name)

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 uuid = "https://github.com/openhie/openinfoman-datim/uuid";
declare namespace csd  =  "urn:ihe:iti:csd:2013";
let $facilities_service_dir := "Facilities"
let $CHW_doc_name := "CHW"
let $doc :=  csd_dm:open_document($csd_webconf:db,$facilities_service_dir)
let $chw_file := file:read-text("./chw.json")
let $json := json:parse($chw_file)
let $data :=
<csd:CSD xmlns:csd="urn:ihe:iti:csd:2013">
  <csd:organizationDirectory/>
  <csd:serviceDirectory/>
  <csd:facilityDirectory/>
  <csd:providerDirectory>
{
for $record in $json/json/_
let $facility_uuid := string($doc//csd:facility[string(./csd:otherID[@code="code"])=data($record/health__centre____code)]/@entityID)
let $referal_facility_uuid := string($doc//csd:facility[string(./csd:otherID[@code="code"])=data($record/referral__hospital____code)]/@entityID)
return
    <csd:provider xmlns:csd="urn:ihe:iti:csd:2013" entityID="{concat("urn:uuid:",random:uuid())}">
      <csd:otherID assigningAuthorityName="2.25.18004676417021084690567854557565765659015601" code="5">{data($record/national__id)}</csd:otherID>
      <csd:demographic>
        <csd:name>
          <csd:commonName>{fn:normalize-space(concat(data($record/given__name),data($record/surname)))}</csd:commonName>
          <csd:surname>{fn:normalize-space(data($record/surname))}</csd:surname>
          <csd:forename>{fn:normalize-space(data($record/given__name))}</csd:forename>
        </csd:name>
        <csd:gender>{data($record/sex)}</csd:gender>
        <csd:dateOfBirth>{data($record/date__of__birth)}</csd:dateOfBirth>
      </csd:demographic>
      <csd:facilities>
        <csd:facility entityID="{$facility_uuid}">
        </csd:facility>
      </csd:facilities>
      <csd:referalHospital entityID="{$referal_facility_uuid}"></csd:referalHospital>
    </csd:provider>
}
</csd:providerDirectory>
</csd:CSD>
return
csd_dm:add($csd_webconf:db,$data,$CHW_doc_name)


enforce lower case option names in options ripper

declare option output:method 'json';
<json type="object">
{
  for $def in doc("http://docs.basex.org/wiki/Options")
    //*:td/*:b[matches(text(), '^Signature$')]/ancestor::*:td/following-sibling::*:td[1]/*:code/text()

     let $name := lower-case(replace($def, '^([A-Z0-9]+).*', '$1'))
     let $type := if(ends-with($def, ']'))
       then replace($def, '.*\[([^\]]+)\]$', '$1')
       else ()
     return
     element {$name} {$type}

}
</json>

declare option output:method 'json';
<json type="object">
{
  for $def in doc("http://docs.basex.org/wiki/Options")
    //*:td/*:b[matches(text(), '^Signature$')]/ancestor::*:td/following-sibling::*:td[1]/*:code/text()

     let $name := replace($def, '^([A-Z0-9]+).*', '$1')
     let $type := if(ends-with($def, ']'))
       then replace($def, '.*\[([^\]]+)\]$', '$1')
       else ()
     return
     element {$name} {$type}

}
</json>


Updating annotation.

Updating annotation.

(: Copyright 2006-2008 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 query is run by the remote queue and nightlies after a test run. :)
(: It tweaks the CTest-generated Test.xml to pass tests which crashed    :)
(: but are marked as EXPECTED_FAILURE().                                 :)
declare namespace l = "http://zorba-xquery.com";
declare namespace ann = "http://www.zorba-xquery.com/annotations";

declare variable $exps as document-node() external;
declare variable $tests as document-node() external;

declare %ann:sequential function l:xform($a) {
  for $exp in $exps/ExpectedFailures/Test
  for $segfault in
     $a/Site/Testing/Test/Results/NamedMeasurement/Value[text() eq "SEGFAULT" or text() eq "OTHER_FAULT"]
  let $failure := $segfault/../../..
  where data($exp/@name) eq data($failure/Name)
  return replace node $failure/@Status with attribute Status { "passed" };

  $a
};

l:xform($tests)

(: Copyright 2006-2008 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 query is run by the remote queue and nightlies after a test run. :)
(: It tweaks the CTest-generated Test.xml to pass tests which crashed    :)
(: but are marked as EXPECTED_FAILURE().                                 :)
declare namespace l = "http://zorba-xquery.com";

declare variable $exps as document-node() external;
declare variable $tests as document-node() external;

declare %sequential function l:xform($a) {
  for $exp in $exps/ExpectedFailures/Test
  for $segfault in
     $a/Site/Testing/Test/Results/NamedMeasurement/Value[text() eq "SEGFAULT" or text() eq "OTHER_FAULT"]
  let $failure := $segfault/../../..
  where data($exp/@name) eq data($failure/Name)
  return replace node $failure/@Status with attribute Status { "passed" };

  $a
};

l:xform($tests)