3.  URI, QName, and Resource

The Resource Description Framework (RDF) is a language for representing information about resources in the World Wide Webs, and it has a special syntax in XML called RDF/XML for short. In RDF, every resource, except literals and blank nodes, is identified with URI references. This idea originates from the meta-data markup for web resources. However, you do not need to mind in Semantic Webs or ontology descriptions whether resources in RDF really exist on the Webs or not.

In theory, a URI reference in RDF denotes an entity in the universe of discourse, namely a virtual world that reflects ideas on the real world. If a URI reference is a terminology in ontology, the URI reference in SWCLOS is bound with a CLOS object that represents a part of ontology on the denotation of a URI reference. You can input a URI reference object in SWCLOS using angle bracket reader macro ‘<’, where URI reference reading is terminated by ‘>’. In the following demonstration, note that expressions enveloped with ‘<’ and ‘>’ designate URIs, and expressions starting with a sharp character and enveloped with ‘<’ and ‘>’ designate objects in Lisp.

gx-user(3): <http://www.w3.org/2000/01/rdf-schema#Resource>
#<uri http://www.w3.org/2000/01/rdf-schema#Resource>
gx-user(4): (iri-value
              <http://www.w3.org/2000/01/rdf-schema#Resource>)
#<rdfs:Class rdfs:Resource>

The QName is an abbreviation of URI reference with the namespace function for XML. For example, “<http://www.w3.org/2000/01/rdf-schema#Resource>” is abbreviated to “rdfs:Resource”. Here, the fragment-less URI or “http://www.w3.org/2000/01/rdf-schema” is mapped to “rdfs”, which is a prefix of QName, while a fragment “Resource” turns out a local part of QName. Franz Inc. provides URI APIs, in which a URI is implemented of CLOS objects typed to net.uri:uri. In SWCLOS, a part of URI that corresponds to a prefix part of QName is connected to a lisp package, whereby a URI corresponds to a QName as lisp symbol in a package. Thus, a URI reference may have one by one mapping to a lisp symbol (QName), and vice versa, if it has a namespace. See the followings.

gx-user(5): (uri2symbol
              <http://www.w3.org/2000/01/rdf-schema#Resource>)
rdfs:Resource
gx-user(6): (symbol2uri 'rdfs:Resource)
#<uri http://www.w3.org/2000/01/rdf-schema#Resource>

At the line 5 in the demonstration above, the URI is converted to the corresponding QName, and at line 6, the reverse operation is directed. Note that such correspondence can be established when SWCLOS loads an ontology including URI references, or when you input URI references as RDF entity in the lisp top level window.

In theory, the substance of RDF can be modeled as labeled uni-directional graph of edge and node called RDF graph. A start node of edge is called subject, an end node is called object, and an edge is called predicate in triple. So, a triple subject/predicate/object in text stands for the minimal structure in graph. A set of triples in text turns out a whole RDF graph.

A predicate in triple is a URI reference or QName, and the statement of predicate requires or produces the corresponding resource called property in RDF vocabulary. Note that any edge must be named by a URI in RDF. Furthermore, it must have a QName in SWCLOS, because it turns a slot name in CLOS. A subject in triple designates a non-literal resource, that is, the node must be expressed by a URI, otherwise it must be a blank node. The blank node has no URI but may be assigned with a blank node ID. An object in triple is either a resource (with or without URI) or a literal. The following shows an example of statement in N-Triple.

<John_Doe> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <Man> .

In SWCLOS, a resource or an entity in RDF is realized as a CLOS object. A denotation of triple subject/predicate/object is represented by a subjective CLOS object and its slot of which the slot name is corresponding to a predicate. The slot value is an objective CLOS object (called resource) or lisp data (literal).

The subjective CLOS object is bound to the QName lisp symbol, if it is not a blank node.

gx-user(7): rdfs:Resource
#<rdfs:Class rdfs:Resource>

As well as a subjective CLOS object is bound to the QName, every subjective CLOS object, even if a blank node, is bound to the relevant URI. See the following demonstration.

gx-user(8): (iri-value
              <http://www.w3.org/2000/01/rdf-schema#Resource>)
#<rdfs:Class rdfs:Resource>
gx-user(9): <<http://www.w3.org/2000/01/rdf-schema#Resource>>
#<rdfs:Class rdfs:Resource>

Note that at line 9, the special reader macro for double angle brackets ‘<<’ reads the character sequence of URI up to characters ‘>>’ and then a bound value to the converted URI is returned. A CLOS object that represents a resource in RDF is called resource object in SWCLOS.

3.1  IRI

SWCLOS utilizes the URI APIs of Allegro Common Lisp (ACL). Please see the details http://www.franz.com/support/documentation/8.2/doc/uri.htm. To implement value-bindable URI, a subclass of net.uri:uri is defined with an extra value slot. This subclass is named IRI. Every IRI in SWCLOS is interned to ensure the uniqueness of IRI in system.

iri
[Class]
A subclass of net.uri:uri. It has the definition of extra slot for value, to which the corresponding resource object is stored.

iri  thing
[Method]
Four methods are defined for this generic function: When thing is an instance of iri, then interned value of it is returned. If thing is an instance of net.uri:uri, its class is changed to iri and interned. The interned value is returned. When thing is a string, it is interned as a uri and its class is changed to iri. Otherwise, it signals an error.

iri-value  iri
[Function]
This function returns a value in its value slot. iri must be an IRI or a string. This function is settable for an IRI.

There are several utilities for handling all uri and iri entries. See print-all-entity-uris, do-all-entity-uris, and list-all-entity-uris in doc folder.

3.2  QName

A uri and iri in SWCLOS may be converted to the corresponding QName. The prefix of QName in XML is mapped to a lisp package in SWCLOS, and the local part is mapped to a symbol name in the package. A QName symbol is exported, because an exported lisp symbol has the same appearance as the QName in XML. A QName symbol is used to designate a resource name in S-expression. In fact, the description at the top level in SWCLOS requires a QName symbol instead of a URI in the context of define macros such as defConcept and defIndividual. Some URI(IRI)s that have no prefix definition cannot be converted to QNames and remain as URI(IRI).

The mapping rule from URI to QName in SWCLOS is as follows.

See the following demonstration.

gx-user(17): (uri2symbol <http://somewhere/maindir/subdir/JohnSmith>)
swsd:JohnSmith
gx-user(18): (uri2symbol <http://somewhere/JohnSmith>)
sw:JohnSmith
gx-user(19): (uri2symbol <http://JohnSmith/>)
no:J.S.

At line 17, prefix query to users is carried out for “<http://somewhere/somedirectory/subdir/>”, and “swsd” is replied by a user. At line 18 for “<http://somewhere/>”, “sw” is replied. At line 19, the local name is required at first, then “J.S.” is supplied, then, “no”" is replied for the prefix query.

3.3  URI Named Space

A URI reference is unique in WWWs, and then XML namespace supports the uniqueness of QName with a local part, which is unique in a name space. In SWCLOS, a local part of QName corresponds to symbol name in a package, and a namespace for a prefix part corresponds to a lisp package. To realize such mapping, we need the connection between a prefix part in URI and a lisp package, and when URI-to-symbol mapping is irregular such as demonstrated above, we further need the mapping from a URI to a symbol name in the lisp package. An instance of uri-namedspace, that is a subclass of net.uri:uri, has two extra slots, package and environment, and it enables such named space environments for the URI name space. See the following demonstration.

gx-user(2): (defpackage :ex
              (:documentation "http://somewhere/main/sub/file"))
#<The ex package>
gx-user(3): (set-uri-namedspace-from-pkg (find-package :ex))
#<The ex package>
gx-user(4): (get-uri-namedspace <http://somewhere/main/sub/file>)
#<uri-namedspace http://somewhere/main/sub/file>
gx-user(5): (uri2package "http://somewhere/main/sub/file")
#<The ex package>
gx-user(6): (uri2symbol "http://somewhere/main/sub/file#JohnSmith")
ex:JohnSmith

In the above demonstration, a URI string is set to a new package named gexh as its documentation option at first, and then the regular mapping is set as prefix named space in system at line 3. So, URI to package mapping is established here as shown later on line 5. In regular mapping for a URI with fragment, regular URI to QName conversion is carried out in default rules without using the URI's symbol mapping environment.

A user may set any user-defined functions to global variable *uri2symbol-name-mapping-fun* and *uri2symbol-package-mapping-fun* in order to implement application-oriented rules for the irregular mapping in default. See the detail in the description of the documentation file of program in the doc folder and the source program.

When SWCLOS reads RDF/XML files, the namespace directions with PrefixedAttName 'xmlns:' and DefaultAttName 'xmlns' make the mapping from a URI to the package name. On the other hand, from the standpoint of lisp expression, SWCLOS users can direct the mapping from a package to a uri in the package documentation as demonstrated above, in which a user put a corresponding URI as documentation of package.

Sometime you may be embarrassed at an error message of no package for a base-URI or a default namespace, when SWCLOS reads an RDF/XML file. It happens if an RDF/XML file does not include any Prefix name in the file for the file itself. In such a case, it is recommended that you supply two sentences, something like “xmlns:base = 'somewhere'” and “xmlns:PREFIX = 'somewhere'” into RDF attributes in the file.

Each uri-namedspace is stored in a hasharray which is bound to a global variable *NameSpaces*. The converting functions, uri2symbol and symbol2uri use these mappings bound to *NameSpaces*.

*NameSpaces*
[Global Var]
A variable where a hashtable is set. The hashtable is for interning prefix URIs that are instances of uri-namedspace. See the document of interning URIs. The interning into this hashtable is carried out at the occurrence of the first mapping from a fragment-less URI, a name-less URI, or a specially directed URI to a package. See uri2symbol.

uri-namedspace
[Class]
Subclass of net.uri:uri class. This subclass has two extra slot definitions; package slot definition and env slot definition. The associated lisp package is stored into the package slot and the irregular associations in the namespace between URIs and QName symbol names are stored into the env slot of this instance object.

list-all-uri-namedspaces
[Function]
This function returns a list of all uri-namedspaces in the system.

set-uri-namedspace prefix-uri
[Function]
This function changes prefix-uri to a namedspace and registers it to system. You need to set a lisp package into the uri-namedspace package slot before the usage.

get-uri-namedspace prefix-uri
[Function]
This function retrieves the uri-namedspace from prefix-uri and returns it. If prefix-uri is not an uri, cl:nil is returned.

set-uri-namedspace-from-pkg pkg
[Function]
This function registers the namespace associated to pkg. The pkg must have a uri string in pkg's document slot.

*default-namespace*
[Global Var]
When a default namespace is indicated by DefaultAttName 'xmlns' in RDF/XML files and the system reads it, the namespace URI is set to this variable. This is often used in scoping of let form.

*base-uri*
[Global Var]
When a base URI is indicated by ‘xml:base’ in RDF/XML files and the system reads it, the URI is set to this variable. This is often used in scoping of let form.

*uri2symbol-package-mapping-fun*
[Global Var]
When there is no associated package for a URI, the function bound to this variable is invoked, and the return value is used as package for the corresponding QName symbol. This mechanism is useful to implement user-specific or application specific conversion as irregular mapping rule. The function bound to this symbol has to have one parameter, i.e., a URI.

*uri2symbol-name-mapping-fun*
[Global Var]
When there is no associated name for a URI, the function bound to this variable is invoked, and the return value is used as name for QName symbol. This mechanism is useful to implement user-specific or application-specific conversion as irregular rule. The function bound to this symbol has to have one parameter, i.e., a URI.

uri2symbol uri
[Function]
converts uri to the corresponding QName symbol and returns it. If uri is null (cl:nil) or null string, it returns cl:nil. If uri is a string, its parsed uri is used. *NameSpaces* is consulted for the association between a fragment-less or name-less URI and package. In the case of irregular mapping, the functions bound to *uri2symbol-package-mapping-fun* and *uri2symbol-name-mapping-fun* are called and the return value is used. See the mapping rule described above.

symbol2uri symbol
[Function]
returns a uri from rdf:about slot of this resource object if this symbol is defined as QName and the resource object is bound to this symbol. Otherwise this function retrieves the uri string from the symbol package of symbol, then returns a uri associated to symbol in the env slot if the association exists, or returns a uri that is made from package-corresponding (fragment-less) URI and symbol-name (as URI fragment).

Note that all resource names or QName symbols are exported. Therefore, in a dedicated package for a resource namespace, the following code is an example that lists up all defined uri in the namespace.

gx-user(7): (loop for x being each external-symbol
in (find-package :rdfs)
collect (symbol2uri x))
(#<uri http://www.w3.org/2000/01/rdf-schema#subPropertyOf>
#<uri http://www.w3.org/2000/01/rdf-schema#Datatype>
#<uri http://www.w3.org/2000/01/rdf-schema#domain>
#<uri http://www.w3.org/2000/01/rdf-schema#label>
#<uri http://www.w3.org/2000/01/rdf-schema#seeAlso>
#<uri http://www.w3.org/2000/01/rdf-schema#Container>
#<uri http://www.w3.org/2000/01/rdf-schema#subClassOf>
#<uri http://www.w3.org/2000/01/rdf-schema#isDefinedBy>
#<uri http://www.w3.org/2000/01/rdf-schema#Resource>
#<uri http://www.w3.org/2000/01/rdf-schema#range> ...)

list-all-entities-in performs almost same work.

gx-user(4): (list-all-entities-in :rdfs)
(rdfs:subPropertyOf rdfs:Datatype rdfs:domain rdfs:label rdfs:seeAlso
rdfs:Container rdfs:subClassOf rdfs:isDefinedBy
rdfs:Resource rdfs:range ...)

list-all-entities-in space
[Method]
space must be a package, a package name, a package name string, or a uri. This method returns a list of all of external symbols in space. Note that even if a user defined external symbols in space without RDF resource definition, they are listed. See also list-all-resources.

Precisely speaking, we have some semantic gap between a URI namespace and a lisp package. The lisp package is always global in the current session. Namely, a lisp package for the namespace should be unique anywhere and anytime. The URI is also globally unique, but its namespace is a temporal setting for the URI abbreviation in the scope of a RDF/XML file or a Web page. In a RDF/XML file, a settled namespace for a URI is scoped within the file, and it is legal that someone set a different name of namespace for the identical URI in another RDF/XML file. Thus, in ideal the two files should be correctly merged regardless of namespaces but regarding URIs. For example, if you have two ontology files, one has a namespace ‘wine’ for some URI and another has a namespace ‘vin’ for the same URI, the system must read both in the same namespace. However, Lisp cannot read symbols in different packages into some one package. To solve this problem, the lisp package nicknames are utilized here. When SWCLOS detects the mapping different package names onto a same URI, the newly indicated prefix turns out a nickname for the previously mapped package. Even so, note that the first encountered package name is a nominal name and nickname's prefixes do not appear in S-expression.

3.4  Resource

In addition to the URI-value mapping mentioned above, a CLOS object as resource is also set as symbol-value to the QName symbol, if it has a QName, or to an assigned nodeID symbol, if it has a nodeID. To test whether a CLOS object is a resource object or not, you may use lisp native type predicate cl:typep as follows. Note to use gx:typep predicate, if you need a type-testing predicate that exactly obeys RDFS semantics up to the range of URIs and Literals.

gx-user(2): (cl:typep rdfs:Resource rdfs:Resource)
t
gx-user(3): (cl:typep rdfs:Class rdfs:Resource)
t
gx-user(4): (cl:typep rdf:Property rdfs:Resource)
t

In the example above, three resource objects, named rdfs:Resource, rdfs:Class, and rdf:Property, are tested whether they are instances of class rdfs:Resource.

Predicate rsc-object-p is prepared for testing whether an CLOS object is a resource object or not. It is same as (cl:typep x rdfs:Resource) in the semantics but it is faster a bit and simplifies your code. Note that object? is used for testing a QName symbol or a nodeID symbol to which a resource object is bound.

gx-user(5): (object? 'rdfs:Resource)
t
gx-user(6): (object? 'rdfs:Class)
t
gx-user(7): (object? 'rdf:Property)
t

object? symbol
[Function]
returns true if symbol has a resource object, otherwise returns false.

To list up all resources defined in the system, you can use list-all-resources as follows.

gx(8): (list-all-resources t)
(#<rdfs:Class rdfs:Resource> #<rdfs:Class rdfs:Container>
 #<rdfs:Class rdf:Alt> #<rdfs:Class rdf:Seq> #<rdfs:Class rdf:Bag>
 #<rdfs:Class gx::ill-structured-XMLLiteral> #<rdfs:Class rdf:Statement>
 #<rdfs:Class rdf:List> #<rdf:List rdf:nil> #<rdfs:Class rdfs:Literal>
 ...)

list-all-resources [with-system-rdf-object-p]
[Function]
This function lists up all of resources that are defined as instance of rdfs:Resource. An instance of rdf:XMLLiteral is not included in the list. with-system-rdf-object-p is optional and RDF(S) and OWL resources are included if true is supplied, otherwise only user-defined resources are included.

In most cases, a resource object is named with a QName. The method name gets the name from a resource object and returns its QName symbol. The resource object is set to the QName symbol. On the other hand, resource objects that have no name are called anonymous resource, or blank node, or bnode for short, and you can access them through iri-value function rather than symbol value.

gx-user(2): (name rdfs:Resource)
rdfs:Resource
gx-user(3): (addObject rdfs:Resource '((rdf:about "NothingElseURI")))
#<rdfs:Resource :anonymous>
gx-user(4): <<NothingElseURI>>
#<rdfs:Resource :anonymous>
gx-user(5): (slot-value <<NothingElseURI>> 'rdf:about)
"NothingElseURI"
gx-user(6): (anonymous-p <<NothingElseURI>>)
t

Note that in the above demonstration, an anonymous object is created at line 3, whose URI string is "NothingElseURI". So, <NothingElseURI> at line 4 is parsed to a uri, and the resource object is retrieved through iri-value and returned it.

named-p resource
[Function]
returns true if a resource object resource has a name, otherwise false. If resource is not a resource object, it returns false.

anonymous-p resource
[Function]
returns true if resource has no name, otherwise false. If resource is not a resource object, it returns false.

name resource
[Method]
returns the name of resource, if named. Otherwise cl:nil. Note that this function is different from cg:name in ACL.

3.5  NodeID

A nodeID is used for referring anonymous node, especially in N-Triple notation. It looks like QName that has ‘_’ as prefix and meaningless local name such as ‘a01’. However, a nodeID is not associated to any URI and has no global identification. There is a package dedicated for nodeID in SWCLOS, its package name is ‘_’, and a nodeID is also a lisp symbol in SWCLOS. You can bind any blank node to a nodeID symbol in the current session, but there is no way to store and reload the information on nodeID bindings by SWCLOS. The following functions are for the nodeID. However, there are useful functions no more on NodeIDs in SWCLOS. Be careful to use NodeIDs with respect to the identity of blank nodes according to RDF Semantics. See RDF Semantics.

nodeID? name
[Function]
name should be a symbol. This function returns true if name can be regarded as a nodeID, namely its package name is ‘_’, otherwise returns false. This function does not care of a bound value of name.

nodeID2symbol str
[Function]
interns a nodeID symbol whose name is str in the nodeID package, exports and returns it. Users must ensure the uniqueness of the nodeID in this function usage.

make-unique-nodeID str
[Function]
interns a nodeID symbol whose name begins with str and has succeeding digits, exports and returns it. The system assures the uniqueness of the nodeID in the current system.

As well as character ‘<’ being a reader macro on for URI, character ‘_’ is also a reader macro so that the character sequence of the succeeding colon and other characters makes an exported lisp symbol, and the symbol is handed to eval function if it is bound. Otherwise new anonymous resource object is created and bound to the symbol, then the symbol is handed to eval function. See the following demonstration.

gx-user(2): _:a01
#<|rdfs:Resource| :anonymous>
gx-user(3): (quote _:a01)
_:a01
gx-user(4): (list _:a01 _:a02)
(#<|rdfs:Resource| :anonymous> #<|rdfs:Resource| :anonymous>)
gx-user(5): (eq _:a01 _:a01)
t
gx-user(6): (eq _:a01 _:a02)
nil

Where |rdfs:Resource| denotes the alternative to rdfs:Resource in SWCLOS, which is provided instead of rdfs:Resource when rdfs:Resource is specified as class of instances. It is expected that rdfs:Resource should be an abstract class in CLOS and finally all slots are defined at subclasses of rdfs:Resource, even if some slot definitions might be tentatively designated to rdfs:Resource. |rdfs:Resource| is useful to suppress making wasteful slot definitions at rdfs:Resource.


Author: Seiji Koide. Copyright (c) 2005, 2006 GALAXY EXPRESS CORPORATION. Feb.2006
Copyright (c) 2007-2010 Seiji Koide. Oct.2010