1:- encoding(utf8).
    2:- module(
    3  rdf_term,
    4  [
    5    rdf_atom_node/2,                     % ?Atom, ?Node
    6    rdf_atom_predicate/2,                % ?Atom, ?Predicate
    7    rdf_base_iri/1,                      % ?BaseIri
    8    rdf_canonical_lexical_form/3,        % +Datatype, +LexicalForm, -CanonicaldLexicalForm
    9    rdf_canonical_literal/2,             % +Literal, -CanonicalLiteral
   10    rdf_container_membership_property/1, % ?Property
   11    rdf_container_membership_property/2, % ?Property, ?Index
   12   %rdf_create_bnode/1,                  % --BNode
   13    rdf_create_iri/3,                    % +Alias, +TermOrTerms, -Iri
   14    rdf_hash_iri/3,                      % +Alias, +Term, -Iri
   15   %rdf_is_bnode/1,                      % @Term
   16    rdf_is_bnode_iri/1,                  % @Term
   17   %rdf_is_iri/1,                        % @Term
   18   %rdf_is_literal/1,                    % @Term
   19    rdf_is_name/1,                       % @Term
   20    rdf_is_numeric_literal/1,            % @Term
   21    rdf_is_object/1,                     % @Term
   22   %rdf_is_predicate/1,                  % @Term
   23    rdf_is_skip_node/1,                  % @Term
   24   %rdf_is_subject/1,                    % @Term
   25    rdf_is_term/1,                       % @Term
   26    rdf_language_tagged_string/3,        % ?LTag, ?LexicalForm, ?Literal
   27    rdf_lexical_value/3,                 % +Datatype, ?LexicalForm, ?Value
   28    rdf_literal/4,                       % ?Datatype, ?LTag, ?LexicalForm, ?Literal
   29    rdf_literal_datatype_iri/2,          % +Literal, ?Datatype
   30    rdf_literal_dwim/2,                  % +Dwim, ?Literal
   31    rdf_literal_lexical_form/2,          % +Literal, ?LexicalForm
   32    rdf_literal_value/2,                 % +Literal, -Value
   33    rdf_literal_value/3,                 % ?Literal, ?Datatype, ?Value
   34    rdf_node_dwim/2,                     % +Dwim, ?Term
   35    rdf_predicate_dwim/2,                % +Dwim, ?P
   36    rdf_triple_term/2,                   % +Triple, ?Term
   37    rdf_typed_literal/3,                 % ?Datatype, ?LexicalForm, ?Literal
   38    well_known_iri/1,                    % -Iri
   39    well_known_iri/2                     % +Segments, -Iri
   40  ]
   41).   42:- reexport(library(rdf_prefix)).

Advanced support for RDF terms

*/

   48:- use_module(library(apply)).   49:- use_module(library(error)).   50:- use_module(library(date_time)).   51:- use_module(library(lists)).   52:- reexport(library(semweb/rdf_db), [
   53     rdf_is_bnode/1,
   54     rdf_is_literal/1
   55   ]).   56:- reexport(library(semweb/rdf11), [
   57     rdf_create_bnode/1,
   58     rdf_is_iri/1,
   59     rdf_is_predicate/1,
   60     rdf_is_subject/1,
   61     op(110,xfx,@),
   62     op(650,xfx,^^)
   63   ]).   64:- use_module(library(semweb/turtle), []).   65:- use_module(library(settings)).   66:- use_module(library(uuid)).   67
   68:- use_module(library(dcg)).   69:- use_module(library(hash_ext)).   70:- use_module(library(plunit)).   71:- use_module(library(rdf_print)).   72:- use_module(library(string_ext)).   73:- use_module(library(uri_ext)).   74:- use_module(library(xsd)).   75:- use_module(library(xsd_grammar)).   76
   77:- discontiguous
   78    rdf_lexical_to_value/3,
   79    rdf_value_to_lexical/3.   80
   81:- dynamic
   82    rdf:rdf_lexical_to_value_hook/3,
   83    rdf:rdf_value_to_lexical_hook/3.   84
   85:- multifile
   86    error:has_type/2,
   87    prolog:message//1,
   88    rdf:rdf_lexical_to_value_hook/3,
   89    rdf:rdf_value_to_lexical_hook/3.   90
   91% IRI
   92error:has_type(iri, Term) :-
   93  rdf_is_iri(Term).
   94% blank node
   95error:has_type(rdf_bnode, Term) :-
   96  rdf_is_bnode(Term).
   97% graph name
   98error:has_type(rdf_graph_name, Term) :-
   99  error:has_type(iri, Term).
  100% literal
  101error:has_type(rdf_literal, Term) :-
  102  rdf_is_literal(Term).
  103% name
  104error:has_type(rdf_name,Term) :-
  105  error:has_type(iri, Term).
  106error:has_type(rdf_name,Term) :-
  107  error:has_type(rdf_literal, Term).
  108% node
  109error:has_type(rdf_node, Term) :-
  110  error:has_type(rdf_bnode, Term).
  111error:has_type(rdf_node, Term) :-
  112  error:has_type(rdf_name, Term).
  113% quadruple
  114error:has_type(rdf_quad, Term) :-
  115  Term = tp(S,P,O,G),
  116  error:has_type(maybe(rdf_node), S),
  117  error:has_type(maybe(iri), P),
  118  error:has_type(maybe(rdf_node), O),
  119  error:has_type(maybe(rdf_graph_name), G).
  120% triple
  121error:has_type(rdf_triple, Term) :-
  122  Term = tp(S,P,O),
  123  error:has_type(maybe(rdf_node), S),
  124  error:has_type(maybe(iri), P),
  125  error:has_type(maybe(rdf_node), O).
  126% tuple
  127error:has_type(rdf_tuple, Term) :-
  128  error:has_type(rdf_quad, Term).
  129error:has_type(rdf_tuple, Term) :-
  130  error:has_type(rdf_triple, Term).
  131
  132:- rdf_meta
  133   rdf_atom_node(?, o),
  134   rdf_atom_predicate(?, r),
  135   rdf_base_iri(r),
  136   rdf_canonical_lexical_form(r, +, -),
  137   rdf_canonical_literal(o, o),
  138   rdf_container_membership_property(r),
  139   rdf_container_membership_property(r, ?),
  140   rdf_is_bnode_iri(r),
  141   rdf_is_name(o),
  142   rdf_is_numeric_literal(o),
  143   rdf_is_object(o),
  144   rdf_is_skip_node(r),
  145   rdf_is_term(o),
  146   rdf_language_tagged_string(?, ?, o),
  147   rdf_lexical_to_value(r, +, -),
  148   rdf_lexical_to_value_error(r, +),
  149   rdf_lexical_value(r, ?, ?),
  150   rdf_literal(r, ?, ?, o),
  151   rdf_literal_datatype_iri(o, r),
  152   rdf_literal_dwim(o, o),
  153   rdf_literal_lexical_form(o, ?),
  154   rdf_literal_value(o, -),
  155   rdf_literal_value(o, r, ?),
  156   rdf_node_dwim(t, -),
  157   rdf_predicate(r, ?, ?),
  158   rdf_predicate_dwim(r, r),
  159   rdf_triple_term(t, r),
  160   rdf_typed_literal(r, ?, o),
  161   rdf_value_to_lexical(r, +, -),
  162   rdf_value_to_lexical_error(r, +).
  163
  164:- maplist(rdf_register_prefix, [rdf,xsd]).  165
  166:- setting(base_iri, atom, 'https://example.com/',
  167           "The default base IRI for RDF IRIs.").  168:- setting(bnode_prefix_authority, atom, 'example.org', "").  169:- setting(bnode_prefix_scheme, atom, https, "").  170:- setting(rdf_container_membership_property_max, nonneg, 3,
  171           "The number of supported container membership properties.").
 rdf_atom_node(+Atom:atom, +Node:rdf_node) is semidet
rdf_atom_node(+Atom:atom, -Node:rdf_node) is det
rdf_atom_node(-Atom:atom, +Node:rdf_node) is det
Parses the given Atom in order to extract the encoded RDF node. The following syntactic forms are supported:
  1. RDF nodes defined by the N-Triples 1.1 grammar (blank nodes, IRIs, and literals).
  2. Turtle 1.1 prefix notation for IRIs.
  189% Generate.
  190rdf_atom_node(Atom, Node) :-
  191  var(Atom), !,
  192  atom_phrase(rdf_dcg_node(Node), Atom).
  193% Parse.
  194rdf_atom_node(Atom, Node) :-
  195  rdf_parse_snippet(node, Atom, Node), !.
  196% Error.
  197rdf_atom_node(Atom, _) :-
  198  syntax_error(rdf_node(Atom)).
  199
  200prolog:message(error(syntax_error(rdf_node(Atom)),_)) -->
  201  ["Could not parse as RDF node: ~a"-[Atom]].
  202
  203:- begin_tests(rdf_atom_node).  204
  205:- rdf_meta
  206   test_rdf_atom_from_node(?, o),
  207   test_rdf_atom_to_node(?, o).
  208
  209test('rdf_atom_node(+,+)', [forall(test_rdf_atom_to_node(Atom,Node))]) :-
  210  rdf_atom_node(Atom, Node).
  211test('rdf_atom_node(+,-)', [forall(test_rdf_atom_to_node(Atom,Node))]) :-
  212  rdf_atom_node(Atom, Node0),
  213  assertion(Node == Node0).
  214test('rdf_atom_node(-,+)', [forall(test_rdf_atom_from_node(Atom,Node))]) :-
  215  rdf_atom_node(Atom0, Node),
  216  assertion(Atom == Atom0).
  217
  218test_rdf_atom_to_node(Atom, Node) :-
  219  test_rdf_atom_from_node(Atom, Node).
  220
  221test_rdf_atom_from_node('<mailto:x>', 'mailto:x').
  222test_rdf_atom_from_node('""^^<mailto:x>', literal(type('mailto:x',''))).
  223
  224:- end_tests(rdf_atom_node).
 rdf_atom_predicate(+Atom:atom, +Predicate:iri) is semidet
rdf_atom_predicate(+Atom:atom, -Predicate:iri) is det
rdf_atom_predicate(-Atom:atom, +Predicate:iri) is det
  232% Generate.
  233rdf_atom_predicate(Atom, P) :-
  234  var(Atom), !,
  235  atom_phrase(rdf_dcg_predicate(P), Atom).
  236% Parse.
  237rdf_atom_predicate(Atom, P) :-
  238  rdf_parse_snippet(predicate, Atom, P), !.
  239% Error.
  240rdf_atom_predicate(Atom, _) :-
  241  atom(Atom), !,
  242  syntax_error(rdf_predicate(Atom)).
  243
  244prolog:message(error(syntax_error(rdf_predicate(Atom)),_)) -->
  245  ["Could not parse as RDF predicate: ~a"-[Atom]].
 rdf_base_iri(+BaseIri:iri) is semidet
rdf_base_iri(-BaseIri:iri) is det
  252rdf_base_iri(BaseIri) :-
  253  setting(base_iri, BaseIri).
 rdf_canonical_lexical_form(+Datatype:iri, +LexicalForm:atom, -CanonicaldLexicalForm:atom) is det
  261rdf_canonical_lexical_form(D, Lex, CanonicalLex) :-
  262  rdf_lexical_value(D, Lex, Value),
  263  rdf_lexical_value(D, CanonicalLex, Value).
 rdf_canonical_literal(+Literal:rdf_literal, -CanonicaldLiteral:rdf_literal) is det
  270rdf_canonical_literal(Literal, CanonicalLiteral) :-
  271  rdf_literal_value(Literal, D, Value),
  272  rdf_literal_value(CanonicalLiteral, D, Value).
 rdf_container_membership_property(+Property:iri) is semidet
rdf_container_membership_property(-Property:iri) is multi
  279rdf_container_membership_property(P) :-
  280  rdf_container_membership_property(P, _).
 rdf_container_membership_property(+Property:iri, +Index:positive_integer) is semidet
rdf_container_membership_property(+Property:iri, -Index:positive_integer) is det
rdf_container_membership_property(-Property:iri, +Index:positive_integer) is det
rdf_container_membership_property(-Property:iri, -Index:positive_integer) is multi
Succeeds if P is the Nth container membership property.
  290rdf_container_membership_property(P, N) :-
  291  rdf_equal(rdf:'_', Prefix),
  292  (   var(P)
  293  ->  setting(rdf_container_membership_property_max, Max),
  294      between(1, Max, N),
  295      atom_concat(Prefix, N, P)
  296  ;   atom_concat(Prefix, Atom, P),
  297      atom_number(Atom, N),
  298      must_be(nonneg, N)
  299  ).
 rdf_create_iri(+Alias:atom, +TermOrTerms:or([term,list(term)]), -Iri:iri) is det
  305rdf_create_iri(Alias, Terms, Iri) :-
  306  is_list(Terms), !,
  307  convlist(term_to_segment_, Terms, Segments),
  308  atomic_list_concat(Segments, /, Local),
  309  %compound_name_arguments(Fingerprint, Alias, Segments),
  310  %md5(Fingerprint, Local),
  311  rdf_prefix_iri(Alias, Local, Iri).
  312rdf_create_iri(Alias, Term, Iri) :-
  313  rdf_create_iri(Alias, [Term], Iri).
  314
  315term_to_segment_(dt(Y,Mo,Da,H,Mi,S,TZ), Segment) :- !,
  316  dt_label(dt(Y,Mo,Da,H,Mi,S,TZ), Segment).
  317term_to_segment_(Literal, Segment) :-
  318  rdf_is_literal(Literal), !,
  319  rdf_literal_lexical_form(Literal, Segment).
  320term_to_segment_(Segment, Segment) :-
  321  ground(Segment).
 rdf_hash_iri(+Alias:atom, +Term:term, -Iri:iri) is det
  327rdf_hash_iri(Alias, Term, Iri) :-
  328  md5(Term, Local),
  329  rdf_prefix_iri(Alias, Local, Iri).
 rdf_is_bnode_iri(@Term) is semidet
  335rdf_is_bnode_iri(Iri) :-
  336  rdf_is_iri(Iri),
  337  uri_comps(Iri, uri(Scheme,Auth,Segments,_,_)),
  338  ground([Scheme,Auth]),
  339  prefix(['.well-known',genid], Segments).
 rdf_is_name(@Term) is semidet
  345rdf_is_name(Iri) :-
  346  rdf_is_iri(Iri), !.
  347rdf_is_name(Literal) :-
  348  rdf_is_literal(Literal).
 rdf_is_numeric_literal(@Term) is semidet
  354rdf_is_numeric_literal(literal(type(D,_))) :-
  355  xsd_numeric_type(D).
 rdf_is_object(@Term) is semidet
  361rdf_is_object(S) :-
  362  rdf_is_subject(S), !.
  363rdf_is_object(Literal) :-
  364  rdf_is_literal(Literal).
 rdf_is_skip_node(@Term) is semidet
  370rdf_is_skip_node(Term) :-
  371  rdf_is_bnode(Term), !.
  372rdf_is_skip_node(Term) :-
  373  rdf_is_bnode_iri(Term).
 rdf_is_term(@Term) is semidet
  379rdf_is_term(O) :-
  380  rdf_is_object(O).
 rdf_language_tagged_string(+LTag:atom, +LexicalForm:atom, -Literal:rdf_literal) is det
rdf_language_tagged_string(-LTag:atom, -LexicalForm:atom, +Literal:rdf_literal) is det
  387rdf_language_tagged_string(LTag, Lex, literal(lang(LTag,Lex))).
 rdf_lexical_value(+Datatype:iri, +LexicalForm:atom, -Value:term) is det
rdf_lexical_value(+Datatype:iri, -LexicalForm:atom, +Value:term) is det
Translate between a value (`Value') and its serialization, according to a given datatype IRI (`Datatype'), into a lexical form (`LexicalForm').
  397rdf_lexical_value(D, Lex, Value) :-
  398  nonvar(Lex), !,
  399  rdf_lexical_to_value(D, Lex, Value).
  400rdf_lexical_value(D, Lex, Value) :-
  401  rdf_value_to_lexical(D, Value, Lex).
  402
  403% hooks
  404rdf_lexical_to_value(D, Lex, Value) :-
  405  rdf:rdf_lexical_to_value_hook(D, Lex, Value), !.
  406rdf_value_to_lexical(D, Value, Lex) :-
  407  rdf:rdf_value_to_lexical_hook(D, Value, Lex), !.
  408
  409% rdf:HTML
  410rdf_lexical_to_value(rdf:'HTML', Lex, Value) :- !,
  411  (   rdf11:parse_partial_xml(load_html, Lex, Value0)
  412  ->  Value = Value0
  413  ;   rdf_lexical_to_value_error(rdf:'HTML', Lex)
  414  ).
  415rdf_value_to_lexical(rdf:'HTML', Value, Lex) :- !,
  416  (   rdf11:write_xml_literal(html, Value, Atom)
  417  ->  Lex = Atom
  418  ;   rdf_value_to_lexical_error(rdf:'HTML', Value)
  419  ).
  420
  421% rdf:XMLLiteral
  422rdf_lexical_to_value(rdf:'XMLLiteral', Lex, Value) :- !,
  423  (   rdf11:parse_partial_xml(load_xml, Lex, Value0)
  424  ->  Value = Value0
  425  ;   rdf_lexical_to_value_error(rdf:'XMLLiteral', Lex)
  426  ).
  427rdf_value_to_lexical(rdf:'XMLLiteral', Value, Lex) :- !,
  428  (   rdf11:write_xml_literal(xml, Value, Atom)
  429  ->  Lex = Atom
  430  ;   rdf_value_to_lexical_error(rdf:'XMLLiteral', Value)
  431  ).
  432
  433% xsd:anyURI
  434rdf_lexical_to_value(xsd:anyURI, Lex, Lex) :- !.
  435
  436rdf_value_to_lexical(xsd:anyURI, Lex, Lex) :- !.
  437
  438% xsd:boolean
  439rdf_lexical_to_value(xsd:boolean, Lex, Value) :- !,
  440  (   xsd_lexical_to_value_boolean(Lex, Value0)
  441  ->  Value = Value0
  442  ;   rdf_lexical_to_value_error(xsd:boolean, Lex)
  443  ).
  444
  445xsd_lexical_to_value_boolean('0', false).
  446xsd_lexical_to_value_boolean(false, false).
  447xsd_lexical_to_value_boolean('1', true).
  448xsd_lexical_to_value_boolean(true, true).
  449
  450rdf_value_to_lexical(xsd:boolean, Value, Lex) :- !,
  451  (   xsd_value_to_lexical_boolean(Value, Atom)
  452  ->  Lex = Atom
  453  ;   rdf_value_to_lexical_error(xsd:boolean, Value)
  454  ).
  455
  456xsd_value_to_lexical_boolean(false, false).
  457xsd_value_to_lexical_boolean(true, true).
  458
  459% xsd:dayTimeDuration
  460rdf_lexical_to_value(xsd:dayTimeDuration, Lex, Value) :- !,
  461  (   atom_phrase(dayTimeDurationMap(Value0), Lex)
  462  ->  Value = Value0
  463  ;   rdf_lexical_to_value_error(xsd:dayTimeDuration, Lex)
  464  ).
  465rdf_value_to_lexical(xsd:dayTimeDuration, Value, Lex) :- !,
  466  (   atom_phrase(dayTimeDurationCanonicalMap(Value), Atom)
  467  ->  Lex = Atom
  468  ;   rdf_value_to_lexical_error(xsd:dayTimeDuration, Value)
  469  ).
  470
  471% xsd:decimal
  472rdf_lexical_to_value(xsd:decimal, Lex, Value) :- !,
  473  (   atom_phrase(decimalLexicalMap(Value0), Lex)
  474  ->  Value = Value0
  475  ;   rdf_lexical_to_value_error(xsd:decimal, Lex)
  476  ).
  477rdf_value_to_lexical(xsd:decimal, Value, Lex) :- !,
  478  (   atom_phrase(decimalCanonicalMap(Value), Atom)
  479  ->  Lex = Atom
  480  ;   rdf_value_to_lexical_error(xsd:decimal, Value)
  481  ).
  482
  483% xsd:duration
  484rdf_lexical_to_value(xsd:duration, Lex, Value) :- !,
  485  (   atom_phrase(durationMap(Value0), Lex)
  486  ->  Value = Value0
  487  ;   rdf_lexical_to_value_error(xsd:duration, Lex)
  488  ).
  489rdf_value_to_lexical(xsd:duration, Value, Lex) :- !,
  490  (   atom_phrase(durationCanonicalMap(Value), Atom)
  491  ->  Lex = Atom
  492  ;   rdf_value_to_lexical_error(xsd:duration, Value)
  493  ).
  494
  495% xsd:byte
  496% xsd:decimal
  497% xsd:double
  498% xsd:float
  499% xsd:int
  500% xsd:integer
  501% xsd:long
  502% xsd:negativeInteger
  503% xsd:nonNegativeInteger
  504% xsd:nonPositiveInteger
  505% xsd:positiveInteger
  506% xsd:short
  507% xsd:unsignedByte
  508% xsd:unsignedInt
  509% xsd:unsignedLong
  510% xsd:unsignedShort
  511rdf_lexical_to_value(D, Lex, Value) :-
  512  rdf11:xsd_numerical(D, Domain, Type), !,
  513  (   (   Type == double
  514      ->  catch(xsd_number_string(Value0, Lex), _, fail)
  515      ;   Type == integer
  516      ->  catch(xsd_number_string(Value0, Lex), _, fail),
  517          rdf11:check_integer_domain(Domain, D, Value0)
  518      )
  519  ->  Value = Value0
  520  ;   rdf_lexical_to_value_error(D, Lex)
  521  ).
  522rdf_value_to_lexical(D, Value, Lex) :-
  523  rdf11:xsd_numerical(D, Domain, Type), !,
  524  (   rdf11:in_number(Type, Domain, D, Value, Atom)
  525  ->  Lex = Atom
  526  ;   rdf_value_to_lexical_error(D, Value)
  527  ).
  528
  529% xsd:date
  530% xsd:dateTime
  531% xsd:gDay
  532% xsd:gMonth
  533% xsd:gMonthDay
  534% xsd:gYear
  535% xsd:gYearMonth
  536% xsd:time
  537rdf_lexical_to_value(D, Lex, Dt) :-
  538  xsd_date_time_type(D), !,
  539  (   catch(xsd_time_string(XsdDt, D, Lex), _, fail)
  540  ->  xsd_date_time(Dt, D, XsdDt)
  541  ;   rdf_lexical_to_value_error(D, Lex)
  542  ).
  543rdf_value_to_lexical(D, Dt, Lex) :-
  544  xsd_date_time_type(D), !,
  545  (   xsd_date_time(Dt, D, XsdDt),
  546      catch(xsd_time_string(XsdDt, D, String), _, true),
  547      atom_string(Atom, String)
  548  ->  Lex = Atom
  549  ;   rdf_value_to_lexical_error(D, Dt)
  550  ).
  551
  552% xsd:string
  553rdf_lexical_to_value(xsd:string, Lex, Value) :- !,
  554  (   atom_string(Lex, Value0)
  555  ->  Value = Value0
  556  ;   rdf_lexical_to_value_error(xsd:string, Lex)
  557  ).
  558rdf_value_to_lexical(xsd:string, Value, Lex) :- !,
  559  (   atom_string(Atom, Value)
  560  ->  Lex = Atom
  561  ;   rdf_value_to_lexical_error(xsd:string, Value)
  562  ).
  563
  564rdf_lexical_to_value_error(D, Lex) :-
  565  syntax_error(rdf_lexical_form(D,Lex)).
  566rdf_value_to_lexical_error(D, Value) :-
  567  type_error(D, Value).
  568
  569prolog:message(error(syntax_error(rdf_lexical_form(D,Lex)),_)) -->
  570  ["Could not parse as <~a>: ~a"-[D,Lex]].
  571
  572:- begin_tests(rdf_lexical_value).  573
  574:- rdf_meta
  575   test_rdf_lexical_value(r, ?, ?).
  576
  577test('rdf_lexical_value(+,+)', [forall(test_rdf_lexical_value(D, Lex, Value))]) :-
  578  rdf_lexical_value(D, Lex, Value).
  579test('rdf_lexical_value(+,-)', [forall(test_rdf_lexical_value(D, Lex, Value))]) :-
  580  rdf_lexical_value(D, Lex, Value0),
  581  assertion(Value == Value0).
  582test('rdf_lexical_value(-,+)', [forall(test_rdf_lexical_value(D, Lex, Value))]) :-
  583  rdf_lexical_value(D, Lex0, Value),
  584  assertion(Lex == Lex0).
  585
  586test_rdf_lexical_value(xsd:string, abc, "abc").
  587
  588:- end_tests(rdf_lexical_value).
 rdf_literal(+Datatype:iri, +LTag:atom, +LexicalForm:atom, +Literal:rdf_literal) is semidet
rdf_literal(+Datatype:iri, +LTag:atom, +LexicalForm:atom, -Literal:rdf_literal) is det
rdf_literal(-Datatype:iri, -LTag:atom, -LexicalForm:atom, +Literal:rdf_literal) is det
Compose/decompose literals.
  598rdf_literal(D, LTag, Lex, literal(type(D,Lex))) :-
  599  var(LTag), !,
  600  must_be(ground, D),
  601  must_be(ground, Lex).
  602rdf_literal(rdf:langString, LTag, Lex, literal(lang(LTag,Lex))) :-
  603  must_be(ground, Lex),
  604  must_be(ground, LTag).
  605
  606:- begin_tests(rdf_literal).  607
  608:- rdf_meta
  609   test_rdf_literal(r, ?, ?, o).
  610
  611test('rdf_literal(+,+,+,+)', [forall(test_rdf_literal(D,LTag,Lex,Literal))]) :-
  612  rdf_literal(D, LTag, Lex, Literal).
  613test('rdf_literal(+,+,+,-)', [forall(test_rdf_literal(D,LTag,Lex,Literal))]) :-
  614  rdf_literal(D, LTag, Lex, Literal0),
  615  assertion(Literal0 == Literal).
  616test('rdf_literal(-,-,-,+)', [forall(test_rdf_literal(D,LTag,Lex,Literal))]) :-
  617  rdf_literal(D0, LTag0, Lex0, Literal),
  618  assertion(D0 == D),
  619  (   rdf_equal(D0, rdf:langString)
  620  ->  assertion(LTag0 == LTag)
  621  ;   assertion(var(LTag0))
  622  ),
  623  assertion(Lex0 == Lex).
  624
  625test_rdf_literal(rdf:'HTML', _, '<p>test</p>', literal(type(rdf:'HTML','<p>test</p>'))).
  626test_rdf_literal(rdf:langString, nl, test, literal(lang(nl,test))).
  627test_rdf_literal(rdf:langString, nl, test, literal(lang(nl,test))).
  628test_rdf_literal(xsd:boolean, _, false, literal(type(xsd:boolean,false))).
  629
  630:- end_tests(rdf_literal).
 rdf_literal_datatype_iri(+Literal:rdf_literal, +Datatype:iri) is semidet
rdf_literal_datatype_iri(+Literal:rdf_literal, -Datatype:iri) is det
  637rdf_literal_datatype_iri(literal(type(D,_)), D).
  638rdf_literal_datatype_iri(literal(lang(_,_)), rdf:langString).
 rdf_literal_dwim(+Dwim:term, +Literal:rdf_literal) is semidet
rdf_literal_dwim(+Dwim:term, -Literal:rdf_literal) is semidet
Allows literal terms to be created based on various simplified inputs:
Input formatDatatype IRI
-----------------------------+------------------------
boolean(LexicalForm)xsd:boolean
date(Y,Mo,Da)xsd:date
date_time(Y,Mo,D,H,Mi,S)xsd:dateTime
date_time(Y,Mo,D,H,Mi,S,TZ)xsd:dateTime
day(Da)xsd:gDay
decimal(N)xsd:decimal
double(N)xsd:double
duration(S)xsd:dayTimeDuration
duration(Mo,S)xsd:duration
floatxsd:double
float(N)xsd:float
integerxsd:integer
integer(N)xsd:integer
literal(lang(LTag,Lex))rdf:langString
literal(type(D,Lex))Datatype
month(Mo)xsd:gMonth
month_day(Mo,Da)xsd:gMonthDay
nonneg(N)xsd:nonNegativeInteger
oneof([false,true])xsd:boolean
pair(string,list(atom))rdf:langString
positive_integer(N)xsd:positiveInteger
stringxsd:string
string(atom)xsd:string
time(H,Mi,S)xsd:time
uri(Uri)xsd:anyURI
year(Y)xsd:gYear
year_month(Y,Mo)xsd:gYearMonth
LexicalForm^^DatatypeIriDatatypeIri
LexicalForm@LanguageTagrdf:langstring
  681rdf_literal_dwim(Var, _) :-
  682  var(Var), !,
  683  fail.
  684% SWI typed literal
  685rdf_literal_dwim(Lex^^D, literal(type(D,Lex))) :- !.
  686% SWI language-tagged string
  687rdf_literal_dwim(Lex@LTag, literal(lang(LTag,Lex))) :- !.
  688% special value literal
  689rdf_literal_dwim(literal(value(D,Value)), Literal) :- !,
  690  rdf_literal_value(Literal, D, Value).
  691% regular typed literal
  692rdf_literal_dwim(literal(type(D,Lex)), literal(type(D,Lex))) :- !.
  693% regular language-tagged string
  694rdf_literal_dwim(literal(lang(LTag,Lex)), literal(lang(LTag,Lex))) :- !.
  695% language-tagged string
  696rdf_literal_dwim(String-Tags, literal(lang(LTag,Lex))) :- !,
  697  atom_string(Lex, String),
  698  atomic_list_concat(Tags, -, LTag).
  699% boolean/1
  700rdf_literal_dwim(boolean(Lex), literal(type(xsd:boolean,Lex))) :- !,
  701  must_be(oneof([false,true]), Lex).
  702% date/3, date_time/[6.7], month_day/2, time/3, year_month/2
  703rdf_literal_dwim(Compound, literal(type(D,Lex))) :-
  704  xsd_date_time_term_(Compound), !,
  705  xsd_time_string(Compound, D, String),
  706  atom_string(Lex, String).
  707% day/1
  708rdf_literal_dwim(day(Da), literal(type(xsd:gDay,Lex))) :- !,
  709  xsd_time_string(Da, xsd:gDay, String),
  710  atom_string(Lex, String).
  711% decimal/1 → xsd:decimal
  712rdf_literal_dwim(decimal(N), literal(type(xsd:decimal,Lex))) :- !,
  713  rdf_lexical_value(xsd:decimal, Lex, N).
  714% double/1 → xsd:double
  715rdf_literal_dwim(double(N), literal(type(xsd:double,Lex))) :- !,
  716  atom_number(Lex, N).
  717% dt/7 → xsd:dateTime
  718rdf_literal_dwim(dt(Y,Mo,Da,H,Mi,S,TZ), Literal) :-
  719  (   ground(dt(Y,Mo,Da,H,Mi,S,TZ))
  720  ->  rdf_literal_dwim(date_time(Y,Mo,Da,H,Mi,S,TZ), Literal)
  721  ;   ground(dt(Y,Mo,Da,H,Mi,S))
  722  ->  rdf_literal_dwim(date_time(Y,Mo,Da,H,Mi,S), Literal)
  723  ;   ground(dt(Y,Mo,Da))
  724  ->  rdf_literal_dwim(date(Y,Mo,Da), Literal)
  725  ;   ground(dt(Mo,Da))
  726  ->  rdf_literal_dwim(month_day(Mo,Da), Literal)
  727  ;   ground(dt(H,Mi,S))
  728  ->  rdf_literal_dwim(time(H,Mi,S), Literal)
  729  ;   ground(dt(Y,Mo))
  730  ->  rdf_literal_dwim(year_month(Y,Mo), Literal)
  731  ;   instantiation_error(dt(Y,Mo,Da,H,Mi,S,TZ))
  732  ).
  733% duration/1 → xsd:dayTimeDuration
  734rdf_literal_dwim(duration(S), literal(type(xsd:dayTimeDuration,Lex))) :- !,
  735  rdf_lexical_value(xsd:dayTimeDuration, Lex, duration(0,S)).
  736% duration/2 → xsd:duration
  737rdf_literal_dwim(duration(Mo,S), literal(type(xsd:duration,Lex))) :- !,
  738  rdf_lexical_value(xsd:duration, Lex, duration(Mo,S)).
  739% float/1 → xsd:float
  740rdf_literal_dwim(float(N), literal(type(xsd:float,Lex))) :- !,
  741  atom_number(Lex, N).
  742% integer/1 → xsd:integer
  743rdf_literal_dwim(integer(N), literal(type(xsd:integer,Lex))) :- !,
  744  atom_number(Lex, N).
  745% month/1
  746rdf_literal_dwim(month(Mo), literal(type(xsd:gMonth,Lex))) :- !,
  747  xsd_time_string(Mo, xsd:gMonth, String),
  748  atom_string(Lex, String).
  749% nonneg/1 → xsd:nonNegativeInteger
  750rdf_literal_dwim(nonneg(N), literal(type(xsd:nonNegativeInteger,Lex))) :- !,
  751  must_be(nonneg, N),
  752  xsd_number_string(N, String),
  753  atom_string(Lex, String).
  754% positive_integer/1 → xsd:positiveInteger
  755rdf_literal_dwim(positive_integer(N), literal(type(xsd:positiveInteger,Lex))) :- !,
  756  must_be(positive_integer, N),
  757  xsd_number_string(N, String),
  758  atom_string(Lex, String).
  759% str/1 → xsd:string
  760rdf_literal_dwim(string(Atomic), literal(type(xsd:string,Lex))) :- !,
  761  atom_string(Atomic, String),
  762  atom_string(Lex, String).
  763% uri/1 → xsd:anyURI
  764rdf_literal_dwim(uri(Lex), literal(type(xsd:anyURI,Lex))) :-!.
  765% year/1 → xsd:gYear
  766rdf_literal_dwim(year(Y), literal(type(xsd:gYear,Lex))) :- !,
  767  xsd_time_string(Y, xsd:gYear, String),
  768  atom_string(Lex, String).
  769% double → xsd:double
  770% float → xsd:double
  771rdf_literal_dwim(Value, literal(type(xsd:double,Lex))) :-
  772  float(Value), !,
  773  xsd_number_string(Value, String),
  774  atom_string(Lex, String).
  775% integer → xsd:integer
  776rdf_literal_dwim(Value, literal(type(xsd:integer,Lex))) :-
  777  integer(Value), !,
  778  atom_number(Lex, Value).
  779% string → xsd:string
  780rdf_literal_dwim(String, literal(type(xsd:string,Lex))) :-
  781  string(String), !,
  782  atom_string(Lex, String).
  783% atom `false' and `true' → xsd:boolean
  784rdf_literal_dwim(Lex, literal(type(xsd:boolean,Lex))) :-
  785  memberchk(Lex, [false,true]).
  786
  787xsd_date_time_term_(date(_,_,_)).
  788xsd_date_time_term_(date_time(_,_,_,_,_,_)).
  789xsd_date_time_term_(date_time(_,_,_,_,_,_,_)).
  790xsd_date_time_term_(month_day(_,_)).
  791xsd_date_time_term_(time(_,_,_)).
  792xsd_date_time_term_(year_month(_,_)).
 rdf_literal_lexical_form(+Literal:rdf_literal, +LexicalForm:atom) is semidet
rdf_literal_lexical_form(+Literal:rdf_literal, -LexicalForm:atom) is det
  799rdf_literal_lexical_form(literal(type(_,Lex)), Lex) :-
  800  must_be(atom, Lex).
  801rdf_literal_lexical_form(literal(lang(_,Lex)), Lex) :-
  802  must_be(atom, Lex).
 rdf_literal_value(+Literal:rdf_literal, -Value:term) is det
Notice that languages-tagged strings do not have a value.
  810rdf_literal_value(Literal, Value) :-
  811  rdf_literal_value(Literal, _, Value).
 rdf_literal_value(+Literal:rdf_literal, -Datatype:iri, -Value:term) is det
rdf_literal_value(-Literal:rdf_literal, +Datatype:iri, +Value:term) is det
  817% language-tagged strings do not have a value space.
  818rdf_literal_value(literal(lang(LTag,Lex)), rdf:langString, String-Tags) :- !,
  819  atomic_list_concat(Tags, -, LTag),
  820  atom_string(Lex, String).
  821% typed literal
  822rdf_literal_value(literal(type(D,Lex)), D, Value) :-
  823  rdf_lexical_value(D, Lex, Value).
 rdf_node_dwim(+Dwim:term, +Node:rdf_node) is semidet
rdf_node_dwim(+Dwim:term, -Node:rdf_node) is semidet
Supports the Input formats of rdf_literal_dwim/2.
  832% blank node or IRI
  833rdf_node_dwim(Term, Term) :-
  834  rdf_is_subject(Term), !.
  835% literal
  836rdf_node_dwim(Term, Literal) :-
  837  rdf_literal_dwim(Term, Literal).
 rdf_predicate_dwim(+Dwim:term, +Predicate:iri) is semidet
rdf_predicate_dwim(+Dwim:term, -Predicate:iri) is det
  844rdf_predicate_dwim(a, rdf:type) :- !.
  845rdf_predicate_dwim(P, P).
 rdf_triple_term(+Triple:rdf_triple, +Term:rdf_term) is semidet
rdf_triple_term(+Triple:rdf_triple, -Term:rdf_term) is multi
  852rdf_triple_term(t(S,_,_), S).
  853rdf_triple_term(t(_,P,_), P).
  854rdf_triple_term(t(_,_,O), O).
 rdf_typed_literal(+Datatype:iri, +LexicalForm:atom, +Literal:rdf_literal) is semidet
rdf_typed_literal(+Datatype:iri, +LexicalForm:atom, -Literal:rdf_literal) is det
rdf_typed_literal(-Datatype:iri, -LexicalForm:atom, +Literal:rdf_literal) is det
  862rdf_typed_literal(D, Lex, literal(type(D,Lex))).
 well_known_iri(-Iri:iri) is det
  868well_known_iri(Iri) :-
  869  uuid(Seed),
  870  md5(Seed, Hash),
  871  well_known_iri([Hash], Iri).
 well_known_iri(+Segments:list(atom), +Iri:iri) is semidet
well_known_iri(+Segments:list(atom), -Iri:iri) is det
well_known_iri(-Segments:list(atom), +Iri:iri) is det
  878well_known_iri(Segments, Iri) :-
  879  setting(bnode_prefix_scheme, Scheme),
  880  setting(bnode_prefix_authority, Auth),
  881  (   ground(Iri)
  882  ->  uri_comps(Prefix, uri(Scheme,Auth,['.well-known',genid],_,_)),
  883      atom_concat(Prefix, Local, Iri),
  884      atomic_list_concat(Segments, /, Local)
  885  ;   uri_comps(Iri, uri(Scheme,Auth,['.well-known',genid|Segments],_,_))
  886  ).
  887
  888
  889
  890% GENERICS %
 rdf_parse_snippet(+Kind:oneof([node,predicate]), +Content:atom, -Term:term) is det
  896rdf_parse_snippet(Kind, Content, Term) :-
  897  prefix_declaration_snippet(PrefixSnippet),
  898  format_string(Kind, Format),
  899  format(string(PatternSnippet), Format, [Content]),
  900  string_concat(PrefixSnippet, PatternSnippet, Snippet),
  901  open_string(Snippet, In),
  902  result_pattern(Kind, Pattern, Term),
  903  turtle:rdf_read_turtle(In, [Pattern], []).
  904
  905format_string(node, "[<>~a].").
  906format_string(predicate, "[~a<>].").
  907
  908prefix_declaration_snippet(String2) :-
  909  aggregate_all(
  910    set(String0),
  911    (
  912      rdf_prefix(Alias, Prefix),
  913      format(string(String0), "prefix ~a: <~a>", [Alias,Prefix])
  914    ),
  915    Strings
  916  ),
  917  string_list_concat(Strings, '\n', String1),
  918  string_concat(String1, '\n', String2).
  919
  920result_pattern(node, rdf(_,_,Term), Term).
  921result_pattern(predicate, rdf(_,Term,_), Term)