1/* -*- Mode: Prolog -*- */ 2 3:- module(rdfs2pl, 4 [assert_schema/2, 5 assert_schema/1, 6 write_schema/3, 7 write_schema/2]).
13:- use_module(library(semweb/rdf11)). 14:- use_module(library(semweb/rdfs)). 15 16:- dynamic clause_comment/2.
21assert_schema(Local,Global):- 22 rdf_register_ns(Local,Global), 23 assert_clauses(Local). 24 25assert_schema(Local):- 26 rdf_current_prefix(Local,_), 27 assert_clauses(Local). 28 29assert_clauses(M):- 30 forall(inf_clause(M,X,[]), 31 M:assert(X)).
E.g. write_schema(bp2,'http://www.biopax.org/release/biopax-level2.owl#')
38write_schema(Local,Opts):- 39 write_schema(Local,_,Opts). 40write_schema(Local,Global,Opts):- 41 ( var(Global) 42 -> ( rdf_current_prefix(Local,Global) 43 -> true 44 ; true) 45 ; rdf_register_ns(Local,Global)), 46 write_module_schema(Local,[module(Local)|Opts]). 47 48% prolog program consists of header and clauses 49write_module_schema(M,Opts):- 50 write_header(M,Opts), 51 write_clauses(M,Opts). 52 53% header consists of module declaration and exports directives 54write_header(M,Opts):- 55 format('%% <module> ~w~n',[M]), 56 format('% Autogenerated by rdfs2pl -- see https://github.com/cmungall/rdfs2pl/~n',[]), 57 nl, 58 findall(E,mod_exports(M,E,Opts),Exports), 59 writep( (:- module(M,Exports)) ), 60 writep( (:- use_module(library(semweb/rdf11))) ), 61 writep( (:- use_module(library(semweb/rdfs))) ), 62 nl, 63 forall((mod_exports(M,Op,Opts),Op=op(_,_,_)), 64 writep( (:- Op) )), 65 nl. 66 67write_clauses(M,Opts):- 68 setof(X,inf_clause(M,X,Opts),Xs), 69 maplist(write_clause,Xs). 70 71write_clause(X):- 72 %X=..[_,Head|Args], 73 %Head =.. [_,_,Head2], 74 %format('%% ~w.~n',[Head2]), 75 %format('%~n'), 76 ( clause_comment(X,Comment) 77 -> write(Comment) 78 ; true), 79 writep(X), 80 nl. 81 82 83%%%% 84% UTIL 85%%%%
91maketerm(URI,Args,Term):- 92 maketerm(URI,Args,Term,_,_,[]). 93maketerm(URI,Args,Term,Opts):- 94 maketerm(URI,Args,Term,_,_,Opts).
note: NS not used
103maketerm(URI,Args,Term,_NS,_Functor,Opts):- 104 member(use_labels(true),Opts), 105 ont_label(URI,Label), 106 member(module(M),Opts), 107 !, 108 psafe(Label,Pred,Opts), 109 debug(schema,' pred= ~w ',[Pred]), 110 T=..[Pred|Args], 111 Term=..[':',M,T]. 112 113maketerm(URI,Args,Term,NS,Functor,Opts):- 114 rdf_global_id(NS:Functor,URI), 115 debug(schema,' P2P ~w ',[Functor]), 116 property_to_predicate(Functor,FunctorSafe,Opts), 117 T1=..[FunctorSafe|Args], 118 Term=..[':',NS,T1]. 119 120make_comment(Clause, _:Term, class, Obj) :- 121 numbervars(Term,8,_), 122 sformat(S,'%! ~w~n%~n% Any instance of <~w>~n%~n',[Term,Obj]), 123 assert(clause_comment(Clause,S)), 124 make_comment_from_def(Clause,Obj). 125make_comment(Clause, _:Term, property, Obj) :- 126 numbervars(Term,8,_), 127 sformat(S,'%! ~w~n%~n% Any relationship of type <~w>~n%~n',[Term,Obj]), 128 assert(clause_comment(Clause,S)), 129 make_comment_from_def(Clause,Obj). 130 131make_aux_comment(Clause, _:Term, Aux) :- 132 numbervars(Term,8,_), 133 Term =.. [P|_], 134 sformat(S,'%! ~w~n%~n% As ~w/2 ~w~n%~n',[Term,P,Aux]), 135 assert(clause_comment(Clause,S)). 136 137make_comment_from_def(Clause,Obj) :- 138 ont_desc(Obj,Desc), 139 sformat(S,'% _|~w|_~n',[Desc]), 140 assert(clause_comment(Clause,S)), 141 !. 142make_comment_from_def(_,_). 143 144 145 146cls(C,Opts) :- 147 % call unique 148 setof(C,cls1(C,Opts),Cs), 149 member(C,Cs). 150 151cls1(C,Opts) :- 152 \+ member( exclude_classes(true), Opts), 153 rdfs_individual_of(C,owl:'Class'), 154 \+ rdf_is_bnode(C).
161inf_clause(NS, Clause, Opts) :- 162 inf_clause_meta(NS, Clause, _, Opts). 163inf_clause(NS, Directive, Opts) :- 164 inf_clause_meta(NS, _, Meta, Opts), 165 make_meta_directive(Meta, Directive).
side effect: asserts clause_comment/2
177% ## CLASSES 178% 179% represented by unary predicates 180 181% unary predicate: C(I) 182inf_clause_meta( _NS, (Head:-Body), Meta, Opts):- 183 cls(C,Opts), 184 maketerm(C,[r],Meta,Opts), 185 maketerm(C,[I],Head,Opts), 186 ( member(expand_subclass(Opts,true),Opts) 187 *-> ( Body=rdf(I,rdf:type,C), 188 make_comment( (Head:-Body), Head, class, C) 189 ; rdfs_subclass_of(D,C), 190 Body=rdf(I,rdf:type,D)) 191 ; Body=rdfs_individual_of(I,C), 192 make_comment( (Head:-Body), Head, class, C)). 193 194% ## Properties 195% 196% represented by binary+ predicates 197 198% basic binary predicate: P(S,O) 199inf_clause_meta( NS, (Head:-Body), Meta, Opts ):- 200 property(R), 201 maketerm(R,[r,r],Meta,NS,_,Opts), 202 maketerm(R,[Subj,Obj],Head,NS,_F,Opts), 203 make_comment( (Head:-Body), Head, property, R), 204 Body=rdf_has(Subj,R,Obj). 205 206% ternary predicate with graph: P(S,O,G) 207inf_clause_meta( NS, (Head:-Body), Meta, Opts ):- 208 property(R), 209 maketerm(R,[r,r,g],Meta,NS,_,Opts), 210 maketerm(R,[Subj,Obj,G],Head,NS,_F,Opts), 211 Body=rdf(Subj,R,Obj,G), 212 make_aux_comment( (Head:-Body), Head, ' where asserted in graph'). 213 214% quad predicate with graph and reified node: P(S,O,G,N) 215inf_clause_meta( NS, (Head:-Body), Meta, Opts ):- 216 property(R), 217 member(reify(true), Opts), 218 NOpts=[suffix(node)|Opts], 219 maketerm(R,[r,r,g,r],Meta,NS,_,NOpts), 220 maketerm(R,[Subj,Obj,G,Node],Head,NS,_F,NOpts), 221 Body=(rdf(Subj,R,Obj,G), 222 rdf(Node,rdf:subject,Subj), 223 rdf(Node,rdf:predicate,R), 224 rdf(Node,rdf:object,Obj)), 225 make_aux_comment( (Head:-Body), Head, ', where asserted in graph and rdf-reified by node'). 226 227 228% ternary predicate with reified node, no graph: P_node(S,O,N) 229inf_clause_meta( NS, (Head:-Body), Meta, Opts ):- 230 property(R), 231 member(reify(true), Opts), 232 NOpts=[suffix(node)|Opts], 233 maketerm(R,[r,r,r],Meta,NS,_,NOpts), 234 maketerm(R,[Subj,Obj,Node],Head,NS,_F,NOpts), 235 Body=(rdf(Subj,R,Obj), 236 rdf(Node,rdf:subject,Subj), 237 rdf(Node,rdf:predicate,R), 238 rdf(Node,rdf:object,Obj)). 239 240% generate subclass_of_P(S,O) from property P 241inf_clause_meta( NS, (Head:-Body), Meta, Opts ):- 242 rdfs_individual_of(R,owl:'ObjectProperty'), 243 NOpts=[prefix(subclass_of)|Opts], 244 maketerm(R,[r,r],Meta,NS,_,NOpts), 245 maketerm(R,[Subj,Obj],Head,NS,_F,NOpts), 246 Body=(rdf(Subj,rdfs:subClassOf,Restr), 247 rdf(Restr,owl:onProperty,R), 248 rdf(Restr,owl:someValuesFrom,Obj)), 249 make_aux_comment( (Head:-Body), Head, ', TODO'). 250 251 252% generate P_axiom(S,O,G,N) from property P 253inf_clause_meta( NS, (Head:-Body), Meta, Opts ):- 254 property(R), 255 member(reify_owl(true), Opts), 256 NOpts = [suffix(axiom)|Opts], 257 maketerm(R,[r,r,g,r],Meta,NS,_,NOpts), 258 maketerm(R,[Subj,Obj,G,Axiom],Head,NS,_F,NOpts), 259 Body=(rdf(Subj,R,Obj,G), 260 rdf(Axiom,owl:annotatedSource,Subj), 261 rdf(Axiom,owl:annotatedProperty,R), 262 rdf(Axiom,owl:annotatedTarget,Obj)), 263 make_aux_comment( (Head:-Body), Head, ', where asserted in graph and owl-reified by node'). 264 265 266% generate P_axiom(S,O,N) from property P 267inf_clause_meta( NS, (Head:-Body), Meta, Opts ):- 268 property(R), 269 member(reify_owl(true), Opts), 270 NOpts = [suffix(axiom)|Opts], 271 maketerm(R,[r,r,r],Meta,NS,_,NOpts), 272 maketerm(R,[Subj,Obj,Axiom],Head,NS,_F,NOpts), 273 Body=(rdf(Subj,R,Obj), 274 rdf(Axiom,owl:annotatedSource,Subj), 275 rdf(Axiom,owl:annotatedProperty,R), 276 rdf(Axiom,owl:annotatedTarget,Obj)), 277 make_aux_comment( (Head:-Body), Head, ', where owl-reified by node'). 278 279 280 281property_to_predicate(R,Pred,Opts):- 282 property_to_predicate1(R,Pred0,Opts), 283 safe_predicate(Pred0,Pred,Opts). 284 285property_to_predicate1(R,Pred,Opts):- 286 member(use_labels(true),Opts), 287 !, 288 debug(schema,'FETCHING ~w ',[R]), 289 ont_label(R,Label), 290 debug(schema,'~w ==> ~w',[R,Label]), 291 downcase_atom(Label,R1), 292 concat_atom(L,'-',R1), 293 concat_atom(L,'_',Pred). 294property_to_predicate1(R,Pred,Opts):- 295 member(prolog_properties(true),Opts), 296 !, 297 downcase_atom(R,R1), 298 concat_atom(L,'-',R1), 299 concat_atom(L,'_',Pred). 300property_to_predicate1(R,R,_). 301 302safe_predicate(P1,P2,Opts):- 303 T=..[P1,_,_], 304 predicate_property(T,_), 305 !, 306 ( member(prefix(M),Opts) 307 -> concat_atom([M,P1],'_',P2) 308 ; atom_concat(P1,'_',P2)). 309safe_predicate(P,P,_). 310 311ont_label(X,Label) :- rdfs_label(X,Label),!. 312ont_label(X,Label) :- rdf(X,rdfs:label,S),S=literal(type(_,Label)). 313 314ont_desc(X,Label) :- rdf(X,'http://purl.obolibrary.org/obo/IAO_0000115',S),S=literal(type(_,Label)). 315 316 317 318mod_exports( NS, F/N, Opts):- 319 cls(C,Opts), 320 maketerm(C,[-], NS:Term,Opts), 321 functor(Term,F,N). 322 323mod_exports( NS, F/N, Opts ):- 324 property(R), 325 maketerm(R,[-,-], NS:Term,Opts), 326 functor(Term,F,N). 327 328mod_exports( NS, F/N, Opts ):- 329 property(R), 330 maketerm(R,[-,-,-], NS:Term,Opts), 331 functor(Term,F,N). 332 333mod_exports( NS, F/N, Opts ):- 334 property(R), 335 member(reify(true), Opts), 336 maketerm(R,[-,-,-], NS:Term,[suffix(node)|Opts]), 337 functor(Term,F,N). 338mod_exports( NS, F/N, Opts ):- 339 property(R), 340 member(reify(true), Opts), 341 maketerm(R,[-,-,-,-], NS:Term,[suffix(node)|Opts]), 342 functor(Term,F,N). 343 344mod_exports( NS, F/N, Opts ):- 345 property(R), 346 member(reify_owl(true), Opts), 347 maketerm(R,[-,-,-], NS:Term,[suffix(axiom)|Opts]), 348 functor(Term,F,N). 349mod_exports( NS, F/N, Opts ):- 350 property(R), 351 member(reify_owl(true), Opts), 352 maketerm(R,[-,-,-,-], NS:Term,[suffix(axiom)|Opts]), 353 functor(Term,F,N). 354 355mod_exports( NS, op(300,xfy,F), Opts ):- 356 option(ops(true),Opts,true), 357 property(R), 358 maketerm(R,[], NS:F,Opts). 359 360/* 361inf_op( NS, F, Opts ):- 362 rdfs_individual_of(C,owl:'ObjectProperty'), 363 rdf_global_id(NS:F0,C), 364 property_to_predicate(F0,F,Opts). 365 366inf_op( NS, F, Opts ):- 367 rdfs_individual_of(C,owl:'DatatypeProperty'), 368 rdf_global_id(NS:F0,C), 369 property_to_predicate(F0,F,Opts). 370*/ 371 372property(R) :- 373 setof(R,property1(R),Rs),member(R,Rs). % call unique 374 375property1(R) :- rdfs_individual_of(R,owl:'ObjectProperty'). 376property1(R) :- rdfs_individual_of(R,owl:'DatatypeProperty'). 377property1(R) :- rdfs_individual_of(R,owl:'AnnotationProperty'). 378property1(R) :- rdf(R,rdf:type,rdf:'Property'). 379 380 381writep(X):- 382 numbervars(X,8,_,[]), 383 writeq(X), 384 write('.'), 385 nl. 386 387 388 389% TODO 390reserved(member). 391 392suffix_reserved(A,B) :- 393 reserved(A), 394 !, 395 atom_concat(A,'_triple',B). 396suffix_reserved(A,A). 397 398psafe(N,Safe,Opts) :- 399 select(suffix(Suffix),Opts,Opts2), 400 !, 401 psafe(N,X,Opts2), 402 concat_atom([X,Suffix],'_',Safe). 403psafe(N,Safe,Opts) :- 404 select(prefix(Prefix),Opts,Opts2), 405 !, 406 psafe(N,X,Opts2), 407 concat_atom([Prefix,X],'_',Safe). 408psafe(N,Safe,_) :- 409 atom_chars(N,[C|L]), 410 downcase_atom(C,C2), 411 lsafe([C2|L],Cs2), 412 atom_chars(Safe1,Cs2), 413 suffix_reserved(Safe1,Safe). 414 415 416safe(N,Safe) :- 417 atom_chars(N,Cs), 418 lsafe(Cs,Cs2), 419 atom_chars(Safe,Cs2). 420 421lsafe([],[]). 422lsafe([H|L],[H2|L2]) :- 423 csafe(H,H2), 424 lsafe(L,L2). 425 426csafe(' ','_') :- !. 427csafe('-','_') :- !. 428csafe('_','_') :- !. 429csafe(C,C) :- 430 C @>= 'a', 431 C @=< 'z', 432 !. 433csafe(C,C) :- 434 C @>= 'A', 435 C @=< 'Z', 436 !. 437csafe(C,C) :- 438 C @>= '0', 439 C @=< '9', 440 !. 441csafe(_,'_'). 442 443 444make_meta_directive(Meta, (:- rdf_meta
compile an RDF schema to a prolog module
*/