30
31:- module(cpa_user, []). 32
33:- use_module(rdfql(serql_xml_result)). 34:- use_module(library(http/http_open)). 35:- use_module(library(http/http_path)). 36:- use_module(library(http/html_head)). 37:- use_module(library(http/html_write)). 38:- use_module(library(http/js_write)). 39:- use_module(library(http/http_dispatch)). 40:- use_module(library(http/http_host)). 41:- use_module(library(http/cp_jquery)). 42:- use_module(api(rdflib)). 43:- use_module(user(user_db)). 44:- use_module(library(debug)). 45:- use_module(components(server_statistics)). 46:- use_module(components(query)). 47:- use_module(components(basics)). 48:- use_module(library(semweb/rdf_db)). 49:- use_module(library(semweb/rdf_library)). 50:- use_module(library(occurs)).
87:- http_handler(root('.'), root,
88 [ priority(-100) ]). 89:- http_handler(cliopatria(home), home,
90 [ priority(-100) ]). 91:- http_handler(cliopatria(admin), home,
92 [ id(admin) ]). 93:- http_handler(cliopatria('user/query'), query_form,
94 [id(sparql_query_form)]). 95:- http_handler(cliopatria('user/statistics'), statistics, []). 96:- http_handler(cliopatria('user/loadFile'), load_file_form, []). 97:- http_handler(cliopatria('user/loadURL'), load_url_form, []). 98:- http_handler(cliopatria('user/loadLibraryRDF'), load_library_rdf_form, []). 99:- http_handler(cliopatria('user/clearRepository'), clear_repository_form, []). 100:- http_handler(cliopatria('user/removeStatements'), remove_statements_form, []).
109root(Request) :-
110 redirect_create_admin(Request),
111 http_redirect(moved_temporary,
112 location_by_id(home),
113 Request).
114
115redirect_create_admin(Request) :-
116 \+ current_user(_), !,
117 http_redirect(moved_temporary,
118 location_by_id(create_admin),
119 Request).
120redirect_create_admin(_).
127home(Request) :-
128 redirect_create_admin(Request),
129 reply_decorated_file(html('welcome.html'), Request).
138reply_decorated_file(Alias, _Request) :-
139 absolute_file_name(Alias, Page, [access(read)]),
140 load_html_file(Page, DOM),
141 contains_term(element(title, _, Title), DOM),
142 contains_term(element(body, _, Body), DOM),
143 Style = element(style, _, _),
144 findall(Style, sub_term(Style, DOM), Styles),
145 append(Styles, Body, Content),
146 reply_html_page(cliopatria(html_file),
147 title(Title), Content).
148
149
150
158statistics(Request) :-
159 http_current_host(Request, Host, _Port, [global(true)]),
160 reply_html_page(cliopatria(default),
161 title('RDF statistics'),
162 [ div(id('rdf-statistics'),
163 [ h1([id(stattitle)], ['RDF statistics for ', Host]),
164 ol([id(toc)],
165 [ li(a(href('#ntriples'), 'Triples in database')),
166 li(a(href('#callstats'), 'Call statistics')),
167 li(a(href('#sessions'), 'Active sessions')),
168 li(a(href('#serverstats'), 'Server statistics'))
169 ]),
170 h2([id(ntriples)], 'Triples in database'),
171 \triple_statistics,
172 h2([id(callstats)],'Call statistics'),
173 \rdf_call_statistics_table,
174 h2([id(sessions)], 'Active sessions'),
175 \http_session_table,
176 h2([id(serverstats)], 'Server statistics'),
177 h3('Static workers and statistics:'),
178 \http_server_statistics,
179 h3('Defined dynamic worker pools:'),
180 \http_server_pool_table
181 ])
182 ]).
183
184
185triple_statistics -->
186 { rdf_statistics(triples(Total)),
187 graph_count(Count),
188 http_link_to_id(list_graphs, [], ListGraphs)
189 },
190 html(p([ 'The RDF store contains ', \n(human, Total), ' triples in ',
191 \n(human, Count), ' ', a(href(ListGraphs), graphs),
192 \using_core])).
193
194:- if((rdf_version(V),V<30000)). 195using_core -->
196 { rdf_statistics(core(Core)) }, !,
197 html([', using ', \n(human, Core), 'b memory']).
198:- endif. 199using_core -->
200 [].
201
202graph_count(Count) :-
203 aggregate_all(count, rdf_graph(_), Count).
209query_form(_Request) :-
210 reply_html_page(cliopatria(default),
211 title('Specify a query'),
212 [ \query_form([]),
213 \query_docs,
214 \warn_interactive
215 ]).
216
217
218
219warn_interactive -->
220 { http_location_by_id(sparql_query, HREF),
221 SparqlAPI = 'http://www.w3.org/TR/rdf-sparql-protocol/'
222 },
223 html([ br(clear(all)),
224 p(class(footnote),
225 [ 'This form is to test SPARQL queries ', i(interactively), '. ',
226 'Machines should use ', b([HREF,'?query=...']),
227 ', which provides a ',
228 a(href(SparqlAPI), 'SPARQL compliant HTTP API'), '.'
229 ])
230 ]).
231
232query_docs -->
233 html(ul([ li(a(href('http://www.w3.org/TR/rdf-sparql-query/'),
234 'SPARQL Documentation')),
235 li(a(href('http://rdf4j.org/'),
236 'Sesame and SeRQL site'))
237 ])).
243load_file_form(Request) :-
244 authorized(write(default, load(posted))),
245 reply_html_page(cliopatria(default),
246 title('Upload RDF'),
247 [ h1('Upload an RDF document'),
248
249 \explain_file_form,
250
251 form([ action(location_by_id(upload_data)),
252 method('POST'),
253 enctype('multipart/form-data')
254 ],
255 [ \hidden(resultFormat, html),
256 table(class(form),
257 [tr([ th(class(label), 'File:'),
258 td(input([ name(data),
259 id(filename),
260 type(file),
261 size(50)
262 ]))
263 ]),
264 tr([ th(class(label), 'Graph:'),
265 td(input([ name(baseURI),
266 id(namedgraph),
267 size(50)
268 ]))
269 ]),
270 tr(class(buttons),
271 [ th([align(right), colspan(2)],
272 input([ type(submit),
273 value('Upload now')
274 ]))
275 ])
276 ])
277 ]),
278 \graph_script(Request)
279 ]).
280
281explain_file_form -->
282 html({|html||
283<p>Upload RDF to the ClioPatria triple store. The uploaded file may
284contain <a href="http://www.w3.org/TR/REC-rdf-syntax/">RDF/XML</a>, <a
285href="http://www.w3.org/TR/turtle/">Turtle</a> or <a
286href="http://www.w3.org/TR/n-triples/">ntriples</a>. The file is
287processed using <a href="http://www.libarchive.org/"> libarchive</a>,
288which implies it can be a (nested) archive and may optionally be
289compressed. </p>
290
291<p>
292Alternatively you can use <a href="loadURL">loadURL</a> to load data from a web server.
293</p>
294 |}).
295
296
297graph_script(Request) -->
298 { http_public_host_url(Request, Host),
299 http_absolute_location(root(data/uploaded), Location, []),
300 string_concat(Host, Location, URL)
301 },
302 html_requires(jquery),
303 js_script({|javascript(URL)||
304$(function() {
305 if ( $("#filename").val() ) {
306 $("#namedgraph").val(URL+"/"+$("#filename").val());
307 }
308
309 $("#filename").on("change", function(ev) {
310 var filename = $(ev.target).val();
311 console.log("Changed file", filename);
312 $("#namedgraph").val(URL+"/"+filename);
313 });
314});
315 |}).
322load_url_form(_Request) :-
323 reply_html_page(cliopatria(default),
324 title('Load RDF from HTTP server'),
325 [ h1('Load RDF from HTTP server'),
326
327 \explain_url_form,
328
329 form([ action(location_by_id(upload_url)),
330 method('GET')
331 ],
332 [ \hidden(resultFormat, html),
333 table(class(form),
334 [tr([ th(class(label), 'URL:'),
335 td(input([ name(url),
336 id(url),
337 value('http://'),
338 size(50)
339 ]))
340 ]),
341 tr([ th(class(label), 'Graph:'),
342 td(input([ name(baseURI),
343 id(namedgraph),
344 value('http://'),
345 size(50)
346 ]))
347 ]),
348 tr(class(buttons),
349 [ td([align(right), colspan(2)],
350 input([ type(submit),
351 value('Load RDF')
352 ]))
353 ])
354 ])
355 ]),
356 \url_graph_script
357 ]).
358
359
360url_graph_script -->
361 html_requires(jquery),
362 js_script({|javascript||
363$(function() {
364 $("#url").on("change keyup", function(ev) {
365 var url = $(ev.target).val();
366 $("#namedgraph").val(url);
367 });
368});
369 |}).
370
371
372explain_url_form -->
373 html({|html||
374
375<p>Download RDF from an URL and insert it into the ClioPatria triple
376store. The downloaded document may contain <a
377href="http://www.w3.org/TR/REC-rdf-syntax/">RDF/XML</a>, <a
378href="http://www.w3.org/TR/turtle/">Turtle</a> or <a
379href="http://www.w3.org/TR/n-triples/">ntriples</a>. The file is
380processed using <a href="http://www.libarchive.org/"> libarchive</a>,
381which implies it can be a (nested) archive and may optionally be
382compressed. </p>
383
384<p>
385Alternatively you can use <a href="loadFile">loadFile</a> to upload
386a file through your browser.
387</p>
388 |}).
400load_library_rdf_form(Request) :-
401 authorized(read(status, listBaseOntologies)),
402 get_base_ontologies(Request, Ontologies),
403 reply_html_page(cliopatria(default),
404 title('Load server-side RDF library'),
405 [ h1('Load a registered RDF library'),
406 p('Select a resource from the registered libraries'),
407 \load_base_ontology_form(Ontologies)
408 ]).
417load_base_ontology_form(Ontologies) -->
418 html(form([ action(location_by_id(load_library_ontology)),
419 method('GET')
420 ],
421 [ \hidden(resultFormat, html),
422 table(class(form),
423 [ tr([ th('Ontology:'),
424 td(select(name(ontology),
425 [ option([], '')
426 | \emit_base_ontologies(Ontologies)
427 ]))
428 ]),
429 tr(class(buttons),
430 td([colspan(2), align(right)],
431 input([ type(submit),
432 value('Load')
433 ])))
434 ])
435 ])).
436
437
438emit_base_ontologies([]) -->
439 [].
440emit_base_ontologies([H|T]) -->
441 ( { rdf_library_index(H, title(Title)) }
442 -> html(option([value(H)], [H, ' -- ', Title]))
443 ; html(option([value(H)], H))
444 ),
445 emit_base_ontologies(T).
446
447
448get_base_ontologies(_Request, List) :-
449 catch(findall(O, library_ontology(O), List0), _, fail), !,
450 sort(List0, List).
451get_base_ontologies(Request, List) :-
452 http_current_host(Request, Host, Port, []),
453 http_location_by_id(list_base_ontologies, ListBaseOntos),
454 debug(base_ontologies, 'Opening http://~w:~w~w',
455 [Host, Port, ListBaseOntos]),
456 http_open([ protocol(http),
457 host(Host),
458 port(Port),
459 path(ListBaseOntos),
460 search([resultFormat(xml)])
461 ],
462 In,
463 [ 464 ]),
465 debug(base_ontologies, '--> Reading from ~w', [In]),
466 xml_read_result_table(In, Rows, _VarNames),
467 maplist(arg(1), Rows, List).
473clear_repository_form(_Request) :-
474 reply_html_page(cliopatria(default),
475 title('Clear triple store'),
476 [ h1('Clear entire repository'),
477
478 p(['This operation removes ', b(all), ' triples from \c
479 the RDF store.']),
480
481 form([ action(location_by_id(clear_repository)),
482 method('GET')
483 ],
484 [ \hidden(repository, default),
485 \hidden(resultFormat, html),
486 input([ type(submit),
487 value('Clear repository now')
488 ])
489 ])
490 ]).
497remove_statements_form(_Request) :-
498 reply_html_page(cliopatria(default),
499 title('Remove triples from store'),
500 [ h1('Remove statements'),
501
502 p(['Remove matching triples from the database. The three ',
503 'fields are in ntriples/Turtle notation. Omitted fields ',
504 'match any value.'
505 ]),
506
507 \remove_statements_form
508 ]).
509
510remove_statements_form -->
511 html(form([ action(location_by_id(remove_statements)),
512 method('GET')
513 ],
514 [ \hidden(repository, default),
515 \hidden(resultFormat, html),
516 table([ class(form)
517 ],
518 [ tr([ th(class(label), 'Subject:'),
519 td(input([ name(subject),
520 size(50)
521 ]))
522 ]),
523 tr([ th(class(label), 'Predicate:'),
524 td(input([ name(predicate),
525 size(50)
526 ]))
527 ]),
528 tr([ th(class(label), 'Object:'),
529 td(input([ name(object),
530 size(50)
531 ]))
532 ]),
533 tr(class(buttons),
534 [ td([ align(right),
535 colspan(2)
536 ],
537 input([ type(submit),
538 value('Remove')
539 ]))
540 ])
541 ])
542 ]))
This module contains the main front-end of ClioPatria. It notably provides the HTTP-handlers for / and /home:
If one develops an application on top of ClioPatria, it is adviced to redefine the handler for
home
, as in:If the application wants to provide a link to the generic ClioPatria administrative interface, it can do so by linking to the id=admin, as in:
*/