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-2017, University of Amsterdam 7 VU University Amsterdam 8 All rights reserved. 9 10 Redistribution and use in source and binary forms, with or without 11 modification, are permitted provided that the following conditions 12 are met: 13 14 1. Redistributions of source code must retain the above copyright 15 notice, this list of conditions and the following disclaimer. 16 17 2. Redistributions in binary form must reproduce the above copyright 18 notice, this list of conditions and the following disclaimer in 19 the documentation and/or other materials provided with the 20 distribution. 21 22 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 23 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 24 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 25 FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 26 COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 27 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 28 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 29 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 30 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 32 ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 33 POSSIBILITY OF SUCH DAMAGE. 34*/ 35 36:- module(rdf_db, 37 [ rdf_version/1, % -Version 38 39 rdf/3, % ?Subject, ?Predicate, ?Object 40 rdf/4, % ?Subject, ?Predicate, ?Object, ?DB 41 rdf_has/3, % ?Subject, +Pred, ?Obj 42 rdf_has/4, % ?Subject, +Pred, ?Obj, -RealPred 43 rdf_reachable/3, % ?Subject, +Pred, ?Object 44 rdf_reachable/5, % ?Subject, +Pred, ?Object, +MaxD, ?D 45 rdf_resource/1, % ?Resource 46 rdf_subject/1, % ?Subject 47 48 rdf_member_property/2, % ?Property, ?Index 49 50 rdf_assert/3, % +Subject, +Predicate, +Object 51 rdf_assert/4, % +Subject, +Predicate, +Object, +DB 52 rdf_retractall/3, % ?Subject, ?Predicate, ?Object 53 rdf_retractall/4, % ?Subject, ?Predicate, ?Object, +DB 54 rdf_update/4, % +Subject, +Predicate, +Object, +Act 55 rdf_update/5, % +Subject, +Predicate, +Object, +Src, +Act 56 rdf_set_predicate/2, % +Predicate, +Property 57 rdf_predicate_property/2, % +Predicate, ?Property 58 rdf_current_predicate/1, % -Predicate 59 rdf_current_literal/1, % -Literal 60 rdf_transaction/1, % :Goal 61 rdf_transaction/2, % :Goal, +Id 62 rdf_transaction/3, % :Goal, +Id, +Options 63 rdf_active_transaction/1, % ?Id 64 65 rdf_monitor/2, % :Goal, +Options 66 67 rdf_save_db/1, % +File 68 rdf_save_db/2, % +File, +DB 69 rdf_load_db/1, % +File 70 rdf_reset_db/0, 71 72 rdf_node/1, % -Id 73 rdf_bnode/1, % -Id 74 rdf_is_bnode/1, % +Id 75 76 rdf_is_resource/1, % +Term 77 rdf_is_literal/1, % +Term 78 rdf_literal_value/2, % +Term, -Value 79 80 rdf_load/1, % +File 81 rdf_load/2, % +File, +Options 82 rdf_save/1, % +File 83 rdf_save/2, % +File, +Options 84 rdf_unload/1, % +File 85 rdf_unload_graph/1, % +Graph 86 87 rdf_md5/2, % +DB, -MD5 88 rdf_atom_md5/3, % +Text, +Times, -MD5 89 90 rdf_create_graph/1, % ?Graph 91 rdf_graph_property/2, % ?Graph, ?Property 92 rdf_set_graph/2, % +Graph, +Property 93 rdf_graph/1, % ?Graph 94 rdf_source/1, % ?File 95 rdf_source/2, % ?DB, ?SourceURL 96 rdf_make/0, % Reload modified databases 97 rdf_gc/0, % Garbage collection 98 99 rdf_source_location/2, % +Subject, -Source 100 rdf_statistics/1, % -Key 101 rdf_set/1, % +Term 102 rdf_generation/1, % -Generation 103 rdf_snapshot/1, % -Snapshot 104 rdf_delete_snapshot/1, % +Snapshot 105 rdf_current_snapshot/1, % +Snapshot 106 rdf_estimate_complexity/4, % +S,+P,+O,-Count 107 108 rdf_save_subject/3, % +Stream, +Subject, +DB 109 rdf_save_header/2, % +Out, +Options 110 rdf_save_footer/1, % +Out 111 112 rdf_equal/2, % ?Resource, ?Resource 113 lang_equal/2, % +Lang1, +Lang2 114 lang_matches/2, % +Lang, +Pattern 115 116 rdf_prefix/2, % :Alias, +URI 117 rdf_current_prefix/2, % :Alias, ?URI 118 rdf_register_prefix/2, % +Alias, +URI 119 rdf_register_prefix/3, % +Alias, +URI, +Options 120 rdf_current_ns/2, % :Alias, ?URI 121 rdf_register_ns/2, % +Alias, +URI 122 rdf_register_ns/3, % +Alias, +URI, +Options 123 rdf_global_id/2, % ?NS:Name, :Global 124 rdf_global_object/2, % +Object, :NSExpandedObject 125 rdf_global_term/2, % +Term, :WithExpandedNS 126 127 rdf_compare/3, % -Dif, +Object1, +Object2 128 rdf_match_label/3, % +How, +String, +Label 129 rdf_split_url/3, % ?Base, ?Local, ?URL 130 rdf_url_namespace/2, % +URL, ?Base 131 132 rdf_warm_indexes/0, 133 rdf_warm_indexes/1, % +Indexed 134 rdf_update_duplicates/0, 135 136 rdf_debug/1, % Set verbosity 137 138 rdf_new_literal_map/1, % -Handle 139 rdf_destroy_literal_map/1, % +Handle 140 rdf_reset_literal_map/1, % +Handle 141 rdf_insert_literal_map/3, % +Handle, +Key, +Literal 142 rdf_insert_literal_map/4, % +Handle, +Key, +Literal, -NewKeys 143 rdf_delete_literal_map/3, % +Handle, +Key, +Literal 144 rdf_delete_literal_map/2, % +Handle, +Key 145 rdf_find_literal_map/3, % +Handle, +KeyList, -Literals 146 rdf_keys_in_literal_map/3, % +Handle, +Spec, -Keys 147 rdf_statistics_literal_map/2, % +Handle, +Name(-Arg...) 148 149 rdf_graph_prefixes/2, % ?Graph, -Prefixes 150 rdf_graph_prefixes/3, % ?Graph, -Prefixes, :Filter 151 152 (rdf_meta)/1, % +Heads 153 op(1150, fx, (rdf_meta)) 154 ]). 155:- use_module(library(rdf)). 156:- use_module(library(lists)). 157:- use_module(library(pairs)). 158:- use_module(library(shlib)). 159:- use_module(library(gensym)). 160:- use_module(library(sgml)). 161:- use_module(library(sgml_write)). 162:- use_module(library(option)). 163:- use_module(library(error)). 164:- use_module(library(uri)). 165:- use_module(library(debug)). 166:- use_module(library(apply)). 167:- use_module(library(xsdp_types)). 168:- if(exists_source(library(thread))). 169:- use_module(library(thread)). 170:- endif. 171:- use_module(library(semweb/rdf_cache)). 172 173:- use_foreign_library(foreign(rdf_db)). 174:- public rdf_print_predicate_cloud/2. % print matrix of reachable predicates 175 176:- meta_predicate 177 rdf_current_prefix( , ), 178 rdf_current_ns( , ), 179 rdf_global_id( , ), 180 rdf_global_term( , ), 181 rdf_global_object( , ), 182 rdf_transaction( ), 183 rdf_transaction( , ), 184 rdf_transaction( , , ), 185 rdf_monitor( , ), 186 rdf_save( , ), 187 rdf_load( , ). 188 189:- predicate_options(rdf_graph_prefixes/3, 3, 190 [expand(callable), filter(callable), min_count(nonneg)]). 191:- predicate_options(rdf_load/2, 2, 192 [ base_uri(atom), 193 cache(boolean), 194 concurrent(positive_integer), 195 db(atom), 196 format(oneof([xml,triples,turtle,trig,nquads,ntriples])), 197 graph(atom), 198 if(oneof([true,changed,not_loaded])), 199 modified(-float), 200 silent(boolean), 201 register_namespaces(boolean) 202 ]). 203:- predicate_options(rdf_register_ns/3, 3, [force(boolean), keep(boolean)]). 204:- predicate_options(rdf_save/2, 2, 205 [ graph(atom), 206 db(atom), 207 anon(boolean), 208 base_uri(atom), 209 write_xml_base(boolean), 210 convert_typed_literal(callable), 211 encoding(encoding), 212 document_language(atom), 213 namespaces(list(atom)), 214 xml_attributes(boolean), 215 inline(boolean) 216 ]). 217:- predicate_options(rdf_save_header/2, 2, 218 [ graph(atom), 219 db(atom), 220 namespaces(list(atom)) 221 ]). 222:- predicate_options(rdf_save_subject/3, 3, 223 [ graph(atom), 224 base_uri(atom), 225 convert_typed_literal(callable), 226 document_language(atom) 227 ]). 228:- predicate_options(rdf_transaction/3, 3, 229 [ snapshot(any) 230 ]). 231 232:- multifile ns/2. 233:- dynamic ns/2. % ID, URL 234:- discontiguous 235 term_expansion/2.
251 /******************************* 252 * PREFIXES * 253 *******************************/
rdf_current_prefix(Prefix, Expansion), atom_concat(Expansion, Local, URI),
269rdf_current_prefix(Module:Alias, URI) :- 270 nonvar(Alias), 271 !, 272 rdf_current_prefix(Module, Alias, URI), 273 !. 274rdf_current_prefix(Module:Alias, URI) :- 275 rdf_current_prefix(Module, Alias, URI). 276 277rdf_current_prefix(system, Alias, URI) :- 278 !, 279 ns(Alias, URI). 280rdf_current_prefix(Module, Alias, URI) :- 281 default_module(Module, M), 282 ( M == system 283 -> ns(Alias, URI) 284 ; '$flushed_predicate'(M:'rdf prefix'(_,_)), 285 call(M:'rdf prefix'(Alias,URI)) 286 ).
296rdf_prefix(Alias, URI) :- 297 throw(error(context_error(nodirective, rdf_prefix(Alias, URI)), _)). 298 299systemterm_expansion((:- rdf_prefix(AliasSpec, URI)), Clauses) :- 300 prolog_load_context(module, Module), 301 strip_module(Module:AliasSpec, TM, Alias), 302 must_be(atom, Alias), 303 must_be(atom, URI), 304 ( rdf_current_prefix(TM:Alias, URI) 305 -> Clauses = [] 306 ; TM == Module 307 -> Clauses = 'rdf prefix'(Alias, URI) 308 ; Clauses = TM:'rdf prefix'(Alias, URI) 309 ).
319ns(dc, 'http://purl.org/dc/elements/1.1/'). 320ns(dcterms, 'http://purl.org/dc/terms/'). 321ns(eor, 'http://dublincore.org/2000/03/13/eor#'). 322ns(foaf, 'http://xmlns.com/foaf/0.1/'). 323ns(owl, 'http://www.w3.org/2002/07/owl#'). 324ns(rdf, 'http://www.w3.org/1999/02/22-rdf-syntax-ns#'). 325ns(rdfs, 'http://www.w3.org/2000/01/rdf-schema#'). 326ns(serql, 'http://www.openrdf.org/schema/serql#'). 327ns(skos, 'http://www.w3.org/2004/02/skos/core#'). 328ns(void, 'http://rdfs.org/ns/void#'). 329ns(xsd, 'http://www.w3.org/2001/XMLSchema#').
true
, Replace existing namespace alias. Please note
that replacing a namespace is dangerous as namespaces
affect preprocessing. Make sure all code that depends on
a namespace is compiled after changing the registration.true
and Alias is already defined, keep the
original binding for Prefix and succeed silently.Without options, an attempt to redefine an alias raises a permission error.
Predefined prefixes are:
365rdf_register_prefix(Alias, URI) :- 366 rdf_register_prefix(Alias, URI, []). 367 368rdf_register_prefix(Alias, URI, Options) :- 369 must_be(atom, Alias), 370 must_be(atom, URI), 371 ( rdf_current_prefix(system:Alias, URI) 372 -> true 373 ; register_global_prefix(Alias, URI, Options) 374 ).
380register_global_prefix(Alias, URI, Options) :- 381 ns(Alias, _), 382 !, 383 ( option(force(true), Options, false) 384 -> retractall(ns(Alias, _)), 385 rdf_register_prefix(Alias, URI, Options), 386 rdf_empty_prefix_cache 387 ; option(keep(true), Options, false) 388 -> true 389 ; throw(error(permission_error(register, namespace, Alias), 390 context(_, 'Already defined'))) 391 ). 392register_global_prefix(Alias, URI, _) :- 393 findall(P-U, prefix_conflict(URI, P, U), Pairs), 394 order_prefixes([Alias-URI|Pairs], Ordered), 395 forall(member(P-U, Pairs), retract(ns(P,U))), 396 forall(member(P-U, Ordered), assert(ns(P,U))). 397 398prefix_conflict(URI, P, U) :- 399 ns(P,U), 400 ( sub_atom(URI, 0, _, _, U) 401 -> true 402 ; sub_atom(U, 0, _, _, URI) 403 ). 404 405order_prefixes(Pairs, Sorted) :- 406 map_list_to_pairs(prefix_uri_length, Pairs, ByLen), 407 sort(1, >=, ByLen, SortedByLen), 408 pairs_values(SortedByLen, Sorted). 409 410prefix_uri_length(_-URI, Len) :- 411 atom_length(URI, Len).
417rdf_current_ns(Prefix, URI) :-
418 rdf_current_prefix(Prefix, URI).
427rdf_register_ns(Prefix, URI) :- 428 rdf_register_prefix(Prefix, URI). 429rdf_register_ns(Prefix, URI, Options) :- 430 rdf_register_prefix(Prefix, URI, Options).
443register_file_ns([]) :- !. 444register_file_ns([Decl|T]) :- 445 !, 446 register_file_ns(Decl), 447 register_file_ns(T). 448register_file_ns([]=_) :- !. % xmlns= (overall default) 449register_file_ns(NS=URL) :- % compatibility 450 !, 451 register_file_ns(NS-URL). 452register_file_ns(NS-URL) :- 453 ( ns(NS, URL) 454 -> true 455 ; ns(NS, _) 456 -> true % redefined abbreviation 457 ; ns(_, URL) 458 -> true % redefined URL 459 ; rdf_register_ns(NS, URL) 460 ).
Note that this predicate is a meta-predicate on its output argument. This is necessary to get the module context while the first argument may be of the form (:)/2. The above mode description is correct, but should be interpreted as (?,?).
483rdf_global_id(Id, Module:Global) :- 484 rdf_global_id(Id, Global, Module). 485 486rdf_global_id(NS:Local, Global, Module) :- 487 global(NS, Local, Global, Module), 488 !. 489rdf_global_id(Global, Global, _).
503rdf_global_object(Object, Module:GlobalObject) :- 504 rdf_global_object(Object, GlobalObject, Module). 505 506rdf_global_object(Var, Global, _M) :- 507 var(Var), 508 !, 509 Global = Var. 510rdf_global_object(Prefix:Local, Global, M) :- 511 global(Prefix, Local, Global, M), 512 !. 513rdf_global_object(literal(type(Prefix:Local, Value)), 514 literal(type(Global, Value)), M) :- 515 global(Prefix, Local, Global, M), 516 !. 517rdf_global_object(^^(Value,Prefix:Local), 518 ^^(Value,Global), M) :- 519 global(Prefix, Local, Global, M), 520 !. 521rdf_global_object(literal(Query0, type(Prefix:Local, Value)), 522 literal(Query1, type(Global, Value)), M) :- 523 global(Prefix, Local, Global, M), 524 !, 525 rdf_global_term(Query0, Query1, M). 526rdf_global_object(literal(Query0, Value), 527 literal(Query1, Value), M) :- 528 !, 529 rdf_global_term(Query0, Query1, M). 530rdf_global_object(Global, Global, _). 531 532global(Prefix, Local, Global, Module) :- 533 ( atom(Global) 534 -> rdf_current_prefix(Module:Prefix, Full), 535 atom_concat(Full, Local, Global) 536 ; atom(Prefix), atom(Local), var(Global) 537 -> ( rdf_current_prefix(Module:Prefix, Full) 538 *-> atom_concat(Full, Local, Global) 539 ; current_prolog_flag(xref, true) 540 -> Global = Prefix:Local 541 ; existence_error(rdf_prefix, Prefix) 542 ) 543 ).
Terms of the form Prefix:Local that appear in TermIn for which Prefix is not defined are not replaced. Unlike rdf_global_id/2 and rdf_global_object/2, no error is raised.
557rdf_global_term(TermIn, Module:TermOut) :- 558 rdf_global_term(TermIn, TermOut, Module). 559 560rdf_global_term(Var, Var, _M) :- 561 var(Var), 562 !. 563rdf_global_term(Prefix:Local, Global, Module) :- 564 atom(Prefix), atom(Local), 565 rdf_current_prefix(Module:Prefix, Full), 566 !, 567 atom_concat(Full, Local, Global). 568rdf_global_term([H0|T0], [H|T], M) :- 569 !, 570 rdf_global_term(H0, H, M), 571 rdf_global_term(T0, T, M). 572rdf_global_term(Term0, Term, M) :- 573 compound(Term0), 574 !, 575 Term0 =.. [H|L0], 576 rdf_global_term(L0, L, M), 577 Term =.. [H|L]. 578rdf_global_term(Term, Term, _).
584rdf_global_graph(Prefix:Local, Global, Module) :- 585 atom(Prefix), atom(Local), 586 !, 587 global(Prefix, Local, Global, Module). 588rdf_global_graph(G, G, _). 589 590 591 /******************************* 592 * EXPANSION * 593 *******************************/ 594 595:- multifile 596 system:term_expansion/2, 597 system:goal_expansion/2. 598 599systemterm_expansion((:- rdf_meta(Heads)), Clauses) :- 600 prolog_load_context(module, M), 601 phrase(mk_clauses(Heads, M), Clauses). 602 603mk_clauses((A,B), M) --> 604 mk_clause(A, M), 605 mk_clauses(B, M). 606mk_clauses(A, M) --> 607 mk_clause(A, M). 608 609mk_clause(Head0, M0) --> 610 { strip_module(M0:Head0, Module, Head), 611 valid_rdf_meta_head(Head), 612 functor(Head, Name, Arity), 613 functor(Unbound, Name, Arity), 614 qualify(Module, 'rdf meta specification'/2, Decl) 615 }, 616 [ (:- multifile(Decl)), 617 Module:'rdf meta specification'(Unbound, Head) 618 ]. 619 620qualify(Module, Decl, Decl) :- 621 prolog_load_context(module, Module), 622 !. 623qualify(Module, Decl, Module:Decl). 624 625 626valid_rdf_meta_head(Head) :- 627 callable(Head), 628 !, 629 Head =.. [_|Args], 630 valid_args(Args). 631valid_rdf_meta_head(Head) :- 632 throw(error(type_error(callable, Head), _)). 633 634valid_args([]). 635valid_args([H|T]) :- 636 valid_arg(H), 637 !, 638 valid_args(T). 639 640valid_arg(:). % meta argument 641valid_arg(+). % non-var 642valid_arg(-). % var 643valid_arg(?). % either var or non-var 644valid_arg(@). % not modified 645valid_arg(r). % RDF resource 646valid_arg(o). % RDF object 647valid_arg(t). % term with RDF resources 648valid_arg(g). % graph argument 649valid_arg(A) :- 650 throw(error(type_error(rdf_meta_argument, A), _)).
As it is subject to term_expansion/2, the rdf_meta/1 declaration
can only be used as a directive. The directive must be processed
before the definition of the predicates as well as before
compiling code that uses the rdf meta-predicates. The atom
rdf_meta
is declared as an operator exported from
library(semweb/rdf_db)
. Files using rdf_meta/1 must explicitely
load this library.
Beginning with SWI-Prolog 7.3.17, the low-level RDF interface
(rdf/3, rdf_assert/3, etc.) perform runtime expansion of
Prefix:Local
terms. This eliminates the need for rdf_meta/1
for simple cases. However, runtime expansion comes at a
significant overhead and having two representations for IRIs (a
plain atom and a term Prefix:Local
) implies that simple
operations such as comparison of IRIs no longer map to native
Prolog operations such as IRI1 == IRI2
.
706rdf_meta(Heads) :-
707 throw(error(context_error(nodirective, rdf_meta(Heads)), _)).
716rdf_meta_specification(Unbounded, Module, Spec) :- 717 '$flushed_predicate'(Module:'rdf meta specification'(_,_)), 718 call(Module:'rdf meta specification'(Unbounded, Spec)). 719 720systemgoal_expansion(G, Expanded) :- 721 \+ predicate_property(G, iso), 722 prolog_load_context(module, LM), 723 predicate_property(LM:G, implementation_module(IM)), 724 rdf_meta_specification(G, IM, Spec), 725 rdf_expand(G, Spec, Expanded, LM). 726 727systemterm_expansion(Fact, Expanded) :- 728 prolog_load_context(module, Module), 729 rdf_meta_specification(Fact, Module, Spec), 730 rdf_expand(Fact, Spec, Expanded, Module), 731 Fact \== Expanded. 732systemterm_expansion((Head :- Body), (Expanded :- Body)) :- 733 prolog_load_context(module, Module), 734 rdf_meta_specification(Head, Module, Spec), 735 rdf_expand(Head, Spec, Expanded, Module), 736 Head \== Expanded. 737 738rdf_expand(G, Spec, Expanded, M) :- 739 functor(G, Name, Arity), 740 functor(Expanded, Name, Arity), 741 rdf_expand_args(0, Arity, G, Spec, Expanded, M). 742 743rdf_expand_args(Arity, Arity, _, _, _, _) :- !. 744rdf_expand_args(I0, Arity, Goal, Spec, Expanded, M) :- 745 I is I0 + 1, 746 arg(I, Goal, GA), 747 arg(I, Spec, SA), 748 arg(I, Expanded, EA), 749 rdf_expand_arg(SA, GA, EA, M), 750 rdf_expand_args(I, Arity, Goal, Spec, Expanded, M). 751 752rdf_expand_arg(r, A, E, M) :- 753 mk_global(A, E, M), 754 !. 755rdf_expand_arg(o, A, E, M) :- 756 rdf_global_object(A, E, M), 757 !. 758rdf_expand_arg(t, A, E, M) :- 759 rdf_global_term(A, E, M), 760 !. 761rdf_expand_arg(g, A, E, M) :- 762 rdf_global_graph(A, E, M), 763 !. 764rdf_expand_arg(:, A, E, _M) :- 765 !, 766 expand_goal(A, E). 767rdf_expand_arg(_, A, A, _M).
rdf_global_id(+, -)
, but adds compiletime checking,
notably to see whether a namespace is not yet defined.774mk_global(X, X, _) :- 775 var(X), 776 !. 777mk_global(X, X, _) :- 778 atom(X), 779 !. 780mk_global(Prefix:Local, Global, Module) :- 781 must_be(atom, Prefix), 782 must_be(atom, Local), 783 ( rdf_current_prefix(Module:Prefix, Full) 784 -> atom_concat(Full, Local, Global) 785 ; current_prolog_flag(xref, true) 786 -> Global = Prefix:Local 787 ; existence_error(rdf_prefix, Prefix) 788 ). 789 790:- rdf_meta 791 rdf(r,r,o), 792 rdf_has(r,r,o,r), 793 rdf_has(r,r,o), 794 rdf_assert(r,r,o), 795 rdf_retractall(r,r,o), 796 rdf(r,r,o,?), 797 rdf_assert(r,r,o,+), 798 rdf_retractall(r,r,o,?), 799 rdf_reachable(r,r,o), 800 rdf_reachable(r,r,o,+,?), 801 rdf_update(r,r,o,t), 802 rdf_update(r,r,o,+,t), 803 rdf_equal(o,o), 804 rdf_source_location(r,-), 805 rdf_resource(r), 806 rdf_subject(r), 807 rdf_create_graph(r), 808 rdf_graph(r), 809 rdf_graph_property(r,?), 810 rdf_set_graph(r,+), 811 rdf_unload_graph(r), 812 rdf_set_predicate(r, t), 813 rdf_predicate_property(r, -), 814 rdf_estimate_complexity(r,r,r,-), 815 rdf_print_predicate_cloud(r,+).
821rdf_equal(Resource, Resource).
829lang_equal(Lang, Lang) :- !. 830lang_equal(Lang1, Lang2) :- 831 downcase_atom(Lang1, LangCannon), 832 downcase_atom(Lang2, LangCannon).
844 /******************************* 845 * BASIC TRIPLE QUERIES * 846 *******************************/
literal(Value)
if the
object is a literal value. If a value of the form
NameSpaceID:LocalName is provided it is expanded to a ground
atom using expand_goal/2. This implies you can use this
construct in compiled code without paying a performance penalty.
Literal values take one of the following forms:
rdf:datatype
TypeID. The Value is either the textual representation or a
natural Prolog representation. See the option
convert_typed_literal(:Convertor) of the parser. The storage
layer provides efficient handling of atoms, integers (64-bit)
and floats (native C-doubles). All other data is represented
as a Prolog record.
For literal querying purposes, Object can be of the form
literal(+Query, -Value)
, where Query is one of the terms below.
If the Query takes a literal argument and the value has a
numeric type numerical comparison is performed.
icase(Text)
. Backward compatibility.
Backtracking never returns duplicate triples. Duplicates can be
retrieved using rdf/4. The predicate rdf/3 raises a type-error
if called with improper arguments. If rdf/3 is called with a
term literal(_)
as Subject or Predicate object it fails
silently. This allows for graph matching goals like
rdf(S,P,O)
,rdf(O,P2,O2)
to proceed without errors.
rdf(Subject, Predicate, Object)
is true
exploiting the rdfs:subPropertyOf predicate as well as inverse
predicates declared using rdf_set_predicate/2 with the
inverse_of
property.inverse_of(Pred)
.symetric(true)
or inverse_of(P2)
properties.
If used with either Subject or Object unbound, it first returns the origin, followed by the reachable nodes in breath-first search-order. The implementation internally looks one solution ahead and succeeds deterministically on the last solution. This predicate never generates the same node twice and is robust against cycles in the transitive relation.
With all arguments instantiated, it succeeds deterministically if a path can be found from Subject to Object. Searching starts at Subject, assuming the branching factor is normally lower. A call with both Subject and Object unbound raises an instantiation error. The following example generates all subclasses of rdfs:Resource:
?- rdf_reachable(X, rdfs:subClassOf, rdfs:'Resource'). X = 'http://www.w3.org/2000/01/rdf-schema#Resource' ; X = 'http://www.w3.org/2000/01/rdf-schema#Class' ; X = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#Property' ; ...
infinite
to impose no
distance-limit.
1012rdf_subject(Resource) :-
1013 rdf_resource(Resource),
1014 ( rdf(Resource, _, _) -> true ).
This predicate is primarily intended as a way to process all resources without processing resources twice. The user must be aware that some of the returned resources may not appear in any visible triple.
1027 /******************************* 1028 * TRIPLE MODIFICATIONS * 1029 *******************************/
user
. Subject and Predicate are
resources. Object is either a resource or a term literal(Value)
.
See rdf/3 for an explanation of Value for typed and language
qualified literals. All arguments are subject to name-space
expansion. Complete duplicates (including the same graph and
`line' and with a compatible `lifespan') are not added to the
database.literal(Value)
.1081 /******************************* 1082 * COLLECTIONS * 1083 *******************************/
1089term_expansion(member_prefix(x), 1090 member_prefix(Prefix)) :- 1091 rdf_db:ns(rdf, NS), 1092 atom_concat(NS, '_', Prefix). 1093member_prefix(x). 1094 1095rdf_member_property(P, N) :- 1096 integer(N), 1097 !, 1098 member_prefix(Prefix), 1099 atom_concat(Prefix, N, P). 1100rdf_member_property(P, N) :- 1101 member_prefix(Prefix), 1102 atom_concat(Prefix, Sub, P), 1103 atom_number(Sub, N). 1104 1105 1106 /******************************* 1107 * ANONYMOUS SUBJECTS * 1108 *******************************/
1116rdf_node(Resource) :-
1117 rdf_bnode(Resource).
1123rdf_bnode(Value) :- 1124 repeat, 1125 gensym('_:genid', Value), 1126 \+ rdf(Value, _, _), 1127 \+ rdf(_, _, Value), 1128 \+ rdf(_, Value, _), 1129 !. 1130 1131 1132 1133 /******************************* 1134 * TYPES * 1135 *******************************/
_:
. For backward compatibility reason, __
is also
considered to be a blank node.
1154rdf_is_resource(Term) :-
1155 atom(Term).
1162rdf_is_literal(literal(Value)) :- 1163 ground(Value). 1164 1165 /******************************* 1166 * LITERALS * 1167 *******************************/
Plain literals | Atom |
Language tagged literal | Atom holding plain text |
xsd:string | Atom |
rdf:XMLLiteral | XML DOM Tree |
Numeric XSD type | Number |
1192:- rdf_meta 1193 rdf_literal_value(o, -), 1194 typed_value(r, +, -), 1195 numeric_value(r, +, -). 1196 1197rdf_literal_value(literal(String), Value) :- 1198 atom(String), 1199 !, 1200 Value = String. 1201rdf_literal_value(literal(lang(_Lang, String)), String). 1202rdf_literal_value(literal(type(Type, String)), Value) :- 1203 typed_value(Type, String, Value). 1204 1205typed_value(Numeric, String, Value) :- 1206 xsdp_numeric_uri(Numeric, NumType), 1207 !, 1208 numeric_value(NumType, String, Value). 1209typed_value(xsd:string, String, String). 1210typed_value(rdf:'XMLLiteral', Value, DOM) :- 1211 ( atom(Value) 1212 -> setup_call_cleanup( 1213 ( atom_to_memory_file(Value, MF), 1214 open_memory_file(MF, read, In, [free_on_close(true)]) 1215 ), 1216 load_structure(stream(In), DOM, [dialect(xml)]), 1217 close(In)) 1218 ; DOM = Value 1219 ). 1220 1221numeric_value(xsd:integer, String, Value) :- 1222 atom_number(String, Value), 1223 integer(Value). 1224numeric_value(xsd:float, String, Value) :- 1225 atom_number(String, Number), 1226 Value is float(Number). 1227numeric_value(xsd:double, String, Value) :- 1228 atom_number(String, Number), 1229 Value is float(Number). 1230numeric_value(xsd:decimal, String, Value) :- 1231 atom_number(String, Value). 1232 1233 1234 /******************************* 1235 * SOURCE * 1236 *******************************/
1244rdf_source_location(Subject, Source) :- 1245 findall(Source, rdf(Subject, _, _, Source), Sources), 1246 sort(Sources, Unique), 1247 member(Source, Unique). 1248 1249 1250 /******************************* 1251 * GARBAGE COLLECT * 1252 *******************************/
1258:- public 1259 rdf_create_gc_thread/0. 1260 1261rdf_create_gc_thread :- 1262 thread_create(rdf_gc_loop, _, 1263 [ alias('__rdf_GC') 1264 ]).
1271rdf_gc_loop :- 1272 catch(rdf_gc_loop(0), E, recover_gc(E)). 1273 1274recover_gc('$aborted') :- 1275 !, 1276 thread_self(Me), 1277 thread_detach(Me). 1278recover_gc(Error) :- 1279 print_message(error, Error), 1280 rdf_gc_loop. 1281 1282rdf_gc_loop(CPU) :- 1283 repeat, 1284 ( consider_gc(CPU) 1285 -> rdf_gc(CPU1), 1286 sleep(CPU1) 1287 ; sleep(0.1) 1288 ), 1289 fail.
1297rdf_gc(CPU) :-
1298 statistics(cputime, CPU0),
1299 ( rdf_gc_
1300 -> statistics(cputime, CPU1),
1301 CPU is CPU1-CPU0,
1302 rdf_add_gc_time(CPU)
1303 ; CPU = 0.0
1304 ).
Using rdf_gc/0 should only be needed to ensure a fully clean database for analysis purposes such as leak detection.
1316rdf_gc :- 1317 has_garbage, 1318 !, 1319 rdf_gc(_), 1320 rdf_gc. 1321rdf_gc.
1327has_garbage :- 1328 rdf_gc_info_(Info), 1329 has_garbage(Info), 1330 !. 1331 1332has_garbage(Info) :- arg(2, Info, Garbage), Garbage > 0. 1333has_garbage(Info) :- arg(3, Info, Reindexed), Reindexed > 0. 1334has_garbage(Info) :- arg(4, Info, Optimizable), Optimizable > 0.
1341consider_gc(_CPU) :- 1342 ( rdf_gc_info_(gc_info(Triples, % Total #triples in DB 1343 Garbage, % Garbage triples in DB 1344 Reindexed, % Reindexed & not reclaimed 1345 Optimizable, % Non-optimized tables 1346 _KeepGen, % Oldest active generation 1347 _LastGCGen, % Oldest active gen at last GC 1348 _ReindexGen, 1349 _LastGCReindexGen)) 1350 -> ( (Garbage+Reindexed) * 5 > Triples 1351 ; Optimizable > 4 1352 ) 1353 ; print_message(error, rdf(invalid_gc_info)), 1354 sleep(10) 1355 ), 1356 !. 1357 1358 1359 /******************************* 1360 * STATISTICS * 1361 *******************************/
triples
for the interpretation of this value.1406rdf_statistics(graphs(Count)) :- 1407 rdf_statistics_(graphs(Count)). 1408rdf_statistics(triples(Count)) :- 1409 rdf_statistics_(triples(Count)). 1410rdf_statistics(duplicates(Count)) :- 1411 rdf_statistics_(duplicates(Count)). 1412rdf_statistics(lingering(Count)) :- 1413 rdf_statistics_(lingering(Count)). 1414rdf_statistics(resources(Count)) :- 1415 rdf_statistics_(resources(Count)). 1416rdf_statistics(properties(Count)) :- 1417 rdf_statistics_(predicates(Count)). 1418rdf_statistics(literals(Count)) :- 1419 rdf_statistics_(literals(Count)). 1420rdf_statistics(gc(Count, Reclaimed, Reindexed, Time)) :- 1421 rdf_statistics_(gc(Count, Reclaimed, Reindexed, Time)). 1422rdf_statistics(searched_nodes(Count)) :- 1423 rdf_statistics_(searched_nodes(Count)). 1424rdf_statistics(lookup(Index, Count)) :- 1425 functor(Indexed, indexed, 16), 1426 rdf_statistics_(Indexed), 1427 index(Index, I), 1428 Arg is I + 1, 1429 arg(Arg, Indexed, Count), 1430 Count \== 0. 1431rdf_statistics(hash_quality(Index, Size, Quality,Optimize)) :- 1432 rdf_statistics_(hash_quality(List)), 1433 member(hash(Place,Size,Quality,Optimize), List), 1434 index(Index, Place). 1435rdf_statistics(triples_by_graph(Graph, Count)) :- 1436 rdf_graph_(Graph, Count). 1437 1438index(rdf(-,-,-,-), 0). 1439index(rdf(+,-,-,-), 1). 1440index(rdf(-,+,-,-), 2). 1441index(rdf(+,+,-,-), 3). 1442index(rdf(-,-,+,-), 4). 1443index(rdf(+,-,+,-), 5). 1444index(rdf(-,+,+,-), 6). 1445index(rdf(+,+,+,-), 7). 1446 1447index(rdf(-,-,-,+), 8). 1448index(rdf(+,-,-,+), 9). 1449index(rdf(-,+,-,+), 10). 1450index(rdf(+,+,-,+), 11). 1451index(rdf(-,-,+,+), 12). 1452index(rdf(+,-,+,+), 13). 1453index(rdf(-,+,+,+), 14). 1454index(rdf(+,+,+,+), 15). 1455 1456 1457 /******************************* 1458 * PREDICATES * 1459 *******************************/
Note that resources that have rdf:type
rdf:Property
are
not automatically included in the result-set of this predicate,
while all resources that appear as the second argument of a
triple are included.
1475rdf_current_predicate(P, DB) :-
1476 rdf_current_predicate(P),
1477 ( rdf(_,P,_,DB)
1478 -> true
1479 ).
inverse_of(Self)
.rdf_subject_branch_factor
, but also considering
triples of `subPropertyOf' this relation. See also rdf_has/3.rdf_object_branch_factor
, but also considering
triples of `subPropertyOf' this relation. See also rdf_has/3.1532rdf_predicate_property(P, Prop) :- 1533 var(P), 1534 !, 1535 rdf_current_predicate(P), 1536 rdf_predicate_property_(P, Prop). 1537rdf_predicate_property(P, Prop) :- 1538 rdf_predicate_property_(P, Prop).
symmetric(true)
is the same as inverse_of(Predicate)
,
i.e., creating a predicate that is the inverse of
itself.inverse_of([])
.
The transitive
property is currently not used. The symmetric
and inverse_of
properties are considered by rdf_has/3,4 and
rdf_reachable/3.
1563 /******************************* 1564 * SNAPSHOTS * 1565 *******************************/
snapshot
option. A
snapshot created outside a transaction exists until it is
deleted. Snapshots taken inside a transaction can only be used
inside this transaction.1588rdf_current_snapshot(Term) :- 1589 current_blob(Term, rdf_snapshot). 1590 1591 1592 /******************************* 1593 * TRANSACTION * 1594 *******************************/
rdf_transaction(Goal, user, [])
. See rdf_transaction/3.rdf_transaction(Goal, Id, [])
. See rdf_transaction/3.library(semweb/rdf_persistency)
.Processed options are:
true
, which implies that an anonymous snapshot is
created at the current state of the store. Modifications
due to executing Goal are only visible to Goal.1630rdf_transaction(Goal) :- 1631 rdf_transaction(, user, []). 1632rdf_transaction(Goal, Id) :- 1633 rdf_transaction(, Id, []).
1644rdf_active_transaction(Id) :-
1645 rdf_active_transactions_(List),
1646 member(Id, List).
1652rdf_monitor(Goal, Options) :- 1653 monitor_mask(Options, 0xffff, Mask), 1654 rdf_monitor_(Goal, Mask). 1655 1656monitor_mask([], Mask, Mask). 1657monitor_mask([H|T], Mask0, Mask) :- 1658 update_mask(H, Mask0, Mask1), 1659 monitor_mask(T, Mask1, Mask). 1660 1661update_mask(-X, Mask0, Mask) :- 1662 !, 1663 monitor_mask(X, M), 1664 Mask is Mask0 /\ \M. 1665update_mask(+X, Mask0, Mask) :- 1666 !, 1667 monitor_mask(X, M), 1668 Mask is Mask0 \/ M. 1669update_mask(X, Mask0, Mask) :- 1670 monitor_mask(X, M), 1671 Mask is Mask0 \/ M.
1678 % C-defined broadcasts 1679monitor_mask(assert, 0x0001). 1680monitor_mask(assert(load), 0x0002). 1681monitor_mask(retract, 0x0004). 1682monitor_mask(update, 0x0008). 1683monitor_mask(new_literal, 0x0010). 1684monitor_mask(old_literal, 0x0020). 1685monitor_mask(transaction, 0x0040). 1686monitor_mask(load, 0x0080). 1687monitor_mask(create_graph, 0x0100). 1688monitor_mask(reset, 0x0200). 1689 % prolog defined broadcasts 1690monitor_mask(parse, 0x1000). 1691monitor_mask(unload, 0x1000). % FIXME: Duplicate 1692 % mask for all 1693monitor_mask(all, 0xffff). 1694 1695%rdf_broadcast(Term, MaskName) :- 1696%% monitor_mask(MaskName, Mask), 1697%% rdf_broadcast_(Term, Mask). 1698 1699 1700 /******************************* 1701 * WARM * 1702 *******************************/
1708rdf_warm_indexes :- 1709 findall(Index, rdf_index(Index), Indexes), 1710 rdf_warm_indexes(Indexes). 1711 1712rdf_index(s). 1713rdf_index(p). 1714rdf_index(o). 1715rdf_index(sp). 1716rdf_index(o). 1717rdf_index(po). 1718rdf_index(spo). 1719rdf_index(g). 1720rdf_index(sg). 1721rdf_index(pg).
1732 /******************************* 1733 * DUPLICATES * 1734 *******************************/
The duplicates marks are used to reduce the administrative load of avoiding duplicate answers. Normally, the duplicates are marked using a background thread that is started on the first query that produces a substantial amount of duplicates.
1749:- public
1750 rdf_update_duplicates_thread/0.
1756rdf_update_duplicates_thread :-
1757 thread_create(rdf_update_duplicates, _,
1758 [ detached(true),
1759 alias('__rdf_duplicate_detecter')
1760 ]).
This predicate is normally executed from a background thread named =__rdf_duplicate_detecter= which is created when a query discovers that checking for duplicates becomes too expensive.
1774 /******************************* 1775 * QUICK BINARY LOAD/SAVE * 1776 *******************************/
1786:- create_prolog_flag(rdf_triple_format, 3, [type(integer)]). 1787 1788rdf_save_db(File) :- 1789 current_prolog_flag(rdf_triple_format, Version), 1790 setup_call_cleanup( 1791 open(File, write, Out, [type(binary)]), 1792 ( set_stream(Out, record_position(false)), 1793 rdf_save_db_(Out, _, Version) 1794 ), 1795 close(Out)). 1796 1797 1798rdf_save_db(File, Graph) :- 1799 current_prolog_flag(rdf_triple_format, Version), 1800 setup_call_cleanup( 1801 open(File, write, Out, [type(binary)]), 1802 ( set_stream(Out, record_position(false)), 1803 rdf_save_db_(Out, Graph, Version) 1804 ), 1805 close(Out)).
1814rdf_load_db_no_admin(File, Id, Graphs) :-
1815 open(File, read, In, [type(binary)]),
1816 set_stream(In, record_position(false)),
1817 call_cleanup(rdf_load_db_(In, Id, Graphs), close(In)).
1828check_loaded_cache(DB, [DB], _Modified) :- !. 1829check_loaded_cache(DB, Graphs, _) :- 1830 print_message(warning, rdf(inconsistent_cache(DB, Graphs))).
1837rdf_load_db(File) :- 1838 uri_file_name(URL, File), 1839 rdf_load_db_no_admin(File, URL, _Graphs). 1840 1841 1842 /******************************* 1843 * LOADING RDF * 1844 *******************************/ 1845 1846:- multifile 1847 rdf_open_hook/8, 1848 rdf_open_decode/4, % +Encoding, +File, -Stream, -Cleanup 1849 rdf_load_stream/3, % +Format, +Stream, +Options 1850 rdf_file_type/2, % ?Extension, ?Format 1851 rdf_storage_encoding/2, % ?Extension, ?Encoding 1852 url_protocol/1. % ?Protocol
rdf_load(FileOrList, [])
. See rdf_load/2.share
(default),
equivalent blank nodes are shared in the same resource.library(semweb/turtle)
extend the set of recognised
extensions.true
, changed
(default) or
not_loaded
.not_modified
, cached(File)
,
last_modified(Stamp)
or unknown
.false
, do not use or create a cache file.true
(default false
), register xmlns
namespace
declarations or Turtle @prefix
prefixes using
rdf_register_prefix/3 if there is no conflict.true
, the message reporting completion is printed using
level silent
. Otherwise the level is informational
. See
also print_message/2.Other options are forwarded to process_rdf/3. By default, rdf_load/2 only loads RDF/XML from files. It can be extended to load data from other formats and locations using plugins. The full set of plugins relevant to support different formats and locations is below:
:- use_module(library(semweb/turtle)). % Turtle and TRiG :- use_module(library(semweb/rdf_ntriples)). :- use_module(library(semweb/rdf_zlib_plugin)). :- use_module(library(semweb/rdf_http_plugin)). :- use_module(library(http/http_ssl_plugin)).
1934:- dynamic 1935 rdf_loading/3. % Graph, Queue, Thread 1936 1937rdf_load(Spec) :- 1938 rdf_load(Spec, []). 1939 1940:- if(\+current_predicate(concurrent/3)). 1941concurrent(_, Goals, _) :- 1942 forall(member(G, Goals), call()). 1943:- endif. 1944 1945% Note that we kill atom garbage collection. This improves performance 1946% with about 15% loading the LUBM Univ_50 benchmark. 1947 1948rdf_load(Spec, M:Options) :- 1949 must_be(list, Options), 1950 current_prolog_flag(agc_margin, Old), 1951 setup_call_cleanup( 1952 set_prolog_flag(agc_margin, 0), 1953 rdf_load_noagc(Spec, M, Options), 1954 set_prolog_flag(agc_margin, Old)). 1955 1956rdf_load_noagc(List, M, Options) :- 1957 is_list(List), 1958 !, 1959 flatten(List, Inputs), % Compatibility: allow nested lists 1960 maplist(must_be(ground), Inputs), 1961 length(Inputs, Count), 1962 load_jobs(Count, Jobs, Options), 1963 ( Jobs =:= 1 1964 -> forall(member(Spec, Inputs), 1965 rdf_load_one(Spec, M, Options)) 1966 ; maplist(load_goal(Options, M), Inputs, Goals), 1967 concurrent(Jobs, Goals, []) 1968 ). 1969rdf_load_noagc(One, M, Options) :- 1970 must_be(ground, One), 1971 rdf_load_one(One, M, Options). 1972 1973load_goal(Options, M, Spec, rdf_load_one(Spec, M, Options)). 1974 1975load_jobs(_, Jobs, Options) :- 1976 option(concurrent(Jobs), Options), 1977 !, 1978 must_be(positive_integer, Jobs). 1979load_jobs(Count, Jobs, _) :- 1980 current_prolog_flag(cpu_count, CPUs), 1981 CPUs > 0, 1982 !, 1983 Jobs is max(1, min(CPUs, Count)). 1984load_jobs(_, 1, _). 1985 1986 1987rdf_load_one(Spec, M, Options) :- 1988 source_url(Spec, Protocol, SourceURL), 1989 load_graph(SourceURL, Graph, Options), 1990 setup_call_cleanup( 1991 with_mutex(rdf_load_file, 1992 rdf_start_load(SourceURL, Loading)), 1993 rdf_load_file(Loading, Spec, SourceURL, Protocol, 1994 Graph, M, Options), 1995 rdf_end_load(Loading)).
2012rdf_start_load(SourceURL, queue(Queue)) :- 2013 rdf_loading(SourceURL, Queue, LoadThread), 2014 \+ thread_self(LoadThread), 2015 !, 2016 debug(rdf(load), '~p is being loaded by thread ~w; waiting ...', 2017 [ SourceURL, LoadThread]). 2018rdf_start_load(SourceURL, Ref) :- 2019 thread_self(Me), 2020 message_queue_create(Queue), 2021 assertz(rdf_loading(SourceURL, Queue, Me), Ref). 2022 2023rdf_end_load(queue(_)) :- !. 2024rdf_end_load(Ref) :- 2025 clause(rdf_loading(_, Queue, _), _, Ref), 2026 erase(Ref), 2027 thread_send_message(Queue, done), 2028 message_queue_destroy(Queue). 2029 2030rdf_load_file(queue(Queue), _Spec, _SourceURL, _Protocol, _Graph, _M, _Options) :- 2031 !, 2032 catch(thread_get_message(Queue, _), _, true). 2033rdf_load_file(_Ref, _Spec, SourceURL, Protocol, Graph, M, Options) :- 2034 debug(rdf(load), 'RDF: Loading ~q into ~q', [SourceURL, Graph]), 2035 statistics(cputime, T0), 2036 rdf_open_input(SourceURL, Protocol, Graph, 2037 In, Cleanup, Modified, Format, Options), 2038 supported_format(Format, Cleanup), 2039 return_modified(Modified, Options), 2040 ( Modified == not_modified 2041 -> Action = none 2042 ; Modified = cached(CacheFile) 2043 -> do_unload(Graph), 2044 catch(rdf_load_db_no_admin(CacheFile, cache(Graph), Graphs), _, fail), 2045 check_loaded_cache(Graph, Graphs, Modified), 2046 Action = load 2047 ; option(base_uri(BaseURI), Options, Graph), 2048 ( var(BaseURI) 2049 -> BaseURI = SourceURL 2050 ; true 2051 ), 2052 once(phrase(derived_options(Options, NSList), Extra)), 2053 merge_options([ base_uri(BaseURI), 2054 graph(Graph), 2055 format(Format) 2056 | Extra 2057 ], Options, RDFOptions), 2058 do_unload(Graph), 2059 graph_modified(Modified, ModifiedStamp), 2060 rdf_set_graph_source(Graph, SourceURL, ModifiedStamp), 2061 call_cleanup(rdf_load_stream(Format, In, M:RDFOptions), 2062 ), 2063 save_cache(Graph, SourceURL, Options), 2064 register_file_ns(NSList), 2065 format_action(Format, Action) 2066 ), 2067 rdf_statistics_(triples(Graph, Triples)), 2068 report_loaded(Action, SourceURL, Graph, Triples, T0, Options). 2069 2070supported_format(Format, _Cleanup) :- 2071 rdf_file_type(_, Format), 2072 !. 2073supported_format(Format, Cleanup) :- 2074 call(), 2075 existence_error(rdf_format_plugin, Format). 2076 2077format_action(triples, load) :- !. 2078format_action(_, parsed). 2079 2080save_cache(Graph, SourceURL, Options) :- 2081 option(cache(true), Options, true), 2082 rdf_cache_file(SourceURL, write, CacheFile), 2083 !, 2084 catch(save_cache(Graph, CacheFile), E, 2085 print_message(warning, E)). 2086save_cache(_, _, _). 2087 2088derived_options([], _) --> 2089 []. 2090derived_options([H|T], NSList) --> 2091 ( { H == register_namespaces(true) 2092 ; H == (register_namespaces = true) 2093 } 2094 -> [ namespaces(NSList) ] 2095 ; [] 2096 ), 2097 derived_options(T, NSList). 2098 2099graph_modified(last_modified(Stamp), Stamp). 2100graph_modified(unknown, Stamp) :- 2101 get_time(Stamp). 2102 2103return_modified(Modified, Options) :- 2104 option(modified(M0), Options), 2105 !, 2106 M0 = Modified. 2107return_modified(_, _). 2108 2109 2110 /******************************* 2111 * INPUT HANDLING * 2112 *******************************/ 2113 2114/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2115This section deals with pluggable input sources. The task of the input 2116layer is 2117 2118 * Decide on the graph-name 2119 * Decide on the source-location 2120 * Decide whether loading is needed (if-modified) 2121 * Decide on the serialization in the input 2122 2123The protocol must ensure minimal overhead, in particular for network 2124protocols. E.g. for HTTP we want to make a single call on the server and 2125use If-modified-since to verify that we need not reloading this file. 2126- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
Options processed:
graph(Graph)
db(Graph)
if(Condition)
cache(Cache)
format(Format)
2144rdf_open_input(SourceURL, Protocol, Graph,
2145 Stream, Cleanup, Modified, Format, Options) :-
2146 option(if(If), Options, changed),
2147 ( If == true
2148 -> true
2149 ; rdf_graph_source_(Graph, SourceURL, HaveModified)
2150 -> true
2151 ; option(cache(true), Options, true),
2152 rdf_cache_file(SourceURL, read, CacheFile)
2153 -> time_file(CacheFile, HaveModified)
2154 ; true
2155 ),
2156 option(format(Format), Options, _),
2157 open_input_if_modified(Protocol, SourceURL, HaveModified,
2158 Stream, Cleanup, Modified0, Format, Options),
2159 ( Modified0 == not_modified
2160 -> ( nonvar(CacheFile)
2161 -> Modified = cached(CacheFile)
2162 ; Modified = not_modified
2163 )
2164 ; Modified = Modified0
2165 ).
stream(Stream)
http
)2176source_url(stream(In), stream(In), SourceURL) :- 2177 !, 2178 ( stream_property(In, file_name(File)) 2179 -> to_url(File, SourceURL) 2180 ; gensym('stream://', SourceURL) 2181 ). 2182source_url(Stream, Class, SourceURL) :- 2183 is_stream(Stream), 2184 !, 2185 source_url(stream(Stream), Class, SourceURL). 2186source_url(Spec, Protocol, SourceURL) :- 2187 compound(Spec), 2188 !, 2189 source_file(Spec, Protocol, SourceURL). 2190source_url(FileURL, Protocol, SourceURL) :- % or return FileURL? 2191 uri_file_name(FileURL, File), 2192 !, 2193 source_file(File, Protocol, SourceURL). 2194source_url(SourceURL0, Protocol, SourceURL) :- 2195 is_url(SourceURL0, Protocol, SourceURL), 2196 !. 2197source_url(File, Protocol, SourceURL) :- 2198 source_file(File, Protocol, SourceURL). 2199 2200source_file(Spec, file(SExt), SourceURL) :- 2201 findall(Ext, valid_extension(Ext), Exts), 2202 absolute_file_name(Spec, File, [access(read), extensions([''|Exts])]), 2203 storage_extension(_Plain, SExt, File), 2204 uri_file_name(SourceURL, File). 2205 2206to_url(URL, URL) :- 2207 uri_is_global(URL), 2208 !. 2209to_url(File, URL) :- 2210 absolute_file_name(File, Path), 2211 uri_file_name(URL, Path). 2212 2213storage_extension(Plain, SExt, File) :- 2214 file_name_extension(Plain, SExt, File), 2215 SExt \== '', 2216 rdf_storage_encoding(SExt, _), 2217 !. 2218storage_extension(File, '', File).
graph(Graph)
optiondb(Graph)
option (backward compatibility)base_uri(BaseURI)
option2230load_graph(Source, Graph, Options) :- 2231 ( option(graph(Graph), Options) 2232 ; option(db(Graph), Options) 2233 ), 2234 !, 2235 load_graph2(Source, Graph, Options). 2236load_graph(Source, Graph, Options) :- 2237 load_graph2(Source, Graph, Options). 2238 2239load_graph2(_, Graph, _) :- 2240 ground(Graph), 2241 !. 2242load_graph2(_Source, Graph, Options) :- 2243 option(base_uri(Graph), Options), 2244 Graph \== [], 2245 ground(Graph), 2246 !. 2247load_graph2(Source, Graph, _) :- 2248 load_graph(Source, Graph). 2249 2250load_graph(SourceURL, BaseURI) :- 2251 file_name_extension(BaseURI, Ext, SourceURL), 2252 rdf_storage_encoding(Ext, _), 2253 !. 2254load_graph(SourceURL, SourceURL). 2255 2256 2257open_input_if_modified(stream(In), SourceURL, _, In, true, 2258 unknown, Format, _) :- 2259 !, 2260 ( var(Format) 2261 -> guess_format(SourceURL, Format) 2262 ; true 2263 ). 2264open_input_if_modified(file(SExt), SourceURL, HaveModified, Stream, Cleanup, 2265 Modified, Format, _) :- 2266 !, 2267 uri_file_name(SourceURL, File), 2268 ( SExt == '' -> Plain = File; file_name_extension(Plain, SExt, File)), 2269 time_file(File, LastModified), 2270 ( nonvar(HaveModified), 2271 HaveModified >= LastModified 2272 -> Modified = not_modified, 2273 Cleanup = true 2274 ; storage_open(SExt, File, Stream, Cleanup), 2275 Modified = last_modified(LastModified), 2276 ( var(Format) 2277 -> guess_format(Plain, Format) 2278 ; true 2279 ) 2280 ). 2281open_input_if_modified(file, SourceURL, HaveModified, Stream, Cleanup, 2282 Modified, Format, Options) :- 2283 !, 2284 open_input_if_modified(file(''), SourceURL, HaveModified, 2285 Stream, Cleanup, 2286 Modified, Format, Options). 2287open_input_if_modified(Protocol, SourceURL, HaveModified, Stream, Cleanup, 2288 Modified, Format, Options) :- 2289 rdf_open_hook(Protocol, SourceURL, HaveModified, Stream, Cleanup, 2290 Modified, Format, Options). 2291 2292guess_format(File, Format) :- 2293 file_name_extension(_, Ext, File), 2294 ( rdf_file_type(Ext, Format) 2295 -> true 2296 ; Format = xml, 2297 print_message(warning, rdf(guess_format(Ext))) 2298 ).
2306storage_open('', File, Stream, close(Stream)) :- 2307 !, 2308 open(File, read, Stream, [type(binary)]). 2309storage_open(Ext, File, Stream, Cleanup) :- 2310 rdf_storage_encoding(Ext, Encoding), 2311 rdf_open_decode(Encoding, File, Stream, Cleanup). 2312 2313valid_extension(Ext) :- 2314 rdf_file_type(Ext, _). 2315valid_extension(Ext) :- 2316 rdf_storage_encoding(Ext, _).
2326is_url(URL, Scheme, FetchURL) :- 2327 atom(URL), 2328 uri_is_global(URL), 2329 uri_normalized(URL, URL1), % case normalization 2330 uri_components(URL1, Components), 2331 uri_data(scheme, Components, Scheme0), 2332 url_protocol(Scheme0), 2333 !, 2334 Scheme = Scheme0, 2335 uri_data(fragment, Components, _, Components1), 2336 uri_components(FetchURL, Components1). 2337 2338url_protocol(file). % built-in
2346rdf_file_type(xml, xml). 2347rdf_file_type(rdf, xml). 2348rdf_file_type(rdfs, xml). 2349rdf_file_type(owl, xml). 2350rdf_file_type(htm, xhtml). 2351rdf_file_type(html, xhtml). 2352rdf_file_type(xhtml, xhtml). 2353rdf_file_type(trp, triples).
2360rdf_storage_encoding('', plain).
2369rdf_load_stream(xml, Stream, Options) :- 2370 !, 2371 graph(Options, Graph), 2372 rdf_transaction(load_stream(Stream, Options), 2373 parse(Graph)). 2374rdf_load_stream(xhtml, Stream, M:Options) :- 2375 !, 2376 graph(Options, Graph), 2377 rdf_transaction(load_stream(Stream, M:[embedded(true)|Options]), 2378 parse(Graph)). 2379rdf_load_stream(triples, Stream, Options) :- 2380 !, 2381 graph(Options, Graph), 2382 rdf_load_db_(Stream, Graph, _Graphs). 2383 2384load_stream(Stream, M:Options) :- 2385 process_rdf(Stream, assert_triples, M:Options), 2386 option(graph(Graph), Options), 2387 rdf_graph_clear_modified_(Graph).
2392report_loaded(none, _, _, _, _, _) :- !. 2393report_loaded(Action, Source, DB, Triples, T0, Options) :- 2394 statistics(cputime, T1), 2395 Time is T1 - T0, 2396 ( option(silent(true), Options) 2397 -> Level = silent 2398 ; Level = informational 2399 ), 2400 print_message(Level, 2401 rdf(loaded(Action, Source, DB, Triples, Time))).
2414rdf_unload(Spec) :- 2415 source_url(Spec, _Protocol, SourceURL), 2416 rdf_graph_source_(Graph, SourceURL, _), 2417 !, 2418 rdf_unload_graph(Graph). 2419rdf_unload(Graph) :- 2420 atom(Graph), 2421 rdf_graph(Graph), 2422 !, 2423 warn_deprecated_unload(Graph), 2424 rdf_unload_graph(Graph). 2425rdf_unload(_). 2426 2427:- dynamic 2428 warned/0. 2429 2430warn_deprecated_unload(_) :- 2431 warned, 2432 !. 2433warn_deprecated_unload(Graph) :- 2434 assertz(warned), 2435 print_message(warning, rdf(deprecated(rdf_unload(Graph)))).
2443rdf_unload_graph(Graph) :- 2444 must_be(atom, Graph), 2445 ( rdf_graph(Graph) 2446 -> rdf_transaction(do_unload(Graph), unload(Graph)) 2447 ; true 2448 ). 2449 2450do_unload(Graph) :- 2451 ( rdf_graph_(Graph, Triples), 2452 Triples > 0 2453 -> rdf_retractall(_,_,_,Graph) 2454 ; true 2455 ), 2456 rdf_destroy_graph(Graph). 2457 2458 /******************************* 2459 * GRAPH QUERIES * 2460 *******************************/
2472rdf_graph(Graph) :-
2473 rdf_graph_(Graph, _Triples).
2481rdf_source(Graph, SourceURL) :-
2482 rdf_graph(Graph),
2483 rdf_graph_source_(Graph, SourceURL, _Modified).
2491rdf_source(SourceURL) :-
2492 rdf_source(_Graph, SourceURL).
2499rdf_make :- 2500 findall(Source-Graph, modified_graph(Source, Graph), Modified), 2501 forall(member(Source-Graph, Modified), 2502 catch(rdf_load(Source, [graph(Graph), if(changed)]), E, 2503 print_message(error, E))). 2504 2505modified_graph(SourceURL, Graph) :- 2506 rdf_graph(Graph), 2507 rdf_graph_source_(Graph, SourceURL, Modified), 2508 \+ sub_atom(SourceURL, 0, _, _, 'stream://'), 2509 Modified > 0.
modified(false)
.Additional graph properties can be added by defining rules for the multifile predicate property_of_graph/2. Currently, the following extensions are defined:
library(semweb/rdf_persistency)
true
if the graph is persistent.2537rdf_graph_property(Graph, Property) :- 2538 rdf_graph(Graph), 2539 property_of_graph(Property, Graph). 2540 2541:- multifile 2542 property_of_graph/2. 2543 2544property_of_graph(hash(Hash), Graph) :- 2545 rdf_md5(Graph, Hash). 2546property_of_graph(modified(Boolean), Graph) :- 2547 rdf_graph_modified_(Graph, Boolean, _). 2548property_of_graph(source(URL), Graph) :- 2549 rdf_graph_source_(Graph, URL, _). 2550property_of_graph(source_last_modified(Time), Graph) :- 2551 rdf_graph_source_(Graph, _, Time), 2552 Time > 0.0. 2553property_of_graph(triples(Count), Graph) :- 2554 rdf_graph_(Graph, Count).
2563rdf_set_graph(Graph, modified(Modified)) :-
2564 must_be(oneof([false]), Modified),
2565 rdf_graph_clear_modified_(Graph).
2572save_cache(DB, Cache) :-
2573 current_prolog_flag(rdf_triple_format, Version),
2574 setup_call_cleanup(
2575 catch(open(Cache, write, CacheStream, [type(binary)]), _, fail),
2576 rdf_save_db_(CacheStream, DB, Version),
2577 close(CacheStream)).
2585assert_triples([], _). 2586assert_triples([rdf(S,P,O)|T], DB) :- 2587 !, 2588 rdf_assert(S, P, O, DB), 2589 assert_triples(T, DB). 2590assert_triples([H|_], _) :- 2591 throw(error(type_error(rdf_triple, H), _)). 2592 2593 2594 /******************************* 2595 * RESET * 2596 *******************************/
2609rdf_reset_db :- 2610 reset_gensym('_:genid'), 2611 rdf_reset_db_. 2612 2613 2614 /******************************* 2615 * SAVE RDF * 2616 *******************************/
rdf_save(Out, [])
. See rdf_save/2 for details.write_xml_base
optiontrue
(default false
), inline resources when
encountered for the first time. Normally, only bnodes
are handled this way.true
(default false
), emit subjects sorted on
the full URI. Useful to make file comparison easier.false
, do not include the xml:base
declaration that is written normally when using the
base_uri
option.false
(default true
), never use xml attributes to
save plain literal attributes, i.e., always used an XML
element as in <name>Joe</name>
.2678:- thread_local 2679 named_anon/2, % +Resource, -Id 2680 inlined/1. % +Resource 2681 2682rdf_save(File) :- 2683 rdf_save2(File, []). 2684 2685rdf_save(Spec, M:Options0) :- 2686 is_list(Options0), 2687 !, 2688 meta_options(save_meta_option, M:Options0, Options), 2689 to_file(Spec, File), 2690 rdf_save2(File, Options). 2691rdf_save(Spec, _:DB) :- 2692 atom(DB), % backward compatibility 2693 !, 2694 to_file(Spec, File), 2695 rdf_save2(File, [graph(DB)]). 2696 2697save_meta_option(convert_typed_literal). 2698 2699to_file(URL, File) :- 2700 atom(URL), 2701 uri_file_name(URL, File), 2702 !. 2703to_file(File, File). 2704 2705rdf_save2(File, Options) :- 2706 option(encoding(Encoding), Options, utf8), 2707 valid_encoding(Encoding), 2708 open_output(File, Encoding, Out, Close), 2709 flag(rdf_db_saved_subjects, OSavedSubjects, 0), 2710 flag(rdf_db_saved_triples, OSavedTriples, 0), 2711 call_cleanup(rdf_do_save(Out, Options), 2712 Reason, 2713 cleanup_save(Reason, 2714 File, 2715 OSavedSubjects, 2716 OSavedTriples, 2717 Close)). 2718 2719open_output(stream(Out), Encoding, Out, 2720 set_stream(Out, encoding(Old))) :- 2721 !, 2722 stream_property(Out, encoding(Old)), 2723 set_stream(Out, encoding(Encoding)). 2724open_output(File, Encoding, Out, 2725 close(Out)) :- 2726 open(File, write, Out, [encoding(Encoding)]). 2727 2728valid_encoding(Enc) :- 2729 ( xml_encoding_name(Enc, _) 2730 -> true 2731 ; throw(error(domain_error(encoding, Enc), _)) 2732 ). 2733 2734 2735cleanup_save(Reason, 2736 File, 2737 OSavedSubjects, 2738 OSavedTriples, 2739 Close) :- 2740 call(), 2741 flag(rdf_db_saved_subjects, SavedSubjects, OSavedSubjects), 2742 flag(rdf_db_saved_triples, SavedTriples, OSavedTriples), 2743 retractall(named_anon(_, _)), 2744 retractall(inlined(_)), 2745 ( Reason == exit 2746 -> print_message(informational, 2747 rdf(saved(File, SavedSubjects, SavedTriples))) 2748 ; format(user_error, 'Reason = ~w~n', [Reason]) 2749 ). 2750 2751rdf_do_save(Out, Options0) :- 2752 rdf_save_header(Out, Options0, Options), 2753 ( option(sorted(true), Options, false) 2754 -> setof(Subject, rdf_subject(Subject, Options), Subjects), 2755 forall(member(Subject, Subjects), 2756 rdf_save_non_anon_subject(Out, Subject, Options)) 2757 ; forall(rdf_subject(Subject, Options), 2758 rdf_save_non_anon_subject(Out, Subject, Options)) 2759 ), 2760 rdf_save_footer(Out), 2761 !. % dubious cut; without the 2762 % cleanup handlers isn't called!? 2763 2764rdf_subject(Subject, Options) :- 2765 graph(Options, DB), 2766 var(DB), 2767 !, 2768 rdf_subject(Subject). 2769rdf_subject(Subject, Options) :- 2770 graph(Options, DB), 2771 rdf_subject(Subject), 2772 ( rdf(Subject, _, _, DB:_) 2773 -> true 2774 ). 2775 2776graph(Options0, DB) :- 2777 strip_module(Options0, _, Options), 2778 ( memberchk(graph(DB0), Options) 2779 -> DB = DB0 2780 ; memberchk(db(DB0), Options) 2781 -> DB = DB0 2782 ; true % leave unbound 2783 ).
Save an RDF header, with the XML header, DOCTYPE, ENTITY and opening the rdf:RDF element with appropriate namespace declarations. It uses the primitives from section 3.5 to generate the required namespaces and desired short-name. Options is one of:
rdf
and rdfs
are added to the provided List. If a namespace is not
declared, the resource is emitted in non-abreviated form.2808rdf_save_header(Out, Options) :- 2809 rdf_save_header(Out, Options, _). 2810 2811rdf_save_header(Out, Options, OptionsOut) :- 2812 is_list(Options), 2813 !, 2814 stream_property(Out, encoding(Enc)), 2815 xml_encoding(Enc, Encoding), 2816 format(Out, '<?xml version=\'1.0\' encoding=\'~w\'?>~n', [Encoding]), 2817 format(Out, '<!DOCTYPE rdf:RDF [', []), 2818 header_namespaces(Options, NSIdList), 2819 nsmap(NSIdList, NsMap), 2820 append(Options, [nsmap(NsMap)], OptionsOut), 2821 forall(member(Id=URI, NsMap), 2822 ( xml_quote_attribute(URI, NSText0, Enc), 2823 xml_escape_parameter_entity(NSText0, NSText), 2824 format(Out, '~N <!ENTITY ~w \'~w\'>', [Id, NSText]) 2825 )), 2826 format(Out, '~N]>~n~n', []), 2827 format(Out, '<rdf:RDF', []), 2828 ( member(Id, NSIdList), 2829 format(Out, '~N xmlns:~w="&~w;"~n', [Id, Id]), 2830 fail 2831 ; true 2832 ), 2833 ( option(base_uri(Base), Options), 2834 option(write_xml_base(true), Options, true) 2835 -> xml_quote_attribute(Base, BaseText, Enc), 2836 format(Out, '~N xml:base="~w"~n', [BaseText]) 2837 ; true 2838 ), 2839 ( memberchk(document_language(Lang), Options) 2840 -> format(Out, '~N xml:lang="~w"', [Lang]) 2841 ; true 2842 ), 2843 format(Out, '>~n', []). 2844rdf_save_header(Out, FileRef, OptionsOut) :- % compatibility 2845 atom(FileRef), 2846 rdf_save_header(Out, [graph(FileRef)], OptionsOut). 2847 2848xml_encoding(Enc, Encoding) :- 2849 ( xml_encoding_name(Enc, Encoding) 2850 -> true 2851 ; throw(error(domain_error(rdf_encoding, Enc), _)) 2852 ). 2853 2854xml_encoding_name(ascii, 'US-ASCII'). 2855xml_encoding_name(iso_latin_1, 'ISO-8859-1'). 2856xml_encoding_name(utf8, 'UTF-8').
2863nsmap([], []). 2864nsmap([Id|T0], [Id=URI|T]) :- 2865 ns(Id, URI), 2866 nsmap(T0, T).
2872xml_escape_parameter_entity(In, Out) :- 2873 sub_atom(In, _, _, _, '%'), 2874 !, 2875 atom_codes(In, Codes), 2876 phrase(escape_parent(Codes), OutCodes), 2877 atom_codes(Out, OutCodes). 2878xml_escape_parameter_entity(In, In). 2879 2880escape_parent([]) --> []. 2881escape_parent([H|T]) --> 2882 ( { H == 37 } 2883 -> "%" 2884 ; [H] 2885 ), 2886 escape_parent(T).
2893header_namespaces(Options, List) :- 2894 memberchk(namespaces(NSL0), Options), 2895 !, 2896 sort([rdf,rdfs|NSL0], List). 2897header_namespaces(Options, List) :- 2898 graph(Options, DB), 2899 used_namespace_entities(List, DB).
call(Filter, Where, Prefix, URI)
The Where argument gives the location of the prefix ans is
one of subject
, predicate
, object
or type
. The
Prefix argument is the potentionally new prefix and URI is
the full URI that is being processed.
call(Goal,S,P,O,Graph)
2937:- thread_local 2938 graph_prefix/3. 2939:- meta_predicate 2940 rdf_graph_prefixes( , , ). 2941 2942rdf_graph_prefixes(Graph, List) :- 2943 rdf_graph_prefixes(Graph, List, []). 2944 2945rdf_graph_prefixes(Graph, List, M:QOptions) :- 2946 is_list(QOptions), 2947 !, 2948 meta_options(is_meta, M:QOptions, Options), 2949 option(filter(Filter), Options, true), 2950 option(expand(Expand), Options, rdf_db), 2951 option(min_count(MinCount), Options, 1), 2952 option(get_prefix(GetPrefix), Options, iri_xml_namespace), 2953 call_cleanup(prefixes(Expand, Graph, Prefixes, Filter, MinCount, GetPrefix), 2954 retractall(graph_prefix(_,_,_))), 2955 sort(Prefixes, List). 2956rdf_graph_prefixes(Graph, List, M:Filter) :- 2957 rdf_graph_prefixes(Graph, List, M:[filter(Filter)]). 2958 2959is_meta(filter). 2960is_meta(expand). 2961is_meta(get_prefix). 2962 2963 2964prefixes(Expand, Graph, Prefixes, Filter, MinCount, GetPrefix) :- 2965 ( call(Expand, S, P, O, Graph), 2966 add_ns(subject, GetPrefix, Filter, S, MinCount, s(S)), 2967 add_ns(predicate, GetPrefix, Filter, P, MinCount, sp(S,P)), 2968 add_ns_obj(GetPrefix, Filter, O, MinCount, spo(S,P,O)), 2969 fail 2970 ; true 2971 ), 2972 findall(Prefix, graph_prefix(Prefix, MinCount, _), Prefixes). 2973 2974add_ns(Where, GetPrefix, Filter, S, MinCount, Context) :- 2975 \+ rdf_is_bnode(S), 2976 call(GetPrefix, S, Full), 2977 Full \== '', 2978 !, 2979 ( graph_prefix(Full, MinCount, _) 2980 -> true 2981 ; Filter == true 2982 -> add_ns(Full, Context) 2983 ; call(Filter, Where, Full, S) 2984 -> add_ns(Full, Context) 2985 ; true 2986 ). 2987add_ns(_, _, _, _, _, _). 2988 2989add_ns(Full, Context) :- 2990 graph_prefix(Full, _, Contexts), 2991 memberchk(Context, Contexts), 2992 !. 2993add_ns(Full, Context) :- 2994 retract(graph_prefix(Full, C0, Contexts)), 2995 !, 2996 C1 is C0+1, 2997 asserta(graph_prefix(Full, C1, [Context|Contexts])). 2998add_ns(Full, _) :- 2999 ns(_, Full), 3000 !, 3001 asserta(graph_prefix(Full, _, _)). 3002add_ns(Full, Context) :- 3003 asserta(graph_prefix(Full, 1, [Context])). 3004 3005 3006add_ns_obj(GetPrefix, Filter, O, MinCount, Context) :- 3007 atom(O), 3008 !, 3009 add_ns(object, GetPrefix, Filter, O, MinCount, Context). 3010add_ns_obj(GetPrefix, Filter, literal(type(Type, _)), MinCount, _) :- 3011 atom(Type), 3012 !, 3013 add_ns(type, GetPrefix, Filter, Type, MinCount, t(Type)). 3014add_ns_obj(_, _, _, _, _).
3024used_namespace_entities(List, Graph) :- 3025 decl_used_predicate_ns(Graph), 3026 used_namespaces(List, Graph). 3027 3028used_namespaces(List, DB) :- 3029 rdf_graph_prefixes(DB, FullList), 3030 ns_abbreviations(FullList, List0), 3031 sort([rdf|List0], List). 3032 3033ns_abbreviations([], []). 3034ns_abbreviations([H0|T0], [H|T]) :- 3035 ns(H, H0), 3036 !, 3037 ns_abbreviations(T0, T). 3038ns_abbreviations([_|T0], T) :- 3039 ns_abbreviations(T0, T). 3040 3041 3042/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3043For every URL used as a predicate we *MUST* define a namespace as we 3044cannot use names holding /, :, etc. as XML identifiers. 3045- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 3046 3047:- thread_local 3048 predicate_ns/2. 3049 3050decl_used_predicate_ns(DB) :- 3051 retractall(predicate_ns(_,_)), 3052 ( rdf_current_predicate(P, DB), 3053 decl_predicate_ns(P), 3054 fail 3055 ; true 3056 ). 3057 3058decl_predicate_ns(Pred) :- 3059 predicate_ns(Pred, _), 3060 !. 3061decl_predicate_ns(Pred) :- 3062 rdf_global_id(NS:Local, Pred), 3063 xml_name(Local), 3064 !, 3065 assert(predicate_ns(Pred, NS)). 3066decl_predicate_ns(Pred) :- 3067 atom_codes(Pred, Codes), 3068 append(NSCodes, LocalCodes, Codes), 3069 xml_codes(LocalCodes), 3070 !, 3071 ( NSCodes \== [] 3072 -> atom_codes(NS, NSCodes), 3073 ( ns(Id, NS) 3074 -> assert(predicate_ns(Pred, Id)) 3075 ; between(1, infinite, N), 3076 atom_concat(ns, N, Id), 3077 \+ ns(Id, _) 3078 -> rdf_register_ns(Id, NS), 3079 print_message(informational, 3080 rdf(using_namespace(Id, NS))) 3081 ), 3082 assert(predicate_ns(Pred, Id)) 3083 ; assert(predicate_ns(Pred, -)) % no namespace used 3084 ). 3085 3086xml_codes([]). 3087xml_codes([H|T]) :- 3088 xml_code(H), 3089 xml_codes(T). 3090 3091xml_code(X) :- 3092 code_type(X, csym), 3093 !. 3094xml_code(0'-). % Match 0'-
3103rdf_save_footer(Out) :-
3104 retractall(named_anon(_, _)),
3105 retractall(inlined(_)),
3106 format(Out, '</rdf:RDF>~n', []).
anon(false)
is present in the Options list.3113rdf_save_non_anon_subject(_Out, Subject, Options) :- 3114 rdf_is_bnode(Subject), 3115 ( memberchk(anon(false), Options) 3116 ; graph(Options, DB), 3117 rdf_db(_, _, Subject, DB) 3118 ), 3119 !. 3120rdf_save_non_anon_subject(Out, Subject, Options) :- 3121 rdf_save_subject(Out, Subject, Options), 3122 flag(rdf_db_saved_subjects, X, X+1).
3137rdf_save_subject(Out, Subject, Options) :- 3138 is_list(Options), 3139 !, 3140 option(base_uri(BaseURI), Options, '-'), 3141 ( rdf_save_subject(Out, Subject, BaseURI, 0, Options) 3142 -> format(Out, '~n', []) 3143 ; throw(error(rdf_save_failed(Subject), 'Internal error')) 3144 ). 3145rdf_save_subject(Out, Subject, DB) :- 3146 ( var(DB) 3147 -> rdf_save_subject(Out, Subject, []) 3148 ; rdf_save_subject(Out, Subject, [graph(DB)]) 3149 ).
3159rdf_save_subject(_, Subject, _, _, _) :- 3160 inlined(Subject), 3161 !. 3162rdf_save_subject(Out, Subject, BaseURI, Indent, Options) :- 3163 do_save_subject(Out, Subject, BaseURI, Indent, Options). 3164 3165do_save_subject(Out, Subject, BaseURI, Indent, Options) :- 3166 graph(Options, DB), 3167 findall(Pred=Object, rdf_db(Subject, Pred, Object, DB), Atts0), 3168 sort(Atts0, Atts), % remove duplicates 3169 length(Atts, L), 3170 ( length(Atts0, L0), 3171 Del is L0-L, 3172 Del > 0 3173 -> print_message(informational, 3174 rdf(save_removed_duplicates(Del, Subject))) 3175 ; true 3176 ), 3177 rdf_save_subject(Out, Subject, BaseURI, Atts, Indent, Options), 3178 flag(rdf_db_saved_triples, X, X+L). 3179 3180rdf_db(Subject, Pred, Object, DB) :- 3181 var(DB), 3182 !, 3183 rdf(Subject, Pred, Object). 3184rdf_db(Subject, Pred, Object, DB) :- 3185 rdf(Subject, Pred, Object, DB:_).
3192rdf_save_subject(Out, Subject, BaseURI, Atts, Indent, Options) :- 3193 rdf_equal(rdf:type, RdfType), 3194 select(RdfType=Type, Atts, Atts1), 3195 \+ rdf_is_bnode(Type), 3196 rdf_id(Type, BaseURI, TypeId), 3197 xml_is_name(TypeId), 3198 !, 3199 format(Out, '~*|<', [Indent]), 3200 rdf_write_id(Out, TypeId), 3201 save_about(Out, BaseURI, Subject), 3202 save_attributes(Atts1, BaseURI, Out, TypeId, Indent, Options). 3203rdf_save_subject(Out, Subject, BaseURI, Atts, Indent, Options) :- 3204 format(Out, '~*|<rdf:Description', [Indent]), 3205 save_about(Out, BaseURI, Subject), 3206 save_attributes(Atts, BaseURI, Out, rdf:'Description', Indent, Options). 3207 3208xml_is_name(_NS:Atom) :- 3209 !, 3210 xml_name(Atom). 3211xml_is_name(Atom) :- 3212 xml_name(Atom).
3219save_about(Out, _, Subject) :- 3220 rdf_is_bnode(Subject), 3221 !, 3222 ( named_anon(Subject, NodeID) 3223 -> format(Out, ' rdf:nodeID="~w"', [NodeID]) 3224 ; true 3225 ). 3226save_about(Out, BaseURI, Subject) :- 3227 stream_property(Out, encoding(Encoding)), 3228 rdf_value(Subject, BaseURI, QSubject, Encoding), 3229 format(Out, ' rdf:about="~w"', [QSubject]).
3237save_attributes(Atts, BaseURI, Out, Element, Indent, Options) :-
3238 split_attributes(Atts, InTag, InBody, Options),
3239 SubIndent is Indent + 2,
3240 save_attributes2(InTag, BaseURI, tag, Out, SubIndent, Options),
3241 ( InBody == []
3242 -> format(Out, '/>~n', [])
3243 ; format(Out, '>~n', []),
3244 save_attributes2(InBody, BaseURI, body, Out, SubIndent, Options),
3245 format(Out, '~N~*|</', [Indent]),
3246 rdf_write_id(Out, Element),
3247 format(Out, '>~n', [])
3248 ).
3256split_attributes(Atts, [], Atts, Options) :- 3257 option(xml_attributes(false), Options), 3258 !. 3259split_attributes(Atts, HeadAttr, BodyAttr, _) :- 3260 duplicate_attributes(Atts, Dupls, Singles), 3261 simple_literal_attributes(Singles, HeadAttr, Rest), 3262 append(Dupls, Rest, BodyAttr).
3269duplicate_attributes([], [], []). 3270duplicate_attributes([H|T], Dupls, Singles) :- 3271 H = (Name=_), 3272 named_attributes(Name, T, D, R), 3273 D \== [], 3274 append([H|D], Dupls2, Dupls), 3275 !, 3276 duplicate_attributes(R, Dupls2, Singles). 3277duplicate_attributes([H|T], Dupls2, [H|Singles]) :- 3278 duplicate_attributes(T, Dupls2, Singles). 3279 3280named_attributes(_, [], [], []) :- !. 3281named_attributes(Name, [H|T], D, R) :- 3282 ( H = (Name=_) 3283 -> D = [H|DT], 3284 named_attributes(Name, T, DT, R) 3285 ; R = [H|RT], 3286 named_attributes(Name, T, D, RT) 3287 ).
3294simple_literal_attributes([], [], []). 3295simple_literal_attributes([H|TA], [H|TI], B) :- 3296 in_tag_attribute(H), 3297 !, 3298 simple_literal_attributes(TA, TI, B). 3299simple_literal_attributes([H|TA], I, [H|TB]) :- 3300 simple_literal_attributes(TA, I, TB). 3301 3302in_tag_attribute(_=literal(Text)) :- 3303 atom(Text), % may not have lang qualifier 3304 atom_length(Text, Len), 3305 Len < 60.
3311save_attributes2([], _, _, _, _, _). 3312save_attributes2([H|T], BaseURI, Where, Out, Indent, Options) :- 3313 save_attribute(Where, H, BaseURI, Out, Indent, Options), 3314 save_attributes2(T, BaseURI, Where, Out, Indent, Options). 3315 3316save_attribute(tag, Name=literal(Value), BaseURI, Out, Indent, _DB) :- 3317 AttIndent is Indent + 2, 3318 rdf_id(Name, BaseURI, NameText), 3319 stream_property(Out, encoding(Encoding)), 3320 xml_quote_attribute(Value, QVal, Encoding), 3321 format(Out, '~N~*|', [AttIndent]), 3322 rdf_write_id(Out, NameText), 3323 format(Out, '="~w"', [QVal]). 3324save_attribute(body, Name=literal(Literal0), BaseURI, Out, Indent, Options) :- 3325 !, 3326 rdf_id(Name, BaseURI, NameText), 3327 ( memberchk(convert_typed_literal(Converter), Options), 3328 call(Converter, Type, Content, Literal0) 3329 -> Literal = type(Type, Content) 3330 ; Literal = Literal0 3331 ), 3332 save_body_literal(Literal, NameText, BaseURI, Out, Indent, Options). 3333save_attribute(body, Name=Value, BaseURI, Out, Indent, Options) :- 3334 rdf_is_bnode(Value), 3335 !, 3336 rdf_id(Name, BaseURI, NameText), 3337 format(Out, '~N~*|<', [Indent]), 3338 rdf_write_id(Out, NameText), 3339 ( named_anon(Value, NodeID) 3340 -> format(Out, ' rdf:nodeID="~w"/>', [NodeID]) 3341 ; ( rdf(S1, Name, Value), 3342 rdf(S2, P2, Value), 3343 (S1 \== S2 ; Name \== P2) 3344 -> predicate_property(named_anon(_,_), number_of_clauses(N)), 3345 atom_concat('bn', N, NodeID), 3346 assertz(named_anon(Value, NodeID)) 3347 ; true 3348 ), 3349 SubIndent is Indent + 2, 3350 ( rdf_collection(Value) 3351 -> save_about(Out, BaseURI, Value), 3352 format(Out, ' rdf:parseType="Collection">~n', []), 3353 rdf_save_list(Out, Value, BaseURI, SubIndent, Options) 3354 ; format(Out, '>~n', []), 3355 rdf_save_subject(Out, Value, BaseURI, SubIndent, Options) 3356 ), 3357 format(Out, '~N~*|</', [Indent]), 3358 rdf_write_id(Out, NameText), 3359 format(Out, '>~n', []) 3360 ). 3361save_attribute(body, Name=Value, BaseURI, Out, Indent, Options) :- 3362 option(inline(true), Options), 3363 has_attributes(Value, Options), 3364 \+ inlined(Value), 3365 !, 3366 assertz(inlined(Value)), 3367 rdf_id(Name, BaseURI, NameText), 3368 format(Out, '~N~*|<', [Indent]), 3369 rdf_write_id(Out, NameText), 3370 SubIndent is Indent + 2, 3371 ( rdf_collection(Value) 3372 -> save_about(Out, BaseURI, Value), 3373 format(Out, ' rdf:parseType="Collection">~n', []), 3374 rdf_save_list(Out, Value, BaseURI, SubIndent, Options) 3375 ; format(Out, '>~n', []), 3376 do_save_subject(Out, Value, BaseURI, SubIndent, Options) 3377 ), 3378 format(Out, '~N~*|</', [Indent]), 3379 rdf_write_id(Out, NameText), 3380 format(Out, '>~n', []). 3381save_attribute(body, Name=Value, BaseURI, Out, Indent, _DB) :- 3382 stream_property(Out, encoding(Encoding)), 3383 rdf_value(Value, BaseURI, QVal, Encoding), 3384 rdf_id(Name, BaseURI, NameText), 3385 format(Out, '~N~*|<', [Indent]), 3386 rdf_write_id(Out, NameText), 3387 format(Out, ' rdf:resource="~w"/>', [QVal]). 3388 3389has_attributes(URI, Options) :- 3390 graph(Options, DB), 3391 rdf_db(URI, _, _, DB), 3392 !.
3397save_body_literal(lang(Lang, Value), 3398 NameText, BaseURI, Out, Indent, Options) :- 3399 !, 3400 format(Out, '~N~*|<', [Indent]), 3401 rdf_write_id(Out, NameText), 3402 ( memberchk(document_language(Lang), Options) 3403 -> write(Out, '>') 3404 ; rdf_id(Lang, BaseURI, LangText), 3405 format(Out, ' xml:lang="~w">', [LangText]) 3406 ), 3407 save_attribute_value(Value, Out, Indent), 3408 write(Out, '</'), rdf_write_id(Out, NameText), write(Out, '>'). 3409save_body_literal(type(Type, DOM), 3410 NameText, _BaseURI, Out, Indent, Options) :- 3411 rdf_equal(Type, rdf:'XMLLiteral'), 3412 !, 3413 ( atom(DOM) 3414 -> format(Out, '~N~*|<', [Indent]), 3415 rdf_write_id(Out, NameText), 3416 format(Out, ' rdf:parseType="Literal">~w</', [DOM]), 3417 rdf_write_id(Out, NameText), write(Out, '>') 3418 ; save_xml_literal(DOM, NameText, Out, Indent, Options) 3419 ). 3420save_body_literal(type(Type, Value), 3421 NameText, BaseURI, Out, Indent, _) :- 3422 !, 3423 format(Out, '~N~*|<', [Indent]), 3424 rdf_write_id(Out, NameText), 3425 stream_property(Out, encoding(Encoding)), 3426 rdf_value(Type, BaseURI, QVal, Encoding), 3427 format(Out, ' rdf:datatype="~w">', [QVal]), 3428 save_attribute_value(Value, Out, Indent), 3429 write(Out, '</'), rdf_write_id(Out, NameText), write(Out, '>'). 3430save_body_literal(Literal, 3431 NameText, _, Out, Indent, _) :- 3432 atomic(Literal), 3433 !, 3434 format(Out, '~N~*|<', [Indent]), 3435 rdf_write_id(Out, NameText), 3436 write(Out, '>'), 3437 save_attribute_value(Literal, Out, Indent), 3438 write(Out, '</'), rdf_write_id(Out, NameText), write(Out, '>'). 3439save_body_literal(DOM, 3440 NameText, BaseURI, Out, Indent, Options) :- 3441 rdf_equal(Type, rdf:'XMLLiteral'), 3442 save_body_literal(type(Type, DOM), 3443 NameText, BaseURI, Out, Indent, Options). 3444 3445save_attribute_value(Value, Out, _) :- % strings 3446 atom(Value), 3447 !, 3448 stream_property(Out, encoding(Encoding)), 3449 xml_quote_cdata(Value, QVal, Encoding), 3450 write(Out, QVal). 3451save_attribute_value(Value, Out, _) :- % numbers 3452 number(Value), 3453 !, 3454 writeq(Out, Value). % quoted: preserve floats 3455save_attribute_value(Value, _Out, _) :- 3456 throw(error(save_attribute_value(Value), _)).
<prop parseType="literal"
but not the terminating >
. We need to establish the
namespaces used in the DOM. The namespaces in the rdf document
are in the nsmap-option of Options.
3470save_xml_literal(DOM, Attr, Out, Indent, Options) :- 3471 xml_is_dom(DOM), 3472 !, 3473 memberchk(nsmap(NsMap), Options), 3474 id_to_atom(Attr, Atom), 3475 xml_write(Out, 3476 element(Atom, ['rdf:parseType'='Literal'], DOM), 3477 [ header(false), 3478 indent(Indent), 3479 nsmap(NsMap) 3480 ]). 3481save_xml_literal(NoDOM, _, _, _, _) :- 3482 must_be(xml_dom, NoDOM). 3483 3484id_to_atom(NS:Local, Atom) :- 3485 !, 3486 atomic_list_concat([NS,Local], :, Atom). 3487id_to_atom(ID, ID).
3497:- rdf_meta 3498 rdf_collection(r), 3499 collection_p(r,r). 3500 3501rdf_collection(rdf:nil) :- !. 3502rdf_collection(Cell) :- 3503 rdf_is_bnode(Cell), 3504 findall(F, rdf(Cell, rdf:first, F), [_]), 3505 findall(F, rdf(Cell, rdf:rest, F), [Rest]), 3506 forall(rdf(Cell, P, V), 3507 collection_p(P, V)), 3508 rdf_collection(Rest). 3509 3510collection_p(rdf:first, V) :- atom(V). 3511collection_p(rdf:rest, _). 3512collection_p(rdf:type, rdf:'List').
3517rdf_save_list(_, List, _, _, _) :- 3518 rdf_equal(List, rdf:nil), 3519 !. 3520rdf_save_list(Out, List, BaseURI, Indent, Options) :- 3521 rdf_has(List, rdf:first, First), 3522 ( rdf_is_bnode(First) 3523 -> nl(Out), 3524 rdf_save_subject(Out, First, BaseURI, Indent, Options) 3525 ; stream_property(Out, encoding(Encoding)), 3526 rdf_value(First, BaseURI, QVal, Encoding), 3527 format(Out, '~N~*|<rdf:Description rdf:about="~w"/>', 3528 [Indent, QVal]) 3529 ), 3530 flag(rdf_db_saved_triples, X, X+3), 3531 ( rdf_has(List, rdf:rest, List2), 3532 \+ rdf_equal(List2, rdf:nil) 3533 -> rdf_save_list(Out, List2, BaseURI, Indent, Options) 3534 ; true 3535 ).
3543rdf_id(Id, BaseURI, Local) :- 3544 assertion(atom(BaseURI)), 3545 atom_concat(BaseURI, Local, Id), 3546 sub_atom(Local, 0, 1, _, #), 3547 !. 3548rdf_id(Id, _, NS:Local) :- 3549 iri_xml_namespace(Id, Full, Local), 3550 ns(NS, Full), 3551 !. 3552rdf_id(Id, _, NS:Local) :- 3553 ns(NS, Full), 3554 Full \== '', 3555 atom_concat(Full, Local, Id), 3556 !. 3557rdf_id(Id, _, Id).
3565rdf_write_id(Out, NS:Local) :- 3566 !, 3567 format(Out, '~w:~w', [NS, Local]). 3568rdf_write_id(Out, Atom) :- 3569 write(Out, Atom).
3578rdf_value(Base, Base, '', _) :- !. 3579rdf_value(V, Base, Text, Encoding) :- 3580 atom_concat(Base, Local, V), 3581 sub_atom(Local, 0, _, _, #), 3582 !, 3583 xml_quote_attribute(Local, Text, Encoding). 3584rdf_value(V, _, Text, Encoding) :- 3585 ns(NS, Full), 3586 atom_concat(Full, Local, V), 3587 xml_is_name(Local), 3588 !, 3589 xml_quote_attribute(Local, QLocal, Encoding), 3590 atomic_list_concat(['&', NS, (';'), QLocal], Text). 3591rdf_value(V, _, Q, Encoding) :- 3592 xml_quote_attribute(V, Q, Encoding). 3593 3594 3595 /******************************* 3596 * MATCH AND COMPARE * 3597 *******************************/
icase
, substring
, word
, prefix
or like
. For backward
compatibility, exact
is a synonym for icase
.3620 /******************************* 3621 * DEPRECATED MATERIAL * 3622 *******************************/
library(sgml)
.
3632rdf_split_url(Prefix, Local, URL) :- 3633 atomic(URL), 3634 !, 3635 iri_xml_namespace(URL, Prefix, Local). 3636rdf_split_url(Prefix, Local, URL) :- 3637 atom_concat(Prefix, Local, URL).
3645rdf_url_namespace(URL, Prefix) :- 3646 iri_xml_namespace(URL, Prefix). 3647 3648 3649 /******************************* 3650 * LITERALS * 3651 *******************************/
rdf_litindex.pl
.not(Key)
. If not-terms are provided, there
must be at least one positive keywords. The negations are tested
after establishing the positive matches.key(+Key)
Succeeds if Key is a key in the map and unify Answer with the
number of values associated with the key. This provides a fast
test of existence without fetching the possibly large
associated value set as with rdf_find_literal_map/3.prefix(+Prefix)
Unify Answer with an ordered set of all keys that have the
given prefix. See section 3.1 for details on prefix matching.
Prefix must be an atom. This call is intended for
auto-completion in user interfaces.ge(+Min)
Unify Answer with all keys that are larger or equal to the
integer Min.le(+Max)
Unify Answer with all keys that are smaller or equal to the integer
Max.between(+Min, +Max)
Unify
Answer with all keys between Min and Max (including).3739 /******************************* 3740 * MISC * 3741 *******************************/
Major*10000 + Minor*100 + Patch.
s
,
p
, sp
, o
, po
, spo
, g
, sg
or pg
. Parameter
is one of:
permission_error
exception.When inside a transaction, Generation is unified to a term TransactionStartGen + InsideTransactionGen. E.g., 4+3 means that the transaction was started at generation 4 of the global database and we have created 3 new generations inside the transaction. Note that this choice of representation allows for comparing generations using Prolog arithmetic. Comparing a generation in one transaction with a generation in another transaction is meaningless.
3835 /******************************* 3836 * MESSAGES * 3837 *******************************/ 3838 3839:- multifile 3840 prolog:message//1. 3841 3842prologmessage(rdf(Term)) --> 3843 message(Term). 3844 3845message(loaded(How, What, BaseURI, Triples, Time)) --> 3846 how(How), 3847 source(What), 3848 into(What, BaseURI), 3849 in_time(Triples, Time). 3850message(save_removed_duplicates(N, Subject)) --> 3851 [ 'Removed ~d duplicate triples about "~p"'-[N,Subject] ]. 3852message(saved(File, SavedSubjects, SavedTriples)) --> 3853 [ 'Saved ~D triples about ~D subjects into ~p'- 3854 [SavedTriples, SavedSubjects, File] 3855 ]. 3856message(using_namespace(Id, NS)) --> 3857 [ 'Using namespace id ~w for ~w'-[Id, NS] ]. 3858message(inconsistent_cache(DB, Graphs)) --> 3859 [ 'RDF cache file for ~w contains the following graphs'-[DB], nl, 3860 '~t~8|~p'-[Graphs] 3861 ]. 3862message(guess_format(Ext)) --> 3863 [ 'Unknown file-extension: ~w. Assuming RDF/XML'-[Ext] ]. 3864message(meta(not_expanded(G))) --> 3865 [ 'rdf_meta/1: ~p is not expanded'-[G] ]. 3866message(deprecated(rdf_unload(Graph))) --> 3867 [ 'rdf_unload/1: Use ~q'-[rdf_unload_graph(Graph)] ]. 3868 3869 3870how(load) --> [ 'Loaded' ]. 3871how(parsed) --> [ 'Parsed' ]. 3872 3873source(SourceURL) --> 3874 { uri_file_name(SourceURL, File), 3875 !, 3876 file_base_name(File, Base) % TBD: relative file? 3877 }, 3878 [ ' "~w"'-[Base] ]. 3879source(SourceURL) --> 3880 [ ' "~w"'-[SourceURL] ]. 3881 3882into(_, _) --> []. % TBD 3883 3884in_time(Triples, ParseTime) --> 3885 [ ' in ~2f sec; ~D triples'-[ParseTime, Triples] 3886 ]
Core RDF database
The file
library(semweb/rdf_db)
provides the core of the SWI-Prolog RDF store.library(semweb/rdf11)
, which provides a much more intuitive API to the RDF store, notably for handling literals. Thelibrary(semweb/rdf11)
runs currently on top of this library and both can run side-by-side in the same application. Terms retrieved from the database however have a different shape and can not be exchanged without precautions. */