View source with raw comments or as raw
   1/*  Part of SWI-Prolog
   2
   3    Author:        Jan Wielemaker and Wouter Beek
   4    E-mail:        J.Wielemaker@vu.nl
   5    WWW:           http://www.swi-prolog.org
   6    Copyright (c)  2015-2016, VU University Amsterdam
   7    All rights reserved.
   8
   9    Redistribution and use in source and binary forms, with or without
  10    modification, are permitted provided that the following conditions
  11    are met:
  12
  13    1. Redistributions of source code must retain the above copyright
  14       notice, this list of conditions and the following disclaimer.
  15
  16    2. Redistributions in binary form must reproduce the above copyright
  17       notice, this list of conditions and the following disclaimer in
  18       the documentation and/or other materials provided with the
  19       distribution.
  20
  21    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  22    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  23    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  24    FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  25    COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  26    INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  27    BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  28    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  29    CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  30    LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  31    ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  32    POSSIBILITY OF SUCH DAMAGE.
  33*/
  34
  35
  36:- module(rdf11,
  37          [ rdf/3,                      % ?S, ?P, ?O
  38            rdf/4,                      % ?S, ?P, ?O, G
  39            rdf_has/3,                  % ?S, ?P, ?O
  40            rdf_has/4,                  % ?S, ?P, ?O, -RealP
  41            rdf_update/4,               % +S, +P, +O, +Action
  42            rdf_update/5,               % +S, +P, +O, +G, +Action
  43            rdf_reachable/3,            % ?S, ?P, ?O
  44            rdf_reachable/5,            % ?S, ?P, ?O, +MaxD, -D
  45
  46            rdf_assert/3,               % +S, +P, +O
  47            rdf_assert/4,               % +S, +P, +O, ?G
  48            rdf_retractall/3,           % ?S, ?P, ?O
  49            rdf_retractall/4,           % ?S, ?P, ?O, ?G
  50
  51            {}/1,                       % +Where
  52            rdf_where/1,                % +Where
  53            rdf_compare/3,              % -Diff, +Left, +Right
  54
  55            rdf_term/1,                 % ?Term
  56            rdf_literal/1,              % ?Term
  57            rdf_bnode/1,                % ?Term
  58            rdf_iri/1,                  % ?Term
  59            rdf_name/1,                 % ?Term
  60
  61            rdf_is_iri/1,               % @Term
  62            rdf_is_bnode/1,             % @Term
  63            rdf_is_literal/1,           % @Term
  64            rdf_is_name/1,              % @Term
  65            rdf_is_object/1,            % @Term
  66            rdf_is_predicate/1,         % @Term
  67            rdf_is_subject/1,           % @Term
  68            rdf_is_term/1,              % @Term
  69
  70            rdf_subject/1,              % ?Term
  71            rdf_predicate/1,            % ?Term
  72            rdf_object/1,               % ?Term
  73            rdf_node/1,                 % ?Term
  74
  75            rdf_create_bnode/1,         % ?Term
  76
  77            rdf_canonical_literal/2,    % +In, -Canonical
  78            rdf_lexical_form/2,         % +Literal, -Lexical
  79
  80            rdf_default_graph/1,        % -Graph
  81            rdf_default_graph/2,        % -Old, +New
  82
  83            rdf_assert_list/2,          % +PrologList, -RDFList
  84            rdf_assert_list/3,          % +PrologList, -RDFList, +G
  85            rdf_last/2,                 % +RDFList, ?Last
  86            rdf_list/1,                 % ?RDFList
  87            rdf_list/2,                 % +RDFList, -PrologList
  88            rdf_length/2,               % ?RDFList, ?Length
  89            rdf_member/2,               % ?Member, +RDFList
  90            rdf_nextto/2,               % ?X, ?Y
  91            rdf_nextto/3,               % ?X, ?Y, ?RdfList
  92            rdf_nth0/3,                 % ?Index, +RDFList, ?X
  93            rdf_retract_list/1,         % +RDFList
  94
  95            op(110, xfx, @),            % must be above .
  96            op(650, xfx, ^^),           % must be above :
  97            op(1150, fx, rdf_meta)
  98          ]).
  99:- use_module(library(debug)).
 100:- use_module(library(error)).
 101:- use_module(library(lists)).
 102:- use_module(library(memfile)).
 103:- reexport(library(semweb/rdf_db),
 104            except([ rdf/3,
 105                     rdf/4,
 106                     rdf_assert/3,
 107                     rdf_assert/4,
 108                     rdf_current_literal/1,
 109                     rdf_current_predicate/1,
 110                     rdf_has/3,
 111                     rdf_has/4,
 112                     rdf_update/4,
 113                     rdf_update/5,
 114                     rdf_reachable/3,
 115                     rdf_reachable/5,
 116                     rdf_retractall/3,
 117                     rdf_retractall/4,
 118                     rdf_node/1,
 119                     rdf_bnode/1,
 120                     rdf_is_literal/1,
 121                     rdf_is_resource/1,
 122                     rdf_literal_value/2,
 123                     rdf_compare/3
 124                   ])
 125           ).
 126:- use_module(library(sgml)).
 127:- use_module(library(solution_sequences)).
 128
 129/** <module> RDF 1.1 API
 130
 131This library provides a new API   on  top of library(semweb/rdf_db). The
 132new API follows the  RDF  1.1  terminology   and  notation  as  much  as
 133possible. It runs on top of the old API, which implies that applications
 134can use the new API in one file and   the other in another one. Once the
 135new API is considered stable and robust the old API will be deprecated.
 136
 137In a nutshell, the following issues are addressed:
 138
 139  - Literals are now represented by Value^^Type or Text@Lang.  Plain
 140    literals no longer exist. Value is a Prolog representation of
 141    the value for known types.  In particular:
 142      - xsd:double, xsd:float and xsd:decimal are represented by a Prolog
 143        float
 144      - Integer types are represented by a Prolog integer
 145      - The date/time types are presented by Prolog terms
 146  - Literal matching and comparison operations are represented as
 147    Prolog _constraints_.  This replaces the literal(+Search,-Value)
 148    construct used by library(semweb/rdf_db). For example, the following
 149    query returns literals with prefix "ams", exploiting the RDF literal
 150    index.
 151
 152      ==
 153      { prefix(Name, "ams") },
 154      rdf(S,P,Name).
 155      ==
 156  - Graphs are always identified by the graph name only, i.e., the
 157    notation Graph:Line is no longer supported.  If a graph name is an IRI
 158    then RDF prefix notation can now be used.
 159  - The enumeration and type-testing predicates are now more closely based
 160    on the RDF 1.1 specification and use consistent naming.
 161
 162@author Jan Wielemaker
 163@author Wouter Beek
 164@see https://github.com/SWI-Prolog/packages-semweb/wiki/Proposal-for-Semweb-library-redesign
 165@version 2016
 166*/
 167
 168:- multifile
 169    in_ground_type_hook/3,                  % +Type, +Input, -Lexical:atom
 170    out_type_hook/3.                        % +Type, -Output, +Lexical:atom
 171
 172:- meta_predicate
 173    parse_partial_xml(3,+,-).
 174
 175:- rdf_meta
 176    rdf(r,r,o),
 177    rdf(r,r,o,r),
 178    rdf_assert(r,r,o),
 179    rdf_assert(r,r,o,r),
 180    rdf_has(r,r,o),
 181    rdf_has(r,r,o,-),
 182    rdf_update(r,r,o,t),
 183    rdf_update(r,r,o,r,t),
 184    rdf_reachable(r,r,o),
 185    rdf_reachable(r,r,o,+,-),
 186    rdf_retractall(r,r,o),
 187    rdf_retractall(r,r,o,r),
 188    {}(t),
 189    rdf_where(t),
 190    rdf_canonical_literal(o,-),
 191    rdf_lexical_form(o,-),
 192    rdf_compare(-,o,o),
 193    rdf_iri(r),
 194    rdf_is_iri(r),
 195    rdf_is_literal(o),
 196    rdf_is_name(o),
 197    rdf_is_object(o),
 198    rdf_is_predicate(r),
 199    rdf_is_subject(r),
 200    rdf_is_term(o),
 201    rdf_term(o),
 202    rdf_literal(o),
 203    rdf_name(o),
 204    rdf_object(o),
 205    rdf_assert_list(t,r),
 206    rdf_assert_list(t,r,r),
 207    rdf_last(r,o),
 208    rdf_list(r),
 209    rdf_list(r,-),
 210    rdf_length(r,-),
 211    rdf_member(o,r),
 212    rdf_nextto(o,o),
 213    rdf_nth0(?,r,o),
 214    rdf_retract_list(r).
 215
 216
 217%!  rdf(?S, ?P, ?O) is nondet.
 218%!  rdf(?S, ?P, ?O, ?G) is nondet.
 219%
 220%   True if an RDF triple <S,P,O> exists, optionally in the graph G.
 221%   The object O is either a resource  (atom)   or  one of the terms
 222%   listed below. The described types apply for  the case where O is
 223%   unbound. If O is instantiated it   is converted according to the
 224%   rules described with rdf_assert/3.
 225%
 226%   Triples consist of the following three terms:
 227%
 228%     - Blank nodes are encoded by atoms that start with `_:`.
 229%     - IRIs appear in two notations:
 230%       - Full IRIs are encoded by atoms that do not start with
 231%         `_:`.  Specifically, an IRI term is not required to follow
 232%         the IRI standard grammar.
 233%       - Abbreviated IRI notation that allows IRI prefix aliases
 234%         that are registered by rdf_register_prefix/[2,3] to be
 235%         used.  Their notation is `Alias:Local`, where Alias and
 236%         Local are atoms.  Each abbreviated IRI is expanded by the
 237%         system to a full IRI.
 238%     - Literals appear in two notations:
 239%       - String@Lang
 240%       A language-tagged string, where String is a Prolog string
 241%       and Lang is an atom.
 242%       - Value^^Type
 243%       A type qualified literal.  For unknown types, Value is a
 244%       Prolog string. If type is known, the Prolog representations
 245%       from the table below are used.
 246%
 247%       | **Datatype IRI**      | **Prolog term**                 |
 248%       |:----------------------|:--------------------------------|
 249%       | xsd:float             | float                           |
 250%       | xsd:double            | float                           |
 251%       | xsd:decimal           | float                     (1)   |
 252%       | xsd:integer           | integer                         |
 253%       | XSD integer sub-types | integer                         |
 254%       | xsd:boolean           | `true` or `false`               |
 255%       | xsd:date              | date(Y,M,D)                     |
 256%       | xsd:dateTime          | date_time(Y,M,D,HH,MM,SS) (2,3) |
 257%       | xsd:gDay              | integer                         |
 258%       | xsd:gMonth            | integer                         |
 259%       | xsd:gMonthDay         | month_day(M,D)                  |
 260%       | xsd:gYear             | integer                         |
 261%       | xsd:gYearMonth        | year_month(Y,M)                 |
 262%       | xsd:time              | time(HH,MM,SS)            (2)   |
 263%
 264%   Notes:
 265%
 266%     (1) The current implementation of `xsd:decimal` values
 267%         as floats is formally incorrect.  Future versions
 268%         of SWI-Prolog may introduce decimal as a subtype
 269%         of rational.
 270%
 271%     (2) `SS` fields denote the number of seconds.  This can
 272%         either be an integer or a float.
 273%
 274%     (3) The `date_time` structure can have a 7th field that
 275%         denotes the timezone offset *in seconds* as an
 276%         integer.
 277%
 278%   In addition, a _ground_  object  value   is  translated  into  a
 279%   properly typed RDF literal using rdf_canonical_literal/2.
 280%
 281%   There is a fine distinction  in   how  duplicate  statements are
 282%   handled in rdf/[3,4]: backtracking over  rdf/3 will never return
 283%   duplicate triples that appear  in   multiple  graphs. rdf/4 will
 284%   return such duplicate triples, because their graph term differs.
 285%
 286%   @arg S is the subject term.  It is either a blank node or IRI.
 287%   @arg P is the predicate term.  It is always an IRI.
 288%   @arg O is the object term.  It is either a literal, a blank
 289%        node or IRI (except for `true` and `false` that denote the
 290%        values of datatype XSD boolean).
 291%   @arg G is the graph term.  It is always an IRI.
 292%
 293%   @see [Triple pattern querying](http://www.w3.org/TR/sparql11-query/#sparqlTriplePatterns)
 294%   @see xsd_number_string/2 and xsd_time_string/3 are used to
 295%        convert between lexical representations and Prolog terms.
 296
 297rdf(S,P,O) :-
 298    pre_object(O,O0),
 299    rdf_db:rdf(S,P,O0),
 300    post_object(O,O0).
 301
 302rdf(S,P,O,G) :-
 303    pre_object(O,O0),
 304    pre_graph(G,G0),
 305    rdf_db:rdf(S,P,O0,G0),
 306    post_graph(G, G0),
 307    post_object(O,O0).
 308
 309%!  rdf_has(?S, ?P, ?O) is nondet.
 310%!  rdf_has(?S, ?P, ?O, -RealP) is nondet.
 311%
 312%   Similar to rdf/3 and rdf/4, but   P  matches all predicates that
 313%   are defined as an rdfs:subPropertyOf of   P. This predicate also
 314%   recognises   the   predicate   properties     `inverse_of`   and
 315%   `symmetric`. See rdf_set_predicate/2.
 316
 317rdf_has(S,P,O) :-
 318    pre_object(O,O0),
 319    rdf_db:rdf_has(S,P,O0),
 320    post_object(O,O0).
 321
 322rdf_has(S,P,O,RealP) :-
 323    pre_object(O,O0),
 324    rdf_db:rdf_has(S,P,O0,RealP),
 325    post_object(O,O0).
 326
 327
 328%!  rdf_update(+S, +P, +O, ++Action) is det.
 329%!  rdf_update(+S, +P, +O, +G, ++Action) is det.
 330%
 331%   Replaces one of  the  three  fields   on  the  matching  triples
 332%   depending on Action:
 333%
 334%     * subject(Resource)
 335%     Changes the first field of the triple.
 336%     * predicate(Resource)
 337%     Changes the second field of the triple.
 338%     * object(Object)
 339%     Changes the last field of the triple to the given resource or
 340%     literal(Value).
 341%     * graph(Graph)
 342%     Moves the triple from its current named graph to Graph.
 343%
 344%   The argument matching  the  action  must   be  ground.  If  this
 345%   argument is equivalent to  the  current   value,  no  action  is
 346%   performed. Otherwise, the requested action   is performed on all
 347%   matching triples.  For example, all resources typed `rdfs:Class`
 348%   can be changed to `owl:Class` using
 349%
 350%     ```
 351%     ?- rdf_update(_, rdf:type, rdfs:'Class',
 352%                   object(owl:'Class')).
 353%     ```
 354%
 355%   @error instantiation_error if Action or the matching argument is
 356%          not ground.
 357%   @error domain_error(rdf_update_action, Action) if Action is not
 358%          one of the above terms.
 359
 360rdf_update(S, P, O, Action) :-
 361    rdf_update(S, P, O, _, Action).
 362rdf_update(S, P, O, G, Action) :-
 363    must_be(ground, Action),
 364    (   update_column(Action, S,P,O,G, On)
 365    ->  must_be(ground, On),
 366        arg(1, Action, Old),
 367        (   On == Old
 368        ->  true
 369        ;   rdf_transaction(rdf_update_(S, P, O, G, Action), update)
 370        )
 371    ;   domain_error(rdf_update_action, Action)
 372    ).
 373
 374update_column(subject(_),   S,_,_,_, S).
 375update_column(predicate(_), _,P,_,_, P).
 376update_column(object(_),    _,_,O,_, O).
 377update_column(graph(_),     _,_,_,G, G).
 378
 379rdf_update_(S1, P, O, G, subject(S2)) :-
 380    !,
 381    forall(rdf(S1, P, O, G),
 382           ( rdf_retractall(S1, P, O, G),
 383             rdf_assert(S2, P, O, G)
 384           )).
 385rdf_update_(S, P1, O, G, predicate(P2)) :-
 386    !,
 387    forall(rdf(S, P1, O, G),
 388           ( rdf_retractall(S, P1, O, G),
 389             rdf_assert(S, P2, O, G)
 390           )).
 391rdf_update_(S, P, O1, G, object(O2)) :-
 392    !,
 393    forall(rdf(S, P, O1, G),
 394           ( rdf_retractall(S, P, O1, G),
 395             rdf_assert(S, P, O2, G)
 396           )).
 397rdf_update_(S, P, O, G1, graph(G2)) :-
 398    !,
 399    forall(rdf(S, P, O, G1),
 400           ( rdf_retractall(S, P, O, G1),
 401             rdf_assert(S, P, O, G2)
 402           )).
 403
 404
 405%!  rdf_reachable(?S, +P, ?O) is nondet.
 406%!  rdf_reachable(?S, +P, ?O, +MaxD, -D) is nondet.
 407%
 408%   True when O can be reached from S using the transitive closure
 409%   of P. The predicate uses (the internals of) rdf_has/3 and thus
 410%   matches both rdfs:subPropertyOf and the `inverse_of` and
 411%   `symmetric` predicate properties. The version rdf_reachable/5
 412%   maximizes the steps considered and returns the number of steps
 413%   taken.
 414%
 415%   If both S and O are given,   these predicates are `semidet`. The
 416%   number of steps D is  minimal   because  the implementation uses
 417%   _breath first_ search.
 418
 419rdf_reachable(S,P,O) :-
 420    pre_object(O,O0),
 421    rdf_db:rdf_reachable(S,P,O0),
 422    post_object(O,O0).
 423
 424rdf_reachable(S,P,O,MaxD,D) :-
 425    pre_object(O,O0),
 426    rdf_db:rdf_reachable(S,P,O0,MaxD,D),
 427    post_object(O,O0).
 428
 429
 430%!  rdf_assert(+S, +P, +O) is det.
 431%!  rdf_assert(+S, +P, +O, +G) is det.
 432%
 433%   Assert a new triple. If O is a literal, certain Prolog terms are
 434%   translated  to  typed  RDF  literals.    These  conversions  are
 435%   described with rdf_canonical_literal/2.
 436%
 437%   If a type  is  provided   using  Value^^Type  syntax, additional
 438%   conversions are performed. All types accept   either  an atom or
 439%   Prolog string holding a valid RDF lexical value for the type and
 440%   xsd:float and xsd:double accept a Prolog integer.
 441
 442rdf_assert(S,P,O) :-
 443    rdf_default_graph(G),
 444    rdf_assert(S,P,O,G).
 445
 446rdf_assert(S,P,O,G) :-
 447    must_be(ground, O),
 448    pre_ground_object(O,O0),
 449    rdf_db:rdf_assert(S,P,O0,G).
 450
 451%!  rdf_retractall(?S, ?P, ?O) is nondet.
 452%!  rdf_retractall(?S, ?P, ?O, ?G) is nondet.
 453%
 454%   Remove all matching  triples  from   the  database.  Matching is
 455%   performed using the same  rules  as   rdf/3.  The  call does not
 456%   instantiate any of its arguments.
 457
 458rdf_retractall(S,P,O) :-
 459    pre_object(O,O0),
 460    rdf_db:rdf_retractall(S,P,O0).
 461
 462rdf_retractall(S,P,O,G) :-
 463    pre_object(O,O0),
 464    pre_graph(G,G0),
 465    rdf_db:rdf_retractall(S,P,O0,G0).
 466
 467
 468%!  rdf_compare(-Diff, +Left, +Right) is det.
 469%
 470%   True if the RDF terms Left and   Right  are ordered according to
 471%   the comparison operator Diff.  The ordering is defines as:
 472%
 473%     - Literal < BNode < IRI
 474%     - For literals
 475%       - Numeric < non-numeric
 476%       - Numeric literals are ordered by value.  If both are
 477%         equal, floats are ordered before integers.
 478%       - Other data types are ordered lexicographically.
 479%     - BNodes and IRIs are ordered lexicographically.
 480%
 481%   Note that this ordering is a complete ordering of RDF terms that
 482%   is consistent with the partial ordering defined by SPARQL.
 483%
 484%   @arg Diff is one of `<`, `=` or `>`
 485
 486rdf_compare(Diff, Left, Right) :-
 487    pre_ground_object(Left, Left0),
 488    pre_ground_object(Right, Right0),
 489    rdf_db:rdf_compare(Diff, Left0, Right0).
 490
 491
 492%!  {}(+Where) is semidet.
 493%!  rdf_where(+Where) is semidet.
 494%
 495%   Formulate constraints on RDF terms,  notably literals. These are
 496%   intended to be used as illustrated   below.  RDF constraints are
 497%   pure: they may be placed before, after or inside a graph pattern
 498%   and, provided the code contains no  _commit_ operations (!, ->),
 499%   the  semantics  of  the  goal   remains  the  same.  Preferably,
 500%   constraints are placed _before_ the graph  pattern as they often
 501%   help the RDF database to  exploit   its  literal indexes. In the
 502%   example below, the database can choose between using the subject
 503%   and/or predicate hash or the ordered literal table.
 504%
 505%     ==
 506%         { Date >= "2000-01-01"^^xsd:dateTime },
 507%         rdf(S, P, Date)
 508%     ==
 509%
 510%   The following constraints are currently defined:
 511%
 512%     - >, >=, ==, =<, <
 513%       The comparison operators are defined between numbers (of any
 514%       recognised type), typed literals of the same type and
 515%       langStrings of the same language.
 516%     - prefix(String, Pattern)
 517%     - substring(String, Pattern)
 518%     - word(String, Pattern)
 519%     - like(String, Pattern)
 520%     - icase(String, Pattern)
 521%       Text matching operators that act on both typed literals
 522%       and langStrings.
 523%     - lang_matches(Term, Pattern)
 524%       Demands a full RDF term (Text@Lang) or a plain `Lang` term
 525%       to match the language pattern Pattern.
 526%
 527%   The  predicates  rdf_where/1  and  {}/1    are   identical.  The
 528%   rdf_where/1  variant  is  provided   to    avoid   ambiguity  in
 529%   applications where {}/1 is used for other purposes. Note that it
 530%   is also possible to write `rdf11:{...}`.
 531
 532{}(Where) :-
 533    rdf_where(Where).
 534
 535rdf_where(Var) :-
 536    var(Var),
 537    !,
 538    instantiation_error(Var).
 539rdf_where((A,B)) :-
 540    !,
 541    rdf_where(A),
 542    rdf_where(B).
 543rdf_where(Constraint) :-
 544    rdf_constraint(Constraint, Goal),
 545    !,
 546    call(Goal).
 547rdf_where(Constraint) :-
 548    existence_error(rdf_constraint, Constraint).
 549
 550% Comparison operators
 551rdf_constraint(Term >= Value,
 552               add_value_constraint(Term, >=, Value)).
 553rdf_constraint(Term >  Value,
 554               add_value_constraint(Term, >,  Value)).
 555rdf_constraint(Term == Value,
 556               add_value_constraint(Term, ==,  Value)).
 557rdf_constraint(Term <  Value,
 558               add_value_constraint(Term, <,  Value)).
 559rdf_constraint(Term =< Value,
 560               add_value_constraint(Term, =<, Value)).
 561% String selection
 562rdf_constraint(prefix(Term, Pattern),
 563               add_text_constraint(Term, prefix(PatternA))) :-
 564    atom_string(PatternA, Pattern).
 565rdf_constraint(substring(Term, Pattern),
 566               add_text_constraint(Term, substring(PatternA))) :-
 567    atom_string(PatternA, Pattern).
 568rdf_constraint(word(Term, Pattern),
 569               add_text_constraint(Term, word(PatternA))) :-
 570    atom_string(PatternA, Pattern).
 571rdf_constraint(like(Term, Pattern),
 572               add_text_constraint(Term, like(PatternA))) :-
 573    atom_string(PatternA, Pattern).
 574rdf_constraint(icase(Term, Pattern),
 575               add_text_constraint(Term, icase(PatternA))) :-
 576    atom_string(PatternA, Pattern).
 577% Lang selection
 578rdf_constraint(lang_matches(Term, Pattern),
 579               add_lang_constraint(Term, lang_matches(Pattern))).
 580
 581add_text_constraint(Var, Cond) :-
 582    var(Var),
 583    !,
 584    (   get_attr(Var, rdf11, Cond0)
 585    ->  put_attr(Var, rdf11, [Cond|Cond0])
 586    ;   put_attr(Var, rdf11, [Cond])
 587    ).
 588add_text_constraint(Text^^_Type, Cond) :-
 589    !,
 590    add_text_constraint(Text, Cond).
 591add_text_constraint(Text@_Lang, Cond) :-
 592    !,
 593    add_text_constraint(Text, Cond).
 594add_text_constraint(Var, Cond) :-
 595    eval_condition(Cond, Var).
 596
 597%!  add_lang_constraint(?Term, +Constraint)
 598%
 599%   Add a constraint on the language of a literal
 600
 601add_lang_constraint(Var, Constraint) :-
 602    var(Var),
 603    !,
 604    (   get_attr(Var, rdf11, Cond0)
 605    ->  put_attr(Var, rdf11, [Constraint|Cond0])
 606    ;   put_attr(Var, rdf11, [Constraint])
 607    ).
 608add_lang_constraint(_Text@Lang, Constraint) :-
 609    !,
 610    add_lang_constraint(Lang, Constraint).
 611add_lang_constraint(_Text^^_Type, _Constraint) :-
 612    !,
 613    fail.
 614add_lang_constraint(Term, Constraint) :-
 615    eval_condition(Constraint, Term).
 616
 617%!  add_value_constraint(?Term, +Constraint, +Value)
 618%
 619%   Apply a value constraint to the RDF Term.
 620
 621add_value_constraint(Term, Constraint, ValueIn) :-
 622    constraint_literal_value(ValueIn, Value),
 623    add_value_constraint_cann(Value, Constraint, Term).
 624
 625constraint_literal_value(Value, Value^^_Type) :-
 626    number(Value),
 627    !.
 628constraint_literal_value(Value, Literal) :-
 629    rdf_canonical_literal(Value, Literal).
 630
 631add_value_constraint_cann(RefVal^^Type, Constraint, Term) :-
 632    var(Term), var(Type),
 633    !,
 634    add_text_constraint(Term, value(Constraint, RefVal, Type)).
 635add_value_constraint_cann(RefVal^^Type, Constraint, Val^^Type2) :-
 636    !,
 637    Type = Type2,
 638    add_text_constraint(Val, value(Constraint, RefVal, Type)).
 639add_value_constraint_cann(RefVal@Lang, Constraint, Val@Lang) :-
 640    !,
 641    add_text_constraint(Val, value(Constraint, RefVal, lang(Lang))).
 642add_value_constraint_cann(RefVal^^Type, Constraint, Val) :-
 643    !,
 644    ground(Val),
 645    Val \= _@_,
 646    eval_condition(value(Constraint, RefVal, Type), Val).
 647
 648put_cond(Var, []) :-
 649    !,
 650    del_attr(Var, rdf11).
 651put_cond(Var, List) :-
 652    put_attr(Var, rdf11, List).
 653
 654eval_condition(Cond, Literal) :-
 655    text_condition(Cond),
 656    !,
 657    text_of(Literal, Text),
 658    text_condition(Cond, Text).
 659eval_condition(Cond, Literal) :-
 660    lang_condition(Cond),
 661    !,
 662    lang_of(Literal, Lang),
 663    lang_condition(Cond, Lang).
 664eval_condition(value(Comp, Ref, _Type), Value) :-
 665    (   number(Ref)
 666    ->  number(Value),
 667        compare_numeric(Comp, Ref, Value)
 668    ;   compare_std(Comp, Ref, Value)
 669    ).
 670
 671compare_numeric(<,  Ref, Value) :- Value  < Ref.
 672compare_numeric(=<, Ref, Value) :- Value =< Ref.
 673compare_numeric(==, Ref, Value) :- Value =:= Ref.
 674compare_numeric(>=, Ref, Value) :- Value >= Ref.
 675compare_numeric( >, Ref, Value) :- Value >  Ref.
 676
 677compare_std(<,  Ref, Value) :- Value  @< Ref.
 678compare_std(=<, Ref, Value) :- Value @=< Ref.
 679compare_std(==, Ref, Value) :- Value ==  Ref.
 680compare_std(>=, Ref, Value) :- Value @>= Ref.
 681compare_std( >, Ref, Value) :- Value @>  Ref.
 682
 683text_condition(prefix(_)).
 684text_condition(substring(_)).
 685text_condition(word(_)).
 686text_condition(like(_)).
 687text_condition(icase(_)).
 688
 689text_of(Literal, Text) :-
 690    atomic(Literal),
 691    !,
 692    Text = Literal.
 693text_of(Text@_Lang, Text).
 694text_of(Text^^_Type, Text).
 695
 696text_condition(prefix(Pattern), Text) :-
 697    rdf_match_label(prefix, Pattern, Text).
 698text_condition(substring(Pattern), Text) :-
 699    rdf_match_label(substring, Pattern, Text).
 700text_condition(word(Pattern), Text) :-
 701    rdf_match_label(word, Pattern, Text).
 702text_condition(like(Pattern), Text) :-
 703    rdf_match_label(like, Pattern, Text).
 704text_condition(icase(Pattern), Text) :-
 705    rdf_match_label(icase, Pattern, Text).
 706
 707lang_condition(lang_matches(_)).
 708
 709lang_of(_Text@Lang0, Lang) :-
 710    !,
 711    Lang = Lang0.
 712lang_of(Lang, Lang) :-
 713    atom(Lang).
 714
 715lang_condition(lang_matches(Pattern), Lang) :-
 716    rdf_db:lang_matches(Lang, Pattern).
 717
 718%!  literal_condition(+Object, -Cond) is semidet.
 719%
 720%   True when some of the constraints   on  Object can be translated
 721%   into an equivalent query  of   the  form  literal(Cond, _Value).
 722%   Translated constraints are removed from object.
 723
 724literal_condition(Object, Cond) :-
 725    var(Object),
 726    !,
 727    get_attr(Object, rdf11, Cond0),
 728    best_literal_cond(Cond0, Cond, Rest),
 729    put_cond(Object, Rest).
 730literal_condition(Text@_Lang, Cond) :-
 731    get_attr(Text, rdf11, Cond0),
 732    !,
 733    best_literal_cond(Cond0, Cond, Rest),
 734    put_cond(Text, Rest).
 735literal_condition(Text^^_Type, Cond) :-
 736    get_attr(Text, rdf11, Cond0),
 737    best_literal_cond(Cond0, Cond, Rest),
 738    put_cond(Text, Rest).
 739
 740%!  best_literal_cond(+Conditions, -Best, -Rest) is semidet.
 741%
 742%   Extract the constraints that can be translated into the _Search_
 743%   of literal(Search, Value).
 744%
 745%   @tbd    Select the best rather than the first.
 746
 747best_literal_cond(Conditions, Best, Rest) :-
 748    sort(Conditions, Unique),
 749    best_literal_cond2(Unique, Best, Rest).
 750
 751best_literal_cond2(Conds, Best, Rest) :-
 752    select(Cond, Conds, Rest0),
 753    rdf10_cond(Cond, Best, Rest0, Rest),
 754    !.
 755
 756rdf10_cond(value(=<, URef, UType), Cond, Rest0, Rest) :-
 757    (   select(value(>=, LRef, LType), Rest0, Rest)
 758    ->  true
 759    ;   memberchk(value(>, LRef, LType), Rest0)
 760    ->  Rest = Rest0
 761    ),
 762    !,
 763    in_constaint_type(LType, SLType, LRef, LRef0),
 764    in_constaint_type(UType, SUType, URef, URef0),
 765    Cond = between(type(SLType, LRef0), type(SUType, URef0)).
 766rdf10_cond(value(<, URef, UType), Cond, Rest0, Rest) :-
 767    (   select(value(>=, LRef, LType), Rest0, Rest1)
 768    ->  true
 769    ;   memberchk(value(>, LRef, LType), Rest0)
 770    ->  Rest1 = Rest0
 771    ),
 772    !,
 773    Rest = [value(<, URef, UType)|Rest1],
 774    in_constaint_type(LType, SLType, LRef, LRef0),
 775    in_constaint_type(UType, SUType, URef, URef0),
 776    Cond = between(type(SLType, LRef0), type(SUType, URef0)).
 777rdf10_cond(value(Cmp, Ref, Type), Pattern, Rest, Rest) :-
 778    !,
 779    rdf10_compare(Cmp, Ref, Type, Pattern).
 780rdf10_cond(lang_matches(_), _, _, _) :- !, fail.
 781rdf10_cond(Cond, Cond, Rest, Rest).
 782
 783rdf10_compare(Cmp, Ref, Type, Pattern) :-
 784    nonvar(Type), Type = lang(Lang),
 785    !,
 786    atom_string(Ref0, Ref),
 787    rdf10_lang_cond(Cmp, Ref0, Lang, Pattern).
 788rdf10_compare(Cmp, Ref, Type, Pattern) :-
 789    in_constaint_type(Type, SType, Ref, Ref0),
 790    rdf10_type_cond(Cmp, Ref0, SType, Pattern).
 791
 792rdf10_lang_cond( <, Ref, Lang, lt(lang(Lang,Ref))).
 793rdf10_lang_cond(=<, Ref, Lang, le(lang(Lang,Ref))).
 794rdf10_lang_cond(==, Ref, Lang, eq(lang(Lang,Ref))).
 795rdf10_lang_cond(>=, Ref, Lang, ge(lang(Lang,Ref))).
 796rdf10_lang_cond(>,  Ref, Lang, gt(lang(Lang,Ref))).
 797
 798rdf10_type_cond( <, Ref, Type, lt(type(Type,Ref))).
 799rdf10_type_cond(=<, Ref, Type, le(type(Type,Ref))).
 800rdf10_type_cond(==, Ref, Type, eq(type(Type,Ref))).
 801rdf10_type_cond(>=, Ref, Type, ge(type(Type,Ref))).
 802rdf10_type_cond( >, Ref, Type, gt(type(Type,Ref))).
 803
 804
 805%!  in_constaint_type(?Type, -SType, ++Val, -Val0)
 806
 807in_constaint_type(Type, SType, Val, Val0) :-
 808    nonvar(Type), ground(Val),
 809    !,
 810    SType = Type,
 811    in_ground_type(Type, Val, Val0).
 812in_constaint_type(Type, SType, Val, Val0) :-
 813    var(Type), number(Val),
 814    !,
 815    (   integer(Val)
 816    ->  rdf_equal(SType, xsd:integer),
 817        in_ground_type(xsd:integer, Val, Val0)
 818    ;   float(Val)
 819    ->  rdf_equal(SType, xsd:double),
 820        in_ground_type(xsd:double, Val, Val0)
 821    ;   assertion(fail)
 822    ).
 823
 824
 825%!  literal_class(+Term, -Class)
 826%
 827%   Classify Term as literal  and  if   possible  as  lang  or typed
 828%   literal on the basis of the constraints that apply to it.
 829
 830literal_class(Term, Class) :-
 831    get_attr(Term, rdf11, Conds),
 832    select(Cond, Conds, Rest),
 833    lang_condition(Cond),
 834    !,
 835    Term = Text@Lang,
 836    put_attr(Lang, rdf11, [Cond]),
 837    put_cond(Text, Rest),
 838    (   var(Text)
 839    ->  true
 840    ;   atom_string(Text2, Text)
 841    ),
 842    Class = lang(Lang, Text2).
 843
 844%!  attr_unify_hook(+AttributeValue, +Value)
 845
 846attr_unify_hook(Cond, Value) :-
 847    get_attr(Value, rdf11, Cond2),
 848    !,
 849    append(Cond, Cond2, CondJ),
 850    sort(CondJ, Unique),
 851    put_cond(Value, Unique).
 852attr_unify_hook(Cond, Text^^_Type) :-
 853    var(Text),
 854    !,
 855    put_cond(Text, Cond).
 856attr_unify_hook(Cond, Text@Lang) :-
 857    var(Text), var(Lang),
 858    !,
 859    partition(lang_condition, Cond, LangCond, TextCond),
 860    put_cond(Text, TextCond),
 861    put_cond(Lang, LangCond).
 862attr_unify_hook(Cond, Value) :-
 863    sort(Cond, Unique),
 864    propagate_conditions(Unique, Value).
 865
 866propagate_conditions([], _).
 867propagate_conditions([H|T], Val) :-
 868    propagate_condition(H, Val),
 869    propagate_conditions(T, Val).
 870
 871propagate_condition(value(Comp, Ref, Type), Value) :-
 872    !,
 873    (   Value = Plain^^VType
 874    ->  VType = Type
 875    ;   Plain = Value
 876    ),
 877    cond_compare(Comp, Ref, Plain).
 878propagate_condition(lang_matches(Pattern), Value) :-
 879    !,
 880    (   Value = _@Lang
 881    ->  true
 882    ;   Lang = Value
 883    ),
 884    rdf_db:lang_matches(Lang, Pattern).
 885propagate_condition(Cond, Value) :-
 886    Cond =.. [Name|Args],
 887    Constraint =.. [Name,Value|Args],
 888    rdf_constraint(Constraint, Continuation),
 889    call(Continuation).
 890
 891cond_compare(>,  Ref, Value) :- Value @>  Ref.
 892cond_compare(>=, Ref, Value) :- Value @>= Ref.
 893cond_compare(==, Ref, Value) :- Value ==  Ref.
 894cond_compare(=<, Ref, Value) :- Value @=< Ref.
 895cond_compare( <, Ref, Value) :- Value  @< Ref.
 896
 897
 898%!  rdf_default_graph(-Graph) is det.
 899%!  rdf_default_graph(-Old, +New) is det.
 900%
 901%   Query/set the notion of the  default   graph.  The notion of the
 902%   default graph is local to a  thread. Threads created inherit the
 903%   default graph from their creator. See set_prolog_flag/2.
 904
 905:- create_prolog_flag(rdf_default_graph, default,
 906                      [ type(atom),
 907                        keep(true)
 908                      ]).
 909
 910rdf_default_graph(Graph) :-
 911    current_prolog_flag(rdf_default_graph, Graph).
 912rdf_default_graph(Old, New) :-
 913    current_prolog_flag(rdf_default_graph, Old),
 914    (   New == Old
 915    ->  true
 916    ;   set_prolog_flag(rdf_default_graph, New)
 917    ).
 918
 919
 920pre_graph(G, _G0) :-
 921    var(G),
 922    !.
 923pre_graph(G, G) :-
 924    atom(G),
 925    !.
 926pre_graph(G, _) :-
 927    type_error(rdf_graph, G).
 928
 929post_graph(G, G0:_) :-
 930    !,
 931    G = G0.
 932post_graph(G, G).
 933
 934
 935pre_object(Literal, literal(Cond, Value)) :-
 936    literal_condition(Literal, Cond),
 937    !,
 938    debug(literal_index, 'Search literal using ~p', [literal(Cond, Value)]),
 939    literal_value0(Literal, Value).
 940pre_object(Literal, literal(Value)) :-
 941    literal_class(Literal, Value),
 942    !,
 943    debug(literal_index, 'Search literal using ~p', [literal(Value)]).
 944pre_object(Var, _Var) :-
 945    var(Var),
 946    !.
 947pre_object(Atom, URI) :-
 948    atom(Atom),
 949    \+ boolean(Atom),
 950    !,
 951    URI = Atom.
 952pre_object(Val@Lang, literal(lang(Lang, Val0))) :-
 953    !,
 954    in_lang_string(Val, Val0).
 955pre_object(Val^^Type, literal(Literal)) :-
 956    !,
 957    in_type(Type, Val, Type0, Val0),
 958    (   var(Type0), var(Val0)
 959    ->  true
 960    ;   Literal = type(Type0, Val0)
 961    ).
 962pre_object(Obj, Val0) :-
 963    ground(Obj),
 964    !,
 965    pre_ground_object(Obj, Val0).
 966pre_object(Obj, _) :-
 967    type_error(rdf_object, Obj).
 968
 969literal_value0(Var, _) :-
 970    var(Var),
 971    !.
 972literal_value0(_ @Lang, lang(Lang, _)).
 973literal_value0(_^^Type, type(Type, _)).
 974
 975
 976%!  pre_ground_object(+Object, -RDF) is det.
 977%
 978%   Convert between a Prolog value and an RDF value for rdf_assert/3
 979%   and friends.  Auto-conversion:
 980%
 981%     - Integer
 982%     Converted to Integer^^xsd:integer
 983%     - Float
 984%     Converted to Float^^xsd:double
 985%     - String
 986%     Converted to String^^xsd:string
 987%     - true
 988%     Converted to true^^xsd:boolean
 989%     - false
 990%     Converted to false^^xsd:boolean
 991%     - Text@Lang
 992%     Converted to Text@Lang.  Uses canonical (lowercase) lang.
 993%     Text is converted into an atom.
 994%     - Value^^Type
 995%     Typed conversion.  The translation of Value depends on
 996%     Type:
 997%       - Numeric types
 998%       - Boolean
 999%       - Date types
1000%     - Atom
1001%     All atoms except for `true` and `false` are considered
1002%     URIs.
1003
1004:- rdf_meta
1005    pre_ground_object(+, o).
1006
1007pre_ground_object(Int, Object) :-
1008    integer(Int),
1009    !,
1010    rdf_equal(Object, literal(type(xsd:integer, Atom))),
1011    atom_number(Atom, Int).
1012pre_ground_object(Float, Object) :-
1013    float(Float),
1014    !,
1015    rdf_equal(Object, literal(type(xsd:double, Atom))),
1016    xsd_number_string(Float, String),
1017    atom_string(Atom, String).
1018pre_ground_object(String, Object) :-
1019    string(String),
1020    !,
1021    rdf_equal(Object, literal(type(xsd:string, Atom))),
1022    atom_string(Atom, String).
1023pre_ground_object(false, literal(type(xsd:boolean, false))) :- !.
1024pre_ground_object(true, literal(type(xsd:boolean, true))) :- !.
1025pre_ground_object(Val@Lang,  literal(lang(Lang0, Val0))) :-
1026    !,
1027    downcase_atom(Lang, Lang0),
1028    in_lang_string(Val, Val0).
1029pre_ground_object(Val^^Type, literal(type(Type0, Val0))) :-
1030    !,
1031    in_type(Type, Val, Type0, Val0).
1032pre_ground_object(Atom, URI) :-
1033    atom(Atom),
1034    !,
1035    URI = Atom.
1036%pre_ground_object(NS:Local, URI) :-            % still leaves S and P.
1037%       atom(NS), atom(Local), !,
1038%       rdf_global_id(NS:Local, URI).
1039pre_ground_object(Value, _) :-
1040    type_error(rdf_object, Value).
1041
1042in_lang_string(Val, Val0) :-
1043    atomic(Val),
1044    !,
1045    atom_string(Val0, Val).
1046in_lang_string(_, _).
1047
1048in_type(Type, Val, Type, Val0) :-
1049    nonvar(Type), ground(Val),
1050    !,
1051    in_ground_type(Type, Val, Val0).
1052in_type(VarType, Val, VarType, Val0) :-
1053    ground(Val),
1054    \+ catch(xsd_number_string(_, Val), _, fail),
1055    !,
1056    atom_string(Val0, Val).
1057in_type(_, _, _, _).
1058
1059:- rdf_meta
1060    in_ground_type(r,?,?),
1061    in_date_component(r, +, +, -).
1062
1063%!  in_ground_type(+Type, +Input, -Lexical:atom) is det.
1064%
1065%   Translate the Prolog date Input according   to Type into its RDF
1066%   lexical form. The lecical form  is   represented  as an atom. In
1067%   future versions this is likely to become a string.
1068
1069in_ground_type(Type, Input, Lex) :-
1070    in_ground_type_hook(Type, Input, Lex),
1071    !.
1072in_ground_type(IntType, Val, Val0) :-
1073    xsd_numerical(IntType, Domain, PrologType),
1074    !,
1075    in_number(PrologType, Domain, IntType, Val, Val0).
1076in_ground_type(xsd:boolean, Val, Val0) :-
1077    !,
1078    (   in_boolean(Val, Val0)
1079    ->  true
1080    ;   type_error(rdf_boolean, Val)
1081    ).
1082in_ground_type(rdf:langString, _Val0, _) :-
1083    !,
1084    domain_error(rdf_data_type, rdf:langString).
1085in_ground_type(DateTimeType, Val, Val0) :-
1086    xsd_date_time_type(DateTimeType),
1087    !,
1088    in_date_time(DateTimeType, Val, Val0).
1089in_ground_type(rdf:'XMLLiteral', Val, Val0) :-
1090    !,
1091    in_xml_literal(xml, Val, Val0).
1092in_ground_type(rdf:'HTML', Val, Val0) :-
1093    !,
1094    in_xml_literal(html, Val, Val0).
1095in_ground_type(_Unknown, Val, Val0) :-
1096    atom_string(Val0, Val).
1097
1098%!  in_date_time(+Type, +Input, -Lexical) is det.
1099%
1100%   Accepts either a term as  accepted   by  xsd_time_string/3  or a
1101%   valid string for the corresponding XSD type.
1102
1103:- rdf_meta
1104    in_date_time(r,+,-).
1105
1106in_date_time(Type, Text, Text0) :-
1107    atom(Text),
1108    !,
1109    xsd_time_string(_, Type, Text),
1110    Text0 = Text.
1111in_date_time(Type, Text, Text0) :-
1112    string(Text),
1113    !,
1114    xsd_time_string(_, Type, Text),
1115    atom_string(Text0, Text).
1116in_date_time(xsd:dateTime, Stamp, Text0) :-
1117    number(Stamp),
1118    !,
1119    format_time(atom(Text0), '%FT%T%:z', Stamp).
1120in_date_time(Type, Term, Text0) :-
1121    !,
1122    xsd_time_string(Term, Type, String),
1123    atom_string(Text0, String).
1124
1125
1126%!  in_boolean(?NonCanonical, ?Canonical)
1127%
1128%   True when Canonical is the canonical boolean for NonCanonical.
1129
1130in_boolean(true,    true).
1131in_boolean(false,   false).
1132in_boolean("true",  true).
1133in_boolean("false", false).
1134in_boolean(1,       true).
1135in_boolean(0,       false).
1136
1137boolean(false).
1138boolean(true).
1139
1140%!  in_number(+PrologType, +Domain, +XSDType, +Value, -Lexical)
1141%
1142%   Lexical is the lexical representation for Value.
1143%
1144%   @error  type_error(PrologType, Value)
1145%   @error  domain_error(XSDType, Value)
1146
1147in_number(integer, Domain, XSDType, Val, Val0) :-
1148    integer(Val),
1149    !,
1150    check_integer_domain(Domain, XSDType, Val),
1151    atom_number(Val0, Val).
1152in_number(integer, Domain, XSDType, Val, Val0) :-
1153    atomic(Val),
1154    atom_number(Val, Num),
1155    integer(Num),
1156    !,
1157    check_integer_domain(Domain, XSDType, Num),
1158    atom_number(Val0, Num).
1159in_number(double, _Domain, _, Val, Val0) :-
1160    number(Val),
1161    !,
1162    ValF is float(Val),
1163    xsd_number_string(ValF, ValS),
1164    atom_string(Val0, ValS).
1165in_number(double, _Domain, _, Val, Val0) :-
1166    atomic(Val),
1167    xsd_number_string(Num, Val),
1168    ValF is float(Num),
1169    !,
1170    xsd_number_string(ValF, ValS),
1171    atom_string(Val0, ValS).
1172in_number(PrologType, _, _, Val, _) :-
1173    type_error(PrologType, Val).
1174
1175check_integer_domain(PLType, _, Val) :-
1176    is_of_type(PLType, Val),
1177    !.
1178check_integer_domain(_, XSDType, Val) :-
1179    domain_error(XSDType, Val).
1180
1181error:has_type(nonpos, T):-
1182    integer(T),
1183    T =< 0.
1184
1185%check_integer_domain(between(Low, High), XSDType, Val) :-
1186%       (   between(Low, High, Val)
1187%       ->  true
1188%       ;   domain_error(XSDType, Val)
1189%       ).
1190%check_integer_domain(integer, _, _).
1191
1192%!  xsd_numerical(?URI, ?TypeCheck, ?PrologType)
1193
1194:- rdf_meta
1195    xsd_numerical(r, ?, ?).
1196
1197xsd_numerical(xsd:byte,               between(-128,127),               integer).
1198xsd_numerical(xsd:double,             float,                           double).
1199xsd_numerical(xsd:decimal,            float,                           double).
1200xsd_numerical(xsd:float,              float,                           double).
1201xsd_numerical(xsd:int,                between(-2147483648,2147483647), integer).
1202xsd_numerical(xsd:integer,            integer,                         integer).
1203xsd_numerical(xsd:long,               between(-9223372036854775808,
1204                                               9223372036854775807),   integer).
1205xsd_numerical(xsd:negativeInteger,    negative_integer,                integer).
1206xsd_numerical(xsd:nonNegativeInteger, nonneg,                          integer).
1207xsd_numerical(xsd:nonPositiveInteger, nonpos,                          integer).
1208xsd_numerical(xsd:positiveInteger,    positive_integer,                integer).
1209xsd_numerical(xsd:short,              between(-32768,32767),           integer).
1210xsd_numerical(xsd:unsignedByte,       between(0,255),                  integer).
1211xsd_numerical(xsd:unsignedInt,        between(0,4294967295),           integer).
1212xsd_numerical(xsd:unsignedLong,       between(0,18446744073709551615), integer).
1213xsd_numerical(xsd:unsignedShort,      between(0,65535),                integer).
1214
1215%!  xsd_date_time_type(?URI)
1216%
1217%   True when URI is an XSD date or time type.
1218
1219:- rdf_meta
1220    xsd_date_time_type(r).
1221
1222xsd_date_time_type(xsd:date).
1223xsd_date_time_type(xsd:dateTime).
1224xsd_date_time_type(xsd:gDay).
1225xsd_date_time_type(xsd:gMonth).
1226xsd_date_time_type(xsd:gMonthDay).
1227xsd_date_time_type(xsd:gYear).
1228xsd_date_time_type(xsd:gYearMonth).
1229xsd_date_time_type(xsd:time).
1230
1231
1232%!  in_xml_literal(+Type, +Val, -Val0) is det.
1233%
1234%   Translate an XMLLiteral or HTML literal to its canonical textual
1235%   representation. Input is either text or a Prolog XML DOM.
1236%
1237%   @tbd    Deal with partial content?
1238
1239in_xml_literal(Type, Val, Val0) :-
1240    xml_is_dom(Val),
1241    !,
1242    write_xml_literal(Type, Val, Val0).
1243in_xml_literal(xml, Val, Val0) :-
1244    parse_partial_xml(load_xml, Val, DOM),
1245    write_xml_literal(xml, DOM, Val0).
1246in_xml_literal(html, Val, Val0) :-
1247    parse_partial_xml(load_html, Val, DOM),
1248    write_xml_literal(html, DOM, Val0).
1249
1250parse_partial_xml(Parser, Val, DOM) :-
1251    setup_call_cleanup(
1252        new_memory_file(MF),
1253        (   setup_call_cleanup(
1254                open_memory_file(MF, write, Out),
1255                format(Out, "<xml>~w</xml>", [Val]),
1256                close(Out)),
1257            setup_call_cleanup(
1258                open_memory_file(MF, read, In),
1259                call(Parser, stream(In), [element(xml, _, DOM)], []),
1260                close(In))
1261        ),
1262        free_memory_file(MF)).
1263
1264
1265write_xml_literal(xml, DOM, Text) :-
1266    with_output_to(atom(Text),
1267                   xml_write(current_output, DOM,
1268                             [ header(false),
1269                               layout(false)
1270                             ])).
1271write_xml_literal(html, DOM, Text) :-
1272    with_output_to(atom(Text),
1273                   html_write(current_output, DOM,
1274                              [ header(false),
1275                                layout(false)
1276                              ])).
1277
1278%!  rdf_canonical_literal(++In, -Literal) is det.
1279%
1280%   Transform  a  relaxed  literal  specification   as  allowed  for
1281%   rdf_assert/3 into its canonical form. The following Prolog terms
1282%   are translated:
1283%
1284%   | **Prolog Term**               | **Datatype IRI** |
1285%   |:------------------------------|:-----------------|
1286%   | float                         | xsd:double       |
1287%   | integer                       | xsd:integer      |
1288%   | string                        | xsd:string       |
1289%   | `true` or `false`             | xsd:boolean      |
1290%   | date(Y,M,D)                   | xsd:date         |
1291%   | date_time(Y,M,D,HH,MM,SS)     | xsd:dateTime     |
1292%   | date_time(Y,M,D,HH,MM,SS,TZ)  | xsd:dateTime     |
1293%   | month_day(M,D)                | xsd:gMonthDay    |
1294%   | year_month(Y,M)               | xsd:gYearMonth   |
1295%   | time(HH,MM,SS)                | xsd:time         |
1296%
1297%   For example:
1298%
1299%     ```
1300%     ?- rdf_canonical_literal(42, X).
1301%     X = 42^^'http://www.w3.org/2001/XMLSchema#integer'.
1302%     ```
1303
1304rdf_canonical_literal(In, Literal) :-
1305    ground(In),
1306    !,
1307    pre_ground_object(In, DBTerm),
1308    post_object(Literal, DBTerm).
1309rdf_canonical_literal(In, _) :-
1310    must_be(ground, In).
1311
1312%!  rdf_lexical_form(++Literal, -Lexical:compound) is det.
1313%
1314%   True when Lexical is the lexical   form for the literal Literal.
1315%   Lexical is of one of the forms below. The ntriples serialization
1316%   is obtained by transforming String into a proper ntriples string
1317%   using double quotes and escaping where   needed and turning Type
1318%   into a proper IRI reference.
1319%
1320%     - String^^Type
1321%     - String@Lang
1322
1323%       For example,
1324%
1325%       ==
1326%       ?- rdf_lexical_form(2.3^^xsd:double, L).
1327%       L = "2.3E0"^^'http://www.w3.org/2001/XMLSchema#double'.
1328%       ==
1329
1330rdf_lexical_form(Literal, Lexical) :-
1331    pre_ground_object(Literal, literal(Lit0)),
1332    !,
1333    text_of0(Lit0, Lexical).
1334rdf_lexical_form(Literal, _) :-
1335    type_error(rdf_literal, Literal).
1336
1337text_of0(type(TypeA, LexicalA), LexicalS^^TypeA) :-
1338    atom_string(LexicalA, LexicalS).
1339text_of0(lang(LangA, LexicalA), LexicalS@LangA) :-
1340    atom_string(LexicalA, LexicalS).
1341
1342
1343                 /*******************************
1344                 *       POST PROCESSING        *
1345                 *******************************/
1346
1347:- rdf_meta
1348    post_object(o,o),
1349    out_type(r,-,+).
1350
1351post_object(Val, _) :-
1352    ground(Val),
1353    !.                 % already specified and matched
1354post_object(URI, URI0) :-
1355    atom(URI0),
1356    !,
1357    URI = URI0.
1358post_object(Val@Lang, literal(lang(Lang, Val0))) :-
1359    nonvar(Lang),          % lang(Lang,Text) returns var(Lang) if no lang
1360    !,
1361    atom_string(Val0, Val).
1362post_object(Val^^Type, literal(type(Type, Val0))) :-
1363    !,
1364    out_type(Type, Val, Val0).
1365post_object(Val^^xsd:string, literal(Plain)) :-
1366    !,
1367    atomic(Plain),
1368    atom_string(Plain, Val).
1369post_object(Val@Lang, literal(_, lang(Lang, Val0))) :-
1370    nonvar(Lang),
1371    !,
1372    atom_string(Val0, Val).
1373post_object(Val^^Type, literal(_, type(Type, Val0))) :-
1374    !,
1375    out_type(Type, Val, Val0).
1376post_object(Val^^xsd:string, literal(_, Plain)) :-
1377    atomic(Plain),
1378    atom_string(Plain, Val).
1379
1380out_type(xsd:string, Val, Val0) :-     % catches unbound type too
1381    !,
1382    atom_string(Val0, Val).
1383out_type(Type, Val, Val0) :-
1384    out_type_hook(Type, Val, Val0),
1385    !.
1386out_type(IntType, Val, Val0) :-
1387    xsd_numerical(IntType, _Domain, _BasicType),
1388    !,
1389    xsd_number_string(Val, Val0).
1390out_type(DateTimeType, Val, Val0) :-
1391    xsd_date_time_type(DateTimeType),
1392    !,
1393    out_date_time(DateTimeType, Val, Val0).
1394out_type(xsd:boolean, Val, Val0) :-
1395    !,
1396    Val = Val0.
1397out_type(rdf:'XMLLiteral', XML, DOM) :-
1398    xml_is_dom(DOM),
1399    !,
1400    with_output_to(string(XML),
1401                   xml_write(DOM, [header(false)])).
1402out_type(_Unknown, Val, Val0) :-
1403    atom_string(Val0, Val).
1404
1405
1406%!  out_date_time(+DateTimeType, -Val, +Val0) is det.
1407%
1408%   Translate an XSD lexical form for   a date/time related datatype
1409%   into the cannical form as defined by xsd_time_string/3.
1410
1411out_date_time(Type, Prolog, Lexical) :-
1412    xsd_time_string(Prolog, Type, Lexical).
1413
1414
1415                 /*******************************
1416                 *          ENUMERATION         *
1417                 *******************************/
1418
1419%!  rdf_term(?Term) is nondet.
1420%
1421%   True if Term appears in the RDF database. Term is either an iri,
1422%   literal or blank node and may  appear   in  any  position of any
1423%   triple. If Term is ground,  it   is  pre-processed as the object
1424%   argument of rdf_assert/3 and the predicate is _semidet_.
1425
1426rdf_term(N) :-
1427    ground(N),
1428    !,
1429    pre_object(N, N0),
1430    visible_term(N0).
1431rdf_term(N) :-
1432    gen_term(N).
1433
1434gen_term(N) :-
1435    resource(N),
1436    visible_term(N).
1437gen_term(O) :-                          % performs double conversion!
1438    rdf_literal(O),
1439    (rdf(_,_,O) -> true).
1440
1441%!  rdf_literal(?Term) is nondet.
1442%
1443%   True if Term is a  known  literal.   If  Term  is  ground, it is
1444%   pre-processed as the object  argument   of  rdf_assert/3 and the
1445%   predicate is _semidet_.
1446
1447rdf_literal(Term) :-
1448    ground(Term),
1449    !,
1450    pre_ground_object(Term, Object),
1451    (rdf_db:rdf(_,_,Object)->true).
1452rdf_literal(Term) :-
1453    pre_object(Term,literal(Lit0)),
1454    rdf_db:rdf_current_literal(Lit0),
1455    (rdf_db:rdf(_,_,literal(Lit0))->true),
1456    post_object(Term, literal(Lit0)).
1457
1458%!  rdf_bnode(?BNode) is nondet.
1459%
1460%   True if BNode is a currently known  blank node. The predicate is
1461%   _semidet_ if BNode is ground.
1462
1463rdf_bnode(BNode) :-
1464    atom(BNode),
1465    !,
1466    current_bnode(BNode).
1467rdf_bnode(BNode) :-
1468    rdf_db:rdf_resource(BNode),
1469    current_bnode(BNode).
1470
1471current_bnode(BNode) :-
1472    rdf_is_bnode(BNode),
1473    visible_node(BNode).            % Assumes BNodes cannot be predicates
1474
1475%!  rdf_iri(?IRI) is nondet.
1476%
1477%   True if IRI is a current IRI.  The predicate is _semidet_ if IRI
1478%   is ground.
1479
1480rdf_iri(IRI) :-
1481    atom(IRI),
1482    !,
1483    \+ rdf_is_bnode(IRI),
1484    visible_term(IRI).
1485rdf_iri(IRI) :-
1486    resource(IRI),
1487    \+ rdf_is_bnode(IRI),
1488    visible_term(IRI).
1489
1490%!  rdf_name(?Name) is nondet.
1491%
1492%   True if Name is a  current  IRI   or  literal.  The predicate is
1493%   _semidet_ if Name is ground.
1494
1495rdf_name(Name) :-
1496    atom(Name), \+ boolean(Name),
1497    !,
1498    \+ rdf_is_bnode(Name),
1499    visible_term(Name).
1500rdf_name(Name) :-
1501    ground(Name),
1502    !,
1503    pre_ground_object(Name, Name0),
1504    (rdf_db:rdf(_,_,Name0)->true).
1505rdf_name(Name) :-
1506    rdf_iri(Name).
1507rdf_name(Name) :-
1508    rdf_literal(Name).
1509
1510%!  rdf_subject(?S) is nondet.
1511%
1512%   True when S is a currently known   _subject_, i.e. it appears in
1513%   the subject position of some visible   triple.  The predicate is
1514%   _semidet_ if S is ground.
1515
1516
1517%!  rdf_predicate(?P) is nondet.
1518%
1519%   True when P is a currently known   predicate, i.e. it appears in
1520%   the predicate position of some visible  triple. The predicate is
1521%   _semidet_ if P is ground.
1522
1523rdf_predicate(P) :-
1524    atom(P),
1525    !,
1526    (rdf(_,P,_) -> true).
1527rdf_predicate(P) :-
1528    rdf_db:rdf_current_predicate(P),
1529    (rdf(_,P,_) -> true).
1530
1531%!  rdf_object(?O) is nondet.
1532%
1533%   True when O is a currently known  object, i.e. it appeasr in the
1534%   object position of some visible triple. If Term is ground, it is
1535%   pre-processed as the object  argument   of  rdf_assert/3 and the
1536%   predicate is _semidet_.
1537
1538rdf_object(O) :-
1539    ground(O),
1540    !,
1541    (   atom(O), \+ boolean(O)
1542    ->  (rdf_db:rdf(_,_,O) -> true)
1543    ;   rdf_literal(O)
1544    ).
1545rdf_object(O) :-
1546    rdf_db:rdf_resource(O),
1547    (rdf_db:rdf(_,_,O) -> true).
1548rdf_object(O) :-
1549    rdf_literal(O).
1550
1551%!  rdf_node(?T) is nondet.
1552%
1553%   True when T appears in the subject or object position of a known
1554%   triple, i.e., is a node in the RDF graph.
1555
1556rdf_node(N) :-
1557    var(N),
1558    !,
1559    gen_node(N).
1560rdf_node(N) :-
1561    pre_ground_object(N, N0),
1562    visible_node(N0).
1563
1564gen_node(N) :-
1565    rdf_db:rdf_resource(N),
1566    visible_node(N).
1567gen_node(O) :-                          % performs double conversion!
1568    rdf_literal(O),
1569    (rdf(_,_,O) -> true).
1570
1571%!  resource(?R)
1572%
1573%   True if R is a node that is not a literal. Note that RDF-DB does
1574%   not necessarily include predicates in the set of resources. Also
1575%   note that the resource may not really exist or be visible.
1576
1577resource(R) :-
1578    var(R),
1579    !,
1580    gen_resource(R).
1581resource(R) :-
1582    rdf_db:rdf_resource(R),
1583    !.
1584resource(R) :-
1585    rdf_db:rdf_current_predicate(R),
1586    !.
1587
1588gen_resource(R) :-
1589    rdf_db:rdf_resource(R).
1590gen_resource(R) :-
1591    rdf_db:rdf_current_predicate(R),
1592    \+ rdf_db:rdf_resource(R).
1593
1594visible_node(Term) :-
1595    atom(Term),
1596    !,
1597    (   rdf_db:rdf(Term,_,_)
1598    ;   rdf_db:rdf(_,_,Term)
1599    ),
1600    !.
1601visible_node(Term) :-
1602    rdf_db:rdf(_,_,Term).
1603
1604visible_term(Term) :-
1605    atom(Term),
1606    !,
1607    (   rdf_db:rdf(Term,_,_)
1608    ;   rdf_db:rdf(_,Term,_)
1609    ;   rdf_db:rdf(_,_,Term)
1610    ),
1611    !.
1612visible_term(Term) :-
1613    rdf_db:rdf(_,_,Term).
1614
1615%!  rdf_create_bnode(--BNode)
1616%
1617%   Create a new BNode. A  blank  node   is  an  atom  starting with
1618%   =|_:|=. Blank nodes generated by this  predicate are of the form
1619%   =|_:genid|= followed by a unique integer.
1620
1621rdf_create_bnode(BNode) :-
1622    var(BNode),
1623    !,
1624    rdf_db:rdf_bnode(BNode).
1625rdf_create_bnode(BNode) :-
1626    uninstantiation_error(BNode).
1627
1628
1629                 /*******************************
1630                 *         TYPE CHECKING        *
1631                 *******************************/
1632
1633%!  rdf_is_iri(@IRI) is semidet.
1634%
1635%   True if IRI is an RDF IRI term.
1636%
1637%   For performance reasons, this does not check for compliance to
1638%   the syntax defined in [[RFC
1639%   3987][http://www.ietf.org/rfc/rfc3987.txt]].  This checks
1640%   whether the term is (1) an atom and (2) not a blank node
1641%   identifier.
1642%
1643%   Success of this goal does not imply that the IRI is present in
1644%   the database (see rdf_iri/1 for that).
1645
1646rdf_is_iri(IRI) :-
1647    atom(IRI),
1648    \+ rdf_is_bnode(IRI).
1649
1650%!  rdf_is_bnode(@Term) is semidet.
1651%
1652%   True if Term is an RDF blank node identifier.
1653%
1654%   A blank node is represented by an atom that starts with
1655%   =|_:|=.
1656%
1657%   Success of this goal does not imply that the blank node is
1658%   present in the database (see rdf_bnode/1 for that).
1659%
1660%   For backwards compatibility, atoms that are represented with
1661%   an atom that starts with =|__|= are also considered to be a
1662%   blank node.
1663
1664
1665%!  rdf_is_literal(@Term) is semidet.
1666%
1667%   True if Term is an RDF literal term.
1668%
1669%   An RDF literal term is of the form `String@LanguageTag` or
1670%   `Value^^Datatype`.
1671%
1672%   Success of this goal does not imply that the literal is
1673%   well-formed or that it is present in the database (see
1674%   rdf_literal/1 for that).
1675
1676rdf_is_literal(Literal) :-
1677    literal_form(Literal),
1678    !,
1679    ground(Literal).
1680
1681literal_form(_@_).
1682literal_form(_^^_).
1683
1684
1685%!  rdf_is_name(@Term) is semidet.
1686%
1687%   True if Term is an RDF Name, i.e., an IRI or literal.
1688%
1689%   Success of this goal does not imply that the name is
1690%   well-formed or that it is present in the database (see
1691%   rdf_name/1) for that).
1692
1693rdf_is_name(T) :- rdf_is_iri(T), !.
1694rdf_is_name(T) :- rdf_is_literal(T).
1695
1696
1697%!  rdf_is_object(@Term) is semidet.
1698%
1699%   True if Term can appear in the object position of a triple.
1700%
1701%   Success of this goal does not imply that the object term in
1702%   well-formed or that it is present in the database (see
1703%   rdf_object/1) for that).
1704%
1705%   Since any RDF term can appear in the object position, this is
1706%   equaivalent to rdf_is_term/1.
1707
1708rdf_is_object(T) :- rdf_is_subject(T), !.
1709rdf_is_object(T) :- rdf_is_literal(T).
1710
1711
1712%!  rdf_is_predicate(@Term) is semidet.
1713%
1714%   True if Term can appear in the   predicate position of a triple.
1715%
1716%   Success of this goal does not imply that the predicate term is
1717%   present in the database (see rdf_predicate/1) for that).
1718%
1719%   Since only IRIs can appear in the predicate position, this is
1720%   equivalent to rdf_is_iri/1.
1721
1722rdf_is_predicate(T) :- rdf_is_iri(T).
1723
1724
1725%!  rdf_is_subject(@Term) is semidet.
1726%
1727%   True if Term can appear in  the   subject  position of a triple.
1728%
1729%   Only blank nodes and IRIs can appear in the subject position.
1730%
1731%   Success of this goal does not imply that the subject term is
1732%   present in the database (see rdf_subject/1) for that).
1733%
1734%   Since blank nodes are represented by atoms that start with
1735%   `_:` and an IRIs are atoms as well, this is equivalent to
1736%   atom(Term).
1737
1738rdf_is_subject(T) :- atom(T).
1739
1740%!  rdf_is_term(@Term) is semidet.
1741%
1742%   True if Term can be used as an RDF term, i.e., if Term is
1743%   either an IRI, a blank node or an RDF literal.
1744%
1745%   Success of this goal does not imply that the RDF term is
1746%   present in the database (see rdf_term/1) for that).
1747
1748rdf_is_term(N) :- rdf_is_subject(N), !.
1749rdf_is_term(N) :- rdf_is_literal(N).
1750
1751
1752                 /*******************************
1753                 *          COLLECTIONS         *
1754                 *******************************/
1755
1756%!  rdf_list(?RDFTerm) is semidet.
1757%
1758%   True if RDFTerm is a proper RDF   list.  This implies that every
1759%   node in the list has an  `rdf:first` and `rdf:rest` property and
1760%   the list ends in `rdf:nil`.
1761%
1762%   If RDFTerm is unbound, RDFTerm is   bound  to each _maximal_ RDF
1763%   list. An RDF list is _maximal_  if   there  is  no triple rdf(_,
1764%   rdf:rest, RDFList).
1765
1766rdf_list(L) :-
1767    var(L),
1768    !,
1769    rdf_has(L, rdf:first, _),
1770    \+ rdf_has(_, rdf:rest, L),
1771    rdf_list_g(L),
1772    !.
1773rdf_list(L) :-
1774    rdf_list_g(L),
1775    !.
1776
1777rdf_list_g(rdf:nil) :- !.
1778rdf_list_g(L) :-
1779    once(rdf_has(L, rdf:first, _)),
1780    rdf_has(L, rdf:rest, Rest),
1781    (   rdf_equal(rdf:nil, Rest)
1782    ->  true
1783    ;   rdf_list_g(Rest)
1784    ).
1785
1786
1787%!  rdf_list(+RDFList, -PrologList) is det.
1788%
1789%   True when PrologList represents the   rdf:first  objects for all
1790%   cells in RDFList. Note that  this   can  be non-deterministic if
1791%   cells have multiple rdf:first or rdf:rest triples.
1792
1793rdf_list(RDFList, Prolog) :-
1794    rdf_is_subject(RDFList),
1795    !,
1796    rdf_list_to_prolog(RDFList, Prolog).
1797rdf_list(RDFList, _Prolog) :-
1798    type_error(rdf_subject, RDFList).
1799
1800:- rdf_meta
1801    rdf_list_to_prolog(r,-).
1802
1803rdf_list_to_prolog(rdf:nil, Prolog) :-
1804    !,
1805    Prolog = [].
1806rdf_list_to_prolog(RDF, [H|T2]) :-
1807    (   rdf_has(RDF, rdf:first, H0),
1808        rdf_has(RDF, rdf:rest, T1)
1809    *-> H = H0,
1810        rdf_list_to_prolog(T1, T2)
1811    ;   type_error(rdf_list, RDF)
1812    ).
1813
1814
1815%!  rdf_length(+RDFList, -Length:nonneg) is nondet.
1816%
1817%   True when Length is the number of  cells in RDFList. Note that a
1818%   list cell may have multiple rdf:rest   triples, which makes this
1819%   predicate  non-deterministic.  This  predicate  does  not  check
1820%   whether the list cells have   associated values (rdf:first). The
1821%   list must end in rdf:nil.
1822
1823rdf_length(RDFList, Len) :-
1824    rdf_is_subject(RDFList),
1825    !,
1826    rdf_length(RDFList, 0, Len).
1827
1828:- rdf_meta
1829    rdf_length(r,+,-).
1830
1831rdf_length(rdf:nil, Len, Len) :- !.
1832rdf_length(RDF, Len0, Len) :-
1833    (   rdf_has(RDF, rdf:rest, T)
1834    *-> Len1 is Len0+1,
1835        rdf_length(T, Len1, Len)
1836    ;   type_error(rdf_list, RDF)
1837    ).
1838
1839
1840%!  rdf_member(?Member, +RDFList) is nondet.
1841%
1842%   True when Member is a member of RDFList
1843
1844rdf_member(M, L) :-
1845    ground(M),
1846    !,
1847    (   rdf_member2(M, L)
1848    ->  true
1849    ).
1850rdf_member(M, L) :-
1851    rdf_member2(M, L).
1852
1853rdf_member2(M, L) :-
1854    rdf_has(L, rdf:first, M).
1855rdf_member2(M, L) :-
1856    rdf_has(L, rdf:rest, L1),
1857    rdf_member2(M, L1).
1858
1859
1860%! rdf_nextto(?X, ?Y) is nondet.
1861%! rdf_nextto(?X, ?Y, ?RdfList) is nondet.
1862%
1863%       True if Y directly follows X in RdfList.
1864
1865rdf_nextto(X, Y) :-
1866    distinct(X-Y, rdf_nextto(X, Y, _)).
1867
1868
1869rdf_nextto(X, Y, L) :-
1870    var(X), ground(Y),
1871    !,
1872    rdf_nextto(Y, X, L).
1873rdf_nextto(X, Y, L) :-
1874    rdf_has(L, rdf:first, X),
1875    rdf_has(L, rdf:rest, T),
1876    rdf_has(T, rdf:first, Y).
1877
1878
1879%!  rdf_nth0(?Index, +RDFList, ?X) is nondet.
1880%
1881%   True when X is the Index-th   element (0-based) of RDFList. This
1882%   predicate is deterministic if Index is given and the list has no
1883%   multiple rdf:first or rdf:rest values.
1884
1885rdf_nth0(I, L, X) :-
1886    rdf_is_subject(L),
1887    !,
1888    (   var(I)
1889    ->  true
1890    ;   must_be(nonneg, I)
1891    ),
1892    rdf_nth0(I, 0, L, X).
1893rdf_nth0(_, L, _) :-
1894    type_error(rdf_subject, L).
1895
1896rdf_nth0(I, I0, L, X) :-
1897    (   I0 == I
1898    ->  !
1899    ;   I0 = I
1900    ),
1901    rdf_has(L, rdf:first, X).
1902rdf_nth0(I, I0, L, X) :-
1903    rdf_has(L, rdf:rest, T),
1904    I1 is I0+1,
1905    rdf_nth0(I, I1, T, X).
1906
1907
1908%!  rdf_last(+RDFList, -Last) is det.
1909%
1910%   True when Last is the last element  of RDFList. Note that if the
1911%   last cell has multiple rdf:first triples, this predicate becomes
1912%   nondet.
1913
1914rdf_last(L, Last) :-
1915    rdf_is_subject(L),
1916    !,
1917    rdf_has(L, rdf:rest, T),
1918    (   rdf_equal(T, rdf:nil)
1919    ->  rdf_has(L, rdf:first, Last)
1920    ;   rdf_last(T, Last)
1921    ).
1922rdf_last(L, _) :-
1923    type_error(rdf_subject, L).
1924
1925
1926%!  rdf_assert_list(+PrologList, ?RDFList) is det.
1927%!  rdf_assert_list(+PrologList, ?RDFList, +Graph) is det.
1928%
1929%   Create an RDF list from the   given Prolog List. PrologList must
1930%   be a proper Prolog list and  all   members  of  the list must be
1931%   acceptable as object for rdf_assert/3. If RDFList is unbound and
1932%   PrologList is not empty, rdf_create_bnode/1   is  used to create
1933%   RDFList.
1934
1935rdf_assert_list(Prolog, RDF) :-
1936    rdf_default_graph(G),
1937    rdf_assert_list(Prolog, RDF, G).
1938
1939rdf_assert_list(Prolog, RDF, G) :-
1940    must_be(list, Prolog),
1941    rdf_transaction(rdf_assert_list_(Prolog, RDF, G)).
1942
1943rdf_assert_list_([], Nil, _) :-
1944    rdf_equal(rdf:nil, Nil).
1945rdf_assert_list_([H|T], L2, G) :-
1946    (var(L2) -> rdf_create_bnode(L2) ; true),
1947    rdf_assert(L2, rdf:type, rdf:'List', G),
1948    rdf_assert(L2, rdf:first, H, G),
1949    (   T == []
1950    ->  rdf_assert(L2, rdf:rest, rdf:nil, G)
1951    ;   rdf_create_bnode(T2),
1952        rdf_assert(L2, rdf:rest, T2, G),
1953        rdf_assert_list_(T, T2, G)
1954    ).
1955
1956
1957%!  rdf_retract_list(+RDFList) is det.
1958%
1959%   Retract the rdf:first, rdf:rest  and rdf:type=rdf:'List' triples
1960%   from all nodes  reachable  through   rdf:rest.  Note  that other
1961%   triples that exist on the nodes are left untouched.
1962
1963rdf_retract_list(L) :-
1964    rdf_is_subject(L),
1965    !,
1966    rdf_transaction(rdf_retract_list_(L)).
1967rdf_retract_list(L) :-
1968    type_error(rdf_subject, L).
1969
1970:- rdf_meta
1971    rdf_retract_list_(r).
1972
1973rdf_retract_list_(rdf:nil) :- !.
1974rdf_retract_list_(L) :-
1975    rdf_retractall(L, rdf:first, _),
1976    forall(rdf_has(L, rdf:rest, L1),
1977           rdf_retract_list_(L1)),
1978    rdf_retractall(L, rdf:rest, _),
1979    rdf_retractall(L, rdf:type, rdf:'List').