Advertisement
Guest User

Untitled

a guest
Jan 31st, 2014
82
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 10.94 KB | None | 0 0
  1. xquery version "3.0";
  2.  
  3. import module namespace functx="http://www.functx.com";
  4.  
  5. declare %private function local:object.cache($xml-fragment as item())
  6. {
  7. try
  8. {
  9. let $object-id := util:uuid()
  10. let $cache-collection := '/db/apps/chris/__object-cache/'
  11. let $cache-filename := $object-id || '.obj'
  12. let $cached-in := xmldb:store($cache-collection, $cache-filename, $xml-fragment)
  13.  
  14. return
  15. (
  16. element cache
  17. {
  18. element object-id { $object-id },
  19. element collection { $cache-collection },
  20. element filename { $cache-filename },
  21. element resource { $cached-in },
  22. element cached { if(empty($cached-in)) then false() else true() }
  23. }
  24. )
  25. }
  26. catch *
  27. {
  28. ()
  29. }
  30. };
  31.  
  32. declare %private function local:object.new.internals($xml-fragment, $cache-information)
  33. {
  34. map:entry("__created", util:system-dateTime()),
  35. map:entry("__id", $cache-information/object-id/text()),
  36. map:entry("__cache", $cache-information/resource/text()),
  37. map:entry("__cached", $cache-information/cached/text()),
  38. map:entry("__hash", util:hash($xml-fragment,'MD5')),
  39. map:entry("__object", $xml-fragment)
  40. };
  41.  
  42. declare %private function local:object.new.methods()
  43. {
  44. map:entry
  45. (
  46. "valid()",
  47. (
  48. (: [1] METADATA :)
  49. element metadata
  50. {
  51. element description { 'Ensures that the internal hash matches that of the embedded object.' }
  52. },
  53. (: [2] IMPL :)
  54. function($map as map) as xs:boolean { $map("__hash") eq util:hash($map("__object"),'MD5') }
  55. )
  56. ),
  57. map:entry
  58. (
  59. "id()",
  60. (
  61. element metadata
  62. {
  63. element description { 'Returns the identifier for this object.' }
  64. },
  65. function($map as map) as xs:string { $map("__id") }
  66. )
  67. ),
  68. map:entry
  69. (
  70. "object()",
  71. (
  72. element metadata
  73. {
  74. element description { 'Returns the XML fragment representing this object.' }
  75. },
  76. function($map as map) as xs:string { $map("__object") }
  77. )
  78. ),
  79. map:entry
  80. (
  81. "transform()",
  82. (
  83. element metadata
  84. {
  85. element description { 'Returns the XML fragment representing this object.' }
  86. },
  87. function($map as map, $stylesheet as item(), $parameters as node()?) as xs:string
  88. { transform:transform($map("__object"),$stylesheet,$parameters) }
  89. )
  90. )
  91. };
  92.  
  93. declare function local:object.new($xml-fragment as item())
  94. {
  95. let $clone := $xml-fragment (: fragment passed by value ? :)
  96. (: util:deep-copy($xml-fragment) :) (: TODO -- necessary? :)
  97.  
  98. return map:new
  99. (
  100. (
  101. local:object.new.internals($clone, local:object.cache($clone)),
  102. local:object.new.methods(),
  103. local:object.build.properties($clone)
  104. )
  105. )
  106. };
  107.  
  108. declare %private function local:object.build.properties($object)
  109. {
  110. for $child in $object/*
  111. return local:object.build.properties.from.children($object/*)
  112. };
  113.  
  114. declare %private function local:object.build.properties.from.children($children)
  115. {
  116. if(empty($children))
  117. then ()
  118. else
  119. (
  120. for $child in $children
  121. return
  122. (
  123. local:object.build.property.map.entry($child),
  124. local:object.build.properties.from.children($child/*)
  125. )
  126. )
  127. };
  128.  
  129. declare %private function local:object.build.property.map.entry($object)
  130. {
  131. let $object-metadata := local:object.build.property.metadata($object)
  132.  
  133. return map:entry
  134. (
  135. $object-metadata[1],
  136. (
  137. (: [1] METADATA :)
  138. $object-metadata[2],
  139. (: [2] FUNCTIONS :)
  140. (
  141. (: [1] GETTER :)
  142. function($map as map, $prop-name as xs:string, $value as xs:boolean)
  143. {
  144. let $node :=
  145. util:node-by-id
  146. (
  147. $map("__object"),
  148. $map($prop-name)[1]/node-id/text()
  149. )
  150.  
  151. return if($value)
  152. then $node/text()
  153. else $node
  154. }
  155. )
  156. )
  157. )
  158. };
  159.  
  160.  
  161.  
  162. declare %private function local:object.build.property.metadata.local-name($object)
  163. {
  164. if($object/@name)
  165. then $object/@name/string()
  166. else
  167. (
  168. if($object/@type/string() eq 'object')
  169. then functx:substring-after-last(functx:path-to-node-with-pos($object), '/')
  170. else 'unknown'
  171. )
  172. };
  173.  
  174. declare %private function local:object.build.property.metadata.full-name($object)
  175. {
  176. string-join(
  177. for $ancestor in $object/ancestor-or-self::*
  178. where util:node-id($ancestor) ne '1'
  179. return local:object.build.property.metadata.local-name($ancestor)
  180. ,'.')
  181. };
  182.  
  183. declare %private function local:object.build.property.metadata($object)
  184. {
  185. local:object.build.property.metadata.full-name($object),
  186. element metadata
  187. {
  188. element type { $object/@type/string() },
  189. element node-id { util:node-id($object) },
  190. element xpath1 { util:node-xpath($object) },
  191. element xpath2 { functx:path-to-node-with-pos($object) }
  192.  
  193. (:
  194. element parent-name { $parent-name },
  195. element parent-id { $parent-id },
  196. element functx
  197. {
  198. element path { functx:path-to-node($object) },
  199. element path-pos { functx:path-to-node-with-pos($object) },
  200. element distinct-paths
  201. {
  202. for $path in functx:distinct-element-paths($object)
  203. return element path { $path }
  204. },
  205. element distinct-names
  206. {
  207. for $name in functx:distinct-element-names($object)
  208. return element name { $name }
  209. },
  210. element max-depth { functx:max-depth($object) },
  211. element depth { functx:depth-of-node($object) }
  212. }
  213. :)
  214. }
  215. };
  216.  
  217.  
  218.  
  219. declare function local:object.dispose($object)
  220. {
  221. ()
  222. };
  223.  
  224. declare function local:object.get-value($object, $property-name)
  225. {
  226. local:object.get($object,$property-name,true())
  227. };
  228.  
  229. declare function local:object.get-item($object, $property-name)
  230. {
  231. local:object.get($object,$property-name,false())
  232. };
  233.  
  234. declare %private function local:object.get($object,$property-name,$value-only)
  235. {
  236. if(map:contains($object, $property-name))
  237. then $object($property-name)[2][1]($object,$property-name,$value-only)
  238. else error(QName('http://haptixgames.com/err', 'PropertyNotFound'), $property-name || ' not found.')
  239. };
  240.  
  241. declare function local:object.call($object, $method-name)
  242. {
  243. local:object.call($object, $method-name, $object)
  244. };
  245.  
  246. declare function local:object.call($object, $method-name, $arguments)
  247. {
  248. if(map:contains($object, $method-name))
  249. then $object($method-name)[2]($arguments)
  250. else error(QName('http://haptixgames.com/err', 'MethodNotFound'), $method-name || ' not found.')
  251. };
  252.  
  253. declare function local:object.inspect($object)
  254. {
  255. element object.inspect
  256. {
  257. local:object.inspect.internals($object),
  258. local:object.inspect.methods($object),
  259. local:object.inspect.properties($object)
  260. }
  261. };
  262.  
  263. declare %private function local:object.inspect.internals($object)
  264. {
  265. element internals
  266. {
  267. for $key in map:keys($object)
  268. where starts-with($key, "__") and $key ne '__object'
  269. order by $key ascending
  270. return element { replace($key, "__", "") } { $object($key) }
  271. }
  272. };
  273.  
  274. declare %private function local:object.inspect.methods($object)
  275. {
  276. element methods
  277. {
  278. for $key in map:keys($object)
  279. let $method := $object($key)
  280. where ends-with($key, "()")
  281. order by $key ascending
  282. return
  283. (
  284. element method
  285. {
  286. element name { $key },
  287. $object($key)[1],
  288. element signature { inspect:inspect-function($method[2])/* }
  289. }
  290. )
  291. }
  292. };
  293.  
  294. declare %private function local:object.inspect.properties($object)
  295. {
  296. element properties
  297. {
  298. for $key in map:keys($object)
  299. let $property := $object($key)
  300. where not(starts-with($key, "__")) and not(ends-with($key, "()"))
  301. order by $property[1]/node-id/text() ascending
  302. return
  303. (
  304. element property
  305. {
  306. element name { $key },
  307. $property[1]
  308. }
  309. )
  310. }
  311. };
  312.  
  313.  
  314. let $xml :=
  315. <json type="object">
  316. <pair name="firstName" type="string">John</pair>
  317. <pair name="lastName" type="string">Smith</pair>
  318. <pair name="age" type="number">25</pair>
  319. <pair name="address" type="object">
  320. <!-- address.streetAddress -->
  321. <pair name="streetAddress" type="string">21 2nd Street</pair>
  322. <pair name="city" type="string">New York</pair>
  323. <pair name="state" type="string">NY</pair>
  324. <pair name="postalCode" type="number">10021</pair>
  325. <pair name="alive" type="boolean">true</pair>
  326. <!--<pair name="empty" type="null"/></pair> BROKEN -->
  327. </pair>
  328. <!-- phoneNumbers -->
  329. <pair name="phoneNumbers" type="array">
  330. <item type="object">
  331. <pair name="type" type="string">home</pair>
  332. <pair name="number" type="string">212 555-1234</pair>
  333. </item>
  334. <!-- phoneNumbers[2] -->
  335. <item type="object">
  336. <!-- phoneNumbers[2].type -->
  337. <pair name="type" type="string">fax</pair>
  338. <!-- phoneNumbers[2].number -->
  339. <pair name="number" type="string">646 555-4567</pair>
  340. </item>
  341. </pair>
  342. </json>
  343.  
  344. let $object := local:object.new($xml)
  345.  
  346. let $xml := <nothing><more/><to/><see/><here/></nothing>
  347.  
  348. return
  349. (
  350. local:object.inspect($object),
  351. local:object.get-item($object, "address"),
  352. local:object.get-item($object, "firstName"),
  353. local:object.get-value($object, "lastName"),
  354. local:object.get-value($object, "address.city"),
  355. local:object.get-value($object, "phoneNumbers.item[2].number"),
  356. local:object.call($object, "valid()"),
  357. local:object.call($object, "id()")
  358. )
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement