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-2015, 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(rdfs, 37 [ rdfs_subproperty_of/2, % ?SubProperties, ?Property 38 rdfs_subclass_of/2, % ?SubClass, ?Class 39 rdfs_class_property/2, % +Class, ?Property 40 rdfs_individual_of/2, % ?Resource, ?Class 41 42 rdfs_label/2, % ?Resource, ?Label 43 rdfs_label/3, % ?Resource, ?Language, ?Label 44 rdfs_ns_label/2, % +Resource, -Label 45 rdfs_ns_label/3, % +Resource, ?Label, -Label 46 47 rdfs_member/2, % ?Object, +Set 48 rdfs_list_to_prolog_list/2, % +Set, -List 49 rdfs_assert_list/3, % +List, -Resource, +DB 50 rdfs_assert_list/2, % +List, -Resource 51 52 rdfs_find/5 % +String, +Dom, +Props, +Method, -Subj 53 ]). 54:- use_module(library(lists)). 55:- use_module(rdf_db).
71 /******************************* 72 * EXPANSION * 73 *******************************/ 74 75:- rdf_meta 76 rdfs_subproperty_of(r,r), 77 rdfs_subclass_of(r,r), 78 rdfs_class_property(r,r), 79 rdfs_individual_of(r,r), 80 rdfs_label(r,-), 81 rdfs_label(r,?,-). 82 83 84 /******************************* 85 * PROPERTY HIERARCHY * 86 *******************************/
93rdfs_subproperty_of(SubProperty, Property) :- 94 rdf_reachable(SubProperty, rdfs:subPropertyOf, Property). 95 96 97 /******************************* 98 * CLASS HIERARCHY * 99 *******************************/
According to production 2.4 "rdfs:Datatype", Each instance of rdfs:Datatype is a subclass of rdfs:Literal.
112rdfs_subclass_of(Class, Super) :- 113 rdf_equal(rdfs:'Resource', Resource), 114 Super == Resource, 115 !, 116 rdfs_individual_of(Class, rdfs:'Class'). 117rdfs_subclass_of(Class, Super) :- 118 rdf_reachable(Class, rdfs:subClassOf, Super). 119rdfs_subclass_of(Class, Super) :- 120 nonvar(Class), 121 var(Super), 122 \+ rdf_reachable(Class, rdfs:subClassOf, rdfs:'Resource'), 123 rdfs_individual_of(Class, rdfs:'Class'), 124 rdf_equal(Super, rdfs:'Resource'). 125rdfs_subclass_of(Class, Super) :- % production 2.4 126 ( nonvar(Class) 127 -> rdf_has(Class, rdf:type, CType), 128 rdf_reachable(CType, rdfs:subClassOf, rdfs:'Datatype'), 129 \+ rdf_reachable(Class, rdfs:subClassOf, rdfs:'Literal'), 130 rdf_equal(Super, rdfs:'Literal') 131 ; nonvar(Super) 132 -> rdf_reachable(Super, rdfs:subClassOf, rdfs:'Literal'), 133 rdfs_individual_of(Class, rdfs:'Datatype') 134 ). 135 136 137 /******************************* 138 * INDIVIDUALS * 139 *******************************/
rdfs_individual_of(+, -)
does not exploit domain and range
properties, deriving that if rdf(R, P, _)
is present R must
satisfy the domain of P (and similar for range).
There are a few hacks:
literal(_)
is an individual of rdfs:Literal158rdfs_individual_of(Resource, Class) :- 159 nonvar(Resource), 160 !, 161 ( nonvar(Class) 162 -> ( rdf_equal(Class, rdfs:'Resource') 163 -> true 164 ; rdfs_individual_of_r_c(Resource, Class) 165 -> true 166 ) 167 ; rdfs_individual_of_r_c(Resource, Class) 168 ). 169rdfs_individual_of(Resource, Class) :- 170 nonvar(Class), 171 !, 172 ( rdf_equal(Class, rdfs:'Resource') 173 -> rdf_subject(Resource) 174 ; rdfs_subclass_of(SubClass, Class), 175 rdf_has(Resource, rdf:type, SubClass) 176 ). 177rdfs_individual_of(_Resource, _Class) :- 178 throw(error(instantiation_error, _)).
182rdfs_individual_of_r_c(literal(_), Class) :- 183 !, 184 rdfs_subclass_of(Class, rdfs:'Literal'). 185rdfs_individual_of_r_c(Resource, Class) :- 186 ( rdf_has(Resource, rdf:type, MyClass) 187 *-> rdfs_subclass_of(MyClass, Class) 188 ; rdf_equal(Class, rdfs:'Resource') 189 ).
199rdfs_label(Resource, Label) :-
200 rdfs_label(Resource, _, Label).
209rdfs_label(Resource, Lang, Label) :- 210 nonvar(Resource), 211 !, 212 take_label(Resource, Lang, Label). 213rdfs_label(Resource, Lang, Label) :- 214 rdf_has(Resource, rdfs:label, literal(lang(Lang, Label))).
224rdfs_ns_label(Resource, Label) :- 225 rdfs_ns_label(Resource, _, Label). 226 227rdfs_ns_label(Resource, Lang, Label) :- 228 rdfs_label(Resource, Lang, Label0), 229 ( rdf_global_id(NS:_, Resource), 230 Label0 \== '' 231 -> atomic_list_concat([NS, Label0], :, Label) 232 ; \+ rdf_has(Resource, rdfs:label, _) 233 -> Label = Resource 234 ; member(Sep, [#,/]), 235 sub_atom(Resource, B, L, A, Sep), 236 sub_atom(Resource, _, A, 0, Frag), 237 \+ sub_atom(Frag, _, _, _, Sep) 238 -> Len is B+L, 239 sub_atom(Resource, 0, Len, _, NS), 240 atomic_list_concat([NS, Label0], :, Label) 241 ; Label = Label0 242 ).
251take_label(Resource, Lang, Label) :- 252 ( label_of(Resource, Lang, Label) 253 *-> true 254 ; after_char(Resource, '#', Local) 255 -> Label = Local 256 ; after_char(Resource, '/', Local) 257 -> Label = Local 258 ; Label = Resource 259 ). 260 261after_char(Atom, Char, Rest) :- 262 State = last(-), 263 ( sub_atom(Atom, _, _, L, Char), 264 nb_setarg(1, State, L), 265 fail 266 ; arg(1, State, L), 267 L \== (-) 268 ), 269 sub_atom(Atom, _, L, 0, Rest).
rdf_has(Resource, rdfs:label, literal(Lang, Label))
is
true, but guaranteed to generate rdfs:label before any
subproperty thereof.278label_of(Resource, Lang, Label) :- 279 rdf(Resource, rdfs:label, literal(lang(Lang, Label))), 280 nonvar(Lang). 281label_of(Resource, Lang, Label) :- 282 rdf_equal(rdfs:label, LabelP), 283 rdf_has(Resource, LabelP, literal(lang(Lang, Label)), P), 284 nonvar(Lang), 285 P \== LabelP. 286label_of(Resource, Lang, Label) :- 287 var(Lang), 288 rdf_has(Resource, rdfs:label, literal(type(xsd:string, Label))).
294rdfs_class_property(Class, Property) :- 295 rdfs_individual_of(Property, rdf:'Property'), 296 rdf_has(Property, rdfs:domain, Domain), 297 rdfs_subclass_of(Class, Domain). 298 299 300 /******************************* 301 * COLLECTIONS * 302 *******************************/
309rdfs_member(Element, Set) :- 310 rdf_has(Set, rdf:first, _), 311 !, 312 rdfs_collection_member(Element, Set). 313rdfs_member(Element, Set) :- 314 container_class(Class), 315 rdfs_individual_of(Set, Class), 316 !, 317 ( nonvar(Element) 318 -> rdf(Set, Predicate, Element), 319 rdf_member_property(Predicate, _N) 320 ; findall(N-V, rdf_nth(Set, N, V), Pairs), 321 keysort(Pairs, Sorted), 322 member(_-Element, Sorted) 323 ). 324 325rdf_nth(Set, N, V) :- 326 rdf(Set, P, V), 327 rdf_member_property(P, N). 328 329:- rdf_meta container_class(r). 330 331container_class(rdf:'Bag'). 332container_class(rdf:'Seq'). 333container_class(rdf:'Alt'). 334 335 336rdfs_collection_member(Element, Set) :- 337 rdf_has(Set, rdf:first, Element). 338rdfs_collection_member(Element, Set) :- 339 rdf_has(Set, rdf:rest, Tail), 340 !, 341 rdfs_collection_member(Element, Tail).
349rdfs_list_to_prolog_list(Set, []) :- 350 rdf_equal(Set, rdf:nil), 351 !. 352rdfs_list_to_prolog_list(Set, [H|T]) :- 353 rdf_has(Set, rdf:first, H), 354 rdf_has(Set, rdf:rest, Tail), 355 !, 356 rdfs_list_to_prolog_list(Tail, T).
364rdfs_assert_list(Resources, List) :- 365 rdfs_assert_list(Resources, List, user). 366 367rdfs_assert_list([], Nil, _) :- 368 rdf_equal(rdf:nil, Nil). 369rdfs_assert_list([H|T], List, DB) :- 370 rdfs_assert_list(T, Tail, DB), 371 rdf_bnode(List), 372 rdf_assert(List, rdf:rest, Tail, DB), 373 rdf_assert(List, rdf:first, H, DB), 374 rdf_assert(List, rdf:type, rdf:'List', DB). 375 376 377 /******************************* 378 * SEARCH IN HIERARCHY * 379 *******************************/
domain is defined by owl_satisfy from owl.pl
Note that the rdfs:label field is handled by rdfs_label/2, making the URI-ref fragment name the last resort to determine the label.
397rdfs_find(String, Domain, Fields, Method, Subject) :- 398 var(Fields), 399 !, 400 For =.. [Method,String], 401 rdf_has(Subject, Field, literal(For, _)), 402 owl_satisfies(Domain, Subject), 403 Fields = [Field]. % report where we found it. 404rdfs_find(String, Domain, Fields, Method, Subject) :- 405 globalise_list(Fields, GlobalFields), 406 For =.. [Method,String], 407 member(Field, GlobalFields), 408 ( Field == resource 409 -> rdf_subject(Subject), 410 rdf_match_label(Method, String, Subject) 411 ; rdf_has(Subject, Field, literal(For, _)) 412 ), 413 owl_satisfies(Domain, Subject). 414 415owl_satisfies(Domain, _) :- 416 rdf_equal(rdfs:'Resource', Domain), 417 !. 418 % Descriptions 419owl_satisfies(class(Domain), Resource) :- 420 !, 421 ( rdf_equal(Domain, rdfs:'Resource') 422 -> true 423 ; rdfs_subclass_of(Resource, Domain) 424 ). 425owl_satisfies(union_of(Domains), Resource) :- 426 !, 427 member(Domain, Domains), 428 owl_satisfies(Domain, Resource), 429 !. 430owl_satisfies(intersection_of(Domains), Resource) :- 431 !, 432 in_all_domains(Domains, Resource). 433owl_satisfies(complement_of(Domain), Resource) :- 434 !, 435 \+ owl_satisfies(Domain, Resource). 436owl_satisfies(one_of(List), Resource) :- 437 !, 438 memberchk(Resource, List). 439 % Restrictions 440owl_satisfies(all_values_from(Domain), Resource) :- 441 ( rdf_equal(Domain, rdfs:'Resource') 442 -> true 443 ; rdfs_individual_of(Resource, Domain) 444 ), 445 !. 446owl_satisfies(some_values_from(_Domain), _Resource) :- !. 447owl_satisfies(has_value(Value), Resource) :- 448 rdf_equal(Value, Resource). 449 450 451in_all_domains([], _). 452in_all_domains([H|T], Resource) :- 453 owl_satisfies(H, Resource), 454 in_all_domains(T, Resource). 455 456globalise_list([], []) :- !. 457globalise_list([H0|T0], [H|T]) :- 458 !, 459 globalise_list(H0, H), 460 globalise_list(T0, T). 461globalise_list(X, G) :- 462 rdf_global_id(X, G)
RDFS handling
This module provides various primitives for more high-level handling of RDF models from an RDFS viewpoint. Note that there exist two approaches for languages on top of RDF: