This document describes how to use the Assembler classes to construct models
-- and other things -- from RDF descriptions that use the
Jena Assembler vocabulary. That vocabulary is available in
ja-vocabulary.n3 as an RDFS schema
with conventional prefix ja
for the URI
http://jena.hpl.hp.com/2005/11/Assembler#
;
the class JA
is its Jena Java rendition.
The examples used in this document are extracted from the examples file examples.n3. The pieces of RDF/OWL schema are extracted from the ja-vocabulary file and can be viewed as N3 or in a condensed notation of the form:
class ClassName [subClassOf SuperClasses] domainOf PropertyName [withRange RangeClasses] [Cardinality] ...
The property names selected are those which are the "declared
properties" (as per Jena's listDeclaredProperties
method) of the class. Only the most specialised superclasses and
rangeclasses are shown, so (for example) rdf:Resource
typically won't appear.
An Assembler specification is a Resource in some RDF Model. The properties of that Resource describe what kind of object is to be assembled and what its components are: for example, an InfModel is constructed by specifying a base model and a reasoner. The specifications for the components are themselves Assembler specifications given by other Resources in the same Model.For example, to specify a memory model with data loaded from a file:
eg:opening-example a ja:MemoryModel ; ja:content [ja:externalContent <file:///home/kers/projects/Scratch/kers/Data/example.n3>] .
The rdf:type of eg:model specifies that the constructed Model is to be a Jena memory-based model. The ja:content property specifies that the model is to be loaded with the content of the resource file:Data/example.n3. The content handler guesses from the ".n3" suffix that this file is to be read using the Jena N3 reader.
By default, Assembler specifications are interpreted after adding in the JA schema and doing (limited) RDFS inference. In the example above, eg:model has to be given an explicit type, but the externalContent bnode is implicitly typed by the domain of ja:externalContent. In this document, we will usually leave out inferrable types.
We can construct our example model from the specification like this (you may need to tweak the filename to make this work in your environment):
Model spec = FileManager.get().loadModel( "examples.n3" ); Model root = spec.createResource( spec.expandPrefix( "eg:opening-example" ) ); Model m = Assembler.builtin.createModel( root );
The model is constructed from the "root resource",
eg:opening-example
in our example. builtin
knows how to create all the kinds of objects -- not just Models --
that we describe in the next sections.
Assembler specifications can describe many kinds of models: memory, inference, database, ontology, and file-backed. All of these model specifications share a set of base properties for attaching content, prefix mappings, and reification modes.
All of a model's ja:content
property values are
interpreted as specifying Content
objects and a single
composite Content
object is constructed and used
to initialise the model.
See Content for the description of Content
specifications. For example:
eg:common-example a ja:MemoryModel ; ja:content eg:sharedContent ; ja:content [ja:externalContent <file:///home/kers/projects/Scratch/kers/Data/B.rdf>] ; ja:content [ja:externalContent <file:///home/kers/projects/Scratch/kers/Data/A.rdf>] . eg:sharedContent ja:externalContent <http://somewhere/RDF/ont.owl> .
The model constructed for eg:A
will be loaded with the
contents of Data/A.n3
, Data/B.rdf
,
and http://somewhere/RDF/ont.owl
. If the model supports
transactions, then the content is loaded inside a transaction; if the
load fails, the transaction is aborted, and a
TransactionAbortedException
thrown.
If the content has any prefix mappings, then they are also added
to the model.
All of a model's ja:includes
, ja:prefix
,
and ja:namespace
properties are
interpreted as specifying a PrefixMapping
object and
a single composite PrefixMapping
is constructed and used
to set the prefixes of the model.
See PrefixMapping for the description of Content
specifications.
A model may have a single ja:reificationMode
property whose value must be one of the constants ja:Standard
,
ja:Convenient
, or ja:Minimal
. The
model's reification mode is set accordingly, if possible.
Not implemented yet.
A ja:Content
specification may have zero or more
ja:externalContent
property values. These are URI
resources naming an external (file or http etc) RDF object.
The constructed Content object contains the union of the values of
all such resources. For example:
eg:external-content-example ja:externalContent <http://jena.hpl.hp.com/some-jena-data.rdf>, <file:///home/kers/projects/Scratch/kers/Data/C.owl> .
The string literal value of the optional unique ja:literalContent
property is interpreted as RDF in an appropriate language. The constructed
Content object contains that RDF. The language is either specified by an
explicit ja:contentEncoding
property value, or guessed from
the content of the string. Only N3 is implemented at the moment.
For example:
eg:literal-content-example ja:literalContent "_:it dc:title 'Interesting Times'" .
If literal content is N3, it is prepended with prefix declarations for rdf, rdfs, owl, dc, and xsd before interpretation.
The description of an RDB model requires its name and a description of the JDBC connection for the database the model is in. For example:
eg:connection ja:dbType "MySQL" ; ja:dbURL <jdbc:mysql://localhost/test> ; ja:dbUser "cjd" . eg:database-example ja:connection eg:connection ; ja:modelName "Thunderbird3" .
Since ja:RDBModel
is a subclass of ja:NamedModel
,
it has a ja:ModelName
property value naming the model.
The mandatory unique property value of ja:connection
specifies the connection to the database to be used.
The description of a connection requires the database name and type
and the user name and password. If the username and password are not
specified, Assembler.builtin
will default them, normally
to the values of the system properties jena.dbUser
and
jena.dbPassword
.
The unique ja:dbURL
property value specifies the
URL of the database to be connected to.
The optional unique ja:dbType
property value
specifies the type of the database as a string.
The unique ja:dbUser
property value is a string
literal whose value is the name of the user connecting to the
database.
The unique ja:dbPassword
property value is the
password of the user connecting to the database.
A FileModel specification builds a memory model that is backed by a file. By "backed", we mean that the model is loaded from that file and written back to the file when (if) it is closed. Furthermore, the model (weakly) supports transactions.
eg:fileModel-example-1 ja:directory <file:///tmp> ; ja:modelName "simple" .
Here, the model is read from (and written to) the file /tmp/simple
.
Directory names are given as resources (not literals) and of course file names
are system dependant -- this is what one might see on a Unix system. If the
directory name is to be shared by several different FileModels, it can be useful
to give it a namespace prefix so that it can be changed in one place as
necessary.
eg:fileModel-example-2 ja:directory <file:///home/kers/projects/Scratch/kers/FileModels> ; ja:mapName ja:true ; ja:modelName "http://somewhere.org/stuff.n3" .
Model names can be mapped to allow them to be URIs without the
/s in URIs being taken as directory separators. Here, the base file name
will be FileModels/http_C_S_Ssomewhere.org_Sstuff.n3
. The
encoding is not pretty, but is sufficient for simple URIs.
The ja:directory
property specifies the directory in which the
model file is located. The ja:modelName
property specifies the name of
the file within that directory.
If the optional unique property ja:mapName
has the value
ja:true
, then the name of the model is mapped by replacing
any _, /, or : characters by the escape sequences __, _S, or _C. This
translation (which is the same one done by FileGraphMaker
for
FileModelMaker
) allows URIs to be used as model names without
conflicting with the filesystems use of / characters.
Inference models are specified by supplying a description of the reasoner that is used by the model and (optionally) a base model to reason over. For example:
eg:inference-example ja:baseModel [a ja:MemoryModel] ; ja:reasoner [ja:reasonerURL <http://jena.hpl.hp.com/2003/RDFSExptRuleReasoner>] .
describes an inference model that uses RDFS reasoning. The
reasonerURL property value is the URI used to identify the
reasoner (it is the value of the Jena constant
RDFSRuleReasonerFactory.URI
). The base model is
specified as a memory model; if it is left out, an empty memory
model is used. Of course, you can specify a database model as a base
model:
eg:connection ja:dbType "MySQL" ; ja:dbURL <jdbc:mysql://localhost/test> ; ja:dbUser "cjd" . eg:database-example ja:connection eg:connection ; ja:modelName "Thunderbird3" . eg:db-inference-example ja:baseModel eg:database-example ; ja:reasoner [ja:reasonerURL <http://jena.hpl.hp.com/2003/RDFSExptRuleReasoner>] .
The same reasoner as used as in the previous example, but now the base model is a database specified in the same way as our earlier example.
An InfModel's ja:baseModel
property value specifies
the base model for the inference model; if omitted, an empty memory model is
used.
An InfModel's ja:Reasoner
property value specifies
the Reasoner for this inference model; if omitted, a GenericRuleReasoner
is used.
A Reasoner's optional ja:schema
property
specifies a Model which contains the schema for the reasoner to
be bound to. If omitted, no schema is used.
Not implemented yet.
A Reasoner's optional ja:rules
property values specify
RuleSets to be added to the reasoner. They are permitted only if the
Reasoner is a GenericRuleReasoner (perhaps implicitly).
Ontology models can be specified in several ways. The simplest is to use the name of an OntModelSpec from the Java OntModelSpec class:
eg:simple-ont-example ja:ontModelSpec ja:OWL_DL_MEM_RULE_INF .
This constructs an OntModel
with an empty base model
and using the OWL_DL language and the full rule reasoner. All of the
OntModelSpec constants in the Jena implementation are available in this way.
A base model can be specified:
eg:base-ont-example ja:baseModel [a ja:MemoryModel ; ja:content [ja:externalContent <http://jena.hpl.hp.com/some-jena-data.rdf>]] .
The OntModel has a base which is a memory model loaded with the contents
of http://jena.hpl.hp.com/some-jena-data.rdf. Since the ontModelSpec
was omitted, it defaults to OWL_MEM_RDFS_INF
- the same default
as ModelFactory.createOntologyModel()
.
OntModel
is a subclass of InfModel
, and the
ja:baseModel
property means the same thing.
The OntModelSpec
property value is a resource. If that
resource has any properties in the specification model, it is interpreted
as an OntModelSpec description (not implemented yet);
otherwise the local name of the value is interpreted as the name of an
OntModelSpec constant (looked up by reflection).
The ja:ontLanguage
property specifies the ontology language of
the OntModel; the ja:docManager
property specifies the document manager
of the OntModel; and the importsMaker
property specifies the
importsMaker of the OntModel. None of these are implemented
yet.
The PrefixMappings of a model may be set from PrefixMapping specifications. examples please.
The ja:includes
property allows a PrefixMapping to include the
content of other specified PrefixMappings.
The ja:prefix
and ja:namespace
properties
allow the construction of a single element of a prefix mapping by specifying
the prefix and namespace of the mapping.
There are two more Assembler directives that can be used in an
Assembler specification: the assembler and imports
directives.
A specification may contain statements of the form:
someResource ja:assembler "some.Assembler.class.name"
When someResource
is used as the type of a root object,
the AssemblerGroup that processes the description will use an instance
of the Java class named by the object of the statement. That class
must implement the Assembler
interface. See
loading assembler classes
for more details.
If a specification contains statements of the form:
anyResource owl:imports someURL
then the specification is regarded as also containing the contents of the
RDF at someURL
. That RDF may in turn contain
owl:imports
referring to other RDF.
Cycle detection is not yet implemented. The loaded
models are cached; cache control is not implemented yet.
Assembler.builtin
is a particular implementation of
the Assembler
interface. An Assembler
knows
how to build the objects -- not just models -- described by an Assembler
specification. The normal route into an Assembler is through the method:
root
resource properties and
decides whether it can build an object with that description. If not,
it throws an exception. Otherwise, it constructs and returns a suitable
object.
Since the creation of Models is the reason for the existance of Assemblers, there is a convenience wrapper method:
When an Assembler
requires sub-objects (for example,
when an InfModel Assembler requires a Reasoner object), it uses the
method:
create(root)
is just
create(Assembler,Resource)
be the place where
all the work is done. (Amongst other things, this makes testing
easier.)
There is a family of basic assemblers, each of which knows how to
assemble a specific kind of object so long as they're given an
Assembler that can construct their sub-objects. There are defined constants
in Assembler
for (an instance of) each of these basic
assembler classes.
produces | Class | Type | constant |
---|---|---|---|
default models | DefaultModelAssembler | ja:DefaultModel | defaultModel |
memory models | MemoryModelAssembler | ja:MemoryModel | memoryModel |
inference models | InfModelAssembler | ja:InfModel | infModel |
RDB models | RDBModelAssembler | ja:RDBModel | rdbModel |
reasoners | ReasonerAssembler | ja:Reasoner | reasoner |
connection descriptions | ConnectionAssembler | ja:Connection | connection |
content | ContentAssembler | ja:Content | content |
ontology models | OntModelAssembler | ja:OntModel | ontModel |
rules | RuleSetAssembler | ja:RuleSet | rules |
union models | UnionModelAssembler | ja:UnionModel | unionModel |
prefix mappings | PrefixMappingAssembler | ja:PrefixMapping | prefixMapping |
file models | FileModelAssembler | ja:FileModel | fileModel |
Assembler.builtin
is an assembler group,
which ties together those basic assemblers. builtin
can be extended by Jena coders if required. Jena components that
use Assembler specifications to construct objects will use
builtin
unless documented otherwise.
In the remaining sections we will discuss the Assembler
classes that return non-Model objects and conclude with a description
of AssemblerGroup
.
The ContentAssembler constructs Content objects (using the
ja:Content
vocabulary) used to supply
content to models. A Content object has the method:
fill
method adds the represented content to
the model. The supplied ModelAssemblers automatically apply
the Content
objects corresponding to
ja:content
property values.
A ConnectionAssembler constructs ConnectionDescriptions according to the specification. An ConnectionDescription retains the information required to make a database connection, can constructs that connection on demand.
When a ConnectionAssembler is constructed, it may optionally be given a Resource describing (using the JA vocabulary) default values for any of the database properties. When that Assembler is used to create a Connection, missing values are filled in from the defaults. This allows sensitive information to be left out of the RDF description.
The ConnectionAssembler embedded in Assembler.builtin has
defaults taken from the system proeprties jena.dbUser
and jena.dbType
(not implemented yet.
Driver issues? Defaulting the database type?
A RulesetAssembler generates lists of Jena rules.
A "default model" is a model of unspecified type which is implemented as
whatever kind the assembler for ja:DefaultModel
generates.
The default for a DefaultModel is to create a MemoryModel with no special
properties.
The AssemblerGroup class allows a bunch of other Assemblers to be bundled together and selected by RDF type. AssemblerGroup implements Assembler and adds the methods:
AssemblerGroup's implementation of create(sub,root)
finds the most specific type of root
that is a subclass
of ja:Object
and looks for the Assembler that has been
associated with that type by a call of implementWith
.
It then delegates construction to that
Assembler, passing itself as the sub-assembler. Hence each
component Assembler only needs to know how to assemble its own
particular objects.
The assemblerFor
method returns the assembler associated
with the argument type by a previous call of implementWith
,
or null
if there is no associated assembler.
AssemblerGroups implement the ja:assembler
functionality.
The object of an (type ja:assembler "ClassName")
statement
is a string which is taken as the name of an Assembler
implementation to load. An instance of that class is associated with
type
using implementWith
.
If the class has a constructor that takes a single Resource
object, that constructor is used to initialise the class, passing in the
type
subject of the triple. Otherwise the no-argument
constructor of the class is used.