Daniel@0: /* Part of DML (Digital Music Laboratory) Daniel@0: Copyright 2014-2015 Samer Abdallah, University of London Daniel@0: Daniel@0: This program is free software; you can redistribute it and/or Daniel@0: modify it under the terms of the GNU General Public License Daniel@0: as published by the Free Software Foundation; either version 2 Daniel@0: of the License, or (at your option) any later version. Daniel@0: Daniel@0: This program is distributed in the hope that it will be useful, Daniel@0: but WITHOUT ANY WARRANTY; without even the implied warranty of Daniel@0: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the Daniel@0: GNU General Public License for more details. Daniel@0: Daniel@0: You should have received a copy of the GNU General Public Daniel@0: License along with this library; if not, write to the Free Software Daniel@0: Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Daniel@0: */ Daniel@0: Daniel@0: :- module(rdfutils, Daniel@0: [ rdf_number/3 , rdf_number/4 Daniel@0: , rdf_text/4 , rdf_text/3 Daniel@0: , rdf_search/5, rdf_search/4 Daniel@0: , literal_number/2 Daniel@0: , literal_text/2 Daniel@0: , (a)/2 Daniel@0: , op(700,xfx,a) Daniel@0: , parse_duration_millis/2 Daniel@0: , as_typed_literal/2 Daniel@0: , rdf_list_take/4 Daniel@0: , rdf_list_length/2 Daniel@0: , rdfx/3 Daniel@0: , op(700,xfx,~=) Daniel@0: , (~=)/2 Daniel@0: ]). Daniel@0: Daniel@0: :- use_module(library(semweb/rdf_db)). Daniel@0: :- use_module(library(semweb/rdf_label)). Daniel@0: :- use_module(library(semweb/rdfs)). Daniel@0: Daniel@0: :- rdf_meta rdf_text(r,r,-), Daniel@0: rdf_text(r,r,-,+), Daniel@0: rdf_number(r,r,-), Daniel@0: rdf_number(r,r,-,+), Daniel@0: rdf_search(+,r,r,+,-), Daniel@0: rdf_search(+,r,r,+), Daniel@0: a(r,r). Daniel@0: Daniel@0: X a Y :- rdfs_individual_of(Y,X). Daniel@0: Daniel@0: rdf_text(S,P,Text) :- rdf(S,P,L), literal_text(L,Text). Daniel@0: rdf_text(S,P,Text,G) :- rdf(S,P,L,G), literal_text(L,Text). Daniel@0: Daniel@0: rdf_number(S,P,Num) :- Daniel@0: ( var(Num) Daniel@0: -> rdf(S,P,literal(Lit)), literal_number(Lit,Num) Daniel@0: ; literal_number(Lit,Num), rdf(S,P,literal(Lit)) Daniel@0: ). Daniel@0: Daniel@0: rdf_number(S,P,Num,G) :- Daniel@0: ( var(Num) Daniel@0: -> rdf(S,P,literal(Lit),G), literal_number(Lit,Num) Daniel@0: ; literal_number(Lit,Num), rdf(S,P,literal(Lit),G) Daniel@0: ). Daniel@0: Daniel@0: literal_number(type(_Type,A),N) :- number(A) -> N=A; atom_number(A,N). Daniel@0: literal_number(Atom,Num) :- atomic(Atom), atom_number(Atom,Num). Daniel@0: Daniel@0: %% rdf_search(+T:match_type,?Subj:uri,?Pred:uri, +Needle:atom, -Val:atom) is nondet. Daniel@0: %% rdf_search(+T:match_type,?Subj:uri,?Pred:uri, +Needle:atom) is nondet. Daniel@0: % Convenience predicate for using rdf/3 with a literal search specifier - this Daniel@0: % version is more amenable for use with maplist and other metapredicates. Daniel@0: % Match types (see rdf/3) are: Daniel@0: % == Daniel@0: % match_type ---> substring; case; prefix; exact; plain; word; like. Daniel@0: % == Daniel@0: rdf_search(T,S,P,X,Y) :- Q=..[T,X], rdf(S,P,literal(Q,Y)). Daniel@0: rdf_search(T,S,P,X) :- rdf_search(T,S,P,X,_). Daniel@0: Daniel@0: % :- rdf_meta type_text_val(r,+,-). Daniel@0: % lit_decode(literal(type(Type,Val)),X) :- type_text_val(Type,Val,X). Daniel@0: % type_text_val(xsd:decimal,V,X) :- atom_number(V,X). Daniel@0: % type_text_val(xsd:integer,V,X) :- atom_number(V,X), must_be(integer,X). Daniel@0: Daniel@0: parse_duration_millis(Atom,Dur) :- Daniel@0: split_string(Atom,':','',Parts), Daniel@0: ( Parts=[HS,MS,SS] Daniel@0: -> number_string(H,HS), Daniel@0: number_string(M,MS), Daniel@0: number_string(S,SS) Daniel@0: ; Parts=[MS,SS] Daniel@0: -> number_string(M,MS), Daniel@0: number_string(S,SS), Daniel@0: H=0 Daniel@0: ), Daniel@0: Dur is 1000*(60*(60*H + M) + S). Daniel@0: Daniel@0: :- rdf_meta xsd_type(+,r). Daniel@0: xsd_type(X,xsd:integer) :- integer(X), !. Daniel@0: xsd_type(X,xsd:double) :- float(X), !. Daniel@0: Daniel@0: as_typed_literal(X,X) :- atom(X), !. Daniel@0: as_typed_literal(X,Y) :- string(X), !, atom_string(Y,X). Daniel@0: as_typed_literal(X,type(Type,X)) :- xsd_type(X,Type). Daniel@0: Daniel@0: :- rdf_meta rdf_list_take(+,r,-,r), Daniel@0: rdf_list_length(r,-). Daniel@0: Daniel@0: rdf_list_take(0,List,[],List) :- !. Daniel@0: rdf_list_take(_,rdf:nil,[],rdf:nil) :- !. Daniel@0: rdf_list_take(N,List,[H|T],Tail) :- Daniel@0: succ(M,N), Daniel@0: rdf(List,rdf:first,H), Daniel@0: rdf(List,rdf:rest,More), Daniel@0: rdf_list_take(M,More,T,Tail). Daniel@0: Daniel@0: rdf_list_length(rdf:nil,0) :- !. Daniel@0: rdf_list_length(List,N) :- Daniel@0: rdf(List,rdf:rest,More), Daniel@0: rdf_list_length(More,M), Daniel@0: succ(M,N). Daniel@0: Daniel@0: X ~= Match :- match(Match,X). Daniel@0: match(Match,literal(O)) :- Daniel@0: must_be(var,O), Daniel@0: ( get_attr(O,rdfutils,match(Matches)) -> true; Matches=[]), Daniel@0: put_attr(O,rdfutils,match([Match|Matches])). Daniel@0: Daniel@0: :- rdf_meta rdfx(r,t,o). Daniel@0: rdfx(S,Q,literal(O)) :- Daniel@0: ( get_attr(O,rdfutils,match(Matches)) Daniel@0: -> maplist(rdf_matches(Q,S,O),Matches) Daniel@0: ; Q=exact(P), rdf(S,P,literal(O)) Daniel@0: ; Q=sub(P), rdf_has(S,P,literal(O)) Daniel@0: ). Daniel@0: Daniel@0: rdf_matches(exact(P),S,O,M) :- rdf(S,P,literal(M,O)). Daniel@0: rdf_matches(sub(P),S,O,M) :- rdf_has(S,P,literal(M,O)). Daniel@0: Daniel@0: attr_unify_hook(_,_). Daniel@0: attr_portray_hook(match(Matches),Var) :- writeq(Var:Matches).