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.
558rdf_global_term(TermIn, Module:TermOut) :- 559 rdf_global_term(TermIn, TermOut, Module). 560 561rdf_global_term(Var, Var, _M) :- 562 var(Var), 563 !. 564rdf_global_term(Prefix:Local, Global, Module) :- 565 atom(Prefix), atom(Local), 566 rdf_current_prefix(Module:Prefix, Full), 567 !, 568 atom_concat(Full, Local, Global). 569rdf_global_term([H0|T0], [H|T], M) :- 570 !, 571 rdf_global_term(H0, H, M), 572 rdf_global_term(T0, T, M). 573rdf_global_term(Term0, Term, M) :- 574 compound(Term0), 575 !, 576 Term0 =.. [H|L0], 577 rdf_global_term(L0, L, M), 578 Term =.. [H|L]. 579rdf_global_term(Term, Term, _).
585rdf_global_graph(Prefix:Local, Global, Module) :- 586 atom(Prefix), atom(Local), 587 !, 588 global(Prefix, Local, Global, Module). 589rdf_global_graph(G, G, _). 590 591 592 /******************************* 593 * EXPANSION * 594 *******************************/ 595 596:- multifile 597 system:term_expansion/2, 598 system:goal_expansion/2. 599 600systemterm_expansion((:- rdf_meta(Heads)), Clauses) :- 601 prolog_load_context(module, M), 602 phrase(mk_clauses(Heads, M), Clauses). 603 604mk_clauses((A,B), M) --> 605 mk_clause(A, M), 606 mk_clauses(B, M). 607mk_clauses(A, M) --> 608 mk_clause(A, M). 609 610mk_clause(Head0, M0) --> 611 { strip_module(M0:Head0, Module, Head), 612 valid_rdf_meta_head(Head), 613 functor(Head, Name, Arity), 614 functor(Unbound, Name, Arity), 615 qualify(Module, 'rdf meta specification'/2, Decl) 616 }, 617 [ (:- multifile(Decl)), 618 Module:'rdf meta specification'(Unbound, Head) 619 ]. 620 621qualify(Module, Decl, Decl) :- 622 prolog_load_context(module, Module), 623 !. 624qualify(Module, Decl, Module:Decl). 625 626 627valid_rdf_meta_head(Head) :- 628 callable(Head), 629 !, 630 Head =.. [_|Args], 631 valid_args(Args). 632valid_rdf_meta_head(Head) :- 633 throw(error(type_error(callable, Head), _)). 634 635valid_args([]). 636valid_args([H|T]) :- 637 valid_arg(H), 638 !, 639 valid_args(T). 640 641valid_arg(:). % meta argument 642valid_arg(+). % non-var 643valid_arg(-). % var 644valid_arg(?). % either var or non-var 645valid_arg(@). % not modified 646valid_arg(r). % RDF resource 647valid_arg(o). % RDF object 648valid_arg(t). % term with RDF resources 649valid_arg(g). % graph argument 650valid_arg(A) :- 651 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
.
707rdf_meta(Heads) :-
708 throw(error(context_error(nodirective, rdf_meta(Heads)), _)).
717rdf_meta_specification(Unbounded, Module, Spec) :- 718 '$flushed_predicate'(Module:'rdf meta specification'(_,_)), 719 call(Module:'rdf meta specification'(Unbounded, Spec)). 720 721systemgoal_expansion(G, Expanded) :- 722 \+ predicate_property(G, iso), 723 prolog_load_context(module, LM), 724 predicate_property(LM:G, implementation_module(IM)), 725 rdf_meta_specification(G, IM, Spec), 726 rdf_expand(G, Spec, Expanded, LM). 727 728systemterm_expansion(Fact, Expanded) :- 729 prolog_load_context(module, Module), 730 rdf_meta_specification(Fact, Module, Spec), 731 rdf_expand(Fact, Spec, Expanded, Module), 732 Fact \== Expanded. 733systemterm_expansion((Head :- Body), (Expanded :- Body)) :- 734 prolog_load_context(module, Module), 735 rdf_meta_specification(Head, Module, Spec), 736 rdf_expand(Head, Spec, Expanded, Module), 737 Head \== Expanded. 738 739rdf_expand(G, Spec, Expanded, M) :- 740 functor(G, Name, Arity), 741 functor(Expanded, Name, Arity), 742 rdf_expand_args(0, Arity, G, Spec, Expanded, M). 743 744rdf_expand_args(Arity, Arity, _, _, _, _) :- !. 745rdf_expand_args(I0, Arity, Goal, Spec, Expanded, M) :- 746 I is I0 + 1, 747 arg(I, Goal, GA), 748 arg(I, Spec, SA), 749 arg(I, Expanded, EA), 750 rdf_expand_arg(SA, GA, EA, M), 751 rdf_expand_args(I, Arity, Goal, Spec, Expanded, M). 752 753rdf_expand_arg(r, A, E, M) :- 754 mk_global(A, E, M), 755 !. 756rdf_expand_arg(o, A, E, M) :- 757 rdf_global_object(A, E, M), 758 !. 759rdf_expand_arg(t, A, E, M) :- 760 rdf_global_term(A, E, M), 761 !. 762rdf_expand_arg(g, A, E, M) :- 763 rdf_global_graph(A, E, M), 764 !. 765rdf_expand_arg(:, A, E, _M) :- 766 !, 767 expand_goal(A, E). 768rdf_expand_arg(_, A, A, _M).
rdf_global_id(+, -)
, but adds compiletime checking,
notably to see whether a namespace is not yet defined.775mk_global(X, X, _) :- 776 var(X), 777 !. 778mk_global(X, X, _) :- 779 atom(X), 780 !. 781mk_global(Prefix:Local, Global, Module) :- 782 must_be(atom, Prefix), 783 must_be(atom, Local), 784 ( rdf_current_prefix(Module:Prefix, Full) 785 -> atom_concat(Full, Local, Global) 786 ; current_prolog_flag(xref, true) 787 -> Global = Prefix:Local 788 ; existence_error(rdf_prefix, Prefix) 789 ). 790 791:- rdf_meta 792 rdf(r,r,o), 793 rdf_has(r,r,o,r), 794 rdf_has(r,r,o), 795 rdf_assert(r,r,o), 796 rdf_retractall(r,r,o), 797 rdf(r,r,o,?), 798 rdf_assert(r,r,o,+), 799 rdf_retractall(r,r,o,?), 800 rdf_reachable(r,r,o), 801 rdf_reachable(r,r,o,+,?), 802 rdf_update(r,r,o,t), 803 rdf_update(r,r,o,+,t), 804 rdf_equal(o,o), 805 rdf_source_location(r,-), 806 rdf_resource(r), 807 rdf_subject(r), 808 rdf_create_graph(r), 809 rdf_graph(r), 810 rdf_graph_property(r,?), 811 rdf_set_graph(r,+), 812 rdf_unload_graph(r), 813 rdf_set_predicate(r, t), 814 rdf_predicate_property(r, -), 815 rdf_estimate_complexity(r,r,r,-), 816 rdf_print_predicate_cloud(r,+).
822rdf_equal(Resource, Resource).
830lang_equal(Lang, Lang) :- !. 831lang_equal(Lang1, Lang2) :- 832 downcase_atom(Lang1, LangCannon), 833 downcase_atom(Lang2, LangCannon).
845 /******************************* 846 * BASIC TRIPLE QUERIES * 847 *******************************/
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.
1013rdf_subject(Resource) :-
1014 rdf_resource(Resource),
1015 ( 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.
1028 /******************************* 1029 * TRIPLE MODIFICATIONS * 1030 *******************************/
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)
.1082 /******************************* 1083 * COLLECTIONS * 1084 *******************************/
1090term_expansion(member_prefix(x), 1091 member_prefix(Prefix)) :- 1092 rdf_db:ns(rdf, NS), 1093 atom_concat(NS, '_', Prefix). 1094member_prefix(x). 1095 1096rdf_member_property(P, N) :- 1097 integer(N), 1098 !, 1099 member_prefix(Prefix), 1100 atom_concat(Prefix, N, P). 1101rdf_member_property(P, N) :- 1102 member_prefix(Prefix), 1103 atom_concat(Prefix, Sub, P), 1104 atom_number(Sub, N). 1105 1106 1107 /******************************* 1108 * ANONYMOUS SUBJECTS * 1109 *******************************/
1117rdf_node(Resource) :-
1118 rdf_bnode(Resource).
1124rdf_bnode(Value) :- 1125 repeat, 1126 gensym('_:genid', Value), 1127 \+ rdf(Value, _, _), 1128 \+ rdf(_, _, Value), 1129 \+ rdf(_, Value, _), 1130 !. 1131 1132 1133 1134 /******************************* 1135 * TYPES * 1136 *******************************/
_:
. For backward compatibility reason, __
is also
considered to be a blank node.
1155rdf_is_resource(Term) :-
1156 atom(Term).
1163rdf_is_literal(literal(Value)) :- 1164 ground(Value). 1165 1166 /******************************* 1167 * LITERALS * 1168 *******************************/
Plain literals | Atom |
Language tagged literal | Atom holding plain text |
xsd:string | Atom |
rdf:XMLLiteral | XML DOM Tree |
Numeric XSD type | Number |
1193:- rdf_meta 1194 rdf_literal_value(o, -), 1195 typed_value(r, +, -), 1196 numeric_value(r, +, -). 1197 1198rdf_literal_value(literal(String), Value) :- 1199 atom(String), 1200 !, 1201 Value = String. 1202rdf_literal_value(literal(lang(_Lang, String)), String). 1203rdf_literal_value(literal(type(Type, String)), Value) :- 1204 typed_value(Type, String, Value). 1205 1206typed_value(Numeric, String, Value) :- 1207 xsdp_numeric_uri(Numeric, NumType), 1208 !, 1209 numeric_value(NumType, String, Value). 1210typed_value(xsd:string, String, String). 1211typed_value(rdf:'XMLLiteral', Value, DOM) :- 1212 ( atom(Value) 1213 -> setup_call_cleanup( 1214 ( atom_to_memory_file(Value, MF), 1215 open_memory_file(MF, read, In, [free_on_close(true)]) 1216 ), 1217 load_structure(stream(In), DOM, [dialect(xml)]), 1218 close(In)) 1219 ; DOM = Value 1220 ). 1221 1222numeric_value(xsd:integer, String, Value) :- 1223 atom_number(String, Value), 1224 integer(Value). 1225numeric_value(xsd:float, String, Value) :- 1226 atom_number(String, Number), 1227 Value is float(Number). 1228numeric_value(xsd:double, String, Value) :- 1229 atom_number(String, Number), 1230 Value is float(Number). 1231numeric_value(xsd:decimal, String, Value) :- 1232 atom_number(String, Value). 1233 1234 1235 /******************************* 1236 * SOURCE * 1237 *******************************/
1245rdf_source_location(Subject, Source) :- 1246 findall(Source, rdf(Subject, _, _, Source), Sources), 1247 sort(Sources, Unique), 1248 member(Source, Unique). 1249 1250 1251 /******************************* 1252 * GARBAGE COLLECT * 1253 *******************************/
1259:- public 1260 rdf_create_gc_thread/0. 1261 1262rdf_create_gc_thread :- 1263 thread_create(rdf_gc_loop, _, 1264 [ alias('__rdf_GC') 1265 ]).
1272rdf_gc_loop :- 1273 catch(rdf_gc_loop(0), E, recover_gc(E)). 1274 1275recover_gc('$aborted') :- 1276 !, 1277 thread_self(Me), 1278 thread_detach(Me). 1279recover_gc(Error) :- 1280 print_message(error, Error), 1281 rdf_gc_loop. 1282 1283rdf_gc_loop(CPU) :- 1284 repeat, 1285 ( consider_gc(CPU) 1286 -> rdf_gc(CPU1), 1287 sleep(CPU1) 1288 ; sleep(0.1) 1289 ), 1290 fail.
1298rdf_gc(CPU) :-
1299 statistics(cputime, CPU0),
1300 ( rdf_gc_
1301 -> statistics(cputime, CPU1),
1302 CPU is CPU1-CPU0,
1303 rdf_add_gc_time(CPU)
1304 ; CPU = 0.0
1305 ).
Using rdf_gc/0 should only be needed to ensure a fully clean database for analysis purposes such as leak detection.
1317rdf_gc :- 1318 has_garbage, 1319 !, 1320 rdf_gc(_), 1321 rdf_gc. 1322rdf_gc.
1328has_garbage :- 1329 rdf_gc_info_(Info), 1330 has_garbage(Info), 1331 !. 1332 1333has_garbage(Info) :- arg(2, Info, Garbage), Garbage > 0. 1334has_garbage(Info) :- arg(3, Info, Reindexed), Reindexed > 0. 1335has_garbage(Info) :- arg(4, Info, Optimizable), Optimizable > 0.
1342consider_gc(_CPU) :- 1343 ( rdf_gc_info_(gc_info(Triples, % Total #triples in DB 1344 Garbage, % Garbage triples in DB 1345 Reindexed, % Reindexed & not reclaimed 1346 Optimizable, % Non-optimized tables 1347 _KeepGen, % Oldest active generation 1348 _LastGCGen, % Oldest active gen at last GC 1349 _ReindexGen, 1350 _LastGCReindexGen)) 1351 -> ( (Garbage+Reindexed) * 5 > Triples 1352 ; Optimizable > 4 1353 ) 1354 ; print_message(error, rdf(invalid_gc_info)), 1355 sleep(10) 1356 ), 1357 !. 1358 1359 1360 /******************************* 1361 * STATISTICS * 1362 *******************************/
triples
for the interpretation of this value.1408rdf_statistics(graphs(Count)) :- 1409 rdf_statistics_(graphs(Count)). 1410rdf_statistics(triples(Count)) :- 1411 rdf_statistics_(triples(Count)). 1412rdf_statistics(duplicates(Count)) :- 1413 rdf_statistics_(duplicates(Count)). 1414rdf_statistics(lingering(Count)) :- 1415 rdf_statistics_(lingering(Count)). 1416rdf_statistics(resources(Count)) :- 1417 rdf_statistics_(resources(Count)). 1418rdf_statistics(properties(Count)) :- 1419 rdf_statistics_(predicates(Count)). 1420rdf_statistics(literals(Count)) :- 1421 rdf_statistics_(literals(Count)). 1422rdf_statistics(gc(Count, Reclaimed, Reindexed, Time)) :- 1423 rdf_statistics_(gc(Count, Reclaimed, Reindexed, Time)). 1424rdf_statistics(searched_nodes(Count)) :- 1425 rdf_statistics_(searched_nodes(Count)). 1426rdf_statistics(lookup(Index, Count)) :- 1427 functor(Indexed, indexed, 16), 1428 rdf_statistics_(Indexed), 1429 index(Index, I), 1430 Arg is I + 1, 1431 arg(Arg, Indexed, Count), 1432 Count \== 0. 1433rdf_statistics(hash_quality(Index, Size, Quality,Optimize)) :- 1434 rdf_statistics_(hash_quality(List)), 1435 member(hash(Place,Size,Quality,Optimize), List), 1436 index(Index, Place). 1437rdf_statistics(triples_by_graph(Graph, Count)) :- 1438 rdf_graph_(Graph, Count). 1439 1440index(rdf(-,-,-,-), 0). 1441index(rdf(+,-,-,-), 1). 1442index(rdf(-,+,-,-), 2). 1443index(rdf(+,+,-,-), 3). 1444index(rdf(-,-,+,-), 4). 1445index(rdf(+,-,+,-), 5). 1446index(rdf(-,+,+,-), 6). 1447index(rdf(+,+,+,-), 7). 1448 1449index(rdf(-,-,-,+), 8). 1450index(rdf(+,-,-,+), 9). 1451index(rdf(-,+,-,+), 10). 1452index(rdf(+,+,-,+), 11). 1453index(rdf(-,-,+,+), 12). 1454index(rdf(+,-,+,+), 13). 1455index(rdf(-,+,+,+), 14). 1456index(rdf(+,+,+,+), 15). 1457 1458 1459 /******************************* 1460 * PREDICATES * 1461 *******************************/
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.
1477rdf_current_predicate(P, DB) :-
1478 rdf_current_predicate(P),
1479 ( rdf(_,P,_,DB)
1480 -> true
1481 ).
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.1534rdf_predicate_property(P, Prop) :- 1535 var(P), 1536 !, 1537 rdf_current_predicate(P), 1538 rdf_predicate_property_(P, Prop). 1539rdf_predicate_property(P, Prop) :- 1540 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.
1565 /******************************* 1566 * SNAPSHOTS * 1567 *******************************/
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.1590rdf_current_snapshot(Term) :- 1591 current_blob(Term, rdf_snapshot). 1592 1593 1594 /******************************* 1595 * TRANSACTION * 1596 *******************************/
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.1632rdf_transaction(Goal) :- 1633 rdf_transaction(, user, []). 1634rdf_transaction(Goal, Id) :- 1635 rdf_transaction(, Id, []).
1646rdf_active_transaction(Id) :-
1647 rdf_active_transactions_(List),
1648 member(Id, List).
1654rdf_monitor(Goal, Options) :- 1655 monitor_mask(Options, 0xffff, Mask), 1656 rdf_monitor_(Goal, Mask). 1657 1658monitor_mask([], Mask, Mask). 1659monitor_mask([H|T], Mask0, Mask) :- 1660 update_mask(H, Mask0, Mask1), 1661 monitor_mask(T, Mask1, Mask). 1662 1663update_mask(-X, Mask0, Mask) :- 1664 !, 1665 monitor_mask(X, M), 1666 Mask is Mask0 /\ \M. 1667update_mask(+X, Mask0, Mask) :- 1668 !, 1669 monitor_mask(X, M), 1670 Mask is Mask0 \/ M. 1671update_mask(X, Mask0, Mask) :- 1672 monitor_mask(X, M), 1673 Mask is Mask0 \/ M.
1680 % C-defined broadcasts 1681monitor_mask(assert, 0x0001). 1682monitor_mask(assert(load), 0x0002). 1683monitor_mask(retract, 0x0004). 1684monitor_mask(update, 0x0008). 1685monitor_mask(new_literal, 0x0010). 1686monitor_mask(old_literal, 0x0020). 1687monitor_mask(transaction, 0x0040). 1688monitor_mask(load, 0x0080). 1689monitor_mask(create_graph, 0x0100). 1690monitor_mask(reset, 0x0200). 1691 % prolog defined broadcasts 1692monitor_mask(parse, 0x1000). 1693monitor_mask(unload, 0x1000). % FIXME: Duplicate 1694 % mask for all 1695monitor_mask(all, 0xffff). 1696 1697%rdf_broadcast(Term, MaskName) :- 1698%% monitor_mask(MaskName, Mask), 1699%% rdf_broadcast_(Term, Mask). 1700 1701 1702 /******************************* 1703 * WARM * 1704 *******************************/
1710rdf_warm_indexes :- 1711 findall(Index, rdf_index(Index), Indexes), 1712 rdf_warm_indexes(Indexes). 1713 1714rdf_index(s). 1715rdf_index(p). 1716rdf_index(o). 1717rdf_index(sp). 1718rdf_index(o). 1719rdf_index(po). 1720rdf_index(spo). 1721rdf_index(g). 1722rdf_index(sg). 1723rdf_index(pg).
1734 /******************************* 1735 * DUPLICATES * 1736 *******************************/
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.
1751:- public
1752 rdf_update_duplicates_thread/0.
1758rdf_update_duplicates_thread :-
1759 thread_create(rdf_update_duplicates, _,
1760 [ detached(true),
1761 alias('__rdf_duplicate_detecter')
1762 ]).
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.
1776 /******************************* 1777 * QUICK BINARY LOAD/SAVE * 1778 *******************************/
1788:- create_prolog_flag(rdf_triple_format, 3, [type(integer)]). 1789 1790rdf_save_db(File) :- 1791 current_prolog_flag(rdf_triple_format, Version), 1792 setup_call_cleanup( 1793 open(File, write, Out, [type(binary)]), 1794 ( set_stream(Out, record_position(false)), 1795 rdf_save_db_(Out, _, Version) 1796 ), 1797 close(Out)). 1798 1799 1800rdf_save_db(File, Graph) :- 1801 current_prolog_flag(rdf_triple_format, Version), 1802 setup_call_cleanup( 1803 open(File, write, Out, [type(binary)]), 1804 ( set_stream(Out, record_position(false)), 1805 rdf_save_db_(Out, Graph, Version) 1806 ), 1807 close(Out)).
1816rdf_load_db_no_admin(File, Id, Graphs) :-
1817 open(File, read, In, [type(binary)]),
1818 set_stream(In, record_position(false)),
1819 call_cleanup(rdf_load_db_(In, Id, Graphs), close(In)).
1830check_loaded_cache(DB, [DB], _Modified) :- !. 1831check_loaded_cache(DB, Graphs, _) :- 1832 print_message(warning, rdf(inconsistent_cache(DB, Graphs))).
1839rdf_load_db(File) :- 1840 uri_file_name(URL, File), 1841 rdf_load_db_no_admin(File, URL, _Graphs). 1842 1843 1844 /******************************* 1845 * LOADING RDF * 1846 *******************************/ 1847 1848:- multifile 1849 rdf_open_hook/8, 1850 rdf_open_decode/4, % +Encoding, +File, -Stream, -Cleanup 1851 rdf_load_stream/3, % +Format, +Stream, +Options 1852 rdf_file_type/2, % ?Extension, ?Format 1853 rdf_storage_encoding/2, % ?Extension, ?Encoding 1854 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)).
1936:- dynamic 1937 rdf_loading/3. % Graph, Queue, Thread 1938 1939rdf_load(Spec) :- 1940 rdf_load(Spec, []). 1941 1942:- if(\+current_predicate(concurrent/3)). 1943concurrent(_, Goals, _) :- 1944 forall(member(G, Goals), call()). 1945:- endif. 1946 1947% Note that we kill atom garbage collection. This improves performance 1948% with about 15% loading the LUBM Univ_50 benchmark. 1949 1950rdf_load(Spec, M:Options) :- 1951 must_be(list, Options), 1952 current_prolog_flag(agc_margin, Old), 1953 setup_call_cleanup( 1954 set_prolog_flag(agc_margin, 0), 1955 rdf_load_noagc(Spec, M, Options), 1956 set_prolog_flag(agc_margin, Old)). 1957 1958rdf_load_noagc(List, M, Options) :- 1959 is_list(List), 1960 !, 1961 flatten(List, Inputs), % Compatibility: allow nested lists 1962 maplist(must_be(ground), Inputs), 1963 length(Inputs, Count), 1964 load_jobs(Count, Jobs, Options), 1965 ( Jobs =:= 1 1966 -> forall(member(Spec, Inputs), 1967 rdf_load_one(Spec, M, Options)) 1968 ; maplist(load_goal(Options, M), Inputs, Goals), 1969 concurrent(Jobs, Goals, []) 1970 ). 1971rdf_load_noagc(One, M, Options) :- 1972 must_be(ground, One), 1973 rdf_load_one(One, M, Options). 1974 1975load_goal(Options, M, Spec, rdf_load_one(Spec, M, Options)). 1976 1977load_jobs(_, Jobs, Options) :- 1978 option(concurrent(Jobs), Options), 1979 !, 1980 must_be(positive_integer, Jobs). 1981load_jobs(Count, Jobs, _) :- 1982 current_prolog_flag(cpu_count, CPUs), 1983 CPUs > 0, 1984 !, 1985 Jobs is max(1, min(CPUs, Count)). 1986load_jobs(_, 1, _). 1987 1988 1989rdf_load_one(Spec, M, Options) :- 1990 source_url(Spec, Protocol, SourceURL), 1991 load_graph(SourceURL, Graph, Options), 1992 setup_call_cleanup( 1993 with_mutex(rdf_load_file, 1994 rdf_start_load(SourceURL, Loading)), 1995 rdf_load_file(Loading, Spec, SourceURL, Protocol, 1996 Graph, M, Options), 1997 rdf_end_load(Loading)).
2014rdf_start_load(SourceURL, queue(Queue)) :- 2015 rdf_loading(SourceURL, Queue, LoadThread), 2016 \+ thread_self(LoadThread), 2017 !, 2018 debug(rdf(load), '~p is being loaded by thread ~w; waiting ...', 2019 [ SourceURL, LoadThread]). 2020rdf_start_load(SourceURL, Ref) :- 2021 thread_self(Me), 2022 message_queue_create(Queue), 2023 assertz(rdf_loading(SourceURL, Queue, Me), Ref). 2024 2025rdf_end_load(queue(_)) :- !. 2026rdf_end_load(Ref) :- 2027 clause(rdf_loading(_, Queue, _), _, Ref), 2028 erase(Ref), 2029 thread_send_message(Queue, done), 2030 message_queue_destroy(Queue). 2031 2032rdf_load_file(queue(Queue), _Spec, _SourceURL, _Protocol, _Graph, _M, _Options) :- 2033 !, 2034 catch(thread_get_message(Queue, _), _, true). 2035rdf_load_file(_Ref, _Spec, SourceURL, Protocol, Graph, M, Options) :- 2036 debug(rdf(load), 'RDF: Loading ~q into ~q', [SourceURL, Graph]), 2037 statistics(cputime, T0), 2038 rdf_open_input(SourceURL, Protocol, Graph, 2039 In, Cleanup, Modified, Format, Options), 2040 supported_format(Format, Cleanup), 2041 return_modified(Modified, Options), 2042 ( Modified == not_modified 2043 -> Action = none 2044 ; Modified = cached(CacheFile) 2045 -> do_unload(Graph), 2046 catch(rdf_load_db_no_admin(CacheFile, cache(Graph), Graphs), _, fail), 2047 check_loaded_cache(Graph, Graphs, Modified), 2048 Action = load 2049 ; option(base_uri(BaseURI), Options, Graph), 2050 ( var(BaseURI) 2051 -> BaseURI = SourceURL 2052 ; true 2053 ), 2054 once(phrase(derived_options(Options, NSList), Extra)), 2055 merge_options([ base_uri(BaseURI), 2056 graph(Graph), 2057 format(Format) 2058 | Extra 2059 ], Options, RDFOptions), 2060 do_unload(Graph), 2061 graph_modified(Modified, ModifiedStamp), 2062 rdf_set_graph_source(Graph, SourceURL, ModifiedStamp), 2063 call_cleanup(rdf_load_stream(Format, In, M:RDFOptions), 2064 ), 2065 save_cache(Graph, SourceURL, Options), 2066 register_file_ns(NSList), 2067 format_action(Format, Action) 2068 ), 2069 rdf_statistics_(triples(Graph, Triples)), 2070 report_loaded(Action, SourceURL, Graph, Triples, T0, Options). 2071 2072supported_format(Format, _Cleanup) :- 2073 rdf_file_type(_, Format), 2074 !. 2075supported_format(Format, Cleanup) :- 2076 call(), 2077 existence_error(rdf_format_plugin, Format). 2078 2079format_action(triples, load) :- !. 2080format_action(_, parsed). 2081 2082save_cache(Graph, SourceURL, Options) :- 2083 option(cache(true), Options, true), 2084 rdf_cache_file(SourceURL, write, CacheFile), 2085 !, 2086 catch(save_cache(Graph, CacheFile), E, 2087 print_message(warning, E)). 2088save_cache(_, _, _). 2089 2090derived_options([], _) --> 2091 []. 2092derived_options([H|T], NSList) --> 2093 ( { H == register_namespaces(true) 2094 ; H == (register_namespaces = true) 2095 } 2096 -> [ namespaces(NSList) ] 2097 ; [] 2098 ), 2099 derived_options(T, NSList). 2100 2101graph_modified(last_modified(Stamp), Stamp). 2102graph_modified(unknown, Stamp) :- 2103 get_time(Stamp). 2104 2105return_modified(Modified, Options) :- 2106 option(modified(M0), Options), 2107 !, 2108 M0 = Modified. 2109return_modified(_, _). 2110 2111 2112 /******************************* 2113 * INPUT HANDLING * 2114 *******************************/ 2115 2116/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2117This section deals with pluggable input sources. The task of the input 2118layer is 2119 2120 * Decide on the graph-name 2121 * Decide on the source-location 2122 * Decide whether loading is needed (if-modified) 2123 * Decide on the serialization in the input 2124 2125The protocol must ensure minimal overhead, in particular for network 2126protocols. E.g. for HTTP we want to make a single call on the server and 2127use If-modified-since to verify that we need not reloading this file. 2128- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
Options processed:
graph(Graph)
db(Graph)
if(Condition)
cache(Cache)
format(Format)
2146rdf_open_input(SourceURL, Protocol, Graph,
2147 Stream, Cleanup, Modified, Format, Options) :-
2148 option(if(If), Options, changed),
2149 ( If == true
2150 -> true
2151 ; rdf_graph_source_(Graph, SourceURL, HaveModified)
2152 -> true
2153 ; option(cache(true), Options, true),
2154 rdf_cache_file(SourceURL, read, CacheFile)
2155 -> time_file(CacheFile, HaveModified)
2156 ; true
2157 ),
2158 option(format(Format), Options, _),
2159 open_input_if_modified(Protocol, SourceURL, HaveModified,
2160 Stream, Cleanup, Modified0, Format, Options),
2161 ( Modified0 == not_modified
2162 -> ( nonvar(CacheFile)
2163 -> Modified = cached(CacheFile)
2164 ; Modified = not_modified
2165 )
2166 ; Modified = Modified0
2167 ).
stream(Stream)
http
)2178source_url(stream(In), stream(In), SourceURL) :- 2179 !, 2180 ( stream_property(In, file_name(File)) 2181 -> to_url(File, SourceURL) 2182 ; gensym('stream://', SourceURL) 2183 ). 2184source_url(Stream, Class, SourceURL) :- 2185 is_stream(Stream), 2186 !, 2187 source_url(stream(Stream), Class, SourceURL). 2188source_url(Spec, Protocol, SourceURL) :- 2189 compound(Spec), 2190 !, 2191 source_file(Spec, Protocol, SourceURL). 2192source_url(FileURL, Protocol, SourceURL) :- % or return FileURL? 2193 uri_file_name(FileURL, File), 2194 !, 2195 source_file(File, Protocol, SourceURL). 2196source_url(SourceURL0, Protocol, SourceURL) :- 2197 is_url(SourceURL0, Protocol, SourceURL), 2198 !. 2199source_url(File, Protocol, SourceURL) :- 2200 source_file(File, Protocol, SourceURL). 2201 2202source_file(Spec, file(SExt), SourceURL) :- 2203 findall(Ext, valid_extension(Ext), Exts), 2204 absolute_file_name(Spec, File, [access(read), extensions([''|Exts])]), 2205 storage_extension(_Plain, SExt, File), 2206 uri_file_name(SourceURL, File). 2207 2208to_url(URL, URL) :- 2209 uri_is_global(URL), 2210 !. 2211to_url(File, URL) :- 2212 absolute_file_name(File, Path), 2213 uri_file_name(URL, Path). 2214 2215storage_extension(Plain, SExt, File) :- 2216 file_name_extension(Plain, SExt, File), 2217 SExt \== '', 2218 rdf_storage_encoding(SExt, _), 2219 !. 2220storage_extension(File, '', File).
graph(Graph)
optiondb(Graph)
option (backward compatibility)base_uri(BaseURI)
option2232load_graph(Source, Graph, Options) :- 2233 ( option(graph(Graph), Options) 2234 ; option(db(Graph), Options) 2235 ), 2236 !, 2237 load_graph2(Source, Graph, Options). 2238load_graph(Source, Graph, Options) :- 2239 load_graph2(Source, Graph, Options). 2240 2241load_graph2(_, Graph, _) :- 2242 ground(Graph), 2243 !. 2244load_graph2(_Source, Graph, Options) :- 2245 option(base_uri(Graph), Options), 2246 Graph \== [], 2247 ground(Graph), 2248 !. 2249load_graph2(Source, Graph, _) :- 2250 load_graph(Source, Graph). 2251 2252load_graph(SourceURL, BaseURI) :- 2253 file_name_extension(BaseURI, Ext, SourceURL), 2254 rdf_storage_encoding(Ext, _), 2255 !. 2256load_graph(SourceURL, SourceURL). 2257 2258 2259open_input_if_modified(stream(In), SourceURL, _, In, true, 2260 unknown, Format, _) :- 2261 !, 2262 ( var(Format) 2263 -> guess_format(SourceURL, Format) 2264 ; true 2265 ). 2266open_input_if_modified(file(SExt), SourceURL, HaveModified, Stream, Cleanup, 2267 Modified, Format, _) :- 2268 !, 2269 uri_file_name(SourceURL, File), 2270 ( SExt == '' -> Plain = File; file_name_extension(Plain, SExt, File)), 2271 time_file(File, LastModified), 2272 ( nonvar(HaveModified), 2273 HaveModified >= LastModified 2274 -> Modified = not_modified, 2275 Cleanup = true 2276 ; storage_open(SExt, File, Stream, Cleanup), 2277 Modified = last_modified(LastModified), 2278 ( var(Format) 2279 -> guess_format(Plain, Format) 2280 ; true 2281 ) 2282 ). 2283open_input_if_modified(file, SourceURL, HaveModified, Stream, Cleanup, 2284 Modified, Format, Options) :- 2285 !, 2286 open_input_if_modified(file(''), SourceURL, HaveModified, 2287 Stream, Cleanup, 2288 Modified, Format, Options). 2289open_input_if_modified(Protocol, SourceURL, HaveModified, Stream, Cleanup, 2290 Modified, Format, Options) :- 2291 rdf_open_hook(Protocol, SourceURL, HaveModified, Stream, Cleanup, 2292 Modified, Format, Options). 2293 2294guess_format(File, Format) :- 2295 file_name_extension(_, Ext, File), 2296 ( rdf_file_type(Ext, Format) 2297 -> true 2298 ; Format = xml, 2299 print_message(warning, rdf(guess_format(Ext))) 2300 ).
2308storage_open('', File, Stream, close(Stream)) :- 2309 !, 2310 open(File, read, Stream, [type(binary)]). 2311storage_open(Ext, File, Stream, Cleanup) :- 2312 rdf_storage_encoding(Ext, Encoding), 2313 rdf_open_decode(Encoding, File, Stream, Cleanup). 2314 2315valid_extension(Ext) :- 2316 rdf_file_type(Ext, _). 2317valid_extension(Ext) :- 2318 rdf_storage_encoding(Ext, _).
2328is_url(URL, Scheme, FetchURL) :- 2329 atom(URL), 2330 uri_is_global(URL), 2331 uri_normalized(URL, URL1), % case normalization 2332 uri_components(URL1, Components), 2333 uri_data(scheme, Components, Scheme0), 2334 url_protocol(Scheme0), 2335 !, 2336 Scheme = Scheme0, 2337 uri_data(fragment, Components, _, Components1), 2338 uri_components(FetchURL, Components1). 2339 2340url_protocol(file). % built-in
2348rdf_file_type(xml, xml). 2349rdf_file_type(rdf, xml). 2350rdf_file_type(rdfs, xml). 2351rdf_file_type(owl, xml). 2352rdf_file_type(htm, xhtml). 2353rdf_file_type(html, xhtml). 2354rdf_file_type(xhtml, xhtml). 2355rdf_file_type(trp, triples).
2362rdf_storage_encoding('', plain).
2371rdf_load_stream(xml, Stream, Options) :- 2372 !, 2373 graph(Options, Graph), 2374 rdf_transaction(load_stream(Stream, Options), 2375 parse(Graph)). 2376rdf_load_stream(xhtml, Stream, M:Options) :- 2377 !, 2378 graph(Options, Graph), 2379 rdf_transaction(load_stream(Stream, M:[embedded(true)|Options]), 2380 parse(Graph)). 2381rdf_load_stream(triples, Stream, Options) :- 2382 !, 2383 graph(Options, Graph), 2384 rdf_load_db_(Stream, Graph, _Graphs). 2385 2386load_stream(Stream, M:Options) :- 2387 process_rdf(Stream, assert_triples, M:Options), 2388 option(graph(Graph), Options), 2389 rdf_graph_clear_modified_(Graph).
2394report_loaded(none, _, _, _, _, _) :- !. 2395report_loaded(Action, Source, DB, Triples, T0, Options) :- 2396 statistics(cputime, T1), 2397 Time is T1 - T0, 2398 ( option(silent(true), Options) 2399 -> Level = silent 2400 ; Level = informational 2401 ), 2402 print_message(Level, 2403 rdf(loaded(Action, Source, DB, Triples, Time))).
2416rdf_unload(Spec) :- 2417 source_url(Spec, _Protocol, SourceURL), 2418 rdf_graph_source_(Graph, SourceURL, _), 2419 !, 2420 rdf_unload_graph(Graph). 2421rdf_unload(Graph) :- 2422 atom(Graph), 2423 rdf_graph(Graph), 2424 !, 2425 warn_deprecated_unload(Graph), 2426 rdf_unload_graph(Graph). 2427rdf_unload(_). 2428 2429:- dynamic 2430 warned/0. 2431 2432warn_deprecated_unload(_) :- 2433 warned, 2434 !. 2435warn_deprecated_unload(Graph) :- 2436 assertz(warned), 2437 print_message(warning, rdf(deprecated(rdf_unload(Graph)))).
2445rdf_unload_graph(Graph) :- 2446 must_be(atom, Graph), 2447 ( rdf_graph(Graph) 2448 -> rdf_transaction(do_unload(Graph), unload(Graph)) 2449 ; true 2450 ). 2451 2452do_unload(Graph) :- 2453 ( rdf_graph_(Graph, Triples), 2454 Triples > 0 2455 -> rdf_retractall(_,_,_,Graph) 2456 ; true 2457 ), 2458 rdf_destroy_graph(Graph). 2459 2460 /******************************* 2461 * GRAPH QUERIES * 2462 *******************************/
2474rdf_graph(Graph) :-
2475 rdf_graph_(Graph, _Triples).
2483rdf_source(Graph, SourceURL) :-
2484 rdf_graph(Graph),
2485 rdf_graph_source_(Graph, SourceURL, _Modified).
2493rdf_source(SourceURL) :-
2494 rdf_source(_Graph, SourceURL).
2501rdf_make :- 2502 findall(Source-Graph, modified_graph(Source, Graph), Modified), 2503 forall(member(Source-Graph, Modified), 2504 catch(rdf_load(Source, [graph(Graph), if(changed)]), E, 2505 print_message(error, E))). 2506 2507modified_graph(SourceURL, Graph) :- 2508 rdf_graph(Graph), 2509 rdf_graph_source_(Graph, SourceURL, Modified), 2510 \+ sub_atom(SourceURL, 0, _, _, 'stream://'), 2511 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.2539rdf_graph_property(Graph, Property) :- 2540 rdf_graph(Graph), 2541 property_of_graph(Property, Graph). 2542 2543:- multifile 2544 property_of_graph/2. 2545 2546property_of_graph(hash(Hash), Graph) :- 2547 rdf_md5(Graph, Hash). 2548property_of_graph(modified(Boolean), Graph) :- 2549 rdf_graph_modified_(Graph, Boolean, _). 2550property_of_graph(source(URL), Graph) :- 2551 rdf_graph_source_(Graph, URL, _). 2552property_of_graph(source_last_modified(Time), Graph) :- 2553 rdf_graph_source_(Graph, _, Time), 2554 Time > 0.0. 2555property_of_graph(triples(Count), Graph) :- 2556 rdf_graph_(Graph, Count).
2565rdf_set_graph(Graph, modified(Modified)) :-
2566 must_be(oneof([false]), Modified),
2567 rdf_graph_clear_modified_(Graph).
2574save_cache(DB, Cache) :-
2575 current_prolog_flag(rdf_triple_format, Version),
2576 setup_call_cleanup(
2577 catch(open(Cache, write, CacheStream, [type(binary)]), _, fail),
2578 rdf_save_db_(CacheStream, DB, Version),
2579 close(CacheStream)).
2587assert_triples([], _). 2588assert_triples([rdf(S,P,O)|T], DB) :- 2589 !, 2590 rdf_assert(S, P, O, DB), 2591 assert_triples(T, DB). 2592assert_triples([H|_], _) :- 2593 throw(error(type_error(rdf_triple, H), _)). 2594 2595 2596 /******************************* 2597 * RESET * 2598 *******************************/
2611rdf_reset_db :- 2612 reset_gensym('_:genid'), 2613 rdf_reset_db_. 2614 2615 2616 /******************************* 2617 * SAVE RDF * 2618 *******************************/
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>
.2680:- thread_local 2681 named_anon/2, % +Resource, -Id 2682 inlined/1. % +Resource 2683 2684rdf_save(File) :- 2685 rdf_save2(File, []). 2686 2687rdf_save(Spec, M:Options0) :- 2688 is_list(Options0), 2689 !, 2690 meta_options(save_meta_option, M:Options0, Options), 2691 to_file(Spec, File), 2692 rdf_save2(File, Options). 2693rdf_save(Spec, _:DB) :- 2694 atom(DB), % backward compatibility 2695 !, 2696 to_file(Spec, File), 2697 rdf_save2(File, [graph(DB)]). 2698 2699save_meta_option(convert_typed_literal). 2700 2701to_file(URL, File) :- 2702 atom(URL), 2703 uri_file_name(URL, File), 2704 !. 2705to_file(File, File). 2706 2707rdf_save2(File, Options) :- 2708 option(encoding(Encoding), Options, utf8), 2709 valid_encoding(Encoding), 2710 open_output(File, Encoding, Out, Close), 2711 flag(rdf_db_saved_subjects, OSavedSubjects, 0), 2712 flag(rdf_db_saved_triples, OSavedTriples, 0), 2713 call_cleanup(rdf_do_save(Out, Options), 2714 Reason, 2715 cleanup_save(Reason, 2716 File, 2717 OSavedSubjects, 2718 OSavedTriples, 2719 Close)). 2720 2721open_output(stream(Out), Encoding, Out, 2722 set_stream(Out, encoding(Old))) :- 2723 !, 2724 stream_property(Out, encoding(Old)), 2725 set_stream(Out, encoding(Encoding)). 2726open_output(File, Encoding, Out, 2727 close(Out)) :- 2728 open(File, write, Out, [encoding(Encoding)]). 2729 2730valid_encoding(Enc) :- 2731 ( xml_encoding_name(Enc, _) 2732 -> true 2733 ; throw(error(domain_error(encoding, Enc), _)) 2734 ). 2735 2736 2737cleanup_save(Reason, 2738 File, 2739 OSavedSubjects, 2740 OSavedTriples, 2741 Close) :- 2742 call(), 2743 flag(rdf_db_saved_subjects, SavedSubjects, OSavedSubjects), 2744 flag(rdf_db_saved_triples, SavedTriples, OSavedTriples), 2745 retractall(named_anon(_, _)), 2746 retractall(inlined(_)), 2747 ( Reason == exit 2748 -> print_message(informational, 2749 rdf(saved(File, SavedSubjects, SavedTriples))) 2750 ; format(user_error, 'Reason = ~w~n', [Reason]) 2751 ). 2752 2753rdf_do_save(Out, Options0) :- 2754 rdf_save_header(Out, Options0, Options), 2755 graph(Options, DB), 2756 ( option(sorted(true), Options, false) 2757 -> ( var(DB) 2758 -> setof(Subject, rdf_subject(Subject), Subjects) 2759 ; findall(Subject, rdf(Subject, _, _, DB:_), SubjectList), 2760 sort(SubjectList, Subjects) 2761 ), 2762 forall(member(Subject, Subjects), 2763 rdf_save_non_anon_subject(Out, Subject, Options)) 2764 ; forall(rdf_subject_in_graph(Subject, DB), 2765 rdf_save_non_anon_subject(Out, Subject, Options)) 2766 ), 2767 rdf_save_footer(Out), 2768 !. % dubious cut; without the 2769 % cleanup handlers isn't called!?
2780rdf_subject_in_graph(Subject, DB) :- 2781 var(DB), 2782 !, 2783 rdf_subject(Subject). 2784rdf_subject_in_graph(Subject, DB) :- 2785 rdf_statistics(triples(AllTriples)), 2786 rdf_graph_property(DB, triples(DBTriples)), 2787 DBTriples > AllTriples // 10, 2788 !, 2789 rdf_resource(Subject), 2790 ( rdf(Subject, _, _, DB:_) 2791 -> true 2792 ). 2793rdf_subject_in_graph(Subject, DB) :- 2794 findall(Subject, rdf(Subject, _, _, DB:_), SubjectList), 2795 list_to_set(SubjectList, Subjects), 2796 member(Subject, Subjects). 2797 2798 2799graph(Options0, DB) :- 2800 strip_module(Options0, _, Options), 2801 ( memberchk(graph(DB0), Options) 2802 -> DB = DB0 2803 ; memberchk(db(DB0), Options) 2804 -> DB = DB0 2805 ; true % leave unbound 2806 ).
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.2831rdf_save_header(Out, Options) :- 2832 rdf_save_header(Out, Options, _). 2833 2834rdf_save_header(Out, Options, OptionsOut) :- 2835 is_list(Options), 2836 !, 2837 stream_property(Out, encoding(Enc)), 2838 xml_encoding(Enc, Encoding), 2839 format(Out, '<?xml version=\'1.0\' encoding=\'~w\'?>~n', [Encoding]), 2840 format(Out, '<!DOCTYPE rdf:RDF [', []), 2841 header_namespaces(Options, NSIdList), 2842 nsmap(NSIdList, NsMap), 2843 append(Options, [nsmap(NsMap)], OptionsOut), 2844 forall(member(Id=URI, NsMap), 2845 ( xml_quote_attribute(URI, NSText0, Enc), 2846 xml_escape_parameter_entity(NSText0, NSText), 2847 format(Out, '~N <!ENTITY ~w \'~w\'>', [Id, NSText]) 2848 )), 2849 format(Out, '~N]>~n~n', []), 2850 format(Out, '<rdf:RDF', []), 2851 ( member(Id, NSIdList), 2852 format(Out, '~N xmlns:~w="&~w;"~n', [Id, Id]), 2853 fail 2854 ; true 2855 ), 2856 ( option(base_uri(Base), Options), 2857 option(write_xml_base(true), Options, true) 2858 -> xml_quote_attribute(Base, BaseText, Enc), 2859 format(Out, '~N xml:base="~w"~n', [BaseText]) 2860 ; true 2861 ), 2862 ( memberchk(document_language(Lang), Options) 2863 -> format(Out, '~N xml:lang="~w"', [Lang]) 2864 ; true 2865 ), 2866 format(Out, '>~n', []). 2867rdf_save_header(Out, FileRef, OptionsOut) :- % compatibility 2868 atom(FileRef), 2869 rdf_save_header(Out, [graph(FileRef)], OptionsOut). 2870 2871xml_encoding(Enc, Encoding) :- 2872 ( xml_encoding_name(Enc, Encoding) 2873 -> true 2874 ; throw(error(domain_error(rdf_encoding, Enc), _)) 2875 ). 2876 2877xml_encoding_name(ascii, 'US-ASCII'). 2878xml_encoding_name(iso_latin_1, 'ISO-8859-1'). 2879xml_encoding_name(utf8, 'UTF-8').
2886nsmap([], []). 2887nsmap([Id|T0], [Id=URI|T]) :- 2888 ns(Id, URI), 2889 nsmap(T0, T).
2895xml_escape_parameter_entity(In, Out) :- 2896 sub_atom(In, _, _, _, '%'), 2897 !, 2898 atom_codes(In, Codes), 2899 phrase(escape_parent(Codes), OutCodes), 2900 atom_codes(Out, OutCodes). 2901xml_escape_parameter_entity(In, In). 2902 2903escape_parent([]) --> []. 2904escape_parent([H|T]) --> 2905 ( { H == 37 } 2906 -> "%" 2907 ; [H] 2908 ), 2909 escape_parent(T).
2916header_namespaces(Options, List) :- 2917 memberchk(namespaces(NSL0), Options), 2918 !, 2919 sort([rdf,rdfs|NSL0], List). 2920header_namespaces(Options, List) :- 2921 graph(Options, DB), 2922 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)
2960:- thread_local 2961 graph_prefix/3. 2962:- meta_predicate 2963 rdf_graph_prefixes( , , ). 2964 2965rdf_graph_prefixes(Graph, List) :- 2966 rdf_graph_prefixes(Graph, List, []). 2967 2968rdf_graph_prefixes(Graph, List, M:QOptions) :- 2969 is_list(QOptions), 2970 !, 2971 meta_options(is_meta, M:QOptions, Options), 2972 option(filter(Filter), Options, true), 2973 option(expand(Expand), Options, rdf_db), 2974 option(min_count(MinCount), Options, 1), 2975 option(get_prefix(GetPrefix), Options, iri_xml_namespace), 2976 call_cleanup(prefixes(Expand, Graph, Prefixes, Filter, MinCount, GetPrefix), 2977 retractall(graph_prefix(_,_,_))), 2978 sort(Prefixes, List). 2979rdf_graph_prefixes(Graph, List, M:Filter) :- 2980 rdf_graph_prefixes(Graph, List, M:[filter(Filter)]). 2981 2982is_meta(filter). 2983is_meta(expand). 2984is_meta(get_prefix). 2985 2986 2987prefixes(Expand, Graph, Prefixes, Filter, MinCount, GetPrefix) :- 2988 ( call(Expand, S, P, O, Graph), 2989 add_ns(subject, GetPrefix, Filter, S, MinCount, s(S)), 2990 add_ns(predicate, GetPrefix, Filter, P, MinCount, sp(S,P)), 2991 add_ns_obj(GetPrefix, Filter, O, MinCount, spo(S,P,O)), 2992 fail 2993 ; true 2994 ), 2995 findall(Prefix, graph_prefix(Prefix, MinCount, _), Prefixes). 2996 2997add_ns(Where, GetPrefix, Filter, S, MinCount, Context) :- 2998 \+ rdf_is_bnode(S), 2999 call(GetPrefix, S, Full), 3000 Full \== '', 3001 !, 3002 ( graph_prefix(Full, MinCount, _) 3003 -> true 3004 ; Filter == true 3005 -> add_ns(Full, Context) 3006 ; call(Filter, Where, Full, S) 3007 -> add_ns(Full, Context) 3008 ; true 3009 ). 3010add_ns(_, _, _, _, _, _). 3011 3012add_ns(Full, Context) :- 3013 graph_prefix(Full, _, Contexts), 3014 memberchk(Context, Contexts), 3015 !. 3016add_ns(Full, Context) :- 3017 retract(graph_prefix(Full, C0, Contexts)), 3018 !, 3019 C1 is C0+1, 3020 asserta(graph_prefix(Full, C1, [Context|Contexts])). 3021add_ns(Full, _) :- 3022 ns(_, Full), 3023 !, 3024 asserta(graph_prefix(Full, _, _)). 3025add_ns(Full, Context) :- 3026 asserta(graph_prefix(Full, 1, [Context])). 3027 3028 3029add_ns_obj(GetPrefix, Filter, O, MinCount, Context) :- 3030 atom(O), 3031 !, 3032 add_ns(object, GetPrefix, Filter, O, MinCount, Context). 3033add_ns_obj(GetPrefix, Filter, literal(type(Type, _)), MinCount, _) :- 3034 atom(Type), 3035 !, 3036 add_ns(type, GetPrefix, Filter, Type, MinCount, t(Type)). 3037add_ns_obj(_, _, _, _, _).
3047used_namespace_entities(List, Graph) :- 3048 decl_used_predicate_ns(Graph), 3049 used_namespaces(List, Graph). 3050 3051used_namespaces(List, DB) :- 3052 rdf_graph_prefixes(DB, FullList), 3053 ns_abbreviations(FullList, List0), 3054 sort([rdf|List0], List). 3055 3056ns_abbreviations([], []). 3057ns_abbreviations([H0|T0], [H|T]) :- 3058 ns(H, H0), 3059 !, 3060 ns_abbreviations(T0, T). 3061ns_abbreviations([_|T0], T) :- 3062 ns_abbreviations(T0, T). 3063 3064 3065/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3066For every URL used as a predicate we *MUST* define a namespace as we 3067cannot use names holding /, :, etc. as XML identifiers. 3068- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 3069 3070:- thread_local 3071 predicate_ns/2. 3072 3073decl_used_predicate_ns(DB) :- 3074 retractall(predicate_ns(_,_)), 3075 ( rdf_current_predicate(P, DB), 3076 decl_predicate_ns(P), 3077 fail 3078 ; true 3079 ). 3080 3081decl_predicate_ns(Pred) :- 3082 predicate_ns(Pred, _), 3083 !. 3084decl_predicate_ns(Pred) :- 3085 rdf_global_id(NS:Local, Pred), 3086 xml_name(Local), 3087 !, 3088 assert(predicate_ns(Pred, NS)). 3089decl_predicate_ns(Pred) :- 3090 atom_codes(Pred, Codes), 3091 append(NSCodes, LocalCodes, Codes), 3092 xml_codes(LocalCodes), 3093 !, 3094 ( NSCodes \== [] 3095 -> atom_codes(NS, NSCodes), 3096 ( ns(Id, NS) 3097 -> assert(predicate_ns(Pred, Id)) 3098 ; between(1, infinite, N), 3099 atom_concat(ns, N, Id), 3100 \+ ns(Id, _) 3101 -> rdf_register_ns(Id, NS), 3102 print_message(informational, 3103 rdf(using_namespace(Id, NS))) 3104 ), 3105 assert(predicate_ns(Pred, Id)) 3106 ; assert(predicate_ns(Pred, -)) % no namespace used 3107 ). 3108 3109xml_codes([]). 3110xml_codes([H|T]) :- 3111 xml_code(H), 3112 xml_codes(T). 3113 3114xml_code(X) :- 3115 code_type(X, csym), 3116 !. 3117xml_code(0'-). % Match 0'-
3126rdf_save_footer(Out) :-
3127 retractall(named_anon(_, _)),
3128 retractall(inlined(_)),
3129 format(Out, '</rdf:RDF>~n', []).
anon(false)
is present in the Options list.3136rdf_save_non_anon_subject(_Out, Subject, Options) :- 3137 rdf_is_bnode(Subject), 3138 ( memberchk(anon(false), Options) 3139 ; graph(Options, DB), 3140 rdf_db(_, _, Subject, DB) 3141 ), 3142 !. 3143rdf_save_non_anon_subject(Out, Subject, Options) :- 3144 rdf_save_subject(Out, Subject, Options), 3145 flag(rdf_db_saved_subjects, X, X+1).
3160rdf_save_subject(Out, Subject, Options) :- 3161 is_list(Options), 3162 !, 3163 option(base_uri(BaseURI), Options, '-'), 3164 ( rdf_save_subject(Out, Subject, BaseURI, 0, Options) 3165 -> format(Out, '~n', []) 3166 ; throw(error(rdf_save_failed(Subject), 'Internal error')) 3167 ). 3168rdf_save_subject(Out, Subject, DB) :- 3169 ( var(DB) 3170 -> rdf_save_subject(Out, Subject, []) 3171 ; rdf_save_subject(Out, Subject, [graph(DB)]) 3172 ).
3182rdf_save_subject(_, Subject, _, _, _) :- 3183 inlined(Subject), 3184 !. 3185rdf_save_subject(Out, Subject, BaseURI, Indent, Options) :- 3186 do_save_subject(Out, Subject, BaseURI, Indent, Options). 3187 3188do_save_subject(Out, Subject, BaseURI, Indent, Options) :- 3189 graph(Options, DB), 3190 findall(Pred=Object, rdf_db(Subject, Pred, Object, DB), Atts0), 3191 sort(Atts0, Atts), % remove duplicates 3192 length(Atts, L), 3193 ( length(Atts0, L0), 3194 Del is L0-L, 3195 Del > 0 3196 -> print_message(informational, 3197 rdf(save_removed_duplicates(Del, Subject))) 3198 ; true 3199 ), 3200 rdf_save_subject(Out, Subject, BaseURI, Atts, Indent, Options), 3201 flag(rdf_db_saved_triples, X, X+L). 3202 3203rdf_db(Subject, Pred, Object, DB) :- 3204 var(DB), 3205 !, 3206 rdf(Subject, Pred, Object). 3207rdf_db(Subject, Pred, Object, DB) :- 3208 rdf(Subject, Pred, Object, DB:_).
3215rdf_save_subject(Out, Subject, BaseURI, Atts, Indent, Options) :- 3216 rdf_equal(rdf:type, RdfType), 3217 select(RdfType=Type, Atts, Atts1), 3218 \+ rdf_is_bnode(Type), 3219 rdf_id(Type, BaseURI, TypeId), 3220 xml_is_name(TypeId), 3221 !, 3222 format(Out, '~*|<', [Indent]), 3223 rdf_write_id(Out, TypeId), 3224 save_about(Out, BaseURI, Subject), 3225 save_attributes(Atts1, BaseURI, Out, TypeId, Indent, Options). 3226rdf_save_subject(Out, Subject, BaseURI, Atts, Indent, Options) :- 3227 format(Out, '~*|<rdf:Description', [Indent]), 3228 save_about(Out, BaseURI, Subject), 3229 save_attributes(Atts, BaseURI, Out, rdf:'Description', Indent, Options). 3230 3231xml_is_name(_NS:Atom) :- 3232 !, 3233 xml_name(Atom). 3234xml_is_name(Atom) :- 3235 xml_name(Atom).
3242save_about(Out, _, Subject) :- 3243 rdf_is_bnode(Subject), 3244 !, 3245 ( named_anon(Subject, NodeID) 3246 -> format(Out, ' rdf:nodeID="~w"', [NodeID]) 3247 ; true 3248 ). 3249save_about(Out, BaseURI, Subject) :- 3250 stream_property(Out, encoding(Encoding)), 3251 rdf_value(Subject, BaseURI, QSubject, Encoding), 3252 format(Out, ' rdf:about="~w"', [QSubject]).
3260save_attributes(Atts, BaseURI, Out, Element, Indent, Options) :-
3261 split_attributes(Atts, InTag, InBody, Options),
3262 SubIndent is Indent + 2,
3263 save_attributes2(InTag, BaseURI, tag, Out, SubIndent, Options),
3264 ( InBody == []
3265 -> format(Out, '/>~n', [])
3266 ; format(Out, '>~n', []),
3267 save_attributes2(InBody, BaseURI, body, Out, SubIndent, Options),
3268 format(Out, '~N~*|</', [Indent]),
3269 rdf_write_id(Out, Element),
3270 format(Out, '>~n', [])
3271 ).
3279split_attributes(Atts, [], Atts, Options) :- 3280 option(xml_attributes(false), Options), 3281 !. 3282split_attributes(Atts, HeadAttr, BodyAttr, _) :- 3283 duplicate_attributes(Atts, Dupls, Singles), 3284 simple_literal_attributes(Singles, HeadAttr, Rest), 3285 append(Dupls, Rest, BodyAttr).
3292duplicate_attributes([], [], []). 3293duplicate_attributes([H|T], Dupls, Singles) :- 3294 H = (Name=_), 3295 named_attributes(Name, T, D, R), 3296 D \== [], 3297 append([H|D], Dupls2, Dupls), 3298 !, 3299 duplicate_attributes(R, Dupls2, Singles). 3300duplicate_attributes([H|T], Dupls2, [H|Singles]) :- 3301 duplicate_attributes(T, Dupls2, Singles). 3302 3303named_attributes(_, [], [], []) :- !. 3304named_attributes(Name, [H|T], D, R) :- 3305 ( H = (Name=_) 3306 -> D = [H|DT], 3307 named_attributes(Name, T, DT, R) 3308 ; R = [H|RT], 3309 named_attributes(Name, T, D, RT) 3310 ).
3317simple_literal_attributes([], [], []). 3318simple_literal_attributes([H|TA], [H|TI], B) :- 3319 in_tag_attribute(H), 3320 !, 3321 simple_literal_attributes(TA, TI, B). 3322simple_literal_attributes([H|TA], I, [H|TB]) :- 3323 simple_literal_attributes(TA, I, TB). 3324 3325in_tag_attribute(_=literal(Text)) :- 3326 atom(Text), % may not have lang qualifier 3327 atom_length(Text, Len), 3328 Len < 60.
3334save_attributes2([], _, _, _, _, _). 3335save_attributes2([H|T], BaseURI, Where, Out, Indent, Options) :- 3336 save_attribute(Where, H, BaseURI, Out, Indent, Options), 3337 save_attributes2(T, BaseURI, Where, Out, Indent, Options). 3338 3339save_attribute(tag, Name=literal(Value), BaseURI, Out, Indent, _DB) :- 3340 AttIndent is Indent + 2, 3341 rdf_id(Name, BaseURI, NameText), 3342 stream_property(Out, encoding(Encoding)), 3343 xml_quote_attribute(Value, QVal, Encoding), 3344 format(Out, '~N~*|', [AttIndent]), 3345 rdf_write_id(Out, NameText), 3346 format(Out, '="~w"', [QVal]). 3347save_attribute(body, Name=literal(Literal0), BaseURI, Out, Indent, Options) :- 3348 !, 3349 rdf_id(Name, BaseURI, NameText), 3350 ( memberchk(convert_typed_literal(Converter), Options), 3351 call(Converter, Type, Content, Literal0) 3352 -> Literal = type(Type, Content) 3353 ; Literal = Literal0 3354 ), 3355 save_body_literal(Literal, NameText, BaseURI, Out, Indent, Options). 3356save_attribute(body, Name=Value, BaseURI, Out, Indent, Options) :- 3357 rdf_is_bnode(Value), 3358 !, 3359 rdf_id(Name, BaseURI, NameText), 3360 format(Out, '~N~*|<', [Indent]), 3361 rdf_write_id(Out, NameText), 3362 ( named_anon(Value, NodeID) 3363 -> format(Out, ' rdf:nodeID="~w"/>', [NodeID]) 3364 ; ( rdf(S1, Name, Value), 3365 rdf(S2, P2, Value), 3366 (S1 \== S2 ; Name \== P2) 3367 -> predicate_property(named_anon(_,_), number_of_clauses(N)), 3368 atom_concat('bn', N, NodeID), 3369 assertz(named_anon(Value, NodeID)) 3370 ; true 3371 ), 3372 SubIndent is Indent + 2, 3373 ( rdf_collection(Value) 3374 -> save_about(Out, BaseURI, Value), 3375 format(Out, ' rdf:parseType="Collection">~n', []), 3376 rdf_save_list(Out, Value, BaseURI, SubIndent, Options) 3377 ; format(Out, '>~n', []), 3378 rdf_save_subject(Out, Value, BaseURI, SubIndent, Options) 3379 ), 3380 format(Out, '~N~*|</', [Indent]), 3381 rdf_write_id(Out, NameText), 3382 format(Out, '>~n', []) 3383 ). 3384save_attribute(body, Name=Value, BaseURI, Out, Indent, Options) :- 3385 option(inline(true), Options), 3386 has_attributes(Value, Options), 3387 \+ inlined(Value), 3388 !, 3389 assertz(inlined(Value)), 3390 rdf_id(Name, BaseURI, NameText), 3391 format(Out, '~N~*|<', [Indent]), 3392 rdf_write_id(Out, NameText), 3393 SubIndent is Indent + 2, 3394 ( rdf_collection(Value) 3395 -> save_about(Out, BaseURI, Value), 3396 format(Out, ' rdf:parseType="Collection">~n', []), 3397 rdf_save_list(Out, Value, BaseURI, SubIndent, Options) 3398 ; format(Out, '>~n', []), 3399 do_save_subject(Out, Value, BaseURI, SubIndent, Options) 3400 ), 3401 format(Out, '~N~*|</', [Indent]), 3402 rdf_write_id(Out, NameText), 3403 format(Out, '>~n', []). 3404save_attribute(body, Name=Value, BaseURI, Out, Indent, _DB) :- 3405 stream_property(Out, encoding(Encoding)), 3406 rdf_value(Value, BaseURI, QVal, Encoding), 3407 rdf_id(Name, BaseURI, NameText), 3408 format(Out, '~N~*|<', [Indent]), 3409 rdf_write_id(Out, NameText), 3410 format(Out, ' rdf:resource="~w"/>', [QVal]). 3411 3412has_attributes(URI, Options) :- 3413 graph(Options, DB), 3414 rdf_db(URI, _, _, DB), 3415 !.
3420save_body_literal(lang(Lang, Value), 3421 NameText, BaseURI, Out, Indent, Options) :- 3422 !, 3423 format(Out, '~N~*|<', [Indent]), 3424 rdf_write_id(Out, NameText), 3425 ( memberchk(document_language(Lang), Options) 3426 -> write(Out, '>') 3427 ; rdf_id(Lang, BaseURI, LangText), 3428 format(Out, ' xml:lang="~w">', [LangText]) 3429 ), 3430 save_attribute_value(Value, Out, Indent), 3431 write(Out, '</'), rdf_write_id(Out, NameText), write(Out, '>'). 3432save_body_literal(type(Type, DOM), 3433 NameText, _BaseURI, Out, Indent, Options) :- 3434 rdf_equal(Type, rdf:'XMLLiteral'), 3435 !, 3436 ( atom(DOM) 3437 -> format(Out, '~N~*|<', [Indent]), 3438 rdf_write_id(Out, NameText), 3439 format(Out, ' rdf:parseType="Literal">~w</', [DOM]), 3440 rdf_write_id(Out, NameText), write(Out, '>') 3441 ; save_xml_literal(DOM, NameText, Out, Indent, Options) 3442 ). 3443save_body_literal(type(Type, Value), 3444 NameText, BaseURI, Out, Indent, _) :- 3445 !, 3446 format(Out, '~N~*|<', [Indent]), 3447 rdf_write_id(Out, NameText), 3448 stream_property(Out, encoding(Encoding)), 3449 rdf_value(Type, BaseURI, QVal, Encoding), 3450 format(Out, ' rdf:datatype="~w">', [QVal]), 3451 save_attribute_value(Value, Out, Indent), 3452 write(Out, '</'), rdf_write_id(Out, NameText), write(Out, '>'). 3453save_body_literal(Literal, 3454 NameText, _, Out, Indent, _) :- 3455 atomic(Literal), 3456 !, 3457 format(Out, '~N~*|<', [Indent]), 3458 rdf_write_id(Out, NameText), 3459 write(Out, '>'), 3460 save_attribute_value(Literal, Out, Indent), 3461 write(Out, '</'), rdf_write_id(Out, NameText), write(Out, '>'). 3462save_body_literal(DOM, 3463 NameText, BaseURI, Out, Indent, Options) :- 3464 rdf_equal(Type, rdf:'XMLLiteral'), 3465 save_body_literal(type(Type, DOM), 3466 NameText, BaseURI, Out, Indent, Options). 3467 3468save_attribute_value(Value, Out, _) :- % strings 3469 atom(Value), 3470 !, 3471 stream_property(Out, encoding(Encoding)), 3472 xml_quote_cdata(Value, QVal, Encoding), 3473 write(Out, QVal). 3474save_attribute_value(Value, Out, _) :- % numbers 3475 number(Value), 3476 !, 3477 writeq(Out, Value). % quoted: preserve floats 3478save_attribute_value(Value, _Out, _) :- 3479 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.
3493save_xml_literal(DOM, Attr, Out, Indent, Options) :- 3494 xml_is_dom(DOM), 3495 !, 3496 memberchk(nsmap(NsMap), Options), 3497 id_to_atom(Attr, Atom), 3498 xml_write(Out, 3499 element(Atom, ['rdf:parseType'='Literal'], DOM), 3500 [ header(false), 3501 indent(Indent), 3502 nsmap(NsMap) 3503 ]). 3504save_xml_literal(NoDOM, _, _, _, _) :- 3505 must_be(xml_dom, NoDOM). 3506 3507id_to_atom(NS:Local, Atom) :- 3508 !, 3509 atomic_list_concat([NS,Local], :, Atom). 3510id_to_atom(ID, ID).
3520:- rdf_meta 3521 rdf_collection(r), 3522 collection_p(r,r). 3523 3524rdf_collection(rdf:nil) :- !. 3525rdf_collection(Cell) :- 3526 rdf_is_bnode(Cell), 3527 findall(F, rdf(Cell, rdf:first, F), [_]), 3528 findall(F, rdf(Cell, rdf:rest, F), [Rest]), 3529 forall(rdf(Cell, P, V), 3530 collection_p(P, V)), 3531 rdf_collection(Rest). 3532 3533collection_p(rdf:first, V) :- atom(V). 3534collection_p(rdf:rest, _). 3535collection_p(rdf:type, rdf:'List').
3540rdf_save_list(_, List, _, _, _) :- 3541 rdf_equal(List, rdf:nil), 3542 !. 3543rdf_save_list(Out, List, BaseURI, Indent, Options) :- 3544 rdf_has(List, rdf:first, First), 3545 ( rdf_is_bnode(First) 3546 -> nl(Out), 3547 rdf_save_subject(Out, First, BaseURI, Indent, Options) 3548 ; stream_property(Out, encoding(Encoding)), 3549 rdf_value(First, BaseURI, QVal, Encoding), 3550 format(Out, '~N~*|<rdf:Description rdf:about="~w"/>', 3551 [Indent, QVal]) 3552 ), 3553 flag(rdf_db_saved_triples, X, X+3), 3554 ( rdf_has(List, rdf:rest, List2), 3555 \+ rdf_equal(List2, rdf:nil) 3556 -> rdf_save_list(Out, List2, BaseURI, Indent, Options) 3557 ; true 3558 ).
3566rdf_id(Id, BaseURI, Local) :- 3567 assertion(atom(BaseURI)), 3568 atom_concat(BaseURI, Local, Id), 3569 sub_atom(Local, 0, 1, _, #), 3570 !. 3571rdf_id(Id, _, NS:Local) :- 3572 iri_xml_namespace(Id, Full, Local), 3573 ns(NS, Full), 3574 !. 3575rdf_id(Id, _, NS:Local) :- 3576 ns(NS, Full), 3577 Full \== '', 3578 atom_concat(Full, Local, Id), 3579 !. 3580rdf_id(Id, _, Id).
3588rdf_write_id(Out, NS:Local) :- 3589 !, 3590 format(Out, '~w:~w', [NS, Local]). 3591rdf_write_id(Out, Atom) :- 3592 write(Out, Atom).
3601rdf_value(Base, Base, '', _) :- !. 3602rdf_value(V, Base, Text, Encoding) :- 3603 atom_concat(Base, Local, V), 3604 sub_atom(Local, 0, _, _, #), 3605 !, 3606 xml_quote_attribute(Local, Text, Encoding). 3607rdf_value(V, _, Text, Encoding) :- 3608 ns(NS, Full), 3609 atom_concat(Full, Local, V), 3610 xml_is_name(Local), 3611 !, 3612 xml_quote_attribute(Local, QLocal, Encoding), 3613 atomic_list_concat(['&', NS, (';'), QLocal], Text). 3614rdf_value(V, _, Q, Encoding) :- 3615 xml_quote_attribute(V, Q, Encoding). 3616 3617 3618 /******************************* 3619 * MATCH AND COMPARE * 3620 *******************************/
icase
, substring
, word
, prefix
or like
. For backward
compatibility, exact
is a synonym for icase
.3643 /******************************* 3644 * DEPRECATED MATERIAL * 3645 *******************************/
library(sgml)
.
3655rdf_split_url(Prefix, Local, URL) :- 3656 atomic(URL), 3657 !, 3658 iri_xml_namespace(URL, Prefix, Local). 3659rdf_split_url(Prefix, Local, URL) :- 3660 atom_concat(Prefix, Local, URL).
3668rdf_url_namespace(URL, Prefix) :- 3669 iri_xml_namespace(URL, Prefix). 3670 3671 3672 /******************************* 3673 * LITERALS * 3674 *******************************/
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).3762 /******************************* 3763 * MISC * 3764 *******************************/
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.
3861 /******************************* 3862 * MESSAGES * 3863 *******************************/ 3864 3865:- multifile 3866 prolog:message//1. 3867 3868prologmessage(rdf(Term)) --> 3869 message(Term). 3870 3871message(loaded(How, What, BaseURI, Triples, Time)) --> 3872 how(How), 3873 source(What), 3874 into(What, BaseURI), 3875 in_time(Triples, Time). 3876message(save_removed_duplicates(N, Subject)) --> 3877 [ 'Removed ~d duplicate triples about "~p"'-[N,Subject] ]. 3878message(saved(File, SavedSubjects, SavedTriples)) --> 3879 [ 'Saved ~D triples about ~D subjects into ~p'- 3880 [SavedTriples, SavedSubjects, File] 3881 ]. 3882message(using_namespace(Id, NS)) --> 3883 [ 'Using namespace id ~w for ~w'-[Id, NS] ]. 3884message(inconsistent_cache(DB, Graphs)) --> 3885 [ 'RDF cache file for ~w contains the following graphs'-[DB], nl, 3886 '~t~8|~p'-[Graphs] 3887 ]. 3888message(guess_format(Ext)) --> 3889 [ 'Unknown file-extension: ~w. Assuming RDF/XML'-[Ext] ]. 3890message(meta(not_expanded(G))) --> 3891 [ 'rdf_meta/1: ~p is not expanded'-[G] ]. 3892message(deprecated(rdf_unload(Graph))) --> 3893 [ 'rdf_unload/1: Use ~q'-[rdf_unload_graph(Graph)] ]. 3894 3895 3896how(load) --> [ 'Loaded' ]. 3897how(parsed) --> [ 'Parsed' ]. 3898 3899source(SourceURL) --> 3900 { uri_file_name(SourceURL, File), 3901 !, 3902 file_base_name(File, Base) % TBD: relative file? 3903 }, 3904 [ ' "~w"'-[Base] ]. 3905source(SourceURL) --> 3906 [ ' "~w"'-[SourceURL] ]. 3907 3908into(_, _) --> []. % TBD 3909 3910in_time(Triples, ParseTime) --> 3911 [ ' in ~2f sec; ~D triples'-[ParseTime, Triples] 3912 ]
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. */