View source with raw comments or as raw
    1/*  Part of SWI-Prolog
    2
    3    Author:        Jan Wielemaker
    4    E-mail:        J.Wielemaker@vu.nl
    5    WWW:           http://www.swi-prolog.org
    6    Copyright (c)  2003-2015, University of Amsterdam
    7                              VU University Amsterdam
    8    All rights reserved.
    9
   10    Redistribution and use in source and binary forms, with or without
   11    modification, are permitted provided that the following conditions
   12    are met:
   13
   14    1. Redistributions of source code must retain the above copyright
   15       notice, this list of conditions and the following disclaimer.
   16
   17    2. Redistributions in binary form must reproduce the above copyright
   18       notice, this list of conditions and the following disclaimer in
   19       the documentation and/or other materials provided with the
   20       distribution.
   21
   22    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   23    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   24    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
   25    FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
   26    COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
   27    INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
   28    BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
   29    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
   30    CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   31    LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
   32    ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   33    POSSIBILITY OF SUCH DAMAGE.
   34*/
   35
   36:- module(rdfs,
   37          [ rdfs_subproperty_of/2,      % ?SubProperties, ?Property
   38            rdfs_subclass_of/2,         % ?SubClass, ?Class
   39            rdfs_class_property/2,      % +Class, ?Property
   40            rdfs_individual_of/2,       % ?Resource, ?Class
   41
   42            rdfs_label/2,               % ?Resource, ?Label
   43            rdfs_label/3,               % ?Resource, ?Language, ?Label
   44            rdfs_ns_label/2,            % +Resource, -Label
   45            rdfs_ns_label/3,            % +Resource, ?Label, -Label
   46
   47            rdfs_member/2,              % ?Object, +Set
   48            rdfs_list_to_prolog_list/2, % +Set, -List
   49            rdfs_assert_list/3,         % +List, -Resource, +DB
   50            rdfs_assert_list/2,         % +List, -Resource
   51
   52            rdfs_find/5                 % +String, +Dom, +Props, +Method, -Subj
   53          ]).   54:- use_module(library(lists)).   55:- use_module(rdf_db).

RDFS handling

This module provides various primitives for more high-level handling of RDF models from an RDFS viewpoint. Note that there exist two approaches for languages on top of RDF:

   71                 /*******************************
   72                 *          EXPANSION           *
   73                 *******************************/
   74
   75:- rdf_meta
   76    rdfs_subproperty_of(r,r),
   77    rdfs_subclass_of(r,r),
   78    rdfs_class_property(r,r),
   79    rdfs_individual_of(r,r),
   80    rdfs_label(r,-),
   81    rdfs_label(r,?,-).   82
   83
   84                 /*******************************
   85                 *      PROPERTY HIERARCHY      *
   86                 *******************************/
 rdfs_subproperty_of(+SubProperty, ?Property) is nondet
rdfs_subproperty_of(?SubProperty, +Property) is nondet
Query the property hierarchy.
   93rdfs_subproperty_of(SubProperty, Property) :-
   94    rdf_reachable(SubProperty, rdfs:subPropertyOf, Property).
   95
   96
   97                 /*******************************
   98                 *        CLASS HIERARCHY       *
   99                 *******************************/
 rdfs_subclass_of(+Class, ?Super) is nondet
rdfs_subclass_of(?Class, +Super) is nondet
Generate sub/super classes. rdf_reachable/3 considers the rdfs:subPropertyOf relation as well as cycles. Note that by definition all classes are subclass of rdfs:Resource, a case which is dealt with by the 1st and 3th clauses :-(

According to production 2.4 "rdfs:Datatype", Each instance of rdfs:Datatype is a subclass of rdfs:Literal.

  112rdfs_subclass_of(Class, Super) :-
  113    rdf_equal(rdfs:'Resource', Resource),
  114    Super == Resource,
  115    !,
  116    rdfs_individual_of(Class, rdfs:'Class').
  117rdfs_subclass_of(Class, Super) :-
  118    rdf_reachable(Class, rdfs:subClassOf, Super).
  119rdfs_subclass_of(Class, Super) :-
  120    nonvar(Class),
  121    var(Super),
  122    \+ rdf_reachable(Class, rdfs:subClassOf, rdfs:'Resource'),
  123    rdfs_individual_of(Class, rdfs:'Class'),
  124    rdf_equal(Super, rdfs:'Resource').
  125rdfs_subclass_of(Class, Super) :-       % production 2.4
  126    (   nonvar(Class)
  127    ->  rdf_has(Class, rdf:type, CType),
  128        rdf_reachable(CType, rdfs:subClassOf, rdfs:'Datatype'),
  129        \+ rdf_reachable(Class, rdfs:subClassOf, rdfs:'Literal'),
  130        rdf_equal(Super, rdfs:'Literal')
  131    ;   nonvar(Super)
  132    ->  rdf_reachable(Super, rdfs:subClassOf, rdfs:'Literal'),
  133        rdfs_individual_of(Class, rdfs:'Datatype')
  134    ).
  135
  136
  137                 /*******************************
  138                 *          INDIVIDUALS         *
  139                 *******************************/
 rdfs_individual_of(+Resource, +Class) is semidet
rdfs_individual_of(+Resource, -Class) is nondet
rdfs_individual_of(-Resource, +Class) is nondet
Generate resources belonging to a class or classes a resource belongs to. We assume everything at the `object' end of a triple is a class. A validator should confirm this property.

rdfs_individual_of(+, -) does not exploit domain and range properties, deriving that if rdf(R, P, _) is present R must satisfy the domain of P (and similar for range).

There are a few hacks:

  158rdfs_individual_of(Resource, Class) :-
  159    nonvar(Resource),
  160    !,
  161    (   nonvar(Class)
  162    ->  (   rdf_equal(Class, rdfs:'Resource')
  163        ->  true
  164        ;   rdfs_individual_of_r_c(Resource, Class)
  165        ->  true
  166        )
  167    ;   rdfs_individual_of_r_c(Resource, Class)
  168    ).
  169rdfs_individual_of(Resource, Class) :-
  170    nonvar(Class),
  171    !,
  172    (   rdf_equal(Class, rdfs:'Resource')
  173    ->  rdf_subject(Resource)
  174    ;   rdfs_subclass_of(SubClass, Class),
  175        rdf_has(Resource, rdf:type, SubClass)
  176    ).
  177rdfs_individual_of(_Resource, _Class) :-
  178    throw(error(instantiation_error, _)).
 rdfs_individual_of_r_c(+Resource, ?Class) is nondet
  182rdfs_individual_of_r_c(literal(_), Class) :-
  183    !,
  184    rdfs_subclass_of(Class, rdfs:'Literal').
  185rdfs_individual_of_r_c(Resource, Class) :-
  186    (   rdf_has(Resource, rdf:type, MyClass)
  187    *-> rdfs_subclass_of(MyClass, Class)
  188    ;   rdf_equal(Class, rdfs:'Resource')
  189    ).
 rdfs_label(+Resource, -Label)
rdfs_label(-Resource, +Label)
Convert between class and label. If the label is generated from the resource the it uses both rdfs:label and its sub-properties, but labels registered with rdfs:label are returned first.
  199rdfs_label(Resource, Label) :-
  200    rdfs_label(Resource, _, Label).
 rdfs_label(+Resource, ?Lang, -Label) is multi
rdfs_label(+Resource, ?Lang, +Label) is semidet
rdfs_label(-Resource, ?Lang, ?Label) is nondet
Resource has Label in Lang. If Resource is nonvar calls take_label/3 which is guaranteed to succeed label.
  209rdfs_label(Resource, Lang, Label) :-
  210    nonvar(Resource),
  211    !,
  212    take_label(Resource, Lang, Label).
  213rdfs_label(Resource, Lang, Label) :-
  214    rdf_has(Resource, rdfs:label, literal(lang(Lang, Label))).
 rdfs_ns_label(+Resource, -Label) is multi
 rdfs_ns_label(+Resource, ?Lang, -Label) is multi
Present label with namespace indication. This predicate is intended to provide meaningful short names applicable to ontology maintainers. Note that this predicate is non-deterministic if the resource has multiple rdfs:label properties
  224rdfs_ns_label(Resource, Label) :-
  225    rdfs_ns_label(Resource, _, Label).
  226
  227rdfs_ns_label(Resource, Lang, Label) :-
  228    rdfs_label(Resource, Lang, Label0),
  229    (   rdf_global_id(NS:_, Resource),
  230        Label0 \== ''
  231    ->  atomic_list_concat([NS, Label0], :, Label)
  232    ;   \+ rdf_has(Resource, rdfs:label, _)
  233    ->  Label = Resource
  234    ;   member(Sep, [#,/]),
  235        sub_atom(Resource, B, L, A, Sep),
  236        sub_atom(Resource, _, A, 0, Frag),
  237        \+ sub_atom(Frag, _, _, _, Sep)
  238    ->  Len is B+L,
  239        sub_atom(Resource, 0, Len, _, NS),
  240        atomic_list_concat([NS, Label0], :, Label)
  241    ;   Label = Label0
  242    ).
 take_label(+Resource, ?Lang, -Label) is multi
Get the label to use for a resource in the give Language. First tries label_of/3. If this fails, break the Resource over # or / and if all fails, unify Label with Resource.
  251take_label(Resource, Lang, Label) :-
  252    (   label_of(Resource, Lang, Label)
  253    *-> true
  254    ;   after_char(Resource, '#', Local)
  255    ->  Label = Local
  256    ;   after_char(Resource, '/', Local)
  257    ->  Label = Local
  258    ;   Label = Resource
  259    ).
  260
  261after_char(Atom, Char, Rest) :-
  262    State = last(-),
  263    (   sub_atom(Atom, _, _, L, Char),
  264        nb_setarg(1, State, L),
  265        fail
  266    ;   arg(1, State, L),
  267        L \== (-)
  268    ),
  269    sub_atom(Atom, _, L, 0, Rest).
 label_of(+Resource, ?Lang, ?Label) is nondet
True if rdf_has(Resource, rdfs:label, literal(Lang, Label)) is true, but guaranteed to generate rdfs:label before any subproperty thereof.
  278label_of(Resource, Lang, Label) :-
  279    rdf(Resource, rdfs:label, literal(lang(Lang, Label))),
  280    nonvar(Lang).
  281label_of(Resource, Lang, Label) :-
  282    rdf_equal(rdfs:label, LabelP),
  283    rdf_has(Resource, LabelP, literal(lang(Lang, Label)), P),
  284    nonvar(Lang),
  285    P \== LabelP.
  286label_of(Resource, Lang, Label) :-
  287    var(Lang),
  288    rdf_has(Resource, rdfs:label, literal(type(xsd:string, Label))).
 rdfs_class_property(+Class, ?Property)
Enumerate the properties in the domain of Class.
  294rdfs_class_property(Class, Property) :-
  295    rdfs_individual_of(Property, rdf:'Property'),
  296    rdf_has(Property, rdfs:domain, Domain),
  297    rdfs_subclass_of(Class, Domain).
  298
  299
  300                 /*******************************
  301                 *           COLLECTIONS        *
  302                 *******************************/
 rdfs_member(?Element, +Set)
As Prolog member on sets. Operates both on attributes parsed as parseType="Collection" as well as on Bag, Set and Alt.
  309rdfs_member(Element, Set) :-
  310    rdf_has(Set, rdf:first, _),
  311    !,
  312    rdfs_collection_member(Element, Set).
  313rdfs_member(Element, Set) :-
  314    container_class(Class),
  315    rdfs_individual_of(Set, Class),
  316    !,
  317    (   nonvar(Element)
  318    ->  rdf(Set, Predicate, Element),
  319        rdf_member_property(Predicate, _N)
  320    ;   findall(N-V, rdf_nth(Set, N, V), Pairs),
  321        keysort(Pairs, Sorted),
  322        member(_-Element, Sorted)
  323    ).
  324
  325rdf_nth(Set, N, V) :-
  326    rdf(Set, P, V),
  327    rdf_member_property(P, N).
  328
  329:- rdf_meta container_class(r).  330
  331container_class(rdf:'Bag').
  332container_class(rdf:'Seq').
  333container_class(rdf:'Alt').
  334
  335
  336rdfs_collection_member(Element, Set) :-
  337    rdf_has(Set, rdf:first, Element).
  338rdfs_collection_member(Element, Set) :-
  339    rdf_has(Set, rdf:rest, Tail),
  340    !,
  341    rdfs_collection_member(Element, Tail).
 rdfs_list_to_prolog_list(+RDFSList, -PrologList)
Convert ann RDFS list (result from parseType=Collection) into a Prolog list of elements.
  349rdfs_list_to_prolog_list(Set, []) :-
  350    rdf_equal(Set, rdf:nil),
  351    !.
  352rdfs_list_to_prolog_list(Set, [H|T]) :-
  353    rdf_has(Set, rdf:first, H),
  354    rdf_has(Set, rdf:rest, Tail),
  355    !,
  356    rdfs_list_to_prolog_list(Tail, T).
 rdfs_assert_list(+Resources, -List) is det
 rdfs_assert_list(+Resources, -List, +DB) is det
Create an RDF list from the given Resources.
  364rdfs_assert_list(Resources, List) :-
  365    rdfs_assert_list(Resources, List, user).
  366
  367rdfs_assert_list([], Nil, _) :-
  368    rdf_equal(rdf:nil, Nil).
  369rdfs_assert_list([H|T], List, DB) :-
  370    rdfs_assert_list(T, Tail, DB),
  371    rdf_bnode(List),
  372    rdf_assert(List, rdf:rest, Tail, DB),
  373    rdf_assert(List, rdf:first, H, DB),
  374    rdf_assert(List, rdf:type, rdf:'List', DB).
  375
  376
  377                 /*******************************
  378                 *     SEARCH IN HIERARCHY      *
  379                 *******************************/
 rdfs_find(+String, +Domain, ?Properties, +Method, -Subject)
Search all classes below Domain for a literal property with that matches String. Method is one of

domain is defined by owl_satisfy from owl.pl

Note that the rdfs:label field is handled by rdfs_label/2, making the URI-ref fragment name the last resort to determine the label.

  397rdfs_find(String, Domain, Fields, Method, Subject) :-
  398    var(Fields),
  399    !,
  400    For =.. [Method,String],
  401    rdf_has(Subject, Field, literal(For, _)),
  402    owl_satisfies(Domain, Subject),
  403    Fields = [Field].               % report where we found it.
  404rdfs_find(String, Domain, Fields, Method, Subject) :-
  405    globalise_list(Fields, GlobalFields),
  406    For =.. [Method,String],
  407    member(Field, GlobalFields),
  408    (   Field == resource
  409    ->  rdf_subject(Subject),
  410        rdf_match_label(Method, String, Subject)
  411    ;   rdf_has(Subject, Field, literal(For, _))
  412    ),
  413    owl_satisfies(Domain, Subject).
  414
  415owl_satisfies(Domain, _) :-
  416    rdf_equal(rdfs:'Resource', Domain),
  417    !.
  418                                        % Descriptions
  419owl_satisfies(class(Domain), Resource) :-
  420    !,
  421    (   rdf_equal(Domain, rdfs:'Resource')
  422    ->  true
  423    ;   rdfs_subclass_of(Resource, Domain)
  424    ).
  425owl_satisfies(union_of(Domains), Resource) :-
  426    !,
  427    member(Domain, Domains),
  428    owl_satisfies(Domain, Resource),
  429    !.
  430owl_satisfies(intersection_of(Domains), Resource) :-
  431    !,
  432    in_all_domains(Domains, Resource).
  433owl_satisfies(complement_of(Domain), Resource) :-
  434    !,
  435    \+ owl_satisfies(Domain, Resource).
  436owl_satisfies(one_of(List), Resource) :-
  437    !,
  438    memberchk(Resource, List).
  439                                        % Restrictions
  440owl_satisfies(all_values_from(Domain), Resource) :-
  441    (   rdf_equal(Domain, rdfs:'Resource')
  442    ->  true
  443    ;   rdfs_individual_of(Resource, Domain)
  444    ),
  445    !.
  446owl_satisfies(some_values_from(_Domain), _Resource) :- !.
  447owl_satisfies(has_value(Value), Resource) :-
  448    rdf_equal(Value, Resource).
  449
  450
  451in_all_domains([], _).
  452in_all_domains([H|T], Resource) :-
  453    owl_satisfies(H, Resource),
  454    in_all_domains(T, Resource).
  455
  456globalise_list([], []) :- !.
  457globalise_list([H0|T0], [H|T]) :-
  458    !,
  459    globalise_list(H0, H),
  460    globalise_list(T0, T).
  461globalise_list(X, G) :-
  462    rdf_global_id(X, G)