kibi-swipl-linux-x64-gnu 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (550) hide show
  1. package/README.md +29 -0
  2. package/bin/swipl +0 -0
  3. package/bin/swipl-win +0 -0
  4. package/build-manifest.json +70 -0
  5. package/lib/cmake/swipl/SWIPLConfig.cmake +21 -0
  6. package/lib/cmake/swipl/SWIPLConfigVersion.cmake +65 -0
  7. package/lib/cmake/swipl/SWIPLTargets-release.cmake +28 -0
  8. package/lib/cmake/swipl/SWIPLTargets.cmake +109 -0
  9. package/lib/swipl/ABI +1 -0
  10. package/lib/swipl/LICENSE +41 -0
  11. package/lib/swipl/README.md +116 -0
  12. package/lib/swipl/app/README.md +25 -0
  13. package/lib/swipl/app/app.pl +87 -0
  14. package/lib/swipl/app/pack.pl +350 -0
  15. package/lib/swipl/app/qlf.pl +521 -0
  16. package/lib/swipl/app/splfr.pl +177 -0
  17. package/lib/swipl/app/sys.pl +310 -0
  18. package/lib/swipl/bin/swipl.home +1 -0
  19. package/lib/swipl/boot/apply.pl +73 -0
  20. package/lib/swipl/boot/attvar.pl +344 -0
  21. package/lib/swipl/boot/autoload.pl +1226 -0
  22. package/lib/swipl/boot/bags.pl +283 -0
  23. package/lib/swipl/boot/dcg.pl +388 -0
  24. package/lib/swipl/boot/dicts.pl +193 -0
  25. package/lib/swipl/boot/dwim.pl +485 -0
  26. package/lib/swipl/boot/engines.pl +152 -0
  27. package/lib/swipl/boot/expand.pl +1628 -0
  28. package/lib/swipl/boot/gc.pl +65 -0
  29. package/lib/swipl/boot/history.pl +304 -0
  30. package/lib/swipl/boot/init.pl +4682 -0
  31. package/lib/swipl/boot/iri.pl +64 -0
  32. package/lib/swipl/boot/license.pl +390 -0
  33. package/lib/swipl/boot/load.pl +81 -0
  34. package/lib/swipl/boot/messages.pl +2521 -0
  35. package/lib/swipl/boot/packs.pl +306 -0
  36. package/lib/swipl/boot/predopts.pl +154 -0
  37. package/lib/swipl/boot/qlf.pl +141 -0
  38. package/lib/swipl/boot/rc.pl +263 -0
  39. package/lib/swipl/boot/syspred.pl +1634 -0
  40. package/lib/swipl/boot/tabling.pl +2321 -0
  41. package/lib/swipl/boot/threads.pl +42 -0
  42. package/lib/swipl/boot/toplevel.pl +2248 -0
  43. package/lib/swipl/boot/topvars.pl +261 -0
  44. package/lib/swipl/boot.prc +0 -0
  45. package/lib/swipl/cmake/swipl.cmake +131 -0
  46. package/lib/swipl/customize/README.md +23 -0
  47. package/lib/swipl/customize/edit +101 -0
  48. package/lib/swipl/customize/init.pl +164 -0
  49. package/lib/swipl/demo/README.md +33 -0
  50. package/lib/swipl/demo/likes.pl +44 -0
  51. package/lib/swipl/doc/packages/examples/chr/bool.chr +281 -0
  52. package/lib/swipl/doc/packages/examples/chr/chrdif.chr +87 -0
  53. package/lib/swipl/doc/packages/examples/chr/chrfreeze.chr +6 -0
  54. package/lib/swipl/doc/packages/examples/chr/family.chr +116 -0
  55. package/lib/swipl/doc/packages/examples/chr/fib.chr +24 -0
  56. package/lib/swipl/doc/packages/examples/chr/fibonacci.chr +31 -0
  57. package/lib/swipl/doc/packages/examples/chr/gcd.chr +28 -0
  58. package/lib/swipl/doc/packages/examples/chr/leq.chr +34 -0
  59. package/lib/swipl/doc/packages/examples/chr/listdom.chr +138 -0
  60. package/lib/swipl/doc/packages/examples/chr/primes.chr +29 -0
  61. package/lib/swipl/doc/packages/examples/http/README.md +98 -0
  62. package/lib/swipl/doc/packages/examples/http/calc.pl +92 -0
  63. package/lib/swipl/doc/packages/examples/http/demo_body.pl +232 -0
  64. package/lib/swipl/doc/packages/examples/http/demo_client.pl +165 -0
  65. package/lib/swipl/doc/packages/examples/http/demo_daemon.pl +38 -0
  66. package/lib/swipl/doc/packages/examples/http/demo_files.pl +50 -0
  67. package/lib/swipl/doc/packages/examples/http/demo_hello.pl +15 -0
  68. package/lib/swipl/doc/packages/examples/http/demo_login.pl +280 -0
  69. package/lib/swipl/doc/packages/examples/http/demo_openid.pl +177 -0
  70. package/lib/swipl/doc/packages/examples/http/demo_pwp.pl +20 -0
  71. package/lib/swipl/doc/packages/examples/http/demo_rest.pl +56 -0
  72. package/lib/swipl/doc/packages/examples/http/demo_threads.pl +52 -0
  73. package/lib/swipl/doc/packages/examples/http/linux-init-script +126 -0
  74. package/lib/swipl/doc/packages/examples/http/pwp/context.pwp +23 -0
  75. package/lib/swipl/doc/packages/examples/http/pwp/index.pwp +25 -0
  76. package/lib/swipl/doc/packages/examples/http/pwp/pwp1.pwp +12 -0
  77. package/lib/swipl/doc/packages/examples/http/pwp/pwp2.pwp +10 -0
  78. package/lib/swipl/doc/packages/examples/http/pwp/pwp3.pwp +25 -0
  79. package/lib/swipl/doc/packages/examples/http/pwp/pwp4.pwp +23 -0
  80. package/lib/swipl/doc/packages/examples/http/pwp/pwp5.pwp +11 -0
  81. package/lib/swipl/doc/packages/examples/http/pwp/pwp6.pwp +3 -0
  82. package/lib/swipl/doc/packages/examples/http/pwp/pwp7.pwp +3 -0
  83. package/lib/swipl/doc/packages/examples/http/pwp/pwp8.pwp +3 -0
  84. package/lib/swipl/doc/packages/examples/http/pwp/pwpdb.pl +12 -0
  85. package/lib/swipl/doc/packages/examples/http/systemd-script.service +18 -0
  86. package/lib/swipl/doc/packages/examples/http/upstart-script.conf +20 -0
  87. package/lib/swipl/doc/packages/examples/plunit/read.pl +17 -0
  88. package/lib/swipl/doc/packages/examples/plunit/simple.pl +33 -0
  89. package/lib/swipl/doc/packages/examples/ssl/client.pl +83 -0
  90. package/lib/swipl/doc/packages/examples/ssl/etc/README +52 -0
  91. package/lib/swipl/doc/packages/examples/ssl/etc/client/client-cert.p12 +0 -0
  92. package/lib/swipl/doc/packages/examples/ssl/etc/client/client-cert.pem +85 -0
  93. package/lib/swipl/doc/packages/examples/ssl/etc/client/client-key.pem +30 -0
  94. package/lib/swipl/doc/packages/examples/ssl/etc/demoCA/cacert.pem +82 -0
  95. package/lib/swipl/doc/packages/examples/ssl/etc/demoCA/careq.pem +18 -0
  96. package/lib/swipl/doc/packages/examples/ssl/etc/demoCA/crlnumber +1 -0
  97. package/lib/swipl/doc/packages/examples/ssl/etc/demoCA/index.txt +3 -0
  98. package/lib/swipl/doc/packages/examples/ssl/etc/demoCA/index.txt.attr +1 -0
  99. package/lib/swipl/doc/packages/examples/ssl/etc/demoCA/newcerts/9DC08797A0F63F7C.pem +85 -0
  100. package/lib/swipl/doc/packages/examples/ssl/etc/demoCA/newcerts/9DC08797A0F63F7D.pem +85 -0
  101. package/lib/swipl/doc/packages/examples/ssl/etc/demoCA/private/cakey.pem +30 -0
  102. package/lib/swipl/doc/packages/examples/ssl/etc/demoCA/serial +1 -0
  103. package/lib/swipl/doc/packages/examples/ssl/etc/server/server-cert.pem +85 -0
  104. package/lib/swipl/doc/packages/examples/ssl/etc/server/server-key.pem +30 -0
  105. package/lib/swipl/doc/packages/examples/ssl/https.pl +267 -0
  106. package/lib/swipl/doc/packages/examples/ssl/server.pl +106 -0
  107. package/lib/swipl/include/SWI-Prolog.h +1544 -0
  108. package/lib/swipl/include/SWI-Stream.h +537 -0
  109. package/lib/swipl/include/Yap/YapInterface.h +283 -0
  110. package/lib/swipl/include/sicstus/sicstus.h +452 -0
  111. package/lib/swipl/lib/x86_64-linux/cgi.so +0 -0
  112. package/lib/swipl/lib/x86_64-linux/crypt.so +0 -0
  113. package/lib/swipl/lib/x86_64-linux/crypto4pl.so +0 -0
  114. package/lib/swipl/lib/x86_64-linux/double_metaphone.so +0 -0
  115. package/lib/swipl/lib/x86_64-linux/files.so +0 -0
  116. package/lib/swipl/lib/x86_64-linux/hashstream.so +0 -0
  117. package/lib/swipl/lib/x86_64-linux/http_stream.so +0 -0
  118. package/lib/swipl/lib/x86_64-linux/isub.so +0 -0
  119. package/lib/swipl/lib/x86_64-linux/json.so +0 -0
  120. package/lib/swipl/lib/x86_64-linux/libswipl.so.10 +0 -0
  121. package/lib/swipl/lib/x86_64-linux/mallocinfo.so +0 -0
  122. package/lib/swipl/lib/x86_64-linux/md54pl.so +0 -0
  123. package/lib/swipl/lib/x86_64-linux/memfile.so +0 -0
  124. package/lib/swipl/lib/x86_64-linux/ntriples.so +0 -0
  125. package/lib/swipl/lib/x86_64-linux/pcre4pl.so +0 -0
  126. package/lib/swipl/lib/x86_64-linux/porter_stem.so +0 -0
  127. package/lib/swipl/lib/x86_64-linux/process.so +0 -0
  128. package/lib/swipl/lib/x86_64-linux/prolog_stream.so +0 -0
  129. package/lib/swipl/lib/x86_64-linux/rdf_db.so +0 -0
  130. package/lib/swipl/lib/x86_64-linux/readutil.so +0 -0
  131. package/lib/swipl/lib/x86_64-linux/rlimit.so +0 -0
  132. package/lib/swipl/lib/x86_64-linux/sched.so +0 -0
  133. package/lib/swipl/lib/x86_64-linux/sgml2pl.so +0 -0
  134. package/lib/swipl/lib/x86_64-linux/sha4pl.so +0 -0
  135. package/lib/swipl/lib/x86_64-linux/snowball.so +0 -0
  136. package/lib/swipl/lib/x86_64-linux/socket.so +0 -0
  137. package/lib/swipl/lib/x86_64-linux/ssl4pl.so +0 -0
  138. package/lib/swipl/lib/x86_64-linux/streaminfo.so +0 -0
  139. package/lib/swipl/lib/x86_64-linux/syslog.so +0 -0
  140. package/lib/swipl/lib/x86_64-linux/time.so +0 -0
  141. package/lib/swipl/lib/x86_64-linux/turtle.so +0 -0
  142. package/lib/swipl/lib/x86_64-linux/uid.so +0 -0
  143. package/lib/swipl/lib/x86_64-linux/unix.so +0 -0
  144. package/lib/swipl/lib/x86_64-linux/uri.so +0 -0
  145. package/lib/swipl/lib/x86_64-linux/websocket.so +0 -0
  146. package/lib/swipl/lib/x86_64-linux/zlib4pl.so +0 -0
  147. package/lib/swipl/library/INDEX.pl +1020 -0
  148. package/lib/swipl/library/aggregate.pl +755 -0
  149. package/lib/swipl/library/ansi_term.pl +653 -0
  150. package/lib/swipl/library/apply.pl +426 -0
  151. package/lib/swipl/library/apply_macros.pl +497 -0
  152. package/lib/swipl/library/arithmetic.pl +320 -0
  153. package/lib/swipl/library/assoc.pl +522 -0
  154. package/lib/swipl/library/atom.pl +169 -0
  155. package/lib/swipl/library/backcomp.pl +688 -0
  156. package/lib/swipl/library/base32.pl +291 -0
  157. package/lib/swipl/library/base64.pl +441 -0
  158. package/lib/swipl/library/broadcast.pl +161 -0
  159. package/lib/swipl/library/build/cmake.pl +137 -0
  160. package/lib/swipl/library/build/conan.pl +232 -0
  161. package/lib/swipl/library/build/make.pl +168 -0
  162. package/lib/swipl/library/build/tools.pl +825 -0
  163. package/lib/swipl/library/charsio.pl +195 -0
  164. package/lib/swipl/library/check.pl +1097 -0
  165. package/lib/swipl/library/check_installation.pl +912 -0
  166. package/lib/swipl/library/clp/INDEX.pl +157 -0
  167. package/lib/swipl/library/clp/bounds.pl +2036 -0
  168. package/lib/swipl/library/clp/clp_distinct.pl +263 -0
  169. package/lib/swipl/library/clp/clp_events.pl +92 -0
  170. package/lib/swipl/library/clp/clpb.pl +1896 -0
  171. package/lib/swipl/library/clp/clpfd.pl +7906 -0
  172. package/lib/swipl/library/clp/simplex.pl +1580 -0
  173. package/lib/swipl/library/codesio.pl +182 -0
  174. package/lib/swipl/library/coinduction.pl +183 -0
  175. package/lib/swipl/library/console_input.pl +289 -0
  176. package/lib/swipl/library/csv.pl +611 -0
  177. package/lib/swipl/library/ctypes.pl +161 -0
  178. package/lib/swipl/library/date.pl +370 -0
  179. package/lib/swipl/library/dcg/INDEX.pl +35 -0
  180. package/lib/swipl/library/dcg/basics.pl +514 -0
  181. package/lib/swipl/library/dcg/high_order.pl +227 -0
  182. package/lib/swipl/library/debug.pl +499 -0
  183. package/lib/swipl/library/dialect/bim.pl +186 -0
  184. package/lib/swipl/library/dialect/commons.pl +77 -0
  185. package/lib/swipl/library/dialect/eclipse/test_util_iso.pl +355 -0
  186. package/lib/swipl/library/dialect/hprolog/format.pl +44 -0
  187. package/lib/swipl/library/dialect/hprolog.pl +314 -0
  188. package/lib/swipl/library/dialect/ifprolog.pl +1317 -0
  189. package/lib/swipl/library/dialect/iso/iso_predicates.pl +277 -0
  190. package/lib/swipl/library/dialect/sicstus/README.TXT +1 -0
  191. package/lib/swipl/library/dialect/sicstus/arrays.pl +121 -0
  192. package/lib/swipl/library/dialect/sicstus/block.pl +278 -0
  193. package/lib/swipl/library/dialect/sicstus/lists.pl +167 -0
  194. package/lib/swipl/library/dialect/sicstus/ordsets.pl +52 -0
  195. package/lib/swipl/library/dialect/sicstus/sockets.pl +174 -0
  196. package/lib/swipl/library/dialect/sicstus/system.pl +262 -0
  197. package/lib/swipl/library/dialect/sicstus/terms.pl +57 -0
  198. package/lib/swipl/library/dialect/sicstus/timeout.pl +92 -0
  199. package/lib/swipl/library/dialect/sicstus.pl +582 -0
  200. package/lib/swipl/library/dialect/sicstus4/aggregate.pl +60 -0
  201. package/lib/swipl/library/dialect/sicstus4/between.pl +62 -0
  202. package/lib/swipl/library/dialect/sicstus4/clpfd.pl +75 -0
  203. package/lib/swipl/library/dialect/sicstus4/file_systems.pl +413 -0
  204. package/lib/swipl/library/dialect/sicstus4/lists.pl +274 -0
  205. package/lib/swipl/library/dialect/sicstus4/ordsets.pl +54 -0
  206. package/lib/swipl/library/dialect/sicstus4/samsort.pl +86 -0
  207. package/lib/swipl/library/dialect/sicstus4/sets.pl +124 -0
  208. package/lib/swipl/library/dialect/sicstus4/sockets.pl +164 -0
  209. package/lib/swipl/library/dialect/sicstus4/system.pl +80 -0
  210. package/lib/swipl/library/dialect/sicstus4/terms.pl +89 -0
  211. package/lib/swipl/library/dialect/sicstus4/timeout.pl +43 -0
  212. package/lib/swipl/library/dialect/sicstus4/types.pl +103 -0
  213. package/lib/swipl/library/dialect/sicstus4.pl +200 -0
  214. package/lib/swipl/library/dialect/swi/syspred_options.pl +250 -0
  215. package/lib/swipl/library/dialect/xsb/README.md +20 -0
  216. package/lib/swipl/library/dialect/xsb/basics.pl +318 -0
  217. package/lib/swipl/library/dialect/xsb/consult.pl +87 -0
  218. package/lib/swipl/library/dialect/xsb/curr_sym.pl +57 -0
  219. package/lib/swipl/library/dialect/xsb/error_handler.pl +111 -0
  220. package/lib/swipl/library/dialect/xsb/gensym.pl +53 -0
  221. package/lib/swipl/library/dialect/xsb/gpp.pl +138 -0
  222. package/lib/swipl/library/dialect/xsb/intern.pl +48 -0
  223. package/lib/swipl/library/dialect/xsb/lists.pl +47 -0
  224. package/lib/swipl/library/dialect/xsb/machine.pl +295 -0
  225. package/lib/swipl/library/dialect/xsb/ordsets.pl +53 -0
  226. package/lib/swipl/library/dialect/xsb/setof.pl +54 -0
  227. package/lib/swipl/library/dialect/xsb/source.pl +308 -0
  228. package/lib/swipl/library/dialect/xsb/standard.pl +169 -0
  229. package/lib/swipl/library/dialect/xsb/storage.pl +70 -0
  230. package/lib/swipl/library/dialect/xsb/string.pl +76 -0
  231. package/lib/swipl/library/dialect/xsb/thread.pl +62 -0
  232. package/lib/swipl/library/dialect/xsb/timed_call.pl +158 -0
  233. package/lib/swipl/library/dialect/xsb.pl +688 -0
  234. package/lib/swipl/library/dialect/yap/README.TXT +8 -0
  235. package/lib/swipl/library/dialect/yap.pl +283 -0
  236. package/lib/swipl/library/dialect.pl +123 -0
  237. package/lib/swipl/library/dicts.pl +399 -0
  238. package/lib/swipl/library/dif.pl +426 -0
  239. package/lib/swipl/library/edinburgh.pl +138 -0
  240. package/lib/swipl/library/edit.pl +783 -0
  241. package/lib/swipl/library/error.pl +495 -0
  242. package/lib/swipl/library/exceptions.pl +231 -0
  243. package/lib/swipl/library/explain.pl +543 -0
  244. package/lib/swipl/library/ext/RDF/INDEX.pl +25 -0
  245. package/lib/swipl/library/ext/RDF/rdf.pl +450 -0
  246. package/lib/swipl/library/ext/RDF/rdf_parser.pl +649 -0
  247. package/lib/swipl/library/ext/RDF/rdf_triple.pl +448 -0
  248. package/lib/swipl/library/ext/RDF/rdf_write.pl +701 -0
  249. package/lib/swipl/library/ext/RDF/rewrite_term.pl +177 -0
  250. package/lib/swipl/library/ext/chr/chr/a_star.pl +80 -0
  251. package/lib/swipl/library/ext/chr/chr/binomialheap.pl +142 -0
  252. package/lib/swipl/library/ext/chr/chr/builtins.pl +629 -0
  253. package/lib/swipl/library/ext/chr/chr/chr_compiler_errors.pl +179 -0
  254. package/lib/swipl/library/ext/chr/chr/chr_compiler_options.pl +382 -0
  255. package/lib/swipl/library/ext/chr/chr/chr_compiler_utility.pl +338 -0
  256. package/lib/swipl/library/ext/chr/chr/chr_debug.pl +59 -0
  257. package/lib/swipl/library/ext/chr/chr/chr_hashtable_store.pl +425 -0
  258. package/lib/swipl/library/ext/chr/chr/chr_integertable_store.pl +139 -0
  259. package/lib/swipl/library/ext/chr/chr/chr_messages.pl +176 -0
  260. package/lib/swipl/library/ext/chr/chr/chr_op.pl +53 -0
  261. package/lib/swipl/library/ext/chr/chr/chr_runtime.pl +1016 -0
  262. package/lib/swipl/library/ext/chr/chr/chr_translate.pl +25424 -0
  263. package/lib/swipl/library/ext/chr/chr/clean_code.pl +252 -0
  264. package/lib/swipl/library/ext/chr/chr/find.pl +78 -0
  265. package/lib/swipl/library/ext/chr/chr/guard_entailment.pl +19432 -0
  266. package/lib/swipl/library/ext/chr/chr/listmap.pl +108 -0
  267. package/lib/swipl/library/ext/chr/chr/pairlist.pl +78 -0
  268. package/lib/swipl/library/ext/chr/chr.pl +686 -0
  269. package/lib/swipl/library/ext/clib/INDEX.pl +158 -0
  270. package/lib/swipl/library/ext/clib/cgi.pl +86 -0
  271. package/lib/swipl/library/ext/clib/crypt.pl +44 -0
  272. package/lib/swipl/library/ext/clib/filesex.pl +644 -0
  273. package/lib/swipl/library/ext/clib/hash_stream.pl +119 -0
  274. package/lib/swipl/library/ext/clib/mallocinfo.pl +138 -0
  275. package/lib/swipl/library/ext/clib/md5.pl +68 -0
  276. package/lib/swipl/library/ext/clib/memfile.pl +61 -0
  277. package/lib/swipl/library/ext/clib/process.pl +573 -0
  278. package/lib/swipl/library/ext/clib/prolog_server.pl +157 -0
  279. package/lib/swipl/library/ext/clib/prolog_stream.pl +80 -0
  280. package/lib/swipl/library/ext/clib/rlimit.pl +54 -0
  281. package/lib/swipl/library/ext/clib/sched.pl +85 -0
  282. package/lib/swipl/library/ext/clib/sha.pl +162 -0
  283. package/lib/swipl/library/ext/clib/socket.pl +1102 -0
  284. package/lib/swipl/library/ext/clib/streaminfo.pl +103 -0
  285. package/lib/swipl/library/ext/clib/streampool.pl +136 -0
  286. package/lib/swipl/library/ext/clib/syslog.pl +180 -0
  287. package/lib/swipl/library/ext/clib/time.pl +194 -0
  288. package/lib/swipl/library/ext/clib/udp_broadcast.pl +975 -0
  289. package/lib/swipl/library/ext/clib/uid.pl +220 -0
  290. package/lib/swipl/library/ext/clib/unix.pl +317 -0
  291. package/lib/swipl/library/ext/clib/uri.pl +530 -0
  292. package/lib/swipl/library/ext/clib/uuid.pl +207 -0
  293. package/lib/swipl/library/ext/http/http/INDEX.pl +266 -0
  294. package/lib/swipl/library/ext/http/http/README.md +34 -0
  295. package/lib/swipl/library/ext/http/http/ax.pl +189 -0
  296. package/lib/swipl/library/ext/http/http/dcg_basics.pl +49 -0
  297. package/lib/swipl/library/ext/http/http/graphql.pl +1367 -0
  298. package/lib/swipl/library/ext/http/http/html_decl.pl +416 -0
  299. package/lib/swipl/library/ext/http/http/html_head.pl +654 -0
  300. package/lib/swipl/library/ext/http/http/html_quasiquotations.pl +120 -0
  301. package/lib/swipl/library/ext/http/http/html_write.pl +1425 -0
  302. package/lib/swipl/library/ext/http/http/htmx.pl +139 -0
  303. package/lib/swipl/library/ext/http/http/http_authenticate.pl +364 -0
  304. package/lib/swipl/library/ext/http/http/http_client.pl +412 -0
  305. package/lib/swipl/library/ext/http/http/http_cookie.pl +245 -0
  306. package/lib/swipl/library/ext/http/http/http_cors.pl +176 -0
  307. package/lib/swipl/library/ext/http/http/http_digest.pl +820 -0
  308. package/lib/swipl/library/ext/http/http/http_dirindex.pl +296 -0
  309. package/lib/swipl/library/ext/http/http/http_dispatch.pl +1552 -0
  310. package/lib/swipl/library/ext/http/http/http_dyn_workers.pl +214 -0
  311. package/lib/swipl/library/ext/http/http/http_error.pl +126 -0
  312. package/lib/swipl/library/ext/http/http/http_exception.pl +225 -0
  313. package/lib/swipl/library/ext/http/http/http_files.pl +163 -0
  314. package/lib/swipl/library/ext/http/http/http_header.pl +2820 -0
  315. package/lib/swipl/library/ext/http/http/http_hook.pl +106 -0
  316. package/lib/swipl/library/ext/http/http/http_host.pl +204 -0
  317. package/lib/swipl/library/ext/http/http/http_load.pl +113 -0
  318. package/lib/swipl/library/ext/http/http/http_log.pl +738 -0
  319. package/lib/swipl/library/ext/http/http/http_multipart_plugin.pl +232 -0
  320. package/lib/swipl/library/ext/http/http/http_open.pl +1821 -0
  321. package/lib/swipl/library/ext/http/http/http_openid.pl +1561 -0
  322. package/lib/swipl/library/ext/http/http/http_parameters.pl +504 -0
  323. package/lib/swipl/library/ext/http/http/http_path.pl +380 -0
  324. package/lib/swipl/library/ext/http/http/http_proxy.pl +80 -0
  325. package/lib/swipl/library/ext/http/http/http_pwp.pl +351 -0
  326. package/lib/swipl/library/ext/http/http/http_redis_plugin.pl +332 -0
  327. package/lib/swipl/library/ext/http/http/http_server.pl +105 -0
  328. package/lib/swipl/library/ext/http/http/http_server_files.pl +126 -0
  329. package/lib/swipl/library/ext/http/http/http_server_health.pl +186 -0
  330. package/lib/swipl/library/ext/http/http/http_session.pl +1040 -0
  331. package/lib/swipl/library/ext/http/http/http_sgml_plugin.pl +137 -0
  332. package/lib/swipl/library/ext/http/http/http_stream.pl +376 -0
  333. package/lib/swipl/library/ext/http/http/http_unix_daemon.pl +989 -0
  334. package/lib/swipl/library/ext/http/http/http_wrapper.pl +559 -0
  335. package/lib/swipl/library/ext/http/http/hub.pl +600 -0
  336. package/lib/swipl/library/ext/http/http/js_write.pl +461 -0
  337. package/lib/swipl/library/ext/http/http/mimepack.pl +224 -0
  338. package/lib/swipl/library/ext/http/http/mimetype.pl +276 -0
  339. package/lib/swipl/library/ext/http/http/term_html.pl +797 -0
  340. package/lib/swipl/library/ext/http/http/thread_httpd.pl +1181 -0
  341. package/lib/swipl/library/ext/http/http/web/css/dirindex.css +24 -0
  342. package/lib/swipl/library/ext/http/http/web/css/openid.css +57 -0
  343. package/lib/swipl/library/ext/http/http/web/icons/back.png +0 -0
  344. package/lib/swipl/library/ext/http/http/web/icons/c.png +0 -0
  345. package/lib/swipl/library/ext/http/http/web/icons/compressed.png +0 -0
  346. package/lib/swipl/library/ext/http/http/web/icons/folder.png +0 -0
  347. package/lib/swipl/library/ext/http/http/web/icons/generic.png +0 -0
  348. package/lib/swipl/library/ext/http/http/web/icons/layout.png +0 -0
  349. package/lib/swipl/library/ext/http/http/web/icons/openid-logo-square.png +0 -0
  350. package/lib/swipl/library/ext/http/http/web/icons/openid-logo-tiny.png +0 -0
  351. package/lib/swipl/library/ext/http/http/websocket.pl +729 -0
  352. package/lib/swipl/library/ext/http/http/yadis.pl +205 -0
  353. package/lib/swipl/library/ext/json/INDEX.pl +36 -0
  354. package/lib/swipl/library/ext/json/http/INDEX.pl +16 -0
  355. package/lib/swipl/library/ext/json/http/http_json.pl +490 -0
  356. package/lib/swipl/library/ext/json/http/js_grammar.pl +53 -0
  357. package/lib/swipl/library/ext/json/http/json.pl +48 -0
  358. package/lib/swipl/library/ext/json/http/json_convert.pl +48 -0
  359. package/lib/swipl/library/ext/json/json.pl +1215 -0
  360. package/lib/swipl/library/ext/json/json_convert.pl +681 -0
  361. package/lib/swipl/library/ext/json/json_grammar.pl +349 -0
  362. package/lib/swipl/library/ext/json/json_rpc_client.pl +423 -0
  363. package/lib/swipl/library/ext/json/json_rpc_common.pl +104 -0
  364. package/lib/swipl/library/ext/json/json_rpc_server.pl +489 -0
  365. package/lib/swipl/library/ext/json/json_schema.pl +2111 -0
  366. package/lib/swipl/library/ext/nlp/INDEX.pl +15 -0
  367. package/lib/swipl/library/ext/nlp/double_metaphone.pl +86 -0
  368. package/lib/swipl/library/ext/nlp/isub.pl +162 -0
  369. package/lib/swipl/library/ext/nlp/porter_stem.pl +50 -0
  370. package/lib/swipl/library/ext/nlp/snowball.pl +97 -0
  371. package/lib/swipl/library/ext/pcre/INDEX.pl +17 -0
  372. package/lib/swipl/library/ext/pcre/pcre.pl +974 -0
  373. package/lib/swipl/library/ext/plunit/INDEX.pl +20 -0
  374. package/lib/swipl/library/ext/plunit/plunit.pl +2631 -0
  375. package/lib/swipl/library/ext/plunit/test_wizard.pl +249 -0
  376. package/lib/swipl/library/ext/semweb/semweb/INDEX.pl +288 -0
  377. package/lib/swipl/library/ext/semweb/semweb/rdf11.pl +2106 -0
  378. package/lib/swipl/library/ext/semweb/semweb/rdf11_containers.pl +299 -0
  379. package/lib/swipl/library/ext/semweb/semweb/rdf_cache.pl +278 -0
  380. package/lib/swipl/library/ext/semweb/semweb/rdf_compare.pl +132 -0
  381. package/lib/swipl/library/ext/semweb/semweb/rdf_db.pl +3468 -0
  382. package/lib/swipl/library/ext/semweb/semweb/rdf_edit.pl +1145 -0
  383. package/lib/swipl/library/ext/semweb/semweb/rdf_http_plugin.pl +274 -0
  384. package/lib/swipl/library/ext/semweb/semweb/rdf_library.pl +1021 -0
  385. package/lib/swipl/library/ext/semweb/semweb/rdf_litindex.pl +1035 -0
  386. package/lib/swipl/library/ext/semweb/semweb/rdf_ntriples.pl +422 -0
  387. package/lib/swipl/library/ext/semweb/semweb/rdf_persistency.pl +1576 -0
  388. package/lib/swipl/library/ext/semweb/semweb/rdf_portray.pl +182 -0
  389. package/lib/swipl/library/ext/semweb/semweb/rdf_prefixes.pl +681 -0
  390. package/lib/swipl/library/ext/semweb/semweb/rdf_sandbox.pl +153 -0
  391. package/lib/swipl/library/ext/semweb/semweb/rdf_turtle.pl +54 -0
  392. package/lib/swipl/library/ext/semweb/semweb/rdf_turtle_write.pl +1587 -0
  393. package/lib/swipl/library/ext/semweb/semweb/rdf_zlib_plugin.pl +52 -0
  394. package/lib/swipl/library/ext/semweb/semweb/rdfa.pl +1510 -0
  395. package/lib/swipl/library/ext/semweb/semweb/rdfs.pl +475 -0
  396. package/lib/swipl/library/ext/semweb/semweb/sparql_client.pl +643 -0
  397. package/lib/swipl/library/ext/semweb/semweb/turtle.pl +455 -0
  398. package/lib/swipl/library/ext/sgml/DTD/HTML4.dcl +88 -0
  399. package/lib/swipl/library/ext/sgml/DTD/HTML4.dtd +1092 -0
  400. package/lib/swipl/library/ext/sgml/DTD/HTML4.soc +6 -0
  401. package/lib/swipl/library/ext/sgml/DTD/HTML5.dtd +906 -0
  402. package/lib/swipl/library/ext/sgml/DTD/HTMLlat1.ent +195 -0
  403. package/lib/swipl/library/ext/sgml/DTD/HTMLspec.ent +77 -0
  404. package/lib/swipl/library/ext/sgml/DTD/HTMLsym.ent +241 -0
  405. package/lib/swipl/library/ext/sgml/INDEX.pl +64 -0
  406. package/lib/swipl/library/ext/sgml/c14n2.pl +203 -0
  407. package/lib/swipl/library/ext/sgml/iso_639.pl +631 -0
  408. package/lib/swipl/library/ext/sgml/pwp.pl +705 -0
  409. package/lib/swipl/library/ext/sgml/sgml.pl +815 -0
  410. package/lib/swipl/library/ext/sgml/sgml_write.pl +1003 -0
  411. package/lib/swipl/library/ext/sgml/xpath.pl +620 -0
  412. package/lib/swipl/library/ext/sgml/xsdp_types.pl +232 -0
  413. package/lib/swipl/library/ext/ssl/INDEX.pl +60 -0
  414. package/lib/swipl/library/ext/ssl/crypto.pl +1015 -0
  415. package/lib/swipl/library/ext/ssl/http/INDEX.pl +5 -0
  416. package/lib/swipl/library/ext/ssl/http/http_ssl_plugin.pl +296 -0
  417. package/lib/swipl/library/ext/ssl/saml.pl +609 -0
  418. package/lib/swipl/library/ext/ssl/ssl.pl +647 -0
  419. package/lib/swipl/library/ext/ssl/xmldsig.pl +391 -0
  420. package/lib/swipl/library/ext/ssl/xmlenc.pl +354 -0
  421. package/lib/swipl/library/ext/zlib/INDEX.pl +8 -0
  422. package/lib/swipl/library/ext/zlib/zlib.pl +112 -0
  423. package/lib/swipl/library/fastrw.pl +105 -0
  424. package/lib/swipl/library/files.pl +80 -0
  425. package/lib/swipl/library/gensym.pl +111 -0
  426. package/lib/swipl/library/git.pl +1027 -0
  427. package/lib/swipl/library/hashtable.pl +365 -0
  428. package/lib/swipl/library/heaps.pl +252 -0
  429. package/lib/swipl/library/hotfix.pl +239 -0
  430. package/lib/swipl/library/http/jquery.pl +103 -0
  431. package/lib/swipl/library/http/web/js/jquery-3.6.0.min.js +2 -0
  432. package/lib/swipl/library/increval.pl +217 -0
  433. package/lib/swipl/library/intercept.pl +263 -0
  434. package/lib/swipl/library/iostream.pl +237 -0
  435. package/lib/swipl/library/iri_scheme/file.pl +70 -0
  436. package/lib/swipl/library/lazy_lists.pl +481 -0
  437. package/lib/swipl/library/listing.pl +1362 -0
  438. package/lib/swipl/library/lists.pl +860 -0
  439. package/lib/swipl/library/lynx/INDEX.pl +14 -0
  440. package/lib/swipl/library/lynx/format.pl +380 -0
  441. package/lib/swipl/library/lynx/html_style.pl +129 -0
  442. package/lib/swipl/library/lynx/html_text.pl +865 -0
  443. package/lib/swipl/library/lynx/pldoc_style.pl +87 -0
  444. package/lib/swipl/library/macros.pl +451 -0
  445. package/lib/swipl/library/main.pl +1200 -0
  446. package/lib/swipl/library/make.pl +197 -0
  447. package/lib/swipl/library/modules.pl +129 -0
  448. package/lib/swipl/library/nb_rbtrees.pl +267 -0
  449. package/lib/swipl/library/nb_set.pl +203 -0
  450. package/lib/swipl/library/obfuscate.pl +115 -0
  451. package/lib/swipl/library/occurs.pl +241 -0
  452. package/lib/swipl/library/operators.pl +182 -0
  453. package/lib/swipl/library/option.pl +388 -0
  454. package/lib/swipl/library/optparse.pl +966 -0
  455. package/lib/swipl/library/ordsets.pl +518 -0
  456. package/lib/swipl/library/oset.pl +160 -0
  457. package/lib/swipl/library/pairs.pl +187 -0
  458. package/lib/swipl/library/persistency.pl +713 -0
  459. package/lib/swipl/library/pio.pl +47 -0
  460. package/lib/swipl/library/portray_text.pl +277 -0
  461. package/lib/swipl/library/pprint.pl +940 -0
  462. package/lib/swipl/library/predicate_options.pl +975 -0
  463. package/lib/swipl/library/prolog_autoload.pl +233 -0
  464. package/lib/swipl/library/prolog_breakpoints.pl +396 -0
  465. package/lib/swipl/library/prolog_clause.pl +1104 -0
  466. package/lib/swipl/library/prolog_code.pl +416 -0
  467. package/lib/swipl/library/prolog_codewalk.pl +1248 -0
  468. package/lib/swipl/library/prolog_colour.pl +3301 -0
  469. package/lib/swipl/library/prolog_colour.qlf +0 -0
  470. package/lib/swipl/library/prolog_config.pl +154 -0
  471. package/lib/swipl/library/prolog_coverage.pl +1333 -0
  472. package/lib/swipl/library/prolog_debug.pl +404 -0
  473. package/lib/swipl/library/prolog_deps.pl +675 -0
  474. package/lib/swipl/library/prolog_evaluable.pl +234 -0
  475. package/lib/swipl/library/prolog_format.pl +219 -0
  476. package/lib/swipl/library/prolog_history.pl +161 -0
  477. package/lib/swipl/library/prolog_jiti.pl +333 -0
  478. package/lib/swipl/library/prolog_locale.pl +61 -0
  479. package/lib/swipl/library/prolog_metainference.pl +307 -0
  480. package/lib/swipl/library/prolog_pack.pl +3906 -0
  481. package/lib/swipl/library/prolog_profile.pl +346 -0
  482. package/lib/swipl/library/prolog_qlfmake.pl +533 -0
  483. package/lib/swipl/library/prolog_source.pl +1188 -0
  484. package/lib/swipl/library/prolog_stack.pl +794 -0
  485. package/lib/swipl/library/prolog_trace.pl +365 -0
  486. package/lib/swipl/library/prolog_versions.pl +347 -0
  487. package/lib/swipl/library/prolog_wrap.pl +164 -0
  488. package/lib/swipl/library/prolog_xref.pl +3090 -0
  489. package/lib/swipl/library/prolog_xref.qlf +0 -0
  490. package/lib/swipl/library/pure_input.pl +266 -0
  491. package/lib/swipl/library/qpforeign.pl +695 -0
  492. package/lib/swipl/library/qsave.pl +1516 -0
  493. package/lib/swipl/library/quasi_quotations.pl +300 -0
  494. package/lib/swipl/library/quintus.pl +437 -0
  495. package/lib/swipl/library/random.pl +459 -0
  496. package/lib/swipl/library/rbtrees.pl +1153 -0
  497. package/lib/swipl/library/readln.pl +256 -0
  498. package/lib/swipl/library/readutil.pl +304 -0
  499. package/lib/swipl/library/record.pl +544 -0
  500. package/lib/swipl/library/rwlocks.pl +172 -0
  501. package/lib/swipl/library/sandbox.pl +1384 -0
  502. package/lib/swipl/library/semweb/dc.rdfs +198 -0
  503. package/lib/swipl/library/semweb/eor.rdfs +95 -0
  504. package/lib/swipl/library/semweb/owl.owl +287 -0
  505. package/lib/swipl/library/semweb/rdf_library.ttl +90 -0
  506. package/lib/swipl/library/semweb/rdfs.rdfs +251 -0
  507. package/lib/swipl/library/settings.pl +755 -0
  508. package/lib/swipl/library/shell.pl +462 -0
  509. package/lib/swipl/library/shlib.pl +670 -0
  510. package/lib/swipl/library/solution_sequences.pl +439 -0
  511. package/lib/swipl/library/sort.pl +119 -0
  512. package/lib/swipl/library/statistics.pl +541 -0
  513. package/lib/swipl/library/streams.pl +118 -0
  514. package/lib/swipl/library/strings.pl +469 -0
  515. package/lib/swipl/library/system.pl +95 -0
  516. package/lib/swipl/library/tables.pl +381 -0
  517. package/lib/swipl/library/tableutil.pl +771 -0
  518. package/lib/swipl/library/tabling.pl +42 -0
  519. package/lib/swipl/library/terms.pl +457 -0
  520. package/lib/swipl/library/theme/auto.pl +61 -0
  521. package/lib/swipl/library/theme/dark.pl +455 -0
  522. package/lib/swipl/library/theme/light.pl +45 -0
  523. package/lib/swipl/library/thread.pl +810 -0
  524. package/lib/swipl/library/thread_pool.pl +508 -0
  525. package/lib/swipl/library/threadutil.pl +574 -0
  526. package/lib/swipl/library/tty.pl +316 -0
  527. package/lib/swipl/library/ugraphs.pl +644 -0
  528. package/lib/swipl/library/unicode/INDEX.pl +6 -0
  529. package/lib/swipl/library/unicode/blocks.pl +414 -0
  530. package/lib/swipl/library/url.pl +1129 -0
  531. package/lib/swipl/library/utf8.pl +145 -0
  532. package/lib/swipl/library/varnumbers.pl +221 -0
  533. package/lib/swipl/library/vm.pl +251 -0
  534. package/lib/swipl/library/wfs.pl +205 -0
  535. package/lib/swipl/library/when.pl +263 -0
  536. package/lib/swipl/library/writef.pl +278 -0
  537. package/lib/swipl/library/www_browser.pl +251 -0
  538. package/lib/swipl/library/yall.pl +574 -0
  539. package/lib/swipl/library/zip.pl +211 -0
  540. package/lib/swipl/swipl.home +1 -0
  541. package/lib/vendor/libcrypto.so.3 +0 -0
  542. package/lib/vendor/libpcre2-8.so.0 +0 -0
  543. package/lib/vendor/libssl.so.3 +0 -0
  544. package/lib/vendor/libz.so.1 +0 -0
  545. package/licenses/OpenSSL-LICENSE.txt +177 -0
  546. package/licenses/PCRE2-COPYING +5 -0
  547. package/licenses/README.md +12 -0
  548. package/licenses/SWI-Prolog-LICENSE +41 -0
  549. package/licenses/zlib-LICENSE +22 -0
  550. package/package.json +27 -0
@@ -0,0 +1,3468 @@
1
+ /* Part of SWI-Prolog
2
+
3
+ Author: Jan Wielemaker
4
+ E-mail: J.Wielemaker@vu.nl
5
+ WWW: http://www.swi-prolog.org
6
+ Copyright (c) 2003-2023, University of Amsterdam
7
+ VU University Amsterdam
8
+ CWI, Amsterdam
9
+ SWI-Prolog Solutions b.v.
10
+ All rights reserved.
11
+
12
+ Redistribution and use in source and binary forms, with or without
13
+ modification, are permitted provided that the following conditions
14
+ are met:
15
+
16
+ 1. Redistributions of source code must retain the above copyright
17
+ notice, this list of conditions and the following disclaimer.
18
+
19
+ 2. Redistributions in binary form must reproduce the above copyright
20
+ notice, this list of conditions and the following disclaimer in
21
+ the documentation and/or other materials provided with the
22
+ distribution.
23
+
24
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
27
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
28
+ COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
29
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
30
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
31
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
32
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
34
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35
+ POSSIBILITY OF SUCH DAMAGE.
36
+ */
37
+
38
+ :- module(rdf_db,
39
+ [ rdf_version/1, % -Version
40
+
41
+ rdf/3, % ?Subject, ?Predicate, ?Object
42
+ rdf/4, % ?Subject, ?Predicate, ?Object, ?DB
43
+ rdf_has/3, % ?Subject, +Pred, ?Obj
44
+ rdf_has/4, % ?Subject, +Pred, ?Obj, -RealPred
45
+ rdf_reachable/3, % ?Subject, +Pred, ?Object
46
+ rdf_reachable/5, % ?Subject, +Pred, ?Object, +MaxD, ?D
47
+ rdf_resource/1, % ?Resource
48
+ rdf_subject/1, % ?Subject
49
+
50
+ rdf_member_property/2, % ?Property, ?Index
51
+
52
+ rdf_assert/3, % +Subject, +Predicate, +Object
53
+ rdf_assert/4, % +Subject, +Predicate, +Object, +DB
54
+ rdf_retractall/3, % ?Subject, ?Predicate, ?Object
55
+ rdf_retractall/4, % ?Subject, ?Predicate, ?Object, +DB
56
+ rdf_update/4, % +Subject, +Predicate, +Object, +Act
57
+ rdf_update/5, % +Subject, +Predicate, +Object, +Src, +Act
58
+ rdf_set_predicate/2, % +Predicate, +Property
59
+ rdf_predicate_property/2, % +Predicate, ?Property
60
+ rdf_current_predicate/1, % -Predicate
61
+ rdf_current_literal/1, % -Literal
62
+ rdf_transaction/1, % :Goal
63
+ rdf_transaction/2, % :Goal, +Id
64
+ rdf_transaction/3, % :Goal, +Id, +Options
65
+ rdf_active_transaction/1, % ?Id
66
+
67
+ rdf_monitor/2, % :Goal, +Options
68
+
69
+ rdf_save_db/1, % +File
70
+ rdf_save_db/2, % +File, +DB
71
+ rdf_load_db/1, % +File
72
+ rdf_reset_db/0,
73
+
74
+ rdf_node/1, % -Id
75
+ rdf_bnode/1, % -Id
76
+ rdf_is_bnode/1, % +Id
77
+
78
+ rdf_is_resource/1, % +Term
79
+ rdf_is_literal/1, % +Term
80
+ rdf_literal_value/2, % +Term, -Value
81
+
82
+ rdf_load/1, % +File
83
+ rdf_load/2, % +File, +Options
84
+ rdf_save/1, % +File
85
+ rdf_save/2, % +File, +Options
86
+ rdf_unload/1, % +File
87
+ rdf_unload_graph/1, % +Graph
88
+
89
+ rdf_md5/2, % +DB, -MD5
90
+ rdf_atom_md5/3, % +Text, +Times, -MD5
91
+
92
+ rdf_create_graph/1, % ?Graph
93
+ rdf_graph_property/2, % ?Graph, ?Property
94
+ rdf_set_graph/2, % +Graph, +Property
95
+ rdf_graph/1, % ?Graph
96
+ rdf_source/1, % ?File
97
+ rdf_source/2, % ?DB, ?SourceURL
98
+ rdf_make/0, % Reload modified databases
99
+ rdf_gc/0, % Garbage collection
100
+
101
+ rdf_source_location/2, % +Subject, -Source
102
+ rdf_statistics/1, % -Key
103
+ rdf_set/1, % +Term
104
+ rdf_generation/1, % -Generation
105
+ rdf_snapshot/1, % -Snapshot
106
+ rdf_delete_snapshot/1, % +Snapshot
107
+ rdf_current_snapshot/1, % +Snapshot
108
+ rdf_estimate_complexity/4, % +S,+P,+O,-Count
109
+
110
+ rdf_save_subject/3, % +Stream, +Subject, +DB
111
+ rdf_save_header/2, % +Out, +Options
112
+ rdf_save_footer/1, % +Out
113
+
114
+ rdf_equal/2, % ?Resource, ?Resource
115
+ lang_equal/2, % +Lang1, +Lang2
116
+ lang_matches/2, % +Lang, +Pattern
117
+
118
+ rdf_prefix/2, % :Alias, +URI
119
+ rdf_current_prefix/2, % :Alias, ?URI
120
+ rdf_register_prefix/2, % +Alias, +URI
121
+ rdf_register_prefix/3, % +Alias, +URI, +Options
122
+ rdf_unregister_prefix/1, % +Alias
123
+ rdf_current_ns/2, % :Alias, ?URI
124
+ rdf_register_ns/2, % +Alias, +URI
125
+ rdf_register_ns/3, % +Alias, +URI, +Options
126
+ rdf_global_id/2, % ?NS:Name, :Global
127
+ rdf_global_object/2, % +Object, :NSExpandedObject
128
+ rdf_global_term/2, % +Term, :WithExpandedNS
129
+
130
+ rdf_compare/3, % -Dif, +Object1, +Object2
131
+ rdf_match_label/3, % +How, +String, +Label
132
+ rdf_split_url/3, % ?Base, ?Local, ?URL
133
+ rdf_url_namespace/2, % +URL, ?Base
134
+
135
+ rdf_warm_indexes/0,
136
+ rdf_warm_indexes/1, % +Indexed
137
+ rdf_update_duplicates/0,
138
+
139
+ rdf_debug/1, % Set verbosity
140
+
141
+ rdf_new_literal_map/1, % -Handle
142
+ rdf_destroy_literal_map/1, % +Handle
143
+ rdf_reset_literal_map/1, % +Handle
144
+ rdf_insert_literal_map/3, % +Handle, +Key, +Literal
145
+ rdf_insert_literal_map/4, % +Handle, +Key, +Literal, -NewKeys
146
+ rdf_delete_literal_map/3, % +Handle, +Key, +Literal
147
+ rdf_delete_literal_map/2, % +Handle, +Key
148
+ rdf_find_literal_map/3, % +Handle, +KeyList, -Literals
149
+ rdf_keys_in_literal_map/3, % +Handle, +Spec, -Keys
150
+ rdf_statistics_literal_map/2, % +Handle, +Name(-Arg...)
151
+
152
+ rdf_graph_prefixes/2, % ?Graph, -Prefixes
153
+ rdf_graph_prefixes/3, % ?Graph, -Prefixes, :Filter
154
+
155
+ (rdf_meta)/1, % +Heads
156
+ op(1150, fx, (rdf_meta))
157
+ ]).
158
+ :- use_module(library(semweb/rdf_prefixes),
159
+ [ (rdf_meta)/1,
160
+ register_file_prefixes/1,
161
+ rdf_global_id/2,
162
+ rdf_register_ns/2,
163
+ % re-exported predicates
164
+ rdf_global_object/2,
165
+ rdf_current_ns/2,
166
+ rdf_prefix/2,
167
+ rdf_global_term/2,
168
+ rdf_register_ns/3,
169
+ rdf_register_prefix/3,
170
+ rdf_register_prefix/2,
171
+ rdf_current_prefix/2,
172
+ rdf_unregister_prefix/1
173
+ ]).
174
+
175
+ :- autoload(library(apply),[maplist/2,maplist/3]).
176
+ :- use_module(library(debug),[debug/3,assertion/1]).
177
+ :- autoload(library(error),[must_be/2,existence_error/2]).
178
+ :- autoload(library(gensym),[gensym/2,reset_gensym/1]).
179
+ :- autoload(library(lists),
180
+ [member/2,flatten/2,list_to_set/2,append/3,select/3]).
181
+ :- autoload(library(memfile),
182
+ [atom_to_memory_file/2,open_memory_file/4]).
183
+ :- autoload(library(option),
184
+ [option/2,option/3,merge_options/3,meta_options/3]).
185
+ :- autoload(library(rdf),[process_rdf/3]).
186
+ :- autoload(library(sgml),
187
+ [ load_structure/3,
188
+ xml_quote_attribute/3,
189
+ xml_name/1,
190
+ xml_quote_cdata/3,
191
+ xml_is_dom/1,
192
+ iri_xml_namespace/3,
193
+ iri_xml_namespace/2
194
+ ]).
195
+ :- autoload(library(sgml_write),[xml_write/3]).
196
+ :- autoload(library(uri),
197
+ [ uri_file_name/2,
198
+ uri_is_global/1,
199
+ uri_normalized/2,
200
+ uri_components/2,
201
+ uri_data/3,
202
+ uri_data/4
203
+ ]).
204
+ :- autoload(library(xsdp_types),[xsdp_numeric_uri/2]).
205
+ :- autoload(library(semweb/rdf_cache),[rdf_cache_file/3]).
206
+
207
+ :- if(exists_source(library(thread))).
208
+ :- autoload(library(thread), [concurrent/3]).
209
+ :- endif.
210
+
211
+ :- use_foreign_library(foreign(rdf_db)).
212
+ :- public rdf_print_predicate_cloud/2. % print matrix of reachable predicates
213
+
214
+ :- meta_predicate
215
+ rdf_transaction(0),
216
+ rdf_transaction(0, +),
217
+ rdf_transaction(0, +, +),
218
+ rdf_monitor(1, +),
219
+ rdf_save(+, :),
220
+ rdf_load(+, :).
221
+
222
+ :- predicate_options(rdf_graph_prefixes/3, 3,
223
+ [ expand(callable+4),
224
+ filter(callable+3),
225
+ get_prefix(callable+2),
226
+ min_count(nonneg)
227
+ ]).
228
+ :- predicate_options(rdf_load/2, 2,
229
+ [ base_uri(atom),
230
+ blank_nodes(oneof([share,noshare])),
231
+ cache(boolean),
232
+ concurrent(positive_integer),
233
+ db(atom),
234
+ format(oneof([xml,triples,turtle,trig,nquads,ntriples])),
235
+ graph(atom),
236
+ multifile(boolean),
237
+ if(oneof([true,changed,not_loaded])),
238
+ modified(-float),
239
+ prefixes(-list),
240
+ silent(boolean),
241
+ register_namespaces(boolean)
242
+ ]).
243
+ :- predicate_options(rdf_save/2, 2,
244
+ [ graph(atom),
245
+ db(atom),
246
+ anon(boolean),
247
+ base_uri(atom),
248
+ write_xml_base(boolean),
249
+ convert_typed_literal(callable),
250
+ encoding(encoding),
251
+ document_language(atom),
252
+ namespaces(list(atom)),
253
+ xml_attributes(boolean),
254
+ inline(boolean)
255
+ ]).
256
+ :- predicate_options(rdf_save_header/2, 2,
257
+ [ graph(atom),
258
+ db(atom),
259
+ namespaces(list(atom))
260
+ ]).
261
+ :- predicate_options(rdf_save_subject/3, 3,
262
+ [ graph(atom),
263
+ base_uri(atom),
264
+ convert_typed_literal(callable),
265
+ document_language(atom)
266
+ ]).
267
+ :- predicate_options(rdf_transaction/3, 3,
268
+ [ snapshot(any)
269
+ ]).
270
+
271
+ :- discontiguous
272
+ term_expansion/2.
273
+
274
+ /** <module> Core RDF database
275
+
276
+ The file library(semweb/rdf_db) provides the core of the SWI-Prolog RDF
277
+ store.
278
+
279
+ @deprecated New applications should use library(semweb/rdf11), which
280
+ provides a much more intuitive API to the RDF store, notably
281
+ for handling literals. The library(semweb/rdf11) runs
282
+ currently on top of this library and both can run side-by-side
283
+ in the same application. Terms retrieved from the database
284
+ however have a different shape and can not be exchanged without
285
+ precautions.
286
+ */
287
+
288
+ /*******************************
289
+ * PREFIXES *
290
+ *******************************/
291
+
292
+ % the ns/2 predicate is historically defined in this module. We'll keep
293
+ % that for compatibility reasons.
294
+
295
+ :- multifile ns/2.
296
+ :- dynamic ns/2. % ID, URL
297
+
298
+ :- multifile
299
+ rdf_prefixes:rdf_empty_prefix_cache/2.
300
+
301
+ rdf_prefixes:rdf_empty_prefix_cache(_Prefix, _IRI) :-
302
+ rdf_empty_prefix_cache.
303
+
304
+ :- rdf_meta
305
+ rdf(r,r,o),
306
+ rdf_has(r,r,o,r),
307
+ rdf_has(r,r,o),
308
+ rdf_assert(r,r,o),
309
+ rdf_retractall(r,r,o),
310
+ rdf(r,r,o,?),
311
+ rdf_assert(r,r,o,+),
312
+ rdf_retractall(r,r,o,?),
313
+ rdf_reachable(r,r,o),
314
+ rdf_reachable(r,r,o,+,?),
315
+ rdf_update(r,r,o,t),
316
+ rdf_update(r,r,o,+,t),
317
+ rdf_equal(o,o),
318
+ rdf_source_location(r,-),
319
+ rdf_resource(r),
320
+ rdf_subject(r),
321
+ rdf_create_graph(r),
322
+ rdf_graph(r),
323
+ rdf_graph_property(r,?),
324
+ rdf_set_graph(r,+),
325
+ rdf_unload_graph(r),
326
+ rdf_set_predicate(r, t),
327
+ rdf_predicate_property(r, -),
328
+ rdf_estimate_complexity(r,r,r,-),
329
+ rdf_print_predicate_cloud(r,+).
330
+
331
+ %! rdf_equal(?Resource1, ?Resource2)
332
+ %
333
+ % Simple equality test to exploit goal-expansion.
334
+
335
+ rdf_equal(Resource, Resource).
336
+
337
+ %! lang_equal(+Lang1, +Lang2) is semidet.
338
+ %
339
+ % True if two RFC language specifiers denote the same language
340
+ %
341
+ % @see lang_matches/2.
342
+
343
+ lang_equal(Lang, Lang) :- !.
344
+ lang_equal(Lang1, Lang2) :-
345
+ downcase_atom(Lang1, LangCannon),
346
+ downcase_atom(Lang2, LangCannon).
347
+
348
+ %! lang_matches(+Lang, +Pattern) is semidet.
349
+ %
350
+ % True if Lang matches Pattern. This implements XML language
351
+ % matching conform RFC 4647. Both Lang and Pattern are
352
+ % dash-separated strings of identifiers or (for Pattern) the
353
+ % wildcard *. Identifiers are matched case-insensitive and a *
354
+ % matches any number of identifiers. A short pattern is the same
355
+ % as *.
356
+
357
+
358
+ /*******************************
359
+ * BASIC TRIPLE QUERIES *
360
+ *******************************/
361
+
362
+ %! rdf(?Subject, ?Predicate, ?Object) is nondet.
363
+ %
364
+ % Elementary query for triples. Subject and Predicate are atoms
365
+ % representing the fully qualified URL of the resource. Object is
366
+ % either an atom representing a resource or literal(Value) if the
367
+ % object is a literal value. If a value of the form
368
+ % NameSpaceID:LocalName is provided it is expanded to a ground
369
+ % atom using expand_goal/2. This implies you can use this
370
+ % construct in compiled code without paying a performance penalty.
371
+ % Literal values take one of the following forms:
372
+ %
373
+ % * Atom
374
+ % If the value is a simple atom it is the textual representation
375
+ % of a string literal without explicit type or language
376
+ % qualifier.
377
+ %
378
+ % * lang(LangID, Atom)
379
+ % Atom represents the text of a string literal qualified with
380
+ % the given language.
381
+ %
382
+ % * type(TypeID, Value)
383
+ % Used for attributes qualified using the =|rdf:datatype|=
384
+ % TypeID. The Value is either the textual representation or a
385
+ % natural Prolog representation. See the option
386
+ % convert_typed_literal(:Convertor) of the parser. The storage
387
+ % layer provides efficient handling of atoms, integers (64-bit)
388
+ % and floats (native C-doubles). All other data is represented
389
+ % as a Prolog record.
390
+ %
391
+ % For literal querying purposes, Object can be of the form
392
+ % literal(+Query, -Value), where Query is one of the terms below.
393
+ % If the Query takes a literal argument and the value has a
394
+ % numeric type numerical comparison is performed.
395
+ %
396
+ % * plain(+Text)
397
+ % Perform exact match and demand the language or type qualifiers
398
+ % to match. This query is fully indexed.
399
+ %
400
+ % * icase(+Text)
401
+ % Perform a full but case-insensitive match. This query is
402
+ % fully indexed.
403
+ %
404
+ % * exact(+Text)
405
+ % Same as icase(Text). Backward compatibility.
406
+ %
407
+ % * substring(+Text)
408
+ % Match any literal that contains Text as a case-insensitive
409
+ % substring. The query is not indexed on Object.
410
+ %
411
+ % * word(+Text)
412
+ % Match any literal that contains Text delimited by a non
413
+ % alpha-numeric character, the start or end of the string. The
414
+ % query is not indexed on Object.
415
+ %
416
+ % * prefix(+Text)
417
+ % Match any literal that starts with Text. This call is intended
418
+ % for completion. The query is indexed using the skip list of
419
+ % literals.
420
+ %
421
+ % * ge(+Literal)
422
+ % Match any literal that is equal or larger than Literal in the
423
+ % ordered set of literals.
424
+ %
425
+ % * gt(+Literal)
426
+ % Match any literal that is larger than Literal in the ordered set
427
+ % of literals.
428
+ %
429
+ % * eq(+Literal)
430
+ % Match any literal that is equal to Literal in the ordered set
431
+ % of literals.
432
+ %
433
+ % * le(+Literal)
434
+ % Match any literal that is equal or smaller than Literal in the
435
+ % ordered set of literals.
436
+ %
437
+ % * lt(+Literal)
438
+ % Match any literal that is smaller than Literal in the ordered set
439
+ % of literals.
440
+ %
441
+ % * between(+Literal1, +Literal2)
442
+ % Match any literal that is between Literal1 and Literal2 in the
443
+ % ordered set of literals. This may include both Literal1 and
444
+ % Literal2.
445
+ %
446
+ % * like(+Pattern)
447
+ % Match any literal that matches Pattern case insensitively,
448
+ % where the `*' character in Pattern matches zero or more
449
+ % characters.
450
+ %
451
+ % Backtracking never returns duplicate triples. Duplicates can be
452
+ % retrieved using rdf/4. The predicate rdf/3 raises a type-error
453
+ % if called with improper arguments. If rdf/3 is called with a
454
+ % term literal(_) as Subject or Predicate object it fails
455
+ % silently. This allows for graph matching goals like
456
+ % rdf(S,P,O),rdf(O,P2,O2) to proceed without errors.
457
+
458
+ %! rdf(?Subject, ?Predicate, ?Object, ?Source) is nondet.
459
+ %
460
+ % As rdf/3 but in addition query the graph to which the triple
461
+ % belongs. Unlike rdf/3, this predicate does not remove duplicates
462
+ % from the result set.
463
+ %
464
+ % @param Source is a term Graph:Line. If Source is instantiated,
465
+ % passing an atom is the same as passing Atom:_.
466
+
467
+
468
+ %! rdf_has(?Subject, +Predicate, ?Object) is nondet.
469
+ %
470
+ % Succeeds if the triple rdf(Subject, Predicate, Object) is true
471
+ % exploiting the rdfs:subPropertyOf predicate as well as inverse
472
+ % predicates declared using rdf_set_predicate/2 with the
473
+ % =inverse_of= property.
474
+
475
+ %! rdf_has(?Subject, +Predicate, ?Object, -RealPredicate) is nondet.
476
+ %
477
+ % Same as rdf_has/3, but RealPredicate is unified to the actual
478
+ % predicate that makes this relation true. RealPredicate must be
479
+ % Predicate or an rdfs:subPropertyOf Predicate. If an inverse
480
+ % match is found, RealPredicate is the term inverse_of(Pred).
481
+
482
+ %! rdf_reachable(?Subject, +Predicate, ?Object) is nondet.
483
+ %
484
+ % Is true if Object can be reached from Subject following the
485
+ % transitive predicate Predicate or a sub-property thereof, while
486
+ % respecting the symmetric(true) or inverse_of(P2) properties.
487
+ %
488
+ % If used with either Subject or Object unbound, it first returns
489
+ % the origin, followed by the reachable nodes in breadth-first
490
+ % search-order. The implementation internally looks one solution
491
+ % ahead and succeeds deterministically on the last solution. This
492
+ % predicate never generates the same node twice and is robust
493
+ % against cycles in the transitive relation.
494
+ %
495
+ % With all arguments instantiated, it succeeds deterministically
496
+ % if a path can be found from Subject to Object. Searching starts
497
+ % at Subject, assuming the branching factor is normally lower. A
498
+ % call with both Subject and Object unbound raises an
499
+ % instantiation error. The following example generates all
500
+ % subclasses of rdfs:Resource:
501
+ %
502
+ % ==
503
+ % ?- rdf_reachable(X, rdfs:subClassOf, rdfs:'Resource').
504
+ % X = 'http://www.w3.org/2000/01/rdf-schema#Resource' ;
505
+ % X = 'http://www.w3.org/2000/01/rdf-schema#Class' ;
506
+ % X = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#Property' ;
507
+ % ...
508
+ % ==
509
+
510
+
511
+ %! rdf_reachable(?Subject, +Predicate, ?Object, +MaxD, -D) is nondet.
512
+ %
513
+ % Same as rdf_reachable/3, but in addition, MaxD limits the number
514
+ % of edges expanded and D is unified with the `distance' between
515
+ % Subject and Object. Distance 0 means Subject and Object are the
516
+ % same resource. MaxD can be the constant =infinite= to impose no
517
+ % distance-limit.
518
+
519
+ %! rdf_subject(?Resource) is nondet.
520
+ %
521
+ % True if Resource appears as a subject. This query respects the
522
+ % visibility rules implied by the logical update view.
523
+ %
524
+ % @see rdf_resource/1.
525
+
526
+ rdf_subject(Resource) :-
527
+ rdf_resource(Resource),
528
+ ( rdf(Resource, _, _) -> true ).
529
+
530
+ %! rdf_resource(?Resource) is nondet.
531
+ %
532
+ % True when Resource is a resource used as a subject or object in
533
+ % a triple.
534
+ %
535
+ % This predicate is primarily intended as a way to process all
536
+ % resources without processing resources twice. The user must be
537
+ % aware that some of the returned resources may not appear in any
538
+ % _visible_ triple.
539
+
540
+
541
+ /*******************************
542
+ * TRIPLE MODIFICATIONS *
543
+ *******************************/
544
+
545
+ %! rdf_assert(+Subject, +Predicate, +Object) is det.
546
+ %
547
+ % Assert a new triple into the database. This is equivalent to
548
+ % rdf_assert/4 using Graph =user=. Subject and Predicate are
549
+ % resources. Object is either a resource or a term literal(Value).
550
+ % See rdf/3 for an explanation of Value for typed and language
551
+ % qualified literals. All arguments are subject to name-space
552
+ % expansion. Complete duplicates (including the same graph and
553
+ % `line' and with a compatible `lifespan') are not added to the
554
+ % database.
555
+
556
+ %! rdf_assert(+Subject, +Predicate, +Object, +Graph) is det.
557
+ %
558
+ % As rdf_assert/3, adding the predicate to the indicated named
559
+ % graph.
560
+ %
561
+ % @param Graph is either the name of a graph (an atom) or a term
562
+ % Graph:Line, where Line is an integer that denotes a line number.
563
+
564
+ %! rdf_retractall(?Subject, ?Predicate, ?Object) is det.
565
+ %
566
+ % Remove all matching triples from the database. As
567
+ % rdf_retractall/4 using an unbound graph. See also
568
+ % rdf_retractall/4 and rdf_unload/1.
569
+
570
+ %! rdf_retractall(?Subject, ?Predicate, ?Object, ?Graph) is det.
571
+ %
572
+ % As rdf_retractall/3, also matching Graph. This is particularly
573
+ % useful to remove all triples coming from a loaded file. See also
574
+ % rdf_unload/1.
575
+
576
+ %! rdf_update(+Subject, +Predicate, +Object, ++Action) is det.
577
+ %! rdf_update(+Subject, +Predicate, +Object, +Graph, ++Action) is det
578
+ %
579
+ % Replaces one of the three (four) fields on the matching triples
580
+ % depending on Action:
581
+ %
582
+ % * subject(Resource)
583
+ % Changes the first field of the triple.
584
+ % * predicate(Resource)
585
+ % Changes the second field of the triple.
586
+ % * object(Object)
587
+ % Changes the last field of the triple to the given resource or
588
+ % literal(Value).
589
+ % * graph(Graph)
590
+ % Moves the triple from its current named graph to Graph.
591
+ % This only works with rdf_update/5 and throws an error when
592
+ % used with rdf_update/4.
593
+
594
+
595
+ /*******************************
596
+ * COLLECTIONS *
597
+ *******************************/
598
+
599
+ %! rdf_member_property(?Prop, ?Index)
600
+ %
601
+ % Deal with the rdf:_1, ... properties.
602
+
603
+ term_expansion(member_prefix(x),
604
+ member_prefix(Prefix)) :-
605
+ rdf_db:ns(rdf, NS),
606
+ atom_concat(NS, '_', Prefix).
607
+ member_prefix(x).
608
+
609
+ rdf_member_property(P, N) :-
610
+ integer(N),
611
+ !,
612
+ member_prefix(Prefix),
613
+ atom_concat(Prefix, N, P).
614
+ rdf_member_property(P, N) :-
615
+ member_prefix(Prefix),
616
+ atom_concat(Prefix, Sub, P),
617
+ atom_number(Sub, N).
618
+
619
+
620
+ /*******************************
621
+ * ANONYMOUS SUBJECTS *
622
+ *******************************/
623
+
624
+ %! rdf_node(-Id)
625
+ %
626
+ % Generate a unique blank node identifier for a subject.
627
+ %
628
+ % @deprecated New code should use rdf_bnode/1.
629
+
630
+ rdf_node(Resource) :-
631
+ rdf_bnode(Resource).
632
+
633
+ %! rdf_bnode(-Id)
634
+ %
635
+ % Generate a unique anonymous identifier for a subject.
636
+
637
+ rdf_bnode(Value) :-
638
+ repeat,
639
+ gensym('_:genid', Value),
640
+ \+ rdf(Value, _, _),
641
+ \+ rdf(_, _, Value),
642
+ \+ rdf(_, Value, _),
643
+ !.
644
+
645
+
646
+
647
+ /*******************************
648
+ * TYPES *
649
+ *******************************/
650
+
651
+ %! rdf_is_bnode(+Id)
652
+ %
653
+ % Tests if a resource is a blank node (i.e. is an anonymous
654
+ % resource). A blank node is represented as an atom that starts
655
+ % with =|_:|=. For backward compatibility reason, =|__|= is also
656
+ % considered to be a blank node.
657
+ %
658
+ % @see rdf_bnode/1.
659
+
660
+ %! rdf_is_resource(@Term) is semidet.
661
+ %
662
+ % True if Term is an RDF resource. Note that this is merely a
663
+ % type-test; it does not mean this resource is involved in any
664
+ % triple. Blank nodes are also considered resources.
665
+ %
666
+ % @see rdf_is_bnode/1
667
+
668
+ rdf_is_resource(Term) :-
669
+ atom(Term).
670
+
671
+ %! rdf_is_literal(@Term) is semidet.
672
+ %
673
+ % True if Term is an RDF literal object. Currently only checks for
674
+ % groundness and the literal functor.
675
+
676
+ rdf_is_literal(literal(Value)) :-
677
+ ground(Value).
678
+
679
+ /*******************************
680
+ * LITERALS *
681
+ *******************************/
682
+
683
+ %! rdf_current_literal(-Literal) is nondet.
684
+ %
685
+ % True when Literal is a currently known literal. Enumerates each
686
+ % unique literal exactly once. Note that it is possible that the
687
+ % literal only appears in already deleted triples. Deleted triples
688
+ % may be locked due to active queries, transactions or snapshots
689
+ % or may not yet be reclaimed by the garbage collector.
690
+
691
+
692
+ %! rdf_literal_value(+Literal, -Value) is semidet.
693
+ %
694
+ % True when value is the appropriate Prolog representation of
695
+ % Literal in the RDF _|value space|_. Current mapping:
696
+ %
697
+ % | Plain literals | Atom |
698
+ % | Language tagged literal | Atom holding plain text |
699
+ % | xsd:string | Atom |
700
+ % | rdf:XMLLiteral | XML DOM Tree |
701
+ % | Numeric XSD type | Number |
702
+ %
703
+ % @tbd Well, this is the long-term idea.
704
+ % @tbd Add mode (-,+)
705
+
706
+ :- rdf_meta
707
+ rdf_literal_value(o, -),
708
+ typed_value(r, +, -),
709
+ numeric_value(r, +, -).
710
+
711
+ rdf_literal_value(literal(String), Value) :-
712
+ atom(String),
713
+ !,
714
+ Value = String.
715
+ rdf_literal_value(literal(lang(_Lang, String)), String).
716
+ rdf_literal_value(literal(type(Type, String)), Value) :-
717
+ typed_value(Type, String, Value).
718
+
719
+ typed_value(Numeric, String, Value) :-
720
+ xsdp_numeric_uri(Numeric, NumType),
721
+ !,
722
+ numeric_value(NumType, String, Value).
723
+ typed_value(xsd:string, String, String).
724
+ typed_value(rdf:'XMLLiteral', Value, DOM) :-
725
+ ( atom(Value)
726
+ -> setup_call_cleanup(
727
+ ( atom_to_memory_file(Value, MF),
728
+ open_memory_file(MF, read, In, [free_on_close(true)])
729
+ ),
730
+ load_structure(stream(In), DOM, [dialect(xml)]),
731
+ close(In))
732
+ ; DOM = Value
733
+ ).
734
+
735
+ numeric_value(xsd:integer, String, Value) :-
736
+ atom_number(String, Value),
737
+ integer(Value).
738
+ numeric_value(xsd:float, String, Value) :-
739
+ atom_number(String, Number),
740
+ Value is float(Number).
741
+ numeric_value(xsd:double, String, Value) :-
742
+ atom_number(String, Number),
743
+ Value is float(Number).
744
+ numeric_value(xsd:decimal, String, Value) :-
745
+ atom_number(String, Value).
746
+
747
+
748
+ /*******************************
749
+ * SOURCE *
750
+ *******************************/
751
+
752
+ %! rdf_source_location(+Subject, -Location) is nondet.
753
+ %
754
+ % True when triples for Subject are loaded from Location.
755
+ %
756
+ % @param Location is a term File:Line.
757
+
758
+ rdf_source_location(Subject, Source) :-
759
+ findall(Source, rdf(Subject, _, _, Source), Sources),
760
+ sort(Sources, Unique),
761
+ member(Source, Unique).
762
+
763
+
764
+ /*******************************
765
+ * GARBAGE COLLECT *
766
+ *******************************/
767
+
768
+ %! rdf_create_gc_thread
769
+ %
770
+ % Create the garbage collection thread.
771
+
772
+ :- public
773
+ rdf_create_gc_thread/0.
774
+
775
+ rdf_create_gc_thread :-
776
+ thread_create(rdf_gc_loop, _,
777
+ [ alias('__rdf_GC')
778
+ ]).
779
+
780
+ %! rdf_gc_loop
781
+ %
782
+ % Take care of running the RDF garbage collection. This predicate
783
+ % is called from a thread started by creating the RDF DB.
784
+
785
+ rdf_gc_loop :-
786
+ catch(rdf_gc_loop(0), E, recover_gc(E, Cont)),
787
+ ( Cont == true
788
+ -> rdf_gc_loop
789
+ ; thread_self(Me),
790
+ thread_detach(Me)
791
+ ).
792
+
793
+ recover_gc('$aborted', false) :-
794
+ !.
795
+ recover_gc(unwind(_), false) :-
796
+ !.
797
+ recover_gc(Error, true) :-
798
+ print_message(error, Error).
799
+
800
+ rdf_gc_loop(CPU) :-
801
+ repeat,
802
+ ( consider_gc(CPU)
803
+ -> rdf_gc(CPU1),
804
+ sleep(CPU1)
805
+ ; sleep(0.1)
806
+ ),
807
+ fail.
808
+
809
+ %! rdf_gc(-CPU) is det.
810
+ %
811
+ % Run RDF GC one time. CPU is the amount of CPU time spent. We
812
+ % update this in Prolog because portable access to thread specific
813
+ % CPU is really hard in C.
814
+
815
+ rdf_gc(CPU) :-
816
+ statistics(cputime, CPU0),
817
+ ( rdf_gc_
818
+ -> statistics(cputime, CPU1),
819
+ CPU is CPU1-CPU0,
820
+ rdf_add_gc_time(CPU)
821
+ ; CPU = 0.0
822
+ ).
823
+
824
+ %! rdf_gc is det.
825
+ %
826
+ % Run the RDF-DB garbage collector until no garbage is left and all
827
+ % tables are fully optimized. Under normal operation a separate thread
828
+ % with identifier =|__rdf_GC|= performs garbage collection as long as
829
+ % it is considered `useful'.
830
+ %
831
+ % Using rdf_gc/0 should only be needed to ensure a fully clean
832
+ % database for analysis purposes such as leak detection.
833
+
834
+ rdf_gc :-
835
+ has_garbage,
836
+ !,
837
+ rdf_gc(_),
838
+ rdf_gc.
839
+ rdf_gc.
840
+
841
+ %! has_garbage is semidet.
842
+ %
843
+ % True if there is something to gain using GC.
844
+
845
+ has_garbage :-
846
+ rdf_gc_info_(Info),
847
+ has_garbage(Info),
848
+ !.
849
+
850
+ has_garbage(Info) :- arg(2, Info, Garbage), Garbage > 0.
851
+ has_garbage(Info) :- arg(3, Info, Reindexed), Reindexed > 0.
852
+ has_garbage(Info) :- arg(4, Info, Optimizable), Optimizable > 0.
853
+
854
+ %! consider_gc(+CPU) is semidet.
855
+ %
856
+ % @param CPU is the amount of CPU time spent in the most recent
857
+ % GC.
858
+
859
+ consider_gc(_CPU) :-
860
+ ( rdf_gc_info_(gc_info(Triples, % Total #triples in DB
861
+ Garbage, % Garbage triples in DB
862
+ Reindexed, % Reindexed & not reclaimed
863
+ Optimizable, % Non-optimized tables
864
+ _KeepGen, % Oldest active generation
865
+ _LastGCGen, % Oldest active gen at last GC
866
+ _ReindexGen,
867
+ _LastGCReindexGen))
868
+ -> ( (Garbage+Reindexed) * 5 > Triples
869
+ ; Optimizable > 4
870
+ )
871
+ ; print_message(error, rdf(invalid_gc_info)),
872
+ sleep(10)
873
+ ),
874
+ !.
875
+
876
+
877
+ /*******************************
878
+ * STATISTICS *
879
+ *******************************/
880
+
881
+ %! rdf_statistics(?KeyValue) is nondet.
882
+ %
883
+ % Obtain statistics on the RDF database. Defined statistics are:
884
+ %
885
+ % * graphs(-Count)
886
+ % Number of named graphs.
887
+ %
888
+ % * triples(-Count)
889
+ % Total number of triples in the database. This is the number
890
+ % of asserted triples minus the number of retracted ones. The
891
+ % number of _visible_ triples in a particular context may be
892
+ % different due to visibility rules defined by the logical
893
+ % update view and transaction isolation.
894
+ %
895
+ % * resources(-Count)
896
+ % Number of resources that appear as subject or object in a
897
+ % triple. See rdf_resource/1.
898
+ %
899
+ % * properties(-Count)
900
+ % Number of current predicates. See rdf_current_predicate/1.
901
+ %
902
+ % * literals(-Count)
903
+ % Number of current literals. See rdf_current_literal/1.
904
+ %
905
+ % * gc(GCCount, ReclaimedTriples, ReindexedTriples, Time)
906
+ % Information about the garbage collector.
907
+ %
908
+ % * searched_nodes(-Count)
909
+ % Number of nodes expanded by rdf_reachable/3 and
910
+ % rdf_reachable/5.
911
+ %
912
+ % * lookup(rdf(S,P,O,G), Count)
913
+ % Number of queries that have been performed for this particular
914
+ % instantiation pattern. Each of S,P,O,G is either + or -.
915
+ % Fails in case the number of performed queries is zero.
916
+ %
917
+ % * hash_quality(rdf(S,P,O,G), Buckets, Quality, PendingResize)
918
+ % Statistics on the index for this pattern. Indices are created
919
+ % lazily on the first relevant query.
920
+ %
921
+ % * triples_by_graph(Graph, Count)
922
+ % This statistics is produced for each named graph. See
923
+ % =triples= for the interpretation of this value.
924
+
925
+ rdf_statistics(graphs(Count)) :-
926
+ rdf_statistics_(graphs(Count)).
927
+ rdf_statistics(triples(Count)) :-
928
+ rdf_statistics_(triples(Count)).
929
+ rdf_statistics(duplicates(Count)) :-
930
+ rdf_statistics_(duplicates(Count)).
931
+ rdf_statistics(lingering(Count)) :-
932
+ rdf_statistics_(lingering(Count)).
933
+ rdf_statistics(resources(Count)) :-
934
+ rdf_statistics_(resources(Count)).
935
+ rdf_statistics(properties(Count)) :-
936
+ rdf_statistics_(predicates(Count)).
937
+ rdf_statistics(literals(Count)) :-
938
+ rdf_statistics_(literals(Count)).
939
+ rdf_statistics(gc(Count, Reclaimed, Reindexed, Time)) :-
940
+ rdf_statistics_(gc(Count, Reclaimed, Reindexed, Time)).
941
+ rdf_statistics(searched_nodes(Count)) :-
942
+ rdf_statistics_(searched_nodes(Count)).
943
+ rdf_statistics(lookup(Index, Count)) :-
944
+ functor(Indexed, indexed, 16),
945
+ rdf_statistics_(Indexed),
946
+ index(Index, I),
947
+ Arg is I + 1,
948
+ arg(Arg, Indexed, Count),
949
+ Count \== 0.
950
+ rdf_statistics(hash_quality(Index, Size, Quality,Optimize)) :-
951
+ rdf_statistics_(hash_quality(List)),
952
+ member(hash(Place,Size,Quality,Optimize), List),
953
+ index(Index, Place).
954
+ rdf_statistics(triples_by_graph(Graph, Count)) :-
955
+ rdf_graph_(Graph, Count).
956
+
957
+ index(rdf(-,-,-,-), 0).
958
+ index(rdf(+,-,-,-), 1).
959
+ index(rdf(-,+,-,-), 2).
960
+ index(rdf(+,+,-,-), 3).
961
+ index(rdf(-,-,+,-), 4).
962
+ index(rdf(+,-,+,-), 5).
963
+ index(rdf(-,+,+,-), 6).
964
+ index(rdf(+,+,+,-), 7).
965
+
966
+ index(rdf(-,-,-,+), 8).
967
+ index(rdf(+,-,-,+), 9).
968
+ index(rdf(-,+,-,+), 10).
969
+ index(rdf(+,+,-,+), 11).
970
+ index(rdf(-,-,+,+), 12).
971
+ index(rdf(+,-,+,+), 13).
972
+ index(rdf(-,+,+,+), 14).
973
+ index(rdf(+,+,+,+), 15).
974
+
975
+
976
+ /*******************************
977
+ * PREDICATES *
978
+ *******************************/
979
+
980
+ %! rdf_current_predicate(?Predicate) is nondet.
981
+ %
982
+ % True when Predicate is a currently known predicate. Predicates
983
+ % are created if a triples is created that uses this predicate or
984
+ % a property of the predicate is set using rdf_set_predicate/2.
985
+ % The predicate may (no longer) have triples associated with it.
986
+ %
987
+ % Note that resources that have =|rdf:type|= =|rdf:Property|= are
988
+ % not automatically included in the result-set of this predicate,
989
+ % while _all_ resources that appear as the second argument of a
990
+ % triple _are_ included.
991
+ %
992
+ % @see rdf_predicate_property/2.
993
+
994
+ rdf_current_predicate(P, DB) :-
995
+ rdf_current_predicate(P),
996
+ ( rdf(_,P,_,DB)
997
+ -> true
998
+ ).
999
+
1000
+ %! rdf_predicate_property(?Predicate, ?Property)
1001
+ %
1002
+ % Query properties of a defined predicate. Currently defined
1003
+ % properties are given below.
1004
+ %
1005
+ % * symmetric(Bool)
1006
+ % True if the predicate is defined to be symmetric. I.e., {A} P
1007
+ % {B} implies {B} P {A}. Setting symmetric is equivalent to
1008
+ % inverse_of(Self).
1009
+ %
1010
+ % * inverse_of(Inverse)
1011
+ % True if this predicate is the inverse of Inverse. This
1012
+ % property is used by rdf_has/3, rdf_has/4, rdf_reachable/3 and
1013
+ % rdf_reachable/5.
1014
+ %
1015
+ % * transitive(Bool)
1016
+ % True if this predicate is transitive. This predicate is
1017
+ % currently not used. It might be used to make rdf_has/3 imply
1018
+ % rdf_reachable/3 for transitive predicates.
1019
+ %
1020
+ % * triples(Triples)
1021
+ % Unify Triples with the number of existing triples using this
1022
+ % predicate as second argument. Reporting the number of triples
1023
+ % is intended to support query optimization.
1024
+ %
1025
+ % * rdf_subject_branch_factor(-Float)
1026
+ % Unify Float with the average number of triples associated with
1027
+ % each unique value for the subject-side of this relation. If
1028
+ % there are no triples the value 0.0 is returned. This value is
1029
+ % cached with the predicate and recomputed only after
1030
+ % substantial changes to the triple set associated to this
1031
+ % relation. This property is intended for path optimisation
1032
+ % when solving conjunctions of rdf/3 goals.
1033
+ %
1034
+ % * rdf_object_branch_factor(-Float)
1035
+ % Unify Float with the average number of triples associated with
1036
+ % each unique value for the object-side of this relation. In
1037
+ % addition to the comments with the =rdf_subject_branch_factor=
1038
+ % property, uniqueness of the object value is computed from the
1039
+ % hash key rather than the actual values.
1040
+ %
1041
+ % * rdfs_subject_branch_factor(-Float)
1042
+ % Same as =rdf_subject_branch_factor=, but also considering
1043
+ % triples of `subPropertyOf' this relation. See also rdf_has/3.
1044
+ %
1045
+ % * rdfs_object_branch_factor(-Float)
1046
+ % Same as =rdf_object_branch_factor=, but also considering
1047
+ % triples of `subPropertyOf' this relation. See also rdf_has/3.
1048
+ %
1049
+ % @see rdf_set_predicate/2.
1050
+
1051
+ rdf_predicate_property(P, Prop) :-
1052
+ var(P),
1053
+ !,
1054
+ rdf_current_predicate(P),
1055
+ rdf_predicate_property_(P, Prop).
1056
+ rdf_predicate_property(P, Prop) :-
1057
+ rdf_predicate_property_(P, Prop).
1058
+
1059
+ %! rdf_set_predicate(+Predicate, +Property) is det.
1060
+ %
1061
+ % Define a property of the predicate. This predicate currently
1062
+ % supports the following properties:
1063
+ %
1064
+ % - symmetric(+Boolean)
1065
+ % Set/unset the predicate as being symmetric. Using
1066
+ % symmetric(true) is the same as inverse_of(Predicate),
1067
+ % i.e., creating a predicate that is the inverse of
1068
+ % itself.
1069
+ % - transitive(+Boolean)
1070
+ % Sets the transitive property.
1071
+ % - inverse_of(+Predicate2)
1072
+ % Define Predicate as the inverse of Predicate2. An inverse
1073
+ % relation is deleted using inverse_of([]).
1074
+ %
1075
+ % The `transitive` property is currently not used. The `symmetric`
1076
+ % and `inverse_of` properties are considered by rdf_has/3,4 and
1077
+ % rdf_reachable/3.
1078
+ %
1079
+ % @tbd Maintain these properties based on OWL triples.
1080
+
1081
+
1082
+ /*******************************
1083
+ * SNAPSHOTS *
1084
+ *******************************/
1085
+
1086
+ %! rdf_snapshot(-Snapshot) is det.
1087
+ %
1088
+ % Take a snapshot of the current state of the RDF store. Later,
1089
+ % goals may be executed in the context of the database at this
1090
+ % moment using rdf_transaction/3 with the =snapshot= option. A
1091
+ % snapshot created outside a transaction exists until it is
1092
+ % deleted. Snapshots taken inside a transaction can only be used
1093
+ % inside this transaction.
1094
+
1095
+ %! rdf_delete_snapshot(+Snapshot) is det.
1096
+ %
1097
+ % Delete a snapshot as obtained from rdf_snapshot/1. After this
1098
+ % call, resources used for maintaining the snapshot become subject
1099
+ % to garbage collection.
1100
+
1101
+ %! rdf_current_snapshot(?Term) is nondet.
1102
+ %
1103
+ % True when Term is a currently known snapshot.
1104
+ %
1105
+ % @bug Enumeration of snapshots is slow.
1106
+
1107
+ rdf_current_snapshot(Term) :-
1108
+ current_blob(Term, rdf_snapshot).
1109
+
1110
+
1111
+ /*******************************
1112
+ * TRANSACTION *
1113
+ *******************************/
1114
+
1115
+ %! rdf_transaction(:Goal) is semidet.
1116
+ %
1117
+ % Same as rdf_transaction(Goal, user, []). See rdf_transaction/3.
1118
+
1119
+ %! rdf_transaction(:Goal, +Id) is semidet.
1120
+ %
1121
+ % Same as rdf_transaction(Goal, Id, []). See rdf_transaction/3.
1122
+
1123
+ %! rdf_transaction(:Goal, +Id, +Options) is semidet.
1124
+ %
1125
+ % Run Goal in an RDF transaction. Compared to the ACID model,
1126
+ % RDF transactions have the following properties:
1127
+ %
1128
+ % 1. Modifications inside the transactions become all atomically
1129
+ % visible to the outside world if Goal succeeds or remain
1130
+ % invisible if Goal fails or throws an exception. I.e.,
1131
+ % the _atomicity_ property is fully supported.
1132
+ % 2. _Consistency_ is not guaranteed. Later versions may
1133
+ % implement consistency constraints that will be checked
1134
+ % serialized just before the actual commit of a transaction.
1135
+ % 3. Concurrently executing transactions do not influence each
1136
+ % other. I.e., the _isolation_ property is fully supported.
1137
+ % 4. _Durability_ can be activated by loading
1138
+ % library(semweb/rdf_persistency).
1139
+ %
1140
+ % Processed options are:
1141
+ %
1142
+ % * snapshot(+Snapshot)
1143
+ % Execute Goal using the state of the RDF store as stored in
1144
+ % Snapshot. See rdf_snapshot/1. Snapshot can also be the
1145
+ % atom =true=, which implies that an anonymous snapshot is
1146
+ % created at the current state of the store. Modifications
1147
+ % due to executing Goal are only visible to Goal.
1148
+
1149
+ rdf_transaction(Goal) :-
1150
+ rdf_transaction(Goal, user, []).
1151
+ rdf_transaction(Goal, Id) :-
1152
+ rdf_transaction(Goal, Id, []).
1153
+
1154
+ %! rdf_active_transaction(?Id) is nondet.
1155
+ %
1156
+ % True if Id is the identifier of a transaction in the context of
1157
+ % which this call is executed. If Id is not instantiated,
1158
+ % backtracking yields transaction identifiers starting with the
1159
+ % innermost nested transaction. Transaction identifier terms are
1160
+ % not copied, need not be ground and can be instantiated during
1161
+ % the transaction.
1162
+
1163
+ rdf_active_transaction(Id) :-
1164
+ rdf_active_transactions_(List),
1165
+ member(Id, List).
1166
+
1167
+ %! rdf_monitor(:Goal, +Options)
1168
+ %
1169
+ % Call Goal if specified actions occur on the database.
1170
+
1171
+ rdf_monitor(Goal, Options) :-
1172
+ monitor_mask(Options, 0xffff, Mask),
1173
+ rdf_monitor_(Goal, Mask).
1174
+
1175
+ monitor_mask([], Mask, Mask).
1176
+ monitor_mask([H|T], Mask0, Mask) :-
1177
+ update_mask(H, Mask0, Mask1),
1178
+ monitor_mask(T, Mask1, Mask).
1179
+
1180
+ update_mask(-X, Mask0, Mask) :-
1181
+ !,
1182
+ monitor_mask(X, M),
1183
+ Mask is Mask0 /\ \M.
1184
+ update_mask(+X, Mask0, Mask) :-
1185
+ !,
1186
+ monitor_mask(X, M),
1187
+ Mask is Mask0 \/ M.
1188
+ update_mask(X, Mask0, Mask) :-
1189
+ monitor_mask(X, M),
1190
+ Mask is Mask0 \/ M.
1191
+
1192
+ %! monitor_mask(Name, Mask)
1193
+ %
1194
+ % Mask bit for the monitor events. Note that this must be kept
1195
+ % consistent with the enum broadcast_id defined in rdf_db.c
1196
+
1197
+ % C-defined broadcasts
1198
+ monitor_mask(assert, 0x0001).
1199
+ monitor_mask(assert(load), 0x0002).
1200
+ monitor_mask(retract, 0x0004).
1201
+ monitor_mask(update, 0x0008).
1202
+ monitor_mask(new_literal, 0x0010).
1203
+ monitor_mask(old_literal, 0x0020).
1204
+ monitor_mask(transaction, 0x0040).
1205
+ monitor_mask(load, 0x0080).
1206
+ monitor_mask(create_graph, 0x0100).
1207
+ monitor_mask(reset, 0x0200).
1208
+ % prolog defined broadcasts
1209
+ monitor_mask(parse, 0x1000).
1210
+ monitor_mask(unload, 0x1000). % FIXME: Duplicate
1211
+ % mask for all
1212
+ monitor_mask(all, 0xffff).
1213
+
1214
+ %rdf_broadcast(Term, MaskName) :-
1215
+ %% monitor_mask(MaskName, Mask),
1216
+ %% rdf_broadcast_(Term, Mask).
1217
+
1218
+
1219
+ /*******************************
1220
+ * WARM *
1221
+ *******************************/
1222
+
1223
+ %! rdf_warm_indexes
1224
+ %
1225
+ % Warm all indexes. See rdf_warm_indexes/1.
1226
+
1227
+ rdf_warm_indexes :-
1228
+ findall(Index, rdf_index(Index), Indexes),
1229
+ rdf_warm_indexes(Indexes).
1230
+
1231
+ rdf_index(s).
1232
+ rdf_index(p).
1233
+ rdf_index(o).
1234
+ rdf_index(sp).
1235
+ rdf_index(o).
1236
+ rdf_index(po).
1237
+ rdf_index(spo).
1238
+ rdf_index(g).
1239
+ rdf_index(sg).
1240
+ rdf_index(pg).
1241
+
1242
+ %! rdf_warm_indexes(+Indexes) is det.
1243
+ %
1244
+ % Create the named indexes. Normally, the RDF database creates
1245
+ % indexes on lazily the first time they are needed. This predicate
1246
+ % serves two purposes: it provides an explicit way to make sure
1247
+ % that the required indexes are present and creating multiple
1248
+ % indexes at the same time is more efficient.
1249
+
1250
+
1251
+ /*******************************
1252
+ * DUPLICATES *
1253
+ *******************************/
1254
+
1255
+ %! rdf_update_duplicates is det.
1256
+ %
1257
+ % Update the duplicate administration of the RDF store. This marks
1258
+ % every triple that is potentially a duplicate of another as
1259
+ % duplicate. Being potentially a duplicate means that subject,
1260
+ % predicate and object are equivalent and the life-times of the
1261
+ % two triples overlap.
1262
+ %
1263
+ % The duplicates marks are used to reduce the administrative load
1264
+ % of avoiding duplicate answers. Normally, the duplicates are
1265
+ % marked using a background thread that is started on the first
1266
+ % query that produces a substantial amount of duplicates.
1267
+
1268
+ :- public
1269
+ rdf_update_duplicates_thread/0.
1270
+
1271
+ %! rdf_update_duplicates_thread
1272
+ %
1273
+ % Start a thread to initialize the duplicate administration.
1274
+
1275
+ rdf_update_duplicates_thread :-
1276
+ thread_create(rdf_update_duplicates, _,
1277
+ [ detached(true),
1278
+ alias('__rdf_duplicate_detecter')
1279
+ ]).
1280
+
1281
+ %! rdf_update_duplicates is det.
1282
+ %
1283
+ % Update the duplicate administration. If this administration is
1284
+ % up-to-date, each triples that _may_ have a duplicate is flagged.
1285
+ % The predicate rdf/3 uses this administration to speedup checking
1286
+ % for duplicate answers.
1287
+ %
1288
+ % This predicate is normally executed from a background thread
1289
+ % named =__rdf_duplicate_detecter= which is created when a query
1290
+ % discovers that checking for duplicates becomes too expensive.
1291
+
1292
+
1293
+ /*******************************
1294
+ * QUICK BINARY LOAD/SAVE *
1295
+ *******************************/
1296
+
1297
+ %! rdf_save_db(+File) is det.
1298
+ %! rdf_save_db(+File, +Graph) is det.
1299
+ %
1300
+ % Save triples into File in a quick-to-load binary format. If Graph
1301
+ % is supplied only triples flagged to originate from that database
1302
+ % are added. Files created this way can be loaded using
1303
+ % rdf_load_db/1.
1304
+
1305
+ :- create_prolog_flag(rdf_triple_format, 3, [type(integer)]).
1306
+
1307
+ rdf_save_db(File) :-
1308
+ current_prolog_flag(rdf_triple_format, Version),
1309
+ setup_call_cleanup(
1310
+ open(File, write, Out, [type(binary)]),
1311
+ ( set_stream(Out, record_position(false)),
1312
+ rdf_save_db_(Out, _, Version)
1313
+ ),
1314
+ close(Out)).
1315
+
1316
+
1317
+ rdf_save_db(File, Graph) :-
1318
+ current_prolog_flag(rdf_triple_format, Version),
1319
+ setup_call_cleanup(
1320
+ open(File, write, Out, [type(binary)]),
1321
+ ( set_stream(Out, record_position(false)),
1322
+ rdf_save_db_(Out, Graph, Version)
1323
+ ),
1324
+ close(Out)).
1325
+
1326
+
1327
+ %! rdf_load_db_no_admin(+File, +Id, -Graphs) is det.
1328
+ %
1329
+ % Load triples from a .trp file without updating the source
1330
+ % administration. Id is handled to monitor action. Graphs is
1331
+ % a list of graph-names encountered in File.
1332
+
1333
+ rdf_load_db_no_admin(File, Id, Graphs) :-
1334
+ open(File, read, In, [type(binary)]),
1335
+ set_stream(In, record_position(false)),
1336
+ call_cleanup(rdf_load_db_(In, Id, Graphs), close(In)).
1337
+
1338
+
1339
+ %! check_loaded_cache(+Graph, +Graphs, +Modified) is det.
1340
+ %
1341
+ % Verify the loaded cache file and optionally fix the modification
1342
+ % time (new versions save this along with the snapshot).
1343
+ %
1344
+ % @tbd What to do if there is a cache mismatch? Delete the loaded
1345
+ % graphs and fail?
1346
+
1347
+ check_loaded_cache(DB, [DB], _Modified) :- !.
1348
+ check_loaded_cache(DB, Graphs, _) :-
1349
+ print_message(warning, rdf(inconsistent_cache(DB, Graphs))).
1350
+
1351
+
1352
+ %! rdf_load_db(+File) is det.
1353
+ %
1354
+ % Load triples from a file created using rdf_save_db/2.
1355
+
1356
+ rdf_load_db(File) :-
1357
+ uri_file_name(URL, File),
1358
+ rdf_load_db_no_admin(File, URL, _Graphs).
1359
+
1360
+
1361
+ /*******************************
1362
+ * LOADING RDF *
1363
+ *******************************/
1364
+
1365
+ :- multifile
1366
+ rdf_open_hook/8,
1367
+ rdf_open_decode/4, % +Encoding, +File, -Stream, -Cleanup
1368
+ rdf_load_stream/3, % +Format, +Stream, +Options
1369
+ rdf_file_type/2, % ?Extension, ?Format
1370
+ rdf_storage_encoding/2, % ?Extension, ?Encoding
1371
+ url_protocol/1. % ?Protocol
1372
+
1373
+ %! rdf_load(+FileOrList) is det.
1374
+ %
1375
+ % Same as rdf_load(FileOrList, []). See rdf_load/2.
1376
+
1377
+ %! rdf_load(+FileOrList, :Options) is det.
1378
+ %
1379
+ % Load RDF data. If this predicate is called a second time
1380
+ % for the same file, it is by default treated as a no-op.
1381
+ % See option =if(changed)=.
1382
+ %
1383
+ % Options provides additional processing options.
1384
+ % Defined options are:
1385
+ %
1386
+ % * blank_nodes(+ShareMode)
1387
+ % How to handle equivalent blank nodes. If =share= (default),
1388
+ % equivalent blank nodes are shared in the same resource.
1389
+ %
1390
+ % * base_uri(+URI)
1391
+ % URI that is used for rdf:about="" and other RDF constructs
1392
+ % that are relative to the base uri. Default is the source
1393
+ % URL.
1394
+ %
1395
+ % * concurrent(+Jobs)
1396
+ % If FileOrList is a list of files, process the input files
1397
+ % using Jobs threads concurrently. Default is the minimum
1398
+ % of the number of cores and the number of inputs. Higher
1399
+ % values can be useful when loading inputs from (slow)
1400
+ % network connections. Using 1 (one) does not use
1401
+ % separate worker threads.
1402
+ %
1403
+ % * format(+Format)
1404
+ % Specify the source format explicitly. Normally this is
1405
+ % deduced from the filename extension or the mime-type. The
1406
+ % core library understands the formats xml (RDF/XML) and
1407
+ % triples (internal quick load and cache format). Plugins,
1408
+ % such as library(semweb/turtle) extend the set of recognised
1409
+ % extensions.
1410
+ %
1411
+ % * graph(?Graph)
1412
+ % Named graph in which to load the data. It is *not* allowed
1413
+ % to load two sources into the same named graph. If Graph is
1414
+ % unbound, it is unified to the graph into which the data is
1415
+ % loaded. The default graph is a =|file://|= URL when loading
1416
+ % a file or, if the specification is a URL, its normalized
1417
+ % version without the optional _|#fragment|_.
1418
+ %
1419
+ % * if(Condition)
1420
+ % When to load the file. One of =true=, =changed= (default) or
1421
+ % =not_loaded=.
1422
+ %
1423
+ % * modified(-Modified)
1424
+ % Unify Modified with one of =not_modified=, cached(File),
1425
+ % last_modified(Stamp) or =unknown=.
1426
+ %
1427
+ % * cache(Bool)
1428
+ % If =false=, do not use or create a cache file.
1429
+ %
1430
+ % * register_namespaces(Bool)
1431
+ % If =true= (default =false=), register =xmlns= namespace
1432
+ % declarations or Turtle =|@prefix|= prefixes using
1433
+ % rdf_register_prefix/3 if there is no conflict.
1434
+ %
1435
+ % * silent(+Bool)
1436
+ % If =true=, the message reporting completion is printed using
1437
+ % level =silent=. Otherwise the level is =informational=. See
1438
+ % also print_message/2.
1439
+ %
1440
+ % * prefixes(-Prefixes)
1441
+ % Returns the prefixes defined in the source data file as a list
1442
+ % of pairs.
1443
+ %
1444
+ % * multifile(+Boolean)
1445
+ % Indicate that the addressed graph may be populated with
1446
+ % triples from multiple sources. This disables caching and
1447
+ % avoids that an rdf_load/2 call affecting the specified
1448
+ % graph cleans the graph.
1449
+ %
1450
+ % Other options are forwarded to process_rdf/3. By default,
1451
+ % rdf_load/2 only loads RDF/XML from files. It can be extended to
1452
+ % load data from other formats and locations using plugins. The
1453
+ % full set of plugins relevant to support different formats and
1454
+ % locations is below:
1455
+ %
1456
+ % ==
1457
+ % :- use_module(library(semweb/turtle)). % Turtle and TriG
1458
+ % :- use_module(library(semweb/rdf_ntriples)).
1459
+ % :- use_module(library(semweb/rdf_zlib_plugin)).
1460
+ % :- use_module(library(semweb/rdf_http_plugin)).
1461
+ % :- use_module(library(http/http_ssl_plugin)).
1462
+ % ==
1463
+ %
1464
+ % @see rdf_db:rdf_open_hook/3, library(semweb/rdf_persistency) and
1465
+ % library(semweb/rdf_cache)
1466
+
1467
+ :- dynamic
1468
+ rdf_loading/3. % Graph, Queue, Thread
1469
+
1470
+ rdf_load(Spec) :-
1471
+ rdf_load(Spec, []).
1472
+
1473
+ :- if(\+current_predicate(concurrent/3)).
1474
+ concurrent(_, Goals, _) :-
1475
+ forall(member(G, Goals), call(G)).
1476
+ :- endif.
1477
+
1478
+ % Note that we kill atom garbage collection. This improves performance
1479
+ % with about 15% loading the LUBM Univ_50 benchmark.
1480
+
1481
+ rdf_load(Spec, M:Options) :-
1482
+ must_be(list, Options),
1483
+ current_prolog_flag(agc_margin, Old),
1484
+ setup_call_cleanup(
1485
+ set_prolog_flag(agc_margin, 0),
1486
+ rdf_load_noagc(Spec, M, Options),
1487
+ set_prolog_flag(agc_margin, Old)).
1488
+
1489
+ rdf_load_noagc(List, M, Options) :-
1490
+ is_list(List),
1491
+ !,
1492
+ flatten(List, Inputs), % Compatibility: allow nested lists
1493
+ maplist(must_be(ground), Inputs),
1494
+ length(Inputs, Count),
1495
+ load_jobs(Count, Jobs, Options),
1496
+ ( Jobs =:= 1
1497
+ -> forall(member(Spec, Inputs),
1498
+ rdf_load_one(Spec, M, Options))
1499
+ ; maplist(load_goal(Options, M), Inputs, Goals),
1500
+ concurrent(Jobs, Goals, [])
1501
+ ).
1502
+ rdf_load_noagc(One, M, Options) :-
1503
+ must_be(ground, One),
1504
+ rdf_load_one(One, M, Options).
1505
+
1506
+ load_goal(Options, M, Spec, rdf_load_one(Spec, M, Options)).
1507
+
1508
+ load_jobs(_, Jobs, Options) :-
1509
+ option(concurrent(Jobs), Options),
1510
+ !,
1511
+ must_be(positive_integer, Jobs).
1512
+ load_jobs(Count, Jobs, _) :-
1513
+ current_prolog_flag(cpu_count, CPUs),
1514
+ CPUs > 0,
1515
+ !,
1516
+ Jobs is max(1, min(CPUs, Count)).
1517
+ load_jobs(_, 1, _).
1518
+
1519
+
1520
+ rdf_load_one(Spec, M, Options) :-
1521
+ source_url(Spec, Protocol, SourceURL),
1522
+ load_graph(SourceURL, Graph, Options),
1523
+ setup_call_cleanup(
1524
+ with_mutex(rdf_load_file,
1525
+ rdf_start_load(SourceURL, Loading)),
1526
+ rdf_load_file(Loading, Spec, SourceURL, Protocol,
1527
+ Graph, M, Options),
1528
+ rdf_end_load(Loading)).
1529
+
1530
+ %! rdf_start_load(+SourceURL, -WhatToDo) is det.
1531
+ %! rdf_end_load(+WhatToDo) is det.
1532
+ %! rdf_load_file(+WhatToDo, +Spec, +SourceURL, +Protocol, +Graph,
1533
+ %! +Module, +Options) is det.
1534
+ %
1535
+ % Of these three predicates, rdf_load_file/7 does the real work.
1536
+ % The others deal with the possibility that the graph is being
1537
+ % loaded by another thread. In that case, we wait for the other
1538
+ % thread to complete the work.
1539
+ %
1540
+ % @tbd What if both threads disagree on what is loaded into the
1541
+ % graph?
1542
+ % @see Code is modelled closely after how concurrent loading
1543
+ % is handled in SWI-Prolog's boot/init.pl
1544
+
1545
+ rdf_start_load(SourceURL, queue(Queue)) :-
1546
+ rdf_loading(SourceURL, Queue, LoadThread),
1547
+ \+ thread_self(LoadThread),
1548
+ !,
1549
+ debug(rdf(load), '~p is being loaded by thread ~w; waiting ...',
1550
+ [ SourceURL, LoadThread]).
1551
+ rdf_start_load(SourceURL, Ref) :-
1552
+ thread_self(Me),
1553
+ message_queue_create(Queue),
1554
+ assertz(rdf_loading(SourceURL, Queue, Me), Ref).
1555
+
1556
+ rdf_end_load(queue(_)) :- !.
1557
+ rdf_end_load(Ref) :-
1558
+ clause(rdf_loading(_, Queue, _), _, Ref),
1559
+ erase(Ref),
1560
+ thread_send_message(Queue, done),
1561
+ message_queue_destroy(Queue).
1562
+
1563
+ rdf_load_file(queue(Queue), _Spec, _SourceURL, _Protocol, _Graph, _M, _Options) :-
1564
+ !,
1565
+ catch(thread_get_message(Queue, _), _, true).
1566
+ rdf_load_file(_Ref, _Spec, SourceURL, Protocol, Graph, M, Options) :-
1567
+ debug(rdf(load), 'RDF: Loading ~q into ~q', [SourceURL, Graph]),
1568
+ statistics(cputime, T0),
1569
+ rdf_open_input(SourceURL, Protocol, Graph,
1570
+ In, Cleanup, Modified, Format, Options),
1571
+ supported_format(Format, Cleanup),
1572
+ return_modified(Modified, Options),
1573
+ ( Modified == not_modified
1574
+ -> Action = none
1575
+ ; Modified = cached(CacheFile)
1576
+ -> do_unload(Graph),
1577
+ catch(rdf_load_db_no_admin(CacheFile, cache(Graph), Graphs), _, fail),
1578
+ check_loaded_cache(Graph, Graphs, Modified),
1579
+ Action = load
1580
+ ; option(base_uri(BaseURI), Options, Graph),
1581
+ ( var(BaseURI)
1582
+ -> BaseURI = SourceURL
1583
+ ; true
1584
+ ),
1585
+ once(phrase(derived_options(Options, NSList), Extra)),
1586
+ merge_options([ base_uri(BaseURI),
1587
+ graph(Graph),
1588
+ format(Format)
1589
+ | Extra
1590
+ ], Options, RDFOptions),
1591
+ ( option(multifile(true), Options)
1592
+ -> true
1593
+ ; do_unload(Graph)
1594
+ ),
1595
+ graph_modified(Modified, ModifiedStamp),
1596
+ rdf_set_graph_source(Graph, SourceURL, ModifiedStamp),
1597
+ call_cleanup(rdf_load_stream(Format, In, M:RDFOptions),
1598
+ Cleanup),
1599
+ save_cache(Graph, SourceURL, Options),
1600
+ register_file_prefixes(NSList),
1601
+ format_action(Format, Action)
1602
+ ),
1603
+ rdf_statistics_(triples(Graph, Triples)),
1604
+ report_loaded(Action, SourceURL, Graph, Triples, T0, Options).
1605
+
1606
+ supported_format(Format, _Cleanup) :-
1607
+ rdf_file_type(_, Format),
1608
+ !.
1609
+ supported_format(Format, Cleanup) :-
1610
+ call(Cleanup),
1611
+ existence_error(rdf_format_plugin, Format).
1612
+
1613
+ format_action(triples, load) :- !.
1614
+ format_action(_, parsed).
1615
+
1616
+ save_cache(Graph, SourceURL, Options) :-
1617
+ option(cache(true), Options, true),
1618
+ rdf_cache_file(SourceURL, write, CacheFile),
1619
+ !,
1620
+ catch(save_cache(Graph, CacheFile), E,
1621
+ print_message(warning, E)).
1622
+ save_cache(_, _, _).
1623
+
1624
+ derived_options([], _) -->
1625
+ [].
1626
+ derived_options([H|T], NSList) -->
1627
+ ( { H == register_namespaces(true)
1628
+ ; H == (register_namespaces = true)
1629
+ }
1630
+ -> [ namespaces(NSList) ]
1631
+ ; []
1632
+ ),
1633
+ derived_options(T, NSList).
1634
+
1635
+ graph_modified(last_modified(Stamp), Stamp).
1636
+ graph_modified(unknown, Stamp) :-
1637
+ get_time(Stamp).
1638
+
1639
+ return_modified(Modified, Options) :-
1640
+ option(modified(M0), Options),
1641
+ !,
1642
+ M0 = Modified.
1643
+ return_modified(_, _).
1644
+
1645
+
1646
+ /*******************************
1647
+ * INPUT HANDLING *
1648
+ *******************************/
1649
+
1650
+ /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1651
+ This section deals with pluggable input sources. The task of the input
1652
+ layer is
1653
+
1654
+ * Decide on the graph-name
1655
+ * Decide on the source-location
1656
+ * Decide whether loading is needed (if-modified)
1657
+ * Decide on the serialization in the input
1658
+
1659
+ The protocol must ensure minimal overhead, in particular for network
1660
+ protocols. E.g. for HTTP we want to make a single call on the server and
1661
+ use If-modified-since to verify that we need not reloading this file.
1662
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1663
+
1664
+ %! rdf_open_input(+SourceURL, +Protocol, +Graph,
1665
+ %! -Stream, -Cleanup, -Modified, -Format, +Options)
1666
+ %
1667
+ % Open an input source.
1668
+ %
1669
+ % Options processed:
1670
+ %
1671
+ % * graph(Graph)
1672
+ % * db(Graph)
1673
+ % * if(Condition)
1674
+ % * cache(Cache)
1675
+ % * format(Format)
1676
+ %
1677
+ % @param Modified is one of =not_modified=, last_modified(Time),
1678
+ % cached(CacheFile) or =unknown=
1679
+
1680
+ rdf_open_input(SourceURL, Protocol, Graph,
1681
+ Stream, Cleanup, Modified, Format, Options) :-
1682
+ ( option(multifile(true), Options)
1683
+ -> true
1684
+ ; option(if(If), Options, changed),
1685
+ ( If == true
1686
+ -> true
1687
+ ; rdf_graph_source_(Graph, SourceURL, HaveModified)
1688
+ -> true
1689
+ ; option(cache(true), Options, true),
1690
+ rdf_cache_file(SourceURL, read, CacheFile)
1691
+ -> time_file(CacheFile, HaveModified)
1692
+ ; true
1693
+ )
1694
+ ),
1695
+ option(format(Format), Options, _),
1696
+ open_input_if_modified(Protocol, SourceURL, HaveModified,
1697
+ Stream, Cleanup, Modified0, Format, Options),
1698
+ ( Modified0 == not_modified
1699
+ -> ( nonvar(CacheFile)
1700
+ -> Modified = cached(CacheFile)
1701
+ ; Modified = not_modified
1702
+ )
1703
+ ; Modified = Modified0
1704
+ ).
1705
+
1706
+
1707
+ %! source_url(+Spec, -Class, -SourceURL) is det.
1708
+ %
1709
+ % Determine class and url of the source. Class is one of
1710
+ %
1711
+ % * stream(Stream)
1712
+ % * file
1713
+ % * a url-protocol (e.g., =http=)
1714
+
1715
+ source_url(stream(In), stream(In), SourceURL) :-
1716
+ !,
1717
+ ( stream_property(In, file_name(File))
1718
+ -> to_url(File, SourceURL)
1719
+ ; gensym('stream://', SourceURL)
1720
+ ).
1721
+ source_url(Stream, Class, SourceURL) :-
1722
+ is_stream(Stream),
1723
+ !,
1724
+ source_url(stream(Stream), Class, SourceURL).
1725
+ source_url(Spec, Protocol, SourceURL) :-
1726
+ compound(Spec),
1727
+ !,
1728
+ source_file(Spec, Protocol, SourceURL).
1729
+ source_url(FileURL, Protocol, SourceURL) :- % or return FileURL?
1730
+ uri_file_name(FileURL, File),
1731
+ !,
1732
+ source_file(File, Protocol, SourceURL).
1733
+ source_url(SourceURL0, Protocol, SourceURL) :-
1734
+ is_url(SourceURL0, Protocol, SourceURL),
1735
+ !.
1736
+ source_url(File, Protocol, SourceURL) :-
1737
+ source_file(File, Protocol, SourceURL).
1738
+
1739
+ source_file(Spec, file(SExt), SourceURL) :-
1740
+ findall(Ext, valid_extension(Ext), Exts),
1741
+ absolute_file_name(Spec, File, [access(read), extensions([''|Exts])]),
1742
+ storage_extension(_Plain, SExt, File),
1743
+ uri_file_name(SourceURL, File).
1744
+
1745
+ to_url(URL, URL) :-
1746
+ uri_is_global(URL),
1747
+ !.
1748
+ to_url(File, URL) :-
1749
+ absolute_file_name(File, Path),
1750
+ uri_file_name(URL, Path).
1751
+
1752
+ storage_extension(Plain, SExt, File) :-
1753
+ file_name_extension(Plain, SExt, File),
1754
+ SExt \== '',
1755
+ rdf_storage_encoding(SExt, _),
1756
+ !.
1757
+ storage_extension(File, '', File).
1758
+
1759
+ %! load_graph(+SourceURL, -Graph, +Options) is det.
1760
+ %
1761
+ % Graph is the graph into which we load the data. Tries these
1762
+ % options:
1763
+ %
1764
+ % 1. The graph(Graph) option
1765
+ % 2. The db(Graph) option (backward compatibility)
1766
+ % 3. The base_uri(BaseURI) option
1767
+ % 4. The source URL
1768
+
1769
+ load_graph(_Source, Graph, Options) :-
1770
+ option(multifile(true), Options),
1771
+ !,
1772
+ ( ( option(graph(Graph), Options)
1773
+ -> true
1774
+ ; option(db(Graph), Options)
1775
+ ),
1776
+ ground(Graph)
1777
+ -> true
1778
+ ; throw(error(existence_error(option, graph),
1779
+ context(_, "rdf_load/2: using multifile requires graph")))
1780
+ ).
1781
+ load_graph(Source, Graph, Options) :-
1782
+ ( option(graph(Graph), Options)
1783
+ ; option(db(Graph), Options)
1784
+ ),
1785
+ !,
1786
+ load_graph2(Source, Graph, Options).
1787
+ load_graph(Source, Graph, Options) :-
1788
+ load_graph2(Source, Graph, Options).
1789
+
1790
+ load_graph2(_, Graph, _) :-
1791
+ ground(Graph),
1792
+ !.
1793
+ load_graph2(_Source, Graph, Options) :-
1794
+ option(base_uri(Graph), Options),
1795
+ Graph \== [],
1796
+ ground(Graph),
1797
+ !.
1798
+ load_graph2(Source, Graph, _) :-
1799
+ load_graph(Source, Graph).
1800
+
1801
+ load_graph(SourceURL, BaseURI) :-
1802
+ file_name_extension(BaseURI, Ext, SourceURL),
1803
+ rdf_storage_encoding(Ext, _),
1804
+ !.
1805
+ load_graph(SourceURL, SourceURL).
1806
+
1807
+
1808
+ open_input_if_modified(stream(In), SourceURL, _, In, true,
1809
+ unknown, Format, _) :-
1810
+ !,
1811
+ ( var(Format)
1812
+ -> guess_format(SourceURL, Format)
1813
+ ; true
1814
+ ).
1815
+ open_input_if_modified(file(SExt), SourceURL, HaveModified, Stream, Cleanup,
1816
+ Modified, Format, _) :-
1817
+ !,
1818
+ uri_file_name(SourceURL, File),
1819
+ ( SExt == '' -> Plain = File; file_name_extension(Plain, SExt, File)),
1820
+ time_file(File, LastModified),
1821
+ ( nonvar(HaveModified),
1822
+ HaveModified >= LastModified
1823
+ -> Modified = not_modified,
1824
+ Cleanup = true
1825
+ ; storage_open(SExt, File, Stream, Cleanup),
1826
+ Modified = last_modified(LastModified),
1827
+ ( var(Format)
1828
+ -> guess_format(Plain, Format)
1829
+ ; true
1830
+ )
1831
+ ).
1832
+ open_input_if_modified(file, SourceURL, HaveModified, Stream, Cleanup,
1833
+ Modified, Format, Options) :-
1834
+ !,
1835
+ open_input_if_modified(file(''), SourceURL, HaveModified,
1836
+ Stream, Cleanup,
1837
+ Modified, Format, Options).
1838
+ open_input_if_modified(Protocol, SourceURL, HaveModified, Stream, Cleanup,
1839
+ Modified, Format, Options) :-
1840
+ rdf_open_hook(Protocol, SourceURL, HaveModified, Stream, Cleanup,
1841
+ Modified, Format, Options).
1842
+
1843
+ guess_format(File, Format) :-
1844
+ file_name_extension(_, Ext, File),
1845
+ ( rdf_file_type(Ext, Format)
1846
+ -> true
1847
+ ; Format = xml,
1848
+ print_message(warning, rdf(guess_format(Ext)))
1849
+ ).
1850
+
1851
+ %! storage_open(+Extension, +File, -Stream, -Cleanup)
1852
+ %
1853
+ % Open the low-level storage. Note that the file is opened as
1854
+ % binary. This is the same as for HTTP resources. The correct
1855
+ % encoding will be set by the XML parser or the Turtle parser.
1856
+
1857
+ storage_open('', File, Stream, close(Stream)) :-
1858
+ !,
1859
+ open(File, read, Stream, [type(binary)]).
1860
+ storage_open(Ext, File, Stream, Cleanup) :-
1861
+ rdf_storage_encoding(Ext, Encoding),
1862
+ rdf_open_decode(Encoding, File, Stream, Cleanup).
1863
+
1864
+ valid_extension(Ext) :-
1865
+ rdf_file_type(Ext, _).
1866
+ valid_extension(Ext) :-
1867
+ rdf_storage_encoding(Ext, _).
1868
+
1869
+ %! is_url(@Term, -Scheme, -URL) is semidet.
1870
+ %
1871
+ % True if Term is an atom denoting URL of the given Scheme. URL is
1872
+ % normalized (see uri_normalized/2) and a possible fragment
1873
+ % identifier (#fragment) is removed. This predicate only succeeds
1874
+ % if the scheme is registered using the multifile hook
1875
+ % url_protocol/1.
1876
+
1877
+ is_url(URL, Scheme, FetchURL) :-
1878
+ atom(URL),
1879
+ uri_is_global(URL),
1880
+ uri_normalized(URL, URL1), % case normalization
1881
+ uri_components(URL1, Components),
1882
+ uri_data(scheme, Components, Scheme0),
1883
+ url_protocol(Scheme0),
1884
+ !,
1885
+ Scheme = Scheme0,
1886
+ uri_data(fragment, Components, _, Components1),
1887
+ uri_components(FetchURL, Components1).
1888
+
1889
+ url_protocol(file). % built-in
1890
+
1891
+ %! rdf_file_type(+Extension, -Format) is semidet.
1892
+ %
1893
+ % True if Format is the format belonging to the given file
1894
+ % extension. This predicate is multifile and can thus be extended
1895
+ % by plugins.
1896
+
1897
+ rdf_file_type(xml, xml).
1898
+ rdf_file_type(rdf, xml).
1899
+ rdf_file_type(rdfs, xml).
1900
+ rdf_file_type(owl, xml).
1901
+ rdf_file_type(htm, xhtml).
1902
+ rdf_file_type(html, xhtml).
1903
+ rdf_file_type(xhtml, xhtml).
1904
+ rdf_file_type(trp, triples).
1905
+
1906
+
1907
+ %! rdf_file_encoding(+Extension, -Format) is semidet.
1908
+ %
1909
+ % True if Format describes the storage encoding of file.
1910
+
1911
+ rdf_storage_encoding('', plain).
1912
+
1913
+
1914
+ %! rdf_load_stream(+Format, +Stream, :Options)
1915
+ %
1916
+ % Load RDF data from Stream.
1917
+ %
1918
+ % @tbd Handle mime-types?
1919
+
1920
+ rdf_load_stream(xml, Stream, Options) :-
1921
+ !,
1922
+ graph(Options, Graph),
1923
+ rdf_transaction(load_stream(Stream, Options),
1924
+ parse(Graph)).
1925
+ rdf_load_stream(xhtml, Stream, M:Options) :-
1926
+ !,
1927
+ graph(Options, Graph),
1928
+ rdf_transaction(load_stream(Stream, M:[embedded(true)|Options]),
1929
+ parse(Graph)).
1930
+ rdf_load_stream(triples, Stream, Options) :-
1931
+ !,
1932
+ graph(Options, Graph),
1933
+ rdf_load_db_(Stream, Graph, _Graphs).
1934
+
1935
+ load_stream(Stream, M:Options) :-
1936
+ process_rdf(Stream, assert_triples, M:Options),
1937
+ option(graph(Graph), Options),
1938
+ rdf_graph_clear_modified_(Graph).
1939
+
1940
+
1941
+ %! report_loaded(+Action, +Source, +DB, +Triples, +StartCPU, +Options)
1942
+
1943
+ report_loaded(none, _, _, _, _, _) :- !.
1944
+ report_loaded(Action, Source, DB, Triples, T0, Options) :-
1945
+ statistics(cputime, T1),
1946
+ Time is T1 - T0,
1947
+ ( option(silent(true), Options)
1948
+ -> Level = silent
1949
+ ; Level = informational
1950
+ ),
1951
+ print_message(Level,
1952
+ rdf(loaded(Action, Source, DB, Triples, Time))).
1953
+
1954
+
1955
+ %! rdf_unload(+Source) is det.
1956
+ %
1957
+ % Identify the graph loaded from Source and use rdf_unload_graph/1
1958
+ % to erase this graph.
1959
+ %
1960
+ % @deprecated For compatibility, this predicate also accepts a
1961
+ % graph name instead of a source specification.
1962
+ % Please update your code to use
1963
+ % rdf_unload_graph/1.
1964
+
1965
+ rdf_unload(Spec) :-
1966
+ source_url(Spec, _Protocol, SourceURL),
1967
+ rdf_graph_source_(Graph, SourceURL, _),
1968
+ !,
1969
+ rdf_unload_graph(Graph).
1970
+ rdf_unload(Graph) :-
1971
+ atom(Graph),
1972
+ rdf_graph(Graph),
1973
+ !,
1974
+ warn_deprecated_unload(Graph),
1975
+ rdf_unload_graph(Graph).
1976
+ rdf_unload(_).
1977
+
1978
+ :- dynamic
1979
+ warned/0.
1980
+
1981
+ warn_deprecated_unload(_) :-
1982
+ warned,
1983
+ !.
1984
+ warn_deprecated_unload(Graph) :-
1985
+ assertz(warned),
1986
+ print_message(warning, rdf(deprecated(rdf_unload(Graph)))).
1987
+
1988
+
1989
+ %! rdf_unload_graph(+Graph) is det.
1990
+ %
1991
+ % Remove Graph from the RDF store. Succeeds silently if the named
1992
+ % graph does not exist.
1993
+
1994
+ rdf_unload_graph(Graph) :-
1995
+ must_be(atom, Graph),
1996
+ ( rdf_graph(Graph)
1997
+ -> rdf_transaction(do_unload(Graph), unload(Graph))
1998
+ ; true
1999
+ ).
2000
+
2001
+ do_unload(Graph) :-
2002
+ ( rdf_graph_(Graph, Triples),
2003
+ Triples > 0
2004
+ -> rdf_retractall(_,_,_,Graph)
2005
+ ; true
2006
+ ),
2007
+ rdf_destroy_graph(Graph).
2008
+
2009
+ /*******************************
2010
+ * GRAPH QUERIES *
2011
+ *******************************/
2012
+
2013
+ %! rdf_create_graph(+Graph) is det.
2014
+ %
2015
+ % Create an RDF graph without triples. Succeeds silently if the
2016
+ % graph already exists.
2017
+
2018
+
2019
+ %! rdf_graph(?Graph) is nondet.
2020
+ %
2021
+ % True when Graph is an existing graph.
2022
+
2023
+ rdf_graph(Graph) :-
2024
+ rdf_graph_(Graph, _Triples).
2025
+
2026
+ %! rdf_source(?Graph, ?SourceURL) is nondet.
2027
+ %
2028
+ % True if named Graph is loaded from SourceURL.
2029
+ %
2030
+ % @deprecated Use rdf_graph_property(Graph, source(SourceURL)).
2031
+
2032
+ rdf_source(Graph, SourceURL) :-
2033
+ rdf_graph(Graph),
2034
+ rdf_graph_source_(Graph, SourceURL, _Modified).
2035
+
2036
+ %! rdf_source(?Source)
2037
+ %
2038
+ % True if Source is a loaded source.
2039
+ %
2040
+ % @deprecated Use rdf_graph/1 or rdf_source/2.
2041
+
2042
+ rdf_source(SourceURL) :-
2043
+ rdf_source(_Graph, SourceURL).
2044
+
2045
+ %! rdf_make
2046
+ %
2047
+ % Reload all loaded files that have been modified since the last
2048
+ % time they were loaded.
2049
+
2050
+ rdf_make :-
2051
+ findall(Source-Graph, modified_graph(Source, Graph), Modified),
2052
+ forall(member(Source-Graph, Modified),
2053
+ catch(rdf_load(Source, [graph(Graph), if(changed)]), E,
2054
+ print_message(error, E))).
2055
+
2056
+ modified_graph(SourceURL, Graph) :-
2057
+ rdf_graph(Graph),
2058
+ rdf_graph_source_(Graph, SourceURL, Modified),
2059
+ \+ sub_atom(SourceURL, 0, _, _, 'stream://'),
2060
+ Modified > 0.
2061
+
2062
+ %! rdf_graph_property(?Graph, ?Property) is nondet.
2063
+ %
2064
+ % True when Property is a property of Graph. Defined properties
2065
+ % are:
2066
+ %
2067
+ % * hash(Hash)
2068
+ % Hash is the (MD5-)hash for the content of Graph.
2069
+ % * modified(Boolean)
2070
+ % True if the graph is modified since it was loaded or
2071
+ % rdf_set_graph/2 was called with modified(false).
2072
+ % * source(Source)
2073
+ % The graph is loaded from the Source (a URL)
2074
+ % * source_last_modified(?Time)
2075
+ % Time is the last-modified timestamp of Source at the moment
2076
+ % the graph was loaded from Source.
2077
+ % * triples(Count)
2078
+ % True when Count is the number of triples in Graph.
2079
+ %
2080
+ % Additional graph properties can be added by defining rules for
2081
+ % the multifile predicate property_of_graph/2. Currently, the
2082
+ % following extensions are defined:
2083
+ %
2084
+ % - library(semweb/rdf_persistency)
2085
+ % - persistent(Boolean)
2086
+ % Boolean is =true= if the graph is persistent.
2087
+
2088
+ rdf_graph_property(Graph, Property) :-
2089
+ rdf_graph(Graph),
2090
+ property_of_graph(Property, Graph).
2091
+
2092
+ :- multifile
2093
+ property_of_graph/2.
2094
+
2095
+ property_of_graph(hash(Hash), Graph) :-
2096
+ rdf_md5(Graph, Hash).
2097
+ property_of_graph(modified(Boolean), Graph) :-
2098
+ rdf_graph_modified_(Graph, Boolean, _).
2099
+ property_of_graph(source(URL), Graph) :-
2100
+ rdf_graph_source_(Graph, URL, _).
2101
+ property_of_graph(source_last_modified(Time), Graph) :-
2102
+ rdf_graph_source_(Graph, _, Time),
2103
+ Time > 0.0.
2104
+ property_of_graph(triples(Count), Graph) :-
2105
+ rdf_graph_(Graph, Count).
2106
+
2107
+ %! rdf_set_graph(+Graph, +Property) is det.
2108
+ %
2109
+ % Set properties of Graph. Defined properties are:
2110
+ %
2111
+ % * modified(false)
2112
+ % Set the modified state of Graph to false.
2113
+
2114
+ rdf_set_graph(Graph, modified(Modified)) :-
2115
+ must_be(oneof([false]), Modified),
2116
+ rdf_graph_clear_modified_(Graph).
2117
+
2118
+
2119
+ %! save_cache(+DB, +Cache) is det.
2120
+ %
2121
+ % Save triples belonging to DB in the file Cache.
2122
+
2123
+ save_cache(DB, Cache) :-
2124
+ current_prolog_flag(rdf_triple_format, Version),
2125
+ setup_call_cleanup(
2126
+ catch(open(Cache, write, CacheStream, [type(binary)]), _, fail),
2127
+ rdf_save_db_(CacheStream, DB, Version),
2128
+ close(CacheStream)).
2129
+
2130
+ %! assert_triples(+Triples, +Source)
2131
+ %
2132
+ % Assert a list of triples into the database. For security
2133
+ % reasons we check we aren't inserting anything but nice RDF
2134
+ % triples.
2135
+
2136
+ assert_triples([], _).
2137
+ assert_triples([rdf(S,P,O)|T], DB) :-
2138
+ !,
2139
+ rdf_assert(S, P, O, DB),
2140
+ assert_triples(T, DB).
2141
+ assert_triples([H|_], _) :-
2142
+ throw(error(type_error(rdf_triple, H), _)).
2143
+
2144
+
2145
+ /*******************************
2146
+ * RESET *
2147
+ *******************************/
2148
+
2149
+ %! rdf_reset_db
2150
+ %
2151
+ % Remove all triples from the RDF database and reset all its
2152
+ % statistics.
2153
+ %
2154
+ % @bug This predicate checks for active queries, but this check is
2155
+ % not properly synchronized and therefore the use of this
2156
+ % predicate is unsafe in multi-threaded contexts. It is
2157
+ % mainly used to run functionality tests that need to
2158
+ % start with an empty database.
2159
+
2160
+ rdf_reset_db :-
2161
+ reset_gensym('_:genid'),
2162
+ rdf_reset_db_.
2163
+
2164
+
2165
+ /*******************************
2166
+ * SAVE RDF *
2167
+ *******************************/
2168
+
2169
+ %! rdf_save(+Out) is det.
2170
+ %
2171
+ % Same as rdf_save(Out, []). See rdf_save/2 for details.
2172
+
2173
+ %! rdf_save(+Out, :Options) is det.
2174
+ %
2175
+ % Write RDF data as RDF/XML. Options is a list of one or more of
2176
+ % the following options:
2177
+ %
2178
+ % * graph(+Graph)
2179
+ % Save only triples associated to the given named Graph.
2180
+ %
2181
+ % * anon(Bool)
2182
+ % If =false= (default =true=) do not save blank nodes that do
2183
+ % not appear (indirectly) as object of a named resource.
2184
+ %
2185
+ % * base_uri(URI)
2186
+ % BaseURI used. If present, all URIs that can be
2187
+ % represented relative to this base are written using
2188
+ % their shorthand. See also =write_xml_base= option.
2189
+ %
2190
+ % * convert_typed_literal(:Convertor)
2191
+ % Call Convertor(-Type, -Content, +RDFObject), providing
2192
+ % the opposite for the convert_typed_literal option of
2193
+ % the RDF parser.
2194
+ %
2195
+ % * document_language(+Lang)
2196
+ % Initial =|xml:lang|= saved with rdf:RDF element.
2197
+ %
2198
+ % * encoding(Encoding)
2199
+ % Encoding for the output. Either utf8 or iso_latin_1.
2200
+ %
2201
+ % * inline(+Bool)
2202
+ % If =true= (default =false=), inline resources when
2203
+ % encountered for the first time. Normally, only bnodes
2204
+ % are handled this way.
2205
+ %
2206
+ % * namespaces(+List)
2207
+ % Explicitly specify saved namespace declarations. See
2208
+ % rdf_save_header/2 option namespaces for details.
2209
+ %
2210
+ % * sorted(+Boolean)
2211
+ % If =true= (default =false=), emit subjects sorted on
2212
+ % the full URI. Useful to make file comparison easier.
2213
+ %
2214
+ % * write_xml_base(Bool)
2215
+ % If =false=, do _not_ include the =|xml:base|=
2216
+ % declaration that is written normally when using the
2217
+ % =base_uri= option.
2218
+ %
2219
+ % * xml_attributes(+Bool)
2220
+ % If =false= (default =true=), never use xml attributes to
2221
+ % save plain literal attributes, i.e., always used an XML
2222
+ % element as in =|<name>Joe</name>|=.
2223
+ %
2224
+ % @param Out Location to save the data. This can also be a
2225
+ % file-url (=|file://path|=) or a stream wrapped
2226
+ % in a term stream(Out).
2227
+ % @see rdf_save_db/1
2228
+
2229
+ :- thread_local
2230
+ named_anon/2, % +Resource, -Id
2231
+ inlined/1. % +Resource
2232
+
2233
+ rdf_save(File) :-
2234
+ rdf_save2(File, []).
2235
+
2236
+ rdf_save(Spec, M:Options0) :-
2237
+ is_list(Options0),
2238
+ !,
2239
+ meta_options(save_meta_option, M:Options0, Options),
2240
+ to_file(Spec, File),
2241
+ rdf_save2(File, Options).
2242
+ rdf_save(Spec, _:DB) :-
2243
+ atom(DB), % backward compatibility
2244
+ !,
2245
+ to_file(Spec, File),
2246
+ rdf_save2(File, [graph(DB)]).
2247
+
2248
+ save_meta_option(convert_typed_literal).
2249
+
2250
+ to_file(URL, File) :-
2251
+ atom(URL),
2252
+ uri_file_name(URL, File),
2253
+ !.
2254
+ to_file(File, File).
2255
+
2256
+ rdf_save2(File, Options) :-
2257
+ option(encoding(Encoding), Options, utf8),
2258
+ valid_encoding(Encoding),
2259
+ open_output(File, Encoding, Out, Close),
2260
+ flag(rdf_db_saved_subjects, OSavedSubjects, 0),
2261
+ flag(rdf_db_saved_triples, OSavedTriples, 0),
2262
+ call_cleanup(rdf_do_save(Out, Options),
2263
+ Reason,
2264
+ cleanup_save(Reason,
2265
+ File,
2266
+ OSavedSubjects,
2267
+ OSavedTriples,
2268
+ Close)).
2269
+
2270
+ open_output(stream(Out), Encoding, Out, Cleanup) :-
2271
+ !,
2272
+ stream_property(Out, encoding(Old)),
2273
+ ( ( Old == Encoding
2274
+ ; Old == wchar_t % Internal encoding
2275
+ )
2276
+ -> Cleanup = true
2277
+ ; set_stream(Out, encoding(Encoding)),
2278
+ Cleanup = set_stream(Out, encoding(Old))
2279
+ ).
2280
+ open_output(File, Encoding, Out,
2281
+ close(Out)) :-
2282
+ open(File, write, Out, [encoding(Encoding)]).
2283
+
2284
+ valid_encoding(Enc) :-
2285
+ ( xml_encoding_name(Enc, _)
2286
+ -> true
2287
+ ; throw(error(domain_error(encoding, Enc), _))
2288
+ ).
2289
+
2290
+
2291
+ cleanup_save(Reason,
2292
+ File,
2293
+ OSavedSubjects,
2294
+ OSavedTriples,
2295
+ Close) :-
2296
+ call(Close),
2297
+ flag(rdf_db_saved_subjects, SavedSubjects, OSavedSubjects),
2298
+ flag(rdf_db_saved_triples, SavedTriples, OSavedTriples),
2299
+ retractall(named_anon(_, _)),
2300
+ retractall(inlined(_)),
2301
+ ( Reason == exit
2302
+ -> print_message(informational,
2303
+ rdf(saved(File, SavedSubjects, SavedTriples)))
2304
+ ; format(user_error, 'Reason = ~w~n', [Reason])
2305
+ ).
2306
+
2307
+ rdf_do_save(Out, Options0) :-
2308
+ rdf_save_header(Out, Options0, Options),
2309
+ graph(Options, DB),
2310
+ ( option(sorted(true), Options, false)
2311
+ -> ( var(DB)
2312
+ -> setof(Subject, rdf_subject(Subject), Subjects)
2313
+ ; findall(Subject, rdf(Subject, _, _, DB:_), SubjectList),
2314
+ sort(SubjectList, Subjects)
2315
+ ),
2316
+ forall(member(Subject, Subjects),
2317
+ rdf_save_non_anon_subject(Out, Subject, Options))
2318
+ ; forall(rdf_subject_in_graph(Subject, DB),
2319
+ rdf_save_non_anon_subject(Out, Subject, Options))
2320
+ ),
2321
+ rdf_save_footer(Out),
2322
+ !. % dubious cut; without the
2323
+ % cleanup handlers isn't called!?
2324
+
2325
+ %! rdf_subject_in_graph(-Subject, ?DB) is nondet.
2326
+ %
2327
+ % True when Subject is a subject in the graph DB. If DB is unbound,
2328
+ % all subjects are enumerated. Otherwise we have two options:
2329
+ % enumerate all subjects and filter by graph or collect all triples of
2330
+ % the graph and get the unique subjects. The first is attractive if
2331
+ % the graph is big compared to the DB, also because it does not
2332
+ % require memory, the second if the graph is small compared to the DB.
2333
+
2334
+ rdf_subject_in_graph(Subject, DB) :-
2335
+ var(DB),
2336
+ !,
2337
+ rdf_subject(Subject).
2338
+ rdf_subject_in_graph(Subject, DB) :-
2339
+ rdf_statistics(triples(AllTriples)),
2340
+ rdf_graph_property(DB, triples(DBTriples)),
2341
+ DBTriples > AllTriples // 10,
2342
+ !,
2343
+ rdf_resource(Subject),
2344
+ ( rdf(Subject, _, _, DB:_)
2345
+ -> true
2346
+ ).
2347
+ rdf_subject_in_graph(Subject, DB) :-
2348
+ findall(Subject, rdf(Subject, _, _, DB:_), SubjectList),
2349
+ list_to_set(SubjectList, Subjects),
2350
+ member(Subject, Subjects).
2351
+
2352
+
2353
+ graph(Options0, DB) :-
2354
+ strip_module(Options0, _, Options),
2355
+ ( memberchk(graph(DB0), Options)
2356
+ -> DB = DB0
2357
+ ; memberchk(db(DB0), Options)
2358
+ -> DB = DB0
2359
+ ; true % leave unbound
2360
+ ).
2361
+
2362
+
2363
+ %! rdf_save_header(+Fd, +Options)
2364
+ %
2365
+ % Save XML document header, doctype and open the RDF environment.
2366
+ % This predicate also sets up the namespace notation.
2367
+ %
2368
+ % Save an RDF header, with the XML header, DOCTYPE, ENTITY and
2369
+ % opening the rdf:RDF element with appropriate namespace
2370
+ % declarations. It uses the primitives from section 3.5 to
2371
+ % generate the required namespaces and desired short-name. Options
2372
+ % is one of:
2373
+ %
2374
+ % * graph(+URI)
2375
+ % Only search for namespaces used in triples that belong to the
2376
+ % given named graph.
2377
+ %
2378
+ % * namespaces(+List)
2379
+ % Where List is a list of namespace abbreviations. With this
2380
+ % option, the expensive search for all namespaces that may be
2381
+ % used by your data is omitted. The namespaces =rdf= and =rdfs=
2382
+ % are added to the provided List. If a namespace is not
2383
+ % declared, the resource is emitted in non-abbreviated form.
2384
+
2385
+ rdf_save_header(Out, Options) :-
2386
+ rdf_save_header(Out, Options, _).
2387
+
2388
+ rdf_save_header(Out, Options, OptionsOut) :-
2389
+ is_list(Options),
2390
+ !,
2391
+ option(encoding(Enc), Options, utf8),
2392
+ xml_encoding(Enc, Encoding),
2393
+ format(Out, '<?xml version=\'1.0\' encoding=\'~w\'?>~n', [Encoding]),
2394
+ format(Out, '<!DOCTYPE rdf:RDF [', []),
2395
+ header_namespaces(Options, NSIdList),
2396
+ nsmap(NSIdList, NsMap),
2397
+ append(Options, [nsmap(NsMap)], OptionsOut),
2398
+ forall(member(Id=URI, NsMap),
2399
+ ( xml_quote_attribute(URI, NSText0, Enc),
2400
+ xml_escape_parameter_entity(NSText0, NSText),
2401
+ format(Out, '~N <!ENTITY ~w \'~w\'>', [Id, NSText])
2402
+ )),
2403
+ format(Out, '~N]>~n~n', []),
2404
+ format(Out, '<rdf:RDF', []),
2405
+ ( member(Id, NSIdList),
2406
+ format(Out, '~N xmlns:~w="&~w;"~n', [Id, Id]),
2407
+ fail
2408
+ ; true
2409
+ ),
2410
+ ( option(base_uri(Base), Options),
2411
+ option(write_xml_base(true), Options, true)
2412
+ -> xml_quote_attribute(Base, BaseText, Enc),
2413
+ format(Out, '~N xml:base="~w"~n', [BaseText])
2414
+ ; true
2415
+ ),
2416
+ ( memberchk(document_language(Lang), Options)
2417
+ -> format(Out, '~N xml:lang="~w"', [Lang])
2418
+ ; true
2419
+ ),
2420
+ format(Out, '>~n', []).
2421
+ rdf_save_header(Out, FileRef, OptionsOut) :- % compatibility
2422
+ atom(FileRef),
2423
+ rdf_save_header(Out, [graph(FileRef)], OptionsOut).
2424
+
2425
+ xml_encoding(Enc, Encoding) :-
2426
+ ( xml_encoding_name(Enc, Encoding)
2427
+ -> true
2428
+ ; throw(error(domain_error(rdf_encoding, Enc), _))
2429
+ ).
2430
+
2431
+ xml_encoding_name(ascii, 'US-ASCII').
2432
+ xml_encoding_name(iso_latin_1, 'ISO-8859-1').
2433
+ xml_encoding_name(utf8, 'UTF-8').
2434
+
2435
+ %! nsmap(+NSIds, -Map:list(id=uri)) is det.
2436
+ %
2437
+ % Create a namespace-map that is compatible to xml_write/2
2438
+ % for dealing with XML-Literals
2439
+
2440
+ nsmap([], []).
2441
+ nsmap([Id|T0], [Id=URI|T]) :-
2442
+ ns(Id, URI),
2443
+ nsmap(T0, T).
2444
+
2445
+ %! xml_escape_parameter_entity(+In, -Out) is det.
2446
+ %
2447
+ % Escape % as &#37; for entity declarations.
2448
+
2449
+ xml_escape_parameter_entity(In, Out) :-
2450
+ sub_atom(In, _, _, _, '%'),
2451
+ !,
2452
+ atom_codes(In, Codes),
2453
+ phrase(escape_parent(Codes), OutCodes),
2454
+ atom_codes(Out, OutCodes).
2455
+ xml_escape_parameter_entity(In, In).
2456
+
2457
+ escape_parent([]) --> [].
2458
+ escape_parent([H|T]) -->
2459
+ ( { H == 37 }
2460
+ -> "&#37;"
2461
+ ; [H]
2462
+ ),
2463
+ escape_parent(T).
2464
+
2465
+
2466
+ %! header_namespaces(Options, -List)
2467
+ %
2468
+ % Get namespaces we will define as entities
2469
+
2470
+ header_namespaces(Options, List) :-
2471
+ memberchk(namespaces(NSL0), Options),
2472
+ !,
2473
+ sort([rdf,rdfs|NSL0], List).
2474
+ header_namespaces(Options, List) :-
2475
+ graph(Options, DB),
2476
+ used_namespace_entities(List, DB).
2477
+
2478
+ %! rdf_graph_prefixes(?Graph, -List:ord_set) is det.
2479
+ %! rdf_graph_prefixes(?Graph, -List:ord_set, :Options) is det.
2480
+ %
2481
+ % List is a sorted list of prefixes (namepaces) in Graph. Options
2482
+ % defined are:
2483
+ %
2484
+ % * filter(:Filter)
2485
+ % optional Filter argument is used to filter the results. It
2486
+ % is called with 3 additional arguments:
2487
+ %
2488
+ % ==
2489
+ % call(Filter, Where, Prefix, URI)
2490
+ % ==
2491
+ %
2492
+ % The Where argument gives the location of the prefix ans is
2493
+ % one of =subject=, =predicate=, =object= or =type=. The
2494
+ % Prefix argument is the potentially new prefix and URI is
2495
+ % the full URI that is being processed.
2496
+ %
2497
+ % * expand(:Goal)
2498
+ % Hook to generate the graph. Called using
2499
+ %
2500
+ % ==
2501
+ % call(Goal,S,P,O,Graph)
2502
+ % ==
2503
+ %
2504
+ % * min_count(+Count)
2505
+ % Only include prefixes that appear at least N times. Default
2506
+ % is 1. Declared prefixes are always returned if found at
2507
+ % least one time.
2508
+ %
2509
+ % * get_prefix(:GetPrefix)
2510
+ % Predicate to extract the candidate prefix from an IRI. Default
2511
+ % is iri_xml_namespace/2.
2512
+
2513
+
2514
+ :- thread_local
2515
+ graph_prefix/3.
2516
+ :- meta_predicate
2517
+ rdf_graph_prefixes(?, -, :).
2518
+
2519
+ rdf_graph_prefixes(Graph, List) :-
2520
+ rdf_graph_prefixes(Graph, List, []).
2521
+
2522
+ rdf_graph_prefixes(Graph, List, M:QOptions) :-
2523
+ is_list(QOptions),
2524
+ !,
2525
+ meta_options(is_meta, M:QOptions, Options),
2526
+ option(filter(Filter), Options, true),
2527
+ option(expand(Expand), Options, rdf_db),
2528
+ option(min_count(MinCount), Options, 1),
2529
+ option(get_prefix(GetPrefix), Options, iri_xml_namespace),
2530
+ call_cleanup(prefixes(Expand, Graph, Prefixes, Filter, MinCount, GetPrefix),
2531
+ retractall(graph_prefix(_,_,_))),
2532
+ sort(Prefixes, List).
2533
+ rdf_graph_prefixes(Graph, List, M:Filter) :-
2534
+ rdf_graph_prefixes(Graph, List, M:[filter(Filter)]).
2535
+
2536
+ is_meta(filter).
2537
+ is_meta(expand).
2538
+ is_meta(get_prefix).
2539
+
2540
+
2541
+ prefixes(Expand, Graph, Prefixes, Filter, MinCount, GetPrefix) :-
2542
+ ( call(Expand, S, P, O, Graph),
2543
+ add_ns(subject, GetPrefix, Filter, S, MinCount, s(S)),
2544
+ add_ns(predicate, GetPrefix, Filter, P, MinCount, sp(S,P)),
2545
+ add_ns_obj(GetPrefix, Filter, O, MinCount, spo(S,P,O)),
2546
+ fail
2547
+ ; true
2548
+ ),
2549
+ findall(Prefix, graph_prefix(Prefix, MinCount, _), Prefixes).
2550
+
2551
+ add_ns(Where, GetPrefix, Filter, S, MinCount, Context) :-
2552
+ \+ rdf_is_bnode(S),
2553
+ call(GetPrefix, S, Full),
2554
+ Full \== '',
2555
+ !,
2556
+ ( graph_prefix(Full, MinCount, _)
2557
+ -> true
2558
+ ; Filter == true
2559
+ -> add_ns(Full, Context)
2560
+ ; call(Filter, Where, Full, S)
2561
+ -> add_ns(Full, Context)
2562
+ ; true
2563
+ ).
2564
+ add_ns(_, _, _, _, _, _).
2565
+
2566
+ add_ns(Full, Context) :-
2567
+ graph_prefix(Full, _, Contexts),
2568
+ memberchk(Context, Contexts),
2569
+ !.
2570
+ add_ns(Full, Context) :-
2571
+ retract(graph_prefix(Full, C0, Contexts)),
2572
+ !,
2573
+ C1 is C0+1,
2574
+ asserta(graph_prefix(Full, C1, [Context|Contexts])).
2575
+ add_ns(Full, _) :-
2576
+ ns(_, Full),
2577
+ !,
2578
+ asserta(graph_prefix(Full, _, _)).
2579
+ add_ns(Full, Context) :-
2580
+ asserta(graph_prefix(Full, 1, [Context])).
2581
+
2582
+
2583
+ add_ns_obj(GetPrefix, Filter, O, MinCount, Context) :-
2584
+ atom(O),
2585
+ !,
2586
+ add_ns(object, GetPrefix, Filter, O, MinCount, Context).
2587
+ add_ns_obj(GetPrefix, Filter, literal(type(Type, _)), MinCount, _) :-
2588
+ atom(Type),
2589
+ !,
2590
+ add_ns(type, GetPrefix, Filter, Type, MinCount, t(Type)).
2591
+ add_ns_obj(_, _, _, _, _).
2592
+
2593
+
2594
+ %! used_namespace_entities(-List, ?Graph) is det.
2595
+ %
2596
+ % Return the namespace aliases that are actually used in Graph. In
2597
+ % addition, this predicate creates ns<N> aliases for namespaces
2598
+ % used in predicates because RDF/XML cannot write predicates other
2599
+ % than as an XML name.
2600
+
2601
+ used_namespace_entities(List, Graph) :-
2602
+ decl_used_predicate_ns(Graph),
2603
+ used_namespaces(List, Graph).
2604
+
2605
+ used_namespaces(List, DB) :-
2606
+ rdf_graph_prefixes(DB, FullList),
2607
+ ns_abbreviations(FullList, List0),
2608
+ sort([rdf|List0], List).
2609
+
2610
+ ns_abbreviations([], []).
2611
+ ns_abbreviations([H0|T0], [H|T]) :-
2612
+ ns(H, H0),
2613
+ !,
2614
+ ns_abbreviations(T0, T).
2615
+ ns_abbreviations([_|T0], T) :-
2616
+ ns_abbreviations(T0, T).
2617
+
2618
+
2619
+ /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2620
+ For every URL used as a predicate we *MUST* define a namespace as we
2621
+ cannot use names holding /, :, etc. as XML identifiers.
2622
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2623
+
2624
+ :- thread_local
2625
+ predicate_ns/2.
2626
+
2627
+ decl_used_predicate_ns(DB) :-
2628
+ retractall(predicate_ns(_,_)),
2629
+ ( rdf_current_predicate(P, DB),
2630
+ decl_predicate_ns(P),
2631
+ fail
2632
+ ; true
2633
+ ).
2634
+
2635
+ decl_predicate_ns(Pred) :-
2636
+ predicate_ns(Pred, _),
2637
+ !.
2638
+ decl_predicate_ns(Pred) :-
2639
+ rdf_global_id(NS:Local, Pred),
2640
+ xml_name(Local),
2641
+ !,
2642
+ assert(predicate_ns(Pred, NS)).
2643
+ decl_predicate_ns(Pred) :-
2644
+ atom_codes(Pred, Codes),
2645
+ append(NSCodes, LocalCodes, Codes),
2646
+ xml_codes(LocalCodes),
2647
+ !,
2648
+ ( NSCodes \== []
2649
+ -> atom_codes(NS, NSCodes),
2650
+ ( ns(Id, NS)
2651
+ -> assert(predicate_ns(Pred, Id))
2652
+ ; between(1, infinite, N),
2653
+ atom_concat(ns, N, Id),
2654
+ \+ ns(Id, _)
2655
+ -> rdf_register_ns(Id, NS),
2656
+ print_message(informational,
2657
+ rdf(using_namespace(Id, NS)))
2658
+ ),
2659
+ assert(predicate_ns(Pred, Id))
2660
+ ; assert(predicate_ns(Pred, -)) % no namespace used
2661
+ ).
2662
+
2663
+ xml_codes([]).
2664
+ xml_codes([H|T]) :-
2665
+ xml_code(H),
2666
+ xml_codes(T).
2667
+
2668
+ xml_code(X) :-
2669
+ code_type(X, csym),
2670
+ !.
2671
+ xml_code(0'-). % Match 0'-
2672
+
2673
+
2674
+ %! rdf_save_footer(Out:stream) is det.
2675
+ %
2676
+ % Finish XML generation and write the document footer.
2677
+ %
2678
+ % @see rdf_save_header/2, rdf_save_subject/3.
2679
+
2680
+ rdf_save_footer(Out) :-
2681
+ retractall(named_anon(_, _)),
2682
+ retractall(inlined(_)),
2683
+ format(Out, '</rdf:RDF>~n', []).
2684
+
2685
+ %! rdf_save_non_anon_subject(+Out, +Subject, +Options)
2686
+ %
2687
+ % Save an object. Anonymous objects not saved if anon(false)
2688
+ % is present in the Options list.
2689
+
2690
+ rdf_save_non_anon_subject(_Out, Subject, Options) :-
2691
+ rdf_is_bnode(Subject),
2692
+ ( memberchk(anon(false), Options)
2693
+ ; graph(Options, DB),
2694
+ rdf_db(_, _, Subject, DB)
2695
+ ),
2696
+ !.
2697
+ rdf_save_non_anon_subject(Out, Subject, Options) :-
2698
+ rdf_save_subject(Out, Subject, Options),
2699
+ flag(rdf_db_saved_subjects, X, X+1).
2700
+
2701
+
2702
+ %! rdf_save_subject(+Out, +Subject:resource, +Options) is det.
2703
+ %
2704
+ % Save the triples associated to Subject to Out. Options:
2705
+ %
2706
+ % * graph(+Graph)
2707
+ % Only save properties from Graph.
2708
+ % * base_uri(+URI)
2709
+ % * convert_typed_literal(:Goal)
2710
+ % * document_language(+XMLLang)
2711
+ %
2712
+ % @see rdf_save/2 for a description of these options.
2713
+
2714
+ rdf_save_subject(Out, Subject, Options) :-
2715
+ is_list(Options),
2716
+ !,
2717
+ option(base_uri(BaseURI), Options, '-'),
2718
+ ( rdf_save_subject(Out, Subject, BaseURI, 0, Options)
2719
+ -> format(Out, '~n', [])
2720
+ ; throw(error(rdf_save_failed(Subject), 'Internal error'))
2721
+ ).
2722
+ rdf_save_subject(Out, Subject, DB) :-
2723
+ ( var(DB)
2724
+ -> rdf_save_subject(Out, Subject, [])
2725
+ ; rdf_save_subject(Out, Subject, [graph(DB)])
2726
+ ).
2727
+
2728
+
2729
+ %! rdf_save_subject(+Out:stream, +Subject:resource, +BaseURI,
2730
+ %! +Indent:int, +Options) is det.
2731
+ %
2732
+ % Save properties of Subject.
2733
+ %
2734
+ % @param Indent Current indentation
2735
+
2736
+ rdf_save_subject(_, Subject, _, _, _) :-
2737
+ inlined(Subject),
2738
+ !.
2739
+ rdf_save_subject(Out, Subject, BaseURI, Indent, Options) :-
2740
+ do_save_subject(Out, Subject, BaseURI, Indent, Options).
2741
+
2742
+ do_save_subject(Out, Subject, BaseURI, Indent, Options) :-
2743
+ graph(Options, DB),
2744
+ findall(Pred=Object, rdf_db(Subject, Pred, Object, DB), Atts0),
2745
+ sort(Atts0, Atts), % remove duplicates
2746
+ length(Atts, L),
2747
+ ( length(Atts0, L0),
2748
+ Del is L0-L,
2749
+ Del > 0
2750
+ -> print_message(informational,
2751
+ rdf(save_removed_duplicates(Del, Subject)))
2752
+ ; true
2753
+ ),
2754
+ rdf_save_subject(Out, Subject, BaseURI, Atts, Indent, Options),
2755
+ flag(rdf_db_saved_triples, X, X+L).
2756
+
2757
+ rdf_db(Subject, Pred, Object, DB) :-
2758
+ var(DB),
2759
+ !,
2760
+ rdf(Subject, Pred, Object).
2761
+ rdf_db(Subject, Pred, Object, DB) :-
2762
+ rdf(Subject, Pred, Object, DB:_).
2763
+
2764
+ %! rdf_save_subject(+Out:stream, +Subject:resource, +BaseURI,
2765
+ %! +Atts:list(Pred=Obj), +Indent:int, +Options) is det.
2766
+ %
2767
+ % Save triples defined by Atts on Subject.
2768
+
2769
+ rdf_save_subject(Out, Subject, BaseURI, Atts, Indent, Options) :-
2770
+ rdf_equal(rdf:type, RdfType),
2771
+ select(RdfType=Type, Atts, Atts1),
2772
+ \+ rdf_is_bnode(Type),
2773
+ rdf_id(Type, BaseURI, TypeId),
2774
+ xml_is_name(TypeId),
2775
+ !,
2776
+ format(Out, '~*|<', [Indent]),
2777
+ rdf_write_id(Out, TypeId),
2778
+ save_about(Out, BaseURI, Subject, Options),
2779
+ save_attributes(Atts1, BaseURI, Out, TypeId, Indent, Options).
2780
+ rdf_save_subject(Out, Subject, BaseURI, Atts, Indent, Options) :-
2781
+ format(Out, '~*|<rdf:Description', [Indent]),
2782
+ save_about(Out, BaseURI, Subject, Options),
2783
+ save_attributes(Atts, BaseURI, Out, rdf:'Description', Indent, Options).
2784
+
2785
+ xml_is_name(_NS:Atom) :-
2786
+ !,
2787
+ xml_name(Atom).
2788
+ xml_is_name(Atom) :-
2789
+ xml_name(Atom).
2790
+
2791
+ %! save_about(+Out, +BaseURI, +Subject, +Options) is det.
2792
+ %
2793
+ % Save the rdf:about. If Subject is a blank node, save the nodeID
2794
+ % if any.
2795
+
2796
+ save_about(Out, _BaseURI, Subject, _Options) :-
2797
+ rdf_is_bnode(Subject),
2798
+ !,
2799
+ ( named_anon(Subject, NodeID)
2800
+ -> format(Out, ' rdf:nodeID="~w"', [NodeID])
2801
+ ; true
2802
+ ).
2803
+ save_about(Out, BaseURI, Subject, Options) :-
2804
+ option(encoding(Encoding), Options, utf8),
2805
+ rdf_value(Subject, BaseURI, QSubject, Encoding),
2806
+ format(Out, ' rdf:about="~w"', [QSubject]).
2807
+
2808
+ %! save_attributes(+List, +BaseURI, +Stream, +Element, +Indent, +Options)
2809
+ %
2810
+ % Save the attributes. Short literal attributes are saved in the
2811
+ % tag. Others as the content of the description element. The
2812
+ % begin tag has already been filled.
2813
+
2814
+ save_attributes(Atts, BaseURI, Out, Element, Indent, Options) :-
2815
+ split_attributes(Atts, InTag, InBody, Options),
2816
+ SubIndent is Indent + 2,
2817
+ save_attributes2(InTag, BaseURI, tag, Out, SubIndent, Options),
2818
+ ( InBody == []
2819
+ -> format(Out, '/>~n', [])
2820
+ ; format(Out, '>~n', []),
2821
+ save_attributes2(InBody, BaseURI, body, Out, SubIndent, Options),
2822
+ format(Out, '~N~*|</', [Indent]),
2823
+ rdf_write_id(Out, Element),
2824
+ format(Out, '>~n', [])
2825
+ ).
2826
+
2827
+ %! split_attributes(+Attributes, -HeadAttrs, -BodyAttr, Options)
2828
+ %
2829
+ % Split attribute (Name=Value) list into attributes for the head
2830
+ % and body. Attributes can only be in the head if they are literal
2831
+ % and appear only one time in the attribute list.
2832
+
2833
+ split_attributes(Atts, [], Atts, Options) :-
2834
+ option(xml_attributes(false), Options),
2835
+ !.
2836
+ split_attributes(Atts, HeadAttr, BodyAttr, _) :-
2837
+ duplicate_attributes(Atts, Dupls, Singles),
2838
+ simple_literal_attributes(Singles, HeadAttr, Rest),
2839
+ append(Dupls, Rest, BodyAttr).
2840
+
2841
+ %! duplicate_attributes(+Attrs, -Duplicates, -Singles)
2842
+ %
2843
+ % Extract attributes that appear more than once as we cannot
2844
+ % duplicate an attribute in the head according to the XML rules.
2845
+
2846
+ duplicate_attributes([], [], []).
2847
+ duplicate_attributes([H|T], Dupls, Singles) :-
2848
+ H = (Name=_),
2849
+ named_attributes(Name, T, D, R),
2850
+ D \== [],
2851
+ append([H|D], Dupls2, Dupls),
2852
+ !,
2853
+ duplicate_attributes(R, Dupls2, Singles).
2854
+ duplicate_attributes([H|T], Dupls2, [H|Singles]) :-
2855
+ duplicate_attributes(T, Dupls2, Singles).
2856
+
2857
+ named_attributes(_, [], [], []) :- !.
2858
+ named_attributes(Name, [H|T], D, R) :-
2859
+ ( H = (Name=_)
2860
+ -> D = [H|DT],
2861
+ named_attributes(Name, T, DT, R)
2862
+ ; R = [H|RT],
2863
+ named_attributes(Name, T, D, RT)
2864
+ ).
2865
+
2866
+ %! simple_literal_attributes(+Attributes, -Inline, -Body)
2867
+ %
2868
+ % Split attributes for (literal) attributes to be used in the
2869
+ % begin-tag and ones that have to go into the body of the description.
2870
+
2871
+ simple_literal_attributes([], [], []).
2872
+ simple_literal_attributes([H|TA], [H|TI], B) :-
2873
+ in_tag_attribute(H),
2874
+ !,
2875
+ simple_literal_attributes(TA, TI, B).
2876
+ simple_literal_attributes([H|TA], I, [H|TB]) :-
2877
+ simple_literal_attributes(TA, I, TB).
2878
+
2879
+ in_tag_attribute(_=literal(Text)) :-
2880
+ atom(Text), % may not have lang qualifier
2881
+ atom_length(Text, Len),
2882
+ Len < 60.
2883
+
2884
+ %! save_attributes2(+List, +BaseURI, +TagOrBody, +Stream, +Indent, +Options)
2885
+ %
2886
+ % Save a list of attributes.
2887
+
2888
+ save_attributes2([], _, _, _, _, _).
2889
+ save_attributes2([H|T], BaseURI, Where, Out, Indent, Options) :-
2890
+ save_attribute(Where, H, BaseURI, Out, Indent, Options),
2891
+ save_attributes2(T, BaseURI, Where, Out, Indent, Options).
2892
+
2893
+ save_attribute(tag, Name=literal(Value), BaseURI, Out, Indent, Options) :-
2894
+ AttIndent is Indent + 2,
2895
+ rdf_id(Name, BaseURI, NameText),
2896
+ option(encoding(Encoding), Options, utf8),
2897
+ xml_quote_attribute(Value, QVal, Encoding),
2898
+ format(Out, '~N~*|', [AttIndent]),
2899
+ rdf_write_id(Out, NameText),
2900
+ format(Out, '="~w"', [QVal]).
2901
+ save_attribute(body, Name=literal(Literal0), BaseURI, Out, Indent, Options) :-
2902
+ !,
2903
+ rdf_id(Name, BaseURI, NameText),
2904
+ ( memberchk(convert_typed_literal(Converter), Options),
2905
+ call(Converter, Type, Content, Literal0)
2906
+ -> Literal = type(Type, Content)
2907
+ ; Literal = Literal0
2908
+ ),
2909
+ save_body_literal(Literal, NameText, BaseURI, Out, Indent, Options).
2910
+ save_attribute(body, Name=Value, BaseURI, Out, Indent, Options) :-
2911
+ rdf_is_bnode(Value),
2912
+ !,
2913
+ rdf_id(Name, BaseURI, NameText),
2914
+ format(Out, '~N~*|<', [Indent]),
2915
+ rdf_write_id(Out, NameText),
2916
+ ( named_anon(Value, NodeID)
2917
+ -> format(Out, ' rdf:nodeID="~w"/>', [NodeID])
2918
+ ; ( rdf(S1, Name, Value),
2919
+ rdf(S2, P2, Value),
2920
+ (S1 \== S2 ; Name \== P2)
2921
+ -> predicate_property(named_anon(_,_), number_of_clauses(N)),
2922
+ atom_concat('bn', N, NodeID),
2923
+ assertz(named_anon(Value, NodeID))
2924
+ ; true
2925
+ ),
2926
+ SubIndent is Indent + 2,
2927
+ ( rdf_collection(Value)
2928
+ -> save_about(Out, BaseURI, Value, Options),
2929
+ format(Out, ' rdf:parseType="Collection">~n', []),
2930
+ rdf_save_list(Out, Value, BaseURI, SubIndent, Options)
2931
+ ; format(Out, '>~n', []),
2932
+ rdf_save_subject(Out, Value, BaseURI, SubIndent, Options)
2933
+ ),
2934
+ format(Out, '~N~*|</', [Indent]),
2935
+ rdf_write_id(Out, NameText),
2936
+ format(Out, '>~n', [])
2937
+ ).
2938
+ save_attribute(body, Name=Value, BaseURI, Out, Indent, Options) :-
2939
+ option(inline(true), Options),
2940
+ has_attributes(Value, Options),
2941
+ \+ inlined(Value),
2942
+ !,
2943
+ assertz(inlined(Value)),
2944
+ rdf_id(Name, BaseURI, NameText),
2945
+ format(Out, '~N~*|<', [Indent]),
2946
+ rdf_write_id(Out, NameText),
2947
+ SubIndent is Indent + 2,
2948
+ ( rdf_collection(Value)
2949
+ -> save_about(Out, BaseURI, Value, Options),
2950
+ format(Out, ' rdf:parseType="Collection">~n', []),
2951
+ rdf_save_list(Out, Value, BaseURI, SubIndent, Options)
2952
+ ; format(Out, '>~n', []),
2953
+ do_save_subject(Out, Value, BaseURI, SubIndent, Options)
2954
+ ),
2955
+ format(Out, '~N~*|</', [Indent]),
2956
+ rdf_write_id(Out, NameText),
2957
+ format(Out, '>~n', []).
2958
+ save_attribute(body, Name=Value, BaseURI, Out, Indent, Options) :-
2959
+ option(encoding(Encoding), Options, utf8),
2960
+ rdf_value(Value, BaseURI, QVal, Encoding),
2961
+ rdf_id(Name, BaseURI, NameText),
2962
+ format(Out, '~N~*|<', [Indent]),
2963
+ rdf_write_id(Out, NameText),
2964
+ format(Out, ' rdf:resource="~w"/>', [QVal]).
2965
+
2966
+ has_attributes(URI, Options) :-
2967
+ graph(Options, DB),
2968
+ rdf_db(URI, _, _, DB),
2969
+ !.
2970
+
2971
+ %! save_body_literal(+Literal, +NameText, +BaseURI,
2972
+ %! +Out, +Indent, +Options).
2973
+
2974
+ save_body_literal(lang(Lang, Value),
2975
+ NameText, BaseURI, Out, Indent, Options) :-
2976
+ !,
2977
+ format(Out, '~N~*|<', [Indent]),
2978
+ rdf_write_id(Out, NameText),
2979
+ ( memberchk(document_language(Lang), Options)
2980
+ -> write(Out, '>')
2981
+ ; rdf_id(Lang, BaseURI, LangText),
2982
+ format(Out, ' xml:lang="~w">', [LangText])
2983
+ ),
2984
+ save_attribute_value(Value, Out, Options),
2985
+ write(Out, '</'), rdf_write_id(Out, NameText), write(Out, '>').
2986
+ save_body_literal(type(Type, DOM),
2987
+ NameText, _BaseURI, Out, Indent, Options) :-
2988
+ rdf_equal(Type, rdf:'XMLLiteral'),
2989
+ !,
2990
+ ( atom(DOM)
2991
+ -> format(Out, '~N~*|<', [Indent]),
2992
+ rdf_write_id(Out, NameText),
2993
+ format(Out, ' rdf:parseType="Literal">~w</', [DOM]),
2994
+ rdf_write_id(Out, NameText), write(Out, '>')
2995
+ ; save_xml_literal(DOM, NameText, Out, Indent, Options)
2996
+ ).
2997
+ save_body_literal(type(Type, Value),
2998
+ NameText, BaseURI, Out, Indent, Options) :-
2999
+ !,
3000
+ format(Out, '~N~*|<', [Indent]),
3001
+ rdf_write_id(Out, NameText),
3002
+ option(encoding(Encoding), Options, utf8),
3003
+ rdf_value(Type, BaseURI, QVal, Encoding),
3004
+ format(Out, ' rdf:datatype="~w">', [QVal]),
3005
+ save_attribute_value(Value, Out, Options),
3006
+ write(Out, '</'), rdf_write_id(Out, NameText), write(Out, '>').
3007
+ save_body_literal(Literal,
3008
+ NameText, _, Out, Indent, Options) :-
3009
+ atomic(Literal),
3010
+ !,
3011
+ format(Out, '~N~*|<', [Indent]),
3012
+ rdf_write_id(Out, NameText),
3013
+ write(Out, '>'),
3014
+ save_attribute_value(Literal, Out, Options),
3015
+ write(Out, '</'), rdf_write_id(Out, NameText), write(Out, '>').
3016
+ save_body_literal(DOM,
3017
+ NameText, BaseURI, Out, Indent, Options) :-
3018
+ rdf_equal(Type, rdf:'XMLLiteral'),
3019
+ save_body_literal(type(Type, DOM),
3020
+ NameText, BaseURI, Out, Indent, Options).
3021
+
3022
+ save_attribute_value(Value, Out, Options) :- % strings
3023
+ ( atom(Value)
3024
+ ; string(Value)
3025
+ ),
3026
+ !,
3027
+ option(encoding(Encoding), Options, utf8),
3028
+ xml_quote_cdata(Value, QVal, Encoding),
3029
+ write(Out, QVal).
3030
+ save_attribute_value(Value, Out, _Options) :- % numbers
3031
+ number(Value),
3032
+ !,
3033
+ writeq(Out, Value). % quoted: preserve floats
3034
+ save_attribute_value(Value, _Out, _Options) :-
3035
+ throw(error(save_attribute_value(Value), _)).
3036
+
3037
+ %! save_xml_literal(+DOM, +Attr, +Out, +Indent, +Options) is det.
3038
+ %
3039
+ % Save an XMLLiteral value. We already emitted
3040
+ %
3041
+ % ==
3042
+ % <prop parseType="literal"
3043
+ % ==
3044
+ %
3045
+ % but not the terminating =|>|=. We need to establish the
3046
+ % namespaces used in the DOM. The namespaces in the rdf document
3047
+ % are in the nsmap-option of Options.
3048
+
3049
+ save_xml_literal(DOM, Attr, Out, Indent, Options) :-
3050
+ xml_is_dom(DOM),
3051
+ !,
3052
+ memberchk(nsmap(NsMap), Options),
3053
+ id_to_atom(Attr, Atom),
3054
+ xml_write(Out,
3055
+ element(Atom, ['rdf:parseType'='Literal'], DOM),
3056
+ [ header(false),
3057
+ indent(Indent),
3058
+ nsmap(NsMap)
3059
+ ]).
3060
+ save_xml_literal(NoDOM, _, _, _, _) :-
3061
+ must_be(xml_dom, NoDOM).
3062
+
3063
+ id_to_atom(NS:Local, Atom) :-
3064
+ !,
3065
+ atomic_list_concat([NS,Local], :, Atom).
3066
+ id_to_atom(ID, ID).
3067
+
3068
+
3069
+ %! rdf_collection(+URI) is semidet.
3070
+ %
3071
+ % True if URI represents an RDF list that fits the RDF
3072
+ % parseType=collection syntax. This means it is a linked list of
3073
+ % bnode-cells with a rdf:first that is a resource, optionally a
3074
+ % rdf:type that is an rdf:list and the list ends in an rdf:nil.
3075
+
3076
+ :- rdf_meta
3077
+ rdf_collection(r),
3078
+ collection_p(r,r).
3079
+
3080
+ rdf_collection(rdf:nil) :- !.
3081
+ rdf_collection(Cell) :-
3082
+ rdf_is_bnode(Cell),
3083
+ findall(F, rdf(Cell, rdf:first, F), [_]),
3084
+ findall(F, rdf(Cell, rdf:rest, F), [Rest]),
3085
+ forall(rdf(Cell, P, V),
3086
+ collection_p(P, V)),
3087
+ rdf_collection(Rest).
3088
+
3089
+ collection_p(rdf:first, V) :- atom(V).
3090
+ collection_p(rdf:rest, _).
3091
+ collection_p(rdf:type, rdf:'List').
3092
+
3093
+
3094
+ %! rdf_save_list(+Out, +List, +BaseURI, +Indent, +Options)
3095
+
3096
+ rdf_save_list(_, List, _, _, _) :-
3097
+ rdf_equal(List, rdf:nil),
3098
+ !.
3099
+ rdf_save_list(Out, List, BaseURI, Indent, Options) :-
3100
+ rdf_has(List, rdf:first, First),
3101
+ ( rdf_is_bnode(First)
3102
+ -> nl(Out),
3103
+ rdf_save_subject(Out, First, BaseURI, Indent, Options)
3104
+ ; option(encoding(Encoding), Options, utf8),
3105
+ rdf_value(First, BaseURI, QVal, Encoding),
3106
+ format(Out, '~N~*|<rdf:Description rdf:about="~w"/>',
3107
+ [Indent, QVal])
3108
+ ),
3109
+ flag(rdf_db_saved_triples, X, X+3),
3110
+ ( rdf_has(List, rdf:rest, List2),
3111
+ \+ rdf_equal(List2, rdf:nil)
3112
+ -> rdf_save_list(Out, List2, BaseURI, Indent, Options)
3113
+ ; true
3114
+ ).
3115
+
3116
+
3117
+ %! rdf_id(+Resource, +BaseURI, -NSLocal)
3118
+ %
3119
+ % Generate a NS:Local name for Resource given the indicated
3120
+ % default namespace. This call is used for elements.
3121
+
3122
+ rdf_id(Id, BaseURI, Local) :-
3123
+ assertion(atom(BaseURI)),
3124
+ atom_concat(BaseURI, Local, Id),
3125
+ sub_atom(Local, 0, 1, _, #),
3126
+ !.
3127
+ rdf_id(Id, _, NS:Local) :-
3128
+ iri_xml_namespace(Id, Full, Local),
3129
+ ns(NS, Full),
3130
+ !.
3131
+ rdf_id(Id, _, NS:Local) :-
3132
+ ns(NS, Full),
3133
+ Full \== '',
3134
+ atom_concat(Full, Local, Id),
3135
+ !.
3136
+ rdf_id(Id, _, Id).
3137
+
3138
+
3139
+ %! rdf_write_id(+Out, +NSLocal) is det.
3140
+ %
3141
+ % Write an identifier. We cannot use native write on it as both NS
3142
+ % and Local can be operators.
3143
+
3144
+ rdf_write_id(Out, NS:Local) :-
3145
+ !,
3146
+ format(Out, '~w:~w', [NS, Local]).
3147
+ rdf_write_id(Out, Atom) :-
3148
+ write(Out, Atom).
3149
+
3150
+ %! rdf_value(+Resource, +BaseURI, -Text, +Encoding)
3151
+ %
3152
+ % According to "6.4 RDF URI References" of the RDF Syntax
3153
+ % specification, a URI reference is UNICODE string not containing
3154
+ % control sequences, represented as UTF-8 and then as escaped
3155
+ % US-ASCII.
3156
+
3157
+ rdf_value(Base, Base, '', _) :- !.
3158
+ rdf_value(V, Base, Text, Encoding) :-
3159
+ atom_concat(Base, Local, V),
3160
+ sub_atom(Local, 0, _, _, #),
3161
+ !,
3162
+ xml_quote_attribute(Local, Text, Encoding).
3163
+ rdf_value(V, _, Text, Encoding) :-
3164
+ ns(NS, Full),
3165
+ atom_concat(Full, Local, V),
3166
+ xml_is_name(Local),
3167
+ !,
3168
+ xml_quote_attribute(Local, QLocal, Encoding),
3169
+ atomic_list_concat(['&', NS, (';'), QLocal], Text).
3170
+ rdf_value(V, _, Q, Encoding) :-
3171
+ xml_quote_attribute(V, Q, Encoding).
3172
+
3173
+
3174
+ /*******************************
3175
+ * MATCH AND COMPARE *
3176
+ *******************************/
3177
+
3178
+ %! rdf_compare(-Dif, +Object1, +Object2) is det.
3179
+ %
3180
+ % Compare two object terms. Where SPARQL defines a partial
3181
+ % ordering, we define a complete ordering of terms. The ordering
3182
+ % is defines as:
3183
+ %
3184
+ % - Blank nodes < IRIs < Literals
3185
+ % - Numeric literals < other literals
3186
+ % - Numeric literals are compared by value and then by type,
3187
+ % where Integer < Decimal < Double
3188
+ % - Other literals are compare lexically, case insensitive.
3189
+ % If equal, uppercase precedes lowercase. If still equal,
3190
+ % the types are compared lexically.
3191
+
3192
+ %! rdf_match_label(+How, +Pattern, +Label) is semidet.
3193
+ %
3194
+ % True if Label matches Pattern according to How. How is one of
3195
+ % `icase`, `substring`, `word`, `prefix` or `like`. For backward
3196
+ % compatibility, `exact` is a synonym for `icase`.
3197
+
3198
+
3199
+ /*******************************
3200
+ * DEPRECATED MATERIAL *
3201
+ *******************************/
3202
+
3203
+ %! rdf_split_url(+Prefix, +Local, -URL) is det.
3204
+ %! rdf_split_url(-Prefix, -Local, +URL) is det.
3205
+ %
3206
+ % Split/join a URL. This functionality is moved to library(sgml).
3207
+ %
3208
+ % @deprecated Use iri_xml_namespace/3. Note that the argument
3209
+ % order is iri_xml_namespace(+IRI, -Namespace, -Localname).
3210
+
3211
+ rdf_split_url(Prefix, Local, URL) :-
3212
+ atomic(URL),
3213
+ !,
3214
+ iri_xml_namespace(URL, Prefix, Local).
3215
+ rdf_split_url(Prefix, Local, URL) :-
3216
+ atom_concat(Prefix, Local, URL).
3217
+
3218
+ %! rdf_url_namespace(+URL, -Namespace)
3219
+ %
3220
+ % Namespace is the namespace of URL.
3221
+ %
3222
+ % @deprecated Use iri_xml_namespace/2
3223
+
3224
+ rdf_url_namespace(URL, Prefix) :-
3225
+ iri_xml_namespace(URL, Prefix).
3226
+
3227
+
3228
+ /*******************************
3229
+ * LITERALS *
3230
+ *******************************/
3231
+
3232
+ %! rdf_new_literal_map(-Map) is det.
3233
+ %
3234
+ % Create a new literal map, returning an opaque handle.
3235
+
3236
+ %! rdf_destroy_literal_map(+Map) is det.
3237
+ %
3238
+ % Destroy a literal map. After this call, further use of the Map
3239
+ % handle is illegal. Additional synchronisation is needed if maps
3240
+ % that are shared between threads are destroyed to guarantee the
3241
+ % handle is no longer used. In some scenarios
3242
+ % rdf_reset_literal_map/1 provides a safe alternative.
3243
+
3244
+ %! rdf_reset_literal_map(+Map) is det.
3245
+ %
3246
+ % Delete all content from the literal map.
3247
+
3248
+ %! rdf_insert_literal_map(+Map, +Key, +Value) is det.
3249
+ %
3250
+ % Add a relation between Key and Value to the map. If this
3251
+ % relation already exists no action is performed.
3252
+
3253
+ %! rdf_insert_literal_map(+Map, +Key, +Value, -KeyCount) is det.
3254
+ %
3255
+ % As rdf_insert_literal_map/3. In addition, if Key is a new key in
3256
+ % Map, unify KeyCount with the number of keys in Map. This serves
3257
+ % two purposes. Derived maps, such as the stem and metaphone maps
3258
+ % need to know about new keys and it avoids additional foreign
3259
+ % calls for doing the progress in rdf_litindex.pl.
3260
+
3261
+ %! rdf_delete_literal_map(+Map, +Key) is det.
3262
+ %
3263
+ % Delete Key and all associated values from the map.
3264
+
3265
+ %! rdf_delete_literal_map(+Map, +Key, +Value) is det.
3266
+ %
3267
+ % Delete the association between Key and Value from the map.
3268
+
3269
+ %! rdf_find_literal_map(+Map, +KeyList, -ValueList) is det.
3270
+ %
3271
+ % Unify ValueList with an ordered set of values associated to all
3272
+ % keys from KeyList. Each key in KeyList is either an atom, an
3273
+ % integer or a term not(Key). If not-terms are provided, there
3274
+ % must be at least one positive keywords. The negations are tested
3275
+ % after establishing the positive matches.
3276
+
3277
+ %! rdf_keys_in_literal_map(+Map, +Spec, -Answer) is det.
3278
+ %
3279
+ % Realises various queries on the key-set:
3280
+ %
3281
+ % * all
3282
+ %
3283
+ % Unify Answer with an ordered list of all keys.
3284
+ % * key(+Key)
3285
+ %
3286
+ % Succeeds if Key is a key in the map and unify Answer with the
3287
+ % number of values associated with the key. This provides a fast
3288
+ % test of existence without fetching the possibly large
3289
+ % associated value set as with rdf_find_literal_map/3.
3290
+ %
3291
+ % * prefix(+Prefix)
3292
+ % Unify Answer with an ordered set of all keys that have the
3293
+ % given prefix. See section 3.1 for details on prefix matching.
3294
+ % Prefix must be an atom. This call is intended for
3295
+ % auto-completion in user interfaces.
3296
+ %
3297
+ % * ge(+Min)
3298
+ % Unify Answer with all keys that are larger or equal to the
3299
+ % integer Min.
3300
+ %
3301
+ % * le(+Max)
3302
+ % Unify Answer with all keys that are smaller or equal to the integer
3303
+ % Max.
3304
+ %
3305
+ % * between(+Min, +Max) Unify
3306
+ % Answer with all keys between Min and Max (including).
3307
+
3308
+ %! rdf_statistics_literal_map(+Map, -KeyValue)
3309
+ %
3310
+ % Query some statistics of the map. Provides KeyValue are:
3311
+ %
3312
+ % * size(-Keys, -Relations)
3313
+ % Unify Keys with the total key-count of the index and Relation
3314
+ % with the total Key-Value count.
3315
+
3316
+
3317
+
3318
+ /*******************************
3319
+ * MISC *
3320
+ *******************************/
3321
+
3322
+ %! rdf_version(-Version) is det.
3323
+ %
3324
+ % True when Version is the numerical version-id of this library.
3325
+ % The version is computed as
3326
+ %
3327
+ % Major*10000 + Minor*100 + Patch.
3328
+
3329
+ %! rdf_set(+Term) is det.
3330
+ %
3331
+ % Set properties of the RDF store. Currently defines:
3332
+ %
3333
+ % * hash(+Hash, +Parameter, +Value)
3334
+ % Set properties for a triple index. Hash is one of =s=,
3335
+ % =p=, =sp=, =o=, =po=, =spo=, =g=, =sg= or =pg=. Parameter
3336
+ % is one of:
3337
+ %
3338
+ % - size
3339
+ % Value defines the number of entries in the hash-table.
3340
+ % Value is rounded _down_ to a power of 2. After setting
3341
+ % the size explicitly, auto-sizing for this table is
3342
+ % disabled. Setting the size smaller than the current
3343
+ % size results in a =permission_error= exception.
3344
+ %
3345
+ % - average_chain_len
3346
+ % Set maximum average collision number for the hash.
3347
+ %
3348
+ % - optimize_threshold
3349
+ % Related to resizing hash-tables. If 0, all triples are
3350
+ % moved to the new size by the garbage collector. If more
3351
+ % then zero, those of the last Value resize steps remain at
3352
+ % their current location. Leaving cells at their current
3353
+ % location reduces memory fragmentation and slows down
3354
+ % access.
3355
+
3356
+ %! rdf_md5(+Graph, -MD5) is det.
3357
+ %
3358
+ % True when MD5 is the MD5 hash for all triples in graph. The MD5
3359
+ % digest itself is represented as an atom holding a 32-character
3360
+ % hexadecimal string. The library maintains the digest
3361
+ % incrementally on rdf_load/[1,2], rdf_load_db/1, rdf_assert/[3,4]
3362
+ % and rdf_retractall/[3,4]. Checking whether the digest has
3363
+ % changed since the last rdf_load/[1,2] call provides a practical
3364
+ % means for checking whether the file needs to be saved.
3365
+ %
3366
+ % @deprecated New code should use rdf_graph_property(Graph,
3367
+ % hash(Hash)).
3368
+
3369
+ %! rdf_generation(-Generation) is det.
3370
+ %
3371
+ % True when Generation is the current generation of the database.
3372
+ % Each modification to the database increments the generation. It
3373
+ % can be used to check the validity of cached results deduced from
3374
+ % the database. Committing a non-empty transaction increments the
3375
+ % generation by one.
3376
+ %
3377
+ % When inside a transaction, Generation is unified to a term
3378
+ % _TransactionStartGen_ + _InsideTransactionGen_. E.g., 4+3 means
3379
+ % that the transaction was started at generation 4 of the global
3380
+ % database and we have created 3 new generations inside the
3381
+ % transaction. Note that this choice of representation allows for
3382
+ % comparing generations using Prolog arithmetic. Comparing a
3383
+ % generation in one transaction with a generation in another
3384
+ % transaction is meaningless.
3385
+
3386
+ %! rdf_estimate_complexity(?Subject, ?Predicate, ?Object, -Complexity)
3387
+ %
3388
+ % Return the number of alternatives as indicated by the database
3389
+ % internal hashed indexing. This is a rough measure for the number
3390
+ % of alternatives we can expect for an rdf_has/3 call using the
3391
+ % given three arguments. When called with three variables, the
3392
+ % total number of triples is returned. This estimate is used in
3393
+ % query optimisation. See also rdf_predicate_property/2 and
3394
+ % rdf_statistics/1 for additional information to help optimizers.
3395
+
3396
+ %! rdf_debug(+Level) is det.
3397
+ %
3398
+ % Set debugging to Level. Level is an integer 0..9. Default is
3399
+ % 0 no debugging.
3400
+
3401
+ %! rdf_atom_md5(+Text, +Times, -MD5) is det.
3402
+ %
3403
+ % Computes the MD5 hash from Text, which is an atom, string or list of
3404
+ % character codes. Times is an integer >= 1. When > 0, the MD5
3405
+ % algorithm is repeated Times times on the generated hash. This can be
3406
+ % used for password encryption algorithms to make generate-and-test
3407
+ % loops slow.
3408
+ %
3409
+ % @deprecated Obviously, password hash primitives do not belong in
3410
+ % this library. The library(crypto) from the \const{ssl} package
3411
+ % provides extensive support for hashes. The \const{clib} package
3412
+ % provides library(crypt) to access the OS (Unix) password hash
3413
+ % implementation as well as lightweight implementations of several
3414
+ % popular hashes.
3415
+
3416
+
3417
+ /*******************************
3418
+ * MESSAGES *
3419
+ *******************************/
3420
+
3421
+ :- multifile
3422
+ prolog:message//1.
3423
+
3424
+ prolog:message(rdf(Term)) -->
3425
+ message(Term).
3426
+
3427
+ message(loaded(How, What, BaseURI, Triples, Time)) -->
3428
+ how(How),
3429
+ source(What),
3430
+ into(What, BaseURI),
3431
+ in_time(Triples, Time).
3432
+ message(save_removed_duplicates(N, Subject)) -->
3433
+ [ 'Removed ~d duplicate triples about "~p"'-[N,Subject] ].
3434
+ message(saved(File, SavedSubjects, SavedTriples)) -->
3435
+ [ 'Saved ~D triples about ~D subjects into ~p'-
3436
+ [SavedTriples, SavedSubjects, File]
3437
+ ].
3438
+ message(using_namespace(Id, NS)) -->
3439
+ [ 'Using namespace id ~w for ~w'-[Id, NS] ].
3440
+ message(inconsistent_cache(DB, Graphs)) -->
3441
+ [ 'RDF cache file for ~w contains the following graphs'-[DB], nl,
3442
+ '~t~8|~p'-[Graphs]
3443
+ ].
3444
+ message(guess_format(Ext)) -->
3445
+ [ 'Unknown file-extension: ~w. Assuming RDF/XML'-[Ext] ].
3446
+ message(meta(not_expanded(G))) -->
3447
+ [ 'rdf_meta/1: ~p is not expanded'-[G] ].
3448
+ message(deprecated(rdf_unload(Graph))) -->
3449
+ [ 'rdf_unload/1: Use ~q'-[rdf_unload_graph(Graph)] ].
3450
+
3451
+
3452
+ how(load) --> [ 'Loaded' ].
3453
+ how(parsed) --> [ 'Parsed' ].
3454
+
3455
+ source(SourceURL) -->
3456
+ { uri_file_name(SourceURL, File),
3457
+ !,
3458
+ file_base_name(File, Base) % TBD: relative file?
3459
+ },
3460
+ [ ' "~w"'-[Base] ].
3461
+ source(SourceURL) -->
3462
+ [ ' "~w"'-[SourceURL] ].
3463
+
3464
+ into(_, _) --> []. % TBD
3465
+
3466
+ in_time(Triples, ParseTime) -->
3467
+ [ ' in ~2f sec; ~D triples'-[ParseTime, Triples]
3468
+ ].