Liking cljdoc? Tell your friends :D

NaturalLexicon logo ont-app/rdf

A backstop for shared logic between rdf-based implementations of IGraph.

Part of the ont-app library, dedicated to Ontology-driven development.

Contents

Dependencies

Clojars Project

Require thus:

(:require 
  [ont-app.rdf.core :as rdf-app]
  )      

URI namespace mappings

The namepace metadata of the core maps to ont-app.rdf.ont, whose preferred prefix is rdf-app (since rdf is already spoken for with ont-app.vocabulary.rdf).

The preferred namespace URI is declared as "http://rdf.naturallexicon.org/rdf/ont#".

Motivation

There are numerous RDF-based platforms, each with its own idosyncracies, but there is also a significant overlap between the underlying logical structure of each RDF platform. This library aims to capture that overlap, parameterized appropriately for implementation-specific variations.

This includes:

  • A multimethod render-literal, aimed at translating between clojure data and data to be stored in an RDF store.
  • Support for language-tagged strings with #lstr reader macro defined in the vocabulary module.
  • Support for a ^^transit:json datatype tag, allowing for arbitrary clojure content to be serialized/deserialized as strings in an RDF store.
  • SPARQL query templates and supporting code to query for the standard member access methods of the IGraph protocol.

Literals

The render-literal multimethod

Each RDF-based implementation of IGraph will need to translate between clojure data and RDF literals. These will include langage-tagged strings, xsd types for the usual scalar values, and possibly custom URI-tagged data. Sometimes the specific platform will already define its own intermediate datastructures for such literals.

The render-literal multimethod exists to handle the task of translating between these contexts.

render-literal is dispatched by the function render-literal-dispatch, which takes as an argument a single literal, and returns a value expected to be fielded by some render-literal method keyed to that value.

By default, instances of the LangStr record (described below) will be dispatched on ::LangStr, with a method defined to return say "my word"@en. otherwise the dispatch value will be the type of the literal.

Integers and floats will be rendered directly by default. Values unhandled by a specific method will default to be rendered in quotes.

There is a translate-literal method defined for :rdf-app/TransitData, discussed in more detail below.

@special-literal-dispatch

Often there is platform-specific behavior required for specific types of literals, for example grafter has its own way of handling xsd values.

There is an atom defined called special-literal-dispatch (defult nil) which if non-nil should be a function f [x] -> <dispatch-value>. Any non-nil dispatch value returned by this function will override the default behavior of render-literal-dispatch, and provide a dispatch value to which you may target the appropriate methods.

The igraph-grafter source has examples of this.

Language-tagged strings

This library imports 'ont-app.vocabulary.lstr', along with its #lstr reader macro.

Such values will be dispatched to render-literal as :rdf/LangStr, but the render-literal method for LangStr is expected to be platform-specific.

xsd values

Most RDF-platforms will typically provide some means of dealing with xsd-encoded values, which encode the usual scalar values such as integers, floats, dates, etc.

Part of adapting IGraph to any new RDF-based platform will involve defining special-literal-dispatch and render-literal methods as appropriate.

The existing sparql-client and igraph-grafter implementations should serve as instructive examples.

Transit-encoded values

Of course some values such as the standard Clojure containers, and user-defined records and datatypes are not handled by the xsd standard.

This library supports storing such literals in serialized form using a ^^transit.json datatype URI tag.

> (rdf-app/render-literal [1 2 3])
"\"[1, 2, 3]\"^^transit:json"

> (rdf-app/read-transit-json "[1,2,3]")
[1 2 3]

> (def round-trip [x]
    (-> (re-matches rdf-app/transit-re (rdf-app/render-literal x))
        (nth 1))
        (rdf-app/read-transit-json))
        
> (round-trip `(fn [x] "yowsa"))
(fn [x] "yowsa")

The render-literal method keyed to :rdf/TransitData is the handler encoding data as transit. To use it, take the following steps:

  • As needed, add a translit read handler to transit-read-handlers.
    • Note in core.cljc that LangStr already has such such a handler
  • As needed, add a transit write handler to transit-write-handlers
    • Again, the LangStr record is already covered, and should serve as a good example.
  • Use derive to make the data type to be rendered a descendent of :rdf/TransitData. This will make the eligible for handling by that render-literal method.
    • e.g. (derive clojure.lang.PersistentVector :rdf/TransitData)
    • All the usual clojure containers already have such derive declarations.
  • Transit rendering for any such type can disabled using underive.

The datatype URI whose qname is transit:json expands to <http://rdf.natural-lexicon.org/ns/cognitect.transit#json>, based on the following delcaration in ont-app.rdf.ont:

(voc/put-ns-meta!
 'cognitect.transit
 {
  :vann/preferredNamespacePrefix "transit"
  :vann/preferredNamespaceUri "http://rdf.naturallexicon.org/ns/cognitect.transit#"
  :dc/description "Functionality for the transit serialization format"
  :foaf/homepage "https://github.com/cognitect/transit-format"
  })

Query templates supporting the IGraph member-access methods

It is expected that the basic IGraph member-access methods will be covered by a common set of SPARQL queries for most if not all RDF-based implementations.

For example, here is a template that should serve to acquire normal form of a given graph (modulo tractability):

(def normal-form-query-template
  "
  Select ?s ?p ?o
  Where
  {
    {{{graph-name-open}}}
    ?_s ?_p ?_o
    # rebinding supports things like platform-specific round-tripping
    Bind ({{{rebind-_s}}} as ?s)
    Bind ({{{rebind-_p}}} as ?p)
    Bind ({{{rebind-_o}}} as ?o)
    {{{graph-name-close}}}
  }
  ")

This template can be referenced by a function query-for-normal-form

> (query-for-normal-form <query-fn> <rdf-store>)
> (query-for-normal-form <graph-kwi> <query-fn> <rdf-store>)

Where:

  • <graph-kwi> is a KWI for the named graph URI (defaults to nil, indicating the DEFAULT graph)
  • <query-fn> is a platform-specific function to pose the rendered query template to rdf-store.
  • <rdf-store> is a platform-specific point of access to the RDF store, e.g. a database connection or SPARQL endpoint.

Analogous template/function ensembles are defined for:

  • query-for-subjects
  • query-for-p-o
  • query-for-o
  • ask-s-p-o

Wherever KWIs are involved, checks will be performed to flag warnings in cases where the metadata has not been properly specified for the implied namespace of the KWI.

Note that the query template above has clauses like:

    ...
    Bind ({{{rebind-_s}}} as ?s)
    ...

The purpose of this is to allow for rebinding of blank nodes to a platform-specific scheme that supports 'round-tripping' of blank nodes in subsequent queries to the same endpoint. The igraph-jena project provides a working example of this.

Debugging

In addition to standard logging, functions in this module are logged with the graph-log logging library, which records various execution events at log levels :glog/TRACE and :glog/DEBUG.

This can be enabled thus:

(require [ont-app.graph-log.core :as glog])

> (glog/set-level! :glog/LogGraph :glog/TRACE)
> ;; DO STUFF
> (glog/entries)
[<entry 0>
 .....
 <entry n>
 ]
 > 

See the graph-log documentation for details.

License

Copyright © 2020 Eric D. Scott

This program and the accompanying materials are made available under the terms of the Eclipse Public License 2.0 which is available at http://www.eclipse.org/legal/epl-2.0.

This Source Code may also be made available under the following Secondary Licenses when the conditions for such availability set forth in the Eclipse Public License, v. 2.0 are satisfied: GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version, with the GNU Classpath Exception which is available at https://www.gnu.org/software/classpath/license.html.

Natural Lexicon logo

Natural Lexicon logo - Copyright © 2020 Eric D. Scott. Artwork by Athena M. Scott.

Released under Creative Commons Attribution-ShareAlike 4.0 International license. Under the terms of this license, if you display this logo or derivates thereof, you must include an attribution to the original source, with a link to https://github.com/ont-app, or http://ericdscott.com.

Can you improve this documentation?Edit on GitHub

cljdoc is a website building & hosting documentation for Clojure/Script libraries

× close