/xquery/utils.xqm

http://transcriptstudio4isha.googlecode.com/ · Unknown · 278 lines · 247 code · 31 blank · 0 comment · 0 complexity · 30f4bd38633214f73675d0be5afa200b MD5 · raw file

  1. xquery version "1.0";
  2. module namespace utils = "http://www.ishafoundation.org/ts4isha/xquery/utils";
  3. import module namespace functx = "http://www.functx.com" at "functx.xqm";
  4. import module namespace transform = "http://exist-db.org/xquery/transform";
  5. declare namespace xmldb = "http://exist-db.org/xquery/xmldb";
  6. declare namespace util = "http://exist-db.org/xquery/util";
  7. declare variable $utils:MAX_FILENAME_LENGTH := 200;
  8. declare variable $utils:ts4ishaCollectionPath := '/db/ts4isha';
  9. declare variable $utils:dataCollectionPath := concat($utils:ts4ishaCollectionPath, '/data');
  10. declare variable $utils:dataCollection := collection($utils:dataCollectionPath);
  11. declare variable $utils:referenceCollectionPath := concat($utils:ts4ishaCollectionPath, '/reference');
  12. declare variable $utils:referenceCollection := collection($utils:referenceCollectionPath);
  13. declare variable $utils:xsltCollectionPath := concat($utils:ts4ishaCollectionPath, '/xslt');
  14. declare variable $utils:tempCollectionPath := concat($utils:ts4ishaCollectionPath, '/temp');
  15. declare function utils:create-collection($path as xs:string, $dbaOnly as xs:boolean) as xs:string
  16. {
  17. if ($dbaOnly and not(utils:is-current-user-admin())) then
  18. error(xs:QName('illegal-access-exception'), concat('Only dba allowed to create collection: ', $path))
  19. else
  20. utils:create-collection-internal('/', tokenize($path, '/'))
  21. };
  22. declare function utils:create-collection-internal($baseCollection as xs:string, $seq as xs:string*) as xs:string
  23. {
  24. if (empty($seq)) then
  25. $baseCollection
  26. else
  27. let $newBaseCollection :=
  28. if ($seq[1] = '') then
  29. $baseCollection
  30. else
  31. xmldb:create-collection($baseCollection, $seq[1])
  32. let $newSeq := $seq[position() > 1]
  33. return utils:create-collection-internal($newBaseCollection, $newSeq)
  34. };
  35. declare function utils:transform($doc as element(), $xsltDocName as xs:string, $params as element()?) as node()?
  36. {
  37. transform:transform($doc, utils:xsltDoc($xsltDocName), $params)
  38. };
  39. declare function utils:xsltDoc($docName as xs:string) as node()?
  40. {
  41. doc(concat($utils:xsltCollectionPath, '/', $docName))
  42. };
  43. declare function utils:is-current-user-admin() as xs:boolean?
  44. {
  45. let $currentUser := xmldb:get-current-user()
  46. return
  47. xmldb:is-admin-user($currentUser)
  48. };
  49. declare function utils:is-current-user-in-group($group as xs:string) as xs:boolean?
  50. {
  51. let $currentUser := xmldb:get-current-user()
  52. let $groups := xmldb:get-user-groups($currentUser)
  53. return
  54. contains($groups, $group)
  55. };
  56. declare function utils:get-event($eventId as xs:string) as element()?
  57. {
  58. $utils:dataCollection/event[@id = $eventId]
  59. };
  60. declare function utils:get-session($sessionId as xs:string) as element()?
  61. {
  62. $utils:dataCollection/session[@id = $sessionId]
  63. };
  64. declare function utils:get-event-type($eventTypeId as xs:string?) as element()?
  65. {
  66. if (not(exists($eventTypeId))) then
  67. ()
  68. else
  69. $utils:referenceCollection/reference//eventType[@id = $eventTypeId]
  70. };
  71. declare function utils:get-device-code-element($deviceCode as xs:string) as element()?
  72. {
  73. $utils:referenceCollection/reference//deviceCode[@id = $deviceCode]
  74. };
  75. declare function utils:set-child-element($existingParentElement as element(), $newChildElement as element()) as element()?
  76. {
  77. let $childTagName := local-name($newChildElement)
  78. let $existingChildElement := $existingParentElement/*[local-name(.) eq $childTagName]
  79. return
  80. if (empty($existingChildElement)) then
  81. let $null := update insert $newChildElement into $existingParentElement
  82. return ()
  83. else if (exactly-one($existingChildElement)) then
  84. let $null := update replace $existingChildElement with $newChildElement
  85. return $existingChildElement
  86. else
  87. error((), concat('More the one child element named: ', $childTagName))
  88. };
  89. declare function utils:store($documentURI as xs:string, $xml as element()) as xs:string
  90. {
  91. let $xml := utils:remove-attributes($xml, '_document-uri')
  92. let $docName := tokenize($documentURI, '/')[last()]
  93. let $collectionName := substring-before($documentURI, concat('/', $docName))
  94. return
  95. xmldb:store($collectionName, $docName, $xml)
  96. };
  97. (: modified because there seems to be a bug in eXist usign the QName - https://sourceforge.net/tracker/index.php?func=detail&aid=1992594&group_id=17691&atid=117691 :)
  98. declare function utils:add-attributes($elements as element()*, $attrNames as xs:string*, $attrValues as xs:anyAtomicType*) as element()? {
  99. for $element in $elements
  100. return element { node-name($element)}
  101. {
  102. for $attrName at $seq in $attrNames
  103. return if ($element/@*[local-name(.) = $attrNames])
  104. then ()
  105. else attribute {$attrName}
  106. {$attrValues[$seq]},
  107. $element/@*,
  108. $element/node()
  109. }
  110. };
  111. declare function utils:remove-attributes ($elements as element()*, $attrNames as xs:string*) as element() {
  112. for $element in $elements
  113. return element
  114. {node-name($element)}
  115. {$element/@*[not(local-name(.) = $attrNames)],
  116. $element/node() }
  117. };
  118. declare function utils:is-valid-date-string($dateString as xs:string?) as xs:boolean
  119. {
  120. if (not(exists($dateString))) then
  121. false()
  122. else
  123. (
  124. let $dateString := replace($dateString, '[^\d]', '')
  125. return
  126. if (string-length($dateString) < 8) then
  127. false()
  128. else
  129. let $year := xs:integer(substring($dateString, 1, 4))
  130. let $month := xs:integer(substring($dateString, 5, 2))
  131. let $day := xs:integer(substring($dateString, 7, 2))
  132. return
  133. $year >= 1 and $month >= 1 and $month <= 12 and $day >= 1 and $day <= 31
  134. )
  135. };
  136. (:
  137. $dateString can be in various formats but must be in order (year(4), month(2), date(2)) with no digits in between
  138. e.g. '20090320', '2009/03/20', '2009-03-20T18:30:00'
  139. :)
  140. declare function utils:date-string-to-date($dateString as xs:string?) as xs:date?
  141. {
  142. if (not(utils:is-valid-date-string($dateString))) then
  143. ()
  144. else
  145. (
  146. (: make sure it doesnt have separators (but keep the 'x' which represents unknown) :)
  147. let $dateString := replace($dateString, '[^\d]', '')
  148. let $standardDateString :=
  149. concat(substring($dateString, 1, 4), '-',
  150. substring($dateString, 5, 2), '-',
  151. substring($dateString, 7, 2))
  152. return
  153. xs:date($standardDateString)
  154. )
  155. };
  156. declare function utils:left-pad-string($stringToPad as xs:string, $minLength as xs:integer) as xs:string
  157. {
  158. let $numExtra := $minLength - string-length($stringToPad)
  159. return
  160. if ($numExtra > 0) then
  161. (
  162. string-join((for $i in (1 to $numExtra) return '0', $stringToPad), '')
  163. )
  164. else
  165. (
  166. $stringToPad
  167. )
  168. };
  169. (: if either (or both) args are empty then empty sequence is returned :)
  170. declare function utils:days-diff($date1 as xs:date?, $date2 as xs:date?) as xs:integer?
  171. {
  172. if (count(($date1, $date2)) < 2) then
  173. ()
  174. else
  175. let $days := days-from-duration($date2 - $date1)
  176. return $days
  177. };
  178. declare function utils:make-filename-friendly($rawFilename as xs:string) as xs:string
  179. {
  180. utils:make-filename-friendly($rawFilename, ())
  181. };
  182. declare function utils:make-filename-friendly($rawFilename as xs:string, $maxLength as xs:integer?) as xs:string
  183. {
  184. let $maxLength := ($maxLength, $utils:MAX_FILENAME_LENGTH)[1]
  185. return
  186. substring(replace(replace($rawFilename, '\s+', '-'), '[^a-z0-9\-_]', ''), 0, $maxLength)
  187. };
  188. declare function utils:build-event-path($event as element()) as xs:string
  189. {
  190. let $collectionName := concat($utils:dataCollectionPath, '/', $event/@type)
  191. let $docName := string-join(($event/@id, utils:build-event-full-name($event)), '_')
  192. return concat($collectionName, '/', $docName, '.xml')
  193. };
  194. declare function utils:build-event-full-name($event as element()) as xs:string?
  195. {
  196. utils:build-event-full-name($event, ())
  197. };
  198. declare function utils:build-event-full-name($event as element(), $maxLength as xs:integer?) as xs:string?
  199. {
  200. let $fullName := lower-case(string-join(($event/metadata/@startAt, $event/metadata/@subTitle, $event/metadata/@location, $event/metadata/@venue), '_'))
  201. let $fullName := utils:make-filename-friendly($fullName, $maxLength)
  202. return
  203. if (string-length($fullName) > 0) then
  204. $fullName
  205. else
  206. ()
  207. };
  208. declare function utils:build-session-path($sessionXML as element()) as xs:string
  209. {
  210. let $eventXML := utils:get-event($sessionXML/@eventId)
  211. let $collectionName := util:collection-name($eventXML)
  212. let $docName := string-join(($sessionXML/@id, utils:build-session-full-name($sessionXML, $eventXML)), '_')
  213. return concat($collectionName, '/', $docName, '.xml')
  214. };
  215. declare function utils:build-session-full-name($sessionXML as element(), $eventXML as element()) as xs:string?
  216. {
  217. utils:build-session-full-name($sessionXML, $eventXML, ())
  218. };
  219. declare function utils:build-session-full-name($sessionXML as element(), $eventXML as element(), $maxLength as xs:integer?) as xs:string?
  220. {
  221. let $metadataXML := $sessionXML/metadata[1]
  222. let $fullName :=
  223. lower-case(string-join(
  224. (
  225. utils:build-event-full-name($eventXML, max(($maxLength idiv 2, $maxLength - 50)))
  226. ,
  227. let $eventDate := utils:date-string-to-date($eventXML/metadata/@startAt)
  228. let $sessionDate := utils:date-string-to-date($metadataXML/@startAt)
  229. let $daysDiff := utils:days-diff($eventDate, $sessionDate)
  230. return
  231. if (exists($daysDiff) and $daysDiff >= 0) then
  232. concat('day-', $daysDiff + 1)
  233. else
  234. ()
  235. ,
  236. $metadataXML/@subTitle
  237. )
  238. ,
  239. '_'
  240. ))
  241. let $fullName := utils:make-filename-friendly($fullName, $maxLength)
  242. return
  243. if (exists($fullName) and string-length($fullName) > 0) then
  244. $fullName
  245. else
  246. ()
  247. };