authors: Chris Dollin, Dave Reynolds
date: Seprember 11th, 2003
version: 1.1; OBSOLETE - new documentation FORTHCOMING.

Model Specification API

This document describes the version of the Jena Model Specification API for Jena 2.0. The JMS is neither complete nor frozen; we hope users will experiment with the early implementations and offer sugegstions that we can incorporate into later versions.

This document is a minor revision of the Jena 2.0 design document, itself a revision of a design note circulated to the jena-devel mailing list in August.

Requirements

The purpose of the model specification API is to allow Model configurations to be declaratively specified, for example, so that an application can create or access a model defined by some configuration parameter or file.

More specifically we wish to:

Scope

We can imagine models as comprising three layers - an API, a storage layer and an optional intervening inference layer. The range of options and configuration parameters needed for these layers by Jena2, as it currently stands, is captured below.
Layer
Option
Parameter
API Model  
InfModel [reasoner]
OntModel OntModelSpec = importMaker, docManager, [reasoner], language
Inference   reasoner = reasonerURI + config
Storage Mem reificationMode
File reificationMode, baseDir
DB reificationMode, IDBConnection = url, user, password, type

Future Jena extensions may add additional options to any of these layers.

The bulk of these cases are easy to specify declaratively.

There are two cases where the additional option of passing an existing specific runtime java object as a parameter would be desirable - a java.sql.Connection for a dB store and a OntDocumentManager for an OntModel specification. The bulk of Model usage could be covered without this additional capability.

API Design

The basic design approach to define a new Java object, ModelSpec, to hold the parsed specification for a type of Model. Instances of ModelSpec can be passed to new ModelFactory calls to create models according to the specification. An instance of ModelSpec can be created from an RDF specification, either one loaded from file using the normal Jena functions or an inline one in some shorthand syntax like N3.

For extensibility ModelSpec is an interface. Future types of Models can be associated with new implementation of ModelSpec. The already-existing OntModelSpec performed a very similar job, and was revised to implement ModelSpec and used as a driver in the code development.

interface ModelSpec
    Model createModel()
    Model createModelOver( String name )
    Model getDescription()
    [other description-producing/augmenting methods]
A ModelSpec can be used to create a Model, to create a Model "over" a base Model found in an internal ModelMaker, and to produce an RDF description of the same kind as was used to create it.

It is convenient to refactor so that the existing ModelMaker interface extends ModelSpec: thus a ModelMaker can be used wherever a ModelSpec is required.

ModelSpec's are usually created by ModelFactory.create(), which has four flavours:

    create( Model desc )
    create( Resource desc )
    create( Resource root, Model desc )
    create( Resource root, Resource desc )
When desc is a resource, its URI identifies where the model to be used is loaded from. When root is omitted, it is implied as the unique resource in the description with type jms:ModelSpec.
class PlainModelSpec implements ModelSpec
    PlainModelSpec( Model description )
    PlainModelSpec( Resource root, Model description )
    ModelMaker: maker
    getter/setters as required

class InfModelSpec implements ModelSpec extends PlainModelSpec
    InfModelSpec( Model description )
    InfModelSpec( Resource root, Model description )
    Reasoner: reasoner
    getter/setters for reasoner

class OntModelSpec implements ModelSpec extends InfModelSpec
    OntModelSpec( Model description )
    OntModelSpec( Resource root, Model description )
    [other OntModelSpec constructors as before]
    String: language
    OntDocumentManager: docManager
    ModelMaker: importMaker
    getter/setters as current
[Earlier versions of this design used init methods, but the current implementation does not, leaving all initialisation to the constructor and further tweaking to the class-specific getters and setters. This choice can be revisted if necessary.]

The constructors taking a (Resource, Model) pair use the sub-graph rooted at the Resource as the description; the Resource must have rdf:type jms:ModelSpec. Thus a single model may contain multiple descriptions. The constructors taking just a Model require that there be a single Resource with that type, which is used as the root of the description.

The design also allows multiple Specs to be described by a single Model, and to have a ModelSpec factory:

class ModelSpecFactory
   ModelSpec create()
   ModelSpec create(Resource config)
   Map createMultipleSpec(Model model)
   ModelSpec createFromN3(String config)

class ModelFactory
   ...
   Model createModel(ModelSpec)
   Model convertTo(ModelSpec, Model)
   ...
   ModelSpec DEFAULT
   ModelSpec MEM_RDFS_INF
   ModelSpec ONT_OWL_MEM_RULE_INF
   etc
The existing implementation does not provide this functionality.

The already-existing ModelFactory methods remain as convenience methods but the single createModel call now covers most of the existing uses, except for the final casting of the returned Model to the appropriate static type.

Extensions and design notes

We imagine a single RDF configuration file being used for defining multiple models. The createMultipleSpec is an early hook to simplify this sort of usage but additional convenience functions can be imagined. In particular, it might be handy to be able to refer to the separate specifications by name rather than by URI given the lack of legibility of URIs.

As defined above if one needs to have a specification build on an existing runtime object like a dB Connection or a replacement ontDocumentManager that would have to be done programmatically (e.g. by a setMaker call on the ModelSpec). To cope with this, the ModelSpecImpl class provides a way to create a new Resource object associated with a Java value, and to retrieve that object from the resource. This allows descriptions to indirectly refer to computed values. [Serialising such models loses the value.]

RDF Schema

A suggested RDFS representation of specifications is outlined below. We have used an informal syntax in which:


class foo subClassOf bar
    prop: Range

means:


    jms:foo rdf:type rdfs:Class .
    jms:foo rdfs:subClassOf bar .
    jms:prop rdf:type rdfs:Property .
    jms:prop rdfs:range jms:Range .
jms is the namespace prefix used for the specifcations; Jena binds it to http://jena.hpl.hp.com/2003/08/jms#.
class ModelSpec
    maker : MakerSpec

class InfModelSpec subClassOf ModelSpec
    reasonsWith : ReasonerSpec

class OntModelSpec subClassOf InfModelSpec
    ontLanguage : String
    importMaker : MakerSpec
    docManger : DocManager

class DocManager
    policyPath : String

class MakerSpec
    reificationMode : String

class MemMaker subClassOf MakerSpec

class FileMaker subClassOf MakerSpec
    filebase : String

class DBMaker subClassOf MakerSpec
    dbURL : Resource
    dbUser : String
    dbPassword : String
    dbType : String
    dbClass: String
    dbConnection : [magic Java object reference]

class ReasonerSpec
    reasoner : Resource
    .. other reasoner specific config props defined by reasoner ..