35
36:- module(rdf_schema,
37 [ rdf_graph_schema/2 38 ]). 39:- use_module(library(semweb/rdf_db)). 40:- use_module(library(semweb/rdfs)). 41
42:- thread_local
43 schema_triple/3. 44:- multifile
45 known_schema_prefix/1.
53rdf_graph_schema(Data, Schema) :-
54 retractall(schema_triple(_,_,_)),
55 make_schema(Data),
56 findall(rdf(S,P,O), retract(schema_triple(S,P,O)), Schema).
57
58:- rdf_meta
59 assert_schema(r,r,o). 60
61assert_schema(S,P,O) :-
62 schema_triple(S,P,O),
63 !.
64assert_schema(S,P,O) :-
65 assert(schema_triple(S,P,O)).
66
67
68make_schema(Data) :-
69 forall(predicate_in_graph(Data, P),
70 define_predicate(P, Data)),
71 forall(type_in_graph(Data, Class),
72 define_type(Class)).
73
74known_schema_prefix(rdf).
75known_schema_prefix(rdfs).
76known_schema_prefix(owl).
77known_schema_prefix(skos).
78known_schema_prefix(dc).
79known_schema_prefix(dcterms).
80
81known_url(P) :-
82 known_schema_prefix(Prefix),
83 rdf_global_id(Prefix:_, P),
84 !.
85
86define_predicate(P, _) :-
87 known_url(P),
88 !.
89define_predicate(P, DataGraph) :-
90 copy_data(P),
91 assert_schema(P, rdf:type, rdf:'Property'),
92 assign_label(P),
93 predicate_statistics(DataGraph, P, _C,
94 _Subjects, _Objects,
95 Domains, Ranges),
96 ( Domains = [Dom]
97 -> assert_schema(P, rdfs:domain, Dom)
98 ; true
99 ),
100 ( Ranges = [Range]
101 -> assert_schema(P, rdfs:range, Range)
102 ; true
103 ).
104
105
106define_type(C) :-
107 known_url(C),
108 !.
109define_type(C) :-
110 copy_data(C),
111 assert_schema(C, rdf:type, rdfs:'Class'),
112 assign_label(C).
113
114
115assign_label(S) :-
116 ( rdf(S, rdfs:label, _)
117 -> true
118 ; rdfs_label(S, Label),
119 Label \== S
120 -> assert_schema(S, rdfs:label, literal(Label))
121 ; true
122 ).
123
124
125copy_data(S) :-
126 retractall(schema_triple(S,_,_)),
127 forall(rdf(S,P,O),
128 assert_schema(S,P,O)).
129
130
131 134
135predicate_in_graph(Graph, P) :-
136 rdf_current_predicate(P),
137 once(rdf(_,P,_,Graph)).
143:- thread_local
144 type_seen/1. 145
146type_in_graph(Graph, Class) :-
147 call_cleanup(type_in_graph2(Graph, Class),
148 retractall(type_seen(_))).
149
150type_in_graph2(Graph, Class) :-
151 subject_in_graph(Graph, S),
152 ( rdf(S, rdf:type, Class)
153 *-> true
154 ; rdf_equal(Class, rdfs:'Resource')
155 ),
156 ( type_seen(Class)
157 -> fail
158 ; assert(type_seen(Class))
159 ).
160
161
162subject_in_graph(Graph, S) :-
163 rdf_subject(S),
164 once(rdf(S, _, _, Graph)).
165
166predicate_statistics(Graph, P, C, Subjects, Objects, Domains, Ranges) :-
167 findall(S-O, rdf(S,P,O,Graph), Pairs),
168 length(Pairs, C),
169 pairs_keys_values(Pairs, Ss, Os),
170 sort(Ss, Subjects),
171 sort(Os, Objects),
172 resources_types(Subjects, Graph, Domains),
173 resources_types(Objects, Graph, Ranges).
174
175resources_types(URIs, Graph, Types) :-
176 findall(T, resource_type_in(URIs, Graph, T), TList),
177 sort(TList, Types).
178
179resource_type_in(List, Graph, T) :-
180 member(URI, List),
181 resource_type(URI, Graph, T).
185resource_type(URI, Graph, T) :-
186 ( URI = literal(Lit)
187 -> ( Lit = type(T, _)
188 -> true
189 ; rdf_equal(T, rdfs:'Literal')
190 )
191 ; rdf(URI, rdf:type, T, Graph)
192 *-> true
193 ; rdf_equal(T, rdfs:'Resource')
194 )