29
30:- module(swish_render_rdf,
31 [ term_rendering//3 32 ]). 33:- use_module(library(semweb/rdf11)). 34:- use_module(library(http/html_write)). 35:- use_module(library(option)). 36:- use_module(library(uri)). 37:- use_module(library(lists)). 38:- use_module(library(apply)). 39:- use_module(library(error)). 40:- use_module(library(broadcast)). 41
42:- use_module('../render'). 43
44:- register_renderer(rdf, "Render RDF terms"). 45
56
61
62term_rendering(List, _Vars, Options) -->
63 { is_list(List), List \== [],
64 maplist(is_rdf, List),
65 truncate(List, Truncated, Options)
66 },
67 html(span([class('rdf-list'), style('display:inline-block')],
68 \rdf_list(Truncated, Options))).
69term_rendering(Term, _Vars, Options) -->
70 { is_rdf(Term) }, !,
71 rdf_link(Term, [target('rdf-link')|Options]).
72
73rdf_list([], _) --> [].
74rdf_list([H|T], Options) -->
75 html(div(class('rdf-list-element'),
76 \rdf_list_elem(H, Options))),
77 rdf_list(T, Options).
78
79
80rdf_list_elem(skipped(Skipped), _) --> !,
81 html(span(class('rdf-list-skipped'),
82 '... skipped ~D ...'-[Skipped])).
83rdf_list_elem(Elem, Options) -->
84 rdf_link(Elem, [target('rdf-link')|Options]).
85
86truncate(List, Truncated, Options) :-
87 ( option(max_length(Max), Options)
88 -> true
89 ; current_prolog_flag(answer_write_options, WrOptions),
90 option(max_depth(Max), WrOptions)
91 ),
92 length(List, Len),
93 Len + 1 > Max,
94 Start is Max - 1,
95 Skipped is Len-Max,
96 length(Prefix, Start),
97 append(Prefix, _, List),
98 last(List, Last),
99 append(Prefix, [skipped(Skipped), Last], Truncated).
100truncate(List, List, _).
101
105
106is_rdf(Term) :-
107 is_uri(Term), !.
108is_rdf(literal(Value)) :-
109 is_literal(Value).
110is_rdf(^^(Value,Type)) :- atom(Type), ground(Value).
111is_rdf(@(Text,Lang)) :- atom(Lang), is_text(Text).
112
113is_uri(Term) :-
114 atom(Term),
115 ( uri_is_global(Term)
116 -> true
117 ; rdf_is_bnode(Term)
118 ).
119
120is_literal(Atomic) :- is_plain_literal(Atomic).
121is_literal(type(Type, Literal)) :- is_uri(Type), is_plain_literal(Literal).
122is_literal(lang(Lang, Literal)) :- atom(Lang), is_text(Literal).
123
124is_plain_literal(Value) :-
125 atomic(Value).
126
127is_text(Value) :- atom(Value), !.
128is_text(Value) :- string(Value).
129
131
132rdf_link(Text@Lang, _Options) --> !,
133 html(span(class('rdf-lang-literal'),
134 [ '"', span(class('rdf-lexical'), Text), '"@',
135 span(class('rdf-lang'), Lang)
136 ])).
137rdf_link(Value^^Type, Options) --> !,
138 { rdf_lexical_form(Value^^Type, String^^Type)
139 },
140 html(span(class('rdf-typed-literal'),
141 [ '"', span(class('rdf-lexical'), String), '"^^',
142 \rdf_link(Type, Options)
143 ])).
144rdf_link(literal(Literal), Options) --> !,
145 rdf_literal_link(Literal, Options).
146rdf_link(IRI, Options) -->
147 { rdf_global_id(Prefix:Local, IRI),
148 !,
149 a_options(IRI, Extra, Options)
150 },
151 html(a([href(IRI)|Extra],
152 [ span(class('rdf-pname'), Prefix), :,
153 span(class('rdf-local'), Local)
154 ])).
155rdf_link(IRI, Options) -->
156 { must_be(atom, IRI),
157 a_options(IRI, Extra, Options)
158 },
159 html(a([href(IRI)|Extra],
160 [ span(class('rdf-iri'), IRI)
161 ])).
162
163
164rdf_literal_link(type(Type,Value), Options) --> !,
165 rdf_link(Value^^Type, Options).
166rdf_literal_link(lang(Lang,Value), Options) --> !,
167 rdf_link(Value@Lang, Options).
168rdf_literal_link(Plain, Options) -->
169 { atom(Plain), !,
170 rdf_equal(String, xsd:string)
171 },
172 rdf_link(Plain^^String, Options).
173
174a_options(IRI, Extra, Options) :-
175 ( broadcast_request(rdf_label(IRI, Label))
176 -> Extra = [title(Label)|E1]
177 ; E1 = Extra
178 ),
179 ( option(target(Target), Options)
180 -> E1 = [target(Target)]
181 ; E1 = []
182 )