Chris@0: /* $Id$ Chris@0: Chris@0: Part of SWI-Prolog Chris@0: Chris@0: Author: Jan Wielemaker Chris@0: E-mail: jan@swi.psy.uva.nl Chris@0: WWW: http://www.swi-prolog.org Chris@0: Copyright (C): 1985-2002, University of Amsterdam Chris@0: Chris@0: This program is free software; you can redistribute it and/or Chris@0: modify it under the terms of the GNU General Public License Chris@0: as published by the Free Software Foundation; either version 2 Chris@0: of the License, or (at your option) any later version. Chris@0: Chris@0: This program is distributed in the hope that it will be useful, Chris@0: but WITHOUT ANY WARRANTY; without even the implied warranty of Chris@0: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the Chris@0: GNU General Public License for more details. Chris@0: Chris@0: You should have received a copy of the GNU Lesser General Public Chris@0: License along with this library; if not, write to the Free Software Chris@0: Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Chris@0: Chris@0: As a special exception, if you link this library with other files, Chris@0: compiled with a Free Software compiler, to produce an executable, this Chris@0: library does not by itself cause the resulting executable to be covered Chris@0: by the GNU General Public License. This exception does not however Chris@0: invalidate any other reasons why the executable file might be covered by Chris@0: the GNU General Public License. Chris@0: */ Chris@0: Chris@0: Chris@0: :- module(rdf_portray, Chris@0: [ rdf_portray_as/1, % +Style Chris@0: rdf_portray_lang/1 % +Lang Chris@0: ]). Chris@0: :- use_module(library(semweb/rdf_db)). Chris@0: :- use_module(library(semweb/rdfs)). Chris@0: :- use_module(library(error)). Chris@0: Chris@0: /** Portray RDF resources Chris@0: Chris@0: This module defines rules for user:portray/1 to help tracing and Chris@0: debugging RDF resources by printing them in a more concise Chris@0: representation and optionally adding comment from the label field to het Chris@0: the user interpreting the URL. The main predicates are: Chris@0: Chris@0: * rdf_portray_as/1 defines the overall style Chris@0: * rdf_portray_lang/1 selects languages for extracting label comments Chris@0: Chris@0: @tbd Define alternate predicate to use for providing a comment Chris@0: @tbd Use type if there is no meaningful label? Chris@0: @tbd Smarter guess whether or not the local identifier might be Chris@0: meaningful to the user without a comment. I.e. does it look Chris@0: `word-like'? Chris@0: */ Chris@0: Chris@0: :- dynamic Chris@0: style/1, Chris@0: lang/1. Chris@0: Chris@0: %% rdf_portray_as(+Style) is det. Chris@0: % Chris@0: % Set the style used to portray resources. Style is one of: Chris@0: % Chris@0: % * ns:id Chris@0: % Write as NS:ID, compatible with what can be handed to Chris@0: % the rdf predicates. This is the default. Chris@0: % Chris@0: % * writeq Chris@0: % Use quoted write of the full resource. Chris@0: % Chris@0: % * ns:label Chris@0: % Write namespace followed by the label. This format Chris@0: % cannot be handed to rdf/3 and friends, but can be Chris@0: % useful if resource-names are meaningless identifiers. Chris@0: % Chris@0: % * ns:id=label Chris@0: % This combines ns:id with ns:label, providing both human Chris@0: % readable output and output that can be pasted into the Chris@0: % commandline. Chris@0: Chris@0: rdf_portray_as(Style) :- Chris@0: must_be(oneof([writeq, ns:id, ns:label, ns:id=label]), Style), Chris@0: retractall(style(_)), Chris@0: assert(style(Style)). Chris@0: Chris@0: %% rdf_portray_lang(+Lang) is det. Chris@0: % Chris@0: % If Lang is a list, set the list or preferred languages. If it is Chris@0: % a single atom, push this language as the most preferred Chris@0: % language. Chris@0: Chris@0: rdf_portray_lang(Lang) :- Chris@0: ( is_list(Lang) Chris@0: -> must_be(list(atom), Lang), Chris@0: retractall(lang(_)), Chris@0: forall(member(L,Lang), assert(lang(L))) Chris@0: ; must_be(atom, Lang), Chris@0: asserta(lang(Lang)) Chris@0: ). Chris@0: Chris@0: try_lang(L) :- lang(L). Chris@0: try_lang(_). Chris@0: Chris@0: Chris@0: :- multifile Chris@0: user:portray/1. Chris@0: Chris@0: user:portray(URL) :- Chris@0: atom(URL), Chris@0: sub_atom(URL, 0, _, _, 'http://'), !, Chris@0: ( style(Style) Chris@0: -> true Chris@0: ; Style = ns:id Chris@0: ), Chris@0: portray_url(Style, URL). Chris@0: user:portray(URL) :- Chris@0: atom(URL), Chris@0: atom_concat('__file://', URL2, URL), Chris@0: sub_atom(URL2, S, _, A, #), Chris@0: sub_atom(URL2, _, A, 0, Local), Chris@0: sub_atom(URL2, 0, S, _, Path), Chris@0: file_base_name(Path, Base), Chris@0: format('__~w#~w', [Base, Local]). Chris@0: Chris@0: portray_url(writeq, URL) :- Chris@0: writeq(URL). Chris@0: portray_url(ns:id, URL) :- Chris@0: ( rdf_global_id(NS:Id, URL) Chris@0: -> writeq(NS:Id) Chris@0: ; writeq(URL) Chris@0: ). Chris@0: portray_url(ns:id=label, URL) :- Chris@0: ( rdf_global_id(NS:Id, URL) Chris@0: -> Value = NS:Id Chris@0: ; Value = URL Chris@0: ), Chris@0: ( Id \== '', Chris@0: ( ( try_lang(Lang), Chris@0: rdf_has(URL, rdfs:label, literal(lang(Lang, Label))) Chris@0: -> nonvar(Lang), Chris@0: \+ label_is_id(Label, Id) Chris@0: ) Chris@0: -> format('~q/*"~w"@~w*/', [Value, Label, Lang]) Chris@0: ; rdf_has(URL, rdfs:label, literal(type(Type, Label))), Chris@0: nonvar(Type), Chris@0: \+ label_is_id(Label, Id) Chris@0: -> ( rdf_global_id(TNS:TId, Type) Chris@0: -> TVal = TNS:TId Chris@0: ; TVal = Type Chris@0: ), Chris@0: format('~q/*"~w"^^~w*/', [Value, Label, TVal]) Chris@0: ; rdf_has(URL, rdfs:label, literal(Label)), Chris@0: atom(Label), Chris@0: Label \== Id Chris@0: -> format('~q/*"~w"*/', [Value, Label]) Chris@0: ) Chris@0: -> true Chris@0: ; writeq(Value) Chris@0: ). Chris@0: portray_url(ns:label, URL) :- Chris@0: rdfs_ns_label(URL, Label), Chris@0: write(Label). Chris@0: Chris@0: label_is_id(_, Var) :- Chris@0: var(Var), !, fail. Chris@0: label_is_id(Label, Label) :- !. Chris@0: label_is_id(L0, L1) :- Chris@0: downcase_atom(L0, Lwr), Chris@0: downcase_atom(L1, Lwr). Chris@0: