Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
xquery version "3.1" encoding "UTF-8";
(:~
: XQuery module for caching documents and collections
~:)
module namespace cache="http://xquery.weber-gesamtausgabe.de/modules/cache";
import module namespace functx="http://www.functx.com";
import module namespace wega-util-shared="http://xquery.weber-gesamtausgabe.de/modules/wega-util-shared" at "wega-util-shared.xqm";
declare variable $cache:TOO_MANY_PARAMETERS_ERROR := QName("http://xquery.weber-gesamtausgabe.de/modules/cache", "TooManyParametersError");
declare variable $cache:UNSUPPORTED_PARAMETER_VALUE_ERROR := QName("http://xquery.weber-gesamtausgabe.de/modules/cache", "UnsupportedParameterValueError");
(:~
: A caching function for documents (XML and binary)
:
: @author Peter Stadler
: @param $docURI the database URI of the document
: @param $callBack a function to create the document content when the document is outdated or not available
: @param $lease an xs:dayTimeDuration value of how long the cache should persist, e.g. P999D (= 999 days).
: Alternatively, $lease can be a callback function – then one argument (the last change date of the file as xs:date()?) will be provided
: and the function should return xs:boolean
: @return the cached document
:)
declare function cache:doc($docURI as xs:string, $callback as function() as item(), $callback-params as item()*, $lease as item()?, $onFailure as function() as item()*) as item()* {
let $fileName := functx:substring-after-last($docURI, '/')
let $collection := functx:substring-before-last($docURI, '/')
let $currentDateTimeOfFile :=
if(wega-util-shared:doc-available($docURI)) then xmldb:last-modified($collection, $fileName)
else if(util:binary-doc-available($docURI)) then xmldb:last-modified($collection, $fileName)
else ()
let $updateNecessary :=
typeswitch($lease)
case xs:dayTimeDuration return
$currentDateTimeOfFile + $lease lt current-dateTime()
or empty($lease)
or empty($currentDateTimeOfFile)
case function() as xs:boolean return $lease($currentDateTimeOfFile)
default return error($cache:UNSUPPORTED_PARAMETER_VALUE_ERROR, 'The parameter value for $lease must be xs:dayTimeDuration()? or a function reference which must take exactly one argument.')
return
if($updateNecessary) then (
let $content :=
if(count($callback-params) eq 0) then $callback()
else if(count($callback-params) eq 1) then $callback($callback-params)
else if(count($callback-params) eq 2) then $callback($callback-params[1], $callback-params[2])
else if(count($callback-params) eq 3) then $callback($callback-params[1], $callback-params[2], $callback-params[3])
else if(count($callback-params) eq 4) then $callback($callback-params[1], $callback-params[2], $callback-params[3], $callback-params[4])
else error($cache:TOO_MANY_PARAMETERS_ERROR, 'Too many arguments to callback function within cache:doc(). A maximum of 4 arguments is supported')
let $mime-type := wega-util-shared:guess-mimeType-from-suffix(functx:substring-after-last($docURI, '.'))
let $store-file := cache:store-file($collection, $fileName, $content, $mime-type, $onFailure)
return
if(util:binary-doc-available($store-file)) then util:binary-doc($store-file)
else if(wega-util-shared:doc-available($store-file)) then doc($store-file)
else ()
)
else if(util:binary-doc-available($docURI)) then util:binary-doc($docURI)
else if(wega-util-shared:doc-available($docURI)) then doc($docURI)
else ()
};
(:~
: Store some content as file in the db
: (Helper function for cache:doc())
:
: @author Peter Stadler
: @param $collection the collection to put the file in. If it does not exist, it will be created
: @param $fileName the filename of the to be created resource with filename extension
: @param $contents the content to store. Either a node, an xs:string, a Java file object or an xs:anyURI
: @return Returns the path to the newly created resource, empty sequence otherwise
:)
declare %private function cache:store-file($collection as xs:string, $fileName as xs:string, $contents as item(), $mime-type as xs:string, $onFailure as function() as item()*) as xs:string? {
let $createCollection :=
for $coll in tokenize($collection, '/')
let $parentColl := substring-before($collection, $coll)
return
if(xmldb:collection-available($parentColl || '/' || $coll)) then ()
else xmldb:create-collection($parentColl, $coll)
return
try { xmldb:store($collection, $fileName, $contents, $mime-type) }
catch * { $onFailure($err:code, $err:description) }
};